nitro-graphql 2.0.0-beta.2 → 2.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +855 -5
  2. package/dist/ecosystem/nuxt.mjs +109 -0
  3. package/dist/index.d.mts +43 -0
  4. package/dist/index.mjs +63 -0
  5. package/dist/rollup.d.mts +12 -0
  6. package/dist/rollup.mjs +282 -0
  7. package/dist/routes/apollo-server.d.mts +6 -0
  8. package/dist/routes/{apollo-server.js → apollo-server.mjs} +6 -6
  9. package/dist/routes/debug.d.mts +61 -0
  10. package/dist/routes/debug.mjs +445 -0
  11. package/dist/routes/graphql-yoga.d.mts +6 -0
  12. package/dist/routes/{graphql-yoga.js → graphql-yoga.mjs} +6 -6
  13. package/dist/routes/health.d.mts +10 -0
  14. package/dist/routes/{health.js → health.mjs} +2 -1
  15. package/dist/setup.d.mts +11 -0
  16. package/dist/setup.mjs +390 -0
  17. package/dist/types/index.d.mts +246 -0
  18. package/dist/utils/{apollo.js → apollo.mjs} +2 -2
  19. package/dist/utils/{client-codegen.d.ts → client-codegen.d.mts} +3 -3
  20. package/dist/utils/{client-codegen.js → client-codegen.mjs} +5 -5
  21. package/dist/utils/{define.d.ts → define.d.mts} +2 -1
  22. package/dist/utils/file-generator.d.mts +37 -0
  23. package/dist/utils/file-generator.mjs +72 -0
  24. package/dist/utils/{index.d.ts → index.d.mts} +2 -2
  25. package/dist/utils/{index.js → index.mjs} +64 -36
  26. package/dist/utils/path-resolver.d.mts +70 -0
  27. package/dist/utils/path-resolver.mjs +127 -0
  28. package/dist/utils/{server-codegen.d.ts → server-codegen.d.mts} +1 -1
  29. package/dist/utils/{server-codegen.js → server-codegen.mjs} +2 -2
  30. package/dist/utils/{type-generation.js → type-generation.mjs} +153 -42
  31. package/dist/virtual/debug-info.d.mts +9 -0
  32. package/dist/virtual/debug-info.mjs +26 -0
  33. package/dist/virtual/graphql-config.d.mts +9 -0
  34. package/dist/virtual/graphql-config.mjs +10 -0
  35. package/dist/virtual/module-config.d.mts +9 -0
  36. package/dist/virtual/module-config.mjs +10 -0
  37. package/dist/virtual/server-directives.d.mts +11 -0
  38. package/dist/virtual/server-directives.mjs +10 -0
  39. package/dist/virtual/server-resolvers.d.mts +11 -0
  40. package/dist/virtual/server-resolvers.mjs +10 -0
  41. package/dist/virtual/server-schemas.d.mts +11 -0
  42. package/dist/virtual/server-schemas.mjs +10 -0
  43. package/dist/vite.d.mts +30 -0
  44. package/dist/vite.mjs +49 -0
  45. package/package.json +73 -59
  46. package/dist/ecosystem/nuxt.js +0 -67
  47. package/dist/index.d.ts +0 -8
  48. package/dist/index.js +0 -264
  49. package/dist/rollup.js +0 -114
  50. package/dist/routes/apollo-server.d.ts +0 -6
  51. package/dist/routes/graphql-yoga.d.ts +0 -6
  52. package/dist/routes/health.d.ts +0 -6
  53. package/dist/types/index.d.ts +0 -128
  54. /package/dist/ecosystem/{nuxt.d.ts → nuxt.d.mts} +0 -0
  55. /package/dist/graphql/{index.d.ts → index.d.mts} +0 -0
  56. /package/dist/graphql/{index.js → index.mjs} +0 -0
  57. /package/dist/graphql/{server.d.ts → server.d.mts} +0 -0
  58. /package/dist/graphql/{server.js → server.mjs} +0 -0
  59. /package/dist/types/{standard-schema.d.ts → standard-schema.d.mts} +0 -0
  60. /package/dist/utils/{apollo.d.ts → apollo.d.mts} +0 -0
  61. /package/dist/utils/{define.js → define.mjs} +0 -0
  62. /package/dist/utils/{directive-parser.d.ts → directive-parser.d.mts} +0 -0
  63. /package/dist/utils/{directive-parser.js → directive-parser.mjs} +0 -0
  64. /package/dist/utils/{type-generation.d.ts → type-generation.d.mts} +0 -0
package/README.md CHANGED
@@ -1,20 +1,31 @@
1
- # Nitro GraphQL
2
-
3
1
  <div align="center">
4
2
 
3
+ <img src="./.docs/public/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
4
+
5
+ # Nitro GraphQL
6
+
5
7
  [![npm version][npm-version-src]][npm-version-href]
8
+ [![Beta Status][beta-src]][beta-href]
6
9
  [![npm downloads][npm-downloads-src]][npm-downloads-href]
7
10
  [![bundle][bundle-src]][bundle-href]
8
11
  [![License][license-src]][license-href]
12
+ [![Documentation][docs-src]][docs-href]
9
13
 
10
14
  **The easiest way to add GraphQL to any Nitro application**
11
15
 
12
16
  🚀 **Auto-discovery** • 📝 **Type Generation** • 🎮 **Apollo Sandbox** • 🔧 **Zero Config**
13
17
 
14
- [Quick Start](#-quick-start) • [Examples](#-examples) • [Documentation](#-documentation) • [Community](#-community)
18
+ [📚 Documentation](https://nitro-graphql.pages.dev) • [Quick Start](#-quick-start) • [Examples](#-examples) • [Community](#-community)
15
19
 
16
20
  </div>
17
21
 
22
+ > [!IMPORTANT]
23
+ > **v2.0 Beta (Current - Main Branch)**
24
+ > This is the **v2.0** beta branch with Nitro v3 and H3 v2 support. Includes Rolldown optimization, improved chunking, and enhanced Vite integration.
25
+ >
26
+ > **Looking for v1.x?**
27
+ > For the stable v1 version (Nitro v2), see the [`v1` branch](https://github.com/productdevbook/nitro-graphql/tree/v1).
28
+
18
29
  ---
19
30
 
20
31
  ## 🎥 Watch & Learn
@@ -31,6 +42,14 @@
31
42
  - 🎮 **Developer-friendly** - Built-in Apollo Sandbox for testing
32
43
  - 🔧 **Zero config** - Sensible defaults, customize when needed
33
44
 
45
+ ### 🆕 What's New in v2.0 Beta
46
+
47
+ - 🚀 **Nitro v3 & H3 v2** - Full compatibility with the latest Nitro and H3
48
+ - ⚙️ **Rolldown Support** - Optimized for both Rolldown (Vite 7+) and Rollup
49
+ - 📦 **Smart Chunking** - GraphQL code split into separate chunks (~98% size reduction)
50
+ - 🔍 **Debug Dashboard** - Built-in diagnostics at `/_nitro/graphql/debug` (dev only)
51
+ - 🎨 **Enhanced Vite Integration** - Better custom path support and virtual module resolution
52
+
34
53
  ## 🚀 Quick Start
35
54
 
36
55
  ### 1. Install
@@ -52,7 +71,7 @@ pnpm add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integration
52
71
 
53
72
  ```ts
54
73
  // nitro.config.ts
55
- import { defineNitroConfig } from 'nitropack/config'
74
+ import { defineNitroConfig } from 'nitro/config'
56
75
 
57
76
  export default defineNitroConfig({
58
77
  modules: ['nitro-graphql'],
@@ -64,6 +83,33 @@ export default defineNitroConfig({
64
83
 
65
84
  </details>
66
85
 
86
+ <details>
87
+ <summary>⚡ <strong>Vite + Nitro Project</strong></summary>
88
+
89
+ ```ts
90
+ // vite.config.ts
91
+ import { defineConfig } from 'vite'
92
+ import { nitro } from 'nitro/vite'
93
+ import { graphql } from 'nitro-graphql/vite'
94
+
95
+ export default defineConfig({
96
+ plugins: [
97
+ graphql(), // ⚠️ Must be before nitro()
98
+ nitro(),
99
+ ],
100
+ nitro: {
101
+ modules: ['nitro-graphql'],
102
+ graphql: {
103
+ framework: 'graphql-yoga',
104
+ },
105
+ },
106
+ })
107
+ ```
108
+
109
+ > **⚠️ Important**: The `graphql()` plugin must be placed **before** `nitro()` to prevent Vite from trying to parse GraphQL files as JavaScript.
110
+
111
+ </details>
112
+
67
113
  <details>
68
114
  <summary>🟢 <strong>Nuxt Project</strong></summary>
69
115
 
@@ -117,6 +163,7 @@ pnpm dev
117
163
  - **Endpoint**: `http://localhost:3000/api/graphql`
118
164
  - **Playground**: `http://localhost:3000/api/graphql` (browser)
119
165
  - **Health**: `http://localhost:3000/api/graphql/health`
166
+ - **Debug Dashboard**: `http://localhost:3000/_nitro/graphql/debug` (dev mode only)
120
167
 
121
168
  ## 🎮 Examples
122
169
 
@@ -125,9 +172,17 @@ Try these working examples:
125
172
  | Example | Description | Demo |
126
173
  |---------|-------------|------|
127
174
  | [**Nitro Basic**](./playgrounds/nitro/) | Standalone Nitro with GraphQL | `pnpm playground:nitro` |
175
+ | [**Vite + Nitro**](./playgrounds/vite/) | Vite with Nitro GraphQL integration | `cd playgrounds/vite && pnpm dev` |
128
176
  | [**Nuxt Integration**](./playgrounds/nuxt/) | Full Nuxt app with client types | `pnpm playground:nuxt` |
129
177
  | [**Apollo Federation**](./playgrounds/federation/) | Federated GraphQL services | `pnpm playground:federation` |
130
178
 
179
+ ### 🧪 Test Projects
180
+
181
+ Real-world test projects using nitro-graphql v2:
182
+
183
+ - [**Vite + Nitro + Rolldown**](https://github.com/productdevbook/vite-nitro-graphql/tree/rolldown) - Testing with Rolldown bundler (Vite 7+)
184
+ - [**Vite + Nitro (Main)**](https://github.com/productdevbook/vite-nitro-graphql) - Standard Vite integration tests
185
+
131
186
  ## 🏗️ Building Your First Feature
132
187
 
133
188
  Let's create a complete user management system:
@@ -210,6 +265,246 @@ query {
210
265
 
211
266
  ## 🚀 Advanced Features
212
267
 
268
+ <details>
269
+ <summary><strong>🎛️ Custom File Generation & Paths</strong></summary>
270
+
271
+ Control which files are auto-generated and customize their output paths. Perfect for library development, monorepos, or custom project structures.
272
+
273
+ ### Library Mode
274
+
275
+ Disable all scaffold files for library/module development:
276
+
277
+ ```ts
278
+ // nitro.config.ts
279
+ export default defineNitroConfig({
280
+ graphql: {
281
+ framework: 'graphql-yoga',
282
+ scaffold: false, // Disable all scaffold files
283
+ clientUtils: false, // Disable client utilities
284
+ }
285
+ })
286
+ ```
287
+
288
+ ### Fine-Grained Control
289
+
290
+ Control each file individually:
291
+
292
+ ```ts
293
+ export default defineNitroConfig({
294
+ graphql: {
295
+ framework: 'graphql-yoga',
296
+
297
+ // Scaffold files
298
+ scaffold: {
299
+ graphqlConfig: false, // Don't generate graphql.config.ts
300
+ serverSchema: true, // Generate server/graphql/schema.ts
301
+ serverConfig: true, // Generate server/graphql/config.ts
302
+ serverContext: false, // Don't generate server/graphql/context.ts
303
+ },
304
+
305
+ // Client utilities (Nuxt only)
306
+ clientUtils: {
307
+ index: true, // Generate app/graphql/index.ts
308
+ ofetch: false, // Don't generate ofetch wrappers
309
+ },
310
+
311
+ // SDK files
312
+ sdk: {
313
+ main: true, // Generate default SDK
314
+ external: true, // Generate external service SDKs
315
+ },
316
+
317
+ // Type files
318
+ types: {
319
+ server: true, // Generate server types
320
+ client: true, // Generate client types
321
+ external: true, // Generate external service types
322
+ }
323
+ }
324
+ })
325
+ ```
326
+
327
+ ### Custom Paths
328
+
329
+ Customize where files are generated:
330
+
331
+ ```ts
332
+ export default defineNitroConfig({
333
+ graphql: {
334
+ framework: 'graphql-yoga',
335
+
336
+ // Method 1: Global paths (affects all files)
337
+ paths: {
338
+ serverGraphql: 'src/server/graphql',
339
+ clientGraphql: 'src/client/graphql',
340
+ buildDir: '.build',
341
+ typesDir: '.build/types',
342
+ },
343
+
344
+ // Method 2: Specific file paths
345
+ scaffold: {
346
+ serverSchema: 'lib/graphql/schema.ts',
347
+ serverConfig: 'lib/graphql/config.ts',
348
+ },
349
+
350
+ sdk: {
351
+ main: 'app/graphql/organization/sdk.ts',
352
+ external: 'app/graphql/{serviceName}/client-sdk.ts',
353
+ },
354
+
355
+ types: {
356
+ server: 'types/graphql-server.d.ts',
357
+ client: 'types/graphql-client.d.ts',
358
+ }
359
+ }
360
+ })
361
+ ```
362
+
363
+ ### Path Placeholders
364
+
365
+ Use placeholders in custom paths:
366
+
367
+ | Placeholder | Description | Example |
368
+ |------------|-------------|---------|
369
+ | `{serviceName}` | External service name | `github`, `stripe` |
370
+ | `{buildDir}` | Build directory | `.nitro` or `.nuxt` |
371
+ | `{rootDir}` | Root directory | `/Users/you/project` |
372
+ | `{framework}` | Framework name | `nuxt` or `nitro` |
373
+ | `{typesDir}` | Types directory | `.nitro/types` |
374
+ | `{serverGraphql}` | Server GraphQL dir | `server/graphql` |
375
+ | `{clientGraphql}` | Client GraphQL dir | `app/graphql` |
376
+
377
+ Example:
378
+ ```ts
379
+ sdk: {
380
+ external: '{clientGraphql}/{serviceName}/sdk.ts'
381
+ }
382
+ // → app/graphql/github/sdk.ts
383
+ // → app/graphql/stripe/sdk.ts
384
+ ```
385
+
386
+ ### Service-Specific Paths
387
+
388
+ Customize paths for individual external services:
389
+
390
+ ```ts
391
+ export default defineNuxtConfig({
392
+ nitro: {
393
+ graphql: {
394
+ framework: 'graphql-yoga',
395
+
396
+ // Global default for all external services
397
+ sdk: {
398
+ external: 'app/graphql/{serviceName}/sdk.ts'
399
+ },
400
+
401
+ externalServices: [
402
+ {
403
+ name: 'github',
404
+ endpoint: 'https://api.github.com/graphql',
405
+ schema: 'https://api.github.com/graphql',
406
+
407
+ // GitHub-specific paths (override global config)
408
+ paths: {
409
+ sdk: 'app/graphql/organization/github-sdk.ts',
410
+ types: 'types/github.d.ts',
411
+ ofetch: 'app/graphql/organization/github-client.ts'
412
+ }
413
+ },
414
+ {
415
+ name: 'stripe',
416
+ endpoint: 'https://api.stripe.com/graphql',
417
+ schema: 'https://api.stripe.com/graphql',
418
+
419
+ // Stripe-specific paths
420
+ paths: {
421
+ sdk: 'app/graphql/payments/stripe-sdk.ts',
422
+ types: 'types/payments/stripe.d.ts',
423
+ // ofetch uses global config
424
+ }
425
+ },
426
+ {
427
+ name: 'shopify',
428
+ endpoint: 'https://api.shopify.com/graphql',
429
+ // No paths → uses global config
430
+ // → app/graphql/shopify/sdk.ts
431
+ }
432
+ ]
433
+ }
434
+ }
435
+ })
436
+ ```
437
+
438
+ ### Path Resolution Priority
439
+
440
+ When resolving file paths, the system follows this priority order:
441
+
442
+ 1. **Service-specific path** (for external services): `service.paths.sdk`
443
+ 2. **Category config**: `sdk.external` or `sdk.main`
444
+ 3. **Global paths**: `paths.clientGraphql`
445
+ 4. **Framework defaults**: Nuxt vs Nitro defaults
446
+
447
+ Example:
448
+ ```ts
449
+ // Given this config:
450
+ {
451
+ paths: { clientGraphql: 'custom/graphql' },
452
+ sdk: { external: '{clientGraphql}/{serviceName}/sdk.ts' },
453
+ externalServices: [
454
+ {
455
+ name: 'github',
456
+ paths: { sdk: 'app/org/github-sdk.ts' } // ← Wins (priority 1)
457
+ },
458
+ {
459
+ name: 'stripe',
460
+ // Uses sdk.external (priority 2)
461
+ // → custom/graphql/stripe/sdk.ts
462
+ }
463
+ ]
464
+ }
465
+ ```
466
+
467
+ ### Use Cases
468
+
469
+ **Monorepo structure:**
470
+ ```ts
471
+ paths: {
472
+ serverGraphql: 'packages/api/src/graphql',
473
+ clientGraphql: 'packages/web/src/graphql',
474
+ typesDir: 'packages/types/src/generated',
475
+ }
476
+ ```
477
+
478
+ **Multiple external service organizations:**
479
+ ```ts
480
+ externalServices: [
481
+ {
482
+ name: 'github',
483
+ paths: { sdk: 'app/graphql/vcs/github-sdk.ts' }
484
+ },
485
+ {
486
+ name: 'gitlab',
487
+ paths: { sdk: 'app/graphql/vcs/gitlab-sdk.ts' }
488
+ },
489
+ {
490
+ name: 'stripe',
491
+ paths: { sdk: 'app/graphql/billing/stripe-sdk.ts' }
492
+ }
493
+ ]
494
+ ```
495
+
496
+ **Library development (no scaffolding):**
497
+ ```ts
498
+ {
499
+ scaffold: false,
500
+ clientUtils: false,
501
+ sdk: { enabled: true }, // Only generate SDKs
502
+ types: { enabled: true }, // Only generate types
503
+ }
504
+ ```
505
+
506
+ </details>
507
+
213
508
  <details>
214
509
  <summary><strong>🎭 Custom Directives</strong></summary>
215
510
 
@@ -357,6 +652,94 @@ server/
357
652
  - ✅ Use correct path: `nitro-graphql/utils/define`
358
653
  - ✅ Use named exports in resolvers
359
654
 
655
+ **Vite: "Parse failure: Expected ';', '}' or <eof>" on GraphQL files**
656
+ - ✅ Add `graphql()` plugin from `nitro-graphql/vite`
657
+ - ✅ Ensure `graphql()` is placed **before** `nitro()` in plugins array
658
+ - ✅ Example:
659
+ ```ts
660
+ import { graphql } from 'nitro-graphql/vite'
661
+
662
+ export default defineConfig({
663
+ plugins: [
664
+ graphql(), // ← Must be first
665
+ nitro(),
666
+ ]
667
+ })
668
+ ```
669
+
670
+ **RollupError: "[exportName]" is not exported by "[file].resolver.ts"**
671
+
672
+ This error occurs when the resolver scanner can't find the expected export in your resolver file. Common causes:
673
+
674
+ 1. **Using default export instead of named export** ❌
675
+ ```ts
676
+ // ❌ WRONG - Will not be detected
677
+ export default defineQuery({
678
+ users: () => [...]
679
+ })
680
+ ```
681
+
682
+ ```ts
683
+ // ✅ CORRECT - Use named export
684
+ export const userQueries = defineQuery({
685
+ users: () => [...]
686
+ })
687
+ ```
688
+
689
+ 2. **Not using a define function** ❌
690
+ ```ts
691
+ // ❌ WRONG - Plain object won't be detected
692
+ export const resolvers = {
693
+ Query: {
694
+ users: () => [...]
695
+ }
696
+ }
697
+ ```
698
+
699
+ ```ts
700
+ // ✅ CORRECT - Use defineResolver, defineQuery, etc.
701
+ export const userResolver = defineResolver({
702
+ Query: {
703
+ users: () => [...]
704
+ }
705
+ })
706
+ ```
707
+
708
+ 3. **File naming doesn't match export** ❌
709
+ ```ts
710
+ // ❌ File: uploadFile.resolver.ts but export is named differently
711
+ export const fileUploader = defineMutation({...})
712
+ ```
713
+
714
+ ```ts
715
+ // ✅ CORRECT - Export name can be anything, as long as it uses a define function
716
+ export const uploadFile = defineMutation({...})
717
+ export const fileUploader = defineMutation({...}) // Both work!
718
+ ```
719
+
720
+ 4. **Syntax errors preventing parsing**
721
+ - Check for TypeScript compilation errors in the file
722
+ - Ensure imports are valid
723
+ - Verify no missing brackets or syntax issues
724
+
725
+ **How resolver scanning works:**
726
+ - The module uses `oxc-parser` to scan `.resolver.ts` files
727
+ - It looks for **named exports** using these functions:
728
+ - `defineResolver` - Complete resolver with Query, Mutation, etc.
729
+ - `defineQuery` - Query-only resolvers
730
+ - `defineMutation` - Mutation-only resolvers
731
+ - `defineType` - Custom type resolvers
732
+ - `defineSubscription` - Subscription resolvers
733
+ - `defineDirective` - Directive resolvers
734
+ - Only exports using these functions are included in the virtual module
735
+
736
+ **Debugging steps:**
737
+ 1. Check your resolver file uses named exports: `export const name = defineQuery({...})`
738
+ 2. Verify you're using one of the define functions listed above
739
+ 3. Look for TypeScript/syntax errors in the file
740
+ 4. Restart the dev server after fixing
741
+ 5. If issues persist, simplify the resolver to test (single query)
742
+
360
743
  </details>
361
744
 
362
745
  ## 🌟 Production Usage
@@ -365,6 +748,469 @@ This package powers production applications:
365
748
 
366
749
  - [**Nitroping**](https://github.com/productdevbook/nitroping) - Self-hosted push notification service
367
750
 
751
+ ## 🤖 Using Claude Code
752
+
753
+ Speed up development with [Claude Code](https://claude.ai/code) — AI-powered assistance for setting up and building with nitro-graphql.
754
+
755
+ ### Quick Setup Prompts
756
+
757
+ Copy and paste these prompts into Claude Code to scaffold a complete GraphQL API.
758
+
759
+ **💡 Tip**: After pasting, Claude Code will execute step-by-step and validate each action.
760
+
761
+ <details>
762
+ <summary>🟢 <strong>Nuxt Project</strong></summary>
763
+
764
+ ```
765
+ ## GOAL
766
+ Set up nitro-graphql in this Nuxt project with a User management GraphQL API.
767
+
768
+ ## PREREQUISITES
769
+ Check if this is a Nuxt project by looking for nuxt.config.ts in the root.
770
+
771
+ ## STEP 1: INSTALL DEPENDENCIES
772
+ Action: Run this command
773
+ Command: pnpm add nitro-graphql graphql-yoga graphql
774
+ Validation: Check package.json contains these packages
775
+
776
+ ## STEP 2: CONFIGURE NUXT
777
+ File: nuxt.config.ts
778
+ Action: EDIT (add to existing config, don't replace)
779
+ Add these properties:
780
+
781
+ export default defineNuxtConfig({
782
+ modules: ['nitro-graphql/nuxt'], // Add this module
783
+ nitro: {
784
+ graphql: {
785
+ framework: 'graphql-yoga',
786
+ },
787
+ },
788
+ })
789
+
790
+ Validation: Check the file has modules array and nitro.graphql config
791
+
792
+ ## STEP 3: CREATE SCHEMA
793
+ File: server/graphql/schema.graphql
794
+ Action: CREATE NEW FILE (create server/graphql/ directory if needed)
795
+ Content:
796
+
797
+ type User {
798
+ id: ID!
799
+ name: String!
800
+ email: String!
801
+ }
802
+
803
+ type Query {
804
+ users: [User!]!
805
+ user(id: ID!): User
806
+ }
807
+
808
+ type Mutation {
809
+ _empty: String
810
+ }
811
+
812
+ Validation: File should be in server/graphql/ directory
813
+
814
+ ## STEP 4: CREATE CONTEXT (Optional but recommended)
815
+ File: server/graphql/context.ts
816
+ Action: CREATE NEW FILE (auto-generated on first run, but create manually for clarity)
817
+ Content:
818
+
819
+ // Extend H3 event context with custom properties
820
+ declare module 'h3' {
821
+ interface H3EventContext {
822
+ // Add your custom context properties here
823
+ // Example:
824
+ // db?: Database
825
+ // auth?: { userId: string }
826
+ }
827
+ }
828
+
829
+ Note: This file lets you add custom properties to resolver context
830
+ Validation: File exists in server/graphql/
831
+
832
+ ## STEP 5: CREATE CONFIG (Optional)
833
+ File: server/graphql/config.ts
834
+ Action: CREATE NEW FILE (auto-generated, customize if needed)
835
+ Content:
836
+
837
+ // Custom GraphQL Yoga configuration
838
+ export default defineGraphQLConfig({
839
+ // Custom context enhancer, plugins, etc.
840
+ // See: https://the-guild.dev/graphql/yoga-server/docs
841
+ })
842
+
843
+ Note: Use this to customize GraphQL Yoga options
844
+ Validation: File exists in server/graphql/
845
+
846
+ ## STEP 6: CREATE RESOLVERS
847
+ File: server/graphql/users.resolver.ts
848
+ Action: CREATE NEW FILE
849
+ Content:
850
+
851
+ // ⚠️ CRITICAL: Use NAMED EXPORTS (not default export)
852
+ export const userQueries = defineQuery({
853
+ users: async (_, __, context) => {
854
+ // context is H3EventContext - access event, storage, etc.
855
+ return [
856
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
857
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
858
+ ]
859
+ },
860
+ user: async (_, { id }, context) => {
861
+ // Third parameter is context (H3EventContext)
862
+ const users = [
863
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
864
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
865
+ ]
866
+ return users.find(u => u.id === id) || null
867
+ }
868
+ })
869
+
870
+ Validation: File ends with .resolver.ts and uses named export
871
+
872
+ ## STEP 7: START DEV SERVER
873
+ Command: pnpm dev
874
+ Expected Output: Server starts on http://localhost:3000
875
+ Wait for: "Nitro built in X ms" message
876
+ Note: context.ts and config.ts will auto-generate if you skipped steps 4-5
877
+
878
+ ## VALIDATION CHECKLIST
879
+ - [ ] Navigate to http://localhost:3000/api/graphql - should show GraphQL playground
880
+ - [ ] Health check: http://localhost:3000/api/graphql/health - should return OK
881
+ - [ ] Run this query in playground:
882
+ ```graphql
883
+ query {
884
+ users {
885
+ id
886
+ name
887
+ email
888
+ }
889
+ }
890
+ ```
891
+ Expected: Returns 2 users
892
+ - [ ] Check .nuxt/types/nitro-graphql-server.d.ts exists (types auto-generated)
893
+
894
+ ## FILE STRUCTURE CREATED
895
+ ```
896
+ server/
897
+ graphql/
898
+ schema.graphql ← GraphQL type definitions
899
+ context.ts ← H3 event context augmentation (optional)
900
+ config.ts ← GraphQL Yoga config (optional)
901
+ users.resolver.ts ← Query resolvers
902
+ .nuxt/
903
+ types/
904
+ nitro-graphql-server.d.ts ← Auto-generated types
905
+ graphql.config.ts ← Auto-generated (for IDE tooling)
906
+ ```
907
+
908
+ ## CRITICAL RULES (MUST FOLLOW)
909
+ ❌ DO NOT use default exports in resolvers
910
+ Wrong: export default defineQuery({...})
911
+ Right: export const userQueries = defineQuery({...})
912
+
913
+ ❌ DO NOT name files without .resolver.ts extension
914
+ Wrong: users.ts or user-resolver.ts
915
+ Right: users.resolver.ts or user.resolver.ts
916
+
917
+ ✅ DO use named exports for all resolvers
918
+ ✅ DO place files in server/graphql/ directory
919
+ ✅ DO restart dev server if types don't generate
920
+
921
+ ## TROUBLESHOOTING
922
+ Issue: "GraphQL endpoint returns 404"
923
+ Fix: Ensure 'nitro-graphql/nuxt' is in modules array (not just 'nitro-graphql')
924
+
925
+ Issue: "defineQuery is not defined"
926
+ Fix: Restart dev server - auto-imports need to regenerate
927
+
928
+ Issue: "Types not generating"
929
+ Fix: Check .nuxt/types/nitro-graphql-server.d.ts exists, if not restart dev server
930
+
931
+ Issue: "Module not found: nitro-graphql"
932
+ Fix: Run pnpm install again, check package.json has the package
933
+
934
+ ## NEXT STEPS (After Setup Works)
935
+ 1. Add mutations: "Add createUser and deleteUser mutations with H3 storage"
936
+ 2. Extend context: "Add database connection to context.ts and use it in resolvers"
937
+ 3. Use types: "Import and use TypeScript types from #graphql/server in resolvers"
938
+ 4. Add auth: "Add authentication middleware using context in resolvers"
939
+ 5. Custom config: "Configure GraphQL Yoga plugins in config.ts"
940
+
941
+ Now implement this setup step-by-step.
942
+ ```
943
+
944
+ </details>
945
+
946
+ <details>
947
+ <summary>⚡ <strong>Nitro Project</strong></summary>
948
+
949
+ ```
950
+ Set up nitro-graphql in this Nitro project following these exact specifications:
951
+
952
+ INSTALLATION:
953
+ 1. Run: pnpm add nitro-graphql graphql-yoga graphql
954
+
955
+ CONFIGURATION (nitro.config.ts):
956
+ import { defineNitroConfig } from 'nitro/config'
957
+
958
+ export default defineNitroConfig({
959
+ modules: ['nitro-graphql'],
960
+ graphql: {
961
+ framework: 'graphql-yoga',
962
+ },
963
+ })
964
+
965
+ SCHEMA (server/graphql/schema.graphql):
966
+ type Product {
967
+ id: ID!
968
+ name: String!
969
+ price: Float!
970
+ }
971
+
972
+ input CreateProductInput {
973
+ name: String!
974
+ price: Float!
975
+ }
976
+
977
+ type Query {
978
+ products: [Product!]!
979
+ product(id: ID!): Product
980
+ }
981
+
982
+ type Mutation {
983
+ createProduct(input: CreateProductInput!): Product!
984
+ }
985
+
986
+ RESOLVERS (server/graphql/products.resolver.ts):
987
+ // Use NAMED EXPORTS only
988
+ export const productQueries = defineQuery({
989
+ products: async (_, __, context) => {
990
+ // Access H3 event context
991
+ const products = await context.storage?.getItem('products') || []
992
+ return products
993
+ },
994
+ product: async (_, { id }, context) => {
995
+ const products = await context.storage?.getItem('products') || []
996
+ return products.find(p => p.id === id)
997
+ }
998
+ })
999
+
1000
+ export const productMutations = defineMutation({
1001
+ createProduct: async (_, { input }, context) => {
1002
+ const products = await context.storage?.getItem('products') || []
1003
+ const product = {
1004
+ id: Date.now().toString(),
1005
+ ...input
1006
+ }
1007
+ products.push(product)
1008
+ await context.storage?.setItem('products', products)
1009
+ return product
1010
+ }
1011
+ })
1012
+
1013
+ KEY RULES:
1014
+ - Files: *.graphql for schemas, *.resolver.ts for resolvers
1015
+ - MUST use named exports (not default export)
1016
+ - defineQuery and defineMutation are auto-imported
1017
+ - Context is the third parameter (access H3 event context)
1018
+ - Endpoint: http://localhost:3000/api/graphql
1019
+
1020
+ Now implement this setup.
1021
+ ```
1022
+
1023
+ </details>
1024
+
1025
+ <details>
1026
+ <summary>🎮 <strong>Apollo Server Setup</strong></summary>
1027
+
1028
+ ```
1029
+ Set up nitro-graphql with Apollo Server following these exact specifications:
1030
+
1031
+ INSTALLATION:
1032
+ 1. Run: pnpm add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
1033
+
1034
+ CONFIGURATION (nitro.config.ts):
1035
+ import { defineNitroConfig } from 'nitro/config'
1036
+
1037
+ export default defineNitroConfig({
1038
+ modules: ['nitro-graphql'],
1039
+ graphql: {
1040
+ framework: 'apollo-server',
1041
+ },
1042
+ })
1043
+
1044
+ SCHEMA (server/graphql/schema.graphql):
1045
+ type Book {
1046
+ id: ID!
1047
+ title: String!
1048
+ author: String!
1049
+ }
1050
+
1051
+ type Query {
1052
+ books: [Book!]!
1053
+ book(id: ID!): Book
1054
+ }
1055
+
1056
+ type Mutation {
1057
+ addBook(title: String!, author: String!): Book!
1058
+ }
1059
+
1060
+ RESOLVERS (server/graphql/books.resolver.ts):
1061
+ // IMPORTANT: Use NAMED EXPORTS
1062
+ export const bookResolver = defineResolver({
1063
+ Query: {
1064
+ books: async () => {
1065
+ return [
1066
+ { id: '1', title: '1984', author: 'George Orwell' }
1067
+ ]
1068
+ },
1069
+ book: async (_, { id }) => {
1070
+ return { id, title: '1984', author: 'George Orwell' }
1071
+ }
1072
+ },
1073
+ Mutation: {
1074
+ addBook: async (_, { title, author }) => {
1075
+ return {
1076
+ id: Date.now().toString(),
1077
+ title,
1078
+ author
1079
+ }
1080
+ }
1081
+ }
1082
+ })
1083
+
1084
+ KEY RULES:
1085
+ - framework: 'apollo-server' in config
1086
+ - defineResolver for complete resolver maps
1087
+ - Named exports required (export const name = ...)
1088
+ - Apollo Sandbox: http://localhost:3000/api/graphql
1089
+ - Supports Apollo Federation with federation: { enabled: true }
1090
+
1091
+ Now implement this setup.
1092
+ ```
1093
+
1094
+ </details>
1095
+
1096
+ <details>
1097
+ <summary>🔄 <strong>Add Feature to Existing Setup</strong></summary>
1098
+
1099
+ ```
1100
+ Add a complete blog posts feature to my nitro-graphql API following these specifications:
1101
+
1102
+ SCHEMA (server/graphql/posts/post.graphql):
1103
+ type Post {
1104
+ id: ID!
1105
+ title: String!
1106
+ content: String!
1107
+ authorId: ID!
1108
+ createdAt: String!
1109
+ }
1110
+
1111
+ input CreatePostInput {
1112
+ title: String!
1113
+ content: String!
1114
+ authorId: ID!
1115
+ }
1116
+
1117
+ input UpdatePostInput {
1118
+ title: String
1119
+ content: String
1120
+ }
1121
+
1122
+ extend type Query {
1123
+ posts(limit: Int = 10, offset: Int = 0): [Post!]!
1124
+ post(id: ID!): Post
1125
+ }
1126
+
1127
+ extend type Mutation {
1128
+ createPost(input: CreatePostInput!): Post!
1129
+ updatePost(id: ID!, input: UpdatePostInput!): Post
1130
+ deletePost(id: ID!): Boolean!
1131
+ }
1132
+
1133
+ RESOLVERS (server/graphql/posts/post.resolver.ts):
1134
+ // Use NAMED EXPORTS
1135
+ export const postQueries = defineQuery({
1136
+ posts: async (_, { limit, offset }, context) => {
1137
+ const posts = await context.storage?.getItem('posts') || []
1138
+ return posts.slice(offset, offset + limit)
1139
+ },
1140
+ post: async (_, { id }, context) => {
1141
+ const posts = await context.storage?.getItem('posts') || []
1142
+ return posts.find(p => p.id === id) || null
1143
+ }
1144
+ })
1145
+
1146
+ export const postMutations = defineMutation({
1147
+ createPost: async (_, { input }, context) => {
1148
+ const posts = await context.storage?.getItem('posts') || []
1149
+ const post = {
1150
+ id: Date.now().toString(),
1151
+ ...input,
1152
+ createdAt: new Date().toISOString()
1153
+ }
1154
+ posts.push(post)
1155
+ await context.storage?.setItem('posts', posts)
1156
+ return post
1157
+ },
1158
+ updatePost: async (_, { id, input }, context) => {
1159
+ const posts = await context.storage?.getItem('posts') || []
1160
+ const index = posts.findIndex(p => p.id === id)
1161
+ if (index === -1) return null
1162
+ posts[index] = { ...posts[index], ...input }
1163
+ await context.storage?.setItem('posts', posts)
1164
+ return posts[index]
1165
+ },
1166
+ deletePost: async (_, { id }, context) => {
1167
+ const posts = await context.storage?.getItem('posts') || []
1168
+ const filtered = posts.filter(p => p.id !== id)
1169
+ await context.storage?.setItem('posts', filtered)
1170
+ return filtered.length < posts.length
1171
+ }
1172
+ })
1173
+
1174
+ TYPE USAGE:
1175
+ After dev server restarts, types are auto-generated in:
1176
+ - .nitro/types/nitro-graphql-server.d.ts (server types)
1177
+ - .nuxt/types/nitro-graphql-server.d.ts (for Nuxt)
1178
+
1179
+ Import types:
1180
+ import type { Post, CreatePostInput } from '#graphql/server'
1181
+
1182
+ KEY RULES:
1183
+ - Use "extend type" to add to existing Query/Mutation
1184
+ - Named exports required
1185
+ - Context has H3 event properties
1186
+ - Types auto-generate on file changes
1187
+
1188
+ Now implement this feature.
1189
+ ```
1190
+
1191
+ </details>
1192
+
1193
+ ### Working with Your GraphQL API
1194
+
1195
+ Once set up, you can ask Claude Code for help with:
1196
+
1197
+ ```
1198
+ "Add authentication to my GraphQL resolvers"
1199
+ "Create a custom @auth directive for field-level permissions"
1200
+ "Set up type generation for client-side queries"
1201
+ "Add pagination to my users query"
1202
+ "Connect to an external GitHub GraphQL API"
1203
+ "Debug: my types aren't generating in .nitro/types/"
1204
+ "Optimize resolver performance using DataLoader"
1205
+ ```
1206
+
1207
+ ### Tips for Better Results
1208
+
1209
+ - **Start specific**: Include your framework (Nuxt/Nitro), version, and goal
1210
+ - **Reference docs**: Mention "following nitro-graphql conventions" to align with best practices
1211
+ - **Show errors**: Paste error messages for faster debugging
1212
+ - **Test iteratively**: Run `pnpm dev` after each change to verify
1213
+
368
1214
  ## 🛠️ Development
369
1215
 
370
1216
  ```bash
@@ -424,4 +1270,8 @@ pnpm lint
424
1270
  [bundle-src]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
425
1271
  [bundle-href]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
426
1272
  [license-src]: https://img.shields.io/github/license/productdevbook/nitro-graphql.svg?style=flat&colorA=080f12&colorB=1fa669
427
- [license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
1273
+ [license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
1274
+ [docs-src]: https://img.shields.io/badge/docs-read-blue?style=flat&colorA=080f12&colorB=1fa669
1275
+ [docs-href]: https://nitro-graphql.pages.dev
1276
+ [beta-src]: https://img.shields.io/npm/v/nitro-graphql/beta?style=flat&logo=rocket&logoColor=white&label=beta&color=7c3aed&colorA=080f12
1277
+ [beta-href]: https://github.com/productdevbook/nitro-graphql/releases