nitro-graphql 2.0.0-beta.37 → 2.0.0-beta.39

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 (204) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/commands/generate.d.mts +26 -0
  3. package/dist/cli/commands/generate.mjs +196 -0
  4. package/dist/cli/commands/index.d.mts +4 -0
  5. package/dist/cli/commands/index.mjs +5 -0
  6. package/dist/cli/commands/init.d.mts +43 -0
  7. package/dist/cli/commands/init.mjs +191 -0
  8. package/dist/cli/commands/validate.d.mts +10 -0
  9. package/dist/cli/commands/validate.mjs +69 -0
  10. package/dist/cli/completions.d.mts +7 -0
  11. package/dist/cli/completions.mjs +34 -0
  12. package/dist/cli/config.d.mts +75 -0
  13. package/dist/cli/config.mjs +20 -0
  14. package/dist/cli/index.d.mts +24 -0
  15. package/dist/cli/index.mjs +253 -0
  16. package/dist/core/codegen/client.d.mts +23 -0
  17. package/dist/core/codegen/client.mjs +150 -0
  18. package/dist/core/codegen/document-loader.d.mts +10 -0
  19. package/dist/core/codegen/document-loader.mjs +18 -0
  20. package/dist/core/codegen/index.d.mts +8 -0
  21. package/dist/core/codegen/index.mjs +9 -0
  22. package/dist/{utils/codegen-plugin.d.mts → core/codegen/plugin.d.mts} +2 -2
  23. package/dist/{utils/codegen-plugin.mjs → core/codegen/plugin.mjs} +1 -1
  24. package/dist/core/codegen/runtime.d.mts +20 -0
  25. package/dist/core/codegen/runtime.mjs +60 -0
  26. package/dist/core/codegen/schema-loader.d.mts +28 -0
  27. package/dist/core/codegen/schema-loader.mjs +128 -0
  28. package/dist/core/codegen/server.d.mts +28 -0
  29. package/dist/core/codegen/server.mjs +143 -0
  30. package/dist/{codegen → core/codegen}/validation.d.mts +1 -1
  31. package/dist/{codegen → core/codegen}/validation.mjs +1 -1
  32. package/dist/core/config.d.mts +50 -0
  33. package/dist/core/config.mjs +82 -0
  34. package/dist/core/constants.d.mts +188 -0
  35. package/dist/core/constants.mjs +210 -0
  36. package/dist/core/index.d.mts +32 -0
  37. package/dist/core/index.mjs +26 -0
  38. package/dist/core/scanning/ast-scanner.d.mts +23 -0
  39. package/dist/core/scanning/ast-scanner.mjs +103 -0
  40. package/dist/core/scanning/common.d.mts +37 -0
  41. package/dist/core/scanning/common.mjs +60 -0
  42. package/dist/core/scanning/directives.d.mts +10 -0
  43. package/dist/core/scanning/directives.mjs +29 -0
  44. package/dist/core/scanning/documents.d.mts +21 -0
  45. package/dist/core/scanning/documents.mjs +43 -0
  46. package/dist/core/scanning/index.d.mts +7 -0
  47. package/dist/core/scanning/index.mjs +8 -0
  48. package/dist/core/scanning/resolvers.d.mts +10 -0
  49. package/dist/core/scanning/resolvers.mjs +58 -0
  50. package/dist/core/scanning/schemas.d.mts +14 -0
  51. package/dist/core/scanning/schemas.mjs +64 -0
  52. package/dist/{utils/schema-builder.d.mts → core/schema/builder.d.mts} +7 -2
  53. package/dist/{utils/schema-builder.mjs → core/schema/builder.mjs} +22 -3
  54. package/dist/{utils → core/schema}/federation.d.mts +10 -5
  55. package/dist/{utils → core/schema}/federation.mjs +1 -1
  56. package/dist/core/schema/index.d.mts +3 -0
  57. package/dist/core/schema/index.mjs +4 -0
  58. package/dist/core/types/adapter.d.mts +58 -0
  59. package/dist/core/types/codegen.d.mts +133 -0
  60. package/dist/core/types/config.d.mts +212 -0
  61. package/dist/{types → core/types}/define.d.mts +3 -7
  62. package/dist/core/types/index.d.mts +5 -0
  63. package/dist/core/types/scanning.d.mts +69 -0
  64. package/dist/core/types/scanning.mjs +1 -0
  65. package/dist/{utils → core/utils}/directive-parser.d.mts +21 -5
  66. package/dist/{utils → core/utils}/directive-parser.mjs +25 -36
  67. package/dist/{utils → core/utils}/errors.d.mts +8 -4
  68. package/dist/{utils → core/utils}/errors.mjs +8 -4
  69. package/dist/core/utils/file-io.d.mts +24 -0
  70. package/dist/core/utils/file-io.mjs +47 -0
  71. package/dist/{utils → core/utils}/imports.d.mts +1 -1
  72. package/dist/{utils → core/utils}/imports.mjs +1 -1
  73. package/dist/core/utils/index.d.mts +7 -0
  74. package/dist/core/utils/index.mjs +8 -0
  75. package/dist/core/utils/logger.d.mts +19 -0
  76. package/dist/core/utils/logger.mjs +38 -0
  77. package/dist/{utils → core/utils}/ofetch-templates.d.mts +1 -1
  78. package/dist/{utils → core/utils}/ofetch-templates.mjs +1 -1
  79. package/dist/core/validation/external-services.d.mts +11 -0
  80. package/dist/{utils/validation.mjs → core/validation/external-services.mjs} +3 -3
  81. package/dist/core/validation/index.d.mts +2 -0
  82. package/dist/core/validation/index.mjs +3 -0
  83. package/dist/define.d.mts +2 -4
  84. package/dist/define.mjs +1 -1
  85. package/dist/index.d.mts +6 -44
  86. package/dist/index.mjs +5 -62
  87. package/dist/nitro/adapter.d.mts +30 -0
  88. package/dist/nitro/adapter.mjs +97 -0
  89. package/dist/{utils → nitro}/apollo.d.mts +1 -1
  90. package/dist/{utils → nitro}/apollo.mjs +1 -1
  91. package/dist/nitro/codegen.d.mts +19 -0
  92. package/dist/nitro/codegen.mjs +141 -0
  93. package/dist/nitro/config.d.mts +52 -0
  94. package/dist/nitro/config.mjs +58 -0
  95. package/dist/nitro/index.d.mts +46 -0
  96. package/dist/nitro/index.mjs +65 -0
  97. package/dist/{utils/path-resolver.d.mts → nitro/paths.d.mts} +3 -19
  98. package/dist/{utils/path-resolver.mjs → nitro/paths.mjs} +2 -36
  99. package/dist/{rollup.d.mts → nitro/rollup.d.mts} +1 -1
  100. package/dist/{rollup.mjs → nitro/rollup.mjs} +11 -23
  101. package/dist/{routes → nitro/routes}/apollo-server.d.mts +1 -1
  102. package/dist/{routes → nitro/routes}/apollo-server.mjs +5 -5
  103. package/dist/{routes → nitro/routes}/debug-template.d.mts +1 -1
  104. package/dist/{routes → nitro/routes}/debug-template.mjs +1 -1
  105. package/dist/{routes → nitro/routes}/debug.d.mts +10 -16
  106. package/dist/{routes → nitro/routes}/debug.mjs +2 -2
  107. package/dist/{routes → nitro/routes}/graphql-yoga.d.mts +1 -1
  108. package/dist/{routes → nitro/routes}/graphql-yoga.mjs +3 -3
  109. package/dist/{routes → nitro/routes}/health.d.mts +1 -1
  110. package/dist/{routes → nitro/routes}/health.mjs +1 -1
  111. package/dist/nitro/setup/file-watcher.d.mts +16 -0
  112. package/dist/{setup → nitro/setup}/file-watcher.mjs +14 -18
  113. package/dist/{setup.d.mts → nitro/setup/logging.d.mts} +5 -6
  114. package/dist/nitro/setup/logging.mjs +66 -0
  115. package/dist/nitro/setup/rollup-integration.d.mts +16 -0
  116. package/dist/{setup → nitro/setup}/rollup-integration.mjs +2 -2
  117. package/dist/nitro/setup/routes.d.mts +10 -0
  118. package/dist/nitro/setup/routes.mjs +35 -0
  119. package/dist/nitro/setup/ts-config.d.mts +11 -0
  120. package/dist/{setup → nitro/setup}/ts-config.mjs +3 -3
  121. package/dist/nitro/setup.d.mts +12 -0
  122. package/dist/{setup.mjs → nitro/setup.mjs} +33 -100
  123. package/dist/{types/index.d.mts → nitro/types.d.mts} +125 -43
  124. package/dist/nitro/types.mjs +1 -0
  125. package/dist/nitro/virtual/generators.d.mts +31 -0
  126. package/dist/nitro/virtual/generators.mjs +193 -0
  127. package/dist/nitro/virtual/stubs.d.mts +20 -0
  128. package/dist/nitro/virtual/stubs.mjs +31 -0
  129. package/dist/{ecosystem/nuxt.d.mts → nuxt.d.mts} +1 -1
  130. package/dist/{ecosystem/nuxt.mjs → nuxt.mjs} +2 -2
  131. package/dist/{graphql/server.d.mts → stubs/index.d.mts} +5 -1
  132. package/dist/stubs/index.mjs +1 -0
  133. package/package.json +45 -42
  134. package/dist/codegen/client-types.d.mts +0 -13
  135. package/dist/codegen/client-types.mjs +0 -131
  136. package/dist/codegen/external-types.d.mts +0 -12
  137. package/dist/codegen/external-types.mjs +0 -88
  138. package/dist/codegen/index.d.mts +0 -18
  139. package/dist/codegen/index.mjs +0 -24
  140. package/dist/codegen/server-types.d.mts +0 -13
  141. package/dist/codegen/server-types.mjs +0 -64
  142. package/dist/config/defaults.mjs +0 -36
  143. package/dist/constants/scalars.mjs +0 -27
  144. package/dist/constants.mjs +0 -106
  145. package/dist/graphql/index.d.mts +0 -5
  146. package/dist/setup/graphql-scanner.mjs +0 -25
  147. package/dist/setup/scaffold-generator.mjs +0 -109
  148. package/dist/types/standard-schema.d.mts +0 -59
  149. package/dist/utils/client-codegen.d.mts +0 -41
  150. package/dist/utils/client-codegen.mjs +0 -277
  151. package/dist/utils/file-generator.d.mts +0 -37
  152. package/dist/utils/file-generator.mjs +0 -72
  153. package/dist/utils/file-writer.d.mts +0 -35
  154. package/dist/utils/file-writer.mjs +0 -32
  155. package/dist/utils/index.d.mts +0 -13
  156. package/dist/utils/index.mjs +0 -13
  157. package/dist/utils/layers.d.mts +0 -22
  158. package/dist/utils/layers.mjs +0 -28
  159. package/dist/utils/scanning/common.d.mts +0 -23
  160. package/dist/utils/scanning/common.mjs +0 -39
  161. package/dist/utils/scanning/directives.d.mts +0 -11
  162. package/dist/utils/scanning/directives.mjs +0 -43
  163. package/dist/utils/scanning/documents.d.mts +0 -15
  164. package/dist/utils/scanning/documents.mjs +0 -46
  165. package/dist/utils/scanning/index.d.mts +0 -6
  166. package/dist/utils/scanning/index.mjs +0 -7
  167. package/dist/utils/scanning/resolvers.d.mts +0 -11
  168. package/dist/utils/scanning/resolvers.mjs +0 -100
  169. package/dist/utils/scanning/schemas.d.mts +0 -15
  170. package/dist/utils/scanning/schemas.mjs +0 -29
  171. package/dist/utils/server-codegen.d.mts +0 -7
  172. package/dist/utils/server-codegen.mjs +0 -113
  173. package/dist/utils/type-generation.d.mts +0 -6
  174. package/dist/utils/type-generation.mjs +0 -7
  175. package/dist/utils/validation.d.mts +0 -11
  176. package/dist/virtual/debug-info.d.mts +0 -9
  177. package/dist/virtual/debug-info.mjs +0 -26
  178. package/dist/virtual/generators/config.d.mts +0 -22
  179. package/dist/virtual/generators/config.mjs +0 -36
  180. package/dist/virtual/generators/debug.d.mts +0 -14
  181. package/dist/virtual/generators/debug.mjs +0 -53
  182. package/dist/virtual/generators/directives.d.mts +0 -14
  183. package/dist/virtual/generators/directives.mjs +0 -52
  184. package/dist/virtual/generators/index.d.mts +0 -6
  185. package/dist/virtual/generators/index.mjs +0 -7
  186. package/dist/virtual/generators/resolvers.d.mts +0 -14
  187. package/dist/virtual/generators/resolvers.mjs +0 -55
  188. package/dist/virtual/generators/schemas.d.mts +0 -14
  189. package/dist/virtual/generators/schemas.mjs +0 -43
  190. package/dist/virtual/graphql-config.d.mts +0 -9
  191. package/dist/virtual/graphql-config.mjs +0 -10
  192. package/dist/virtual/module-config.d.mts +0 -9
  193. package/dist/virtual/module-config.mjs +0 -10
  194. package/dist/virtual/server-directives.d.mts +0 -11
  195. package/dist/virtual/server-directives.mjs +0 -10
  196. package/dist/virtual/server-resolvers.d.mts +0 -11
  197. package/dist/virtual/server-resolvers.mjs +0 -10
  198. package/dist/virtual/server-schemas.d.mts +0 -11
  199. package/dist/virtual/server-schemas.mjs +0 -10
  200. /package/dist/{graphql/index.mjs → core/types/adapter.mjs} +0 -0
  201. /package/dist/{graphql/server.mjs → core/types/codegen.mjs} +0 -0
  202. /package/dist/{types/define.mjs → core/types/config.mjs} +0 -0
  203. /package/dist/{types/index.mjs → core/types/define.mjs} +0 -0
  204. /package/dist/{types/standard-schema.mjs → core/types/index.mjs} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="./.docs/public/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
3
+ <img src="./.github/assets/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
4
4
 
5
5
  # Nitro GraphQL
6
6
 
@@ -633,7 +633,7 @@ import { defineResolver, defineQuery, defineMutation, defineField, defineDirecti
633
633
  | `defineGraphQLConfig` | GraphQL server config | `defineGraphQLConfig({ maskedErrors: {...} })` |
634
634
  | `defineSchema` | Schema with Zod integration | `defineSchema({ Book: selectBookSchema })` |
635
635
 
636
- **Additional Utilities** from `nitro-graphql/utils`:
636
+ **Additional Utilities** from `nitro-graphql/core`:
637
637
  - `createDefaultMaskError()` - Error handler for ZodError and HTTPError (use in `defineGraphQLConfig`)
638
638
 
639
639
  ### Type Generation
@@ -0,0 +1,26 @@
1
+ import { CLIContext } from "../index.mjs";
2
+
3
+ //#region src/cli/commands/generate.d.ts
4
+
5
+ /**
6
+ * Generate all types (server + client + optional runtime)
7
+ */
8
+ declare function generateAll(ctx: CLIContext, options?: {
9
+ silent?: boolean;
10
+ watch?: boolean;
11
+ runtime?: boolean;
12
+ }): Promise<void>;
13
+ /**
14
+ * Generate server types
15
+ */
16
+ declare function generateServer(ctx: CLIContext, options?: {
17
+ silent?: boolean;
18
+ }): Promise<void>;
19
+ /**
20
+ * Generate client types
21
+ */
22
+ declare function generateClient(ctx: CLIContext, options?: {
23
+ silent?: boolean;
24
+ }): Promise<void>;
25
+ //#endregion
26
+ export { generateAll, generateClient, generateServer };
@@ -0,0 +1,196 @@
1
+ import { LOG_TAG } from "../../core/constants.mjs";
2
+ import { loadGraphQLDocuments } from "../../core/codegen/document-loader.mjs";
3
+ import { generateClientTypesCore } from "../../core/codegen/client.mjs";
4
+ import { generateResolverModule, generateRuntimeIndex, generateSchemaModule } from "../../core/codegen/runtime.mjs";
5
+ import { generateServerTypesCore } from "../../core/codegen/server.mjs";
6
+ import { scanDocumentsCore } from "../../core/scanning/documents.mjs";
7
+ import { scanResolversCore } from "../../core/scanning/resolvers.mjs";
8
+ import { scanSchemasCore } from "../../core/scanning/schemas.mjs";
9
+ import { buildGraphQLSchema } from "../../core/schema/builder.mjs";
10
+ import consola from "consola";
11
+ import { dirname, join, relative } from "pathe";
12
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
13
+
14
+ //#region src/cli/commands/generate.ts
15
+ const logger = consola.withTag(LOG_TAG);
16
+ /**
17
+ * Create ScanContext from CLI context
18
+ */
19
+ function createScanContext(ctx) {
20
+ return {
21
+ rootDir: ctx.config.rootDir,
22
+ serverDir: ctx.config.serverDir,
23
+ clientDir: ctx.config.clientDir,
24
+ ignorePatterns: ctx.config.ignore,
25
+ isDev: false,
26
+ logger: {
27
+ info: (msg, ...args) => logger.info(msg, ...args),
28
+ warn: (msg, ...args) => logger.warn(msg, ...args),
29
+ error: (msg, ...args) => logger.error(msg, ...args),
30
+ success: (msg, ...args) => logger.success(msg, ...args),
31
+ debug: (msg, ...args) => logger.debug(msg, ...args)
32
+ },
33
+ layerServerDirs: [],
34
+ layerAppDirs: []
35
+ };
36
+ }
37
+ /**
38
+ * Generate all types (server + client + optional runtime)
39
+ */
40
+ async function generateAll(ctx, options = {}) {
41
+ await generateServer(ctx, options);
42
+ await generateClient(ctx, options);
43
+ if (options.runtime) await generateRuntimeFiles(ctx, options);
44
+ if (options.watch) await watchAndRegenerate(ctx, options);
45
+ }
46
+ /**
47
+ * Generate server types
48
+ */
49
+ async function generateServer(ctx, options = {}) {
50
+ const schemaResult = await scanSchemasCore(createScanContext(ctx));
51
+ if (schemaResult.errors.length > 0) for (const error of schemaResult.errors) logger.error(error);
52
+ if (schemaResult.items.length === 0) {
53
+ if (!options.silent) logger.info("No GraphQL schemas found in server directory");
54
+ return;
55
+ }
56
+ const schema = await buildGraphQLSchema(schemaResult.items);
57
+ if (!schema) {
58
+ logger.error("Failed to build GraphQL schema");
59
+ return;
60
+ }
61
+ const result = await generateServerTypesCore({
62
+ framework: ctx.config.framework,
63
+ schema,
64
+ config: ctx.config.codegen?.server,
65
+ federationEnabled: ctx.config.federation?.enabled
66
+ });
67
+ const schemaPath = join(ctx.config.buildDir, "schema.graphql");
68
+ mkdirSync(dirname(schemaPath), { recursive: true });
69
+ writeFileSync(schemaPath, result.schemaString, "utf-8");
70
+ const typesPath = join(ctx.config.typesDir, "nitro-graphql-server.d.ts");
71
+ mkdirSync(dirname(typesPath), { recursive: true });
72
+ writeFileSync(typesPath, result.types, "utf-8");
73
+ if (!options.silent) logger.success(`Generated server types: ${relative(ctx.config.rootDir, typesPath)}`);
74
+ }
75
+ /**
76
+ * Generate client types
77
+ */
78
+ async function generateClient(ctx, options = {}) {
79
+ const scanCtx = createScanContext(ctx);
80
+ const schemaPath = join(ctx.config.buildDir, "schema.graphql");
81
+ if (!existsSync(schemaPath)) {
82
+ if (!options.silent) logger.info("Server schema not found. Generate server types first.");
83
+ return;
84
+ }
85
+ const docsResult = await scanDocumentsCore(scanCtx, { externalServices: ctx.config.externalServices });
86
+ if (docsResult.errors.length > 0) for (const error of docsResult.errors) logger.error(error);
87
+ if (docsResult.items.length === 0) {
88
+ if (!options.silent) logger.info("No GraphQL documents found in client directory");
89
+ return;
90
+ }
91
+ const documents = await loadGraphQLDocuments(docsResult.items);
92
+ const { buildSchema } = await import("graphql");
93
+ const { readFileSync: readFileSync$1 } = await import("node:fs");
94
+ const result = await generateClientTypesCore({
95
+ schema: buildSchema(readFileSync$1(schemaPath, "utf-8")),
96
+ documents,
97
+ config: ctx.config.codegen?.client,
98
+ sdkConfig: ctx.config.codegen?.clientSDK,
99
+ options: { silent: options.silent }
100
+ });
101
+ if (result === false) {
102
+ if (!options.silent) logger.warn("Client type generation skipped");
103
+ return;
104
+ }
105
+ const typesPath = join(ctx.config.typesDir, "nitro-graphql-client.d.ts");
106
+ mkdirSync(dirname(typesPath), { recursive: true });
107
+ writeFileSync(typesPath, result.types, "utf-8");
108
+ const sdkPath = join(ctx.config.clientDir, "default", "sdk.ts");
109
+ mkdirSync(dirname(sdkPath), { recursive: true });
110
+ writeFileSync(sdkPath, result.sdk, "utf-8");
111
+ if (!options.silent) logger.success(`Generated client types: ${relative(ctx.config.rootDir, typesPath)}`);
112
+ }
113
+ /**
114
+ * Generate runtime files (resolvers.ts, schema.ts, index.ts)
115
+ */
116
+ async function generateRuntimeFiles(ctx, options = {}) {
117
+ const scanCtx = createScanContext(ctx);
118
+ const runtimeConfig = ctx.config.runtime;
119
+ const runtimeDir = typeof runtimeConfig === "object" && runtimeConfig.outDir ? join(ctx.config.rootDir, runtimeConfig.outDir) : join(ctx.config.buildDir, "runtime");
120
+ mkdirSync(runtimeDir, { recursive: true });
121
+ const include = typeof runtimeConfig === "object" && runtimeConfig.include ? runtimeConfig.include : {
122
+ resolvers: true,
123
+ schema: true,
124
+ index: true
125
+ };
126
+ if (include.resolvers !== false) {
127
+ const resolversResult = await scanResolversCore(scanCtx);
128
+ if (resolversResult.items.length > 0) {
129
+ const resolverCode = generateResolverModule(resolversResult.items, runtimeDir);
130
+ writeFileSync(join(runtimeDir, "resolvers.ts"), resolverCode, "utf-8");
131
+ if (!options.silent) logger.success(`Generated runtime: ${relative(ctx.config.rootDir, join(runtimeDir, "resolvers.ts"))}`);
132
+ } else if (!options.silent) logger.info("No resolvers found for runtime generation");
133
+ }
134
+ if (include.schema !== false) {
135
+ const schemaPath = join(ctx.config.buildDir, "schema.graphql");
136
+ if (existsSync(schemaPath)) {
137
+ const { readFileSync: readFileSync$1 } = await import("node:fs");
138
+ const schemaCode = generateSchemaModule(readFileSync$1(schemaPath, "utf-8"));
139
+ writeFileSync(join(runtimeDir, "schema.ts"), schemaCode, "utf-8");
140
+ if (!options.silent) logger.success(`Generated runtime: ${relative(ctx.config.rootDir, join(runtimeDir, "schema.ts"))}`);
141
+ } else if (!options.silent) logger.info("Schema not found for runtime generation. Run generate first.");
142
+ }
143
+ if (include.index !== false) {
144
+ const indexCode = generateRuntimeIndex();
145
+ writeFileSync(join(runtimeDir, "index.ts"), indexCode, "utf-8");
146
+ if (!options.silent) logger.success(`Generated runtime: ${relative(ctx.config.rootDir, join(runtimeDir, "index.ts"))}`);
147
+ }
148
+ }
149
+ /**
150
+ * Watch mode - regenerate on file changes
151
+ */
152
+ async function watchAndRegenerate(ctx, options = {}) {
153
+ const { watch } = await import("chokidar");
154
+ const watchDirs = [ctx.config.serverDir, ctx.config.clientDir];
155
+ const watcher = watch(watchDirs, {
156
+ ignoreInitial: true,
157
+ ignored: [
158
+ ...ctx.config.ignore || [],
159
+ /node_modules/,
160
+ /\.git/
161
+ ],
162
+ persistent: true
163
+ });
164
+ await new Promise((resolve$1) => {
165
+ watcher.on("ready", resolve$1);
166
+ watcher.on("error", (error) => logger.error("Watcher error:", error));
167
+ });
168
+ const relPath = (p) => relative(ctx.config.rootDir, p) || ".";
169
+ logger.info(`Watching: ${watchDirs.map(relPath).join(", ")}`);
170
+ let debounceTimer = null;
171
+ const debounceMs = ctx.config.watch?.debounce ?? 300;
172
+ watcher.on("all", (event, filePath) => {
173
+ if (!filePath.endsWith(".graphql") && !filePath.endsWith(".resolver.ts")) return;
174
+ if (debounceTimer) clearTimeout(debounceTimer);
175
+ debounceTimer = setTimeout(async () => {
176
+ try {
177
+ await generateAll(ctx, {
178
+ silent: options.silent ?? true,
179
+ watch: false
180
+ });
181
+ logger.success(`Types regenerated (${relPath(filePath)})`);
182
+ } catch (error) {
183
+ logger.error("Regeneration failed:", error);
184
+ }
185
+ }, debounceMs);
186
+ });
187
+ await new Promise((resolve$1) => {
188
+ process.on("SIGINT", () => {
189
+ watcher.close();
190
+ resolve$1();
191
+ });
192
+ });
193
+ }
194
+
195
+ //#endregion
196
+ export { generateAll, generateClient, generateServer };
@@ -0,0 +1,4 @@
1
+ import { generateAll, generateClient, generateServer } from "./generate.mjs";
2
+ import { init } from "./init.mjs";
3
+ import { validate } from "./validate.mjs";
4
+ export { generateAll, generateClient, generateServer, init, validate };
@@ -0,0 +1,5 @@
1
+ import { init } from "./init.mjs";
2
+ import { generateAll, generateClient, generateServer } from "./generate.mjs";
3
+ import { validate } from "./validate.mjs";
4
+
5
+ export { generateAll, generateClient, generateServer, init, validate };
@@ -0,0 +1,43 @@
1
+ import { CLIContext } from "../index.mjs";
2
+
3
+ //#region src/cli/commands/init.d.ts
4
+
5
+ /**
6
+ * Available templates from the examples directory
7
+ */
8
+ declare const AVAILABLE_TEMPLATES: readonly [{
9
+ readonly name: "drizzle-orm";
10
+ readonly description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL";
11
+ }, {
12
+ readonly name: "vite";
13
+ readonly description: "Vite + Nitro GraphQL integration";
14
+ }, {
15
+ readonly name: "vite-react";
16
+ readonly description: "Vite + React + Nitro GraphQL";
17
+ }, {
18
+ readonly name: "vite-vue";
19
+ readonly description: "Vite + Vue + Nitro GraphQL";
20
+ }, {
21
+ readonly name: "better-auth";
22
+ readonly description: "Nitro + GraphQL + Better Auth integration";
23
+ }];
24
+ type TemplateName = typeof AVAILABLE_TEMPLATES[number]['name'];
25
+ /**
26
+ * List available templates
27
+ */
28
+ declare function listTemplates(): void;
29
+ /**
30
+ * Initialize project from template
31
+ */
32
+ declare function initFromTemplate(projectName: string, templateName: string, options?: {
33
+ force?: boolean;
34
+ cwd?: string;
35
+ }): Promise<void>;
36
+ /**
37
+ * Initialize project structure (basic scaffolding)
38
+ */
39
+ declare function init(ctx: CLIContext, options?: {
40
+ force?: boolean;
41
+ }): Promise<void>;
42
+ //#endregion
43
+ export { AVAILABLE_TEMPLATES, TemplateName, init, initFromTemplate, listTemplates };
@@ -0,0 +1,191 @@
1
+ import { LOG_TAG } from "../../core/constants.mjs";
2
+ import consola from "consola";
3
+ import { basename, join, relative, resolve } from "pathe";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { downloadTemplate } from "giget";
6
+
7
+ //#region src/cli/commands/init.ts
8
+ const logger = consola.withTag(LOG_TAG);
9
+ /**
10
+ * Available templates from the examples directory
11
+ */
12
+ const AVAILABLE_TEMPLATES = [
13
+ {
14
+ name: "drizzle-orm",
15
+ description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL"
16
+ },
17
+ {
18
+ name: "vite",
19
+ description: "Vite + Nitro GraphQL integration"
20
+ },
21
+ {
22
+ name: "vite-react",
23
+ description: "Vite + React + Nitro GraphQL"
24
+ },
25
+ {
26
+ name: "vite-vue",
27
+ description: "Vite + Vue + Nitro GraphQL"
28
+ },
29
+ {
30
+ name: "better-auth",
31
+ description: "Nitro + GraphQL + Better Auth integration"
32
+ }
33
+ ];
34
+ /**
35
+ * Default GitHub template source
36
+ */
37
+ const DEFAULT_TEMPLATE_REGISTRY = "github:productdevbook/nitro-graphql/examples";
38
+ /**
39
+ * List available templates
40
+ */
41
+ function listTemplates() {
42
+ logger.info("Available templates:\n");
43
+ for (const template of AVAILABLE_TEMPLATES) console.log(` ${template.name.padEnd(15)} - ${template.description}`);
44
+ console.log("\nUsage:");
45
+ console.log(" nitro-graphql init <project-name> --template <template-name>");
46
+ console.log(" nitro-graphql init my-app -t drizzle-orm");
47
+ console.log("\nCustom templates:");
48
+ console.log(" nitro-graphql init my-app -t gh:user/repo");
49
+ console.log(" nitro-graphql init my-app -t github:user/repo/subdir");
50
+ }
51
+ /**
52
+ * Initialize project from template
53
+ */
54
+ async function initFromTemplate(projectName, templateName, options = {}) {
55
+ const { force, cwd = process.cwd() } = options;
56
+ const targetDir = resolve(cwd, projectName);
57
+ if (existsSync(targetDir) && !force) {
58
+ logger.error(`Directory "${projectName}" already exists. Use --force to overwrite.`);
59
+ process.exit(1);
60
+ }
61
+ let templateSource;
62
+ if (templateName.includes(":") || templateName.includes("/")) templateSource = templateName;
63
+ else {
64
+ if (!AVAILABLE_TEMPLATES.find((t) => t.name === templateName)) {
65
+ logger.error(`Unknown template: "${templateName}"`);
66
+ logger.info("Use --list to see available templates");
67
+ process.exit(1);
68
+ }
69
+ templateSource = `${DEFAULT_TEMPLATE_REGISTRY}/${templateName}`;
70
+ }
71
+ logger.info(`Downloading template: ${templateName}`);
72
+ logger.debug(`Source: ${templateSource}`);
73
+ try {
74
+ const result = await downloadTemplate(templateSource, {
75
+ dir: targetDir,
76
+ force
77
+ });
78
+ logger.success(`Template downloaded to: ${result.dir}`);
79
+ const packageJsonPath = join(targetDir, "package.json");
80
+ if (existsSync(packageJsonPath)) try {
81
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
82
+ packageJson.name = basename(projectName).replace(/[^a-z0-9-]/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "my-graphql-app";
83
+ writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf-8");
84
+ logger.debug(`Updated package.json name to: ${packageJson.name}`);
85
+ } catch {
86
+ logger.warn("Could not update package.json name");
87
+ }
88
+ console.log("");
89
+ logger.info("Next steps:");
90
+ console.log(` cd ${projectName}`);
91
+ console.log(" pnpm install");
92
+ console.log(" pnpm dev");
93
+ console.log("");
94
+ } catch (error) {
95
+ logger.error("Failed to download template:", error);
96
+ process.exit(1);
97
+ }
98
+ }
99
+ /**
100
+ * Initialize project structure (basic scaffolding)
101
+ */
102
+ async function init(ctx, options = {}) {
103
+ const { force } = options;
104
+ const dirs = [ctx.config.serverDir, ctx.config.clientDir];
105
+ for (const dir of dirs) if (!existsSync(dir)) {
106
+ mkdirSync(dir, { recursive: true });
107
+ logger.info(`Created directory: ${dir}`);
108
+ }
109
+ const configPath = join(ctx.config.rootDir, "nitro-graphql.config.ts");
110
+ if (force || !existsSync(configPath)) {
111
+ const relativeServerDir = relative(ctx.config.rootDir, ctx.config.serverDir) || "server/graphql";
112
+ const relativeClientDir = relative(ctx.config.rootDir, ctx.config.clientDir) || "graphql";
113
+ writeFileSync(configPath, `import { defineConfig } from 'nitro-graphql/cli'
114
+
115
+ export default defineConfig({
116
+ framework: '${ctx.config.framework}',
117
+ serverDir: './${relativeServerDir}',
118
+ clientDir: './${relativeClientDir}',
119
+ })
120
+ `, "utf-8");
121
+ logger.success(`Created config file: ${configPath}`);
122
+ } else logger.info(`Config file already exists: ${configPath}`);
123
+ const tsconfigPath = join(ctx.config.rootDir, "tsconfig.json");
124
+ if (force || !existsSync(tsconfigPath)) {
125
+ const relativeBuildDir = relative(ctx.config.rootDir, ctx.config.buildDir) || ".graphql";
126
+ writeFileSync(tsconfigPath, `{
127
+ "compilerOptions": {
128
+ "target": "ESNext",
129
+ "module": "ESNext",
130
+ "moduleResolution": "Bundler",
131
+ "resolveJsonModule": true,
132
+ "allowSyntheticDefaultImports": true,
133
+ "strict": true,
134
+ "noEmit": true,
135
+ "skipLibCheck": true,
136
+ "forceConsistentCasingInFileNames": true,
137
+ "paths": {
138
+ "#graphql/server": ["./${relativeBuildDir}/types/nitro-graphql-server.d.ts"],
139
+ "#graphql/client": ["./${relativeBuildDir}/types/nitro-graphql-client.d.ts"],
140
+ "#graphql/schema": ["./${relative(ctx.config.rootDir, ctx.config.serverDir) || "server/graphql"}/schema.ts"]
141
+ }
142
+ },
143
+ "include": ["**/*.ts"],
144
+ "exclude": ["node_modules", "${relativeBuildDir}"]
145
+ }
146
+ `, "utf-8");
147
+ logger.success(`Created tsconfig.json: ${tsconfigPath}`);
148
+ } else logger.info(`tsconfig.json already exists: ${tsconfigPath}`);
149
+ const schemaPath = join(ctx.config.serverDir, "schema.graphql");
150
+ if (force || !existsSync(schemaPath)) {
151
+ writeFileSync(schemaPath, `# GraphQL Schema
152
+ # Add your type definitions here
153
+
154
+ type Query {
155
+ hello: String!
156
+ }
157
+
158
+ type Mutation {
159
+ # Add your mutations here
160
+ _empty: String
161
+ }
162
+ `, "utf-8");
163
+ logger.success(`Created example schema: ${schemaPath}`);
164
+ } else logger.info(`Schema file already exists: ${schemaPath}`);
165
+ const resolverPath = join(ctx.config.serverDir, "hello.resolver.ts");
166
+ if (force || !existsSync(resolverPath)) {
167
+ writeFileSync(resolverPath, `import { defineQuery } from 'nitro-graphql/define'
168
+
169
+ export const helloQueries = defineQuery({
170
+ hello: () => 'Hello, world!',
171
+ })
172
+ `, "utf-8");
173
+ logger.success(`Created example resolver: ${resolverPath}`);
174
+ } else logger.info(`Resolver file already exists: ${resolverPath}`);
175
+ const queryPath = join(ctx.config.clientDir, "hello.graphql");
176
+ if (force || !existsSync(queryPath)) {
177
+ writeFileSync(queryPath, `query Hello {
178
+ hello
179
+ }
180
+ `, "utf-8");
181
+ logger.success(`Created example query: ${queryPath}`);
182
+ } else logger.info(`Query file already exists: ${queryPath}`);
183
+ logger.info("");
184
+ logger.info("Next steps:");
185
+ logger.info(" 1. Run \"nitro-graphql generate\" to generate types");
186
+ logger.info(" 2. Add more schemas to your server directory");
187
+ logger.info(" 3. Add more queries/mutations to your client directory");
188
+ }
189
+
190
+ //#endregion
191
+ export { AVAILABLE_TEMPLATES, init, initFromTemplate, listTemplates };
@@ -0,0 +1,10 @@
1
+ import { CLIContext } from "../index.mjs";
2
+
3
+ //#region src/cli/commands/validate.d.ts
4
+
5
+ /**
6
+ * Validate GraphQL schemas
7
+ */
8
+ declare function validate(ctx: CLIContext): Promise<boolean>;
9
+ //#endregion
10
+ export { validate };
@@ -0,0 +1,69 @@
1
+ import { LOG_TAG } from "../../core/constants.mjs";
2
+ import { validateNoDuplicateTypes } from "../../core/codegen/validation.mjs";
3
+ import { scanSchemasCore } from "../../core/scanning/schemas.mjs";
4
+ import consola from "consola";
5
+ import { existsSync, readFileSync } from "node:fs";
6
+
7
+ //#region src/cli/commands/validate.ts
8
+ const logger = consola.withTag(LOG_TAG);
9
+ /**
10
+ * Validate GraphQL schemas
11
+ */
12
+ async function validate(ctx) {
13
+ const schemaResult = await scanSchemasCore({
14
+ rootDir: ctx.config.rootDir,
15
+ serverDir: ctx.config.serverDir,
16
+ clientDir: ctx.config.clientDir,
17
+ ignorePatterns: ctx.config.ignore,
18
+ isDev: false,
19
+ logger: {
20
+ info: (msg, ...args) => logger.info(msg, ...args),
21
+ warn: (msg, ...args) => logger.warn(msg, ...args),
22
+ error: (msg, ...args) => logger.error(msg, ...args),
23
+ success: (msg, ...args) => logger.success(msg, ...args),
24
+ debug: (msg, ...args) => logger.debug(msg, ...args)
25
+ },
26
+ layerServerDirs: [],
27
+ layerAppDirs: []
28
+ });
29
+ if (schemaResult.errors.length > 0) {
30
+ for (const error of schemaResult.errors) logger.error(error);
31
+ return false;
32
+ }
33
+ if (schemaResult.items.length === 0) {
34
+ logger.warn("No GraphQL schemas found to validate");
35
+ return true;
36
+ }
37
+ const schemaContents = [];
38
+ for (const schemaPath of schemaResult.items) {
39
+ if (!existsSync(schemaPath)) {
40
+ logger.error(`Schema file not found: ${schemaPath}`);
41
+ return false;
42
+ }
43
+ try {
44
+ const content = readFileSync(schemaPath, "utf-8");
45
+ schemaContents.push(content);
46
+ } catch (error) {
47
+ logger.error(`Failed to read schema file ${schemaPath}:`, error);
48
+ return false;
49
+ }
50
+ }
51
+ if (!validateNoDuplicateTypes(schemaResult.items, schemaContents)) {
52
+ logger.error("Schema validation failed");
53
+ return false;
54
+ }
55
+ try {
56
+ const { buildSchema, print } = await import("graphql");
57
+ const { mergeTypeDefs } = await import("@graphql-tools/merge");
58
+ const mergedTypeDefs = mergeTypeDefs(schemaContents);
59
+ buildSchema(typeof mergedTypeDefs === "string" ? mergedTypeDefs : print(mergedTypeDefs));
60
+ logger.info(`Validated ${schemaResult.items.length} schema file(s)`);
61
+ return true;
62
+ } catch (error) {
63
+ logger.error("Schema syntax error:", error);
64
+ return false;
65
+ }
66
+ }
67
+
68
+ //#endregion
69
+ export { validate };
@@ -0,0 +1,7 @@
1
+ import { ArgsDef, CommandDef } from "citty";
2
+
3
+ //#region src/cli/completions.d.ts
4
+
5
+ declare function initCompletions<T extends ArgsDef = ArgsDef>(command: CommandDef<T>): Promise<void>;
6
+ //#endregion
7
+ export { initCompletions };
@@ -0,0 +1,34 @@
1
+ import { AVAILABLE_TEMPLATES } from "./commands/init.mjs";
2
+
3
+ //#region src/cli/completions.ts
4
+ async function initCompletions(command) {
5
+ const { default: tab } = await import("@bomb.sh/tab/citty");
6
+ await tab(command, { subCommands: {
7
+ "init": { options: {
8
+ template: (complete) => {
9
+ for (const template of AVAILABLE_TEMPLATES) complete(template.name, template.description);
10
+ complete("gh:", "GitHub shorthand (gh:user/repo)");
11
+ complete("github:", "GitHub template (github:user/repo/path)");
12
+ complete("gitlab:", "GitLab template (gitlab:user/repo)");
13
+ },
14
+ cwd: (complete) => {
15
+ complete(".", "Current directory");
16
+ }
17
+ } },
18
+ "generate": { options: { cwd: (complete) => {
19
+ complete(".", "Current directory");
20
+ } } },
21
+ "generate:server": { options: { cwd: (complete) => {
22
+ complete(".", "Current directory");
23
+ } } },
24
+ "generate:client": { options: { cwd: (complete) => {
25
+ complete(".", "Current directory");
26
+ } } },
27
+ "validate": { options: { cwd: (complete) => {
28
+ complete(".", "Current directory");
29
+ } } }
30
+ } });
31
+ }
32
+
33
+ //#endregion
34
+ export { initCompletions };