Skip to content

Comments

fix: resolve circular dependencies in app-store package#23535

Closed
joeauyeung wants to merge 12 commits intomainfrom
devin/1756874030-fix-app-store-circular-dependencies
Closed

fix: resolve circular dependencies in app-store package#23535
joeauyeung wants to merge 12 commits intomainfrom
devin/1756874030-fix-app-store-circular-dependencies

Conversation

@joeauyeung
Copy link
Contributor

What does this PR do?

This PR resolves circular dependencies in the app-store package that were causing TypeScript compilation issues and architectural problems. The main changes include:

  • Creates a new @calcom/app-store-types package to house shared types (CredentialDataWithTeamName, LocationOption, TDependencyData, defaultVideoAppCategories) that were causing circular dependencies between app-store, lib, and prisma packages
  • Extracts routingFormResponseInDbSchema from routing-forms to @calcom/lib/zod/routingFormResponse to break the circular dependency between app-store and prisma packages
  • Fixes type compatibility issues between CredentialForCalendarService and CredentialDataWithTeamName by making fields properly nullable/optional to match the actual Prisma schema
  • Updates import statements across the codebase to use the new shared locations instead of creating circular references

Link to Devin run: https://app.devin.ai/sessions/d5c40dff618e42ef89edfc3e3e205fb6

Requested by: @joeauyeung

How should this be tested?

  • Type checking: Run yarn type-check:ci --force to verify no TypeScript errors
  • App store functionality: Test credential management, app installations, and calendar/payment integrations
  • Generated files: Run yarn app-store:build to ensure CLI still generates files correctly
  • Build process: Run yarn build to ensure no dependency or compilation issues

Expected behavior: All existing app-store functionality should work unchanged, but without circular dependency warnings/errors.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - internal refactoring only.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

⚠️ Critical Review Points

Please pay special attention to:

  1. Type safety: Verify that the CredentialDataWithTeamName type changes (making delegatedToId optional and several fields nullable) actually match the real data structure returned by Prisma queries
  2. Circular dependencies: Confirm that no new circular dependencies were introduced by the refactoring
  3. Package setup: Validate that the new @calcom/app-store-types package is correctly configured and exported
  4. Generated files: Test that app-store CLI generation still works and produces correct imports
  5. Credential handling: End-to-end test credential creation, updates, and usage to ensure no regressions in core functionality

Checklist

  • I haven't read the contributing guide
  • My code doesn't follow the style guidelines of this project
  • I haven't commented my code, particularly in hard-to-understand areas
  • I haven't checked if my changes generate no new warnings

devin-ai-integration bot and others added 2 commits September 3, 2025 04:51
- Create @calcom/app-store-types package for shared metadata types
- Extract routingFormResponseInDbSchema to @calcom/lib/zod/routingFormResponse
- Update CredentialDataWithTeamName type to match CredentialForCalendarService
- Fix import statements to separate type and value imports
- Remove circular dependency warnings from utils.ts
- Update package dependencies and exports

This resolves circular import issues between app-store, lib, and prisma packages
while maintaining existing functionality and type safety.

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 3, 2025

Walkthrough

  • Added defaultVideoAppCategories in packages/app-store/constants.ts (typed with AppCategories and includes messaging, conferencing, video).
  • Updated packages/app-store/utils.ts to import defaultVideoAppCategories from constants and removed its local export; added and centralized exported type CredentialDataWithTeamName.
  • Updated packages/app-store/server.ts to import defaultVideoAppCategories from constants.
  • Removed unused imports in routing-forms TRPC handlers (isFormCreateEditAllowed, TRPCError).
  • Changed MembershipRole import to type-only in permissions.ts.
  • Removed a TODO comment in packages/prisma/zod/custom/booking.ts.

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1756874030-fix-app-store-circular-dependencies

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Sep 3, 2025
devin-ai-integration bot and others added 2 commits September 3, 2025 14:34
- Move all types from external @calcom/app-store-types package into app-store/types.d.ts
- Add missing LocationOption, CredentialDataWithTeamName, TDependencyData types
- Remove dependency on external @calcom/app-store-types package
- Keep all types within app-store package as requested by user
- Resolves TypeScript errors for IntegrationOAuthCallbackState and CredentialOwner

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
- Remove all files from packages/app-store-types directory
- Update remaining imports in _appRegistry.ts and utils.ts to use internal types
- Complete consolidation of all types into app-store/types.d.ts
- Eliminates external package dependency as requested by user

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
@pull-request-size pull-request-size bot removed the size/L label Sep 3, 2025
@vercel
Copy link

vercel bot commented Sep 3, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Sep 3, 2025 5:55pm
cal-eu Ignored Ignored Sep 3, 2025 5:55pm

devin-ai-integration bot and others added 2 commits September 3, 2025 14:56
- Move defaultVideoAppCategories from types.d.ts to constants.ts
- Update imports in utils.ts and server.ts to use constants.ts
- Resolves module resolution error causing 60+ unit test failures
- TypeScript .d.ts files are for type declarations only, not runtime values

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
- Auto-formatted by pre-commit hooks during previous commit

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
- Move schema from @calcom/lib/zod/routingFormResponse to routing-forms/zod.ts
- Update import in booking.ts to use routing-forms package location
- Remove unused routingFormResponse.ts file from lib
- Keeps routing-form related schemas consolidated in one location

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
@pull-request-size pull-request-size bot added size/M and removed size/L labels Sep 3, 2025
devin-ai-integration bot and others added 4 commits September 3, 2025 16:12
This change doesn't solve any circular dependency and was unnecessary
consolidation. Keep types where they logically belong.

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
…ils.ts

These type moves don't solve any circular dependencies and were
unnecessary consolidation. Keep types in their original locations:
- LocationOption and CredentialDataWithTeamName back to utils.ts
- MeetLocationType and MSTeamsLocationType back to utils.ts
- Remove constants.ts file and update all imports accordingly

Only keep changes that actually resolve circular dependency issues.

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
…r dependency

- Create constants.ts with defaultVideoAppCategories, MeetLocationType, MSTeamsLocationType
- Update imports in utils.ts, googlecalendar, office365calendar, and locations.ts
- This separates runtime values from type declarations to fix module resolution errors
- Revert routing-forms lint fixes that don't solve actual circular dependencies

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
…ategories

- Fixes type check error: Module '@calcom/app-store/utils' has no exported member 'defaultVideoAppCategories'
- This was the last remaining import that needed to be updated after moving runtime values to constants.ts

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
import { createFallbackRoute } from "../lib/createFallbackRoute";
import { getSerializableForm } from "../lib/getSerializableForm";
import { isFallbackRoute } from "../lib/isFallbackRoute";
import { isFormCreateEditAllowed } from "../lib/isFormCreateEditAllowed";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used in file

import { MembershipRole } from "@calcom/prisma/enums";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";

import { TRPCError } from "@trpc/server";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used in file


export const MSTeamsLocationType = "integrations:office365_video";

export const defaultVideoAppCategories: AppCategories[] = [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this in utils.ts was causing a circular dependency

@joeauyeung joeauyeung marked this pull request as ready for review September 3, 2025 18:17
@joeauyeung joeauyeung requested a review from a team as a code owner September 3, 2025 18:17
@graphite-app graphite-app bot requested a review from a team September 3, 2025 18:17
@dosubot dosubot bot added app-store area: app store, apps, calendar integrations, google calendar, outlook, lark, apple calendar 💻 refactor labels Sep 3, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/app-store/utils.ts (2)

171-171: Convert default export to named export and update imports
Removing export default getApps; will break all existing default imports in these files (and others):

  • packages/trpc/server/routers/viewer/apps/updateUserDefaultConferencingApp.handler.ts:3
  • packages/trpc/server/routers/viewer/apps/appById.handler.ts:1
  • packages/platform/libraries/app-store.ts:1
  • packages/lib/server/getDefaultLocations.ts:3
  • packages/lib/apps/getEnabledAppsFromCredentials.ts:4
  • packages/lib/EventManager.ts:11
  • packages/lib/CalendarManager.ts:6
    Update each import getApps from "@calcom/app-store/utils" to import { getApps } from "@calcom/app-store/utils".

56-79: Scrub credential.key from getApps output — in packages/app-store/utils.ts, change

credentials: appCredentials

to

credentials: appCredentials.map(getPiiFreeCredential)

so no tRPC/HTTP route ever returns a raw key.

♻️ Duplicate comments (1)
packages/app-store/constants.ts (1)

7-7: Ack: moving from utils breaks the cycle

Centralizing defaultVideoAppCategories here fixes the utils-induced cycle.

🧹 Nitpick comments (4)
packages/app-store/routing-forms/trpc/permissions.ts (1)

12-18: Make fallbackRoles optional with a safe default

Minor resilience: default to [] so callers don’t need to pass it explicitly.

 export async function checkPermissionOnExistingRoutingForm({
   formId,
   userId,
   permission,
-  fallbackRoles,
+  fallbackRoles = [],
 }: {
   formId: string;
   userId: number;
   permission: PermissionString;
-  fallbackRoles: MembershipRole[];
+  fallbackRoles?: MembershipRole[];
 }) {
packages/app-store/server.ts (1)

39-47: Select only what you need from org lookup

Small efficiency win: only id is used.

-    const org = await prisma.team.findFirst({
-      where: {
+    const org = await prisma.team.findFirst({
+      select: { id: true },
+      where: {
         children: {
           some: {
             id: teamId,
           },
         },
       },
     });
packages/app-store/constants.ts (1)

7-12: Freeze the list at type-level to prevent mutation

Make it readonly while preserving AppCategories checking.

-export const defaultVideoAppCategories: AppCategories[] = [
-  "messaging",
-  "conferencing",
-  // Legacy name for conferencing
-  "video",
-];
+export const defaultVideoAppCategories =
+  ["messaging", "conferencing", /* Legacy */ "video"] as const
+  satisfies readonly AppCategories[];
packages/app-store/utils.ts (1)

147-165: Minor: use a Set for category membership

Slight micro-optimization and readability.

-  return !appCategories.some(
-    (category) =>
-      category === "calendar" ||
-      (defaultVideoAppCategories.includes(category as AppCategories) && !concurrentMeetings)
-  );
+  const videoCats = new Set(defaultVideoAppCategories);
+  return !appCategories.some(
+    (c) => c === "calendar" || (videoCats.has(c as AppCategories) && !concurrentMeetings)
+  );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2d9c1b3 and ed488f4.

📒 Files selected for processing (7)
  • packages/app-store/constants.ts (1 hunks)
  • packages/app-store/routing-forms/trpc/formMutation.handler.ts (0 hunks)
  • packages/app-store/routing-forms/trpc/formQuery.handler.ts (0 hunks)
  • packages/app-store/routing-forms/trpc/permissions.ts (1 hunks)
  • packages/app-store/server.ts (1 hunks)
  • packages/app-store/utils.ts (2 hunks)
  • packages/prisma/zod/custom/booking.ts (0 hunks)
💤 Files with no reviewable changes (3)
  • packages/app-store/routing-forms/trpc/formQuery.handler.ts
  • packages/app-store/routing-forms/trpc/formMutation.handler.ts
  • packages/prisma/zod/custom/booking.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/app-store/routing-forms/trpc/permissions.ts
  • packages/app-store/constants.ts
  • packages/app-store/server.ts
  • packages/app-store/utils.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/app-store/routing-forms/trpc/permissions.ts
  • packages/app-store/constants.ts
  • packages/app-store/server.ts
  • packages/app-store/utils.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/app-store/routing-forms/trpc/permissions.ts
  • packages/app-store/constants.ts
  • packages/app-store/server.ts
  • packages/app-store/utils.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: nangelina
PR: calcom/cal.com#23486
File: packages/app-store/kyzon-space/config.json:5-5
Timestamp: 2025-09-01T07:31:00.963Z
Learning: In Cal.com's video integration system, credential types (e.g., "kyzon-space_video") are transformed to app names by removing underscores using `cred.type.split("_").join("")` in videoClient.ts line 28. This means the key in packages/app-store/index.ts should match the underscore-removed version (e.g., "kyzon-spacevideo") rather than the original type name. This same pattern is used in other parts of the system like getCalendar.ts.
Learnt from: nangelina
PR: calcom/cal.com#23486
File: packages/app-store/kyzon-space/config.json:5-5
Timestamp: 2025-09-01T07:31:00.963Z
Learning: In Cal.com's video integration system, credential types (e.g., "kyzon-space_video") are transformed to app names by removing underscores using `cred.type.split("_").join("")` in videoClient.ts line 28. This means the key in packages/app-store/index.ts should match the underscore-removed version (e.g., "kyzon-spacevideo") rather than the original type name.
📚 Learning: 2025-09-01T07:31:00.963Z
Learnt from: nangelina
PR: calcom/cal.com#23486
File: packages/app-store/kyzon-space/config.json:5-5
Timestamp: 2025-09-01T07:31:00.963Z
Learning: In Cal.com's video integration system, credential types (e.g., "kyzon-space_video") are transformed to app names by removing underscores using `cred.type.split("_").join("")` in videoClient.ts line 28. This means the key in packages/app-store/index.ts should match the underscore-removed version (e.g., "kyzon-spacevideo") rather than the original type name.

Applied to files:

  • packages/app-store/server.ts
  • packages/app-store/utils.ts
📚 Learning: 2025-09-01T07:31:00.963Z
Learnt from: nangelina
PR: calcom/cal.com#23486
File: packages/app-store/kyzon-space/config.json:5-5
Timestamp: 2025-09-01T07:31:00.963Z
Learning: In Cal.com's video integration system, credential types (e.g., "kyzon-space_video") are transformed to app names by removing underscores using `cred.type.split("_").join("")` in videoClient.ts line 28. This means the key in packages/app-store/index.ts should match the underscore-removed version (e.g., "kyzon-spacevideo") rather than the original type name. This same pattern is used in other parts of the system like getCalendar.ts.

Applied to files:

  • packages/app-store/server.ts
  • packages/app-store/utils.ts
🧬 Code graph analysis (1)
packages/app-store/constants.ts (1)
packages/app-store/locations.ts (2)
  • MeetLocationType (18-18)
  • MSTeamsLocationType (19-19)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (6)
packages/app-store/routing-forms/trpc/permissions.ts (1)

4-4: Good: type-only enum import

Switching MembershipRole to a type-only import avoids runtime coupling and helps prevent cycles.

packages/app-store/server.ts (2)

67-84: credentialForCalendarServiceSelect correctly omits credential.key
The select only includes id, appId, and type; no key field is returned, satisfying the credential exposure policy.


4-4: Import path consolidation verified
No remaining imports of defaultVideoAppCategories from @calcom/app-store/utils were found—everything now correctly references @calcom/app-store/constants.

packages/app-store/constants.ts (1)

1-1: Confirm AppCategories enum parity
Runtime definitions for AppCategories (@calcom/prisma/enums) aren’t present in the repo—manually verify that the generated enum in your published wrapper exactly matches the Prisma schema’s values (calendar, messaging) to avoid mismatches.

packages/app-store/utils.ts (2)

4-4: Good: import constant from constants

This aligns imports and avoids the prior utils self-reference.


21-25: Verify existence of @calcom/app-store-types and its export
I couldn’t locate a packages/app-store-types directory or an export named CredentialDataWithTeamName in the repo—please confirm that the @calcom/app-store-types package and the CredentialDataWithTeamName export exist before re-exporting.

@@ -1,3 +1,12 @@
import type { AppCategories } from "@prisma/client";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import type { AppCategories } from "@prisma/client";
import type { AppCategories } from "@calcom/prisma/enums";

Copy link
Member

@hariombalhara hariombalhara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small suggestion, otherwise good !!

@github-actions
Copy link
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added the Stale label Sep 23, 2025
Copy link
Contributor

@Udit-takkar Udit-takkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joeauyeung Can you please fix all the conflicts? and do we still need this PR?

@Udit-takkar Udit-takkar marked this pull request as draft September 25, 2025 18:58
@github-actions github-actions bot removed the Stale label Sep 26, 2025
@github-actions
Copy link
Contributor

This PR is being marked as stale due to inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app-store area: app store, apps, calendar integrations, google calendar, outlook, lark, apple calendar core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e 💻 refactor size/M Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants