nitro-graphql 1.4.3 → 1.5.0

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
@@ -357,6 +357,94 @@ server/
357
357
  - ✅ Use correct path: `nitro-graphql/utils/define`
358
358
  - ✅ Use named exports in resolvers
359
359
 
360
+ **Vite: "Parse failure: Expected ';', '}' or <eof>" on GraphQL files**
361
+ - ✅ Add `graphql()` plugin from `nitro-graphql/vite`
362
+ - ✅ Ensure `graphql()` is placed **before** `nitro()` in plugins array
363
+ - ✅ Example:
364
+ ```ts
365
+ import { graphql } from 'nitro-graphql/vite'
366
+
367
+ export default defineConfig({
368
+ plugins: [
369
+ graphql(), // ← Must be first
370
+ nitro(),
371
+ ]
372
+ })
373
+ ```
374
+
375
+ **RollupError: "[exportName]" is not exported by "[file].resolver.ts"**
376
+
377
+ This error occurs when the resolver scanner can't find the expected export in your resolver file. Common causes:
378
+
379
+ 1. **Using default export instead of named export** ❌
380
+ ```ts
381
+ // ❌ WRONG - Will not be detected
382
+ export default defineQuery({
383
+ users: () => [...]
384
+ })
385
+ ```
386
+
387
+ ```ts
388
+ // ✅ CORRECT - Use named export
389
+ export const userQueries = defineQuery({
390
+ users: () => [...]
391
+ })
392
+ ```
393
+
394
+ 2. **Not using a define function** ❌
395
+ ```ts
396
+ // ❌ WRONG - Plain object won't be detected
397
+ export const resolvers = {
398
+ Query: {
399
+ users: () => [...]
400
+ }
401
+ }
402
+ ```
403
+
404
+ ```ts
405
+ // ✅ CORRECT - Use defineResolver, defineQuery, etc.
406
+ export const userResolver = defineResolver({
407
+ Query: {
408
+ users: () => [...]
409
+ }
410
+ })
411
+ ```
412
+
413
+ 3. **File naming doesn't match export** ❌
414
+ ```ts
415
+ // ❌ File: uploadFile.resolver.ts but export is named differently
416
+ export const fileUploader = defineMutation({...})
417
+ ```
418
+
419
+ ```ts
420
+ // ✅ CORRECT - Export name can be anything, as long as it uses a define function
421
+ export const uploadFile = defineMutation({...})
422
+ export const fileUploader = defineMutation({...}) // Both work!
423
+ ```
424
+
425
+ 4. **Syntax errors preventing parsing**
426
+ - Check for TypeScript compilation errors in the file
427
+ - Ensure imports are valid
428
+ - Verify no missing brackets or syntax issues
429
+
430
+ **How resolver scanning works:**
431
+ - The module uses `oxc-parser` to scan `.resolver.ts` files
432
+ - It looks for **named exports** using these functions:
433
+ - `defineResolver` - Complete resolver with Query, Mutation, etc.
434
+ - `defineQuery` - Query-only resolvers
435
+ - `defineMutation` - Mutation-only resolvers
436
+ - `defineType` - Custom type resolvers
437
+ - `defineSubscription` - Subscription resolvers
438
+ - `defineDirective` - Directive resolvers
439
+ - Only exports using these functions are included in the virtual module
440
+
441
+ **Debugging steps:**
442
+ 1. Check your resolver file uses named exports: `export const name = defineQuery({...})`
443
+ 2. Verify you're using one of the define functions listed above
444
+ 3. Look for TypeScript/syntax errors in the file
445
+ 4. Restart the dev server after fixing
446
+ 5. If issues persist, simplify the resolver to test (single query)
447
+
360
448
  </details>
361
449
 
362
450
  ## 🌟 Production Usage
@@ -365,6 +453,469 @@ This package powers production applications:
365
453
 
366
454
  - [**Nitroping**](https://github.com/productdevbook/nitroping) - Self-hosted push notification service
367
455
 
456
+ ## 🤖 Using Claude Code
457
+
458
+ Speed up development with [Claude Code](https://claude.ai/code) — AI-powered assistance for setting up and building with nitro-graphql.
459
+
460
+ ### Quick Setup Prompts
461
+
462
+ Copy and paste these prompts into Claude Code to scaffold a complete GraphQL API.
463
+
464
+ **💡 Tip**: After pasting, Claude Code will execute step-by-step and validate each action.
465
+
466
+ <details>
467
+ <summary>🟢 <strong>Nuxt Project</strong></summary>
468
+
469
+ ```
470
+ ## GOAL
471
+ Set up nitro-graphql in this Nuxt project with a User management GraphQL API.
472
+
473
+ ## PREREQUISITES
474
+ Check if this is a Nuxt project by looking for nuxt.config.ts in the root.
475
+
476
+ ## STEP 1: INSTALL DEPENDENCIES
477
+ Action: Run this command
478
+ Command: pnpm add nitro-graphql graphql-yoga graphql
479
+ Validation: Check package.json contains these packages
480
+
481
+ ## STEP 2: CONFIGURE NUXT
482
+ File: nuxt.config.ts
483
+ Action: EDIT (add to existing config, don't replace)
484
+ Add these properties:
485
+
486
+ export default defineNuxtConfig({
487
+ modules: ['nitro-graphql/nuxt'], // Add this module
488
+ nitro: {
489
+ graphql: {
490
+ framework: 'graphql-yoga',
491
+ },
492
+ },
493
+ })
494
+
495
+ Validation: Check the file has modules array and nitro.graphql config
496
+
497
+ ## STEP 3: CREATE SCHEMA
498
+ File: server/graphql/schema.graphql
499
+ Action: CREATE NEW FILE (create server/graphql/ directory if needed)
500
+ Content:
501
+
502
+ type User {
503
+ id: ID!
504
+ name: String!
505
+ email: String!
506
+ }
507
+
508
+ type Query {
509
+ users: [User!]!
510
+ user(id: ID!): User
511
+ }
512
+
513
+ type Mutation {
514
+ _empty: String
515
+ }
516
+
517
+ Validation: File should be in server/graphql/ directory
518
+
519
+ ## STEP 4: CREATE CONTEXT (Optional but recommended)
520
+ File: server/graphql/context.ts
521
+ Action: CREATE NEW FILE (auto-generated on first run, but create manually for clarity)
522
+ Content:
523
+
524
+ // Extend H3 event context with custom properties
525
+ declare module 'h3' {
526
+ interface H3EventContext {
527
+ // Add your custom context properties here
528
+ // Example:
529
+ // db?: Database
530
+ // auth?: { userId: string }
531
+ }
532
+ }
533
+
534
+ Note: This file lets you add custom properties to resolver context
535
+ Validation: File exists in server/graphql/
536
+
537
+ ## STEP 5: CREATE CONFIG (Optional)
538
+ File: server/graphql/config.ts
539
+ Action: CREATE NEW FILE (auto-generated, customize if needed)
540
+ Content:
541
+
542
+ // Custom GraphQL Yoga configuration
543
+ export default defineGraphQLConfig({
544
+ // Custom context enhancer, plugins, etc.
545
+ // See: https://the-guild.dev/graphql/yoga-server/docs
546
+ })
547
+
548
+ Note: Use this to customize GraphQL Yoga options
549
+ Validation: File exists in server/graphql/
550
+
551
+ ## STEP 6: CREATE RESOLVERS
552
+ File: server/graphql/users.resolver.ts
553
+ Action: CREATE NEW FILE
554
+ Content:
555
+
556
+ // ⚠️ CRITICAL: Use NAMED EXPORTS (not default export)
557
+ export const userQueries = defineQuery({
558
+ users: async (_, __, context) => {
559
+ // context is H3EventContext - access event, storage, etc.
560
+ return [
561
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
562
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
563
+ ]
564
+ },
565
+ user: async (_, { id }, context) => {
566
+ // Third parameter is context (H3EventContext)
567
+ const users = [
568
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
569
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
570
+ ]
571
+ return users.find(u => u.id === id) || null
572
+ }
573
+ })
574
+
575
+ Validation: File ends with .resolver.ts and uses named export
576
+
577
+ ## STEP 7: START DEV SERVER
578
+ Command: pnpm dev
579
+ Expected Output: Server starts on http://localhost:3000
580
+ Wait for: "Nitro built in X ms" message
581
+ Note: context.ts and config.ts will auto-generate if you skipped steps 4-5
582
+
583
+ ## VALIDATION CHECKLIST
584
+ - [ ] Navigate to http://localhost:3000/api/graphql - should show GraphQL playground
585
+ - [ ] Health check: http://localhost:3000/api/graphql/health - should return OK
586
+ - [ ] Run this query in playground:
587
+ ```graphql
588
+ query {
589
+ users {
590
+ id
591
+ name
592
+ email
593
+ }
594
+ }
595
+ ```
596
+ Expected: Returns 2 users
597
+ - [ ] Check .nuxt/types/nitro-graphql-server.d.ts exists (types auto-generated)
598
+
599
+ ## FILE STRUCTURE CREATED
600
+ ```
601
+ server/
602
+ graphql/
603
+ schema.graphql ← GraphQL type definitions
604
+ context.ts ← H3 event context augmentation (optional)
605
+ config.ts ← GraphQL Yoga config (optional)
606
+ users.resolver.ts ← Query resolvers
607
+ .nuxt/
608
+ types/
609
+ nitro-graphql-server.d.ts ← Auto-generated types
610
+ graphql.config.ts ← Auto-generated (for IDE tooling)
611
+ ```
612
+
613
+ ## CRITICAL RULES (MUST FOLLOW)
614
+ ❌ DO NOT use default exports in resolvers
615
+ Wrong: export default defineQuery({...})
616
+ Right: export const userQueries = defineQuery({...})
617
+
618
+ ❌ DO NOT name files without .resolver.ts extension
619
+ Wrong: users.ts or user-resolver.ts
620
+ Right: users.resolver.ts or user.resolver.ts
621
+
622
+ ✅ DO use named exports for all resolvers
623
+ ✅ DO place files in server/graphql/ directory
624
+ ✅ DO restart dev server if types don't generate
625
+
626
+ ## TROUBLESHOOTING
627
+ Issue: "GraphQL endpoint returns 404"
628
+ Fix: Ensure 'nitro-graphql/nuxt' is in modules array (not just 'nitro-graphql')
629
+
630
+ Issue: "defineQuery is not defined"
631
+ Fix: Restart dev server - auto-imports need to regenerate
632
+
633
+ Issue: "Types not generating"
634
+ Fix: Check .nuxt/types/nitro-graphql-server.d.ts exists, if not restart dev server
635
+
636
+ Issue: "Module not found: nitro-graphql"
637
+ Fix: Run pnpm install again, check package.json has the package
638
+
639
+ ## NEXT STEPS (After Setup Works)
640
+ 1. Add mutations: "Add createUser and deleteUser mutations with H3 storage"
641
+ 2. Extend context: "Add database connection to context.ts and use it in resolvers"
642
+ 3. Use types: "Import and use TypeScript types from #graphql/server in resolvers"
643
+ 4. Add auth: "Add authentication middleware using context in resolvers"
644
+ 5. Custom config: "Configure GraphQL Yoga plugins in config.ts"
645
+
646
+ Now implement this setup step-by-step.
647
+ ```
648
+
649
+ </details>
650
+
651
+ <details>
652
+ <summary>⚡ <strong>Nitro Project</strong></summary>
653
+
654
+ ```
655
+ Set up nitro-graphql in this Nitro project following these exact specifications:
656
+
657
+ INSTALLATION:
658
+ 1. Run: pnpm add nitro-graphql graphql-yoga graphql
659
+
660
+ CONFIGURATION (nitro.config.ts):
661
+ import { defineNitroConfig } from 'nitro/config'
662
+
663
+ export default defineNitroConfig({
664
+ modules: ['nitro-graphql'],
665
+ graphql: {
666
+ framework: 'graphql-yoga',
667
+ },
668
+ })
669
+
670
+ SCHEMA (server/graphql/schema.graphql):
671
+ type Product {
672
+ id: ID!
673
+ name: String!
674
+ price: Float!
675
+ }
676
+
677
+ input CreateProductInput {
678
+ name: String!
679
+ price: Float!
680
+ }
681
+
682
+ type Query {
683
+ products: [Product!]!
684
+ product(id: ID!): Product
685
+ }
686
+
687
+ type Mutation {
688
+ createProduct(input: CreateProductInput!): Product!
689
+ }
690
+
691
+ RESOLVERS (server/graphql/products.resolver.ts):
692
+ // Use NAMED EXPORTS only
693
+ export const productQueries = defineQuery({
694
+ products: async (_, __, context) => {
695
+ // Access H3 event context
696
+ const products = await context.storage?.getItem('products') || []
697
+ return products
698
+ },
699
+ product: async (_, { id }, context) => {
700
+ const products = await context.storage?.getItem('products') || []
701
+ return products.find(p => p.id === id)
702
+ }
703
+ })
704
+
705
+ export const productMutations = defineMutation({
706
+ createProduct: async (_, { input }, context) => {
707
+ const products = await context.storage?.getItem('products') || []
708
+ const product = {
709
+ id: Date.now().toString(),
710
+ ...input
711
+ }
712
+ products.push(product)
713
+ await context.storage?.setItem('products', products)
714
+ return product
715
+ }
716
+ })
717
+
718
+ KEY RULES:
719
+ - Files: *.graphql for schemas, *.resolver.ts for resolvers
720
+ - MUST use named exports (not default export)
721
+ - defineQuery and defineMutation are auto-imported
722
+ - Context is the third parameter (access H3 event context)
723
+ - Endpoint: http://localhost:3000/api/graphql
724
+
725
+ Now implement this setup.
726
+ ```
727
+
728
+ </details>
729
+
730
+ <details>
731
+ <summary>🎮 <strong>Apollo Server Setup</strong></summary>
732
+
733
+ ```
734
+ Set up nitro-graphql with Apollo Server following these exact specifications:
735
+
736
+ INSTALLATION:
737
+ 1. Run: pnpm add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
738
+
739
+ CONFIGURATION (nitro.config.ts):
740
+ import { defineNitroConfig } from 'nitro/config'
741
+
742
+ export default defineNitroConfig({
743
+ modules: ['nitro-graphql'],
744
+ graphql: {
745
+ framework: 'apollo-server',
746
+ },
747
+ })
748
+
749
+ SCHEMA (server/graphql/schema.graphql):
750
+ type Book {
751
+ id: ID!
752
+ title: String!
753
+ author: String!
754
+ }
755
+
756
+ type Query {
757
+ books: [Book!]!
758
+ book(id: ID!): Book
759
+ }
760
+
761
+ type Mutation {
762
+ addBook(title: String!, author: String!): Book!
763
+ }
764
+
765
+ RESOLVERS (server/graphql/books.resolver.ts):
766
+ // IMPORTANT: Use NAMED EXPORTS
767
+ export const bookResolver = defineResolver({
768
+ Query: {
769
+ books: async () => {
770
+ return [
771
+ { id: '1', title: '1984', author: 'George Orwell' }
772
+ ]
773
+ },
774
+ book: async (_, { id }) => {
775
+ return { id, title: '1984', author: 'George Orwell' }
776
+ }
777
+ },
778
+ Mutation: {
779
+ addBook: async (_, { title, author }) => {
780
+ return {
781
+ id: Date.now().toString(),
782
+ title,
783
+ author
784
+ }
785
+ }
786
+ }
787
+ })
788
+
789
+ KEY RULES:
790
+ - framework: 'apollo-server' in config
791
+ - defineResolver for complete resolver maps
792
+ - Named exports required (export const name = ...)
793
+ - Apollo Sandbox: http://localhost:3000/api/graphql
794
+ - Supports Apollo Federation with federation: { enabled: true }
795
+
796
+ Now implement this setup.
797
+ ```
798
+
799
+ </details>
800
+
801
+ <details>
802
+ <summary>🔄 <strong>Add Feature to Existing Setup</strong></summary>
803
+
804
+ ```
805
+ Add a complete blog posts feature to my nitro-graphql API following these specifications:
806
+
807
+ SCHEMA (server/graphql/posts/post.graphql):
808
+ type Post {
809
+ id: ID!
810
+ title: String!
811
+ content: String!
812
+ authorId: ID!
813
+ createdAt: String!
814
+ }
815
+
816
+ input CreatePostInput {
817
+ title: String!
818
+ content: String!
819
+ authorId: ID!
820
+ }
821
+
822
+ input UpdatePostInput {
823
+ title: String
824
+ content: String
825
+ }
826
+
827
+ extend type Query {
828
+ posts(limit: Int = 10, offset: Int = 0): [Post!]!
829
+ post(id: ID!): Post
830
+ }
831
+
832
+ extend type Mutation {
833
+ createPost(input: CreatePostInput!): Post!
834
+ updatePost(id: ID!, input: UpdatePostInput!): Post
835
+ deletePost(id: ID!): Boolean!
836
+ }
837
+
838
+ RESOLVERS (server/graphql/posts/post.resolver.ts):
839
+ // Use NAMED EXPORTS
840
+ export const postQueries = defineQuery({
841
+ posts: async (_, { limit, offset }, context) => {
842
+ const posts = await context.storage?.getItem('posts') || []
843
+ return posts.slice(offset, offset + limit)
844
+ },
845
+ post: async (_, { id }, context) => {
846
+ const posts = await context.storage?.getItem('posts') || []
847
+ return posts.find(p => p.id === id) || null
848
+ }
849
+ })
850
+
851
+ export const postMutations = defineMutation({
852
+ createPost: async (_, { input }, context) => {
853
+ const posts = await context.storage?.getItem('posts') || []
854
+ const post = {
855
+ id: Date.now().toString(),
856
+ ...input,
857
+ createdAt: new Date().toISOString()
858
+ }
859
+ posts.push(post)
860
+ await context.storage?.setItem('posts', posts)
861
+ return post
862
+ },
863
+ updatePost: async (_, { id, input }, context) => {
864
+ const posts = await context.storage?.getItem('posts') || []
865
+ const index = posts.findIndex(p => p.id === id)
866
+ if (index === -1) return null
867
+ posts[index] = { ...posts[index], ...input }
868
+ await context.storage?.setItem('posts', posts)
869
+ return posts[index]
870
+ },
871
+ deletePost: async (_, { id }, context) => {
872
+ const posts = await context.storage?.getItem('posts') || []
873
+ const filtered = posts.filter(p => p.id !== id)
874
+ await context.storage?.setItem('posts', filtered)
875
+ return filtered.length < posts.length
876
+ }
877
+ })
878
+
879
+ TYPE USAGE:
880
+ After dev server restarts, types are auto-generated in:
881
+ - .nitro/types/nitro-graphql-server.d.ts (server types)
882
+ - .nuxt/types/nitro-graphql-server.d.ts (for Nuxt)
883
+
884
+ Import types:
885
+ import type { Post, CreatePostInput } from '#graphql/server'
886
+
887
+ KEY RULES:
888
+ - Use "extend type" to add to existing Query/Mutation
889
+ - Named exports required
890
+ - Context has H3 event properties
891
+ - Types auto-generate on file changes
892
+
893
+ Now implement this feature.
894
+ ```
895
+
896
+ </details>
897
+
898
+ ### Working with Your GraphQL API
899
+
900
+ Once set up, you can ask Claude Code for help with:
901
+
902
+ ```
903
+ "Add authentication to my GraphQL resolvers"
904
+ "Create a custom @auth directive for field-level permissions"
905
+ "Set up type generation for client-side queries"
906
+ "Add pagination to my users query"
907
+ "Connect to an external GitHub GraphQL API"
908
+ "Debug: my types aren't generating in .nitro/types/"
909
+ "Optimize resolver performance using DataLoader"
910
+ ```
911
+
912
+ ### Tips for Better Results
913
+
914
+ - **Start specific**: Include your framework (Nuxt/Nitro), version, and goal
915
+ - **Reference docs**: Mention "following nitro-graphql conventions" to align with best practices
916
+ - **Show errors**: Paste error messages for faster debugging
917
+ - **Test iteratively**: Run `pnpm dev` after each change to verify
918
+
368
919
  ## 🛠️ Development
369
920
 
370
921
  ```bash
@@ -43,9 +43,7 @@ var nuxt_default = defineNuxtModule({
43
43
  nitroConfig.graphql.layerDirectories = layerDirectories;
44
44
  nitroConfig.graphql.layerServerDirs = layerServerDirs;
45
45
  nitroConfig.graphql.layerAppDirs = layerAppDirs;
46
- const appGraphqlDir = resolve(nuxt.options.rootDir, "app/graphql");
47
- const hasAppGraphqlDir = existsSync(appGraphqlDir);
48
- if (!hasAppGraphqlDir) {
46
+ if (!existsSync(resolve(nuxt.options.rootDir, "app/graphql"))) {
49
47
  const defaultDir = join(clientDir, "default");
50
48
  if (!existsSync(defaultDir)) mkdirSync(defaultDir, { recursive: true });
51
49
  const sampleQueryFile = join(defaultDir, "queries.graphql");
package/dist/index.js CHANGED
@@ -96,28 +96,62 @@ var src_default = defineNitroModule({
96
96
  nitro.hooks.hook("close", () => {
97
97
  watcher.close();
98
98
  });
99
- const tsConfigPath = resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath);
100
- const tsconfigDir = dirname(tsConfigPath);
99
+ const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
101
100
  const typesDir = resolve(nitro.options.buildDir, "types");
102
- const schemas = await scanSchemas(nitro);
103
- nitro.scanSchemas = schemas;
104
- const docs = await scanDocs(nitro);
105
- nitro.scanDocuments = docs;
106
- const resolvers = await scanResolvers(nitro);
107
- nitro.scanResolvers = resolvers;
101
+ nitro.scanSchemas = await scanSchemas(nitro);
102
+ nitro.scanDocuments = await scanDocs(nitro);
103
+ nitro.scanResolvers = await scanResolvers(nitro);
108
104
  const directives = await scanDirectives(nitro);
109
105
  nitro.scanDirectives = directives;
110
106
  await generateDirectiveSchemas(nitro, directives);
111
107
  nitro.hooks.hook("dev:start", async () => {
112
- const schemas$1 = await scanSchemas(nitro);
113
- nitro.scanSchemas = schemas$1;
114
- const resolvers$1 = await scanResolvers(nitro);
115
- nitro.scanResolvers = resolvers$1;
108
+ const schemas = await scanSchemas(nitro);
109
+ nitro.scanSchemas = schemas;
110
+ const resolvers = await scanResolvers(nitro);
111
+ nitro.scanResolvers = resolvers;
116
112
  const directives$1 = await scanDirectives(nitro);
117
113
  nitro.scanDirectives = directives$1;
118
114
  await generateDirectiveSchemas(nitro, directives$1);
119
- const docs$1 = await scanDocs(nitro);
120
- nitro.scanDocuments = docs$1;
115
+ const docs = await scanDocs(nitro);
116
+ nitro.scanDocuments = docs;
117
+ if (nitro.options.dev) {
118
+ consola.box({
119
+ title: "Nitro GraphQL",
120
+ message: [
121
+ `Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
122
+ `Schemas: ${schemas.length}`,
123
+ `Resolvers: ${resolvers.length}`,
124
+ `Directives: ${directives$1.length}`,
125
+ `Documents: ${docs.length}`,
126
+ "",
127
+ "Debug Dashboard: /_nitro/graphql/debug"
128
+ ].join("\n"),
129
+ style: {
130
+ borderColor: "cyan",
131
+ borderStyle: "rounded"
132
+ }
133
+ });
134
+ if (resolvers.length > 0) {
135
+ const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
136
+ const typeCount = {
137
+ query: 0,
138
+ mutation: 0,
139
+ resolver: 0,
140
+ type: 0,
141
+ subscription: 0,
142
+ directive: 0
143
+ };
144
+ for (const resolver of resolvers) for (const imp of resolver.imports) if (imp.type in typeCount) typeCount[imp.type]++;
145
+ const breakdown = [];
146
+ if (typeCount.query > 0) breakdown.push(`${typeCount.query} query`);
147
+ if (typeCount.mutation > 0) breakdown.push(`${typeCount.mutation} mutation`);
148
+ if (typeCount.resolver > 0) breakdown.push(`${typeCount.resolver} resolver`);
149
+ if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
150
+ if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
151
+ if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
152
+ if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
153
+ } else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
154
+ }
121
155
  });
122
156
  await rollupConfig(nitro);
123
157
  await serverTypeGeneration(nitro);
@@ -147,6 +181,14 @@ var src_default = defineNitroModule({
147
181
  handler: join(runtime, "health"),
148
182
  method: "get"
149
183
  });
184
+ if (nitro.options.dev) {
185
+ nitro.options.handlers.push({
186
+ route: "/_nitro/graphql/debug",
187
+ handler: join(runtime, "debug"),
188
+ method: "get"
189
+ });
190
+ consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
191
+ }
150
192
  if (nitro.options.imports) {
151
193
  nitro.options.imports.presets ??= [];
152
194
  nitro.options.imports.presets.push({
@@ -170,7 +212,6 @@ var src_default = defineNitroModule({
170
212
  if (id.endsWith(".graphql") || id.endsWith(".gql")) return "schemas";
171
213
  if (id.endsWith(".resolver.ts")) return "resolvers";
172
214
  if (typeof manualChunks === "function") return manualChunks(id, meta);
173
- return void 0;
174
215
  };
175
216
  rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
176
217
  if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;