-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: add GQloom example: GraphQL + Zod + Prisma #8331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: latest
Are you sure you want to change the base?
Conversation
…pabilities with new filters and enums
…ith related metadata and type definitions
… files, and generated source code
…pproach and TypeScript integration
…cted fields for Post and User models
|
Warning Rate limit exceeded@xcfox has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 9 minutes and 42 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
WalkthroughAdds a new GraphQL example at Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server as GraphQL Server
participant Resolver as GQloom Resolver
participant Prisma as Prisma Client
participant DB as PostgreSQL
Client->>Server: GraphQL Query/Mutation
activate Server
Server->>Resolver: Route to resolver
activate Resolver
Resolver->>Resolver: Validate input (Zod)
Resolver->>Prisma: Execute DB operation
activate Prisma
Prisma->>DB: SQL (via PrismaPg + Accelerate)
activate DB
DB-->>Prisma: Result
deactivate DB
Prisma-->>Resolver: Data
deactivate Prisma
Resolver->>Resolver: Project selected fields
Resolver-->>Server: GraphQL response
deactivate Resolver
Server-->>Client: JSON response
deactivate Server
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Pre-merge checks✅ Passed checks (3 passed)
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (6)
orm/graphql-gqloom/package.json (1)
16-27: Consider adding validation and test scripts.The package.json includes dev, start, and generate scripts but lacks validation or test scripts. For an example project, it would be beneficial to include:
- A script to validate the GraphQL schema
- A script to run type checking
- A script to lint the code (if applicable)
Consider adding these scripts:
"scripts": { "dev": "tsx watch --env-file=.env src/server.ts", "start": "tsx --env-file=.env src/server.ts", - "generate": "prisma generate" + "generate": "prisma generate", + "validate": "prisma validate && tsc --noEmit", + "test": "echo \"Add tests here\" && exit 0" },orm/graphql-gqloom/src/server.ts (1)
33-40: Consider making the port configurable.The server port is hard-coded to 4000. For better flexibility in different environments (development, testing, production), consider making it configurable via an environment variable.
Apply this diff to make the port configurable:
+const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 4000 + const yoga = createYoga({ graphqlEndpoint: '/', schema, }) const server = createServer(yoga) -server.listen(4000, () => { - console.info('Server is running on http://localhost:4000') +server.listen(PORT, () => { + console.info(`Server is running on http://localhost:${PORT}`) })orm/graphql-gqloom/prisma/seed.ts (1)
58-67: Consider parallelizing user creation.The current implementation creates users sequentially in a for-loop. For better performance, especially with larger datasets, consider using
Promise.all()to create users in parallel.Apply this diff to parallelize user creation:
async function main() { console.log(`Start seeding ...`) - for (const u of userData) { - const user = await prisma.user.create({ + const users = await Promise.all( + userData.map((u) => + prisma.user.create({ + data: u, + }) + ) + ) + + for (const user of users) { - data: u, - }) console.log(`Created user with id: ${user.id}`) } console.log(`Seeding finished.`) }Note: Only apply this if you don't need sequential IDs or have no ordering dependencies.
.github/tests/orm/graphql-gqloom/run.sh (1)
70-74: Add safeguards to kill commands.The kill commands could fail if the processes have already exited or if the PIDs are invalid, causing the script to fail despite successful test execution.
Apply this diff to make cleanup more robust:
# Cleanup echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..." -kill "$pid" -kill "$NODE_PID" +kill "$pid" 2>/dev/null || true +kill "$NODE_PID" 2>/dev/null || true +wait "$pid" || true wait "$NODE_PID" || trueorm/graphql-gqloom/README.md (1)
18-21: Add code-fence languages and tighten copy.
- Specify languages for fenced blocks (bash, terminal → bash, graphql, diff, prisma, ts) to satisfy MD040 and improve readability.
- Prefer “afterward” (US English).
- Vary “Note that you need to replace …” phrasing to avoid repetition.
Example fixes:
-``` +```bash npx try-prisma@latest --template orm/graphql-gqloom --install npm --name graphql-gqloom-
+bash
cd graphql-gqloom-``` +```bash npm run dev-
+diff
// ./prisma/schema.prisma…and similarly tag GraphQL blocks as `graphql`, Prisma blocks as `prisma`, TypeScript as `ts`. Also applies to: 24-27, 141-144, 398-401 </blockquote></details> <details> <summary>orm/graphql-gqloom/src/resolvers/post.ts (1)</summary><blockquote> `8-15`: **Optionally sanitize input to drop helper keys.** To guard all call sites, consider transforming `PostCreateInput` to strip `__typename` so downstream Prisma calls can safely spread inputs. ```diff export const PostCreateInput = z.object({ - __typename: z.literal('PostCreateInput').nullish(), - title: z.string(), - content: z + __typename: z.literal('PostCreateInput').nullish(), + title: z.string(), + content: z .string() .nullish() - .transform((x) => x ?? undefined), -}) + .transform((x) => x ?? undefined), +}).transform(({ __typename, ...rest }) => rest)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
.github/tests/orm/graphql-gqloom/run.sh(1 hunks)orm/graphql-gqloom/.gitignore(1 hunks)orm/graphql-gqloom/.nvmrc(1 hunks)orm/graphql-gqloom/README.md(1 hunks)orm/graphql-gqloom/package.json(1 hunks)orm/graphql-gqloom/prisma/schema.prisma(1 hunks)orm/graphql-gqloom/prisma/seed.ts(1 hunks)orm/graphql-gqloom/schema.graphql(1 hunks)orm/graphql-gqloom/src/db.ts(1 hunks)orm/graphql-gqloom/src/resolvers/post.ts(1 hunks)orm/graphql-gqloom/src/resolvers/user.ts(1 hunks)orm/graphql-gqloom/src/server.ts(1 hunks)orm/graphql-gqloom/tsconfig.json(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-22T12:12:24.602Z
Learnt from: FGoessler
PR: prisma/prisma-examples#8260
File: generator-prisma-client/nextjs-starter-webpack-turborepo/packages/database/package.json:13-13
Timestamp: 2025-08-22T12:12:24.602Z
Learning: When analyzing changes from package.json seed scripts to "prisma db seed", always verify the actual content of prisma.config.ts rather than relying solely on regex patterns, as the configuration may be properly defined but in a format that doesn't match overly restrictive search patterns.
Applied to files:
orm/graphql-gqloom/prisma/seed.ts
🧬 Code graph analysis (4)
orm/graphql-gqloom/src/resolvers/post.ts (1)
orm/graphql-gqloom/src/db.ts (1)
prisma(8-8)
orm/graphql-gqloom/src/server.ts (2)
orm/graphql-gqloom/src/resolvers/user.ts (1)
userResolver(11-36)orm/graphql-gqloom/src/resolvers/post.ts (1)
postResolver(19-163)
orm/graphql-gqloom/src/resolvers/user.ts (2)
orm/graphql-gqloom/src/db.ts (1)
prisma(8-8)orm/graphql-gqloom/src/resolvers/post.ts (1)
PostCreateInput(8-15)
orm/graphql-gqloom/prisma/seed.ts (1)
orm/graphql-gqloom/src/db.ts (1)
prisma(8-8)
🪛 LanguageTool
orm/graphql-gqloom/README.md
[style] ~151-~151: Consider using a less common alternative to make your writing sound more unique and professional.
Context: ... the API using the GraphQL Playground. Feel free to adjust any operation by adding or remov...
(FEEL_FREE_TO_STYLE_ME)
[style] ~316-~316: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ... published } } ``` Note that you need to replace the __POST_ID__ placeholder w...
(REP_NEED_TO_VB)
[style] ~339-~339: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ID__) { id } } ``` Note that you need to replace the __POST_ID__ placeholder w...
(REP_NEED_TO_VB)
[locale-violation] ~363-~363: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ...isma) file and then running a migration afterwards: ```diff // ./prisma/schema.prisma mo...
(AFTERWARDS_US)
🪛 markdownlint-cli2 (0.18.1)
orm/graphql-gqloom/README.md
18-18: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
24-24: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
141-141: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
398-398: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (12)
orm/graphql-gqloom/.gitignore (1)
1-4: LGTM!The ignore patterns appropriately cover dependencies, build artifacts, environment files, and generated sources.
orm/graphql-gqloom/src/server.ts (2)
1-12: LGTM!Imports are well-organized and include all necessary dependencies for setting up the GraphQL server with GQLoom, Prisma, and Zod integration.
14-27: Schema weaving looks correct.The schema composition with ZodWeaver, PrismaWeaver configuration, and asyncContextProvider is properly structured. The DateTime scalar mapping to GraphQLDateTime is a good practice.
orm/graphql-gqloom/prisma/seed.ts (2)
10-56: LGTM!The seed data is well-structured with realistic examples that demonstrate the User-Post relationship and various Post states (published/draft, with/without viewCount).
69-77: LGTM!The error handling and cleanup logic properly ensures Prisma disconnects in both success and error cases, preventing hanging connections.
.github/tests/orm/graphql-gqloom/run.sh (3)
1-19: LGTM!The initial setup with strict mode, logging, and dependency installation is well-structured and provides good visibility into the test execution.
20-52: Excellent Prisma Dev startup and wait logic.The implementation properly:
- Starts Prisma Dev in the background with logging
- Implements a timeout-based wait loop (60 seconds)
- Validates the DATABASE_URL format before proceeding
- Provides clear error messages and cleanup on failure
55-59: LGTM!The migration and seed workflow is correct: reset without seed, then dev migration with init, then explicit seed.
orm/graphql-gqloom/.nvmrc (1)
1-1: Invalid Node.js LTS codename."lts/jod" is not a valid Node.js LTS codename. Standard LTS codenames follow patterns like "lts/iron" (Node 20), "lts/hydrogen" (Node 18), or "lts/gallium" (Node 16).
Apply this diff to use a valid LTS version:
-lts/jod +lts/ironOr specify an explicit version if you need a specific Node release:
-lts/jod +20Likely an incorrect or invalid review comment.
orm/graphql-gqloom/tsconfig.json (1)
1-11: Configuration is compatible and correctly uses tsx for module transpilation.After verification, the module system "mismatch" identified in the review comment is not actually problematic. The codebase uses
tsxv4.20.6 explicitly in all execution paths (dev, start, and Prisma seed scripts), which transpiles TypeScript on-the-fly and handles module resolution regardless of thepackage.jsontype declaration. All source files use standard ESM imports, with no ESM-specific patterns (top-level await, dynamic imports) that would conflict with CommonJS semantics. The"module": "ESNext"in tsconfig.json paired with"type": "commonjs"is a deliberate and functional configuration when using tsx as the runtime executor.orm/graphql-gqloom/package.json (1)
6-7: No action required—the configuration is compatible.Verification confirms the setup is correct:
- tsx v4.20.6 supports the --env-file flag
- orm/graphql-gqloom/.nvmrc specifies
lts/jod(Node.js v22), which exceeds the 20.6+ requirementBoth the tsx version (
^4.20.6in package.json) and Node.js version support the--env-fileflag.orm/graphql-gqloom/prisma/schema.prisma (1)
6-10: Configuration is valid for Prisma 6.17.1.The project uses Prisma 6.17.1, which supports
engineType = "client"in conjunction with JavaScript driver adapters like@prisma/adapter-pg. The configuration is correct and intentional for edge/serverless deployments.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
orm/graphql-gqloom/src/resolvers/user.ts (1)
30-32: Good fix: strip GraphQL helper keys before nested create.Mapping
data.poststo remove__typenameprevents Prisma validation errors.
🧹 Nitpick comments (4)
.github/tests/orm/graphql-gqloom/run.sh (1)
1-88: Add trap to ensure cleanup runs on script exit.If the script errors before reaching the cleanup section (lines 85–88), background processes (
$pidand$NODE_PID) will remain running. Use a trap to guarantee cleanup.Add a cleanup function and trap near the top of the script:
#!/bin/bash set -eu + +cleanup() { + echo "🛑 Cleaning up..." + kill "$pid" 2>/dev/null || true + kill "$NODE_PID" 2>/dev/null || true + wait "$NODE_PID" 2>/dev/null || true + wait "$pid" 2>/dev/null || true +} +trap cleanup EXIT echo "🔍 Starting test setup for graphql-gqloom..."Then update the cleanup section at the end to remove the redundant kills:
-# Cleanup -echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..." -kill "$pid" 2>/dev/null || true -kill "$NODE_PID" -wait "$NODE_PID" 2>/dev/null || true -wait "$pid" 2>/dev/null || true +echo "✅ Tests completed successfully"orm/graphql-gqloom/src/server.ts (1)
43-46: Use PORT env and bind to 0.0.0.0 for deployability.Make the example runnable on platforms that inject PORT and expect 0.0.0.0 binding.
-const server = createServer(yoga) -server.listen(4000, () => { - console.info('Server is running on http://localhost:4000') -}) +const server = createServer(yoga) +const port = Number(process.env.PORT) || 4000 +const host = process.env.HOST || '0.0.0.0' +server.listen(port, host, () => { + const displayHost = host === '0.0.0.0' ? 'localhost' : host + console.info(`Server is running on http://${displayHost}:${port}`) +})orm/graphql-gqloom/src/resolvers/user.ts (1)
21-22: Default posts to an empty array.Signup shouldn’t require posts; default improves DX and avoids conditional mapping.
- posts: z.array(PostCreateInput), + posts: z.array(PostCreateInput).default([]),orm/graphql-gqloom/src/resolvers/post.ts (1)
58-66: Optional: make search case-insensitive.Improve UX by adding
mode: 'insensitive'to string filters.- OR: [ - { title: { contains: searchString } }, - { content: { contains: searchString } }, - ], + OR: [ + { title: { contains: searchString, mode: 'insensitive' } }, + { content: { contains: searchString, mode: 'insensitive' } }, + ],
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/tests/orm/graphql-gqloom/run.sh(1 hunks)orm/graphql-gqloom/src/resolvers/post.ts(1 hunks)orm/graphql-gqloom/src/resolvers/user.ts(1 hunks)orm/graphql-gqloom/src/server.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
orm/graphql-gqloom/src/server.ts (2)
orm/graphql-gqloom/src/resolvers/user.ts (1)
userResolver(11-36)orm/graphql-gqloom/src/resolvers/post.ts (1)
postResolver(19-164)
orm/graphql-gqloom/src/resolvers/post.ts (1)
orm/graphql-gqloom/src/db.ts (1)
prisma(8-8)
orm/graphql-gqloom/src/resolvers/user.ts (2)
orm/graphql-gqloom/src/db.ts (1)
prisma(8-8)orm/graphql-gqloom/src/resolvers/post.ts (1)
PostCreateInput(8-15)
🔇 Additional comments (6)
.github/tests/orm/graphql-gqloom/run.sh (4)
64-78: Health check implementation approved.The app readiness check correctly replaces the arbitrary sleep with a polling loop and timeout. This addresses the previous review feedback and is more reliable for CI environments.
38-47: Database URL wait loop is well-implemented.The Prisma Dev readiness check with timeout and logging is appropriate. The use of
grepfor theprisma+postgres://prefix provides a clear signal for readiness.
55-58: Verify Prisma seed script exists and is idempotent.The script runs
prisma migrate resetand thenprisma db seed. Confirm that the seed script (if present) is idempotent so it can run reliably on repeated test executions.
82-82: Verify Postman collection path is correct.The script references
$REPO_ROOT/.github/tests/postman_collections/graphql.json. Ensure this file exists and is checked into the repository, or the Newman step will fail silently or with an unclear error.orm/graphql-gqloom/src/resolvers/user.ts (1)
19-21: ****The review comment is based on outdated Zod API assumptions. In Zod 4+,
z.email()is the standard top-level API andz.string().email()is deprecated. The codebase is using the modern, correct form. No changes needed.Likely an incorrect or invalid review comment.
orm/graphql-gqloom/src/resolvers/post.ts (1)
23-27: ****The review comment recommends refactoring to
z.number().int()andz.string().email(), but the codebase uses Zod 4.1.12, where the current top-level APIs (z.int()andz.email()) are the preferred and modern forms. The suggested changes would replace correct patterns with deprecated alternatives.Likely an incorrect or invalid review comment.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This PR adds a GraphQL server example demonstrating a modern, type-safe stack with GQLoom, Prisma, GraphQL Yoga, and Zod.
The highlight of this example is GQLoom, a Code-First GraphQL schema library designed to enhance developer experience and productivity.
Key GQLoom Advantages Showcased:
Ergonomic API Design: GQLoom offers a semantic, code-first API that minimizes boilerplate and makes schema definition intuitive and enjoyable.
Single Source of Truth: It leverages runtime validation libraries like Zod as the single source of truth. Define your validation schema once, and GQLoom automatically derives both TypeScript types and the GraphQL schema, ensuring they are always in sync.
Automatic CRUD with ResolverFactory: This example heavily utilizes GQLoom's killer feature: the
PrismaResolverFactory. It automatically generates common queries (findUnique,findMany) and mutations (create,update,delete) directly from Prisma models, eliminating the need to write repetitive CRUD logic manually.End-to-End Type Safety: By integrating seamlessly with Prisma and Zod, GQLoom provides full type safety from the database to the API layer, catching errors at compile time.
Summary by CodeRabbit
New Features
Documentation
Tests
Chores