Skip to content

Comments

refactor: replace @prisma/client/runtime imports with public API#23087

Merged
emrysal merged 3 commits intomainfrom
devin/1755168007-replace-prisma-runtime-imports
Aug 29, 2025
Merged

refactor: replace @prisma/client/runtime imports with public API#23087
emrysal merged 3 commits intomainfrom
devin/1755168007-replace-prisma-runtime-imports

Conversation

@hbjORbj
Copy link
Contributor

@hbjORbj hbjORbj commented Aug 14, 2025

Summary

This PR eliminates all imports from @prisma/client/runtime and its subpaths, replacing them with the corresponding public API exports from the Prisma namespace. This change removes brittle dependencies on internal Prisma runtime modules and ensures compatibility with future Prisma versions.

Key changes:

  • Error classes: Replaced PrismaClientKnownRequestError, PrismaClientValidationError, etc. with Prisma.PrismaClientKnownRequestError, Prisma.PrismaClientValidationError
  • Prisma extensions: Removed internal DefaultArgs and InternalArgs type imports, simplified function signatures to use base Prisma types
  • Import structure: Fixed type vs value imports in NextAuth adapter to resolve TypeScript compilation error

Files modified:

  • apps/api/v2/src/filters/prisma-exception.filter.ts - API exception filter
  • packages/app-store/stripepayment/lib/team-billing.ts - Stripe payment error handling
  • packages/features/auth/lib/next-auth-custom-adapter.ts - NextAuth adapter
  • packages/trpc/server/routers/viewer/eventTypes/create.handler.ts - tRPC event type creation
  • packages/prisma/extensions/exclude-locked-users.ts - Prisma extension
  • packages/prisma/extensions/exclude-pending-payment-teams.ts - Prisma extension

- Replace PrismaClientKnownRequestError and other error classes with Prisma namespace equivalents
- Remove internal DefaultArgs and InternalArgs type imports from Prisma extensions
- Ensure all error handling uses stable public API exports
- Maintain compatibility with future Prisma versions by avoiding runtime dependencies

Co-Authored-By: benny@cal.com <sldisek783@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 Aug 14, 2025

Walkthrough

This PR refactors Prisma imports and type references across multiple modules to use the Prisma namespace (import { Prisma } from @prisma/client). It updates instanceof checks to Prisma.PrismaClientKnownRequestError and related types in API filters, TRPC handlers, Stripe billing, and auth adapter. In Prisma extensions, it removes runtime-library generics (InternalArgs, DefaultArgs) and switches to non-generic Prisma arg types (e.g., Prisma.UserFindUniqueArgs, Prisma.TeamFindFirstArgs). No runtime logic or control flow changes were made, and no exported/public signatures changed.

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ 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/1755168007-replace-prisma-runtime-imports

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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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 foundation labels Aug 14, 2025
@hbjORbj hbjORbj marked this pull request as ready for review August 23, 2025 13:24
@hbjORbj hbjORbj requested review from a team August 23, 2025 13:24
@hbjORbj hbjORbj requested a review from a team as a code owner August 23, 2025 13:24
@graphite-app graphite-app bot requested a review from a team August 23, 2025 13:24
@vercel
Copy link

vercel bot commented Aug 23, 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 Aug 29, 2025 0:47am
cal-eu Ignored Ignored Aug 29, 2025 0:47am

@graphite-app
Copy link

graphite-app bot commented Aug 23, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (08/23/25)

1 reviewer was added to this PR based on Keith Williams's automation.

@hbjORbj hbjORbj enabled auto-merge (squash) August 23, 2025 13:25
@dosubot dosubot bot added api area: API, enterprise API, access token, OAuth authentication area: authentication, auth, google sign in, password, SAML, password reset, can't log in 💻 refactor labels Aug 23, 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 (3)
packages/features/auth/lib/next-auth-custom-adapter.ts (1)

69-71: updateUser accepts CreateInput; should use UpdateInput to match prisma.user.update.

Using Prisma.UserUncheckedCreateInput (or CreateInput) for an update method is incorrect and can hide invalid fields at compile-time. Switch to UpdateInput (or UncheckedUpdateInput) to align with prisma.user.update’s expected XOR<UserUpdateInput, UserUncheckedUpdateInput>.

Apply this diff:

-    updateUser: ({ id, ...data }: Prisma.UserUncheckedCreateInput) =>
+    updateUser: ({ id, ...data }: Prisma.UserUncheckedUpdateInput) =>
       prismaClient.user.update({ where: { id }, data }),

If you prefer the checked path:

-    updateUser: ({ id, ...data }: Prisma.UserUncheckedCreateInput) =>
+    updateUser: ({ id, ...data }: Prisma.UserUpdateInput) =>
       prismaClient.user.update({ where: { id }, data }),
apps/api/v2/src/filters/prisma-exception.filter.ts (1)

1-85: Address Prisma runtime import and direct error usage in tests

We ran the requested repo-wide scans and found the following critical issues that must be fixed before merging:

• In packages/trpc/server/routers/viewer/eventTypes/duplicate.handler.test.ts (line 3):
– The test is importing directly from @prisma/client/runtime/library.
– It also instantiates new PrismaClientKnownRequestError(…) without the Prisma. namespace.
Fix:
```diff
- import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
+ import { Prisma } from "@prisma/client";

- new PrismaClientKnownRequestError("Unique constraint failed", { ... });
+ new Prisma.PrismaClientKnownRequestError("Unique constraint failed", { ... });
```

• Please search for any other direct imports from @prisma/client/runtime or un-namespaced PrismaClient*Error classes in tests or source files and update them to use the Prisma namespace.


Additional guardrails (for awareness / future refactors):

Prisma include usage:
Our scan flagged extensive use of include: { … } across the codebase. We prefer select to avoid over-fetching — consider scheduling a gradual refactor to replace high-risk include calls with explicit select clauses.

credential.key exposures:
Dozens of API and tRPC handlers reference or parse credential.key. Audit these to ensure no sensitive keys are accidentally sent to clients or logged in plaintext.

packages/trpc/server/routers/viewer/eventTypes/create.handler.ts (1)

62-64: Bug: users connect is gated by schedulingType instead of teamId.

Comment says "non-managed event types and non team event types" but the condition disables users whenever schedulingType is truthy (i.e., always), so the current user is never connected. Gate by teamId instead.

Apply:

-    // Only connecting the current user for non-managed event types and non team event types
-    users: isManagedEventType || schedulingType ? undefined : { connect: { id: userId } },
+    // Only connect the current user for non-managed, non-team event types
+    users: isManagedEventType || !!teamId ? undefined : { connect: { id: userId } },
🧹 Nitpick comments (9)
packages/features/auth/lib/next-auth-custom-adapter.ts (3)

80-93: Tighten P2025 handling and simplify the catch branch.

Minor cleanup: collapse the nested if and explicitly ignore only P2025; rethrow everything else.

-      } catch (error) {
-        // If token already used/deleted, just return null
-        // https://www.prisma.io/docs/reference/api-reference/error-reference#p2025
-        if (error instanceof Prisma.PrismaClientKnownRequestError) {
-          if (error.code === "P2025") return null;
-        }
-        throw error;
-      }
+      } catch (error) {
+        // If token already used/deleted, just return null (P2025)
+        if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2025") {
+          return null;
+        }
+        throw error;
+      }

33-35: Specify radix in parseInt for id normalization.

Guard against environment-dependent parsing by providing base 10.

-      prismaClient.user.findUnique({ where: { id: typeof id === "string" ? parseInt(id) : id } }),
+      prismaClient.user.findUnique({ where: { id: typeof id === "string" ? parseInt(id, 10) : id } }),

41-47: Consider narrowing selected user fields in getUserByAccount.

You already use select, which is good. If the caller doesn’t need the entire User, prefer an explicit subset (e.g., id, email, name) to reduce payload and risk of accidental leakage. Only do this if the adapter’s return type can be relaxed accordingly.

-      const account = await prismaClient.account.findUnique({
+      const account = await prismaClient.account.findUnique({
         where: {
           provider_providerAccountId,
         },
-        select: { user: true },
+        select: { user: { select: { id: true, email: true, name: true, image: true, identityProvider: true } } },
       });
packages/prisma/extensions/exclude-pending-payment-teams.ts (1)

27-35: Simplify the union with a structural generic to improve type safety.

A structural constraint avoids repeating all Team*Args unions while keeping intellisense for where. Optional—current code is fine.

-async function excludePendingPayments(
-  args:
-    | Prisma.TeamFindUniqueArgs
-    | Prisma.TeamFindFirstArgs
-    | Prisma.TeamFindManyArgs
-    | Prisma.TeamFindUniqueOrThrowArgs
-    | Prisma.TeamFindFirstOrThrowArgs,
-  query: <T>(args: T) => Promise<unknown>
-) {
+type WithTeamWhere<T extends { where?: Prisma.TeamWhereInput }> = T;
+async function excludePendingPayments<T extends { where?: Prisma.TeamWhereInput }>(
+  args: WithTeamWhere<T>,
+  query: (args: WithTeamWhere<T>) => Promise<unknown>
+) {
apps/api/v2/src/filters/prisma-exception.filter.ts (1)

38-39: Header lookup should be case-insensitive.

Express lower-cases header names. Consider checking the lowercase form first to avoid missing a provided X-Request-Id.

-    const requestId = request.headers["X-Request-Id"] ?? "unknown-request-id";
+    const requestId = (request.headers["x-request-id"] ?? request.headers["X-Request-Id"] ?? "unknown-request-id").toString();
-    response.setHeader("X-Request-Id", requestId.toString());
+    response.setHeader("X-Request-Id", requestId);
packages/prisma/extensions/exclude-locked-users.ts (1)

45-50: Avoid stringify-based detection; use a recursive key check for accuracy.

String matching can false-positive on values or nested strings. A small recursive helper is clearer and safer. Optional improvement.

-  const whereString = safeJSONStringify(args.where);
-  const shouldIncludeLocked = whereString.includes('"locked":');
+  const shouldIncludeLocked = hasKey(args.where, "locked");
   // Unless explicitly specified, we exclude locked users
   if (!shouldIncludeLocked) {
     args.where.locked = false;
   }

Add this helper near the top of the file:

function hasKey(obj: unknown, key: string): boolean {
  if (!obj || typeof obj !== "object") return false;
  if (Object.prototype.hasOwnProperty.call(obj as Record<string, unknown>, key)) return true;
  for (const v of Object.values(obj as Record<string, unknown>)) {
    if (hasKey(v, key)) return true;
  }
  return false;
}
packages/trpc/server/routers/viewer/eventTypes/create.handler.ts (3)

83-89: Prisma query should select only required fields.

We only use role from membership. Per guidelines, prefer select for minimal data.

     const hasMembership = await ctx.prisma.membership.findFirst({
       where: {
         userId,
         teamId: teamId,
         accepted: true,
-      },
-    });
+      },
+      select: { role: true },
+    });

141-146: LGTM on switching to Prisma.PrismaClientKnownRequestError; broaden target check.

In some Prisma versions e.meta.target can be a string or an array. Slightly harden the guard.

-    if (e instanceof Prisma.PrismaClientKnownRequestError) {
-      if (e.code === "P2002" && Array.isArray(e.meta?.target) && e.meta?.target.includes("slug")) {
-        throw new TRPCError({ code: "BAD_REQUEST", message: "URL Slug already exists for given user." });
-      }
-    }
+    if (e instanceof Prisma.PrismaClientKnownRequestError) {
+      const target = e.meta?.target as unknown;
+      const isSlugUniqueViolation =
+        e.code === "P2002" &&
+        ((Array.isArray(target) && target.includes("slug")) ||
+          (typeof target === "string" && target.includes("slug")));
+      if (isSlugUniqueViolation) {
+        throw new TRPCError({ code: "BAD_REQUEST", message: "URL Slug already exists for given user." });
+      }
+    }

146-147: Consider returning 500 for unknown errors instead of 400.

Unknown failures are more accurately mapped to INTERNAL_SERVER_ERROR; 400 implies client fault.

-    throw new TRPCError({ code: "BAD_REQUEST" });
+    throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
📜 Review details

Configuration used: CodeRabbit UI

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 d2f8076 and 0d99824.

📒 Files selected for processing (6)
  • apps/api/v2/src/filters/prisma-exception.filter.ts (3 hunks)
  • packages/app-store/stripepayment/lib/team-billing.ts (1 hunks)
  • packages/features/auth/lib/next-auth-custom-adapter.ts (2 hunks)
  • packages/prisma/extensions/exclude-locked-users.ts (1 hunks)
  • packages/prisma/extensions/exclude-pending-payment-teams.ts (1 hunks)
  • packages/trpc/server/routers/viewer/eventTypes/create.handler.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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/features/auth/lib/next-auth-custom-adapter.ts
  • packages/trpc/server/routers/viewer/eventTypes/create.handler.ts
  • packages/prisma/extensions/exclude-pending-payment-teams.ts
  • packages/prisma/extensions/exclude-locked-users.ts
  • packages/app-store/stripepayment/lib/team-billing.ts
  • apps/api/v2/src/filters/prisma-exception.filter.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/features/auth/lib/next-auth-custom-adapter.ts
  • packages/trpc/server/routers/viewer/eventTypes/create.handler.ts
  • packages/prisma/extensions/exclude-pending-payment-teams.ts
  • packages/prisma/extensions/exclude-locked-users.ts
  • packages/app-store/stripepayment/lib/team-billing.ts
  • apps/api/v2/src/filters/prisma-exception.filter.ts
🧬 Code graph analysis (1)
apps/api/v2/src/filters/prisma-exception.filter.ts (4)
apps/api/v2/src/filters/calendar-service-exception.filter.ts (1)
  • Catch (24-61)
apps/api/v2/src/filters/http-exception.filter.ts (1)
  • Catch (9-38)
apps/api/v2/src/filters/zod-exception.filter.ts (1)
  • Catch (11-46)
apps/api/v2/src/filters/trpc-exception.filter.ts (1)
  • Catch (104-142)
🔇 Additional comments (7)
packages/app-store/stripepayment/lib/team-billing.ts (1)

1-1: Refactor to Prisma namespace looks correct and keeps runtime behavior unchanged.

The instanceof check against Prisma.PrismaClientKnownRequestError for P2002 is the right public API and aligns with the PR goal. No functional changes introduced here.

Also applies to: 9-12

packages/features/auth/lib/next-auth-custom-adapter.ts (1)

1-2: Correct switch to Prisma namespace for error types.

Importing the Prisma namespace and using Prisma.PrismaClientKnownRequestError resolves the type/value import issue cleanly.

packages/prisma/extensions/exclude-pending-payment-teams.ts (1)

29-33: Good move to public Prisma arg types (no generics from runtime).

Dropping InternalArgs/DefaultArgs removes a dependency on private runtime types and matches the public API. Behavior is preserved.

apps/api/v2/src/filters/prisma-exception.filter.ts (1)

5-5: Namespace refactor is consistent and correct.

Switching to Prisma.PrismaClient*Error everywhere (type alias, @catch, and instanceof) uses the public API and avoids any runtime subpath imports. Control flow unchanged.

Also applies to: 17-22, 25-30, 55-75

packages/prisma/extensions/exclude-locked-users.ts (1)

37-41: Public Prisma arg types only—looks good.

Removing DefaultArgs/InternalArgs keeps this extension on public, stable types without impacting runtime behavior.

packages/trpc/server/routers/viewer/eventTypes/create.handler.ts (2)

1-1: Fix lingering @prisma/client/runtime import in duplicate.handler.test.ts

A quick sweep uncovered a direct import from @prisma/client/runtime/library in your test, which should be replaced with the Prisma namespace import to keep runtime checks working correctly.

• File: packages/trpc/server/routers/viewer/eventTypes/duplicate.handler.test.ts
○ Line 3: import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";

Suggested replacement:

-import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
+import { Prisma } from "@prisma/client";

 // …

- new PrismaClientKnownRequestError(/* … */)
+ new Prisma.PrismaClientKnownRequestError(/* … */)

After this change, there should be no remaining imports from @prisma/client/runtime outside of your bundler configs.

Likely an incorrect or invalid review comment.


138-139: ✅ No credential.key is returned by EventTypeRepository#create

I’ve verified that EventTypeRepository#create calls:

return this.prismaClient.eventType.create({
  data: ,
  include: { calVideoSettings: true },
});

– The EventType model in schema.prisma does not have any credentialId or key fields, and
– The only included relation is calVideoSettings, which likewise contains only its own boolean flags and timestamps (no credentials).

Therefore, returning { eventType } cannot leak any credential.key.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 29, 2025

E2E results are ready!

Copy link
Contributor

@emrysal emrysal left a comment

Choose a reason for hiding this comment

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

LGTM, very safe change (keeping it the way it is is actually more dangerous)

@emrysal emrysal merged commit 6defa1c into main Aug 29, 2025
65 of 68 checks passed
@emrysal emrysal deleted the devin/1755168007-replace-prisma-runtime-imports branch August 29, 2025 02:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api area: API, enterprise API, access token, OAuth authentication area: authentication, auth, google sign in, password, SAML, password reset, can't log in core area: core, team members only foundation ready-for-e2e 💻 refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants