nitro-graphql 1.2.3 → 1.3.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.
Files changed (150) hide show
  1. package/README.md +161 -3
  2. package/dist/graphql/index.js +1 -0
  3. package/dist/graphql/server.js +1 -0
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +11 -3
  6. package/dist/rollup.js +24 -0
  7. package/dist/routes/apollo-server.d.ts +2 -2
  8. package/dist/routes/apollo-server.js +16 -7
  9. package/dist/routes/graphql-yoga.js +14 -4
  10. package/dist/routes/health.d.ts +2 -2
  11. package/dist/types/index.d.ts +2 -1
  12. package/dist/utils/client-codegen.js +1 -1
  13. package/dist/utils/define.d.ts +52 -1
  14. package/dist/utils/define.js +33 -1
  15. package/dist/utils/directive-parser.d.ts +80 -0
  16. package/dist/utils/directive-parser.js +235 -0
  17. package/dist/utils/index.d.ts +3 -2
  18. package/dist/utils/index.js +42 -4
  19. package/dist/utils/type-generation.js +103 -6
  20. package/package.json +29 -18
  21. package/dist/_virtual/rolldown_runtime.js +0 -37
  22. package/dist/node_modules/.pnpm/@graphql-codegen_add@3.2.3_graphql@16.11.0/node_modules/@graphql-codegen/add/esm/config.js +0 -9
  23. package/dist/node_modules/.pnpm/@graphql-codegen_add@3.2.3_graphql@16.11.0/node_modules/@graphql-codegen/add/esm/index.js +0 -17
  24. package/dist/node_modules/.pnpm/@graphql-codegen_import-types-preset@3.0.1_graphql@16.11.0/node_modules/@graphql-codegen/import-types-preset/esm/index.js +0 -38
  25. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/federation.js +0 -22
  26. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/getCachedDocumentNodeFromSchema.js +0 -6
  27. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/helpers.js +0 -79
  28. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/index.js +0 -6
  29. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/oldVisit.js +0 -1
  30. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/resolve-external-module-and-fn.js +0 -7
  31. package/dist/node_modules/.pnpm/@graphql-codegen_plugin-helpers@3.1.2_graphql@16.11.0/node_modules/@graphql-codegen/plugin-helpers/esm/utils.js +0 -13
  32. package/dist/node_modules/.pnpm/camel-case@4.1.2/node_modules/camel-case/dist/index.js +0 -33
  33. package/dist/node_modules/.pnpm/capital-case@1.0.4/node_modules/capital-case/dist/index.js +0 -32
  34. package/dist/node_modules/.pnpm/change-case-all@1.0.15/node_modules/change-case-all/dist/index.js +0 -56
  35. package/dist/node_modules/.pnpm/change-case@4.1.2/node_modules/change-case/dist/index.js +0 -37
  36. package/dist/node_modules/.pnpm/constant-case@3.0.4/node_modules/constant-case/dist/index.js +0 -28
  37. package/dist/node_modules/.pnpm/dot-case@3.0.4/node_modules/dot-case/dist/index.js +0 -23
  38. package/dist/node_modules/.pnpm/header-case@2.0.4/node_modules/header-case/dist/index.js +0 -23
  39. package/dist/node_modules/.pnpm/is-lower-case@2.0.2/node_modules/is-lower-case/dist/index.js +0 -21
  40. package/dist/node_modules/.pnpm/is-upper-case@2.0.2/node_modules/is-upper-case/dist/index.js +0 -21
  41. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Hash.js +0 -37
  42. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_ListCache.js +0 -37
  43. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Map.js +0 -15
  44. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_MapCache.js +0 -37
  45. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Stack.js +0 -34
  46. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Symbol.js +0 -15
  47. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Uint8Array.js +0 -15
  48. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_apply.js +0 -30
  49. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_arrayLikeKeys.js +0 -35
  50. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_assignMergeValue.js +0 -26
  51. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_assignValue.js +0 -32
  52. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_assocIndexOf.js +0 -26
  53. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseAssignValue.js +0 -31
  54. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseCreate.js +0 -34
  55. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseFor.js +0 -25
  56. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseGetTag.js +0 -30
  57. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseIsArguments.js +0 -26
  58. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseIsNative.js +0 -44
  59. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseIsTypedArray.js +0 -32
  60. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseKeysIn.js +0 -32
  61. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseMerge.js +0 -42
  62. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseMergeDeep.js +0 -75
  63. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseRest.js +0 -26
  64. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseSetToString.js +0 -31
  65. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseTimes.js +0 -25
  66. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseUnary.js +0 -23
  67. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_cloneArrayBuffer.js +0 -25
  68. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_cloneBuffer.js +0 -35
  69. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_cloneTypedArray.js +0 -25
  70. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_copyArray.js +0 -25
  71. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_copyObject.js +0 -37
  72. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_coreJsData.js +0 -15
  73. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_createAssigner.js +0 -37
  74. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_createBaseFor.js +0 -28
  75. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_defineProperty.js +0 -20
  76. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_freeGlobal.js +0 -13
  77. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getMapData.js +0 -25
  78. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getNative.js +0 -26
  79. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getPrototype.js +0 -15
  80. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getRawTag.js +0 -43
  81. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getValue.js +0 -22
  82. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_hashClear.js +0 -24
  83. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_hashDelete.js +0 -26
  84. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_hashGet.js +0 -36
  85. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_hashHas.js +0 -30
  86. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_hashSet.js +0 -31
  87. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_initCloneObject.js +0 -25
  88. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_isIndex.js +0 -28
  89. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_isIterateeCall.js +0 -32
  90. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_isKeyable.js +0 -22
  91. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_isMasked.js +0 -28
  92. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_isPrototype.js +0 -24
  93. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_listCacheClear.js +0 -22
  94. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_listCacheDelete.js +0 -35
  95. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_listCacheGet.js +0 -26
  96. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_listCacheHas.js +0 -25
  97. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_listCacheSet.js +0 -31
  98. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_mapCacheClear.js +0 -30
  99. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_mapCacheDelete.js +0 -27
  100. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_mapCacheGet.js +0 -25
  101. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_mapCacheHas.js +0 -25
  102. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_mapCacheSet.js +0 -29
  103. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_nativeCreate.js +0 -14
  104. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_nativeKeysIn.js +0 -25
  105. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_nodeUtil.js +0 -29
  106. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_objectToString.js +0 -29
  107. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_overArg.js +0 -24
  108. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_overRest.js +0 -35
  109. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_root.js +0 -17
  110. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_safeGet.js +0 -24
  111. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_setToString.js +0 -23
  112. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_shortOut.js +0 -34
  113. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_stackClear.js +0 -24
  114. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_stackDelete.js +0 -25
  115. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_stackGet.js +0 -23
  116. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_stackHas.js +0 -23
  117. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_stackSet.js +0 -42
  118. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_toSource.js +0 -33
  119. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/constant.js +0 -35
  120. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/eq.js +0 -46
  121. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/identity.js +0 -30
  122. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isArguments.js +0 -43
  123. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isArray.js +0 -35
  124. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isArrayLike.js +0 -42
  125. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isArrayLikeObject.js +0 -42
  126. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isBuffer.js +0 -41
  127. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isFunction.js +0 -38
  128. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isLength.js +0 -42
  129. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObject.js +0 -40
  130. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObjectLike.js +0 -38
  131. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isPlainObject.js +0 -60
  132. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isTypedArray.js +0 -34
  133. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/keysIn.js +0 -41
  134. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/merge.js +0 -48
  135. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/stubFalse.js +0 -27
  136. package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/toPlainObject.js +0 -41
  137. package/dist/node_modules/.pnpm/lower-case-first@2.0.2/node_modules/lower-case-first/dist/index.js +0 -21
  138. package/dist/node_modules/.pnpm/lower-case@2.0.2/node_modules/lower-case/dist/index.js +0 -64
  139. package/dist/node_modules/.pnpm/no-case@3.0.4/node_modules/no-case/dist/index.js +0 -41
  140. package/dist/node_modules/.pnpm/param-case@3.0.4/node_modules/param-case/dist/index.js +0 -23
  141. package/dist/node_modules/.pnpm/pascal-case@3.1.2/node_modules/pascal-case/dist/index.js +0 -37
  142. package/dist/node_modules/.pnpm/path-case@3.0.4/node_modules/path-case/dist/index.js +0 -23
  143. package/dist/node_modules/.pnpm/sentence-case@3.0.4/node_modules/sentence-case/dist/index.js +0 -34
  144. package/dist/node_modules/.pnpm/snake-case@3.0.4/node_modules/snake-case/dist/index.js +0 -23
  145. package/dist/node_modules/.pnpm/sponge-case@1.0.1/node_modules/sponge-case/dist/index.js +0 -20
  146. package/dist/node_modules/.pnpm/swap-case@2.0.2/node_modules/swap-case/dist/index.js +0 -23
  147. package/dist/node_modules/.pnpm/title-case@3.0.3/node_modules/title-case/dist/index.js +0 -35
  148. package/dist/node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.js +0 -547
  149. package/dist/node_modules/.pnpm/upper-case-first@2.0.2/node_modules/upper-case-first/dist/index.js +0 -21
  150. package/dist/node_modules/.pnpm/upper-case@2.0.2/node_modules/upper-case/dist/index.js +0 -56
package/README.md CHANGED
@@ -30,6 +30,7 @@
30
30
  - 🔄 **Hot Reload**: Development mode with automatic schema and resolver updates
31
31
  - 📦 **Optimized Bundling**: Smart chunking and dynamic imports for production
32
32
  - 🌐 **Nuxt Integration**: First-class Nuxt.js support with dedicated module
33
+ - 🎭 **Custom Directives**: Create reusable GraphQL directives with automatic schema generation
33
34
  - 🔗 **Multi-Service Support**: Connect to multiple external GraphQL APIs alongside your main server
34
35
 
35
36
  ## 🎯 Used Projects
@@ -66,13 +67,13 @@ yarn add nitro-graphql graphql-yoga graphql
66
67
  **For Apollo Server:**
67
68
  ```bash
68
69
  # npm
69
- npm install nitro-graphql @apollo/server graphql
70
+ npm install nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
70
71
 
71
72
  # pnpm (recommended)
72
- pnpm add nitro-graphql @apollo/server graphql
73
+ pnpm add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
73
74
 
74
75
  # yarn
75
- yarn add nitro-graphql @apollo/server graphql
76
+ yarn add nitro-graphql @apollo/server @apollo/utils.withrequired @as-integrations/h3 graphql
76
77
  ```
77
78
 
78
79
  ### Step 2: Setup Your Project
@@ -195,6 +196,10 @@ server/
195
196
  ├── graphql/
196
197
  │ ├── schema.graphql # Main schema with scalars and base types
197
198
  │ ├── hello.resolver.ts # Global resolvers (use named exports)
199
+ │ ├── directives/ # Custom GraphQL directives
200
+ │ │ ├── auth.directive.ts # Authentication directive
201
+ │ │ ├── cache.directive.ts # Caching directive
202
+ │ │ └── validate.directive.ts # Validation directive
198
203
  │ ├── users/
199
204
  │ │ ├── user.graphql # User schema definitions
200
205
  │ │ ├── user-queries.resolver.ts # User query resolvers (use named exports)
@@ -629,6 +634,90 @@ export const postTypes = defineType({
629
634
 
630
635
  </details>
631
636
 
637
+ <details>
638
+ <summary><strong>defineDirective</strong> - Create custom GraphQL directives</summary>
639
+
640
+ ```ts
641
+ import { defineDirective } from 'nitro-graphql/utils/define'
642
+ import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils'
643
+ import { defaultFieldResolver, GraphQLError } from 'graphql'
644
+
645
+ export const authDirective = defineDirective({
646
+ name: 'auth',
647
+ locations: ['FIELD_DEFINITION', 'OBJECT'],
648
+ args: {
649
+ requires: {
650
+ type: 'String',
651
+ defaultValue: 'USER',
652
+ description: 'Required role to access this field',
653
+ },
654
+ },
655
+ description: 'Directive to check authentication and authorization',
656
+ transformer: (schema) => {
657
+ return mapSchema(schema, {
658
+ [MapperKind.OBJECT_FIELD]: (fieldConfig) => {
659
+ const authDirectiveConfig = getDirective(schema, fieldConfig, 'auth')?.[0]
660
+
661
+ if (authDirectiveConfig) {
662
+ const { resolve = defaultFieldResolver } = fieldConfig
663
+
664
+ fieldConfig.resolve = async function (source, args, context, info) {
665
+ if (!context.user) {
666
+ throw new GraphQLError('You must be logged in')
667
+ }
668
+
669
+ if (context.user.role !== authDirectiveConfig.requires) {
670
+ throw new GraphQLError('Insufficient permissions')
671
+ }
672
+
673
+ return resolve(source, args, context, info)
674
+ }
675
+ }
676
+
677
+ return fieldConfig
678
+ },
679
+ })
680
+ },
681
+ })
682
+ ```
683
+
684
+ **Usage in Schema:**
685
+ ```graphql
686
+ type User {
687
+ id: ID!
688
+ name: String!
689
+ email: String! @auth(requires: "ADMIN")
690
+ secretData: String @auth(requires: "SUPER_ADMIN")
691
+ }
692
+
693
+ type Query {
694
+ users: [User!]! @auth
695
+ adminStats: AdminStats @auth(requires: "ADMIN")
696
+ }
697
+ ```
698
+
699
+ **Available Argument Types:**
700
+ - Basic scalars: `String`, `Int`, `Float`, `Boolean`, `ID`, `JSON`, `DateTime`
701
+ - Non-nullable: `String!`, `Int!`, `Float!`, `Boolean!`, `ID!`, `JSON!`, `DateTime!`
702
+ - Arrays: `[String]`, `[String!]`, `[String]!`, `[String!]!` (and all combinations for other types)
703
+ - Custom types: Any string for your custom GraphQL types
704
+
705
+ **Helper Function:**
706
+ ```ts
707
+ export const validateDirective = defineDirective({
708
+ name: 'validate',
709
+ locations: ['FIELD_DEFINITION', 'ARGUMENT_DEFINITION'],
710
+ args: {
711
+ minLength: arg('Int', { description: 'Minimum length' }),
712
+ maxLength: arg('Int', { description: 'Maximum length' }),
713
+ pattern: arg('String', { description: 'Regex pattern' }),
714
+ },
715
+ // ... transformer implementation
716
+ })
717
+ ```
718
+
719
+ </details>
720
+
632
721
  <details>
633
722
  <summary><strong>defineSchema</strong> - Define custom schema with validation</summary>
634
723
 
@@ -755,6 +844,75 @@ export default defineNitroConfig({
755
844
 
756
845
  ## 🔥 Advanced Features
757
846
 
847
+ <details>
848
+ <summary><strong>Custom Directives</strong></summary>
849
+
850
+ Create reusable GraphQL directives with automatic schema generation:
851
+
852
+ ```ts
853
+ // server/graphql/directives/auth.directive.ts
854
+ import { defineDirective } from 'nitro-graphql/utils/define'
855
+ import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils'
856
+
857
+ export const authDirective = defineDirective({
858
+ name: 'auth',
859
+ locations: ['FIELD_DEFINITION', 'OBJECT'],
860
+ args: {
861
+ requires: {
862
+ type: 'String',
863
+ defaultValue: 'USER',
864
+ description: 'Required role to access this field',
865
+ },
866
+ },
867
+ description: 'Authentication and authorization directive',
868
+ transformer: (schema) => {
869
+ return mapSchema(schema, {
870
+ [MapperKind.OBJECT_FIELD]: (fieldConfig) => {
871
+ const authConfig = getDirective(schema, fieldConfig, 'auth')?.[0]
872
+ if (authConfig) {
873
+ // Transform field resolvers to check authentication
874
+ const { resolve = defaultFieldResolver } = fieldConfig
875
+ fieldConfig.resolve = async (source, args, context, info) => {
876
+ if (!context.user || context.user.role !== authConfig.requires) {
877
+ throw new GraphQLError('Access denied')
878
+ }
879
+ return resolve(source, args, context, info)
880
+ }
881
+ }
882
+ return fieldConfig
883
+ },
884
+ })
885
+ },
886
+ })
887
+ ```
888
+
889
+ **Common Directive Examples:**
890
+ - `@auth(requires: "ADMIN")` - Role-based authentication
891
+ - `@cache(ttl: 300, scope: "PUBLIC")` - Field-level caching
892
+ - `@rateLimit(limit: 10, window: 60)` - Rate limiting
893
+ - `@validate(minLength: 5, maxLength: 100)` - Input validation
894
+ - `@transform(upper: true, trim: true)` - Data transformation
895
+ - `@permission(roles: ["ADMIN", "MODERATOR"])` - Multi-role permissions
896
+
897
+ **Usage in Schema:**
898
+ ```graphql
899
+ type User {
900
+ id: ID!
901
+ name: String!
902
+ email: String! @auth(requires: "ADMIN")
903
+ posts: [Post!]! @cache(ttl: 300)
904
+ }
905
+
906
+ type Query {
907
+ users: [User!]! @rateLimit(limit: 100, window: 3600)
908
+ sensitiveData: String @auth(requires: "SUPER_ADMIN")
909
+ }
910
+ ```
911
+
912
+ The module automatically generates the directive schema definitions and integrates them with both GraphQL Yoga and Apollo Server.
913
+
914
+ </details>
915
+
758
916
  <details>
759
917
  <summary><strong>Custom Scalars</strong></summary>
760
918
 
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { StandardSchemaV1 } from "./types/standard-schema.js";
2
2
  import { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions } from "./types/index.js";
3
- import * as nitropack5 from "nitropack";
3
+ import * as nitropack0 from "nitropack";
4
4
 
5
5
  //#region src/index.d.ts
6
- declare const _default: nitropack5.NitroModule;
6
+ declare const _default: nitropack0.NitroModule;
7
7
  //#endregion
8
8
  export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions, StandardSchemaV1, _default as default };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import { relativeWithDot, scanDocs, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.js";
1
+ import { generateDirectiveSchemas } from "./utils/directive-parser.js";
2
+ import { relativeWithDot, scanDirectives, scanDocs, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.js";
2
3
  import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.js";
3
4
  import { rollupConfig } from "./rollup.js";
4
5
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
@@ -79,7 +80,7 @@ var src_default = defineNitroModule({
79
80
  const watcher = watch(watchDirs, {
80
81
  persistent: true,
81
82
  ignoreInitial: true,
82
- ignored: nitro.options.ignore
83
+ ignored: [...nitro.options.ignore, "**/server/graphql/_directives.graphql"]
83
84
  }).on("all", async (event, path) => {
84
85
  if (path.endsWith(".graphql") || path.endsWith(".gql")) await clientTypeGeneration(nitro);
85
86
  });
@@ -95,11 +96,17 @@ var src_default = defineNitroModule({
95
96
  nitro.scanDocuments = docs;
96
97
  const resolvers = await scanResolvers(nitro);
97
98
  nitro.scanResolvers = resolvers;
99
+ const directives = await scanDirectives(nitro);
100
+ nitro.scanDirectives = directives;
101
+ await generateDirectiveSchemas(nitro, directives);
98
102
  nitro.hooks.hook("dev:start", async () => {
99
103
  const schemas$1 = await scanSchemas(nitro);
100
104
  nitro.scanSchemas = schemas$1;
101
105
  const resolvers$1 = await scanResolvers(nitro);
102
106
  nitro.scanResolvers = resolvers$1;
107
+ const directives$1 = await scanDirectives(nitro);
108
+ nitro.scanDirectives = directives$1;
109
+ await generateDirectiveSchemas(nitro, directives$1);
103
110
  const docs$1 = await scanDocs(nitro);
104
111
  nitro.scanDocuments = docs$1;
105
112
  });
@@ -142,7 +149,8 @@ var src_default = defineNitroModule({
142
149
  "defineSubscription",
143
150
  "defineType",
144
151
  "defineGraphQLConfig",
145
- "defineSchema"
152
+ "defineSchema",
153
+ "defineDirective"
146
154
  ]
147
155
  });
148
156
  }
package/dist/rollup.js CHANGED
@@ -9,6 +9,7 @@ import { genImport } from "knitwork";
9
9
  async function rollupConfig(app) {
10
10
  virtualSchemas(app);
11
11
  virtualResolvers(app);
12
+ virtualDirectives(app);
12
13
  getGraphQLConfig(app);
13
14
  app.hooks.hook("rollup:before", (nitro, rollupConfig$1) => {
14
15
  rollupConfig$1.plugins = rollupConfig$1.plugins || [];
@@ -85,6 +86,29 @@ function virtualResolvers(app) {
85
86
  return code;
86
87
  };
87
88
  }
89
+ function virtualDirectives(app) {
90
+ const getDirectives = () => {
91
+ const directives = [...app.scanDirectives || []];
92
+ return directives;
93
+ };
94
+ app.options.virtual ??= {};
95
+ app.options.virtual["#nitro-internal-virtual/server-directives"] = () => {
96
+ const imports = getDirectives();
97
+ const importsContent = [...imports.map(({ specifier, imports: imports$1, options }) => {
98
+ return genImport(specifier, imports$1, options);
99
+ })];
100
+ const data = imports.map(({ imports: imports$1 }) => imports$1.map((i) => `{ directive: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n");
101
+ const content = [
102
+ "export const directives = [",
103
+ data,
104
+ "]",
105
+ ""
106
+ ];
107
+ content.unshift(...importsContent);
108
+ const code = content.join("\n");
109
+ return code;
110
+ };
111
+ }
88
112
  function getGraphQLConfig(app) {
89
113
  const configPath = resolve(app.graphql.serverDir, "config.ts");
90
114
  app.options.virtual ??= {};
@@ -1,6 +1,6 @@
1
- import * as h31 from "h3";
1
+ import * as h30 from "h3";
2
2
 
3
3
  //#region src/routes/apollo-server.d.ts
4
- declare const _default: h31.EventHandler<h31.EventHandlerRequest, any>;
4
+ declare const _default: h30.EventHandler<h30.EventHandlerRequest, any>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -2,21 +2,31 @@ import { startServerAndCreateH3Handler } from "../utils/apollo.js";
2
2
  import defu from "defu";
3
3
  import { mergeResolvers, mergeTypeDefs } from "@graphql-tools/merge";
4
4
  import { importedConfig } from "#nitro-internal-virtual/graphql-config";
5
+ import { directives } from "#nitro-internal-virtual/server-directives";
5
6
  import { resolvers } from "#nitro-internal-virtual/server-resolvers";
6
7
  import { schemas } from "#nitro-internal-virtual/server-schemas";
7
8
  import { ApolloServer } from "@apollo/server";
8
9
  import { ApolloServerPluginLandingPageLocalDefault } from "@apollo/server/plugin/landingPage/default";
10
+ import { makeExecutableSchema } from "@graphql-tools/schema";
9
11
 
10
12
  //#region src/routes/apollo-server.ts
11
13
  function createMergedSchema() {
12
14
  try {
13
- const mergedSchemas = schemas.map((schema) => schema.def).join("\n\n");
14
- const typeDefs = mergeTypeDefs([mergedSchemas]);
15
+ const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
16
+ const typeDefs = mergeTypeDefs([mergedSchemas], {
17
+ throwOnConflict: true,
18
+ commentDescriptions: true,
19
+ sort: true
20
+ });
15
21
  const mergedResolvers = mergeResolvers(resolvers.map((r) => r.resolver));
16
- return {
22
+ let schema = makeExecutableSchema({
17
23
  typeDefs,
18
24
  resolvers: mergedResolvers
19
- };
25
+ });
26
+ if (directives && directives.length > 0) {
27
+ for (const { directive } of directives) if (directive.transformer) schema = directive.transformer(schema);
28
+ }
29
+ return schema;
20
30
  } catch (error) {
21
31
  console.error("Schema merge error:", error);
22
32
  throw error;
@@ -25,10 +35,9 @@ function createMergedSchema() {
25
35
  let apolloServer = null;
26
36
  function createApolloServer() {
27
37
  if (!apolloServer) {
28
- const { typeDefs, resolvers: mergedResolvers } = createMergedSchema();
38
+ const schema = createMergedSchema();
29
39
  apolloServer = new ApolloServer(defu({
30
- typeDefs,
31
- resolvers: mergedResolvers,
40
+ schema,
32
41
  introspection: true,
33
42
  plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })]
34
43
  }, importedConfig));
@@ -1,10 +1,12 @@
1
1
  import defu from "defu";
2
2
  import { mergeResolvers, mergeTypeDefs } from "@graphql-tools/merge";
3
3
  import { importedConfig } from "#nitro-internal-virtual/graphql-config";
4
+ import { directives } from "#nitro-internal-virtual/server-directives";
4
5
  import { resolvers } from "#nitro-internal-virtual/server-resolvers";
5
6
  import { schemas } from "#nitro-internal-virtual/server-schemas";
7
+ import { makeExecutableSchema } from "@graphql-tools/schema";
6
8
  import { defineEventHandler, toWebRequest } from "h3";
7
- import { createSchema, createYoga } from "graphql-yoga";
9
+ import { createYoga } from "graphql-yoga";
8
10
 
9
11
  //#region src/routes/graphql-yoga.ts
10
12
  const apolloSandboxHtml = `<!DOCTYPE html>
@@ -26,13 +28,21 @@ new window.EmbeddedSandbox({
26
28
  </html>`;
27
29
  function createMergedSchema() {
28
30
  try {
29
- const mergedSchemas = schemas.map((schema) => schema.def).join("\n\n");
30
- const typeDefs = mergeTypeDefs([mergedSchemas]);
31
+ const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
32
+ const typeDefs = mergeTypeDefs([mergedSchemas], {
33
+ throwOnConflict: true,
34
+ commentDescriptions: true,
35
+ sort: true
36
+ });
31
37
  const mergedResolvers = mergeResolvers(resolvers.map((r) => r.resolver));
32
- return createSchema({
38
+ let schema = makeExecutableSchema({
33
39
  typeDefs,
34
40
  resolvers: mergedResolvers
35
41
  });
42
+ if (directives && directives.length > 0) {
43
+ for (const { directive } of directives) if (directive.transformer) schema = directive.transformer(schema);
44
+ }
45
+ return schema;
36
46
  } catch (error) {
37
47
  console.error("Schema merge error:", error);
38
48
  throw error;
@@ -1,7 +1,7 @@
1
- import * as h36 from "h3";
1
+ import * as h31 from "h3";
2
2
 
3
3
  //#region src/routes/health.d.ts
4
- declare const _default: h36.EventHandler<h36.EventHandlerRequest, Promise<{
4
+ declare const _default: h31.EventHandler<h31.EventHandlerRequest, Promise<{
5
5
  status: string;
6
6
  message: string;
7
7
  timestamp: string;
@@ -20,7 +20,7 @@ type CodegenClientConfig = TypeScriptPluginConfig & TypeScriptDocumentsPluginCon
20
20
  interface IESMImport {
21
21
  name: string;
22
22
  as?: string;
23
- type: 'resolver' | 'query' | 'mutation' | 'type' | 'subscription';
23
+ type: 'resolver' | 'query' | 'mutation' | 'type' | 'subscription' | 'directive';
24
24
  }
25
25
  interface GenImport {
26
26
  specifier: string;
@@ -32,6 +32,7 @@ declare module 'nitropack/types' {
32
32
  scanSchemas: string[];
33
33
  scanDocuments: string[];
34
34
  scanResolvers: GenImport[];
35
+ scanDirectives: GenImport[];
35
36
  graphql: {
36
37
  buildDir: string;
37
38
  watchDirs: string[];
@@ -1,4 +1,3 @@
1
- import { preset } from "../node_modules/.pnpm/@graphql-codegen_import-types-preset@3.0.1_graphql@16.11.0/node_modules/@graphql-codegen/import-types-preset/esm/index.js";
2
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
2
  import { consola as consola$1 } from "consola";
4
3
  import { defu as defu$1 } from "defu";
@@ -7,6 +6,7 @@ import { parse } from "graphql";
7
6
  import { printSchemaWithDirectives } from "@graphql-tools/utils";
8
7
  import { createHash } from "node:crypto";
9
8
  import { codegen } from "@graphql-codegen/core";
9
+ import { preset } from "@graphql-codegen/import-types-preset";
10
10
  import { plugin } from "@graphql-codegen/typescript";
11
11
  import { plugin as plugin$1 } from "@graphql-codegen/typescript-generic-sdk";
12
12
  import { plugin as plugin$2 } from "@graphql-codegen/typescript-operations";
@@ -1,3 +1,4 @@
1
+ import { GraphQLSchema } from "graphql";
1
2
  import { ApolloServerOptions } from "@apollo/server";
2
3
  import { H3Event } from "h3";
3
4
  import { YogaServerOptions } from "graphql-yoga";
@@ -17,5 +18,55 @@ declare function defineSubscription(resolvers?: Resolvers['Subscription']): Reso
17
18
  declare function defineType(resolvers: Resolvers): Resolvers;
18
19
  type DefineServerConfig<T extends NPMConfig = NPMConfig> = T['framework'] extends 'graphql-yoga' ? Partial<YogaServerOptions<H3Event, Partial<H3Event>>> : T['framework'] extends 'apollo-server' ? Partial<ApolloServerOptions<H3Event>> : Partial<YogaServerOptions<H3Event, Partial<H3Event>>> | Partial<ApolloServerOptions<H3Event>>;
19
20
  declare function defineGraphQLConfig<T extends NPMConfig = NPMConfig>(config: Partial<DefineServerConfig<T>>): Partial<DefineServerConfig<T>>;
21
+ type DirectiveLocationName = 'QUERY' | 'MUTATION' | 'SUBSCRIPTION' | 'FIELD' | 'FRAGMENT_DEFINITION' | 'FRAGMENT_SPREAD' | 'INLINE_FRAGMENT' | 'VARIABLE_DEFINITION' | 'SCHEMA' | 'SCALAR' | 'OBJECT' | 'FIELD_DEFINITION' | 'ARGUMENT_DEFINITION' | 'INTERFACE' | 'UNION' | 'ENUM' | 'ENUM_VALUE' | 'INPUT_OBJECT' | 'INPUT_FIELD_DEFINITION';
22
+ type GraphQLScalarType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID' | 'JSON' | 'DateTime';
23
+ type GraphQLBaseType = GraphQLScalarType | (string & {});
24
+ type GraphQLArgumentType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID' | 'JSON' | 'DateTime' | 'String!' | 'Int!' | 'Float!' | 'Boolean!' | 'ID!' | 'JSON!' | 'DateTime!' | '[String]' | '[String!]' | '[String]!' | '[String!]!' | '[Int]' | '[Int!]' | '[Int]!' | '[Int!]!' | '[Float]' | '[Float!]' | '[Float]!' | '[Float!]!' | '[Boolean]' | '[Boolean!]' | '[Boolean]!' | '[Boolean!]!' | '[ID]' | '[ID!]' | '[ID]!' | '[ID!]!' | '[JSON]' | '[JSON!]' | '[JSON]!' | '[JSON!]!' | '[DateTime]' | '[DateTime!]' | '[DateTime]!' | '[DateTime!]!' | (string & {});
25
+ interface DirectiveArgument<T extends GraphQLArgumentType = GraphQLArgumentType> {
26
+ /**
27
+ * GraphQL type for the argument
28
+ * @example 'String', 'Int!', '[String!]!', 'DateTime', 'JSON'
29
+ */
30
+ type: T;
31
+ defaultValue?: any;
32
+ description?: string;
33
+ }
34
+ interface DirectiveArg {
35
+ type: GraphQLArgumentType;
36
+ defaultValue?: any;
37
+ description?: string;
38
+ }
39
+ interface DirectiveDefinition {
40
+ name: string;
41
+ locations: DirectiveLocationName[];
42
+ args?: Record<string, DirectiveArg>;
43
+ description?: string;
44
+ isRepeatable?: boolean;
45
+ transformer?: (schema: GraphQLSchema) => GraphQLSchema;
46
+ }
47
+ interface DefineDirectiveConfig {
48
+ name: string;
49
+ locations: ReadonlyArray<DirectiveLocationName>;
50
+ args?: Record<string, {
51
+ type: GraphQLArgumentType;
52
+ defaultValue?: any;
53
+ description?: string;
54
+ }>;
55
+ description?: string;
56
+ isRepeatable?: boolean;
57
+ transformer?: (schema: GraphQLSchema) => GraphQLSchema;
58
+ }
59
+ /**
60
+ * Helper function to create directive arguments with proper type inference
61
+ * @example
62
+ * args: {
63
+ * myArg: arg('String!', { defaultValue: 'hello' })
64
+ * }
65
+ */
66
+ declare function arg<T extends GraphQLArgumentType>(type: T, options?: {
67
+ defaultValue?: any;
68
+ description?: string;
69
+ }): DirectiveArgument<T>;
70
+ declare function defineDirective(config: DefineDirectiveConfig): DirectiveDefinition;
20
71
  //#endregion
21
- export { DefineServerConfig, ResolverQuery, defineGraphQLConfig, defineMutation, defineQuery, defineResolver, defineSchema, defineSubscription, defineType };
72
+ export { DefineDirectiveConfig, DefineServerConfig, DirectiveArgument, DirectiveDefinition, GraphQLArgumentType, GraphQLBaseType, GraphQLScalarType, ResolverQuery, arg, defineDirective, defineGraphQLConfig, defineMutation, defineQuery, defineResolver, defineSchema, defineSubscription, defineType };
@@ -20,6 +20,38 @@ function defineType(resolvers) {
20
20
  function defineGraphQLConfig(config) {
21
21
  return config;
22
22
  }
23
+ /**
24
+ * Helper function to create directive arguments with proper type inference
25
+ * @example
26
+ * args: {
27
+ * myArg: arg('String!', { defaultValue: 'hello' })
28
+ * }
29
+ */
30
+ function arg(type, options) {
31
+ return {
32
+ type,
33
+ ...options
34
+ };
35
+ }
36
+ function defineDirective(config) {
37
+ const args = config.args ? Object.entries(config.args).map(([name, arg$1]) => {
38
+ const defaultValue = arg$1.defaultValue !== void 0 ? ` = ${JSON.stringify(arg$1.defaultValue)}` : "";
39
+ return `${name}: ${arg$1.type}${defaultValue}`;
40
+ }).join(", ") : "";
41
+ const argsString = args ? `(${args})` : "";
42
+ const locations = config.locations.join(" | ");
43
+ const schemaDefinition = `directive @${config.name}${argsString} on ${locations}`;
44
+ Object.defineProperty(config, "__schema", {
45
+ value: schemaDefinition,
46
+ enumerable: false,
47
+ configurable: false,
48
+ writable: false
49
+ });
50
+ return {
51
+ ...config,
52
+ locations: [...config.locations]
53
+ };
54
+ }
23
55
 
24
56
  //#endregion
25
- export { defineGraphQLConfig, defineMutation, defineQuery, defineResolver, defineSchema, defineSubscription, defineType };
57
+ export { arg, defineDirective, defineGraphQLConfig, defineMutation, defineQuery, defineResolver, defineSchema, defineSubscription, defineType };
@@ -0,0 +1,80 @@
1
+ //#region src/utils/directive-parser.d.ts
2
+ interface ParsedDirective {
3
+ name: string;
4
+ locations: string[];
5
+ args?: Record<string, {
6
+ type: string;
7
+ defaultValue?: any;
8
+ }>;
9
+ description?: string;
10
+ isRepeatable?: boolean;
11
+ }
12
+ /**
13
+ * Clean AST-based directive parser using oxc-parser
14
+ */
15
+ declare class DirectiveParser {
16
+ private oxc;
17
+ init(): Promise<void>;
18
+ /**
19
+ * Parse directives from a TypeScript/JavaScript file
20
+ */
21
+ parseDirectives(fileContent: string, filePath: string): Promise<ParsedDirective[]>;
22
+ /**
23
+ * Extract directive definitions from AST
24
+ */
25
+ private extractDirectiveDefinitions;
26
+ /**
27
+ * Traverse AST nodes recursively
28
+ */
29
+ private traverse;
30
+ /**
31
+ * Check if node is a defineDirective call
32
+ */
33
+ private isDefineDirectiveCall;
34
+ /**
35
+ * Extract directive configuration from defineDirective call
36
+ */
37
+ private extractDirectiveFromCall;
38
+ /**
39
+ * Extract directive properties from object expression
40
+ */
41
+ private extractDirectiveFromObject;
42
+ /**
43
+ * Extract string literal value
44
+ */
45
+ private extractStringLiteral;
46
+ /**
47
+ * Extract boolean literal value
48
+ */
49
+ private extractBooleanLiteral;
50
+ /**
51
+ * Extract array of strings
52
+ */
53
+ private extractStringArray;
54
+ /**
55
+ * Extract arguments object
56
+ */
57
+ private extractArgsObject;
58
+ /**
59
+ * Extract argument configuration
60
+ */
61
+ private extractArgConfig;
62
+ /**
63
+ * Extract literal value (string, number, boolean)
64
+ */
65
+ private extractLiteralValue;
66
+ }
67
+ /**
68
+ * Generate GraphQL directive schema from parsed directive
69
+ */
70
+ declare function generateDirectiveSchema(directive: ParsedDirective): string;
71
+ /**
72
+ * Generate directive schemas file from scanned directives
73
+ */
74
+ declare function generateDirectiveSchemas(nitro: any, directives: any[]): Promise<void>;
75
+ /**
76
+ * Singleton instance for reuse
77
+ */
78
+ declare const directiveParser: DirectiveParser;
79
+ //#endregion
80
+ export { DirectiveParser, ParsedDirective, directiveParser, generateDirectiveSchema, generateDirectiveSchemas };