nitro-graphql 2.0.0-beta.3 → 2.0.0-beta.30

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 (72) hide show
  1. package/README.md +476 -19
  2. package/dist/define.d.mts +296 -0
  3. package/dist/define.mjs +323 -0
  4. package/dist/ecosystem/nuxt.mjs +109 -0
  5. package/dist/index.d.mts +43 -0
  6. package/dist/index.mjs +63 -0
  7. package/dist/rollup.d.mts +12 -0
  8. package/dist/rollup.mjs +282 -0
  9. package/dist/routes/apollo-server.d.mts +6 -0
  10. package/dist/routes/{apollo-server.js → apollo-server.mjs} +7 -7
  11. package/dist/routes/debug.d.mts +61 -0
  12. package/dist/routes/debug.mjs +445 -0
  13. package/dist/routes/graphql-yoga.d.mts +6 -0
  14. package/dist/routes/{graphql-yoga.js → graphql-yoga.mjs} +11 -7
  15. package/dist/routes/health.d.mts +10 -0
  16. package/dist/routes/{health.js → health.mjs} +3 -2
  17. package/dist/setup.d.mts +11 -0
  18. package/dist/setup.mjs +392 -0
  19. package/dist/{utils/define.d.ts → types/define.d.mts} +4 -27
  20. package/dist/types/define.mjs +1 -0
  21. package/dist/types/index.d.mts +246 -0
  22. package/dist/types/index.mjs +1 -0
  23. package/dist/types/standard-schema.mjs +1 -0
  24. package/dist/utils/{apollo.d.ts → apollo.d.mts} +2 -2
  25. package/dist/utils/apollo.mjs +59 -0
  26. package/dist/utils/{client-codegen.d.ts → client-codegen.d.mts} +6 -3
  27. package/dist/utils/{client-codegen.js → client-codegen.mjs} +6 -6
  28. package/dist/utils/errors.d.mts +73 -0
  29. package/dist/utils/errors.mjs +89 -0
  30. package/dist/utils/file-generator.d.mts +37 -0
  31. package/dist/utils/file-generator.mjs +72 -0
  32. package/dist/utils/{index.d.ts → index.d.mts} +4 -3
  33. package/dist/utils/{index.js → index.mjs} +76 -37
  34. package/dist/utils/path-resolver.d.mts +70 -0
  35. package/dist/utils/path-resolver.mjs +127 -0
  36. package/dist/utils/{server-codegen.d.ts → server-codegen.d.mts} +1 -1
  37. package/dist/utils/{server-codegen.js → server-codegen.mjs} +3 -3
  38. package/dist/utils/type-generation.d.mts +12 -0
  39. package/dist/utils/type-generation.mjs +420 -0
  40. package/dist/virtual/debug-info.d.mts +9 -0
  41. package/dist/virtual/debug-info.mjs +26 -0
  42. package/dist/virtual/graphql-config.d.mts +9 -0
  43. package/dist/virtual/graphql-config.mjs +10 -0
  44. package/dist/virtual/module-config.d.mts +9 -0
  45. package/dist/virtual/module-config.mjs +10 -0
  46. package/dist/virtual/server-directives.d.mts +11 -0
  47. package/dist/virtual/server-directives.mjs +10 -0
  48. package/dist/virtual/server-resolvers.d.mts +11 -0
  49. package/dist/virtual/server-resolvers.mjs +10 -0
  50. package/dist/virtual/server-schemas.d.mts +11 -0
  51. package/dist/virtual/server-schemas.mjs +10 -0
  52. package/package.json +79 -70
  53. package/dist/ecosystem/nuxt.js +0 -67
  54. package/dist/index.d.ts +0 -8
  55. package/dist/index.js +0 -264
  56. package/dist/rollup.js +0 -114
  57. package/dist/routes/apollo-server.d.ts +0 -6
  58. package/dist/routes/graphql-yoga.d.ts +0 -6
  59. package/dist/routes/health.d.ts +0 -6
  60. package/dist/types/index.d.ts +0 -128
  61. package/dist/utils/apollo.js +0 -61
  62. package/dist/utils/define.js +0 -57
  63. package/dist/utils/type-generation.d.ts +0 -7
  64. package/dist/utils/type-generation.js +0 -287
  65. /package/dist/ecosystem/{nuxt.d.ts → nuxt.d.mts} +0 -0
  66. /package/dist/graphql/{index.d.ts → index.d.mts} +0 -0
  67. /package/dist/graphql/{index.js → index.mjs} +0 -0
  68. /package/dist/graphql/{server.d.ts → server.d.mts} +0 -0
  69. /package/dist/graphql/{server.js → server.mjs} +0 -0
  70. /package/dist/types/{standard-schema.d.ts → standard-schema.d.mts} +0 -0
  71. /package/dist/utils/{directive-parser.d.ts → directive-parser.d.mts} +0 -0
  72. /package/dist/utils/{directive-parser.js → directive-parser.mjs} +0 -0
package/dist/setup.mjs ADDED
@@ -0,0 +1,392 @@
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 defu from "defu";
8
+ import { existsSync, mkdirSync } from "node:fs";
9
+ import { fileURLToPath } from "node:url";
10
+ import { watch } from "chokidar";
11
+ import consola from "consola";
12
+ import { dirname, join, relative, resolve } from "pathe";
13
+
14
+ //#region src/setup.ts
15
+ const logger = consola.withTag("nitro-graphql");
16
+ /**
17
+ * Shared setup logic for nitro-graphql module
18
+ * Used by both the direct Nitro module export and the Vite plugin's nitro: hook
19
+ */
20
+ async function setupNitroGraphQL(nitro) {
21
+ nitro.options.graphql ||= {};
22
+ nitro.options.graphql.types = defu(nitro.options.graphql.types, {
23
+ server: ".graphql/nitro-graphql-server.d.ts",
24
+ client: ".graphql/nitro-graphql-client.d.ts",
25
+ enabled: true
26
+ });
27
+ if (!nitro.options.graphql?.framework) logger.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
28
+ if (nitro.options.graphql?.externalServices?.length) {
29
+ const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
30
+ if (validationErrors.length > 0) {
31
+ logger.error("External services configuration errors:");
32
+ for (const error of validationErrors) logger.error(` - ${error}`);
33
+ throw new Error("Invalid external services configuration");
34
+ }
35
+ logger.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
36
+ }
37
+ const { getDefaultPaths } = await import("./utils/path-resolver.mjs");
38
+ const defaultPaths = getDefaultPaths(nitro);
39
+ nitro.graphql ||= {
40
+ buildDir: "",
41
+ watchDirs: [],
42
+ clientDir: defaultPaths.clientGraphql,
43
+ serverDir: defaultPaths.serverGraphql,
44
+ dir: {
45
+ build: relative(nitro.options.rootDir, nitro.options.buildDir),
46
+ client: "graphql",
47
+ server: "server"
48
+ }
49
+ };
50
+ nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
51
+ rollupConfig$1.external = rollupConfig$1.external || [];
52
+ const allExternals = [...["oxc-parser", "@oxc-parser"]];
53
+ if (!nitro.options.graphql?.federation?.enabled) allExternals.push(...[
54
+ "@apollo/subgraph",
55
+ "@apollo/federation-internals",
56
+ "@apollo/cache-control-types"
57
+ ]);
58
+ if (Array.isArray(rollupConfig$1.external)) rollupConfig$1.external.push(...allExternals);
59
+ else if (typeof rollupConfig$1.external === "function") {
60
+ const originalExternal = rollupConfig$1.external;
61
+ rollupConfig$1.external = (id, parent, isResolved) => {
62
+ if (allExternals.some((external) => id.includes(external))) return true;
63
+ return originalExternal(id, parent, isResolved);
64
+ };
65
+ }
66
+ });
67
+ nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, {
68
+ endpoint: {
69
+ graphql: "/api/graphql",
70
+ healthCheck: "/api/graphql/health"
71
+ },
72
+ playground: true
73
+ });
74
+ if (nitro.options.graphql?.federation?.enabled) logger.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
75
+ const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
76
+ nitro.graphql.buildDir = graphqlBuildDir;
77
+ const watchDirs = [];
78
+ switch (nitro.options.framework.name) {
79
+ case "nuxt": {
80
+ nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
81
+ nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
82
+ watchDirs.push(nitro.graphql.clientDir);
83
+ const layerServerDirs = getLayerServerDirectories(nitro);
84
+ const layerAppDirs = getLayerAppDirectories(nitro);
85
+ for (const layerServerDir of layerServerDirs) watchDirs.push(join(layerServerDir, "graphql"));
86
+ for (const layerAppDir of layerAppDirs) watchDirs.push(join(layerAppDir, "graphql"));
87
+ break;
88
+ }
89
+ case "nitro":
90
+ nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
91
+ nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
92
+ watchDirs.push(nitro.graphql.clientDir);
93
+ watchDirs.push(nitro.graphql.serverDir);
94
+ break;
95
+ default:
96
+ }
97
+ if (nitro.options.graphql?.externalServices?.length) {
98
+ for (const service of nitro.options.graphql.externalServices) if (service.documents?.length) for (const pattern of service.documents) {
99
+ if (!pattern) continue;
100
+ const baseDir = pattern.split("**")[0]?.replace(/\/$/, "") || ".";
101
+ const resolvedDir = resolve(nitro.options.rootDir, baseDir);
102
+ if (!watchDirs.includes(resolvedDir)) watchDirs.push(resolvedDir);
103
+ }
104
+ }
105
+ const watcher = watch(watchDirs, {
106
+ persistent: true,
107
+ ignoreInitial: true,
108
+ ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns()]
109
+ }).on("all", async (_, path) => {
110
+ const isGraphQLFile = path.endsWith(".graphql") || path.endsWith(".gql");
111
+ const isResolverFile = path.endsWith(".resolver.ts") || path.endsWith(".resolver.js");
112
+ const isDirectiveFile = path.endsWith(".directive.ts") || path.endsWith(".directive.js");
113
+ if (isGraphQLFile || isResolverFile || isDirectiveFile) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql") || isResolverFile || isDirectiveFile) {
114
+ await scanResolvers(nitro).then((r) => nitro.scanResolvers = r);
115
+ await scanDirectives(nitro).then((d) => nitro.scanDirectives = d);
116
+ logger.success("Types regenerated");
117
+ await serverTypeGeneration(nitro, { silent: true });
118
+ await clientTypeGeneration(nitro, { silent: true });
119
+ await nitro.hooks.callHook("dev:reload");
120
+ } else {
121
+ logger.success("Types regenerated");
122
+ await clientTypeGeneration(nitro, { silent: true });
123
+ }
124
+ });
125
+ nitro.hooks.hook("close", () => {
126
+ watcher.close();
127
+ });
128
+ const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
129
+ nitro.scanSchemas = await scanSchemas(nitro);
130
+ nitro.scanDocuments = await scanDocs(nitro);
131
+ nitro.scanResolvers = await scanResolvers(nitro);
132
+ const directives = await scanDirectives(nitro);
133
+ nitro.scanDirectives = directives;
134
+ await generateDirectiveSchemas(nitro, directives);
135
+ let hasShownInitialLogs = false;
136
+ nitro.hooks.hook("dev:start", async () => {
137
+ nitro.scanSchemas = await scanSchemas(nitro);
138
+ const resolvers = await scanResolvers(nitro);
139
+ nitro.scanResolvers = resolvers;
140
+ const directives$1 = await scanDirectives(nitro);
141
+ nitro.scanDirectives = directives$1;
142
+ await generateDirectiveSchemas(nitro, directives$1);
143
+ nitro.scanDocuments = await scanDocs(nitro);
144
+ if (nitro.options.dev && !hasShownInitialLogs) {
145
+ hasShownInitialLogs = true;
146
+ if (resolvers.length > 0) {
147
+ const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
148
+ const typeCount = {
149
+ query: 0,
150
+ mutation: 0,
151
+ resolver: 0,
152
+ type: 0,
153
+ subscription: 0,
154
+ directive: 0
155
+ };
156
+ for (const resolver of resolvers) for (const imp of resolver.imports) if (imp.type in typeCount) typeCount[imp.type]++;
157
+ const breakdown = [];
158
+ if (typeCount.query > 0) breakdown.push(`${typeCount.query} query`);
159
+ if (typeCount.mutation > 0) breakdown.push(`${typeCount.mutation} mutation`);
160
+ if (typeCount.resolver > 0) breakdown.push(`${typeCount.resolver} resolver`);
161
+ if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
162
+ if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
163
+ if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
164
+ if (breakdown.length > 0) logger.success(`${totalExports} resolver export(s): ${breakdown.join(", ")}`);
165
+ } else logger.warn("No resolvers found. Check /_nitro/graphql/debug for details.");
166
+ }
167
+ });
168
+ await rollupConfig(nitro);
169
+ await serverTypeGeneration(nitro);
170
+ await clientTypeGeneration(nitro, { isInitial: true });
171
+ nitro.hooks.hook("close", async () => {
172
+ await serverTypeGeneration(nitro, { silent: true });
173
+ await clientTypeGeneration(nitro, { silent: true });
174
+ });
175
+ const runtime = fileURLToPath(new URL("routes", import.meta.url));
176
+ const methods = [
177
+ "GET",
178
+ "POST",
179
+ "OPTIONS"
180
+ ];
181
+ if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
182
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
183
+ handler: join(runtime, "graphql-yoga"),
184
+ method
185
+ });
186
+ if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
187
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
188
+ handler: join(runtime, "apollo-server"),
189
+ method
190
+ });
191
+ nitro.options.handlers.push({
192
+ route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
193
+ handler: join(runtime, "health"),
194
+ method: "GET"
195
+ });
196
+ if (nitro.options.dev) nitro.options.handlers.push({
197
+ route: "/_nitro/graphql/debug",
198
+ handler: join(runtime, "debug"),
199
+ method: "GET"
200
+ });
201
+ if (nitro.options.imports) {
202
+ nitro.options.imports.presets ??= [];
203
+ nitro.options.imports.presets.push({
204
+ from: fileURLToPath(new URL("define", import.meta.url)),
205
+ imports: [
206
+ "defineResolver",
207
+ "defineMutation",
208
+ "defineQuery",
209
+ "defineSubscription",
210
+ "defineType",
211
+ "defineGraphQLConfig",
212
+ "defineSchema",
213
+ "defineDirective"
214
+ ]
215
+ });
216
+ }
217
+ nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
218
+ const manualChunks = rollupConfig$1.output?.manualChunks;
219
+ const chunkFiles = rollupConfig$1.output?.chunkFileNames;
220
+ if (!rollupConfig$1.output.inlineDynamicImports) {
221
+ rollupConfig$1.output.manualChunks = (id, meta) => {
222
+ if (id.endsWith(".graphql") || id.endsWith(".gql")) {
223
+ let graphqlIndex = id.indexOf("server/graphql/");
224
+ let baseLength = 15;
225
+ if (graphqlIndex === -1) {
226
+ graphqlIndex = id.indexOf("routes/graphql/");
227
+ baseLength = 15;
228
+ }
229
+ if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
230
+ return "schemas";
231
+ }
232
+ if (id.endsWith(".resolver.ts")) {
233
+ let graphqlIndex = id.indexOf("server/graphql/");
234
+ let baseLength = 15;
235
+ if (graphqlIndex === -1) {
236
+ graphqlIndex = id.indexOf("routes/graphql/");
237
+ baseLength = 15;
238
+ }
239
+ if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
240
+ return "resolvers";
241
+ }
242
+ if (typeof manualChunks === "function") return manualChunks(id, meta);
243
+ };
244
+ rollupConfig$1.output.advancedChunks = {
245
+ groups: [{
246
+ name: (moduleId) => {
247
+ if (!moduleId.endsWith(".graphql") && !moduleId.endsWith(".gql")) return;
248
+ let graphqlIndex = moduleId.indexOf("server/graphql/");
249
+ let baseLength = 15;
250
+ if (graphqlIndex === -1) {
251
+ graphqlIndex = moduleId.indexOf("routes/graphql/");
252
+ baseLength = 15;
253
+ }
254
+ if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
255
+ return "schemas";
256
+ },
257
+ test: /\.(?:graphql|gql)$/
258
+ }, {
259
+ name: (moduleId) => {
260
+ if (!moduleId.endsWith(".resolver.ts")) return;
261
+ let graphqlIndex = moduleId.indexOf("server/graphql/");
262
+ let baseLength = 15;
263
+ if (graphqlIndex === -1) {
264
+ graphqlIndex = moduleId.indexOf("routes/graphql/");
265
+ baseLength = 15;
266
+ }
267
+ if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
268
+ return "resolvers";
269
+ },
270
+ test: /\.resolver\.(?:ts|js)$/
271
+ }],
272
+ minSize: 0,
273
+ minShareCount: 1
274
+ };
275
+ }
276
+ rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
277
+ if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;
278
+ if (typeof chunkFiles === "function") return chunkFiles(chunkInfo);
279
+ return `chunks/_/[name].mjs`;
280
+ };
281
+ });
282
+ nitro.options.typescript.strict = true;
283
+ nitro.hooks.hook("types:extend", (types) => {
284
+ types.tsConfig ||= {};
285
+ types.tsConfig.compilerOptions ??= {};
286
+ types.tsConfig.compilerOptions.paths ??= {};
287
+ const placeholders = getDefaultPaths(nitro);
288
+ const typesConfig = getTypesConfig(nitro);
289
+ const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
290
+ if (serverTypesPath) types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
291
+ const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
292
+ if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
293
+ types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
294
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
295
+ const servicePlaceholders = {
296
+ ...placeholders,
297
+ serviceName: service.name
298
+ };
299
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
300
+ if (externalTypesPath) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
301
+ }
302
+ types.tsConfig.include = types.tsConfig.include || [];
303
+ if (serverTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
304
+ if (clientTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
305
+ types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
306
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
307
+ const servicePlaceholders = {
308
+ ...placeholders,
309
+ serviceName: service.name
310
+ };
311
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
312
+ if (externalTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
313
+ }
314
+ });
315
+ if (nitro.options.framework?.name === "nuxt" && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
316
+ const nuxtOptions = nitro._nuxt?.options;
317
+ if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
318
+ });
319
+ if (shouldGenerateScaffold(nitro)) {
320
+ const placeholders = getDefaultPaths(nitro);
321
+ const scaffoldConfig = getScaffoldConfig(nitro);
322
+ const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
323
+ if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
324
+ import type { IGraphQLConfig } from 'graphql-config'
325
+
326
+ export default <IGraphQLConfig> {
327
+ projects: {
328
+ default: {
329
+ schema: [
330
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
331
+ ],
332
+ documents: [
333
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
334
+ ],
335
+ },
336
+ },
337
+ }`, "graphql.config.ts");
338
+ const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
339
+ const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
340
+ const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.d.ts", placeholders);
341
+ if (serverSchemaPath || serverConfigPath || serverContextPath) {
342
+ if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
343
+ }
344
+ if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
345
+
346
+ })
347
+ `, "server schema.ts");
348
+ if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
349
+ // import * as tables from '../drizzle/schema/index'
350
+ // import { useDatabase } from '../utils/useDb'
351
+ import { defineGraphQLConfig } from 'nitro-graphql/define'
352
+
353
+ export default defineGraphQLConfig({
354
+ // graphql-yoga example config
355
+ // context: () => {
356
+ // return {
357
+ // context: {
358
+ // useDatabase,
359
+ // tables,
360
+ // },
361
+ // }
362
+ // },
363
+ })
364
+ `, "server config.ts");
365
+ if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
366
+ // import type { Database } from '../utils/useDb'
367
+
368
+ declare module 'nitro/h3' {
369
+ interface H3EventContext {
370
+ // Add your custom context properties here
371
+ // useDatabase: () => Database
372
+ // tables: typeof import('../drizzle/schema')
373
+ // auth?: {
374
+ // user?: {
375
+ // id: string
376
+ // role: 'admin' | 'user'
377
+ // }
378
+ // }
379
+ }
380
+ }
381
+
382
+ export {}
383
+ `, "server context.d.ts");
384
+ if (existsSync(join(nitro.graphql.serverDir, "context.ts"))) {
385
+ logger.warn("Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
386
+ logger.info("The context file should now be context.d.ts instead of context.ts");
387
+ }
388
+ } else logger.info("Scaffold file generation is disabled (library mode)");
389
+ }
390
+
391
+ //#endregion
392
+ export { setupNitroGraphQL };
@@ -1,23 +1,12 @@
1
1
  import { GraphQLSchema } from "graphql";
2
2
  import { ApolloServerOptions } from "@apollo/server";
3
- import { H3Event } from "h3";
3
+ import { H3Event } from "nitro/h3";
4
4
  import { YogaServerOptions } from "graphql-yoga";
5
- import { NPMConfig, Resolvers, ResolversTypes } from "#graphql/server";
6
- import { StandardSchemaV1 } from "nitro-graphql";
5
+ import { NPMConfig } from "#graphql/server";
7
6
 
8
- //#region src/utils/define.d.ts
7
+ //#region src/types/define.d.ts
9
8
  type Flatten<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
10
- declare function defineSchema<T extends Partial<Record<keyof ResolversTypes, StandardSchemaV1>>>(config: T): Flatten<T>;
11
- declare function defineResolver(resolvers: Resolvers): Resolvers;
12
- type ResolverQuery = Resolvers extends {
13
- Query: infer Q;
14
- } ? Q : never;
15
- declare function defineQuery(resolvers?: Resolvers['Query']): Resolvers;
16
- declare function defineMutation(resolvers?: Resolvers['Mutation']): Resolvers;
17
- declare function defineSubscription(resolvers?: Resolvers['Subscription']): Resolvers;
18
- declare function defineType(resolvers: Resolvers): Resolvers;
19
9
  type DefineServerConfig<T extends NPMConfig = NPMConfig> = T['framework'] extends 'graphql-yoga' ? Partial<YogaServerOptions<H3Event, Partial<H3Event>>> : T['framework'] extends 'apollo-server' ? Partial<ApolloServerOptions<H3Event>> : Partial<YogaServerOptions<H3Event, Partial<H3Event>>> | Partial<ApolloServerOptions<H3Event>>;
20
- declare function defineGraphQLConfig<T extends NPMConfig = NPMConfig>(config: Partial<DefineServerConfig<T>>): Partial<DefineServerConfig<T>>;
21
10
  type DirectiveLocationName = 'QUERY' | 'MUTATION' | 'SUBSCRIPTION' | 'FIELD' | 'FRAGMENT_DEFINITION' | 'FRAGMENT_SPREAD' | 'INLINE_FRAGMENT' | 'VARIABLE_DEFINITION' | 'SCHEMA' | 'SCALAR' | 'OBJECT' | 'FIELD_DEFINITION' | 'ARGUMENT_DEFINITION' | 'INTERFACE' | 'UNION' | 'ENUM' | 'ENUM_VALUE' | 'INPUT_OBJECT' | 'INPUT_FIELD_DEFINITION';
22
11
  type GraphQLScalarType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID' | 'JSON' | 'DateTime';
23
12
  type GraphQLBaseType = GraphQLScalarType | (string & {});
@@ -56,17 +45,5 @@ interface DefineDirectiveConfig {
56
45
  isRepeatable?: boolean;
57
46
  transformer?: (schema: GraphQLSchema) => GraphQLSchema;
58
47
  }
59
- /**
60
- * Helper function to create directive arguments with proper type inference
61
- * @example
62
- * args: {
63
- * myArg: arg('String!', { defaultValue: 'hello' })
64
- * }
65
- */
66
- declare function arg<T extends GraphQLArgumentType>(type: T, options?: {
67
- defaultValue?: any;
68
- description?: string;
69
- }): DirectiveArgument<T>;
70
- declare function defineDirective(config: DefineDirectiveConfig): DirectiveDefinition;
71
48
  //#endregion
72
- export { DefineDirectiveConfig, DefineServerConfig, DirectiveArgument, DirectiveDefinition, GraphQLArgumentType, GraphQLBaseType, GraphQLScalarType, ResolverQuery, arg, defineDirective, defineGraphQLConfig, defineMutation, defineQuery, defineResolver, defineSchema, defineSubscription, defineType };
49
+ export { DefineDirectiveConfig, DefineServerConfig, DirectiveArgument, DirectiveDefinition, Flatten, GraphQLArgumentType, GraphQLBaseType, GraphQLScalarType };
@@ -0,0 +1 @@
1
+ export { };
@@ -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, StandardSchemaV1, TypesConfig };