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.
- package/README.md +855 -5
- package/dist/ecosystem/nuxt.mjs +109 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +16 -0
- package/dist/rollup.d.mts +12 -0
- package/dist/rollup.mjs +282 -0
- package/dist/routes/apollo-server.d.mts +6 -0
- package/dist/routes/{apollo-server.js → apollo-server.mjs} +5 -5
- package/dist/routes/debug.d.mts +61 -0
- package/dist/routes/debug.mjs +445 -0
- package/dist/routes/graphql-yoga.d.mts +6 -0
- package/dist/routes/{graphql-yoga.js → graphql-yoga.mjs} +5 -5
- package/dist/routes/health.d.mts +10 -0
- package/dist/routes/{health.js → health.mjs} +1 -0
- package/dist/setup.d.mts +11 -0
- package/dist/setup.mjs +390 -0
- package/dist/types/index.d.mts +246 -0
- package/dist/utils/{apollo.js → apollo.mjs} +2 -2
- package/dist/utils/{client-codegen.d.ts → client-codegen.d.mts} +3 -3
- package/dist/utils/{client-codegen.js → client-codegen.mjs} +4 -4
- package/dist/utils/file-generator.d.mts +37 -0
- package/dist/utils/file-generator.mjs +72 -0
- package/dist/utils/{index.d.ts → index.d.mts} +2 -2
- package/dist/utils/{index.js → index.mjs} +63 -35
- package/dist/utils/path-resolver.d.mts +70 -0
- package/dist/utils/path-resolver.mjs +127 -0
- package/dist/utils/{server-codegen.d.ts → server-codegen.d.mts} +1 -1
- package/dist/utils/{server-codegen.js → server-codegen.mjs} +1 -1
- package/dist/utils/{type-generation.js → type-generation.mjs} +153 -42
- package/dist/virtual/debug-info.d.mts +9 -0
- package/dist/virtual/debug-info.mjs +26 -0
- package/dist/virtual/graphql-config.d.mts +9 -0
- package/dist/virtual/graphql-config.mjs +10 -0
- package/dist/virtual/module-config.d.mts +9 -0
- package/dist/virtual/module-config.mjs +10 -0
- package/dist/virtual/server-directives.d.mts +11 -0
- package/dist/virtual/server-directives.mjs +10 -0
- package/dist/virtual/server-resolvers.d.mts +11 -0
- package/dist/virtual/server-resolvers.mjs +10 -0
- package/dist/virtual/server-schemas.d.mts +11 -0
- package/dist/virtual/server-schemas.mjs +10 -0
- package/dist/vite.d.mts +27 -0
- package/dist/vite.mjs +49 -0
- package/package.json +72 -58
- package/dist/ecosystem/nuxt.js +0 -67
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -264
- package/dist/rollup.js +0 -114
- package/dist/routes/apollo-server.d.ts +0 -6
- package/dist/routes/graphql-yoga.d.ts +0 -6
- package/dist/routes/health.d.ts +0 -6
- package/dist/types/index.d.ts +0 -128
- /package/dist/ecosystem/{nuxt.d.ts → nuxt.d.mts} +0 -0
- /package/dist/graphql/{index.d.ts → index.d.mts} +0 -0
- /package/dist/graphql/{index.js → index.mjs} +0 -0
- /package/dist/graphql/{server.d.ts → server.d.mts} +0 -0
- /package/dist/graphql/{server.js → server.mjs} +0 -0
- /package/dist/types/{standard-schema.d.ts → standard-schema.d.mts} +0 -0
- /package/dist/utils/{apollo.d.ts → apollo.d.mts} +0 -0
- /package/dist/utils/{define.d.ts → define.d.mts} +0 -0
- /package/dist/utils/{define.js → define.mjs} +0 -0
- /package/dist/utils/{directive-parser.d.ts → directive-parser.d.mts} +0 -0
- /package/dist/utils/{directive-parser.js → directive-parser.mjs} +0 -0
- /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.
|
|
21
|
+
event.res.status = status || 200;
|
|
22
22
|
return body.string;
|
|
23
23
|
} catch (error) {
|
|
24
24
|
if (error instanceof SyntaxError) {
|
|
25
|
-
event.res.
|
|
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.
|
|
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>;
|