nitro-graphql 2.0.0-beta.4 → 2.0.0-beta.41

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 (168) hide show
  1. package/README.md +438 -27
  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 +46 -0
  7. package/dist/cli/commands/init.mjs +195 -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/config.d.mts +2 -0
  17. package/dist/config.mjs +3 -0
  18. package/dist/core/codegen/client.d.mts +23 -0
  19. package/dist/core/codegen/client.mjs +150 -0
  20. package/dist/core/codegen/document-loader.d.mts +10 -0
  21. package/dist/core/codegen/document-loader.mjs +18 -0
  22. package/dist/core/codegen/index.d.mts +8 -0
  23. package/dist/core/codegen/index.mjs +9 -0
  24. package/dist/core/codegen/plugin.d.mts +20 -0
  25. package/dist/core/codegen/plugin.mjs +30 -0
  26. package/dist/core/codegen/runtime.d.mts +20 -0
  27. package/dist/core/codegen/runtime.mjs +60 -0
  28. package/dist/core/codegen/schema-loader.d.mts +28 -0
  29. package/dist/core/codegen/schema-loader.mjs +128 -0
  30. package/dist/core/codegen/server.d.mts +28 -0
  31. package/dist/core/codegen/server.mjs +143 -0
  32. package/dist/core/codegen/validation.d.mts +13 -0
  33. package/dist/core/codegen/validation.mjs +96 -0
  34. package/dist/core/config.d.mts +50 -0
  35. package/dist/core/config.mjs +82 -0
  36. package/dist/core/constants.d.mts +188 -0
  37. package/dist/core/constants.mjs +210 -0
  38. package/dist/core/index.d.mts +33 -0
  39. package/dist/core/index.mjs +27 -0
  40. package/dist/core/manifest.d.mts +46 -0
  41. package/dist/core/manifest.mjs +76 -0
  42. package/dist/core/scanning/ast-scanner.d.mts +28 -0
  43. package/dist/core/scanning/ast-scanner.mjs +122 -0
  44. package/dist/core/scanning/common.d.mts +37 -0
  45. package/dist/core/scanning/common.mjs +60 -0
  46. package/dist/core/scanning/directives.d.mts +10 -0
  47. package/dist/core/scanning/directives.mjs +29 -0
  48. package/dist/core/scanning/documents.d.mts +21 -0
  49. package/dist/core/scanning/documents.mjs +43 -0
  50. package/dist/core/scanning/index.d.mts +7 -0
  51. package/dist/core/scanning/index.mjs +8 -0
  52. package/dist/core/scanning/resolvers.d.mts +15 -0
  53. package/dist/core/scanning/resolvers.mjs +59 -0
  54. package/dist/core/scanning/schemas.d.mts +14 -0
  55. package/dist/core/scanning/schemas.mjs +64 -0
  56. package/dist/core/schema/builder.d.mts +53 -0
  57. package/dist/core/schema/builder.mjs +70 -0
  58. package/dist/core/schema/federation.d.mts +34 -0
  59. package/dist/core/schema/federation.mjs +40 -0
  60. package/dist/core/schema/index.d.mts +3 -0
  61. package/dist/core/schema/index.mjs +4 -0
  62. package/dist/core/types/adapter.d.mts +58 -0
  63. package/dist/core/types/codegen.d.mts +133 -0
  64. package/dist/core/types/config.d.mts +210 -0
  65. package/dist/core/types/config.mjs +1 -0
  66. package/dist/{utils/define.d.ts → core/types/define.d.mts} +3 -30
  67. package/dist/core/types/define.mjs +1 -0
  68. package/dist/core/types/index.d.mts +5 -0
  69. package/dist/core/types/index.mjs +1 -0
  70. package/dist/core/types/scanning.d.mts +69 -0
  71. package/dist/core/types/scanning.mjs +1 -0
  72. package/dist/{utils/directive-parser.d.ts → core/utils/directive-parser.d.mts} +21 -4
  73. package/dist/{utils/directive-parser.js → core/utils/directive-parser.mjs} +25 -34
  74. package/dist/core/utils/errors.d.mts +77 -0
  75. package/dist/core/utils/errors.mjs +93 -0
  76. package/dist/core/utils/file-io.d.mts +24 -0
  77. package/dist/core/utils/file-io.mjs +47 -0
  78. package/dist/core/utils/imports.d.mts +15 -0
  79. package/dist/core/utils/imports.mjs +25 -0
  80. package/dist/core/utils/index.d.mts +7 -0
  81. package/dist/core/utils/index.mjs +8 -0
  82. package/dist/core/utils/logger.d.mts +19 -0
  83. package/dist/core/utils/logger.mjs +38 -0
  84. package/dist/core/utils/ofetch-templates.d.mts +30 -0
  85. package/dist/core/utils/ofetch-templates.mjs +135 -0
  86. package/dist/core/validation/external-services.d.mts +11 -0
  87. package/dist/core/validation/external-services.mjs +34 -0
  88. package/dist/core/validation/index.d.mts +2 -0
  89. package/dist/core/validation/index.mjs +3 -0
  90. package/dist/define.d.mts +294 -0
  91. package/dist/define.mjs +323 -0
  92. package/dist/index.d.mts +6 -0
  93. package/dist/index.mjs +6 -0
  94. package/dist/nitro/adapter.d.mts +30 -0
  95. package/dist/nitro/adapter.mjs +97 -0
  96. package/dist/{utils/apollo.d.ts → nitro/apollo.d.mts} +3 -3
  97. package/dist/nitro/apollo.mjs +59 -0
  98. package/dist/nitro/codegen.d.mts +19 -0
  99. package/dist/nitro/codegen.mjs +141 -0
  100. package/dist/nitro/config.d.mts +51 -0
  101. package/dist/nitro/config.mjs +57 -0
  102. package/dist/nitro/index.d.mts +46 -0
  103. package/dist/nitro/index.mjs +65 -0
  104. package/dist/nitro/paths.d.mts +54 -0
  105. package/dist/nitro/paths.mjs +92 -0
  106. package/dist/nitro/rollup.d.mts +6 -0
  107. package/dist/nitro/rollup.mjs +95 -0
  108. package/dist/nitro/routes/apollo-server.d.mts +6 -0
  109. package/dist/nitro/routes/apollo-server.mjs +71 -0
  110. package/dist/nitro/routes/debug-template.d.mts +15 -0
  111. package/dist/nitro/routes/debug-template.mjs +385 -0
  112. package/dist/nitro/routes/debug.d.mts +55 -0
  113. package/dist/nitro/routes/debug.mjs +102 -0
  114. package/dist/nitro/routes/graphql-yoga.d.mts +6 -0
  115. package/dist/nitro/routes/graphql-yoga.mjs +62 -0
  116. package/dist/nitro/routes/health.d.mts +10 -0
  117. package/dist/{routes/health.js → nitro/routes/health.mjs} +4 -3
  118. package/dist/nitro/setup/extend-loader.d.mts +19 -0
  119. package/dist/nitro/setup/extend-loader.mjs +129 -0
  120. package/dist/nitro/setup/file-watcher.d.mts +16 -0
  121. package/dist/nitro/setup/file-watcher.mjs +98 -0
  122. package/dist/nitro/setup/logging.d.mts +17 -0
  123. package/dist/nitro/setup/logging.mjs +66 -0
  124. package/dist/nitro/setup/rollup-integration.d.mts +16 -0
  125. package/dist/nitro/setup/rollup-integration.mjs +90 -0
  126. package/dist/nitro/setup/routes.d.mts +10 -0
  127. package/dist/nitro/setup/routes.mjs +35 -0
  128. package/dist/nitro/setup/ts-config.d.mts +11 -0
  129. package/dist/nitro/setup/ts-config.mjs +69 -0
  130. package/dist/nitro/setup.d.mts +12 -0
  131. package/dist/nitro/setup.mjs +234 -0
  132. package/dist/nitro/types.d.mts +374 -0
  133. package/dist/nitro/types.mjs +1 -0
  134. package/dist/nitro/virtual/generators.d.mts +31 -0
  135. package/dist/nitro/virtual/generators.mjs +113 -0
  136. package/dist/nitro/virtual/stubs.d.mts +20 -0
  137. package/dist/nitro/virtual/stubs.mjs +31 -0
  138. package/dist/{ecosystem/nuxt.d.ts → nuxt.d.mts} +1 -1
  139. package/dist/nuxt.mjs +109 -0
  140. package/dist/{graphql/server.d.ts → stubs/index.d.mts} +5 -1
  141. package/dist/stubs/index.mjs +1 -0
  142. package/package.json +102 -77
  143. package/dist/ecosystem/nuxt.js +0 -67
  144. package/dist/graphql/index.d.ts +0 -5
  145. package/dist/index.d.ts +0 -8
  146. package/dist/index.js +0 -264
  147. package/dist/rollup.js +0 -119
  148. package/dist/routes/apollo-server.d.ts +0 -6
  149. package/dist/routes/apollo-server.js +0 -89
  150. package/dist/routes/graphql-yoga.d.ts +0 -6
  151. package/dist/routes/graphql-yoga.js +0 -91
  152. package/dist/routes/health.d.ts +0 -6
  153. package/dist/types/index.d.ts +0 -128
  154. package/dist/types/standard-schema.d.ts +0 -59
  155. package/dist/utils/apollo.js +0 -61
  156. package/dist/utils/client-codegen.d.ts +0 -38
  157. package/dist/utils/client-codegen.js +0 -290
  158. package/dist/utils/define.js +0 -57
  159. package/dist/utils/index.d.ts +0 -39
  160. package/dist/utils/index.js +0 -250
  161. package/dist/utils/server-codegen.d.ts +0 -7
  162. package/dist/utils/server-codegen.js +0 -136
  163. package/dist/utils/type-generation.d.ts +0 -7
  164. package/dist/utils/type-generation.js +0 -287
  165. package/dist/vite.d.ts +0 -25
  166. package/dist/vite.js +0 -40
  167. /package/dist/{graphql/index.js → core/types/adapter.mjs} +0 -0
  168. /package/dist/{graphql/server.js → core/types/codegen.mjs} +0 -0
@@ -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,46 @@
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: "nitro";
10
+ readonly description: "Minimal Nitro + GraphQL starter";
11
+ }, {
12
+ readonly name: "drizzle-orm";
13
+ readonly description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL";
14
+ }, {
15
+ readonly name: "vite";
16
+ readonly description: "Vite + Nitro GraphQL integration";
17
+ }, {
18
+ readonly name: "vite-react";
19
+ readonly description: "Vite + React + Nitro GraphQL";
20
+ }, {
21
+ readonly name: "vite-vue";
22
+ readonly description: "Vite + Vue + Nitro GraphQL";
23
+ }, {
24
+ readonly name: "better-auth";
25
+ readonly description: "Nitro + GraphQL + Better Auth integration";
26
+ }];
27
+ type TemplateName = typeof AVAILABLE_TEMPLATES[number]['name'];
28
+ /**
29
+ * List available templates
30
+ */
31
+ declare function listTemplates(): void;
32
+ /**
33
+ * Initialize project from template
34
+ */
35
+ declare function initFromTemplate(projectName: string, templateName: string, options?: {
36
+ force?: boolean;
37
+ cwd?: string;
38
+ }): Promise<void>;
39
+ /**
40
+ * Initialize project structure (basic scaffolding)
41
+ */
42
+ declare function init(ctx: CLIContext, options?: {
43
+ force?: boolean;
44
+ }): Promise<void>;
45
+ //#endregion
46
+ export { AVAILABLE_TEMPLATES, TemplateName, init, initFromTemplate, listTemplates };
@@ -0,0 +1,195 @@
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: "nitro",
15
+ description: "Minimal Nitro + GraphQL starter"
16
+ },
17
+ {
18
+ name: "drizzle-orm",
19
+ description: "Nitro + GraphQL + Drizzle ORM with PostgreSQL"
20
+ },
21
+ {
22
+ name: "vite",
23
+ description: "Vite + Nitro GraphQL integration"
24
+ },
25
+ {
26
+ name: "vite-react",
27
+ description: "Vite + React + Nitro GraphQL"
28
+ },
29
+ {
30
+ name: "vite-vue",
31
+ description: "Vite + Vue + Nitro GraphQL"
32
+ },
33
+ {
34
+ name: "better-auth",
35
+ description: "Nitro + GraphQL + Better Auth integration"
36
+ }
37
+ ];
38
+ /**
39
+ * Default GitHub template source
40
+ */
41
+ const DEFAULT_TEMPLATE_REGISTRY = "github:productdevbook/nitro-graphql/examples";
42
+ /**
43
+ * List available templates
44
+ */
45
+ function listTemplates() {
46
+ logger.info("Available templates:\n");
47
+ for (const template of AVAILABLE_TEMPLATES) console.log(` ${template.name.padEnd(15)} - ${template.description}`);
48
+ console.log("\nUsage:");
49
+ console.log(" nitro-graphql init <project-name> --template <template-name>");
50
+ console.log(" nitro-graphql init my-app -t drizzle-orm");
51
+ console.log("\nCustom templates:");
52
+ console.log(" nitro-graphql init my-app -t gh:user/repo");
53
+ console.log(" nitro-graphql init my-app -t github:user/repo/subdir");
54
+ }
55
+ /**
56
+ * Initialize project from template
57
+ */
58
+ async function initFromTemplate(projectName, templateName, options = {}) {
59
+ const { force, cwd = process.cwd() } = options;
60
+ const targetDir = resolve(cwd, projectName);
61
+ if (existsSync(targetDir) && !force) {
62
+ logger.error(`Directory "${projectName}" already exists. Use --force to overwrite.`);
63
+ process.exit(1);
64
+ }
65
+ let templateSource;
66
+ if (templateName.includes(":") || templateName.includes("/")) templateSource = templateName;
67
+ else {
68
+ if (!AVAILABLE_TEMPLATES.find((t) => t.name === templateName)) {
69
+ logger.error(`Unknown template: "${templateName}"`);
70
+ logger.info("Use --list to see available templates");
71
+ process.exit(1);
72
+ }
73
+ templateSource = `${DEFAULT_TEMPLATE_REGISTRY}/${templateName}`;
74
+ }
75
+ logger.info(`Downloading template: ${templateName}`);
76
+ logger.debug(`Source: ${templateSource}`);
77
+ try {
78
+ const result = await downloadTemplate(templateSource, {
79
+ dir: targetDir,
80
+ force
81
+ });
82
+ logger.success(`Template downloaded to: ${result.dir}`);
83
+ const packageJsonPath = join(targetDir, "package.json");
84
+ if (existsSync(packageJsonPath)) try {
85
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
86
+ packageJson.name = basename(projectName).replace(/[^a-z0-9-]/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "my-graphql-app";
87
+ writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf-8");
88
+ logger.debug(`Updated package.json name to: ${packageJson.name}`);
89
+ } catch {
90
+ logger.warn("Could not update package.json name");
91
+ }
92
+ console.log("");
93
+ logger.info("Next steps:");
94
+ console.log(` cd ${projectName}`);
95
+ console.log(" pnpm install");
96
+ console.log(" pnpm dev");
97
+ console.log("");
98
+ } catch (error) {
99
+ logger.error("Failed to download template:", error);
100
+ process.exit(1);
101
+ }
102
+ }
103
+ /**
104
+ * Initialize project structure (basic scaffolding)
105
+ */
106
+ async function init(ctx, options = {}) {
107
+ const { force } = options;
108
+ const dirs = [ctx.config.serverDir, ctx.config.clientDir];
109
+ for (const dir of dirs) if (!existsSync(dir)) {
110
+ mkdirSync(dir, { recursive: true });
111
+ logger.info(`Created directory: ${dir}`);
112
+ }
113
+ const configPath = join(ctx.config.rootDir, "nitro-graphql.config.ts");
114
+ if (force || !existsSync(configPath)) {
115
+ const relativeServerDir = relative(ctx.config.rootDir, ctx.config.serverDir) || "server/graphql";
116
+ const relativeClientDir = relative(ctx.config.rootDir, ctx.config.clientDir) || "graphql";
117
+ writeFileSync(configPath, `import { defineConfig } from 'nitro-graphql/cli'
118
+
119
+ export default defineConfig({
120
+ framework: '${ctx.config.framework}',
121
+ serverDir: './${relativeServerDir}',
122
+ clientDir: './${relativeClientDir}',
123
+ })
124
+ `, "utf-8");
125
+ logger.success(`Created config file: ${configPath}`);
126
+ } else logger.info(`Config file already exists: ${configPath}`);
127
+ const tsconfigPath = join(ctx.config.rootDir, "tsconfig.json");
128
+ if (force || !existsSync(tsconfigPath)) {
129
+ const relativeBuildDir = relative(ctx.config.rootDir, ctx.config.buildDir) || ".graphql";
130
+ writeFileSync(tsconfigPath, `{
131
+ "compilerOptions": {
132
+ "target": "ESNext",
133
+ "module": "ESNext",
134
+ "moduleResolution": "Bundler",
135
+ "resolveJsonModule": true,
136
+ "allowSyntheticDefaultImports": true,
137
+ "strict": true,
138
+ "noEmit": true,
139
+ "skipLibCheck": true,
140
+ "forceConsistentCasingInFileNames": true,
141
+ "paths": {
142
+ "#graphql/server": ["./${relativeBuildDir}/types/nitro-graphql-server.d.ts"],
143
+ "#graphql/client": ["./${relativeBuildDir}/types/nitro-graphql-client.d.ts"],
144
+ "#graphql/schema": ["./${relative(ctx.config.rootDir, ctx.config.serverDir) || "server/graphql"}/schema.ts"]
145
+ }
146
+ },
147
+ "include": ["**/*.ts"],
148
+ "exclude": ["node_modules", "${relativeBuildDir}"]
149
+ }
150
+ `, "utf-8");
151
+ logger.success(`Created tsconfig.json: ${tsconfigPath}`);
152
+ } else logger.info(`tsconfig.json already exists: ${tsconfigPath}`);
153
+ const schemaPath = join(ctx.config.serverDir, "schema.graphql");
154
+ if (force || !existsSync(schemaPath)) {
155
+ writeFileSync(schemaPath, `# GraphQL Schema
156
+ # Add your type definitions here
157
+
158
+ type Query {
159
+ hello: String!
160
+ }
161
+
162
+ type Mutation {
163
+ # Add your mutations here
164
+ _empty: String
165
+ }
166
+ `, "utf-8");
167
+ logger.success(`Created example schema: ${schemaPath}`);
168
+ } else logger.info(`Schema file already exists: ${schemaPath}`);
169
+ const resolverPath = join(ctx.config.serverDir, "hello.resolver.ts");
170
+ if (force || !existsSync(resolverPath)) {
171
+ writeFileSync(resolverPath, `import { defineQuery } from 'nitro-graphql/define'
172
+
173
+ export const helloQueries = defineQuery({
174
+ hello: () => 'Hello, world!',
175
+ })
176
+ `, "utf-8");
177
+ logger.success(`Created example resolver: ${resolverPath}`);
178
+ } else logger.info(`Resolver file already exists: ${resolverPath}`);
179
+ const queryPath = join(ctx.config.clientDir, "hello.graphql");
180
+ if (force || !existsSync(queryPath)) {
181
+ writeFileSync(queryPath, `query Hello {
182
+ hello
183
+ }
184
+ `, "utf-8");
185
+ logger.success(`Created example query: ${queryPath}`);
186
+ } else logger.info(`Query file already exists: ${queryPath}`);
187
+ logger.info("");
188
+ logger.info("Next steps:");
189
+ logger.info(" 1. Run \"nitro-graphql generate\" to generate types");
190
+ logger.info(" 2. Add more schemas to your server directory");
191
+ logger.info(" 3. Add more queries/mutations to your client directory");
192
+ }
193
+
194
+ //#endregion
195
+ 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 };
@@ -0,0 +1,75 @@
1
+ import { GraphQLFramework } from "../core/constants.mjs";
2
+ import { CoreClientUtilsConfig, CoreCodegenConfig, CoreExternalService, CoreFederationConfig, CorePathsConfig, CoreScaffoldConfig, CoreSdkConfig, CoreSecurityConfig, CoreTypesConfig } from "../core/types/config.mjs";
3
+ import "../core/types/index.mjs";
4
+
5
+ //#region src/cli/config.d.ts
6
+
7
+ /**
8
+ * CLI configuration options
9
+ * Used when running nitro-graphql as a standalone CLI tool
10
+ */
11
+ interface CLIConfig {
12
+ /** Root directory (defaults to current working directory) */
13
+ rootDir?: string;
14
+ /** Build output directory */
15
+ buildDir?: string;
16
+ /** Server GraphQL directory (defaults to 'server/graphql') */
17
+ serverDir?: string;
18
+ /** Client GraphQL directory (defaults to 'graphql') */
19
+ clientDir?: string;
20
+ /** Types output directory */
21
+ typesDir?: string;
22
+ /** GraphQL framework (defaults to 'graphql-yoga') */
23
+ framework?: GraphQLFramework;
24
+ /** Codegen configuration */
25
+ codegen?: CoreCodegenConfig;
26
+ /** Security configuration */
27
+ security?: CoreSecurityConfig;
28
+ /** External GraphQL services */
29
+ externalServices?: CoreExternalService[];
30
+ /** Apollo Federation configuration */
31
+ federation?: CoreFederationConfig;
32
+ /** Path configuration */
33
+ paths?: CorePathsConfig;
34
+ /** Scaffold file configuration */
35
+ scaffold?: false | CoreScaffoldConfig;
36
+ /** Type generation configuration */
37
+ types?: false | CoreTypesConfig;
38
+ /** SDK generation configuration */
39
+ sdk?: false | CoreSdkConfig;
40
+ /** Client utilities configuration */
41
+ clientUtils?: false | CoreClientUtilsConfig;
42
+ /** Patterns to ignore during scanning */
43
+ ignore?: string[];
44
+ /** Watch mode configuration */
45
+ watch?: {
46
+ /** Enable watch mode */
47
+ enabled?: boolean;
48
+ /** Debounce time in ms */
49
+ debounce?: number;
50
+ };
51
+ /**
52
+ * Runtime file generation
53
+ * Generates resolvers.ts, schema.ts for standalone server usage
54
+ */
55
+ runtime?: boolean | {
56
+ /** Output directory for runtime files (defaults to '{buildDir}/runtime') */
57
+ outDir?: string;
58
+ /** What to include in generation */
59
+ include?: {
60
+ resolvers?: boolean;
61
+ schema?: boolean;
62
+ index?: boolean;
63
+ };
64
+ };
65
+ }
66
+ /**
67
+ * Define CLI configuration with type safety
68
+ */
69
+ declare function defineConfig(config: CLIConfig): CLIConfig;
70
+ /**
71
+ * Default CLI configuration values
72
+ */
73
+ declare const DEFAULT_CLI_CONFIG: CLIConfig;
74
+ //#endregion
75
+ export { CLIConfig, DEFAULT_CLI_CONFIG, defineConfig };
@@ -0,0 +1,20 @@
1
+ //#region src/cli/config.ts
2
+ /**
3
+ * Define CLI configuration with type safety
4
+ */
5
+ function defineConfig(config) {
6
+ return config;
7
+ }
8
+ /**
9
+ * Default CLI configuration values
10
+ */
11
+ const DEFAULT_CLI_CONFIG = {
12
+ framework: "graphql-yoga",
13
+ serverDir: "server/graphql",
14
+ clientDir: "graphql",
15
+ buildDir: ".graphql",
16
+ ignore: ["**/node_modules/**", "**/dist/**"]
17
+ };
18
+
19
+ //#endregion
20
+ export { DEFAULT_CLI_CONFIG, defineConfig };