nitro-graphql 2.0.0-beta.2 → 2.0.0-beta.20

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 (64) hide show
  1. package/README.md +855 -5
  2. package/dist/ecosystem/nuxt.mjs +109 -0
  3. package/dist/index.d.mts +12 -0
  4. package/dist/index.mjs +16 -0
  5. package/dist/rollup.d.mts +12 -0
  6. package/dist/rollup.mjs +282 -0
  7. package/dist/routes/apollo-server.d.mts +6 -0
  8. package/dist/routes/{apollo-server.js → apollo-server.mjs} +5 -5
  9. package/dist/routes/debug.d.mts +61 -0
  10. package/dist/routes/debug.mjs +445 -0
  11. package/dist/routes/graphql-yoga.d.mts +6 -0
  12. package/dist/routes/{graphql-yoga.js → graphql-yoga.mjs} +5 -5
  13. package/dist/routes/health.d.mts +10 -0
  14. package/dist/routes/{health.js → health.mjs} +1 -0
  15. package/dist/setup.d.mts +11 -0
  16. package/dist/setup.mjs +390 -0
  17. package/dist/types/index.d.mts +246 -0
  18. package/dist/utils/{apollo.js → apollo.mjs} +2 -2
  19. package/dist/utils/{client-codegen.d.ts → client-codegen.d.mts} +3 -3
  20. package/dist/utils/{client-codegen.js → client-codegen.mjs} +4 -4
  21. package/dist/utils/file-generator.d.mts +37 -0
  22. package/dist/utils/file-generator.mjs +72 -0
  23. package/dist/utils/{index.d.ts → index.d.mts} +2 -2
  24. package/dist/utils/{index.js → index.mjs} +63 -35
  25. package/dist/utils/path-resolver.d.mts +70 -0
  26. package/dist/utils/path-resolver.mjs +127 -0
  27. package/dist/utils/{server-codegen.d.ts → server-codegen.d.mts} +1 -1
  28. package/dist/utils/{server-codegen.js → server-codegen.mjs} +1 -1
  29. package/dist/utils/{type-generation.js → type-generation.mjs} +153 -42
  30. package/dist/virtual/debug-info.d.mts +9 -0
  31. package/dist/virtual/debug-info.mjs +26 -0
  32. package/dist/virtual/graphql-config.d.mts +9 -0
  33. package/dist/virtual/graphql-config.mjs +10 -0
  34. package/dist/virtual/module-config.d.mts +9 -0
  35. package/dist/virtual/module-config.mjs +10 -0
  36. package/dist/virtual/server-directives.d.mts +11 -0
  37. package/dist/virtual/server-directives.mjs +10 -0
  38. package/dist/virtual/server-resolvers.d.mts +11 -0
  39. package/dist/virtual/server-resolvers.mjs +10 -0
  40. package/dist/virtual/server-schemas.d.mts +11 -0
  41. package/dist/virtual/server-schemas.mjs +10 -0
  42. package/dist/vite.d.mts +27 -0
  43. package/dist/vite.mjs +49 -0
  44. package/package.json +72 -58
  45. package/dist/ecosystem/nuxt.js +0 -67
  46. package/dist/index.d.ts +0 -8
  47. package/dist/index.js +0 -264
  48. package/dist/rollup.js +0 -114
  49. package/dist/routes/apollo-server.d.ts +0 -6
  50. package/dist/routes/graphql-yoga.d.ts +0 -6
  51. package/dist/routes/health.d.ts +0 -6
  52. package/dist/types/index.d.ts +0 -128
  53. /package/dist/ecosystem/{nuxt.d.ts → nuxt.d.mts} +0 -0
  54. /package/dist/graphql/{index.d.ts → index.d.mts} +0 -0
  55. /package/dist/graphql/{index.js → index.mjs} +0 -0
  56. /package/dist/graphql/{server.d.ts → server.d.mts} +0 -0
  57. /package/dist/graphql/{server.js → server.mjs} +0 -0
  58. /package/dist/types/{standard-schema.d.ts → standard-schema.d.mts} +0 -0
  59. /package/dist/utils/{apollo.d.ts → apollo.d.mts} +0 -0
  60. /package/dist/utils/{define.d.ts → define.d.mts} +0 -0
  61. /package/dist/utils/{define.js → define.mjs} +0 -0
  62. /package/dist/utils/{directive-parser.d.ts → directive-parser.d.mts} +0 -0
  63. /package/dist/utils/{directive-parser.js → directive-parser.mjs} +0 -0
  64. /package/dist/utils/{type-generation.d.ts → type-generation.d.mts} +0 -0
package/dist/setup.mjs ADDED
@@ -0,0 +1,390 @@
1
+ import { generateDirectiveSchemas } from "./utils/directive-parser.mjs";
2
+ import { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.mjs";
3
+ import { writeFileIfNotExists } from "./utils/file-generator.mjs";
4
+ import { getScaffoldConfig, getTypesConfig, resolveFilePath, shouldGenerateScaffold } from "./utils/path-resolver.mjs";
5
+ import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.mjs";
6
+ import { rollupConfig } from "./rollup.mjs";
7
+ import { existsSync, mkdirSync } from "node:fs";
8
+ import { fileURLToPath } from "node:url";
9
+ import { watch } from "chokidar";
10
+ import consola from "consola";
11
+ import defu from "defu";
12
+ import { dirname, join, relative, resolve } from "pathe";
13
+
14
+ //#region src/setup.ts
15
+ /**
16
+ * Shared setup logic for nitro-graphql module
17
+ * Used by both the direct Nitro module export and the Vite plugin's nitro: hook
18
+ */
19
+ async function setupNitroGraphQL(nitro) {
20
+ if (!nitro.options.graphql?.framework) consola.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
21
+ if (nitro.options.graphql?.externalServices?.length) {
22
+ const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
23
+ if (validationErrors.length > 0) {
24
+ consola.error("External services configuration errors:");
25
+ for (const error of validationErrors) consola.error(` - ${error}`);
26
+ throw new Error("Invalid external services configuration");
27
+ }
28
+ consola.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
29
+ }
30
+ const { getDefaultPaths } = await import("./utils/path-resolver.mjs");
31
+ const defaultPaths = getDefaultPaths(nitro);
32
+ nitro.graphql ||= {
33
+ buildDir: "",
34
+ watchDirs: [],
35
+ clientDir: defaultPaths.clientGraphql,
36
+ serverDir: defaultPaths.serverGraphql,
37
+ dir: {
38
+ build: relative(nitro.options.rootDir, nitro.options.buildDir),
39
+ client: "graphql",
40
+ server: "server"
41
+ }
42
+ };
43
+ nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
44
+ rollupConfig$1.external = rollupConfig$1.external || [];
45
+ const codegenExternals = ["oxc-parser", "@oxc-parser"];
46
+ if (Array.isArray(rollupConfig$1.external)) rollupConfig$1.external.push(...codegenExternals);
47
+ else if (typeof rollupConfig$1.external === "function") {
48
+ const originalExternal = rollupConfig$1.external;
49
+ rollupConfig$1.external = (id, parent, isResolved) => {
50
+ if (codegenExternals.some((external) => id.includes(external))) return true;
51
+ return originalExternal(id, parent, isResolved);
52
+ };
53
+ }
54
+ });
55
+ nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, {
56
+ endpoint: {
57
+ graphql: "/api/graphql",
58
+ healthCheck: "/api/graphql/health"
59
+ },
60
+ playground: true
61
+ });
62
+ if (nitro.options.graphql?.federation?.enabled) consola.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
63
+ const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
64
+ nitro.graphql.buildDir = graphqlBuildDir;
65
+ const watchDirs = [];
66
+ switch (nitro.options.framework.name) {
67
+ case "nuxt": {
68
+ nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
69
+ nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
70
+ watchDirs.push(nitro.graphql.clientDir);
71
+ const layerServerDirs = getLayerServerDirectories(nitro);
72
+ const layerAppDirs = getLayerAppDirectories(nitro);
73
+ for (const layerServerDir of layerServerDirs) watchDirs.push(join(layerServerDir, "graphql"));
74
+ for (const layerAppDir of layerAppDirs) watchDirs.push(join(layerAppDir, "graphql"));
75
+ break;
76
+ }
77
+ case "nitro":
78
+ nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
79
+ nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
80
+ watchDirs.push(nitro.graphql.clientDir);
81
+ watchDirs.push(nitro.graphql.serverDir);
82
+ break;
83
+ default:
84
+ }
85
+ if (nitro.options.graphql?.externalServices?.length) {
86
+ for (const service of nitro.options.graphql.externalServices) if (service.documents?.length) for (const pattern of service.documents) {
87
+ if (!pattern) continue;
88
+ const baseDir = pattern.split("**")[0]?.replace(/\/$/, "") || ".";
89
+ const resolvedDir = resolve(nitro.options.rootDir, baseDir);
90
+ if (!watchDirs.includes(resolvedDir)) watchDirs.push(resolvedDir);
91
+ }
92
+ }
93
+ const watcher = watch(watchDirs, {
94
+ persistent: true,
95
+ ignoreInitial: true,
96
+ ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns()]
97
+ }).on("all", async (_, path) => {
98
+ if (path.endsWith(".graphql") || path.endsWith(".gql")) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql")) {
99
+ await serverTypeGeneration(nitro);
100
+ await clientTypeGeneration(nitro);
101
+ await nitro.hooks.callHook("dev:reload");
102
+ } else await clientTypeGeneration(nitro);
103
+ });
104
+ nitro.hooks.hook("close", () => {
105
+ watcher.close();
106
+ });
107
+ const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
108
+ nitro.scanSchemas = await scanSchemas(nitro);
109
+ nitro.scanDocuments = await scanDocs(nitro);
110
+ nitro.scanResolvers = await scanResolvers(nitro);
111
+ const directives = await scanDirectives(nitro);
112
+ nitro.scanDirectives = directives;
113
+ await generateDirectiveSchemas(nitro, directives);
114
+ nitro.hooks.hook("dev:start", async () => {
115
+ const schemas = await scanSchemas(nitro);
116
+ nitro.scanSchemas = schemas;
117
+ const resolvers = await scanResolvers(nitro);
118
+ nitro.scanResolvers = resolvers;
119
+ const directives$1 = await scanDirectives(nitro);
120
+ nitro.scanDirectives = directives$1;
121
+ await generateDirectiveSchemas(nitro, directives$1);
122
+ const docs = await scanDocs(nitro);
123
+ nitro.scanDocuments = docs;
124
+ if (nitro.options.dev) {
125
+ consola.box({
126
+ title: "Nitro GraphQL",
127
+ message: [
128
+ `Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
129
+ `Schemas: ${schemas.length}`,
130
+ `Resolvers: ${resolvers.length}`,
131
+ `Directives: ${directives$1.length}`,
132
+ `Documents: ${docs.length}`,
133
+ "",
134
+ "Debug Dashboard: /_nitro/graphql/debug"
135
+ ].join("\n"),
136
+ style: {
137
+ borderColor: "cyan",
138
+ borderStyle: "rounded"
139
+ }
140
+ });
141
+ if (resolvers.length > 0) {
142
+ const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
143
+ const typeCount = {
144
+ query: 0,
145
+ mutation: 0,
146
+ resolver: 0,
147
+ type: 0,
148
+ subscription: 0,
149
+ directive: 0
150
+ };
151
+ for (const resolver of resolvers) for (const imp of resolver.imports) if (imp.type in typeCount) typeCount[imp.type]++;
152
+ const breakdown = [];
153
+ if (typeCount.query > 0) breakdown.push(`${typeCount.query} query`);
154
+ if (typeCount.mutation > 0) breakdown.push(`${typeCount.mutation} mutation`);
155
+ if (typeCount.resolver > 0) breakdown.push(`${typeCount.resolver} resolver`);
156
+ if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
157
+ if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
158
+ if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
159
+ if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
160
+ } else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
161
+ }
162
+ });
163
+ await rollupConfig(nitro);
164
+ await serverTypeGeneration(nitro);
165
+ await clientTypeGeneration(nitro);
166
+ nitro.hooks.hook("close", async () => {
167
+ await serverTypeGeneration(nitro);
168
+ await clientTypeGeneration(nitro);
169
+ });
170
+ const runtime = fileURLToPath(new URL("routes", import.meta.url));
171
+ const methods = [
172
+ "GET",
173
+ "POST",
174
+ "OPTIONS"
175
+ ];
176
+ if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
177
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
178
+ handler: join(runtime, "graphql-yoga"),
179
+ method
180
+ });
181
+ if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
182
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
183
+ handler: join(runtime, "apollo-server"),
184
+ method
185
+ });
186
+ nitro.options.handlers.push({
187
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
188
+ handler: join(runtime, "health"),
189
+ method: "GET"
190
+ });
191
+ if (nitro.options.dev) {
192
+ nitro.options.handlers.push({
193
+ route: "/_nitro/graphql/debug",
194
+ handler: join(runtime, "debug"),
195
+ method: "GET"
196
+ });
197
+ consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
198
+ }
199
+ if (nitro.options.imports) {
200
+ nitro.options.imports.presets ??= [];
201
+ nitro.options.imports.presets.push({
202
+ from: fileURLToPath(new URL("utils/define", import.meta.url)),
203
+ imports: [
204
+ "defineResolver",
205
+ "defineMutation",
206
+ "defineQuery",
207
+ "defineSubscription",
208
+ "defineType",
209
+ "defineGraphQLConfig",
210
+ "defineSchema",
211
+ "defineDirective"
212
+ ]
213
+ });
214
+ }
215
+ nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
216
+ const manualChunks = rollupConfig$1.output?.manualChunks;
217
+ const chunkFiles = rollupConfig$1.output?.chunkFileNames;
218
+ if (!rollupConfig$1.output.inlineDynamicImports) {
219
+ rollupConfig$1.output.manualChunks = (id, meta) => {
220
+ if (id.endsWith(".graphql") || id.endsWith(".gql")) {
221
+ let graphqlIndex = id.indexOf("server/graphql/");
222
+ let baseLength = 15;
223
+ if (graphqlIndex === -1) {
224
+ graphqlIndex = id.indexOf("routes/graphql/");
225
+ baseLength = 15;
226
+ }
227
+ if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
228
+ return "schemas";
229
+ }
230
+ if (id.endsWith(".resolver.ts")) {
231
+ let graphqlIndex = id.indexOf("server/graphql/");
232
+ let baseLength = 15;
233
+ if (graphqlIndex === -1) {
234
+ graphqlIndex = id.indexOf("routes/graphql/");
235
+ baseLength = 15;
236
+ }
237
+ if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
238
+ return "resolvers";
239
+ }
240
+ if (typeof manualChunks === "function") return manualChunks(id, meta);
241
+ };
242
+ rollupConfig$1.output.advancedChunks = {
243
+ groups: [{
244
+ name: (moduleId) => {
245
+ if (!moduleId.endsWith(".graphql") && !moduleId.endsWith(".gql")) return;
246
+ let graphqlIndex = moduleId.indexOf("server/graphql/");
247
+ let baseLength = 15;
248
+ if (graphqlIndex === -1) {
249
+ graphqlIndex = moduleId.indexOf("routes/graphql/");
250
+ baseLength = 15;
251
+ }
252
+ if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
253
+ return "schemas";
254
+ },
255
+ test: /\.(?:graphql|gql)$/
256
+ }, {
257
+ name: (moduleId) => {
258
+ if (!moduleId.endsWith(".resolver.ts")) return;
259
+ let graphqlIndex = moduleId.indexOf("server/graphql/");
260
+ let baseLength = 15;
261
+ if (graphqlIndex === -1) {
262
+ graphqlIndex = moduleId.indexOf("routes/graphql/");
263
+ baseLength = 15;
264
+ }
265
+ if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
266
+ return "resolvers";
267
+ },
268
+ test: /\.resolver\.(?:ts|js)$/
269
+ }],
270
+ minSize: 0,
271
+ minShareCount: 1
272
+ };
273
+ }
274
+ rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
275
+ if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;
276
+ if (typeof chunkFiles === "function") return chunkFiles(chunkInfo);
277
+ return `chunks/_/[name].mjs`;
278
+ };
279
+ });
280
+ nitro.options.typescript.strict = true;
281
+ nitro.hooks.hook("types:extend", (types) => {
282
+ types.tsConfig ||= {};
283
+ types.tsConfig.compilerOptions ??= {};
284
+ types.tsConfig.compilerOptions.paths ??= {};
285
+ const placeholders = getDefaultPaths(nitro);
286
+ const typesConfig = getTypesConfig(nitro);
287
+ const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
288
+ if (serverTypesPath) types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
289
+ const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
290
+ if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
291
+ types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
292
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
293
+ const servicePlaceholders = {
294
+ ...placeholders,
295
+ serviceName: service.name
296
+ };
297
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
298
+ if (externalTypesPath) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
299
+ }
300
+ types.tsConfig.include = types.tsConfig.include || [];
301
+ if (serverTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
302
+ if (clientTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
303
+ types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
304
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
305
+ const servicePlaceholders = {
306
+ ...placeholders,
307
+ serviceName: service.name
308
+ };
309
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
310
+ if (externalTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
311
+ }
312
+ });
313
+ if (nitro.options.framework?.name === "nuxt" && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
314
+ const nuxtOptions = nitro._nuxt?.options;
315
+ if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
316
+ });
317
+ if (shouldGenerateScaffold(nitro)) {
318
+ const placeholders = getDefaultPaths(nitro);
319
+ const scaffoldConfig = getScaffoldConfig(nitro);
320
+ const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
321
+ if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
322
+ import type { IGraphQLConfig } from 'graphql-config'
323
+
324
+ export default <IGraphQLConfig> {
325
+ projects: {
326
+ default: {
327
+ schema: [
328
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
329
+ ],
330
+ documents: [
331
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
332
+ ],
333
+ },
334
+ },
335
+ }`, "graphql.config.ts");
336
+ const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
337
+ const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
338
+ const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.d.ts", placeholders);
339
+ if (serverSchemaPath || serverConfigPath || serverContextPath) {
340
+ if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
341
+ }
342
+ if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
343
+
344
+ })
345
+ `, "server schema.ts");
346
+ if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
347
+ // import * as tables from '../drizzle/schema/index'
348
+ // import { useDatabase } from '../utils/useDb'
349
+ import { defineGraphQLConfig } from 'nitro-graphql/utils/define'
350
+
351
+ export default defineGraphQLConfig({
352
+ // graphql-yoga example config
353
+ // context: () => {
354
+ // return {
355
+ // context: {
356
+ // useDatabase,
357
+ // tables,
358
+ // },
359
+ // }
360
+ // },
361
+ })
362
+ `, "server config.ts");
363
+ if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
364
+ // import type { Database } from '../utils/useDb'
365
+
366
+ declare module 'nitro/h3' {
367
+ interface H3EventContext {
368
+ // Add your custom context properties here
369
+ // useDatabase: () => Database
370
+ // tables: typeof import('../drizzle/schema')
371
+ // auth?: {
372
+ // user?: {
373
+ // id: string
374
+ // role: 'admin' | 'user'
375
+ // }
376
+ // }
377
+ }
378
+ }
379
+
380
+ export {}
381
+ `, "server context.d.ts");
382
+ if (existsSync(join(nitro.graphql.serverDir, "context.ts"))) {
383
+ consola.warn("nitro-graphql: Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
384
+ consola.info("The context file should now be context.d.ts instead of context.ts");
385
+ }
386
+ } else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
387
+ }
388
+
389
+ //#endregion
390
+ export { setupNitroGraphQL };
@@ -0,0 +1,246 @@
1
+ import { StandardSchemaV1 } from "./standard-schema.mjs";
2
+ import { ESMCodeGenOptions } from "knitwork";
3
+ import { IResolvers } from "@graphql-tools/utils";
4
+ import { TypeScriptPluginConfig } from "@graphql-codegen/typescript";
5
+ import { plugin as plugin$1 } from "@graphql-codegen/typescript-generic-sdk";
6
+ import { TypeScriptDocumentsPluginConfig } from "@graphql-codegen/typescript-operations";
7
+ import { TypeScriptResolversPluginConfig } from "@graphql-codegen/typescript-resolvers";
8
+
9
+ //#region src/types/index.d.ts
10
+ type CodegenServerConfig = TypeScriptPluginConfig & TypeScriptResolversPluginConfig;
11
+ type DocumentModeConfig = Pick<Parameters<typeof plugin$1>[2], 'documentMode'>;
12
+ type DocumentModeEnum = NonNullable<DocumentModeConfig['documentMode']>;
13
+ type DocumentModeType = `${DocumentModeEnum}`;
14
+ type GenericSdkConfig = Omit<Parameters<typeof plugin$1>[2], 'documentMode'> & {
15
+ documentMode?: DocumentModeType;
16
+ };
17
+ type CodegenClientConfig = TypeScriptPluginConfig & TypeScriptDocumentsPluginConfig & {
18
+ endpoint?: string;
19
+ };
20
+ interface IESMImport {
21
+ name: string;
22
+ as?: string;
23
+ type: 'resolver' | 'query' | 'mutation' | 'type' | 'subscription' | 'directive';
24
+ }
25
+ interface GenImport {
26
+ specifier: string;
27
+ imports: IESMImport[];
28
+ options?: ESMCodeGenOptions;
29
+ }
30
+ declare module 'nitro/types' {
31
+ interface Nitro {
32
+ scanSchemas: string[];
33
+ scanDocuments: string[];
34
+ scanResolvers: GenImport[];
35
+ scanDirectives: GenImport[];
36
+ graphql: {
37
+ buildDir: string;
38
+ watchDirs: string[];
39
+ clientDir: string;
40
+ serverDir: string;
41
+ dir: {
42
+ build: string;
43
+ client: string;
44
+ server: string;
45
+ };
46
+ };
47
+ }
48
+ }
49
+ declare module 'nitro/types' {
50
+ interface NitroOptions {
51
+ graphql?: NitroGraphQLOptions;
52
+ }
53
+ interface NitroRuntimeConfig {
54
+ graphql?: NitroGraphQLOptions;
55
+ }
56
+ interface NitroConfig {
57
+ graphql?: NitroGraphQLOptions;
58
+ }
59
+ }
60
+ /**
61
+ * Service-specific path overrides for external GraphQL services
62
+ * These paths override global config for this specific service
63
+ */
64
+ interface ExternalServicePaths {
65
+ /** SDK file path (overrides global sdk.external config) */
66
+ sdk?: FileGenerationConfig;
67
+ /** Type definitions file path (overrides global types.external config) */
68
+ types?: FileGenerationConfig;
69
+ /** ofetch client wrapper path (overrides global clientUtils.ofetch config) */
70
+ ofetch?: FileGenerationConfig;
71
+ }
72
+ interface ExternalGraphQLService {
73
+ /** Unique name for this service (used for file naming and type generation) */
74
+ name: string;
75
+ /** Schema source - can be URL(s) for remote schemas or file path(s) for local schemas */
76
+ schema: string | string[];
77
+ /** GraphQL endpoint for this service */
78
+ endpoint: string;
79
+ /** Optional headers for schema introspection and client requests */
80
+ headers?: Record<string, string> | (() => Record<string, string>);
81
+ /** Optional: specific document patterns for this service */
82
+ documents?: string[];
83
+ /**
84
+ * Optional: Download and cache schema locally for offline usage
85
+ * - true or 'once': Download if file doesn't exist, then use cached version (offline-friendly)
86
+ * - 'always': Check for updates on every build (current behavior)
87
+ * - 'manual': Never download automatically, user manages schema files manually
88
+ * - false: Disable schema downloading
89
+ */
90
+ downloadSchema?: boolean | 'once' | 'always' | 'manual';
91
+ /** Optional: Custom path to save downloaded schema (default: .nitro/graphql/schemas/[serviceName].graphql) */
92
+ downloadPath?: string;
93
+ /** Optional: service-specific codegen configuration */
94
+ codegen?: {
95
+ client?: CodegenClientConfig;
96
+ clientSDK?: GenericSdkConfig;
97
+ };
98
+ /**
99
+ * Optional: Service-specific path overrides
100
+ * These paths take precedence over global config (sdk, types, clientUtils)
101
+ * Supports placeholders: {serviceName}, {buildDir}, {rootDir}, {framework}, {typesDir}, {clientGraphql}
102
+ */
103
+ paths?: ExternalServicePaths;
104
+ }
105
+ interface FederationConfig {
106
+ /** Enable Apollo Federation subgraph support */
107
+ enabled: boolean;
108
+ /** Service name for federation (used in subgraph config) */
109
+ serviceName?: string;
110
+ /** Service version for federation */
111
+ serviceVersion?: string;
112
+ /** Service URL for federation gateway */
113
+ serviceUrl?: string;
114
+ }
115
+ /**
116
+ * File generation control:
117
+ * - false: Do not generate this file
118
+ * - true: Generate at default location
119
+ * - string: Generate at custom path (supports placeholders: {serviceName}, {buildDir}, {rootDir}, {framework})
120
+ */
121
+ type FileGenerationConfig = boolean | string;
122
+ /**
123
+ * Scaffold files configuration
124
+ * Control auto-generation of scaffold/boilerplate files
125
+ */
126
+ interface ScaffoldConfig {
127
+ /** Enable/disable all scaffold files */
128
+ enabled?: boolean;
129
+ /** graphql.config.ts - GraphQL Config file for IDE tooling */
130
+ graphqlConfig?: FileGenerationConfig;
131
+ /** server/graphql/schema.ts - Schema definition file */
132
+ serverSchema?: FileGenerationConfig;
133
+ /** server/graphql/config.ts - GraphQL server configuration */
134
+ serverConfig?: FileGenerationConfig;
135
+ /** server/graphql/context.ts - H3 context augmentation */
136
+ serverContext?: FileGenerationConfig;
137
+ }
138
+ /**
139
+ * Client utilities configuration
140
+ * Control auto-generation of client-side utility files (Nuxt only)
141
+ */
142
+ interface ClientUtilsConfig {
143
+ /** Enable/disable all client utilities */
144
+ enabled?: boolean;
145
+ /** app/graphql/index.ts - Main exports file */
146
+ index?: FileGenerationConfig;
147
+ /** app/graphql/{serviceName}/ofetch.ts - ofetch client wrapper */
148
+ ofetch?: FileGenerationConfig;
149
+ }
150
+ /**
151
+ * SDK files configuration
152
+ * Control auto-generation of GraphQL SDK files
153
+ */
154
+ interface SdkConfig {
155
+ /** Enable/disable all SDK files */
156
+ enabled?: boolean;
157
+ /** app/graphql/default/sdk.ts - Main service SDK */
158
+ main?: FileGenerationConfig;
159
+ /** app/graphql/{serviceName}/sdk.ts - External service SDKs */
160
+ external?: FileGenerationConfig;
161
+ }
162
+ /**
163
+ * Type files configuration
164
+ * Control auto-generation of TypeScript type definition files
165
+ */
166
+ interface TypesConfig {
167
+ /** Enable/disable all type files */
168
+ enabled?: boolean;
169
+ /** .nitro/types/nitro-graphql-server.d.ts - Server-side types */
170
+ server?: FileGenerationConfig;
171
+ /** .nitro/types/nitro-graphql-client.d.ts - Client-side types */
172
+ client?: FileGenerationConfig;
173
+ /** .nitro/types/nitro-graphql-client-{serviceName}.d.ts - External service types */
174
+ external?: FileGenerationConfig;
175
+ }
176
+ /**
177
+ * Global path overrides
178
+ * Set base directories for file generation
179
+ */
180
+ interface PathsConfig {
181
+ /** Server GraphQL directory (default: 'server/graphql') */
182
+ serverGraphql?: string;
183
+ /** Client GraphQL directory (default: 'app/graphql' for Nuxt, 'graphql' for Nitro) */
184
+ clientGraphql?: string;
185
+ /** Build directory (default: '.nitro' or '.nuxt') */
186
+ buildDir?: string;
187
+ /** Types directory (default: '{buildDir}/types') */
188
+ typesDir?: string;
189
+ }
190
+ interface NitroGraphQLOptions {
191
+ framework?: 'graphql-yoga' | 'apollo-server';
192
+ endpoint?: {
193
+ graphql?: string;
194
+ healthCheck?: string;
195
+ };
196
+ playground?: boolean;
197
+ typedefs?: string[];
198
+ resolvers?: Array<IResolvers<any, any>>;
199
+ loader?: {
200
+ include?: RegExp;
201
+ exclude?: RegExp;
202
+ validate?: boolean;
203
+ };
204
+ codegen?: {
205
+ server?: CodegenServerConfig;
206
+ client?: CodegenClientConfig;
207
+ clientSDK?: GenericSdkConfig;
208
+ };
209
+ /** External GraphQL services to generate types and SDKs for */
210
+ externalServices?: ExternalGraphQLService[];
211
+ /** Apollo Federation configuration */
212
+ federation?: FederationConfig;
213
+ /** Server GraphQL directory path */
214
+ serverDir?: string;
215
+ /** Layer directories (populated by Nuxt module) */
216
+ layerDirectories?: string[];
217
+ layerServerDirs?: string[];
218
+ layerAppDirs?: string[];
219
+ /**
220
+ * Scaffold files configuration
221
+ * Set to false to disable all scaffold file generation (library mode)
222
+ */
223
+ scaffold?: false | ScaffoldConfig;
224
+ /**
225
+ * Client utilities configuration
226
+ * Set to false to disable all client utility generation
227
+ */
228
+ clientUtils?: false | ClientUtilsConfig;
229
+ /**
230
+ * SDK files configuration
231
+ * Set to false to disable all SDK generation
232
+ */
233
+ sdk?: false | SdkConfig;
234
+ /**
235
+ * Type files configuration
236
+ * Set to false to disable all type generation
237
+ */
238
+ types?: false | TypesConfig;
239
+ /**
240
+ * Global path overrides
241
+ * Customize base directories for file generation
242
+ */
243
+ paths?: PathsConfig;
244
+ }
245
+ //#endregion
246
+ export { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, ExternalServicePaths, FederationConfig, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, PathsConfig, ScaffoldConfig, SdkConfig, TypesConfig };
@@ -18,11 +18,11 @@ function startServerAndCreateH3Handler(server, options) {
18
18
  });
19
19
  if (body.kind === "chunked") throw new Error("Incremental delivery not implemented");
20
20
  setHeaders(event, Object.fromEntries(headers));
21
- event.res.statusCode = status || 200;
21
+ event.res.status = status || 200;
22
22
  return body.string;
23
23
  } catch (error) {
24
24
  if (error instanceof SyntaxError) {
25
- event.res.statusCode = 400;
25
+ event.res.status = 400;
26
26
  return error.message;
27
27
  } else throw error;
28
28
  }
@@ -1,4 +1,4 @@
1
- import { CodegenClientConfig, ExternalGraphQLService, GenericSdkConfig } from "../types/index.js";
1
+ import { CodegenClientConfig, ExternalGraphQLService, GenericSdkConfig } from "../types/index.mjs";
2
2
  import { GraphQLSchema } from "graphql";
3
3
  import { Source } from "@graphql-tools/utils";
4
4
  import { LoadSchemaOptions, UnnormalizedTypeDefPointer } from "@graphql-tools/load";
@@ -23,14 +23,14 @@ declare function loadExternalSchema(service: ExternalGraphQLService, buildDir?:
23
23
  */
24
24
  declare function downloadAndSaveSchema(service: ExternalGraphQLService, buildDir: string): Promise<string | undefined>;
25
25
  declare function loadGraphQLDocuments(patterns: string | string[]): Promise<Source[]>;
26
- declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string): Promise<false | {
26
+ declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string, virtualTypesPath?: string): Promise<false | {
27
27
  types: string;
28
28
  sdk: string;
29
29
  }>;
30
30
  /**
31
31
  * Generate client types for external GraphQL service
32
32
  */
33
- declare function generateExternalClientTypes(service: ExternalGraphQLService, schema: GraphQLSchema, docs: Source[]): Promise<{
33
+ declare function generateExternalClientTypes(service: ExternalGraphQLService, schema: GraphQLSchema, docs: Source[], virtualTypesPath?: string): Promise<{
34
34
  types: string;
35
35
  sdk: string;
36
36
  } | false>;