refactor: reorganize platform packages with /src folders and fix cyclic dependencies#26143
refactor: reorganize platform packages with /src folders and fix cyclic dependencies#26143
Conversation
…ic dependencies - Add /src folder to constants, enums, types, utils, and libraries packages - Move source files into /src folders for each package - Update index.ts exports to point to new src folder locations - Update tsconfig.json to only build /src folder for each package - Add proper exports configuration to package.json for each package - Fix cyclic dependency by moving PLATFORM_PERMISSION type to constants package - Remove unused @calcom/platform-types dependency from utils package - Update vite.config.js for libraries package to use new src folder paths Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
There was a problem hiding this comment.
1 issue found across 166 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/platform/types/src/slots/slots-2024-09-04/inputs/get-slots-input.pipe.ts">
<violation number="1" location="packages/platform/types/src/slots/slots-2024-09-04/inputs/get-slots-input.pipe.ts:32">
P2: The ESLint disable comment was accidentally removed and replaced with whitespace. The empty constructor is intentional (as documented in the comment above), so the eslint-disable directive should be restored to prevent linting failures.</violation>
</file>
Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR
packages/platform/types/src/slots/slots-2024-09-04/inputs/get-slots-input.pipe.ts
Show resolved
Hide resolved
… reorganization Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/platform/constants/package.json">
<violation number="1" location="packages/platform/constants/package.json:14">
P1: The exports paths may not align with the actual TypeScript build output. Since `tsconfig.json` includes both `index.ts` (at root) and `src/` folder without an explicit `rootDir`, TypeScript computes rootDir as the package root. This means `src/permissions.ts` compiles to `dist/src/permissions.js`, not `dist/permissions.js`.
Either:
1. Add `"rootDir": "./"` explicitly and update exports to use `./dist/src/...` paths (reverting this change), OR
2. Add `"rootDir": "./src"` to tsconfig and move `index.ts` into `src/` so all files compile to `dist/` directly</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| @@ -4,6 +4,41 @@ | |||
| "main": "./dist/index.js", | |||
There was a problem hiding this comment.
P1: The exports paths may not align with the actual TypeScript build output. Since tsconfig.json includes both index.ts (at root) and src/ folder without an explicit rootDir, TypeScript computes rootDir as the package root. This means src/permissions.ts compiles to dist/src/permissions.js, not dist/permissions.js.
Either:
- Add
"rootDir": "./"explicitly and update exports to use./dist/src/...paths (reverting this change), OR - Add
"rootDir": "./src"to tsconfig and moveindex.tsintosrc/so all files compile todist/directly
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/platform/constants/package.json, line 14:
<comment>The exports paths may not align with the actual TypeScript build output. Since `tsconfig.json` includes both `index.ts` (at root) and `src/` folder without an explicit `rootDir`, TypeScript computes rootDir as the package root. This means `src/permissions.ts` compiles to `dist/src/permissions.js`, not `dist/permissions.js`.
Either:
1. Add `"rootDir": "./"` explicitly and update exports to use `./dist/src/...` paths (reverting this change), OR
2. Add `"rootDir": "./src"` to tsconfig and move `index.ts` into `src/` so all files compile to `dist/` directly</comment>
<file context>
@@ -11,31 +11,31 @@
- "require": "./dist/src/permissions.js",
- "import": "./dist/src/permissions.js",
- "types": "./dist/src/permissions.d.ts"
+ "require": "./dist/permissions.js",
+ "import": "./dist/permissions.js",
+ "types": "./dist/permissions.d.ts"
</file context>
✅ Addressed in 47f06d2
…ipt build output Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
The type-check:ci task was failing because it only depended on @calcom/trpc#build, but the platform packages (@calcom/platform-constants, @calcom/platform-types) also need to be built before type checking can work. These packages have exports that point to their dist/ folders, which don't exist until the packages are built. This adds @calcom/platform-constants#build and @calcom/platform-types#build as dependencies for both type-check and type-check:ci tasks in turbo.json. Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
Devin AI is resolving merge conflictsThis PR has merge conflicts with the Devin will:
If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself. |
…87758 Resolved merge conflicts: - apps/api/v2/tsconfig.json: Kept simplified paths from PR branch - packages/platform/libraries/vite.config.js: Combined /src paths with new errors entry - Moved errors.ts to src/ folder to match PR reorganization pattern - Accepted new type files (disable-cancelling, disable-rescheduling) in src/ location - Fixed lint errors in packages/lib/__mocks__/constants.ts (@ts-ignore -> @ts-expect-error) Co-Authored-By: unknown <>
There was a problem hiding this comment.
40 issues found across 588 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="apps/web/modules/bookings/components/BookEventForm/BookingFields.tsx">
<violation number="1" location="apps/web/modules/bookings/components/BookEventForm/BookingFields.tsx:166">
P1: Calling `setValue` during render can cause infinite re-render loops. Move this logic to a `useEffect` hook that watches `locationResponse` changes.</violation>
</file>
<file name="apps/web/modules/bookings/components/EventMeta.tsx">
<violation number="1" location="apps/web/modules/bookings/components/EventMeta.tsx:145">
P1: `navigator.language` will throw during SSR because `navigator` is not available on the server. Use a browser check or provide a default fallback for SSR.</violation>
</file>
<file name="apps/web/modules/bookings/components/Header.tsx">
<violation number="1" location="apps/web/modules/bookings/components/Header.tsx:198">
P1: Incorrect JSX syntax: using `${t(...)}` instead of `{t(...)}`. The `$` will render as a literal character in the screen reader text.</violation>
<violation number="2" location="apps/web/modules/bookings/components/Header.tsx:208">
P1: Incorrect JSX syntax: using `${t(...)}` instead of `{t(...)}`. The `$` will render as a literal character in the screen reader text.</violation>
<violation number="3" location="apps/web/modules/bookings/components/Header.tsx:218">
P1: Incorrect JSX syntax: using `${t(...)}` instead of `{t(...)}`. The `$` will render as a literal character in the screen reader text.</violation>
</file>
<file name="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts">
<violation number="1" location="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts:59">
P1: Rule violated: **Avoid Logging Sensitive Information**
User email is being logged directly in debug output. Email addresses are PII and should not be logged. Consider removing the email from the log statement or masking it (e.g., `m***@example.com`).</violation>
<violation number="2" location="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts:170">
P2: Use `select` instead of `include` to avoid fetching unnecessary data from `organizationSettings`. Per project guidelines, `include` fetches all fields which can expose sensitive data and impact performance.</violation>
<violation number="3" location="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts:289">
P2: Consider awaiting `sendEmailVerification` to properly handle potential errors. Unawaited async calls can result in unhandled promise rejections.</violation>
<violation number="4" location="apps/web/app/api/auth/signup/handlers/calcomSignupHandler.ts:298">
P2: Use the defined logger instead of console.log for consistent logging. The `log` variable is already defined at line 34.</violation>
</file>
<file name="apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts">
<violation number="1" location="apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts:63">
P1: Rule violated: **Avoid Logging Sensitive Information**
Logging raw error object in OAuth token exchange could expose sensitive credentials (authorization codes, client secrets, PKCE verifiers). Consider logging a sanitized message without the full error object, e.g., `this.logger.error('Token exchange failed', { clientId })`.</violation>
<violation number="2" location="apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts:63">
P1: Rule violated: **Avoid Logging Sensitive Information**
Logging raw error object in OAuth token refresh could expose sensitive credentials (refresh tokens, client secrets). Consider logging a sanitized message without the full error object, e.g., `this.logger.error('Token refresh failed', { clientId })`.</violation>
<violation number="3" location="apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts:63">
P2: Logging raw error objects in OAuth endpoints may expose sensitive data. Consider logging only the error message or a sanitized version instead of the entire error object.
(Based on your team's feedback about not logging raw error objects as they may expose sensitive data.) [FEEDBACK_USED]</violation>
<violation number="4" location="apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts:102">
P1: Potential open redirect vulnerability: If `getClient()` fails (e.g., client not found) or an unexpected error occurs before redirect URI validation in `generateAuthorizationCode`, the code redirects to the user-supplied `body.redirectUri`. Per OAuth2 spec, when the client cannot be verified, you should NOT redirect to the request's redirect URI. Consider validating the client exists and the redirect URI is registered before using it for error redirects, or throw an HTTP error directly for client validation failures.</violation>
</file>
<file name="apps/web/modules/bookings/components/SeatsAvailabilityText.tsx">
<violation number="1" location="apps/web/modules/bookings/components/SeatsAvailabilityText.tsx:32">
P1: Division by zero risk when `totalSeats` is 0. Consider adding a guard or early return to handle this edge case.</violation>
</file>
<file name="apps/web/modules/apps/components/RecentAppsSlider.tsx">
<violation number="1" location="apps/web/modules/apps/components/RecentAppsSlider.tsx:13">
P1: Calling `.sort()` directly on the `items` prop mutates the original array. Props should be treated as immutable in React. Create a copy before sorting to avoid side effects in parent components.</violation>
</file>
<file name="apps/web/modules/bookings/components/DecoyBookingSuccessCard.tsx">
<violation number="1" location="apps/web/modules/bookings/components/DecoyBookingSuccessCard.tsx:37">
P1: The `aria-hidden="true"` attribute on this container hides all booking confirmation content from screen readers, making it inaccessible. This is particularly problematic for a success confirmation that users need to verify. Consider removing `aria-hidden="true"` to allow assistive technologies to announce the booking details.</violation>
</file>
<file name="apps/web/modules/apps/components/PopularAppsSlider.tsx">
<violation number="1" location="apps/web/modules/apps/components/PopularAppsSlider.tsx:13">
P1: Mutating `items` prop with `.sort()` - this modifies the original array passed from the parent. Create a copy first using `[...items].sort(...)` to avoid side effects.</violation>
</file>
<file name="apps/web/modules/bookings/components/DatePicker.tsx">
<violation number="1" location="apps/web/modules/bookings/components/DatePicker.tsx:104">
P1: Calling `moveToNextMonthOnNoAvailability()` directly during render triggers state updates (`setMonth`, `setSelectedDate`, `setDayCount`) which is a React anti-pattern. Side effects should be wrapped in `useEffect` to avoid potential infinite render loops.</violation>
</file>
<file name="apps/web/app/api/auth/signup/handlers/selfHostedHandler.ts">
<violation number="1" location="apps/web/app/api/auth/signup/handlers/selfHostedHandler.ts:64">
P1: Rule violated: **Avoid Logging Sensitive Information**
Logging `userValidation` object exposes PII - it contains `username` and potentially `email` (the existing user's email). Remove sensitive fields from the log or only log the `isValid` boolean.</violation>
<violation number="2" location="apps/web/app/api/auth/signup/handlers/selfHostedHandler.ts:85">
P2: Using `include` with `organizationSettings: true` fetches all columns from the relation. Per project guidelines, prefer `select` to specify only the fields needed. This reduces data exposure risk and improves performance.
If you need specific fields from `organizationSettings`, use:
```typescript
select: {
organizationSettings: {
select: { /* only needed fields */ }
}
}
```</violation>
</file>
<file name=".github/workflows/cubic-devin-review.yml">
<violation number="1" location=".github/workflows/cubic-devin-review.yml:163">
P2: Missing HTTP status code check for API call. Unlike the 'Send message to existing Devin session' step which properly checks the HTTP response code and exits on failure, this step silently continues if the API call fails. Consider adding error handling consistent with lines 118-123.</violation>
</file>
<file name="apps/web/modules/apps/components/AdminAppsList.tsx">
<violation number="1" location="apps/web/modules/apps/components/AdminAppsList.tsx:246">
P2: Using `formMethods.setValue` instead of `field.onChange` from Controller bypasses react-hook-form's proper state management. This can cause issues with dirty state tracking and validation. Destructure and use `field.onChange` directly.</violation>
<violation number="2" location="apps/web/modules/apps/components/AdminAppsList.tsx:326">
P2: Using `app.name` as a React key may cause reconciliation issues if app names aren't unique. Consider using `app.slug` which is designed to be a unique identifier and is already used elsewhere in this file.</violation>
</file>
<file name="apps/web/modules/apps/components/AppListCardPlatformWrapper.tsx">
<violation number="1" location="apps/web/modules/apps/components/AppListCardPlatformWrapper.tsx:5">
P2: Missing validation for `props.logo`. If `logo` is undefined (it's optional in AppListCardProps), this creates `https://app.cal.comundefined`. If it's already an absolute URL, this creates a malformed URL. Prefer an early return to handle edge cases.</violation>
</file>
<file name="apps/web/modules/apps/components/AllApps.tsx">
<violation number="1" location="apps/web/modules/apps/components/AllApps.tsx:35">
P2: Using `ref.current` properties in useEffect dependency array is a React anti-pattern. Refs are mutable and don't trigger re-renders, so changes to `scrollWidth`/`clientWidth` won't re-run this effect. Consider using a ResizeObserver or running the check on window resize instead.</violation>
</file>
<file name="apps/web/modules/apps/components/AppListCard.tsx">
<violation number="1" location="apps/web/modules/apps/components/AppListCard.tsx:13">
P2: `dynamic()` should be called at module scope, not inside the component. This pattern prevents proper preloading and creates a new component type each time `isPlatform` changes. Move both dynamic imports to module level and use conditional rendering instead.</violation>
</file>
<file name="apps/web/modules/apps/components/AppCard.tsx">
<violation number="1" location="apps/web/modules/apps/components/AppCard.tsx:233">
P2: Use `t("template")` for localization instead of the hardcoded string "Template".</violation>
</file>
<file name="apps/web/modules/apps/components/AppSetDefaultLinkDialog.tsx">
<violation number="1" location="apps/web/modules/apps/components/AppSetDefaultLinkDialog.tsx:44">
P2: Empty regex fallback bypasses validation. When `urlRegExp` is undefined, `new RegExp("")` matches everything. Consider throwing an error or using a strict default pattern.</violation>
</file>
<file name="apps/web/modules/bookings/components/AvailableTimes.tsx">
<violation number="1" location="apps/web/modules/bookings/components/AvailableTimes.tsx:247">
P2: Hardcoded "Busy" text should use `t()` for localization. The component already uses `useLocale()` and `t()` for other strings.</violation>
<violation number="2" location="apps/web/modules/bookings/components/AvailableTimes.tsx:271">
P2: Empty `slots` array causes incorrect behavior. `[].every()` returns `true`, so `oooAllDay` would be true for empty arrays, causing an early return that bypasses the "no slots available" UI. Add an early return for empty slots or include a length check.</violation>
</file>
<file name=".github/workflows/devin-conflict-resolver.yml">
<violation number="1" location=".github/workflows/devin-conflict-resolver.yml:96">
P2: The `maintainerCanModify` field is queried in GraphQL but never used. For manually-triggered fork PR conflict resolution, the workflow should verify `maintainerCanModify` is true before creating a Devin session, otherwise Devin won't be able to push the resolved changes. Add a check similar to `stale-pr-devin-completion.yml` which validates `!isFork || maintainerCanModify`.</violation>
<violation number="2" location=".github/workflows/devin-conflict-resolver.yml:315">
P2: Rule violated: **Avoid Logging Sensitive Information**
Logging the full API response `data` object could expose sensitive session information from the Devin API. Consider logging only specific non-sensitive fields like `data.error` or a generic failure message instead of the entire response object.</violation>
</file>
<file name="apps/web/modules/bookings/components/RedirectToInstantMeetingModal.tsx">
<violation number="1" location="apps/web/modules/bookings/components/RedirectToInstantMeetingModal.tsx:52">
P2: The `calculateTimeRemaining` function is used inside this effect but is not in the dependency array. Since it's defined inside the component and captures `expiryTime`, this could cause stale closures. Move the calculation inside the effect to avoid this issue.</violation>
</file>
<file name="apps/web/modules/apps/components/AppList.tsx">
<violation number="1" location="apps/web/modules/apps/components/AppList.tsx:148">
P2: Missing `key` prop on `<ChildAppCard>` components. When rendering lists, React requires unique keys to identify elements. Add a unique key like `key={app.slug}` for the user credential card and `key={team.teamId}` for team cards.</violation>
</file>
<file name="apps/web/modules/bookings/components/Booker.tsx">
<violation number="1" location="apps/web/modules/bookings/components/Booker.tsx:118">
P2: Day.js object is created inside filter loop, causing repeated instantiation for each slot. Per project guidelines about Day.js performance in hot paths, compute `dayjs(selectedDate)` once before the filter to avoid creating new instances on each iteration.</violation>
</file>
<file name="apps/web/modules/bookings/components/LargeCalendar.tsx">
<violation number="1" location="apps/web/modules/bookings/components/LargeCalendar.tsx:48">
P2: This empty `useEffect` doesn't actually force rerenders - it runs after render and does nothing. The comment mentions "overlay events" but the dependency is `displayOverlay`. Since `overlayEvents` comes from Zustand's `useOverlayCalendarStore`, state changes already trigger rerenders automatically. Consider removing this ineffective code or implementing actual re-render logic if truly needed.</violation>
</file>
<file name="apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx">
<violation number="1" location="apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx:59">
P2: Hardcoded string "Calendar Settings" should use t() for localization to maintain consistency with other localized strings in this component.</violation>
</file>
<file name="apps/web/modules/bookings/components/InstantBooking.tsx">
<violation number="1" location="apps/web/modules/bookings/components/InstantBooking.tsx:40">
P2: Consider extracting the Button component to avoid duplication. The disabled and enabled states render nearly identical buttons, making maintenance error-prone.</violation>
</file>
<file name="apps/web/modules/bookings/components/BookingSuccessCard.tsx">
<violation number="1" location="apps/web/modules/bookings/components/BookingSuccessCard.tsx:86">
P2: Translation key "Host" does not appear to exist in the localization files. Consider using an existing key or adding a new one following the snake_case convention (e.g., `t("host")` after adding the key to common.json).</violation>
</file>
<file name="apps/web/modules/apps/components/DisconnectIntegrationModal.tsx">
<violation number="1" location="apps/web/modules/apps/components/DisconnectIntegrationModal.tsx:38">
P2: When `credentialId` is null, clicking confirm does nothing and the dialog remains open without feedback. Consider adding an early return or guard clause to handle this case gracefully (e.g., close the dialog or disable the confirm button when `credentialId` is null).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
apps/web/modules/apps/components/DisconnectIntegrationModal.tsx
Outdated
Show resolved
Hide resolved
apps/api/v2/src/modules/auth/oauth2/controllers/oauth2.controller.ts
Outdated
Show resolved
Hide resolved
…on-1766487758" This reverts commit b4ddfe1.
There was a problem hiding this comment.
1 issue found across 176 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/platform/constants/package.json">
<violation number="1" location="packages/platform/constants/package.json:8">
P2: The `types` condition should be listed first in each export entry for proper TypeScript type resolution. TypeScript documentation recommends this ordering to ensure types are resolved correctly before other conditions are matched.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| @@ -4,6 +4,41 @@ | |||
| "main": "./dist/index.js", | |||
There was a problem hiding this comment.
P2: The types condition should be listed first in each export entry for proper TypeScript type resolution. TypeScript documentation recommends this ordering to ensure types are resolved correctly before other conditions are matched.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/platform/constants/package.json, line 8:
<comment>The `types` condition should be listed first in each export entry for proper TypeScript type resolution. TypeScript documentation recommends this ordering to ensure types are resolved correctly before other conditions are matched.</comment>
<file context>
@@ -4,6 +4,41 @@
"types": "./dist/index.d.ts",
"private": true,
+ "exports": {
+ ".": {
+ "require": "./dist/index.js",
+ "import": "./dist/index.js",
</file context>
Devin AI is resolving merge conflictsThis PR has merge conflicts with the Devin will:
If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself. |
…87758 Co-Authored-By: unknown <>
Devin AI is resolving merge conflictsThis PR has merge conflicts with the Devin will:
If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself. |
…87758 Co-Authored-By: unknown <>
|
Merge conflicts have been resolved and pushed. Please remove the Conflicts resolved:
|
…ing changes - Add @calcom/platform-libraries#build to turbo.json type-check dependencies - Fix Booker hook import paths from components/hooks/ to hooks/ in atoms - Replace @calcom/lib/tracing/factory import with inline TraceContext in API v2 Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
…ms CJS shim in postbuild - Add @calcom/platform-libraries to apps/web/package.json for atoms type resolution - Update postbuild to generate packages/prisma/enums/index.js CJS shim for runtime resolution Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
- Replace node -e with sed to avoid yarn shell parser syntax error - Restore @calcom/prisma/enums path alias in tsconfig.json Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
What does this PR do?
This PR reorganizes the 5 platform packages (constants, enums, types, utils, libraries) to follow a consistent
/srcfolder structure, fixes cyclic dependencies, modernizes TypeScript configuration, and cleans up unnecessary tsconfig path mappings.Why is this better than before?
1. Consistent Package Structure
Before: Source files were scattered at the root level of each package, mixed with config files.
After: All source files are organized under
/srcfolders, providing a clear separation between source code and configuration.2. Fixed Cyclic Dependencies
Before: There was a cyclic dependency chain:
enums → types → constants → enumscaused byPLATFORM_PERMISSIONtype being in the types package but needed by enums.After: Moved
PLATFORM_PERMISSIONto constants package, breaking the cycle. The dependency chain is now linear:enums → constants,types → constants.3. Modern TypeScript Target
Before: Packages used
target: "ES5", generating unnecessarily verbose JavaScript with polyfills for features that all modern runtimes support natively.After: Upgraded to
target: "ES2021", producing cleaner, more efficient output that takes advantage of modern JavaScript features.4. Cleaner tsconfig in API v2
Before:
apps/api/v2/tsconfig.jsonhad 17+ explicit path mappings for platform packages, creating maintenance overhead and potential for drift.After: Removed all platform package paths. TypeScript now resolves these through node_modules using proper
exportsandtypesVersionsconfiguration. Only@calcom/prisma/clientand@calcom/prisma/enumspath aliases are retained (needed for runtime resolution in the NestJS build).5. Proper Package Exports
Before: Some packages lacked proper
exportsfield in package.json, making deep imports unreliable.After: Added proper
exportsandtypesVersionsfields to support both modern and legacy module resolution, enabling reliable deep imports like@calcom/platform-constants/permissions.6. Fixed Pre-existing Bugs
traceContextproperty in the API v2 bookings service that was introduced in PR feat: dist tracing 4 #25574 but never caught. Fixed with inlineTraceContextcreation usingnode:cryptorandomUUID()(since@calcom/libis TypeScript-only and can't be resolved at runtime in the NestJS build).components/hooks/→hooks/) after hooks were moved in refactor: move Booker hooks from packages/features to apps/web/modules #27343.Updates since last revision
CI Fixes — Round 3 (February 2026)
@calcom/platform-librariesas a dependency — the atoms bookertypes.tsimports from it, so the web app build needs it declared.dist/packages/prisma/enums/index.jsby transforming the TypeScript source withsedto CommonJS format (export const→exports., stripsas constandexport typelines). This is needed because@calcom/prisma/enumspath aliases were removed, so the NestJS compiled output needs a resolvable module at the expected path.@calcom/prisma/enumspath alias — required alongside the CJS shim for both compile-time and runtime resolution.CI Fixes — Round 2 (February 2026)
@calcom/platform-libraries#buildto type-check dependencies — the libraries package types live indist/, so it must be built before type checking.BookerPlatformWrapper.tsximports from@calcom/features/bookings/Booker/components/hooks/to@calcom/features/bookings/Booker/hooks/— the hooks were relocated in refactor: move Booker hooks from packages/features to apps/web/modules #27343 but atoms imports were never updated.import { distributedTracing } from "@calcom/lib/tracing/factory"with inlineTraceContextobjects usingrandomUUID()fromnode:crypto. The@calcom/libpackage has no build step, so it can't berequire()d at runtime in the compiled NestJS output.CI Fixes — Round 1 (January 2026)
@calcom/platform-constants#buildand@calcom/platform-types#buildas dependencies for bothtype-checkandtype-check:citasks.packages/platform/utils/tests/permissions.test.tsto import from../src/permissionsinstead of../permissions.Merge with main (January 2026)
Resolved merge conflict in
apps/api/v2/package.json:postbuildscript for NestJS Swagger plugin path resolutionformatscript to usebiome format --write src test(from main branch's migration from prettier to biome)Runtime Path Resolution for NestJS Swagger Plugin
Added a
postbuildscript toapps/api/v2/package.jsonthat handles runtime path resolution for the NestJS Swagger plugin. The plugin generates relativerequire()paths based on compiled output structure, which don't resolve correctly at runtime. The postbuild script:dist/packages/prisma/client/index.js- a small CommonJS shim that re-exports from@prisma/clientdist/packages/prisma/enums/index.js- transforms TypeScript enums to CommonJS usingsed(removesas const,export typelines, convertsexport consttoexports.)dist/packages/pointing to the repo rootbash -cwrapper for Yarn Berry shell compatibility (Yarn's portable shell doesn't supportforloops)Summary of Changes
Package Reorganization
/srcfolders in constants, enums, types, utils, and libraries packages/srcfoldersindex.tsexports to point to new src folder locationstsconfig.jsonto only includesrcfolder for each packageDependency & Configuration Fixes
PLATFORM_PERMISSIONtype from types to constants@calcom/platform-typesdependency from utils packagepackage.jsontypes field (was incorrectly pointing to.d.ts.map)@calcom/platform-constants,@calcom/platform-libraries, and@calcom/platform-utilstoapps/web/package.jsonenums/monorepo.tsan alias ofindex.tsto avoid divergenceTypeScript Modernization
targetfromES5toES2021for constants, enums, types, and utils packagesmodule: "CommonJS"to platform packages for proper runtime resolutiontypesVersionsfield to constants and types package.json for legacy moduleResolution compatibilityapps/api/v2/tsconfig.json(kept only@calcom/prisma/clientand@calcom/prisma/enums)Build System
turbo.jsonmoduleNameMapperfor platform packages (maps to TypeScript source for ts-jest transpilation)Bug Fixes
traceContexterror inapps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.tsby creating inlineTraceContextobjects withrandomUUID()@calcom/platform-constantsinstead of relative pathcomponents/hooks/tohooks/Link to Devin run: https://app.devin.ai/sessions/95e45b8887cb4d96a1b91d4f86bd75e1
Conflict resolution & CI fixes: https://app.devin.ai/sessions/7e29ebbaac5749378f10baa546d0f297
Requested by: Volnei Munhoz (volnei@cal.com) (@volnei)
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
yarn type-check:ci --forceto verify TypeScript compilationyarn lintto verify linting passesTZ=UTC yarn testto verify unit tests passNote: The
requiredcheck may fail if theready-for-e2elabel is not on the PR - this is expected behavior. The "Check API v2 breaking changes" failure is due to Prisma client not being initialized in the CI environment (infrastructure issue). The E2E API v2 test failure is a flaky test unrelated to these changes.Human Review Checklist
@calcom/prisma/enumsinapps/api/v2/tsconfig.jsonis correct — this was initially removed but needed to be added back for runtime resolution alongside the CJS shimsedtransformation in the postbuild script that converts TypeScript enums to CommonJS. This is fragile and will break if the source enum format changes significantly. Consider whether a more robust solution is needed.TraceContextobjects usingrandomUUID()create trace IDs that aren't connected to the distributed tracing system. This is a functional divergence from the originaldistributedTracing.createTrace(). Confirm this is acceptable or if we need a different approach.@calcom/platform-libraries#build(in addition to constants and types) is correct for CI type checkingcomponents/hooks/tohooks/is correct — hooks were moved in refactor: move Booker hooks from packages/features to apps/web/modules #27343 but atoms imports weren't updatedpostbuildscript inapps/api/v2/package.json- it creates prisma client and enums shims plus symlinks for runtime path resolution. This is a workaround for NestJS Swagger plugin behavior.PLATFORM_PERMISSIONtype move to constants is correcttypes/src/permissions.tsre-exports from constants correctly