nitro-graphql 1.4.4 → 1.5.1

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.
package/README.md CHANGED
@@ -210,6 +210,246 @@ query {
210
210
 
211
211
  ## 🚀 Advanced Features
212
212
 
213
+ <details>
214
+ <summary><strong>🎛️ Custom File Generation & Paths</strong></summary>
215
+
216
+ Control which files are auto-generated and customize their output paths. Perfect for library development, monorepos, or custom project structures.
217
+
218
+ ### Library Mode
219
+
220
+ Disable all scaffold files for library/module development:
221
+
222
+ ```ts
223
+ // nitro.config.ts
224
+ export default defineNitroConfig({
225
+ graphql: {
226
+ framework: 'graphql-yoga',
227
+ scaffold: false, // Disable all scaffold files
228
+ clientUtils: false, // Disable client utilities
229
+ }
230
+ })
231
+ ```
232
+
233
+ ### Fine-Grained Control
234
+
235
+ Control each file individually:
236
+
237
+ ```ts
238
+ export default defineNitroConfig({
239
+ graphql: {
240
+ framework: 'graphql-yoga',
241
+
242
+ // Scaffold files
243
+ scaffold: {
244
+ graphqlConfig: false, // Don't generate graphql.config.ts
245
+ serverSchema: true, // Generate server/graphql/schema.ts
246
+ serverConfig: true, // Generate server/graphql/config.ts
247
+ serverContext: false, // Don't generate server/graphql/context.ts
248
+ },
249
+
250
+ // Client utilities (Nuxt only)
251
+ clientUtils: {
252
+ index: true, // Generate app/graphql/index.ts
253
+ ofetch: false, // Don't generate ofetch wrappers
254
+ },
255
+
256
+ // SDK files
257
+ sdk: {
258
+ main: true, // Generate default SDK
259
+ external: true, // Generate external service SDKs
260
+ },
261
+
262
+ // Type files
263
+ types: {
264
+ server: true, // Generate server types
265
+ client: true, // Generate client types
266
+ external: true, // Generate external service types
267
+ }
268
+ }
269
+ })
270
+ ```
271
+
272
+ ### Custom Paths
273
+
274
+ Customize where files are generated:
275
+
276
+ ```ts
277
+ export default defineNitroConfig({
278
+ graphql: {
279
+ framework: 'graphql-yoga',
280
+
281
+ // Method 1: Global paths (affects all files)
282
+ paths: {
283
+ serverGraphql: 'src/server/graphql',
284
+ clientGraphql: 'src/client/graphql',
285
+ buildDir: '.build',
286
+ typesDir: '.build/types',
287
+ },
288
+
289
+ // Method 2: Specific file paths
290
+ scaffold: {
291
+ serverSchema: 'lib/graphql/schema.ts',
292
+ serverConfig: 'lib/graphql/config.ts',
293
+ },
294
+
295
+ sdk: {
296
+ main: 'app/graphql/organization/sdk.ts',
297
+ external: 'app/graphql/{serviceName}/client-sdk.ts',
298
+ },
299
+
300
+ types: {
301
+ server: 'types/graphql-server.d.ts',
302
+ client: 'types/graphql-client.d.ts',
303
+ }
304
+ }
305
+ })
306
+ ```
307
+
308
+ ### Path Placeholders
309
+
310
+ Use placeholders in custom paths:
311
+
312
+ | Placeholder | Description | Example |
313
+ |------------|-------------|---------|
314
+ | `{serviceName}` | External service name | `github`, `stripe` |
315
+ | `{buildDir}` | Build directory | `.nitro` or `.nuxt` |
316
+ | `{rootDir}` | Root directory | `/Users/you/project` |
317
+ | `{framework}` | Framework name | `nuxt` or `nitro` |
318
+ | `{typesDir}` | Types directory | `.nitro/types` |
319
+ | `{serverGraphql}` | Server GraphQL dir | `server/graphql` |
320
+ | `{clientGraphql}` | Client GraphQL dir | `app/graphql` |
321
+
322
+ Example:
323
+ ```ts
324
+ sdk: {
325
+ external: '{clientGraphql}/{serviceName}/sdk.ts'
326
+ }
327
+ // → app/graphql/github/sdk.ts
328
+ // → app/graphql/stripe/sdk.ts
329
+ ```
330
+
331
+ ### Service-Specific Paths
332
+
333
+ Customize paths for individual external services:
334
+
335
+ ```ts
336
+ export default defineNuxtConfig({
337
+ nitro: {
338
+ graphql: {
339
+ framework: 'graphql-yoga',
340
+
341
+ // Global default for all external services
342
+ sdk: {
343
+ external: 'app/graphql/{serviceName}/sdk.ts'
344
+ },
345
+
346
+ externalServices: [
347
+ {
348
+ name: 'github',
349
+ endpoint: 'https://api.github.com/graphql',
350
+ schema: 'https://api.github.com/graphql',
351
+
352
+ // GitHub-specific paths (override global config)
353
+ paths: {
354
+ sdk: 'app/graphql/organization/github-sdk.ts',
355
+ types: 'types/github.d.ts',
356
+ ofetch: 'app/graphql/organization/github-client.ts'
357
+ }
358
+ },
359
+ {
360
+ name: 'stripe',
361
+ endpoint: 'https://api.stripe.com/graphql',
362
+ schema: 'https://api.stripe.com/graphql',
363
+
364
+ // Stripe-specific paths
365
+ paths: {
366
+ sdk: 'app/graphql/payments/stripe-sdk.ts',
367
+ types: 'types/payments/stripe.d.ts',
368
+ // ofetch uses global config
369
+ }
370
+ },
371
+ {
372
+ name: 'shopify',
373
+ endpoint: 'https://api.shopify.com/graphql',
374
+ // No paths → uses global config
375
+ // → app/graphql/shopify/sdk.ts
376
+ }
377
+ ]
378
+ }
379
+ }
380
+ })
381
+ ```
382
+
383
+ ### Path Resolution Priority
384
+
385
+ When resolving file paths, the system follows this priority order:
386
+
387
+ 1. **Service-specific path** (for external services): `service.paths.sdk`
388
+ 2. **Category config**: `sdk.external` or `sdk.main`
389
+ 3. **Global paths**: `paths.clientGraphql`
390
+ 4. **Framework defaults**: Nuxt vs Nitro defaults
391
+
392
+ Example:
393
+ ```ts
394
+ // Given this config:
395
+ {
396
+ paths: { clientGraphql: 'custom/graphql' },
397
+ sdk: { external: '{clientGraphql}/{serviceName}/sdk.ts' },
398
+ externalServices: [
399
+ {
400
+ name: 'github',
401
+ paths: { sdk: 'app/org/github-sdk.ts' } // ← Wins (priority 1)
402
+ },
403
+ {
404
+ name: 'stripe',
405
+ // Uses sdk.external (priority 2)
406
+ // → custom/graphql/stripe/sdk.ts
407
+ }
408
+ ]
409
+ }
410
+ ```
411
+
412
+ ### Use Cases
413
+
414
+ **Monorepo structure:**
415
+ ```ts
416
+ paths: {
417
+ serverGraphql: 'packages/api/src/graphql',
418
+ clientGraphql: 'packages/web/src/graphql',
419
+ typesDir: 'packages/types/src/generated',
420
+ }
421
+ ```
422
+
423
+ **Multiple external service organizations:**
424
+ ```ts
425
+ externalServices: [
426
+ {
427
+ name: 'github',
428
+ paths: { sdk: 'app/graphql/vcs/github-sdk.ts' }
429
+ },
430
+ {
431
+ name: 'gitlab',
432
+ paths: { sdk: 'app/graphql/vcs/gitlab-sdk.ts' }
433
+ },
434
+ {
435
+ name: 'stripe',
436
+ paths: { sdk: 'app/graphql/billing/stripe-sdk.ts' }
437
+ }
438
+ ]
439
+ ```
440
+
441
+ **Library development (no scaffolding):**
442
+ ```ts
443
+ {
444
+ scaffold: false,
445
+ clientUtils: false,
446
+ sdk: { enabled: true }, // Only generate SDKs
447
+ types: { enabled: true }, // Only generate types
448
+ }
449
+ ```
450
+
451
+ </details>
452
+
213
453
  <details>
214
454
  <summary><strong>🎭 Custom Directives</strong></summary>
215
455
 
@@ -357,6 +597,94 @@ server/
357
597
  - ✅ Use correct path: `nitro-graphql/utils/define`
358
598
  - ✅ Use named exports in resolvers
359
599
 
600
+ **Vite: "Parse failure: Expected ';', '}' or <eof>" on GraphQL files**
601
+ - ✅ Add `graphql()` plugin from `nitro-graphql/vite`
602
+ - ✅ Ensure `graphql()` is placed **before** `nitro()` in plugins array
603
+ - ✅ Example:
604
+ ```ts
605
+ import { graphql } from 'nitro-graphql/vite'
606
+
607
+ export default defineConfig({
608
+ plugins: [
609
+ graphql(), // ← Must be first
610
+ nitro(),
611
+ ]
612
+ })
613
+ ```
614
+
615
+ **RollupError: "[exportName]" is not exported by "[file].resolver.ts"**
616
+
617
+ This error occurs when the resolver scanner can't find the expected export in your resolver file. Common causes:
618
+
619
+ 1. **Using default export instead of named export** ❌
620
+ ```ts
621
+ // ❌ WRONG - Will not be detected
622
+ export default defineQuery({
623
+ users: () => [...]
624
+ })
625
+ ```
626
+
627
+ ```ts
628
+ // ✅ CORRECT - Use named export
629
+ export const userQueries = defineQuery({
630
+ users: () => [...]
631
+ })
632
+ ```
633
+
634
+ 2. **Not using a define function** ❌
635
+ ```ts
636
+ // ❌ WRONG - Plain object won't be detected
637
+ export const resolvers = {
638
+ Query: {
639
+ users: () => [...]
640
+ }
641
+ }
642
+ ```
643
+
644
+ ```ts
645
+ // ✅ CORRECT - Use defineResolver, defineQuery, etc.
646
+ export const userResolver = defineResolver({
647
+ Query: {
648
+ users: () => [...]
649
+ }
650
+ })
651
+ ```
652
+
653
+ 3. **File naming doesn't match export** ❌
654
+ ```ts
655
+ // ❌ File: uploadFile.resolver.ts but export is named differently
656
+ export const fileUploader = defineMutation({...})
657
+ ```
658
+
659
+ ```ts
660
+ // ✅ CORRECT - Export name can be anything, as long as it uses a define function
661
+ export const uploadFile = defineMutation({...})
662
+ export const fileUploader = defineMutation({...}) // Both work!
663
+ ```
664
+
665
+ 4. **Syntax errors preventing parsing**
666
+ - Check for TypeScript compilation errors in the file
667
+ - Ensure imports are valid
668
+ - Verify no missing brackets or syntax issues
669
+
670
+ **How resolver scanning works:**
671
+ - The module uses `oxc-parser` to scan `.resolver.ts` files
672
+ - It looks for **named exports** using these functions:
673
+ - `defineResolver` - Complete resolver with Query, Mutation, etc.
674
+ - `defineQuery` - Query-only resolvers
675
+ - `defineMutation` - Mutation-only resolvers
676
+ - `defineType` - Custom type resolvers
677
+ - `defineSubscription` - Subscription resolvers
678
+ - `defineDirective` - Directive resolvers
679
+ - Only exports using these functions are included in the virtual module
680
+
681
+ **Debugging steps:**
682
+ 1. Check your resolver file uses named exports: `export const name = defineQuery({...})`
683
+ 2. Verify you're using one of the define functions listed above
684
+ 3. Look for TypeScript/syntax errors in the file
685
+ 4. Restart the dev server after fixing
686
+ 5. If issues persist, simplify the resolver to test (single query)
687
+
360
688
  </details>
361
689
 
362
690
  ## 🌟 Production Usage
@@ -365,6 +693,469 @@ This package powers production applications:
365
693
 
366
694
  - [**Nitroping**](https://github.com/productdevbook/nitroping) - Self-hosted push notification service
367
695
 
696
+ ## 🤖 Using Claude Code
697
+
698
+ Speed up development with [Claude Code](https://claude.ai/code) — AI-powered assistance for setting up and building with nitro-graphql.
699
+
700
+ ### Quick Setup Prompts
701
+
702
+ Copy and paste these prompts into Claude Code to scaffold a complete GraphQL API.
703
+
704
+ **💡 Tip**: After pasting, Claude Code will execute step-by-step and validate each action.
705
+
706
+ <details>
707
+ <summary>🟢 <strong>Nuxt Project</strong></summary>
708
+
709
+ ```
710
+ ## GOAL
711
+ Set up nitro-graphql in this Nuxt project with a User management GraphQL API.
712
+
713
+ ## PREREQUISITES
714
+ Check if this is a Nuxt project by looking for nuxt.config.ts in the root.
715
+
716
+ ## STEP 1: INSTALL DEPENDENCIES
717
+ Action: Run this command
718
+ Command: pnpm add nitro-graphql graphql-yoga graphql
719
+ Validation: Check package.json contains these packages
720
+
721
+ ## STEP 2: CONFIGURE NUXT
722
+ File: nuxt.config.ts
723
+ Action: EDIT (add to existing config, don't replace)
724
+ Add these properties:
725
+
726
+ export default defineNuxtConfig({
727
+ modules: ['nitro-graphql/nuxt'], // Add this module
728
+ nitro: {
729
+ graphql: {
730
+ framework: 'graphql-yoga',
731
+ },
732
+ },
733
+ })
734
+
735
+ Validation: Check the file has modules array and nitro.graphql config
736
+
737
+ ## STEP 3: CREATE SCHEMA
738
+ File: server/graphql/schema.graphql
739
+ Action: CREATE NEW FILE (create server/graphql/ directory if needed)
740
+ Content:
741
+
742
+ type User {
743
+ id: ID!
744
+ name: String!
745
+ email: String!
746
+ }
747
+
748
+ type Query {
749
+ users: [User!]!
750
+ user(id: ID!): User
751
+ }
752
+
753
+ type Mutation {
754
+ _empty: String
755
+ }
756
+
757
+ Validation: File should be in server/graphql/ directory
758
+
759
+ ## STEP 4: CREATE CONTEXT (Optional but recommended)
760
+ File: server/graphql/context.ts
761
+ Action: CREATE NEW FILE (auto-generated on first run, but create manually for clarity)
762
+ Content:
763
+
764
+ // Extend H3 event context with custom properties
765
+ declare module 'h3' {
766
+ interface H3EventContext {
767
+ // Add your custom context properties here
768
+ // Example:
769
+ // db?: Database
770
+ // auth?: { userId: string }
771
+ }
772
+ }
773
+
774
+ Note: This file lets you add custom properties to resolver context
775
+ Validation: File exists in server/graphql/
776
+
777
+ ## STEP 5: CREATE CONFIG (Optional)
778
+ File: server/graphql/config.ts
779
+ Action: CREATE NEW FILE (auto-generated, customize if needed)
780
+ Content:
781
+
782
+ // Custom GraphQL Yoga configuration
783
+ export default defineGraphQLConfig({
784
+ // Custom context enhancer, plugins, etc.
785
+ // See: https://the-guild.dev/graphql/yoga-server/docs
786
+ })
787
+
788
+ Note: Use this to customize GraphQL Yoga options
789
+ Validation: File exists in server/graphql/
790
+
791
+ ## STEP 6: CREATE RESOLVERS
792
+ File: server/graphql/users.resolver.ts
793
+ Action: CREATE NEW FILE
794
+ Content:
795
+
796
+ // ⚠️ CRITICAL: Use NAMED EXPORTS (not default export)
797
+ export const userQueries = defineQuery({
798
+ users: async (_, __, context) => {
799
+ // context is H3EventContext - access event, storage, etc.
800
+ return [
801
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
802
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
803
+ ]
804
+ },
805
+ user: async (_, { id }, context) => {
806
+ // Third parameter is context (H3EventContext)
807
+ const users = [
808
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
809
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
810
+ ]
811
+ return users.find(u => u.id === id) || null
812
+ }
813
+ })
814
+
815
+ Validation: File ends with .resolver.ts and uses named export
816
+
817
+ ## STEP 7: START DEV SERVER
818
+ Command: pnpm dev
819
+ Expected Output: Server starts on http://localhost:3000
820
+ Wait for: "Nitro built in X ms" message
821
+ Note: context.ts and config.ts will auto-generate if you skipped steps 4-5
822
+
823
+ ## VALIDATION CHECKLIST
824
+ - [ ] Navigate to http://localhost:3000/api/graphql - should show GraphQL playground
825
+ - [ ] Health check: http://localhost:3000/api/graphql/health - should return OK
826
+ - [ ] Run this query in playground:
827
+ ```graphql
828
+ query {
829
+ users {
830
+ id
831
+ name
832
+ email
833
+ }
834
+ }
835
+ ```
836
+ Expected: Returns 2 users
837
+ - [ ] Check .nuxt/types/nitro-graphql-server.d.ts exists (types auto-generated)
838
+
839
+ ## FILE STRUCTURE CREATED
840
+ ```
841
+ server/
842
+ graphql/
843
+ schema.graphql ← GraphQL type definitions
844
+ context.ts ← H3 event context augmentation (optional)
845
+ config.ts ← GraphQL Yoga config (optional)
846
+ users.resolver.ts ← Query resolvers
847
+ .nuxt/
848
+ types/
849
+ nitro-graphql-server.d.ts ← Auto-generated types
850
+ graphql.config.ts ← Auto-generated (for IDE tooling)
851
+ ```
852
+
853
+ ## CRITICAL RULES (MUST FOLLOW)
854
+ ❌ DO NOT use default exports in resolvers
855
+ Wrong: export default defineQuery({...})
856
+ Right: export const userQueries = defineQuery({...})
857
+
858
+ ❌ DO NOT name files without .resolver.ts extension
859
+ Wrong: users.ts or user-resolver.ts
860
+ Right: users.resolver.ts or user.resolver.ts
861
+
862
+ ✅ DO use named exports for all resolvers
863
+ ✅ DO place files in server/graphql/ directory
864
+ ✅ DO restart dev server if types don't generate
865
+
866
+ ## TROUBLESHOOTING
867
+ Issue: "GraphQL endpoint returns 404"
868
+ Fix: Ensure 'nitro-graphql/nuxt' is in modules array (not just 'nitro-graphql')
869
+
870
+ Issue: "defineQuery is not defined"
871
+ Fix: Restart dev server - auto-imports need to regenerate
872
+
873
+ Issue: "Types not generating"
874
+ Fix: Check .nuxt/types/nitro-graphql-server.d.ts exists, if not restart dev server
875
+
876
+ Issue: "Module not found: nitro-graphql"
877
+ Fix: Run pnpm install again, check package.json has the package
878
+
879
+ ## NEXT STEPS (After Setup Works)
880
+ 1. Add mutations: "Add createUser and deleteUser mutations with H3 storage"
881
+ 2. Extend context: "Add database connection to context.ts and use it in resolvers"
882
+ 3. Use types: "Import and use TypeScript types from #graphql/server in resolvers"
883
+ 4. Add auth: "Add authentication middleware using context in resolvers"
884
+ 5. Custom config: "Configure GraphQL Yoga plugins in config.ts"
885
+
886
+ Now implement this setup step-by-step.
887
+ ```
888
+
889
+ </details>
890
+
891
+ <details>
892
+ <summary>⚡ <strong>Nitro Project</strong></summary>
893
+
894
+ ```
895
+ Set up nitro-graphql in this Nitro project following these exact specifications:
896
+
897
+ INSTALLATION:
898
+ 1. Run: pnpm add nitro-graphql graphql-yoga graphql
899
+
900
+ CONFIGURATION (nitro.config.ts):
901
+ import { defineNitroConfig } from 'nitro/config'
902
+
903
+ export default defineNitroConfig({
904
+ modules: ['nitro-graphql'],
905
+ graphql: {
906
+ framework: 'graphql-yoga',
907
+ },
908
+ })
909
+
910
+ SCHEMA (server/graphql/schema.graphql):
911
+ type Product {
912
+ id: ID!
913
+ name: String!
914
+ price: Float!
915
+ }
916
+
917
+ input CreateProductInput {
918
+ name: String!
919
+ price: Float!
920
+ }
921
+
922
+ type Query {
923
+ products: [Product!]!
924
+ product(id: ID!): Product
925
+ }
926
+
927
+ type Mutation {
928
+ createProduct(input: CreateProductInput!): Product!
929
+ }
930
+
931
+ RESOLVERS (server/graphql/products.resolver.ts):
932
+ // Use NAMED EXPORTS only
933
+ export const productQueries = defineQuery({
934
+ products: async (_, __, context) => {
935
+ // Access H3 event context
936
+ const products = await context.storage?.getItem('products') || []
937
+ return products
938
+ },
939
+ product: async (_, { id }, context) => {
940
+ const products = await context.storage?.getItem('products') || []
941
+ return products.find(p => p.id === id)
942
+ }
943
+ })
944
+
945
+ export const productMutations = defineMutation({
946
+ createProduct: async (_, { input }, context) => {
947
+ const products = await context.storage?.getItem('products') || []
948
+ const product = {
949
+ id: Date.now().toString(),
950
+ ...input
951
+ }
952
+ products.push(product)
953
+ await context.storage?.setItem('products', products)
954
+ return product
955
+ }
956
+ })
957
+
958
+ KEY RULES:
959
+ - Files: *.graphql for schemas, *.resolver.ts for resolvers
960
+ - MUST use named exports (not default export)
961
+ - defineQuery and defineMutation are auto-imported
962
+ - Context is the third parameter (access H3 event context)
963
+ - Endpoint: http://localhost:3000/api/graphql
964
+
965
+ Now implement this setup.
966
+ ```
967
+
968
+ </details>
969
+
970
+ <details>
971
+ <summary>🎮 <strong>Apollo Server Setup</strong></summary>
972
+
973
+ ```
974
+ Set up nitro-graphql with Apollo Server following these exact specifications:
975
+
976
+ INSTALLATION:
977
+ 1. Run: pnpm add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
978
+
979
+ CONFIGURATION (nitro.config.ts):
980
+ import { defineNitroConfig } from 'nitro/config'
981
+
982
+ export default defineNitroConfig({
983
+ modules: ['nitro-graphql'],
984
+ graphql: {
985
+ framework: 'apollo-server',
986
+ },
987
+ })
988
+
989
+ SCHEMA (server/graphql/schema.graphql):
990
+ type Book {
991
+ id: ID!
992
+ title: String!
993
+ author: String!
994
+ }
995
+
996
+ type Query {
997
+ books: [Book!]!
998
+ book(id: ID!): Book
999
+ }
1000
+
1001
+ type Mutation {
1002
+ addBook(title: String!, author: String!): Book!
1003
+ }
1004
+
1005
+ RESOLVERS (server/graphql/books.resolver.ts):
1006
+ // IMPORTANT: Use NAMED EXPORTS
1007
+ export const bookResolver = defineResolver({
1008
+ Query: {
1009
+ books: async () => {
1010
+ return [
1011
+ { id: '1', title: '1984', author: 'George Orwell' }
1012
+ ]
1013
+ },
1014
+ book: async (_, { id }) => {
1015
+ return { id, title: '1984', author: 'George Orwell' }
1016
+ }
1017
+ },
1018
+ Mutation: {
1019
+ addBook: async (_, { title, author }) => {
1020
+ return {
1021
+ id: Date.now().toString(),
1022
+ title,
1023
+ author
1024
+ }
1025
+ }
1026
+ }
1027
+ })
1028
+
1029
+ KEY RULES:
1030
+ - framework: 'apollo-server' in config
1031
+ - defineResolver for complete resolver maps
1032
+ - Named exports required (export const name = ...)
1033
+ - Apollo Sandbox: http://localhost:3000/api/graphql
1034
+ - Supports Apollo Federation with federation: { enabled: true }
1035
+
1036
+ Now implement this setup.
1037
+ ```
1038
+
1039
+ </details>
1040
+
1041
+ <details>
1042
+ <summary>🔄 <strong>Add Feature to Existing Setup</strong></summary>
1043
+
1044
+ ```
1045
+ Add a complete blog posts feature to my nitro-graphql API following these specifications:
1046
+
1047
+ SCHEMA (server/graphql/posts/post.graphql):
1048
+ type Post {
1049
+ id: ID!
1050
+ title: String!
1051
+ content: String!
1052
+ authorId: ID!
1053
+ createdAt: String!
1054
+ }
1055
+
1056
+ input CreatePostInput {
1057
+ title: String!
1058
+ content: String!
1059
+ authorId: ID!
1060
+ }
1061
+
1062
+ input UpdatePostInput {
1063
+ title: String
1064
+ content: String
1065
+ }
1066
+
1067
+ extend type Query {
1068
+ posts(limit: Int = 10, offset: Int = 0): [Post!]!
1069
+ post(id: ID!): Post
1070
+ }
1071
+
1072
+ extend type Mutation {
1073
+ createPost(input: CreatePostInput!): Post!
1074
+ updatePost(id: ID!, input: UpdatePostInput!): Post
1075
+ deletePost(id: ID!): Boolean!
1076
+ }
1077
+
1078
+ RESOLVERS (server/graphql/posts/post.resolver.ts):
1079
+ // Use NAMED EXPORTS
1080
+ export const postQueries = defineQuery({
1081
+ posts: async (_, { limit, offset }, context) => {
1082
+ const posts = await context.storage?.getItem('posts') || []
1083
+ return posts.slice(offset, offset + limit)
1084
+ },
1085
+ post: async (_, { id }, context) => {
1086
+ const posts = await context.storage?.getItem('posts') || []
1087
+ return posts.find(p => p.id === id) || null
1088
+ }
1089
+ })
1090
+
1091
+ export const postMutations = defineMutation({
1092
+ createPost: async (_, { input }, context) => {
1093
+ const posts = await context.storage?.getItem('posts') || []
1094
+ const post = {
1095
+ id: Date.now().toString(),
1096
+ ...input,
1097
+ createdAt: new Date().toISOString()
1098
+ }
1099
+ posts.push(post)
1100
+ await context.storage?.setItem('posts', posts)
1101
+ return post
1102
+ },
1103
+ updatePost: async (_, { id, input }, context) => {
1104
+ const posts = await context.storage?.getItem('posts') || []
1105
+ const index = posts.findIndex(p => p.id === id)
1106
+ if (index === -1) return null
1107
+ posts[index] = { ...posts[index], ...input }
1108
+ await context.storage?.setItem('posts', posts)
1109
+ return posts[index]
1110
+ },
1111
+ deletePost: async (_, { id }, context) => {
1112
+ const posts = await context.storage?.getItem('posts') || []
1113
+ const filtered = posts.filter(p => p.id !== id)
1114
+ await context.storage?.setItem('posts', filtered)
1115
+ return filtered.length < posts.length
1116
+ }
1117
+ })
1118
+
1119
+ TYPE USAGE:
1120
+ After dev server restarts, types are auto-generated in:
1121
+ - .nitro/types/nitro-graphql-server.d.ts (server types)
1122
+ - .nuxt/types/nitro-graphql-server.d.ts (for Nuxt)
1123
+
1124
+ Import types:
1125
+ import type { Post, CreatePostInput } from '#graphql/server'
1126
+
1127
+ KEY RULES:
1128
+ - Use "extend type" to add to existing Query/Mutation
1129
+ - Named exports required
1130
+ - Context has H3 event properties
1131
+ - Types auto-generate on file changes
1132
+
1133
+ Now implement this feature.
1134
+ ```
1135
+
1136
+ </details>
1137
+
1138
+ ### Working with Your GraphQL API
1139
+
1140
+ Once set up, you can ask Claude Code for help with:
1141
+
1142
+ ```
1143
+ "Add authentication to my GraphQL resolvers"
1144
+ "Create a custom @auth directive for field-level permissions"
1145
+ "Set up type generation for client-side queries"
1146
+ "Add pagination to my users query"
1147
+ "Connect to an external GitHub GraphQL API"
1148
+ "Debug: my types aren't generating in .nitro/types/"
1149
+ "Optimize resolver performance using DataLoader"
1150
+ ```
1151
+
1152
+ ### Tips for Better Results
1153
+
1154
+ - **Start specific**: Include your framework (Nuxt/Nitro), version, and goal
1155
+ - **Reference docs**: Mention "following nitro-graphql conventions" to align with best practices
1156
+ - **Show errors**: Paste error messages for faster debugging
1157
+ - **Test iteratively**: Run `pnpm dev` after each change to verify
1158
+
368
1159
  ## 🛠️ Development
369
1160
 
370
1161
  ```bash