nitro-graphql 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +137 -121
- package/dist/rollup.mjs +3 -15
- package/dist/routes/apollo-server-ws.d.mts +2 -2
- package/dist/routes/graphql-yoga-ws.d.mts +2 -2
- package/dist/routes/graphql-yoga.d.mts +2 -2
- package/dist/routes/health.d.mts +2 -2
- package/dist/types/index.d.mts +13 -3
- package/dist/utils/client-codegen.mjs +6 -4
- package/dist/utils/index.mjs +0 -1
- package/dist/utils/type-generation.mjs +0 -7
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -31,7 +31,8 @@ function resolveSecurityConfig(config) {
|
|
|
31
31
|
var src_default = defineNitroModule({
|
|
32
32
|
name: "nitro-graphql",
|
|
33
33
|
async setup(nitro) {
|
|
34
|
-
|
|
34
|
+
const serverEnabled = nitro.options.graphql?.server !== false;
|
|
35
|
+
if (serverEnabled && !nitro.options.graphql?.framework) consola.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
|
|
35
36
|
if (nitro.options.graphql?.externalServices?.length) {
|
|
36
37
|
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
37
38
|
if (validationErrors.length > 0) {
|
|
@@ -117,123 +118,133 @@ var src_default = defineNitroModule({
|
|
|
117
118
|
watcher.close();
|
|
118
119
|
});
|
|
119
120
|
const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
|
|
120
|
-
|
|
121
|
+
if (serverEnabled) {
|
|
122
|
+
nitro.scanSchemas = await scanSchemas(nitro);
|
|
123
|
+
nitro.scanResolvers = await scanResolvers(nitro);
|
|
124
|
+
const directives = await scanDirectives(nitro);
|
|
125
|
+
nitro.scanDirectives = directives;
|
|
126
|
+
await generateDirectiveSchemas(nitro, directives);
|
|
127
|
+
} else {
|
|
128
|
+
nitro.scanSchemas = [];
|
|
129
|
+
nitro.scanResolvers = [];
|
|
130
|
+
nitro.scanDirectives = [];
|
|
131
|
+
}
|
|
121
132
|
nitro.scanDocuments = await scanDocs(nitro);
|
|
122
|
-
nitro.scanResolvers = await scanResolvers(nitro);
|
|
123
|
-
const directives = await scanDirectives(nitro);
|
|
124
|
-
nitro.scanDirectives = directives;
|
|
125
|
-
await generateDirectiveSchemas(nitro, directives);
|
|
126
133
|
nitro.hooks.hook("dev:start", async () => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
let schemas = [];
|
|
135
|
+
let resolvers = [];
|
|
136
|
+
let directives = [];
|
|
137
|
+
if (serverEnabled) {
|
|
138
|
+
schemas = await scanSchemas(nitro);
|
|
139
|
+
nitro.scanSchemas = schemas;
|
|
140
|
+
resolvers = await scanResolvers(nitro);
|
|
141
|
+
nitro.scanResolvers = resolvers;
|
|
142
|
+
directives = await scanDirectives(nitro);
|
|
143
|
+
nitro.scanDirectives = directives;
|
|
144
|
+
await generateDirectiveSchemas(nitro, directives);
|
|
145
|
+
}
|
|
134
146
|
const docs = await scanDocs(nitro);
|
|
135
147
|
nitro.scanDocuments = docs;
|
|
136
148
|
if (nitro.options.dev) {
|
|
137
149
|
const runtimeSecurityConfig = nitro.options.runtimeConfig.graphql?.security;
|
|
138
150
|
const isProd = process.env.NODE_ENV === "production";
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
|
|
180
|
-
if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
|
|
181
|
-
} else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
151
|
+
if (serverEnabled) {
|
|
152
|
+
consola.box({
|
|
153
|
+
title: "Nitro GraphQL",
|
|
154
|
+
message: [
|
|
155
|
+
`Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
|
|
156
|
+
`Environment: ${isProd ? "production" : "development"}`,
|
|
157
|
+
`Schemas: ${schemas.length}`,
|
|
158
|
+
`Resolvers: ${resolvers.length}`,
|
|
159
|
+
`Directives: ${directives.length}`,
|
|
160
|
+
`Documents: ${docs.length}`,
|
|
161
|
+
"",
|
|
162
|
+
"Security:",
|
|
163
|
+
`├─ Introspection: ${runtimeSecurityConfig?.introspection ? "enabled" : "disabled"}`,
|
|
164
|
+
`├─ Playground: ${runtimeSecurityConfig?.playground ? "enabled" : "disabled"}`,
|
|
165
|
+
`├─ Error Masking: ${runtimeSecurityConfig?.maskErrors ? "enabled" : "disabled"}`,
|
|
166
|
+
`└─ Field Suggestions: ${runtimeSecurityConfig?.disableSuggestions ? "disabled" : "enabled"}`,
|
|
167
|
+
"",
|
|
168
|
+
"Debug Dashboard: /_nitro/graphql/debug"
|
|
169
|
+
].join("\n"),
|
|
170
|
+
style: {
|
|
171
|
+
borderColor: isProd ? "yellow" : "cyan",
|
|
172
|
+
borderStyle: "rounded"
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
if (resolvers.length === 0) consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
176
|
+
} else {
|
|
177
|
+
const externalServicesCount = nitro.options.graphql?.externalServices?.length || 0;
|
|
178
|
+
consola.box({
|
|
179
|
+
title: "Nitro GraphQL (Client Only)",
|
|
180
|
+
message: [
|
|
181
|
+
"Server mode: disabled",
|
|
182
|
+
`External Services: ${externalServicesCount}`,
|
|
183
|
+
`Documents: ${docs.length}`
|
|
184
|
+
].join("\n"),
|
|
185
|
+
style: {
|
|
186
|
+
borderColor: "blue",
|
|
187
|
+
borderStyle: "rounded"
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
182
191
|
}
|
|
183
192
|
});
|
|
184
|
-
await rollupConfig(nitro);
|
|
185
|
-
|
|
193
|
+
if (serverEnabled) await rollupConfig(nitro);
|
|
194
|
+
else nitro.hooks.hook("dev:reload", async () => {
|
|
195
|
+
await clientTypeGeneration(nitro);
|
|
196
|
+
});
|
|
197
|
+
if (serverEnabled) await serverTypeGeneration(nitro);
|
|
186
198
|
await clientTypeGeneration(nitro);
|
|
187
199
|
nitro.hooks.hook("close", async () => {
|
|
188
|
-
await serverTypeGeneration(nitro);
|
|
200
|
+
if (serverEnabled) await serverTypeGeneration(nitro);
|
|
189
201
|
await clientTypeGeneration(nitro);
|
|
190
202
|
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
|
|
203
|
-
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
204
|
-
handler: join(runtime, "apollo-server"),
|
|
205
|
-
method
|
|
206
|
-
});
|
|
207
|
-
nitro.options.handlers.push({
|
|
208
|
-
route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
|
|
209
|
-
handler: join(runtime, "health"),
|
|
210
|
-
method: "get"
|
|
211
|
-
});
|
|
212
|
-
if (nitro.options.graphql?.subscriptions?.enabled) {
|
|
213
|
-
nitro.options.experimental ||= {};
|
|
214
|
-
nitro.options.experimental.websocket = true;
|
|
215
|
-
const wsEndpoint = nitro.options.runtimeConfig.graphql?.endpoint?.ws || nitro.options.graphql?.subscriptions?.endpoint || "/api/graphql/ws";
|
|
216
|
-
if (nitro.options.graphql?.framework === "graphql-yoga") nitro.options.handlers.push({
|
|
217
|
-
route: wsEndpoint,
|
|
218
|
-
handler: join(runtime, "graphql-yoga-ws")
|
|
203
|
+
if (serverEnabled) {
|
|
204
|
+
const runtime = fileURLToPath(new URL("routes", import.meta.url));
|
|
205
|
+
const methods = [
|
|
206
|
+
"get",
|
|
207
|
+
"post",
|
|
208
|
+
"options"
|
|
209
|
+
];
|
|
210
|
+
if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
|
|
211
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
212
|
+
handler: join(runtime, "graphql-yoga"),
|
|
213
|
+
method
|
|
219
214
|
});
|
|
220
|
-
if (nitro.options.graphql?.framework === "apollo-server") nitro.options.handlers.push({
|
|
221
|
-
route:
|
|
222
|
-
handler: join(runtime, "apollo-server
|
|
215
|
+
if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
|
|
216
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
217
|
+
handler: join(runtime, "apollo-server"),
|
|
218
|
+
method
|
|
223
219
|
});
|
|
224
|
-
nitro.options.plugins ??= [];
|
|
225
|
-
nitro.options.plugins.push(join(runtime, "ws-shutdown"));
|
|
226
|
-
consola.info(`[nitro-graphql] WebSocket subscriptions enabled at: ${wsEndpoint}`);
|
|
227
|
-
}
|
|
228
|
-
if (nitro.options.dev) {
|
|
229
220
|
nitro.options.handlers.push({
|
|
221
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
|
|
222
|
+
handler: join(runtime, "health"),
|
|
223
|
+
method: "get"
|
|
224
|
+
});
|
|
225
|
+
if (nitro.options.graphql?.subscriptions?.enabled) {
|
|
226
|
+
nitro.options.experimental ||= {};
|
|
227
|
+
nitro.options.experimental.websocket = true;
|
|
228
|
+
const wsEndpoint = nitro.options.runtimeConfig.graphql?.endpoint?.ws || nitro.options.graphql?.subscriptions?.endpoint || "/api/graphql/ws";
|
|
229
|
+
if (nitro.options.graphql?.framework === "graphql-yoga") nitro.options.handlers.push({
|
|
230
|
+
route: wsEndpoint,
|
|
231
|
+
handler: join(runtime, "graphql-yoga-ws")
|
|
232
|
+
});
|
|
233
|
+
if (nitro.options.graphql?.framework === "apollo-server") nitro.options.handlers.push({
|
|
234
|
+
route: wsEndpoint,
|
|
235
|
+
handler: join(runtime, "apollo-server-ws")
|
|
236
|
+
});
|
|
237
|
+
nitro.options.plugins ??= [];
|
|
238
|
+
nitro.options.plugins.push(join(runtime, "ws-shutdown"));
|
|
239
|
+
consola.info(`[nitro-graphql] WebSocket subscriptions enabled at: ${wsEndpoint}`);
|
|
240
|
+
}
|
|
241
|
+
if (nitro.options.dev) nitro.options.handlers.push({
|
|
230
242
|
route: "/_nitro/graphql/debug",
|
|
231
243
|
handler: join(runtime, "debug"),
|
|
232
244
|
method: "get"
|
|
233
245
|
});
|
|
234
|
-
consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
|
|
235
246
|
}
|
|
236
|
-
if (nitro.options.imports) {
|
|
247
|
+
if (serverEnabled && nitro.options.imports) {
|
|
237
248
|
nitro.options.imports.presets ??= [];
|
|
238
249
|
nitro.options.imports.presets.push({
|
|
239
250
|
from: fileURLToPath(new URL("utils/define", import.meta.url)),
|
|
@@ -250,7 +261,7 @@ var src_default = defineNitroModule({
|
|
|
250
261
|
]
|
|
251
262
|
});
|
|
252
263
|
}
|
|
253
|
-
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
264
|
+
if (serverEnabled) nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
254
265
|
const manualChunks = rollupConfig$1.output?.manualChunks;
|
|
255
266
|
const chunkFiles = rollupConfig$1.output?.chunkFileNames;
|
|
256
267
|
if (!rollupConfig$1.output.inlineDynamicImports) rollupConfig$1.output.manualChunks = (id, meta) => {
|
|
@@ -271,11 +282,14 @@ var src_default = defineNitroModule({
|
|
|
271
282
|
types.tsConfig.compilerOptions.paths ??= {};
|
|
272
283
|
const placeholders = getDefaultPaths(nitro);
|
|
273
284
|
const typesConfig = getTypesConfig(nitro);
|
|
274
|
-
|
|
275
|
-
if (
|
|
285
|
+
let serverTypesPath = null;
|
|
286
|
+
if (serverEnabled) {
|
|
287
|
+
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
|
+
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
290
|
+
}
|
|
276
291
|
const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
|
|
277
292
|
if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
|
|
278
|
-
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
279
293
|
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
|
|
280
294
|
const servicePlaceholders = {
|
|
281
295
|
...placeholders,
|
|
@@ -304,8 +318,9 @@ var src_default = defineNitroModule({
|
|
|
304
318
|
if (shouldGenerateScaffold(nitro)) {
|
|
305
319
|
const placeholders = getDefaultPaths(nitro);
|
|
306
320
|
const scaffoldConfig = getScaffoldConfig(nitro);
|
|
307
|
-
|
|
308
|
-
|
|
321
|
+
if (serverEnabled) {
|
|
322
|
+
const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
|
|
323
|
+
if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
|
|
309
324
|
import type { IGraphQLConfig } from 'graphql-config'
|
|
310
325
|
|
|
311
326
|
export default <IGraphQLConfig> {
|
|
@@ -320,17 +335,17 @@ export default <IGraphQLConfig> {
|
|
|
320
335
|
},
|
|
321
336
|
},
|
|
322
337
|
}`, "graphql.config.ts");
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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.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({
|
|
330
345
|
|
|
331
346
|
})
|
|
332
347
|
`, "server schema.ts");
|
|
333
|
-
|
|
348
|
+
if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
|
|
334
349
|
// import * as tables from '../drizzle/schema/index'
|
|
335
350
|
// import { useDatabase } from '../utils/useDb'
|
|
336
351
|
|
|
@@ -346,7 +361,7 @@ export default defineGraphQLConfig({
|
|
|
346
361
|
// },
|
|
347
362
|
})
|
|
348
363
|
`, "server config.ts");
|
|
349
|
-
|
|
364
|
+
if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
|
|
350
365
|
// import type { Database } from '../utils/useDb'
|
|
351
366
|
|
|
352
367
|
declare module 'h3' {
|
|
@@ -362,15 +377,16 @@ declare module 'h3' {
|
|
|
362
377
|
// }
|
|
363
378
|
}
|
|
364
379
|
}`, "server context.ts");
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
380
|
+
if (existsSync(join(nitro.graphql.serverDir, "context.d.ts"))) {
|
|
381
|
+
consola.warn("nitro-graphql: Found context.d.ts file. Please rename it to context.ts for the new structure.");
|
|
382
|
+
consola.info("The context file should now be context.ts instead of context.d.ts");
|
|
383
|
+
}
|
|
384
|
+
if (nitro.options.graphql?.subscriptions?.enabled) {
|
|
385
|
+
if (!existsSync(nitro.graphql.clientDir)) mkdirSync(nitro.graphql.clientDir, { recursive: true });
|
|
386
|
+
const defaultDir = resolve(nitro.graphql.clientDir, "default");
|
|
387
|
+
if (!existsSync(defaultDir)) mkdirSync(defaultDir, { recursive: true });
|
|
388
|
+
writeFileIfNotExists(resolve(defaultDir, "subscribe.ts"), subscribeClientTemplate, "subscribe.ts");
|
|
389
|
+
}
|
|
374
390
|
}
|
|
375
391
|
} else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
|
|
376
392
|
}
|
package/dist/rollup.mjs
CHANGED
|
@@ -62,15 +62,13 @@ function virtualSchemas(app) {
|
|
|
62
62
|
}
|
|
63
63
|
const importStatements = imports.map((handler) => `import ${getImportId(handler)} from '${handler}';`);
|
|
64
64
|
const schemaArray = imports.map((h) => `{ def: ${getImportId(h)} }`);
|
|
65
|
-
|
|
65
|
+
return `
|
|
66
66
|
${importStatements.join("\n")}
|
|
67
67
|
|
|
68
68
|
export const schemas = [
|
|
69
69
|
${schemaArray.join(",\n")}
|
|
70
70
|
];
|
|
71
71
|
`;
|
|
72
|
-
if (app.options.dev) app.logger.success(`[nitro-graphql] Generated virtual schema module: ${imports.length} schema(s)`);
|
|
73
|
-
return code;
|
|
74
72
|
} catch (error) {
|
|
75
73
|
app.logger.error("[nitro-graphql] Failed to generate virtual schema module:", error);
|
|
76
74
|
return "export const schemas = []";
|
|
@@ -108,7 +106,7 @@ function virtualResolvers(app) {
|
|
|
108
106
|
for (const msg of invalidImports) app.logger.warn(` - ${msg}`);
|
|
109
107
|
}
|
|
110
108
|
const data = imports.map(({ imports: importList }) => importList.map((i) => `{ resolver: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n");
|
|
111
|
-
|
|
109
|
+
return [
|
|
112
110
|
...importsContent,
|
|
113
111
|
"",
|
|
114
112
|
"export const resolvers = [",
|
|
@@ -116,11 +114,6 @@ function virtualResolvers(app) {
|
|
|
116
114
|
"]",
|
|
117
115
|
""
|
|
118
116
|
].join("\n");
|
|
119
|
-
if (app.options.dev) {
|
|
120
|
-
const totalExports = imports.reduce((sum, r) => sum + r.imports.length, 0);
|
|
121
|
-
app.logger.success(`[nitro-graphql] Generated virtual resolver module: ${totalExports} export(s) from ${imports.length} file(s)`);
|
|
122
|
-
}
|
|
123
|
-
return code;
|
|
124
117
|
} catch (error) {
|
|
125
118
|
app.logger.error("[nitro-graphql] Failed to generate virtual resolver module:", error);
|
|
126
119
|
return "export const resolvers = []";
|
|
@@ -155,7 +148,7 @@ function virtualDirectives(app) {
|
|
|
155
148
|
for (const msg of invalidImports) app.logger.warn(` - ${msg}`);
|
|
156
149
|
}
|
|
157
150
|
const data = imports.map(({ imports: importList }) => importList.map((i) => `{ directive: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n");
|
|
158
|
-
|
|
151
|
+
return [
|
|
159
152
|
...importsContent,
|
|
160
153
|
"",
|
|
161
154
|
"export const directives = [",
|
|
@@ -163,11 +156,6 @@ function virtualDirectives(app) {
|
|
|
163
156
|
"]",
|
|
164
157
|
""
|
|
165
158
|
].join("\n");
|
|
166
|
-
if (app.options.dev) {
|
|
167
|
-
const totalExports = imports.reduce((sum, d) => sum + d.imports.length, 0);
|
|
168
|
-
app.logger.success(`[nitro-graphql] Generated virtual directive module: ${totalExports} directive(s) from ${imports.length} file(s)`);
|
|
169
|
-
}
|
|
170
|
-
return code;
|
|
171
159
|
} catch (error) {
|
|
172
160
|
app.logger.error("[nitro-graphql] Failed to generate virtual directive module:", error);
|
|
173
161
|
return "export const directives = []";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h33 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/apollo-server-ws.d.ts
|
|
4
4
|
|
|
@@ -7,6 +7,6 @@ import * as h39 from "h3";
|
|
|
7
7
|
* Called by the Nitro runtime plugin on server close.
|
|
8
8
|
*/
|
|
9
9
|
declare function shutdownAllConnections(): Promise<void>;
|
|
10
|
-
declare const _default:
|
|
10
|
+
declare const _default: h33.EventHandler<h33.EventHandlerRequest, never>;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { _default as default, shutdownAllConnections };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h37 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/graphql-yoga-ws.d.ts
|
|
4
4
|
|
|
@@ -7,6 +7,6 @@ import * as h31 from "h3";
|
|
|
7
7
|
* Called by the Nitro runtime plugin on server close.
|
|
8
8
|
*/
|
|
9
9
|
declare function shutdownAllConnections(): Promise<void>;
|
|
10
|
-
declare const _default:
|
|
10
|
+
declare const _default: h37.EventHandler<h37.EventHandlerRequest, never>;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { _default as default, shutdownAllConnections };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h39 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/graphql-yoga.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h39.EventHandler<h39.EventHandlerRequest, Promise<Response>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/routes/health.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h31 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/health.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h31.EventHandler<h31.EventHandlerRequest, Promise<{
|
|
5
5
|
status: string;
|
|
6
6
|
message: string;
|
|
7
7
|
timestamp: string;
|
package/dist/types/index.d.mts
CHANGED
|
@@ -79,10 +79,13 @@ interface ExternalServicePaths {
|
|
|
79
79
|
interface ExternalGraphQLService {
|
|
80
80
|
/** Unique name for this service (used for file naming and type generation) */
|
|
81
81
|
name: string;
|
|
82
|
-
/**
|
|
83
|
-
schema: string | string[];
|
|
84
|
-
/** GraphQL endpoint for this service */
|
|
82
|
+
/** GraphQL endpoint for this service (also used as schema source if `schema` is not specified) */
|
|
85
83
|
endpoint: string;
|
|
84
|
+
/**
|
|
85
|
+
* Schema source - can be URL(s) for remote schemas or file path(s) for local schemas
|
|
86
|
+
* @default Uses `endpoint` for introspection if not specified
|
|
87
|
+
*/
|
|
88
|
+
schema?: string | string[];
|
|
86
89
|
/** Optional headers for schema introspection and client requests */
|
|
87
90
|
headers?: Record<string, string> | (() => Record<string, string>);
|
|
88
91
|
/** Optional: specific document patterns for this service */
|
|
@@ -235,6 +238,13 @@ interface SecurityConfig {
|
|
|
235
238
|
}
|
|
236
239
|
interface NitroGraphQLOptions {
|
|
237
240
|
framework: 'graphql-yoga' | 'apollo-server';
|
|
241
|
+
/**
|
|
242
|
+
* Enable/disable GraphQL server functionality
|
|
243
|
+
* When set to false, only external services client types will be generated
|
|
244
|
+
* Server routes, resolvers, schemas, and directives will not be processed
|
|
245
|
+
* @default true
|
|
246
|
+
*/
|
|
247
|
+
server?: boolean;
|
|
238
248
|
endpoint?: {
|
|
239
249
|
graphql?: string;
|
|
240
250
|
healthCheck?: string;
|
|
@@ -53,7 +53,8 @@ async function graphQLLoadSchemaSync(schemaPointers, data = {}) {
|
|
|
53
53
|
async function loadExternalSchema(service, buildDir) {
|
|
54
54
|
try {
|
|
55
55
|
const headers = typeof service.headers === "function" ? service.headers() : service.headers || {};
|
|
56
|
-
const
|
|
56
|
+
const schemaSource = service.schema ?? service.endpoint;
|
|
57
|
+
const schemas = Array.isArray(schemaSource) ? schemaSource : [schemaSource];
|
|
57
58
|
if (service.downloadSchema && buildDir) {
|
|
58
59
|
const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
|
|
59
60
|
const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
|
|
@@ -88,14 +89,15 @@ function isUrl(path) {
|
|
|
88
89
|
* Download and save schema from external service
|
|
89
90
|
*/
|
|
90
91
|
async function downloadAndSaveSchema(service, buildDir) {
|
|
91
|
-
const
|
|
92
|
+
const schemaSource = service.schema ?? service.endpoint;
|
|
93
|
+
const schemas = Array.isArray(schemaSource) ? schemaSource : [schemaSource];
|
|
94
|
+
const hasUrlSchemas = schemas.some((schema) => isUrl(schema));
|
|
95
|
+
const downloadMode = service.downloadSchema ?? (hasUrlSchemas ? true : false);
|
|
92
96
|
if (!downloadMode || downloadMode === "manual") return;
|
|
93
97
|
const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
|
|
94
98
|
const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
|
|
95
99
|
try {
|
|
96
100
|
const headers = typeof service.headers === "function" ? service.headers() : service.headers || {};
|
|
97
|
-
const schemas = Array.isArray(service.schema) ? service.schema : [service.schema];
|
|
98
|
-
const hasUrlSchemas = schemas.some((schema) => isUrl(schema));
|
|
99
101
|
const hasLocalSchemas = schemas.some((schema) => !isUrl(schema));
|
|
100
102
|
let shouldDownload = false;
|
|
101
103
|
const fileExists = existsSync(schemaFilePath);
|
package/dist/utils/index.mjs
CHANGED
|
@@ -216,7 +216,6 @@ function validateExternalServices(services) {
|
|
|
216
216
|
if (!("name" in service) || typeof service.name !== "string") errors.push(`${prefix}.name is required and must be a string`);
|
|
217
217
|
else if (serviceNames.has(service.name)) errors.push(`${prefix}.name "${service.name}" must be unique`);
|
|
218
218
|
else serviceNames.add(service.name);
|
|
219
|
-
if (!("schema" in service) || !service.schema) errors.push(`${prefix}.schema is required`);
|
|
220
219
|
if (!("endpoint" in service) || typeof service.endpoint !== "string") errors.push(`${prefix}.endpoint is required and must be a string`);
|
|
221
220
|
else try {
|
|
222
221
|
new URL(service.endpoint);
|
|
@@ -232,7 +232,6 @@ async function serverTypeGeneration(app) {
|
|
|
232
232
|
if (serverTypesPath) {
|
|
233
233
|
mkdirSync(dirname(serverTypesPath), { recursive: true });
|
|
234
234
|
writeFileSync(serverTypesPath, data, "utf-8");
|
|
235
|
-
consola.success(`[nitro-graphql] Generated server types at: ${serverTypesPath}`);
|
|
236
235
|
}
|
|
237
236
|
} catch (error) {
|
|
238
237
|
consola.error("Server schema generation error:", error);
|
|
@@ -293,13 +292,11 @@ async function generateMainClientTypes(nitro) {
|
|
|
293
292
|
if (clientTypesPath) {
|
|
294
293
|
mkdirSync(dirname(clientTypesPath), { recursive: true });
|
|
295
294
|
writeFileSync(clientTypesPath, types.types, "utf-8");
|
|
296
|
-
consola.success(`[nitro-graphql] Generated client types at: ${clientTypesPath}`);
|
|
297
295
|
}
|
|
298
296
|
const sdkPath = resolveFilePath(sdkConfig.main, sdkConfig.enabled, true, "{clientGraphql}/default/sdk.ts", placeholders);
|
|
299
297
|
if (sdkPath) {
|
|
300
298
|
mkdirSync(dirname(sdkPath), { recursive: true });
|
|
301
299
|
writeFileSync(sdkPath, types.sdk, "utf-8");
|
|
302
|
-
consola.success(`[nitro-graphql] Generated SDK at: ${sdkPath}`);
|
|
303
300
|
}
|
|
304
301
|
if (nitro.options.framework?.name === "nuxt") {
|
|
305
302
|
generateNuxtOfetchClient(nitro, nitro.graphql.clientDir, "default");
|
|
@@ -310,7 +307,6 @@ async function generateMainClientTypes(nitro) {
|
|
|
310
307
|
async function generateExternalServicesTypes(nitro) {
|
|
311
308
|
const externalServices = nitro.options.graphql?.externalServices || [];
|
|
312
309
|
for (const service of externalServices) try {
|
|
313
|
-
consola.info(`[graphql:${service.name}] Processing external service`);
|
|
314
310
|
await downloadAndSaveSchema(service, nitro.options.buildDir);
|
|
315
311
|
const schema = await loadExternalSchema(service, nitro.options.buildDir);
|
|
316
312
|
if (!schema) {
|
|
@@ -344,16 +340,13 @@ async function generateExternalServicesTypes(nitro) {
|
|
|
344
340
|
if (serviceTypesPath) {
|
|
345
341
|
mkdirSync(dirname(serviceTypesPath), { recursive: true });
|
|
346
342
|
writeFileSync(serviceTypesPath, types.types, "utf-8");
|
|
347
|
-
consola.success(`[graphql:${service.name}] Generated types at: ${serviceTypesPath}`);
|
|
348
343
|
}
|
|
349
344
|
const serviceSdkPath = resolveFilePath(service.paths?.sdk ?? sdkConfig.external, sdkConfig.enabled, true, "{clientGraphql}/{serviceName}/sdk.ts", placeholders);
|
|
350
345
|
if (serviceSdkPath) {
|
|
351
346
|
mkdirSync(dirname(serviceSdkPath), { recursive: true });
|
|
352
347
|
writeFileSync(serviceSdkPath, types.sdk, "utf-8");
|
|
353
|
-
consola.success(`[graphql:${service.name}] Generated SDK at: ${serviceSdkPath}`);
|
|
354
348
|
}
|
|
355
349
|
if (nitro.options.framework?.name === "nuxt") generateExternalOfetchClient(nitro, service, service.endpoint);
|
|
356
|
-
consola.success(`[graphql:${service.name}] External service types generated successfully`);
|
|
357
350
|
} catch (error) {
|
|
358
351
|
consola.error(`[graphql:${service.name}] External service generation failed:`, error);
|
|
359
352
|
}
|