Skip to content

Conversation

@keithwillcode
Copy link
Contributor

@keithwillcode keithwillcode commented Dec 22, 2025

What does this PR do?

Converts CRM, Calendar, Payment, and Analytics services from exporting classes to exporting factory functions that return interface types. This prevents SDK types (HubSpot, Stripe, jsforce, etc.) from leaking into TypeScript's emitted .d.ts files.

Additionally, this PR sets up TypeScript project references so that @calcom/trpc consumes prebuilt .d.ts files from @calcom/app-store instead of typechecking source files. This reduces the tRPC build file count from 7,733 to 5,618 files (27% reduction).

Metric Set 1 (Old) Set 2 (New) Difference % Change
Files 7,734 5,658 -2,076 -26.84%
Lines of Library 53,140 53,140 +0 +0.00%
Lines of Definitions 808,346 631,844 -176,502 -21.83%
Lines of TypeScript 439,248 413,690 -25,558 -5.82%
Lines of JSON 29,447 27,185 -2,262 -7.68%
Identifiers 1,529,985 1,333,377 -196,608 -12.85%
Symbols 1,955,227 1,708,634 -246,593 -12.61%
Types 671,842 619,774 -52,068 -7.75%
Instantiations 2,745,603 2,580,111 -165,492 -6.03%
Memory used 2,108,356K 2,170,655K +62,299K +2.95%
Assignability cache 276,753 259,464 -17,289 -6.25%
Identity cache size 13,089 12,454 -635 -4.85%
Subtype cache size 5,892 4,759 -1,133 -19.23%
Strict subtype cache 8,122 6,967 -1,155 -14.22%
I/O Read time 0.18s 0.25s +0.07s +38.89%
Parse time 1.43s 1.21s -0.22s -15.38%
ResolveModule time 0.62s 0.30s -0.32s -51.61%
Program time 2.55s 1.98s -0.57s -22.35%
Bind time 0.77s 0.64s -0.13s -16.88%
Check time 8.14s 7.13s -1.01s -12.41%
transformTime 3.31s 2.56s -0.75s -22.66%
printTime 3.76s 2.94s -0.82s -21.81%
Total time 15.22s 12.68s -2.54s -16.69%

Background: When TypeScript emits .d.ts files for exported classes, it includes private fields. If a class has private hubspotClient: hubspot.Client, TypeScript must resolve the full HubSpot SDK type graph (1,822 .d.ts files). By exporting factory functions typed as returning interfaces (e.g., CRM, Calendar), the emitted declarations only reference the interface types, not SDK internals.

Services modified:

  • CRM: hubspot, salesforce, closecom, pipedrive-crm, zoho-bigin, zohocrm (6)
  • Calendar: all 13 calendar services
  • Payment: stripe, paypal, alby, btcpayserver, hitpay, mock-payment-app (6)
  • Analytics: dub (1)

Video adapters were audited and already use factory pattern - no changes needed.

Updates since last revision

Latest - Merged main to resolve conflicts:

  • Merged latest main branch into PR branch
  • Resolved conflict in packages/app-store/_utils/getCalendar.ts - kept main's refactored structure while using factory function pattern (createCalendarService instead of new CalendarService)
  • Resolved conflict in packages/app-store/googlecalendar/lib/__tests__/CalendarService.test.ts - accepted main's version which removed the "Delegation Credential Batching" tests (these tests were moved/refactored in main)

Previous - Code cleanup:

  • Removed explanatory comments about factory functions from payment handlers (deletePayment.ts, handleNoShowFee.ts, handlePaymentRefund.ts, handlePayment.ts) and test file (getCalendarsEvents.test.ts)
  • Fixed indentation in payment files
  • Updated .gitignore to use *.tsbuildinfo pattern to catch all TypeScript build info files (not just tsconfig.tsbuildinfo)

Previous - Renamed factory functions to Build* naming convention:

  • Renamed all factory functions to use Build* prefix to make it clear they are factory functions, not classes:
    • Calendar: create*CalendarServiceBuildCalendarService
    • CRM: create*CrmServiceBuildCrmService
    • Payment: PaymentServiceBuildPaymentService
    • Analytics: createDubAnalyticsServiceBuildAnalyticsService
  • Updated all index.ts re-exports to use new names
  • Updated all consumer files (getConnectedApps.ts, handlePayment.ts, deletePayment.ts, handleNoShowFee.ts, handlePaymentRefund.ts)
  • Updated test mocks in handleNoShowFee.test.ts to use BuildPaymentService

Previous - Fixed E2E API v2 test for ICS calendar service:

  • Updated calendars.controller.e2e-spec.ts to mock the factory function instead of the class prototype

Previous - Renamed dist-types to types for consistency:

  • Renamed the prebuilt TypeScript declarations folder from dist-types to types to match the convention used by @calcom/trpc and other packages in the monorepo

Previous - Fixed circular build dependency:

  • Removed the turbo dependency @calcom/trpc#build@calcom/app-store#build:types
  • The typesVersions fallback pattern ["./types/*", "./*"] handles this: uses prebuilt declarations when they exist, falls back to source files otherwise

Previous - TypeScript project references setup:

  • Added packages/app-store/tsconfig.build.json with composite settings for declaration emit to types/
  • Added types and typesVersions to packages/app-store/package.json to redirect type resolution
  • Added build:types script to app-store for generating declarations

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.

How should this be tested?

  1. Run yarn type-check:ci --force to verify no type errors
  2. Run cd packages/app-store && yarn build:types to generate declarations (should complete without errors)
  3. Run yarn build on the tRPC package to verify the build still works
  4. Run TZ=UTC yarn test packages/features/bookings/lib/payment/handleNoShowFee.test.ts to verify payment test mocks work
  5. Run TZ=UTC yarn test packages/features/calendars/lib/getCalendarsEvents.test.ts to verify calendar test mocks work

Human Review Checklist

  • Merge conflict resolution: Verify packages/app-store/_utils/getCalendar.ts correctly uses createCalendarService factory function (lines 64 and 76)
  • Factory function naming: Verify all factory functions use Build* prefix consistently (e.g., BuildPaymentService, BuildCalendarService, BuildCrmService, BuildAnalyticsService)
  • Indentation in payment files: Verify indentation is correct in deletePayment.ts, handleNoShowFee.ts, handlePaymentRefund.ts after comment removal
  • getConnectedApps.ts indentation: Check the indentation around lines 186-188 - the diff shows unusual spacing that may need cleanup
  • Search for remaining old names: Grep for \.PaymentService, \.CalendarService, \.CrmService to ensure all call sites were updated to use Build* names
  • Test mocking pattern: Tests now mock factory functions using jest.spyOn(module, "functionName").mockImplementation() instead of jest.spyOn(Class.prototype, "method"). Verify this pattern is correctly applied.
  • Runtime behavior: Verify no code relies on instanceof checks against these service classes (would break with factory pattern)
  • Pre-existing Prisma type errors: Note that running build:types may surface pre-existing Prisma type mismatches - these are NOT caused by this PR.

Checklist

  • I have read the contributing guide
  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings (pre-existing lint warnings in modified files)

Link to Devin run: https://app.devin.ai/sessions/5508be898fa641a99c0a30b83c8d3162
Requested by: keith@cal.com (@keithwillcode)

…type exports

This change converts CRM, Calendar, Payment, and Analytics services from
exporting classes to exporting factory functions that return interface types.
This prevents SDK types (HubSpot, Stripe, etc.) from leaking into the type
system when TypeScript emits .d.ts files.

Services modified:
- CRM: hubspot, salesforce, closecom, pipedrive-crm, zoho-bigin, zohocrm
- Calendar: all 13 calendar services
- Payment: stripe, paypal, alby, btcpayserver, hitpay, mock-payment-app
- Analytics: dub

Video adapters were audited and already use factory pattern.

WIP: Salesforce CRM service has a type error that needs fixing.
Co-Authored-By: keith@cal.com <keithwillcode@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' or '@devin'.
  • 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

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
@vercel
Copy link

vercel bot commented Dec 22, 2025

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

3 Skipped Deployments
Project Deployment Review Updated (UTC)
cal Ignored Ignored Dec 31, 2025 7:03pm
cal-companion Ignored Ignored Preview Dec 31, 2025 7:03pm
cal-eu Ignored Ignored Dec 31, 2025 7:03pm

- getAnalytics.ts: call factory function instead of new
- getConnectedApps.ts: call factory function instead of new
- salesforce/CrmService.ts: fix type assertion with default value
- salesforce/routingForm/incompleteBookingAction.ts: use factory function
- salesforce/routingFormBookingFormHandler.ts: use factory function

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
…methods

- Create SalesforceCRM interface extending CRM with findUserEmailFromLookupField and incompleteBookingWriteToRecord methods
- Add createSalesforceCrmServiceWithSalesforceType factory function for internal Salesforce modules
- Update routing form files to use the new factory function with proper typing

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
The findUserEmailFromLookupField method returns { email: string; recordType: RoutingReasons } | undefined,
not string | undefined. Updated the interface to match the actual implementation.

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
- Update calendar API add files to use factory functions (7 files)
- Update Google Calendar test files to use factory functions (3 files)
- Update Salesforce test files to use SalesforceCRM interface
- Add testMode parameter to createSalesforceCrmServiceWithSalesforceType
- Remove unused @ts-expect-error directive in bookingScenario.ts

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
devin-ai-integration bot and others added 2 commits December 22, 2025 04:13
…rvice-specific methods

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
… function

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
devin-ai-integration bot and others added 2 commits December 22, 2025 04:42
… function

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
… type error

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
…nd payment services

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
… new

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
devin-ai-integration bot and others added 2 commits December 22, 2025 15:20
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
…vice in e2e test

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
@keithwillcode keithwillcode marked this pull request as ready for review December 22, 2025 16:02
@keithwillcode keithwillcode requested review from a team as code owners December 22, 2025 16:02
@graphite-app graphite-app bot added core area: core, team members only foundation labels Dec 22, 2025
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 93 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.

volnei
volnei previously approved these changes Dec 22, 2025
Copy link
Contributor

@volnei volnei left a comment

Choose a reason for hiding this comment

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

Beyond the review, I ran it locally and see no issues. Looks good 🚀

devin-ai-integration bot and others added 2 commits December 29, 2025 02:46
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 93 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.

@keithwillcode keithwillcode changed the title perf(app-store): convert services to factory functions and add TypeScript project references perf: convert services to factory functions and add TypeScript project references Dec 29, 2025
@keithwillcode keithwillcode enabled auto-merge (squash) December 31, 2025 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants