Files
calendar/apps/web/pagesAndRewritePaths.ts
T
Volnei MunhozGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
76b53eb3d4 chore: remove webpack config and convert next.config to TypeScript (#26126)
* chore: remove webpack experimental flags from apps/web

- Remove webpackMemoryOptimizations and webpackBuildWorker from experimental config
- Remove unused DefinePlugin for process.env.BUILD_ID (not used anywhere in codebase)
- Remove unused buildId parameter from webpack function signature

These webpack-specific experimental flags were showing up during dev mode
even though Turbopack is used for development. The flags only apply to
production webpack builds and their presence in the config was confusing.

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>

* chore: remove webpack function for full Turbopack build

- Remove entire webpack function (IgnorePlugin, PrismaPlugin, resolve.fallback, sideEffects)
- Remove unused PrismaPlugin import
- Turbopack handles all bundling without webpack configuration

Benchmark shows no performance regression:
- Main (with webpack): 67s compile
- Full webpack removal: 69s compile

Both fail at same pre-existing TypeScript error on main branch.

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>

* chore: convert next.config.js to TypeScript

- Convert CommonJS require() to ES6 imports
- Add proper TypeScript types for config and plugins
- Remove /* eslint-disable */ comment
- Keep all existing functionality intact

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>

* conditional load axiom

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-12-22 12:23:00 -03:00

102 lines
4.8 KiB
TypeScript

import { sync as globSync } from "glob";
import { nextJsOrgRewriteConfig } from "./getNextjsOrgRewriteConfig";
// Top-level route names that are explicitly allowed for org rewrite (whitelist)
export const topLevelRouteNamesWhitelistedForRewrite: string[] = [
// We don't allow all dashboard route names to be used as slug because people are probably accustomed to access links like acme.cal.com/workflows, acme.cal.com/event-types etc.
// So, we carefully allow, what is absolutely needed.
// Allowed to be a team/user slug in organization because onboarding is a common team name
"onboarding",
];
/**
* Extracts top-level route names from all pages/app files and excludes them from org rewrite.
* For example: /abc/def/ghi -> 'abc'
*
* These top-level route names are excluded from rewrites in beforeFiles in next.config.js
* to prevent conflicts with organization slug rewrites.
*/
export const topLevelRoutesExcludedFromOrgRewrite: string[] = globSync(
"{pages,app,app/(booking-page-wrapper),app/(use-page-wrapper),app/(use-page-wrapper)/(main-nav)}/**/[^_]*.{tsx,js,ts}",
{
cwd: __dirname,
}
)
.map((filename) =>
filename
// Remove the directory prefix (pages/, app/ and route group folders.)
.replace(
/^(app\/\(use-page-wrapper\)\/\(main-nav\)|app\/\(use-page-wrapper\)|app\/\(booking-page-wrapper\)|pages|app)\//,
""
)
// Remove file extensions
.replace(/(\.tsx|\.js|\.ts)/, "")
// Extract only the top-level route name (e.g., /abc/def -> abc)
.replace(/\/.*/, "")
)
.filter(
(v, i, self) =>
self.indexOf(v) === i &&
![
"[user]",
"_trpc",
"layout",
"layoutHOC",
"WithAppDirSsg",
"global-error",
"WithAppDirSsr",
"WithEmbedSSR",
"WithEmbedSSR.test",
"ShellMainAppDir",
"ShellMainAppDirBackButton",
].some((prefix) => v.startsWith(prefix))
)
.filter((page) => {
return !topLevelRouteNamesWhitelistedForRewrite.includes(page);
});
// .* matches / as well(Note: *(i.e wildcard) doesn't match / but .*(i.e. RegExp) does)
// It would match /free/30min but not /bookings/upcoming because 'bookings' is an item in pages
// It would also not match /free/30min/embed because we are ensuring just two slashes
// ?!book ensures it doesn't match /free/book page which doesn't have a corresponding new-booker page.
// [^/]+ makes the RegExp match the full path, it seems like a partial match doesn't work.
// book$ ensures that only /book is excluded from rewrite(which is at the end always) and not /booked
export { nextJsOrgRewriteConfig };
/**
* Returns a regex that matches all existing routes, virtual routes (like /forms, /router, /success etc) and nextjs special paths (_next, public)
* @param suffix - The suffix to append to each route in the regex
*/
function getRegExpMatchingAllReservedRoutes(suffix: string): string {
// Following routes don't exist but they work by doing rewrite. Thus they need to be excluded from matching the orgRewrite patterns
// Make sure to keep it upto date as more nonExistingRouteRewrites are added.
// "app" is reserved for the Cal.com Companion landing page served by Framer at cal.com/app.
// The browser extension redirects users to cal.com/app when clicked on restricted pages (like chrome://newtab).
// Without this reservation, /app would be treated as a username lookup and show "username available" error.
const otherNonExistingRoutePrefixes = ["forms", "router", "success", "cancel", "app"];
// Most files/dirs in public dir must not be rewritten to org pages. Ideally it should be all the content of public dir, but that can be done later
// It is important to exclude the embed pages separately here because with SINGLE_ORG_SLUG enabled, the entire domain is eligible for rewrite vs just the org subdomain otherwise
const staticAssets = ["embed"];
// FIXME: I am not sure why public is needed here, an asset 'test' in public isn't accessible through "/public/test" but only through "/test"
// We should infact scan through all files in public and exclude them instead.
const nextJsSpecialPaths = ["_next", "public"];
const allTopLevelRoutesExcludedFromOrgRewrite = topLevelRoutesExcludedFromOrgRewrite
.concat(otherNonExistingRoutePrefixes)
.concat(nextJsSpecialPaths)
.concat(staticAssets);
return allTopLevelRoutesExcludedFromOrgRewrite.join(`${suffix}|`) + suffix;
}
// To handle /something
export const orgUserRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/?$")})[a-zA-Z0-9\\-_]+)`;
// To handle /something/somethingelse
export const orgUserTypeRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/")})[^/]+)/:type((?!avatar\\.png)[^/]+)`;
// To handle /something/somethingelse/embed
export const orgUserTypeEmbedRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/")})[^/]+)/:type/embed`;