refactor: remove circular dependency between appstore and trpc#23768
refactor: remove circular dependency between appstore and trpc#23768
Conversation
WalkthroughThis PR is a large-scale import and type-surface refactor: many relative imports were replaced with canonical aliases (e.g., @calcom/app-store, @calcom/web, @calcom/features), several prop/type definitions were moved into their server-side props modules, routing-forms client config was rehomed (removed from app-store and added under web), routing-forms error handling switched from TRPCError to HttpError, and multiple components gained or forwarded an onAppInstallSuccess callback. No control-flow or core business logic was introduced beyond error-type and exported-symbol adjustments. (≈77 words) Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
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. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
…-between-appstore-trpc
E2E results are ready! |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
.eslintrc.js (2)
11-21: Make the app-store boundary symmetric by failing imports from @calcom/app-store in lib/prismaToday this is only a warning; consider failing CI the same way to prevent regressions.
Apply this diff:
rules: { "no-restricted-imports": [ - "warn", - { - paths: ["@calcom/app-store"], - patterns: ["@calcom/app-store/*"], - }, + "error", + { + paths: [ + { name: "@calcom/app-store", message: "Core packages (lib/prisma) must not depend on app-store." } + ], + patterns: [ + { group: "@calcom/app-store/*", message: "Do not import app-store subpaths from core packages." } + ], + allowTypeImports: false + }, ], },
25-31: Hardened boundary is correct; add guidance + block type-only importsScan of packages/app-store found no @calcom/trpc imports.
"no-restricted-imports": [ - "error", - { - paths: ["@calcom/trpc"], - patterns: ["@calcom/trpc/*"], - }, + "error", + { + paths: [ + { name: "@calcom/trpc", message: "packages/app-store must not depend on @calcom/trpc. Move UI to apps/web and keep routers in packages/trpc." } + ], + patterns: [ + { group: "@calcom/trpc/*", message: "packages/app-store must not import any subpath of @calcom/trpc." } + ], + allowTypeImports: false + }, ],Apply the diff to add explanatory messages and prevent type-only import leaks.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
.eslintrc.js(1 hunks)
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
apps/web/components/apps/routing-forms/SingleForm.tsx (1)
18-18: Resolved: SSR helper is type-only.Good fix. Prevents bundling server code in the client.
🧹 Nitpick comments (5)
apps/web/components/apps/routing-forms/SingleForm.tsx (5)
26-38: Public prop contract is clear; minor type polish.Consider extracting the inline Page prop object into a named type to reduce repetition and improve discoverability.
Apply:
+export type SingleFormPageProps = { + form: RoutingFormWithResponseCount; + appUrl: string; + hookForm: UseFormReturn<RoutingFormWithResponseCount>; +}; export type SingleFormComponentProps = { form: RoutingFormWithResponseCount; appUrl: string; - Page: React.FC<{ - form: RoutingFormWithResponseCount; - appUrl: string; - hookForm: UseFormReturn<RoutingFormWithResponseCount>; - }>; + Page: React.FC<SingleFormPageProps>; enrichedWithUserProfileForm: inferSSRProps< typeof getServerSidePropsForSingleFormView >["enrichedWithUserProfileForm"]; permissions: inferSSRProps<typeof getServerSidePropsForSingleFormView>["permissions"]; };
106-107: useFormContext requires an ancestor FormProvider.This component calls useFormContext before rendering the
that likely provides the context. If no provider wraps SingleForm higher up, this will throw at runtime.If there is no upstream provider, initialize the form locally:
-import { useFormContext } from "react-hook-form"; +import { useForm } from "react-hook-form"; @@ - const hookForm = useFormContext<RoutingFormWithResponseCount>(); + const hookForm = useForm<RoutingFormWithResponseCount>({ values: form });If there is an upstream provider, consider removing the redundant provider in or avoid re-providing the same instance.
142-143: Localize fallback error toast.Avoid hardcoded strings in UI; use t().
- showToast(`Something went wrong`, "error"); + showToast(t("something_went_wrong"), "error");
148-157: Test preview may be stale for non-route fields.uptoDateForm re-renders only when routes changes. Other field edits won’t refresh the preview.
Minimal change to watch the whole form:
- const uptoDateForm = { - ...hookForm.getValues(), - routes: hookForm.watch("routes"), + const watchedForm = hookForm.watch(); + const uptoDateForm = { + ...watchedForm, + routes: watchedForm?.routes, user: enrichedWithUserProfileForm.user, team: enrichedWithUserProfileForm.team, nonOrgUsername: enrichedWithUserProfileForm.nonOrgUsername, nonOrgTeamslug: enrichedWithUserProfileForm.nonOrgTeamslug, userOrigin: enrichedWithUserProfileForm.userOrigin, teamOrigin: enrichedWithUserProfileForm.teamOrigin, } as UptoDateForm;If re-render cost is a concern, move the watch into a small preview-only child (e.g., inside TestFormRenderer) using useWatch to isolate updates.
231-236: Run RHF validation before saving from the dialog.Directly mutating with getValues bypasses client-side validation and normalization.
- <InfoLostWarningDialog - handleSubmit={() => { - mutation.mutate({ - ...hookForm.getValues(), - }); - }} + <InfoLostWarningDialog + handleSubmit={hookForm.handleSubmit((values) => { + mutation.mutate(values); + })}
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
apps/web/components/apps/routing-forms/SingleForm.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Always use
t()for text localization in frontend code; direct text embedding should trigger a warning
Files:
apps/web/components/apps/routing-forms/SingleForm.tsx
**/*.{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:
apps/web/components/apps/routing-forms/SingleForm.tsx
**/*.{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:
apps/web/components/apps/routing-forms/SingleForm.tsx
🧠 Learnings (2)
📚 Learning: 2025-08-29T22:57:30.382Z
Learnt from: bandhan-majumder
PR: calcom/cal.com#23454
File: packages/features/form-builder/FormBuilder.tsx:11-11
Timestamp: 2025-08-29T22:57:30.382Z
Learning: FormBuilder.tsx in packages/features/form-builder/ does not have "use client" directive at the top despite using client-side React hooks and event handlers, which suggests it should be a client component.
Applied to files:
apps/web/components/apps/routing-forms/SingleForm.tsx
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
Applied to files:
apps/web/components/apps/routing-forms/SingleForm.tsx
🧬 Code graph analysis (1)
apps/web/components/apps/routing-forms/SingleForm.tsx (2)
packages/app-store/routing-forms/types/types.d.ts (1)
RoutingFormWithResponseCount(106-114)apps/web/lib/apps/routing-forms/[...pages]/getServerSidePropsSingleForm.ts (1)
getServerSidePropsForSingleFormView(9-166)
⏰ 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: Codacy Static Code Analysis
🔇 Additional comments (4)
apps/web/components/apps/routing-forms/SingleForm.tsx (4)
6-6: Type-only import for UseFormReturn is correct.Keeps runtime bundle clean.
13-13: Type-only import for inferSSRProps is correct.Ties client props to SSR safely without runtime coupling.
22-24: Import path consolidation looks good.Localizing TestForm/Header usage under the same directory improves cohesion.
8-9: Verify no tRPC usage inside app-store InfoLostWarningDialog.Search script produced no output; verification inconclusive. Confirm @calcom/app-store/routing-forms/components/InfoLostWarningDialog (imported in apps/web/components/apps/routing-forms/SingleForm.tsx — lines 8–9) and all transitive imports do not import @calcom/trpc to avoid reintroducing circular deps.
| utils.viewer.apps.appById.invalidate({ appId }); | ||
| utils.viewer.apps.integrations.invalidate({ | ||
| extendsFeature: "EventType", | ||
| ...(teamId && { teamId }), | ||
| }); |
There was a problem hiding this comment.
To remove the import of trpc client in this file (appstore package), I moved this logic to one level higher: packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx.
I am aware that features shouldn't import trpc ideally but that's another huddle we have to address cc @keithwillcode
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
packages/app-store/paypal/components/EventTypeAppCardInterface.tsx (1)
39-46: Persist the toggle to app data (parity with other apps)Switch only updates local state; it doesn’t persist to app data. This diverges from others using updateEnabled/setAppData and likely won’t survive save/navigation.
Apply:
- switchOnClick={(enabled) => { - setRequirePayment(enabled); - }} + switchOnClick={(enabled) => { + setRequirePayment(enabled); + setAppData("enabled", enabled); + }}packages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsx (1)
43-47: Switch toggling isn’t persisted to app dataLocal state requirePayment diverges from stored “enabled”. Use useIsAppEnabled(app) and updateEnabled to persist, and gate UI on enabled.
+import useIsAppEnabled from "@calcom/app-store/_utils/useIsAppEnabled"; @@ - const enable = getAppData("enabled"); - - const [requirePayment, setRequirePayment] = useState(enable); + const { enabled, updateEnabled } = useIsAppEnabled(app); @@ - switchChecked={requirePayment} - switchOnClick={(enabled) => { - setRequirePayment(enabled); - }} + switchChecked={enabled} + switchOnClick={(e) => { + updateEnabled(e); + }} @@ - requirePayment && ( + enabled && (Also applies to: 57-61, 66-68, 111-116
packages/app-store/insihts/components/EventTypeAppCardInterface.tsx (1)
1-3: Fix misspelled directory: packages/app-store/insihts → packages/app-store/insightsConfirmed packages/app-store/insihts exists and no occurrences of "insights" were found; rename the directory and update any imports/registry/slug references.
Affected example: packages/app-store/insihts/ (e.g. packages/app-store/insihts/components/EventTypeAppCardInterface.tsx).packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx (2)
243-247: Avoid mutating state objects in placeDeleting keys on onBookingWriteToEventObjectMap mutates the same reference; updates may not propagate.
Apply:
- const newObject = onBookingWriteToEventObjectMap; - delete onBookingWriteToEventObjectMap[key]; - setAppData("onBookingWriteToEventObjectMap", newObject); + const { [key]: _omit, ...rest } = onBookingWriteToEventObjectMap; + setAppData("onBookingWriteToEventObjectMap", rest);
40-41: Type mismatch: array vs string in input valueonBookingChangeRecordOwnerName defaults to [] but is bound to a text input (string). This can cause runtime issues and incorrect data shape.
Apply:
- const onBookingChangeRecordOwnerName = getAppData("onBookingChangeRecordOwnerName") ?? []; + const onBookingChangeRecordOwnerName = + (getAppData("onBookingChangeRecordOwnerName") as string | undefined) ?? ""; @@ - <InputField + <InputField id="on-booking-change-record-owner-name" size="sm" value={onBookingChangeRecordOwnerName} onChange={(e) => setAppData("onBookingChangeRecordOwnerName", e.target.value)} />If multiple owners are required, switch to a multiselect or chips input and persist an array consistently.
Also applies to: 348-352
🧹 Nitpick comments (33)
packages/app-store/matomo/components/EventTypeAppCardInterface.tsx (1)
26-46: Localize user-facing labels/placeholdersTextField labels/placeholders should use t() per guidelines.
Apply:
- <TextField - dataTestid={`${app.slug}-url`} - name="Matomo URL" - placeholder="Enter your Matomo URL here" + <TextField + data-testid={`${app.slug}-url`} + name={t("matomo_url")} + placeholder={t("enter_matomo_url")} value={matomoUrl} disabled={disabled} onChange={(e) => { setAppData("MATOMO_URL", e.target.value); }} /> - <TextField - dataTestid={`${app.slug}-site-id`} + <TextField + data-testid={`${app.slug}-site-id`} disabled={disabled} - name="Site ID" - placeholder="Enter your Site ID" + name={t("site_id")} + placeholder={t("enter_site_id")} value={siteId} onChange={(e) => { setAppData("SITE_ID", e.target.value); }} />And add t():
import { TextField } from "@calcom/ui/components/form"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ -const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app, eventType, onAppInstallSuccess }) { +const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app, eventType, onAppInstallSuccess }) { + const { t } = useLocale();packages/app-store/paypal/components/EventTypeAppCardInterface.tsx (2)
43-45: Localize description and fix brand casingUse t() and “PayPal”.
- description={<>Add Paypal payment to your events</>} + description={t("add_paypal_payment_to_your_events")}
21-22: Remove stale TODO about pathname bracketsComment no longer applies; remove to avoid confusion.
- /** TODO "pathname" no longer contains square-bracket expressions. Rewrite the code relying on them if required. **/packages/app-store/umami/components/EventTypeAppCardInterface.tsx (1)
29-47: Avoid controlled + defaultValue mix; localize labels/placeholdersPassing both value and defaultValue is an anti-pattern; also localize text.
- <TextField - disabled={disabled} - name="Script URL" - value={scriptURL} - defaultValue="https://us.umami.is/script.js" - placeholder="Enter the script source URL" + <TextField + disabled={disabled} + name={t("script_url")} + value={scriptURL} + placeholder={t("enter_script_source_url")} onChange={(e) => { setAppData("SCRIPT_URL", e.target.value); }} /> - <TextField - disabled={disabled} - name="Site ID" + <TextField + disabled={disabled} + name={t("site_id")} value={siteId} - placeholder="Enter your Site ID" + placeholder={t("enter_site_id")} onChange={(e) => { setAppData("SITE_ID", e.target.value); }} />Add t():
import { TextField } from "@calcom/ui/components/form"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale();packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
27-27: Localize ErrorBoundary messageUser-facing string should use t().
-import { ErrorBoundary } from "@calcom/ui/components/errorBoundary"; +import { ErrorBoundary } from "@calcom/ui/components/errorBoundary"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ -export const EventTypeAppCard = (props: { +export const EventTypeAppCard = (props: { @@ - return ( + const { t } = useLocale(); + return ( <ErrorBoundary message={`There is some problem with ${app.name} App`}>Prefer:
- <ErrorBoundary message={`There is some problem with ${app.name} App`}> + <ErrorBoundary message={t("there_is_a_problem_with_app", { appName: app.name })}>packages/app-store/_components/OmniInstallAppButton.tsx (1)
33-36: Guard callback to avoid breaking success flowA thrown error in onAppInstallSuccess would suppress the toast. Wrap it.
- onAppInstallSuccess(); + try { + onAppInstallSuccess(); + } catch (err) { + console.error("onAppInstallSuccess failed", err); + }packages/app-store/types.d.ts (1)
74-76: Tiny doc nit: stray backslashRemove the trailing backslash in the comment.
- // Limit what data should be accessible to apps\ + // Limit what data should be accessible to appspackages/app-store/twipla/components/EventTypeAppCardInterface.tsx (1)
23-31: Localize user‑visible stringsReplace hardcoded “Site ID” and “Enter your Site ID” with t(). Also add useLocale.
+import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale(); @@ - <TextField + <TextField disabled={disabled} - name="Site ID" + name={t("site_id")} value={siteId} - placeholder="Enter your Site ID" + placeholder={t("enter_your_site_id")} onChange={(e) => { setAppData("SITE_ID", e.target.value); }} />[coding_guidelines]
packages/app-store/qr_code/components/EventTypeAppCardInterface.tsx (1)
23-33: Localize placeholders/labels and avoid duplicate disabledUse t() for “Site ID”/placeholder and drop redundant disabled on TextField (fieldset already disables children).
+import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale(); @@ - <fieldset className="space-y-2" disabled={disabled}> - <TextField - disabled={disabled} - name="Site ID" + <fieldset className="space-y-2" disabled={disabled}> + <TextField + name={t("site_id")} value={siteId} - placeholder="Enter your Site ID" + placeholder={t("enter_your_site_id")} onChange={(e) => { setAppData("SITE_ID", e.target.value); }} />[coding_guidelines]
packages/app-store/fathom/components/EventTypeAppCardInterface.tsx (1)
23-31: Localize user‑visible stringsUse t() for “Site ID” and its placeholder; add useLocale.
+import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale(); @@ - <EventTypeAppSettingsInterface + <EventTypeAppSettingsInterface eventType={eventType} slug={app.slug} disabled={disabled} getAppData={getAppData} setAppData={setAppData} />And in the TextField below (keep current structure), change:
- name="Site ID" - placeholder="Enter your Site ID" + name={t("site_id")} + placeholder={t("enter_your_site_id")}[coding_guidelines]
packages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsx (3)
61-61: Localize user‑visible stringsWrap description, “Price”, and “Payment option” in t().
[coding_guidelines]
- description={<>Add a mock payment to your events</>} + description={<>{t("add_mock_payment_to_your_events")}</>} @@ - label="Price" + label={t("price")} @@ - placeholder="Price" + placeholder={t("price")} @@ - <label className="text-default mb-1 block text-sm font-medium" htmlFor="currency"> - Payment option - </label> + <label className="text-default mb-1 block text-sm font-medium" htmlFor="currency"> + {t("payment_option")} + </label>Also applies to: 71-81, 112-114
82-87: Avoid floating‑point currency errorsStore cents as integers using Math.round.
- setAppData("price", Number(e.target.value) * 100); + setAppData("price", Math.round(Number(e.target.value) * 100));
25-30: Stale TODO around pathnameIf no longer relying on bracketed segments, remove or update the comment.
packages/app-store/basecamp3/components/EventTypeAppCardInterface.tsx (1)
5-5: Prefer path alias over relative importUse monorepo alias for consistency and easier refactors.
-import useIsAppEnabled from "../../_utils/useIsAppEnabled"; +import useIsAppEnabled from "@calcom/app-store/_utils/useIsAppEnabled";packages/app-store/gtm/components/EventTypeAppCardInterface.tsx (3)
22-22: Use nullish coalescing for teamIdAvoid || which treats 0 as falsy; prefer ??.
Apply:
- teamId={eventType.team?.id || undefined}> + teamId={eventType.team?.id ?? undefined}>
34-34: Prefer named export (optional)Consider a named export for better tree‑shaking and refactors.
-export default EventTypeAppCard; +export { EventTypeAppCard };
9-22: Replace|| undefinedwith??for teamId and confirm onAppInstallSuccess forwarding
- Scan result: all EventTypeAppCardInterface files forward onAppInstallSuccess to except packages/app-store/_components/EventTypeAppCardInterface.tsx (it references onAppInstallSuccess but contains no — confirm intended behavior).
- Files that still use teamId={eventType.team?.id || undefined} (update to
teamId={eventType.team?.id ?? undefined}or simplyteamId={eventType.team?.id}):
- packages/app-store/zohocrm/components/EventTypeAppCardInterface.tsx
- packages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsx
- packages/app-store/umami/components/EventTypeAppCardInterface.tsx
- packages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsx
- packages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsx
- packages/app-store/twipla/components/EventTypeAppCardInterface.tsx
- packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx
- packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx
- packages/app-store/qr_code/components/EventTypeAppCardInterface.tsx
- packages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsx
- packages/app-store/plausible/components/EventTypeAppCardInterface.tsx
- packages/app-store/posthog/components/EventTypeAppCardInterface.tsx
- packages/app-store/metapixel/components/EventTypeAppCardInterface.tsx
- packages/app-store/matomo/components/EventTypeAppCardInterface.tsx
- packages/app-store/insihts/components/EventTypeAppCardInterface.tsx
- packages/app-store/hubspot/components/EventTypeAppCardInterface.tsx
- packages/app-store/gtm/components/EventTypeAppCardInterface.tsx
- packages/app-store/giphy/components/EventTypeAppCardInterface.tsx
- packages/app-store/hitpay/components/EventTypeAppCardInterface.tsx
- packages/app-store/ga4/components/EventTypeAppCardInterface.tsx
- packages/app-store/fathom/components/EventTypeAppCardInterface.tsx
- packages/app-store/closecom/components/EventTypeAppCardInterface.tsx
packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx (1)
38-38: Use ?? instead of || for teamIdPrevents dropping a valid 0 id.
- teamId={eventType.team?.id || undefined} + teamId={eventType.team?.id ?? undefined}packages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsx (1)
38-38: Localize user‑visible textWrap description in t() per frontend i18n guideline.
- description={<>Add lightning payments to your events and booking</>} + description={<>{t("add_lightning_payments_to_your_events_and_booking")}</>}packages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsx (1)
18-18: Use ?? for teamIdAvoid falsy pitfalls.
- teamId={eventType.team?.id || undefined} + teamId={eventType.team?.id ?? undefined}packages/app-store/closecom/components/EventTypeAppCardInterface.tsx (2)
32-32: Use ?? for teamIdSafer nullish handling.
- teamId={eventType.team?.id || undefined} + teamId={eventType.team?.id ?? undefined}
34-44: Localize strings in UIUser‑visible strings should use t().
- <span className="ltr:mr-2 rtl:ml-2"> + <span className="ltr:mr-2 rtl:ml-2"> <Icon name={isSunrise ? "sunrise" : "sunset"} /> </span> - I am an AppCard for Event with Title: {eventType.title} + {t("appcard_for_event_with_title", { title: eventType.title })} </div>{" "} <div className="mt-2"> - Edit <span className="italic">packages/app-store/{app.slug}/EventTypeAppCardInterface.tsx</span> to - play with me + {t("edit_event_type_appcard_interface_to_play", { slug: app.slug })} </div>packages/app-store/alby/components/EventTypeAppCardInterface.tsx (1)
43-45: Localize descriptionUse t() for the description string.
- description={<>Add bitcoin lightning payments to your events</>} + description={<>{t("add_bitcoin_lightning_payments_to_your_events")}</>}packages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsx (1)
49-49: Prefer named export (optional)Consider exporting EventTypeAppCard as a named export in templates as well.
-export default EventTypeAppCard; +export { EventTypeAppCard };packages/app-store/hitpay/components/EventTypeAppCardInterface.tsx (1)
38-38: Use ?? for teamIdAvoid || here.
- teamId={eventType.team?.id || undefined} + teamId={eventType.team?.id ?? undefined}packages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsx (2)
28-35: Localize user‑visible strings"Tracking ID" should use t() per guidelines. Add useLocale and wrap labels/placeholders.
Apply:
+import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale(); @@ - <TextField - name="Tracking ID" + <TextField + name={t("tracking_id")} value={trackingId} onChange={(e) => { setAppData("trackingId", e.target.value); }} />
19-27: Align enabled state handling with existing hookYou manage enabled via local state while AppCard also writes enabled via context. Prefer useIsAppEnabled(app) for a single source of truth.
Apply:
+import useIsAppEnabled from "@calcom/app-store/_utils/useIsAppEnabled"; @@ - const [enabled, setEnabled] = useState(getAppData("enabled")); + const { enabled, updateEnabled } = useIsAppEnabled(app); @@ - switchOnClick={(e) => { - if (!e) { - setEnabled(false); - } else { - setEnabled(true); - } - }} + switchOnClick={(e) => updateEnabled(e)}packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx (2)
295-297: Localize user‑visible strings
- showToast("Field already exists", …)
- Section title "Send no show attendee data to event object"
- Label "Field name to check (must be checkbox data type)"
Wrap with t() and add corresponding keys.
Apply:
- showToast("Field already exists", "error"); + showToast(t("field_already_exists"), "error"); @@ - <Section.SubSectionHeader - icon="calendar" - title="Send no show attendee data to event object" + <Section.SubSectionHeader + icon="calendar" + title={t("send_no_show_attendee_data_to_event_object")} @@ - Field name to check (must be checkbox data type) + {t("field_name_to_check_checkbox")}Also applies to: 460-477
367-367: Minor: fix id typo"book-directly-witha-attendee-owner" → "book-directly-with-attendee-owner".
- id="book-directly-witha-attendee-owner" + id="book-directly-with-attendee-owner"packages/app-store/posthog/components/EventTypeAppCardInterface.tsx (1)
30-49: Localize labels/placeholders and fix casingUse t() for "Tracking ID", "API host", and placeholders. Prefer "API host URL".
Apply:
+import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ - const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); + const { t } = useLocale(); @@ - <TextField + <TextField required disabled={disabled} - name="Tracking ID" + name={t("tracking_id")} value={trackingId} - placeholder="Enter your Tracking ID" + placeholder={t("enter_your_tracking_id")} onChange={(e) => { setAppData("TRACKING_ID", e.target.value); }} /> @@ - <TextField + <TextField required disabled={disabled} - name="Api host" + name={t("api_host")} value={apiHost} - placeholder="Enter your Api host url" + placeholder={t("enter_api_host_url")} onChange={(e) => { setAppData("API_HOST", e.target.value); }} />packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx (1)
147-148: Nit: simplify nested map with flatMapMinor readability improvement.
- {cardsForAppsWithTeams.map((apps) => apps.map((cards) => cards))} + {cardsForAppsWithTeams.flat()}packages/app-store/plausible/components/EventTypeAppCardInterface.tsx (2)
19-21: Micro: pass handler directlySlight tidy-up; avoids creating a new closure each render.
- switchOnClick={(e) => { - updateEnabled(e); - }} + switchOnClick={updateEnabled}
23-23: Avoid falsy trap with teamIdUse nullish coalescing to preserve a valid teamId of 0.
- teamId={eventType.team?.id || undefined}> + teamId={eventType.team?.id ?? undefined}>
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (34)
.eslintrc.js(1 hunks)packages/app-store/_components/AppCard.tsx(2 hunks)packages/app-store/_components/DynamicComponent.tsx(1 hunks)packages/app-store/_components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/_components/OmniInstallAppButton.tsx(1 hunks)packages/app-store/alby/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/basecamp3/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/closecom/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/fathom/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/ga4/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/giphy/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/gtm/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/hitpay/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/hubspot/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/insihts/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/matomo/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/metapixel/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/paypal/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/plausible/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/posthog/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/qr_code/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx(2 hunks)packages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/twipla/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/types.d.ts(1 hunks)packages/app-store/umami/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/zohocrm/components/EventTypeAppCardInterface.tsx(1 hunks)packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx(6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/app-store/types.d.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/types.d.tspackages/app-store/_components/DynamicComponent.tsxpackages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsxpackages/app-store/stripepayment/components/EventTypeAppCardInterface.tsxpackages/app-store/basecamp3/components/EventTypeAppCardInterface.tsxpackages/app-store/closecom/components/EventTypeAppCardInterface.tsxpackages/app-store/qr_code/components/EventTypeAppCardInterface.tsxpackages/app-store/umami/components/EventTypeAppCardInterface.tsxpackages/app-store/salesforce/components/EventTypeAppCardInterface.tsxpackages/app-store/insihts/components/EventTypeAppCardInterface.tsxpackages/app-store/fathom/components/EventTypeAppCardInterface.tsxpackages/app-store/zohocrm/components/EventTypeAppCardInterface.tsxpackages/app-store/plausible/components/EventTypeAppCardInterface.tsxpackages/app-store/paypal/components/EventTypeAppCardInterface.tsxpackages/app-store/hubspot/components/EventTypeAppCardInterface.tsxpackages/app-store/metapixel/components/EventTypeAppCardInterface.tsxpackages/app-store/matomo/components/EventTypeAppCardInterface.tsxpackages/app-store/alby/components/EventTypeAppCardInterface.tsxpackages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsxpackages/app-store/twipla/components/EventTypeAppCardInterface.tsxpackages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/AppCard.tsxpackages/app-store/giphy/components/EventTypeAppCardInterface.tsxpackages/app-store/ga4/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsxpackages/app-store/posthog/components/EventTypeAppCardInterface.tsxpackages/app-store/gtm/components/EventTypeAppCardInterface.tsxpackages/app-store/hitpay/components/EventTypeAppCardInterface.tsxpackages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/OmniInstallAppButton.tsxpackages/app-store/_components/EventTypeAppCardInterface.tsxpackages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx
**/*.{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/types.d.tspackages/app-store/_components/DynamicComponent.tsxpackages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsxpackages/app-store/stripepayment/components/EventTypeAppCardInterface.tsxpackages/app-store/basecamp3/components/EventTypeAppCardInterface.tsxpackages/app-store/closecom/components/EventTypeAppCardInterface.tsxpackages/app-store/qr_code/components/EventTypeAppCardInterface.tsxpackages/app-store/umami/components/EventTypeAppCardInterface.tsxpackages/app-store/salesforce/components/EventTypeAppCardInterface.tsxpackages/app-store/insihts/components/EventTypeAppCardInterface.tsxpackages/app-store/fathom/components/EventTypeAppCardInterface.tsxpackages/app-store/zohocrm/components/EventTypeAppCardInterface.tsxpackages/app-store/plausible/components/EventTypeAppCardInterface.tsxpackages/app-store/paypal/components/EventTypeAppCardInterface.tsxpackages/app-store/hubspot/components/EventTypeAppCardInterface.tsxpackages/app-store/metapixel/components/EventTypeAppCardInterface.tsxpackages/app-store/matomo/components/EventTypeAppCardInterface.tsxpackages/app-store/alby/components/EventTypeAppCardInterface.tsxpackages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsxpackages/app-store/twipla/components/EventTypeAppCardInterface.tsxpackages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/AppCard.tsxpackages/app-store/giphy/components/EventTypeAppCardInterface.tsxpackages/app-store/ga4/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsxpackages/app-store/posthog/components/EventTypeAppCardInterface.tsxpackages/app-store/gtm/components/EventTypeAppCardInterface.tsxpackages/app-store/hitpay/components/EventTypeAppCardInterface.tsxpackages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/OmniInstallAppButton.tsxpackages/app-store/_components/EventTypeAppCardInterface.tsxpackages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Always use
t()for text localization in frontend code; direct text embedding should trigger a warning
Files:
packages/app-store/_components/DynamicComponent.tsxpackages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsxpackages/app-store/stripepayment/components/EventTypeAppCardInterface.tsxpackages/app-store/basecamp3/components/EventTypeAppCardInterface.tsxpackages/app-store/closecom/components/EventTypeAppCardInterface.tsxpackages/app-store/qr_code/components/EventTypeAppCardInterface.tsxpackages/app-store/umami/components/EventTypeAppCardInterface.tsxpackages/app-store/salesforce/components/EventTypeAppCardInterface.tsxpackages/app-store/insihts/components/EventTypeAppCardInterface.tsxpackages/app-store/fathom/components/EventTypeAppCardInterface.tsxpackages/app-store/zohocrm/components/EventTypeAppCardInterface.tsxpackages/app-store/plausible/components/EventTypeAppCardInterface.tsxpackages/app-store/paypal/components/EventTypeAppCardInterface.tsxpackages/app-store/hubspot/components/EventTypeAppCardInterface.tsxpackages/app-store/metapixel/components/EventTypeAppCardInterface.tsxpackages/app-store/matomo/components/EventTypeAppCardInterface.tsxpackages/app-store/alby/components/EventTypeAppCardInterface.tsxpackages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsxpackages/app-store/twipla/components/EventTypeAppCardInterface.tsxpackages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/AppCard.tsxpackages/app-store/giphy/components/EventTypeAppCardInterface.tsxpackages/app-store/ga4/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsxpackages/app-store/posthog/components/EventTypeAppCardInterface.tsxpackages/app-store/gtm/components/EventTypeAppCardInterface.tsxpackages/app-store/hitpay/components/EventTypeAppCardInterface.tsxpackages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsxpackages/app-store/_components/OmniInstallAppButton.tsxpackages/app-store/_components/EventTypeAppCardInterface.tsxpackages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-12T07:15:58.030Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.030Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.
Applied to files:
packages/app-store/types.d.tspackages/app-store/basecamp3/components/EventTypeAppCardInterface.tsxpackages/app-store/closecom/components/EventTypeAppCardInterface.tsxpackages/app-store/qr_code/components/EventTypeAppCardInterface.tsxpackages/app-store/umami/components/EventTypeAppCardInterface.tsxpackages/app-store/salesforce/components/EventTypeAppCardInterface.tsxpackages/app-store/insihts/components/EventTypeAppCardInterface.tsxpackages/app-store/fathom/components/EventTypeAppCardInterface.tsxpackages/app-store/zohocrm/components/EventTypeAppCardInterface.tsxpackages/app-store/plausible/components/EventTypeAppCardInterface.tsxpackages/app-store/metapixel/components/EventTypeAppCardInterface.tsxpackages/app-store/matomo/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsxpackages/app-store/twipla/components/EventTypeAppCardInterface.tsxpackages/app-store/giphy/components/EventTypeAppCardInterface.tsxpackages/app-store/ga4/components/EventTypeAppCardInterface.tsxpackages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsxpackages/app-store/posthog/components/EventTypeAppCardInterface.tsxpackages/app-store/gtm/components/EventTypeAppCardInterface.tsxpackages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsx
🧬 Code graph analysis (25)
packages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)
packages/app-store/basecamp3/components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/closecom/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/qr_code/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/umami/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)
packages/app-store/insihts/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/fathom/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/zohocrm/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/plausible/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/hubspot/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/metapixel/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/matomo/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/twipla/components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/_components/AppCard.tsx (1)
packages/app-store/types.d.ts (1)
AppCardApp(25-27)
packages/app-store/giphy/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/ga4/components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/posthog/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/gtm/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsx (3)
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
EventTypeAppCard(14-38)packages/app-store/types.d.ts (1)
EventTypeAppCardComponent(88-88)packages/app-store/_components/AppCard.tsx (1)
AppCard(16-149)
packages/app-store/_components/EventTypeAppCardInterface.tsx (2)
packages/app-store/_components/DynamicComponent.tsx (1)
DynamicComponent(2-21)packages/app-store/apps.browser.generated.tsx (1)
EventTypeAddonMap(22-54)
packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx (1)
packages/trpc/react/trpc.ts (1)
trpc(54-138)
🔇 Additional comments (32)
.eslintrc.js (1)
26-26: Confirm no remaining tRPC imports in packages/app-store. Ran ripgrep for '@calcom/trpc' and '@trpc/' under packages/app-store — no matches found.packages/app-store/matomo/components/EventTypeAppCardInterface.tsx (2)
9-18: Good: onAppInstallSuccess is correctly plumbed to AppCardForwarding the callback here matches the updated public API.
27-38: data-testid prop casing — OK
TextField accepts a camelCasedataTestidprop and maps it to the DOMdata-testid; EventTypeAppCard'sdataTestidusage is correct (packages/ui/components/form/inputs/TextField.tsx).packages/app-store/hubspot/components/EventTypeAppCardInterface.tsx (1)
8-16: LGTM: prop added and forwardedonAppInstallSuccess is correctly added to the signature and passed to AppCard.
packages/app-store/_components/EventTypeAppCardInterface.tsx (1)
19-20: LGTM: public API extended and forwarded properlyonAppInstallSuccess added to props, destructured, and forwarded to DynamicComponent.
Also applies to: 25-26, 33-34
packages/app-store/metapixel/components/EventTypeAppCardInterface.tsx (1)
9-20: LGTM: parity with other EventType cardsSignature update and forwarding look consistent.
packages/app-store/types.d.ts (1)
68-69: Resolved — EventTypeAppCardInterface implementations forward onAppInstallSuccessVerified: every EventTypeAppCardInterface in packages/app-store/*/components (and packages/app-store/_components/EventTypeAppCardInterface.tsx) accepts and forwards onAppInstallSuccess to . AppCard usages in packages/features/apps and apps/web import a different AppCard and are unaffected. No changes required.
packages/app-store/ga4/components/EventTypeAppCardInterface.tsx (1)
9-13: onAppInstallSuccess correctly added and forwarded — LGTMThe prop is wired into the component API and passed to AppCard as required.
Also applies to: 19-20
packages/app-store/twipla/components/EventTypeAppCardInterface.tsx (1)
9-9: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard.
Also applies to: 16-17
packages/app-store/qr_code/components/EventTypeAppCardInterface.tsx (1)
9-9: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard.
Also applies to: 16-17
packages/app-store/fathom/components/EventTypeAppCardInterface.tsx (1)
9-9: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard.
Also applies to: 15-16
packages/app-store/insihts/components/EventTypeAppCardInterface.tsx (1)
8-12: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard.
Also applies to: 19-21
packages/app-store/mock-payment-app/components/EventTypeAppCardInterface.tsx (1)
23-23: onAppInstallSuccess propagation — looks goodWired through to AppCard.
Also applies to: 54-55
packages/app-store/zohocrm/components/EventTypeAppCardInterface.tsx (1)
8-12: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard; returnTo wiring consistent.
Also applies to: 19-21
packages/app-store/basecamp3/components/EventTypeAppCardInterface.tsx (1)
9-13: onAppInstallSuccess propagation — looks goodSignature updated and forwarded to AppCard.
Also applies to: 19-20
packages/app-store/gtm/components/EventTypeAppCardInterface.tsx (1)
9-16: Prop passthrough looks correctonAppInstallSuccess is correctly added to the signature and forwarded to AppCard. Type-only import usage for appDataSchema is also correct.
packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx (1)
15-20: Wiring is consistentonAppInstallSuccess is added and forwarded correctly; returnTo and other props unchanged.
Also applies to: 31-32
packages/app-store/btcpayserver/components/EventTypeAppCardInterface.tsx (1)
16-21: Wiring is correctonAppInstallSuccess is accepted and forwarded to AppCard.
Also applies to: 31-32
packages/app-store/pipedrive-crm/components/EventTypeAppCardInterface.tsx (1)
8-12: Looks goodSignature update and prop forwarding are consistent with the shared types.
Also applies to: 15-16, 19-19
packages/app-store/closecom/components/EventTypeAppCardInterface.tsx (1)
9-13: Good prop surface updateonAppInstallSuccess is correctly added and passed to AppCard.
Also applies to: 19-21
packages/app-store/alby/components/EventTypeAppCardInterface.tsx (1)
15-20: Prop added and forwarded correctlyonAppInstallSuccess is wired through to AppCard.
Also applies to: 35-37
packages/app-store/templates/event-type-app-card/components/EventTypeAppCardInterface.tsx (1)
9-13: Template wiring LGTMonAppInstallSuccess added and forwarded; aligns with the new AppCard API.
Also applies to: 20-20
packages/app-store/hitpay/components/EventTypeAppCardInterface.tsx (1)
15-20: Solid passthroughonAppInstallSuccess added and passed to AppCard as expected.
Also applies to: 31-32
packages/app-store/templates/booking-pages-tag/components/EventTypeAppCardInterface.tsx (1)
10-10: Good: callback threaded correctlyonAppInstallSuccess is added to the component signature and forwarded to AppCard. Looks consistent with the new contract.
Also applies to: 17-17
packages/app-store/giphy/components/EventTypeAppCardInterface.tsx (1)
10-14: LGTM: onAppInstallSuccess correctly added and forwardedSignature and AppCard prop are updated consistently.
Also applies to: 22-22
packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx (1)
23-23: LGTM: callback wiringonAppInstallSuccess added and passed into AppCard; matches the shared AppCard API.
Also applies to: 98-99
packages/app-store/posthog/components/EventTypeAppCardInterface.tsx (1)
9-13: LGTM: onAppInstallSuccess threadingSignature and AppCard prop look correct.
Also applies to: 21-21
packages/app-store/zoho-bigin/components/EventTypeAppCardInterface.tsx (1)
8-12: LGTM: callback added and forwardedSignature and AppCard prop are consistent with the shared API.
Also applies to: 19-19
packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx (1)
28-29: LGTM: cache invalidation callback wired throughutils.useUtils + handleAppInstallSuccess and forwarding onAppInstallSuccess across all cards is consistent and readable.
Also applies to: 46-53, 71-72, 96-97, 162-163, 196-197
packages/app-store/_components/AppCard.tsx (1)
28-32: API change: onAppInstallSuccess now requiredEnsure every <AppCard ...> usage includes onAppInstallSuccess={...}; otherwise TypeScript/CI will fail. Automated verification returned no conclusive results — manual repo check required.
Location: packages/app-store/_components/AppCard.tsx (lines 28–32; also 117–118).
packages/app-store/plausible/components/EventTypeAppCardInterface.tsx (2)
6-6: Good: type-only schema importUsing
import type { appDataSchema }keeps this module free of runtime deps; aligns with prior learning on schema-only usage.
1-4: No tRPC client usage found in the imported modulesScanned packages/app-store for "trpc", "createTRPC", "createTRPCReact", and "trpc." and inspected:
- packages/app-store/EventTypeAppContext.tsx
- packages/app-store/_components/AppCard.tsx
- packages/app-store/_utils/useIsAppEnabled.ts
- packages/app-store/types.d.ts
No matches found.
| const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app, eventType, onAppInstallSuccess }) { | ||
| const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>(); | ||
|
|
||
| const { enabled, updateEnabled } = useIsAppEnabled(app); | ||
|
|
||
| return ( | ||
| <AppCard | ||
| onAppInstallSuccess={onAppInstallSuccess} | ||
| hideSettingsIcon |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Prop added and correctly forwarded
Adding and passing onAppInstallSuccess to AppCard is correct and matches the updated contract.
Verify all call sites provide the new required prop:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Checking all <EventTypeAppCard …> usages for onAppInstallSuccess…"
files=$(rg -n --glob '!**/node_modules/**' -l '<EventTypeAppCard\b')
for f in $files; do
if ! rg -n 'onAppInstallSuccess\s*=' "$f" >/dev/null; then
echo "Missing onAppInstallSuccess in: $f"
fi
done || trueLength of output: 214
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Searching for JSX usages of EventTypeAppCard (including hidden/unignored files)..."
files=$(rg -n --hidden -uu -S -l '<EventTypeAppCard\b' || true)
if [[ -z "$files" ]]; then
echo "No JSX tag usages found. Searching for any references to EventTypeAppCard..."
files=$(rg -n --hidden -uu -S -l '\bEventTypeAppCard\b' || true)
fi
if [[ -z "$files" ]]; then
echo "No files reference EventTypeAppCard."
exit 0
fi
echo "Found references in the following files:"
printf '%s\n' "$files"
echo
missing=0
echo "Checking each file for an explicit onAppInstallSuccess prop..."
while IFS= read -r f; do
if rg -n --hidden -uu -S 'onAppInstallSuccess\s*=' "$f" >/dev/null 2>&1; then
echo "OK: $f"
else
echo "Missing onAppInstallSuccess in: $f"
missing=$((missing+1))
fi
done <<< "$files"
echo
echo "Summary: total files referencing EventTypeAppCard: $(echo "$files" | wc -l | tr -d ' ')"
echo "Files missing explicit onAppInstallSuccess: $missing"Length of output: 783
Add onAppInstallSuccess to these EventTypeAppCard call sites
- packages/platform/atoms/event-types/wrappers/EventPaymentsTabPlatformWrapper.tsx
- packages/app-store/_components/eventTypeAppCardInterface.test.tsx
There was a problem hiding this comment.
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 (4)
packages/app-store/_components/eventTypeAppCardInterface.test.tsx (4)
51-64: Fix: you’re calling the mocks before render; pass function refs instead.Using
getAppData: getAppDataMock()andsetAppData: setAppDataMock()executes the mocks immediately and makes the assertions trivially pass. Pass the functions, not their return values.Apply this diff:
- value={{ - getAppData: getAppDataMock(), - setAppData: setAppDataMock(), - }} + value={{ + getAppData: getAppDataMock, + setAppData: setAppDataMock, + }}
41-46: React FCs receive a single props arg; drop the extra{}in call assertions.
DynamicComponent(a function component) is invoked with props only. Expecting a second argument is brittle and may fail.Apply this diff in both places:
- expect(DynamicComponent).toHaveBeenCalledWith( - expect.objectContaining({ - slug: mockProps.app.slug, - }), - {} - ); + expect(DynamicComponent).toHaveBeenCalledWith( + expect.objectContaining({ + slug: mockProps.app.slug, + }) + );- expect(DynamicComponent).toHaveBeenCalledWith( - expect.objectContaining({ - slug: "stripepayment", - }), - {} - ); + expect(DynamicComponent).toHaveBeenCalledWith( + expect.objectContaining({ + slug: "stripepayment", + }) + );Also applies to: 77-82
3-3: Use Vitest types; throw to trigger the error boundary; scope to one call.Avoid
jest.Mockin a Vitest test and return-vs-throw confusion.Apply this diff:
-import { vi } from "vitest"; +import { vi, type Mock } from "vitest";- (DynamicComponent as jest.Mock).mockImplementation(() => { - return Error("Mocked error from DynamicComponent"); - }); + (DynamicComponent as Mock).mockImplementationOnce(() => { + throw new Error("Mocked error from DynamicComponent"); + });Also applies to: 88-90
16-18: Reset mock implementations between tests.
vi.clearAllMocks()doesn’t reset implementations. Usevi.resetAllMocks()for isolation.Apply this diff:
-afterEach(() => { - vi.clearAllMocks(); -}); +afterEach(() => { + vi.resetAllMocks(); +});
🧹 Nitpick comments (3)
packages/app-store/_components/eventTypeAppCardInterface.test.tsx (3)
33-33: Add an assertion that onAppInstallSuccess is forwarded.You add the prop but don’t verify it’s passed to
DynamicComponent.Append a test like:
+ test("Forwards onAppInstallSuccess to DynamicComponent", () => { + render(<EventTypeAppCard {...mockProps} />); + expect(DynamicComponent).toHaveBeenCalledWith( + expect.objectContaining({ + onAppInstallSuccess: mockProps.onAppInstallSuccess, + }) + ); + });
22-35: Avoidas any; typemockPropsprecisely.Use
satisfies Partial<ComponentProps<typeof EventTypeAppCard>>to keep type‑safety without over‑specifying.Apply this diff:
+import type { ComponentProps } from "react"; @@ - onAppInstallSuccess: vi.fn(), - // eslint-disable-next-line @typescript-eslint/no-explicit-any -} as any; + onAppInstallSuccess: vi.fn(), +} satisfies Partial<ComponentProps<typeof EventTypeAppCard>>;
93-94: Reduce brittleness of i18n‑dependent assertion.Asserting on a hardcoded English message is fragile. Prefer a role/testid or a stable container around the boundary.
Example:
// In component: <div data-testid="app-error-boundary">...</div> // In test: expect(screen.getByTestId("app-error-boundary")).toBeInTheDocument();
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
.eslintrc.js(1 hunks)packages/app-store/_components/EventTypeAppCardInterface.tsx(1 hunks)packages/app-store/_components/eventTypeAppCardInterface.test.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/app-store/_components/EventTypeAppCardInterface.tsx
- .eslintrc.js
🧰 Additional context used
📓 Path-based instructions (3)
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Always use
t()for text localization in frontend code; direct text embedding should trigger a warning
Files:
packages/app-store/_components/eventTypeAppCardInterface.test.tsx
**/*.{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/_components/eventTypeAppCardInterface.test.tsx
**/*.{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/_components/eventTypeAppCardInterface.test.tsx
🔇 Additional comments (1)
packages/app-store/_components/eventTypeAppCardInterface.test.tsx (1)
66-85: LGTM: stripe → stripepayment slug mapping test.Covers the critical alias behavior.
Impact
Problem Statement
Files in
packages/app-storewere importing tRPC client utilities, creating circular dependencies between the core app-store package and higher-level web application packages. This violated architectural boundaries and could cause build issues, increased bundle sizes, and runtime dependency resolution problems.Solution Overview
This PR resolves the circular dependency by migrating UI components and pages from
packages/app-storetoapps/web/components/apps/, establishing clear separation between core app logic and presentation layer.📊 Impact Metrics
packages/app-store🚚 Complete File Migration Details
18 Apps Migrated to
apps/web/components/apps/:Payment Integration Apps (4 apps):
Calendar Integration Apps (6 apps):
Automation & Integration Apps (3 apps):
Routing Forms Complete Migration (1 app, 6 components):
Utility Apps (1 app):
🏗️ Infrastructure Changes
New Files Created:
apps/web/components/apps/AppSetupPage.tsx- Centralized setup page routingFiles Removed:
packages/app-store/_pages/setup/index.tsx- Old setup handlerpackages/app-store/routing-forms/types/shared.ts- Migrated shared typespackages/app-store/wipemycalother/components/index.ts- Component exportsImport Path Updates:
50+ files updated across the codebase including:
🎯 Architecture After Migration
packages/app-store/now contains only:apps/web/components/apps/now contains: