nitro-graphql 2.0.0-beta.25 → 2.0.0-beta.27
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 +99 -532
- package/dist/rollup.mjs +2 -2
- package/dist/routes/apollo-server.d.mts +2 -2
- package/dist/routes/debug.d.mts +2 -2
- package/dist/routes/graphql-yoga.d.mts +2 -2
- package/dist/setup.mjs +45 -49
- package/dist/utils/apollo.d.mts +1 -1
- package/dist/utils/client-codegen.d.mts +4 -1
- package/dist/utils/client-codegen.mjs +2 -2
- package/dist/utils/index.mjs +14 -4
- package/dist/utils/type-generation.d.mts +7 -2
- package/dist/utils/type-generation.mjs +43 -21
- package/package.json +58 -70
package/dist/rollup.mjs
CHANGED
|
@@ -94,8 +94,8 @@ async function rollupConfig(app) {
|
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
96
|
app.hooks.hook("dev:reload", async () => {
|
|
97
|
-
await serverTypeGeneration(app);
|
|
98
|
-
await clientTypeGeneration(app);
|
|
97
|
+
await serverTypeGeneration(app, { silent: true });
|
|
98
|
+
await clientTypeGeneration(app, { silent: true });
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
function virtualSchemas(app) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h30 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/apollo-server.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h30.EventHandlerWithFetch<h30.EventHandlerRequest, Promise<any>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/routes/debug.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h33 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/debug.d.ts
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ import * as h35 from "h3";
|
|
|
10
10
|
* - /_nitro/graphql/debug - HTML dashboard
|
|
11
11
|
* - /_nitro/graphql/debug?format=json - JSON API
|
|
12
12
|
*/
|
|
13
|
-
declare const _default:
|
|
13
|
+
declare const _default: h33.EventHandlerWithFetch<h33.EventHandlerRequest, Promise<string | {
|
|
14
14
|
timestamp: string;
|
|
15
15
|
environment: {
|
|
16
16
|
dev: any;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h35 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/graphql-yoga.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h35.EventHandlerWithFetch<h35.EventHandlerRequest, Promise<Response>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/setup.mjs
CHANGED
|
@@ -12,20 +12,21 @@ import consola from "consola";
|
|
|
12
12
|
import { dirname, join, relative, resolve } from "pathe";
|
|
13
13
|
|
|
14
14
|
//#region src/setup.ts
|
|
15
|
+
const logger = consola.withTag("nitro-graphql");
|
|
15
16
|
/**
|
|
16
17
|
* Shared setup logic for nitro-graphql module
|
|
17
18
|
* Used by both the direct Nitro module export and the Vite plugin's nitro: hook
|
|
18
19
|
*/
|
|
19
20
|
async function setupNitroGraphQL(nitro) {
|
|
20
|
-
if (!nitro.options.graphql?.framework)
|
|
21
|
+
if (!nitro.options.graphql?.framework) logger.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
|
|
21
22
|
if (nitro.options.graphql?.externalServices?.length) {
|
|
22
23
|
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
23
24
|
if (validationErrors.length > 0) {
|
|
24
|
-
|
|
25
|
-
for (const error of validationErrors)
|
|
25
|
+
logger.error("External services configuration errors:");
|
|
26
|
+
for (const error of validationErrors) logger.error(` - ${error}`);
|
|
26
27
|
throw new Error("Invalid external services configuration");
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
+
logger.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
|
|
29
30
|
}
|
|
30
31
|
const { getDefaultPaths } = await import("./utils/path-resolver.mjs");
|
|
31
32
|
const defaultPaths = getDefaultPaths(nitro);
|
|
@@ -42,12 +43,17 @@ async function setupNitroGraphQL(nitro) {
|
|
|
42
43
|
};
|
|
43
44
|
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
44
45
|
rollupConfig$1.external = rollupConfig$1.external || [];
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
46
|
+
const allExternals = [...["oxc-parser", "@oxc-parser"]];
|
|
47
|
+
if (!nitro.options.graphql?.federation?.enabled) allExternals.push(...[
|
|
48
|
+
"@apollo/subgraph",
|
|
49
|
+
"@apollo/federation-internals",
|
|
50
|
+
"@apollo/cache-control-types"
|
|
51
|
+
]);
|
|
52
|
+
if (Array.isArray(rollupConfig$1.external)) rollupConfig$1.external.push(...allExternals);
|
|
47
53
|
else if (typeof rollupConfig$1.external === "function") {
|
|
48
54
|
const originalExternal = rollupConfig$1.external;
|
|
49
55
|
rollupConfig$1.external = (id, parent, isResolved) => {
|
|
50
|
-
if (
|
|
56
|
+
if (allExternals.some((external) => id.includes(external))) return true;
|
|
51
57
|
return originalExternal(id, parent, isResolved);
|
|
52
58
|
};
|
|
53
59
|
}
|
|
@@ -59,7 +65,7 @@ async function setupNitroGraphQL(nitro) {
|
|
|
59
65
|
},
|
|
60
66
|
playground: true
|
|
61
67
|
});
|
|
62
|
-
if (nitro.options.graphql?.federation?.enabled)
|
|
68
|
+
if (nitro.options.graphql?.federation?.enabled) logger.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
|
|
63
69
|
const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
|
|
64
70
|
nitro.graphql.buildDir = graphqlBuildDir;
|
|
65
71
|
const watchDirs = [];
|
|
@@ -95,11 +101,20 @@ async function setupNitroGraphQL(nitro) {
|
|
|
95
101
|
ignoreInitial: true,
|
|
96
102
|
ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns()]
|
|
97
103
|
}).on("all", async (_, path) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
const isGraphQLFile = path.endsWith(".graphql") || path.endsWith(".gql");
|
|
105
|
+
const isResolverFile = path.endsWith(".resolver.ts") || path.endsWith(".resolver.js");
|
|
106
|
+
const isDirectiveFile = path.endsWith(".directive.ts") || path.endsWith(".directive.js");
|
|
107
|
+
if (isGraphQLFile || isResolverFile || isDirectiveFile) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql") || isResolverFile || isDirectiveFile) {
|
|
108
|
+
await scanResolvers(nitro).then((r) => nitro.scanResolvers = r);
|
|
109
|
+
await scanDirectives(nitro).then((d) => nitro.scanDirectives = d);
|
|
110
|
+
logger.success("Types regenerated");
|
|
111
|
+
await serverTypeGeneration(nitro, { silent: true });
|
|
112
|
+
await clientTypeGeneration(nitro, { silent: true });
|
|
101
113
|
await nitro.hooks.callHook("dev:reload");
|
|
102
|
-
} else
|
|
114
|
+
} else {
|
|
115
|
+
logger.success("Types regenerated");
|
|
116
|
+
await clientTypeGeneration(nitro, { silent: true });
|
|
117
|
+
}
|
|
103
118
|
});
|
|
104
119
|
nitro.hooks.hook("close", () => {
|
|
105
120
|
watcher.close();
|
|
@@ -111,33 +126,17 @@ async function setupNitroGraphQL(nitro) {
|
|
|
111
126
|
const directives = await scanDirectives(nitro);
|
|
112
127
|
nitro.scanDirectives = directives;
|
|
113
128
|
await generateDirectiveSchemas(nitro, directives);
|
|
129
|
+
let hasShownInitialLogs = false;
|
|
114
130
|
nitro.hooks.hook("dev:start", async () => {
|
|
115
|
-
|
|
116
|
-
nitro.scanSchemas = schemas;
|
|
131
|
+
nitro.scanSchemas = await scanSchemas(nitro);
|
|
117
132
|
const resolvers = await scanResolvers(nitro);
|
|
118
133
|
nitro.scanResolvers = resolvers;
|
|
119
134
|
const directives$1 = await scanDirectives(nitro);
|
|
120
135
|
nitro.scanDirectives = directives$1;
|
|
121
136
|
await generateDirectiveSchemas(nitro, directives$1);
|
|
122
|
-
|
|
123
|
-
nitro.
|
|
124
|
-
|
|
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
|
-
});
|
|
137
|
+
nitro.scanDocuments = await scanDocs(nitro);
|
|
138
|
+
if (nitro.options.dev && !hasShownInitialLogs) {
|
|
139
|
+
hasShownInitialLogs = true;
|
|
141
140
|
if (resolvers.length > 0) {
|
|
142
141
|
const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
|
|
143
142
|
const typeCount = {
|
|
@@ -156,16 +155,16 @@ async function setupNitroGraphQL(nitro) {
|
|
|
156
155
|
if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
|
|
157
156
|
if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
|
|
158
157
|
if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
|
|
159
|
-
if (breakdown.length > 0)
|
|
160
|
-
} else
|
|
158
|
+
if (breakdown.length > 0) logger.success(`${totalExports} resolver export(s): ${breakdown.join(", ")}`);
|
|
159
|
+
} else logger.warn("No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
161
160
|
}
|
|
162
161
|
});
|
|
163
162
|
await rollupConfig(nitro);
|
|
164
163
|
await serverTypeGeneration(nitro);
|
|
165
|
-
await clientTypeGeneration(nitro);
|
|
164
|
+
await clientTypeGeneration(nitro, { isInitial: true });
|
|
166
165
|
nitro.hooks.hook("close", async () => {
|
|
167
|
-
await serverTypeGeneration(nitro);
|
|
168
|
-
await clientTypeGeneration(nitro);
|
|
166
|
+
await serverTypeGeneration(nitro, { silent: true });
|
|
167
|
+
await clientTypeGeneration(nitro, { silent: true });
|
|
169
168
|
});
|
|
170
169
|
const runtime = fileURLToPath(new URL("routes", import.meta.url));
|
|
171
170
|
const methods = [
|
|
@@ -188,14 +187,11 @@ async function setupNitroGraphQL(nitro) {
|
|
|
188
187
|
handler: join(runtime, "health"),
|
|
189
188
|
method: "GET"
|
|
190
189
|
});
|
|
191
|
-
if (nitro.options.dev) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
});
|
|
197
|
-
consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
|
|
198
|
-
}
|
|
190
|
+
if (nitro.options.dev) nitro.options.handlers.push({
|
|
191
|
+
route: "/_nitro/graphql/debug",
|
|
192
|
+
handler: join(runtime, "debug"),
|
|
193
|
+
method: "GET"
|
|
194
|
+
});
|
|
199
195
|
if (nitro.options.imports) {
|
|
200
196
|
nitro.options.imports.presets ??= [];
|
|
201
197
|
nitro.options.imports.presets.push({
|
|
@@ -380,10 +376,10 @@ declare module 'nitro/h3' {
|
|
|
380
376
|
export {}
|
|
381
377
|
`, "server context.d.ts");
|
|
382
378
|
if (existsSync(join(nitro.graphql.serverDir, "context.ts"))) {
|
|
383
|
-
|
|
384
|
-
|
|
379
|
+
logger.warn("Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
|
|
380
|
+
logger.info("The context file should now be context.d.ts instead of context.ts");
|
|
385
381
|
}
|
|
386
|
-
} else
|
|
382
|
+
} else logger.info("Scaffold file generation is disabled (library mode)");
|
|
387
383
|
}
|
|
388
384
|
|
|
389
385
|
//#endregion
|
package/dist/utils/apollo.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ApolloServer, BaseContext, ContextFunction } from "@apollo/server";
|
|
2
2
|
import { EventHandler, H3Event } from "h3";
|
|
3
|
-
import { WithRequired } from "@apollo/utils.withrequired";
|
|
4
3
|
import { Hooks } from "crossws";
|
|
5
4
|
|
|
6
5
|
//#region src/utils/apollo.d.ts
|
|
6
|
+
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
|
7
7
|
interface H3ContextFunctionArgument {
|
|
8
8
|
event: H3Event;
|
|
9
9
|
}
|
|
@@ -23,7 +23,10 @@ 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, virtualTypesPath?: string
|
|
26
|
+
declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string, virtualTypesPath?: string, options?: {
|
|
27
|
+
silent?: boolean;
|
|
28
|
+
isInitial?: boolean;
|
|
29
|
+
}): Promise<false | {
|
|
27
30
|
types: string;
|
|
28
31
|
sdk: string;
|
|
29
32
|
}>;
|
|
@@ -165,9 +165,9 @@ async function loadGraphQLDocuments(patterns) {
|
|
|
165
165
|
else throw e;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath) {
|
|
168
|
+
async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath, options = {}) {
|
|
169
169
|
if (docs.length === 0 && !serviceName) {
|
|
170
|
-
consola$1.info("No client GraphQL files found. Skipping client type generation.");
|
|
170
|
+
if (!options.silent && options.isInitial) consola$1.info("No client GraphQL files found. Skipping client type generation.");
|
|
171
171
|
return false;
|
|
172
172
|
}
|
|
173
173
|
const serviceLabel = serviceName ? `:${serviceName}` : "";
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { directiveParser, generateDirectiveSchema, generateDirectiveSchemas } from "./directive-parser.mjs";
|
|
2
2
|
import { createDefaultMaskError } from "./errors.mjs";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
|
-
import { join, relative } from "pathe";
|
|
4
|
+
import { basename, join, relative } from "pathe";
|
|
5
5
|
import { hash } from "ohash";
|
|
6
6
|
import { parseAsync } from "oxc-parser";
|
|
7
7
|
import { glob } from "tinyglobby";
|
|
@@ -77,6 +77,17 @@ async function scanResolvers(nitro) {
|
|
|
77
77
|
for (const file of files) try {
|
|
78
78
|
const fileContent = await readFile(file.fullPath, "utf-8");
|
|
79
79
|
const parsed = await parseAsync(file.fullPath, fileContent);
|
|
80
|
+
if (parsed.errors && parsed.errors.length > 0) {
|
|
81
|
+
if (nitro.options.dev) {
|
|
82
|
+
const fileName = basename(file.fullPath);
|
|
83
|
+
const firstError = parsed.errors[0];
|
|
84
|
+
const location = firstError.labels?.[0];
|
|
85
|
+
const lineInfo = location ? `:${location.start}` : "";
|
|
86
|
+
const message = firstError.message.split(",")[0];
|
|
87
|
+
console.error(`✖ ${fileName}${lineInfo} - ${message}`);
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
80
91
|
const exports = {
|
|
81
92
|
imports: [],
|
|
82
93
|
specifier: file.fullPath
|
|
@@ -126,7 +137,6 @@ async function scanResolvers(nitro) {
|
|
|
126
137
|
}
|
|
127
138
|
}
|
|
128
139
|
if (nitro.options.dev) {
|
|
129
|
-
const relPath = relative(nitro.options.rootDir, file.fullPath);
|
|
130
140
|
if (hasDefaultExport && !hasNamedExport) nitro.logger.warn(`[nitro-graphql] ${relPath}: Using default export instead of named export. Resolvers must use named exports like "export const myResolver = defineQuery(...)". Default exports are not detected.`);
|
|
131
141
|
if (exports.imports.length === 0 && hasNamedExport) {
|
|
132
142
|
const validFunctions = VALID_DEFINE_FUNCTIONS.join(", ");
|
|
@@ -136,8 +146,8 @@ async function scanResolvers(nitro) {
|
|
|
136
146
|
}
|
|
137
147
|
if (exports.imports.length > 0) exportName.push(exports);
|
|
138
148
|
} catch (error) {
|
|
139
|
-
const relPath = relative(nitro.options.rootDir, file.fullPath);
|
|
140
|
-
nitro.logger.error(`[nitro-graphql] Failed to parse resolver file ${relPath}:`, error);
|
|
149
|
+
const relPath$1 = relative(nitro.options.rootDir, file.fullPath);
|
|
150
|
+
nitro.logger.error(`[nitro-graphql] Failed to parse resolver file ${relPath$1}:`, error);
|
|
141
151
|
}
|
|
142
152
|
return exportName;
|
|
143
153
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Nitro } from "nitro/types";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/type-generation.d.ts
|
|
4
|
-
declare function serverTypeGeneration(app: Nitro
|
|
5
|
-
|
|
4
|
+
declare function serverTypeGeneration(app: Nitro, options?: {
|
|
5
|
+
silent?: boolean;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
declare function clientTypeGeneration(nitro: Nitro, options?: {
|
|
8
|
+
silent?: boolean;
|
|
9
|
+
isInitial?: boolean;
|
|
10
|
+
}): Promise<void>;
|
|
6
11
|
//#endregion
|
|
7
12
|
export { clientTypeGeneration, serverTypeGeneration };
|
|
@@ -6,12 +6,22 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
6
6
|
import consola from "consola";
|
|
7
7
|
import { basename, dirname, join, resolve } from "pathe";
|
|
8
8
|
import { buildSchema, parse } from "graphql";
|
|
9
|
-
import { buildSubgraphSchema } from "@apollo/subgraph";
|
|
10
9
|
import { loadFilesSync } from "@graphql-tools/load-files";
|
|
11
10
|
import { mergeTypeDefs } from "@graphql-tools/merge";
|
|
12
11
|
import { printSchemaWithDirectives } from "@graphql-tools/utils";
|
|
13
12
|
|
|
14
13
|
//#region src/utils/type-generation.ts
|
|
14
|
+
const logger = consola.withTag("nitro-graphql");
|
|
15
|
+
let buildSubgraphSchema = null;
|
|
16
|
+
async function loadFederationSupport() {
|
|
17
|
+
if (buildSubgraphSchema !== null) return buildSubgraphSchema;
|
|
18
|
+
try {
|
|
19
|
+
buildSubgraphSchema = (await import("@apollo/subgraph")).buildSubgraphSchema;
|
|
20
|
+
} catch {
|
|
21
|
+
buildSubgraphSchema = false;
|
|
22
|
+
}
|
|
23
|
+
return buildSubgraphSchema;
|
|
24
|
+
}
|
|
15
25
|
function generateGraphQLIndexFile(nitro, clientDir, externalServices = []) {
|
|
16
26
|
if (!shouldGenerateClientUtils(nitro)) return;
|
|
17
27
|
const placeholders = getDefaultPaths(nitro);
|
|
@@ -238,15 +248,15 @@ function validateNoDuplicateTypes(schemas, schemaStrings) {
|
|
|
238
248
|
}
|
|
239
249
|
return true;
|
|
240
250
|
}
|
|
241
|
-
async function serverTypeGeneration(app) {
|
|
251
|
+
async function serverTypeGeneration(app, options = {}) {
|
|
242
252
|
try {
|
|
243
253
|
if (!shouldGenerateTypes(app)) {
|
|
244
|
-
|
|
254
|
+
logger.debug("Server type generation is disabled");
|
|
245
255
|
return;
|
|
246
256
|
}
|
|
247
257
|
const schemas = app.scanSchemas || [];
|
|
248
258
|
if (!schemas.length) {
|
|
249
|
-
consola.info("No GraphQL definitions found for server type generation.");
|
|
259
|
+
if (!options.silent) consola.info("No GraphQL definitions found for server type generation.");
|
|
250
260
|
return;
|
|
251
261
|
}
|
|
252
262
|
const schemaStrings = loadFilesSync(schemas).map((schema$1) => typeof schema$1 === "string" ? schema$1 : schema$1.loc?.source?.body || "").filter(Boolean);
|
|
@@ -257,7 +267,12 @@ async function serverTypeGeneration(app) {
|
|
|
257
267
|
commentDescriptions: true,
|
|
258
268
|
sort: true
|
|
259
269
|
});
|
|
260
|
-
|
|
270
|
+
let schema;
|
|
271
|
+
if (federationEnabled) {
|
|
272
|
+
const buildSubgraph = await loadFederationSupport();
|
|
273
|
+
if (!buildSubgraph) throw new Error("Federation is enabled but @apollo/subgraph is not installed. Run: pnpm add @apollo/subgraph");
|
|
274
|
+
schema = buildSubgraph([{ typeDefs: parse(mergedSchemas) }]);
|
|
275
|
+
} else schema = buildSchema(mergedSchemas);
|
|
261
276
|
const data = await generateTypes(app.options.graphql?.framework || "graphql-yoga", schema, app.options.graphql ?? {});
|
|
262
277
|
const printSchema = printSchemaWithDirectives(schema);
|
|
263
278
|
const schemaPath = resolve(app.graphql.buildDir, "schema.graphql");
|
|
@@ -269,18 +284,18 @@ async function serverTypeGeneration(app) {
|
|
|
269
284
|
if (serverTypesPath) {
|
|
270
285
|
mkdirSync(dirname(serverTypesPath), { recursive: true });
|
|
271
286
|
writeFileSync(serverTypesPath, data, "utf-8");
|
|
272
|
-
|
|
287
|
+
if (!options.silent) logger.success(`Generated server types at: ${serverTypesPath}`);
|
|
273
288
|
}
|
|
274
289
|
} catch (error) {
|
|
275
|
-
|
|
290
|
+
logger.error("Server schema generation error:", error);
|
|
276
291
|
}
|
|
277
292
|
}
|
|
278
|
-
async function clientTypeGeneration(nitro) {
|
|
293
|
+
async function clientTypeGeneration(nitro, options = {}) {
|
|
279
294
|
try {
|
|
280
|
-
if (nitro.scanSchemas && nitro.scanSchemas.length > 0) await generateMainClientTypes(nitro);
|
|
281
|
-
if (nitro.options.graphql?.externalServices?.length) await generateExternalServicesTypes(nitro);
|
|
295
|
+
if (nitro.scanSchemas && nitro.scanSchemas.length > 0) await generateMainClientTypes(nitro, options);
|
|
296
|
+
if (nitro.options.graphql?.externalServices?.length) await generateExternalServicesTypes(nitro, options);
|
|
282
297
|
} catch (error) {
|
|
283
|
-
|
|
298
|
+
logger.error("Client schema generation error:", error);
|
|
284
299
|
}
|
|
285
300
|
}
|
|
286
301
|
/**
|
|
@@ -311,17 +326,24 @@ function checkOldStructure(clientDir) {
|
|
|
311
326
|
🚫 The old files will cause import conflicts until moved!`);
|
|
312
327
|
}
|
|
313
328
|
}
|
|
314
|
-
async function generateMainClientTypes(nitro) {
|
|
329
|
+
async function generateMainClientTypes(nitro, options = {}) {
|
|
315
330
|
checkOldStructure(nitro.graphql.clientDir);
|
|
316
331
|
const docs = nitro.scanDocuments;
|
|
317
332
|
const loadDocs = await loadGraphQLDocuments(docs);
|
|
318
333
|
const schemaFilePath = join(nitro.graphql.buildDir, "schema.graphql");
|
|
319
334
|
if (!existsSync(schemaFilePath)) {
|
|
320
|
-
consola.info("Schema file not ready yet for client type generation. Server types need to be generated first.");
|
|
335
|
+
if (!options.silent) consola.info("Schema file not ready yet for client type generation. Server types need to be generated first.");
|
|
321
336
|
return;
|
|
322
337
|
}
|
|
323
338
|
const graphqlString = readFileSync(schemaFilePath, "utf-8");
|
|
324
|
-
const
|
|
339
|
+
const federationEnabled = nitro.options.graphql?.federation?.enabled === true;
|
|
340
|
+
let schema;
|
|
341
|
+
if (federationEnabled) {
|
|
342
|
+
const buildSubgraph = await loadFederationSupport();
|
|
343
|
+
if (!buildSubgraph) throw new Error("Federation is enabled but @apollo/subgraph is not installed. Run: pnpm add @apollo/subgraph");
|
|
344
|
+
schema = buildSubgraph([{ typeDefs: parse(graphqlString) }]);
|
|
345
|
+
} else schema = buildSchema(graphqlString);
|
|
346
|
+
const types = await generateClientTypes(schema, loadDocs, nitro.options.graphql?.codegen?.client ?? {}, nitro.options.graphql?.codegen?.clientSDK ?? {}, void 0, void 0, void 0, options);
|
|
325
347
|
if (types === false) return;
|
|
326
348
|
const placeholders = getDefaultPaths(nitro);
|
|
327
349
|
const typesConfig = getTypesConfig(nitro);
|
|
@@ -330,22 +352,22 @@ async function generateMainClientTypes(nitro) {
|
|
|
330
352
|
if (clientTypesPath) {
|
|
331
353
|
mkdirSync(dirname(clientTypesPath), { recursive: true });
|
|
332
354
|
writeFileSync(clientTypesPath, types.types, "utf-8");
|
|
333
|
-
|
|
355
|
+
if (!options.silent) logger.success(`Generated client types at: ${clientTypesPath}`);
|
|
334
356
|
}
|
|
335
357
|
const sdkPath = resolveFilePath(sdkConfig.main, sdkConfig.enabled, true, "{clientGraphql}/default/sdk.ts", placeholders);
|
|
336
358
|
if (sdkPath) {
|
|
337
359
|
mkdirSync(dirname(sdkPath), { recursive: true });
|
|
338
360
|
writeFileSync(sdkPath, types.sdk, "utf-8");
|
|
339
|
-
|
|
361
|
+
if (!options.silent) logger.success(`Generated SDK at: ${sdkPath}`);
|
|
340
362
|
}
|
|
341
363
|
generateNuxtOfetchClient(nitro, nitro.graphql.clientDir, "default");
|
|
342
364
|
const externalServices = nitro.options.graphql?.externalServices || [];
|
|
343
365
|
if (externalServices.length > 0) generateGraphQLIndexFile(nitro, nitro.graphql.clientDir, externalServices);
|
|
344
366
|
}
|
|
345
|
-
async function generateExternalServicesTypes(nitro) {
|
|
367
|
+
async function generateExternalServicesTypes(nitro, options = {}) {
|
|
346
368
|
const externalServices = nitro.options.graphql?.externalServices || [];
|
|
347
369
|
for (const service of externalServices) try {
|
|
348
|
-
consola.info(`[graphql:${service.name}] Processing external service`);
|
|
370
|
+
if (!options.silent) consola.info(`[graphql:${service.name}] Processing external service`);
|
|
349
371
|
await downloadAndSaveSchema(service, nitro.options.buildDir);
|
|
350
372
|
const schema = await loadExternalSchema(service, nitro.options.buildDir);
|
|
351
373
|
if (!schema) {
|
|
@@ -379,16 +401,16 @@ async function generateExternalServicesTypes(nitro) {
|
|
|
379
401
|
if (serviceTypesPath) {
|
|
380
402
|
mkdirSync(dirname(serviceTypesPath), { recursive: true });
|
|
381
403
|
writeFileSync(serviceTypesPath, types.types, "utf-8");
|
|
382
|
-
consola.success(`[graphql:${service.name}] Generated types at: ${serviceTypesPath}`);
|
|
404
|
+
if (!options.silent) consola.success(`[graphql:${service.name}] Generated types at: ${serviceTypesPath}`);
|
|
383
405
|
}
|
|
384
406
|
const serviceSdkPath = resolveFilePath(service.paths?.sdk ?? sdkConfig.external, sdkConfig.enabled, true, "{clientGraphql}/{serviceName}/sdk.ts", placeholders);
|
|
385
407
|
if (serviceSdkPath) {
|
|
386
408
|
mkdirSync(dirname(serviceSdkPath), { recursive: true });
|
|
387
409
|
writeFileSync(serviceSdkPath, types.sdk, "utf-8");
|
|
388
|
-
consola.success(`[graphql:${service.name}] Generated SDK at: ${serviceSdkPath}`);
|
|
410
|
+
if (!options.silent) consola.success(`[graphql:${service.name}] Generated SDK at: ${serviceSdkPath}`);
|
|
389
411
|
}
|
|
390
412
|
generateExternalOfetchClient(nitro, service, service.endpoint);
|
|
391
|
-
consola.success(`[graphql:${service.name}] External service types generated successfully`);
|
|
413
|
+
if (!options.silent) consola.success(`[graphql:${service.name}] External service types generated successfully`);
|
|
392
414
|
} catch (error) {
|
|
393
415
|
consola.error(`[graphql:${service.name}] External service generation failed:`, error);
|
|
394
416
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-graphql",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
5
|
-
"packageManager": "pnpm@10.22.0",
|
|
4
|
+
"version": "2.0.0-beta.27",
|
|
6
5
|
"description": "GraphQL integration for Nitro",
|
|
7
6
|
"license": "MIT",
|
|
8
7
|
"sideEffects": false,
|
|
@@ -71,25 +70,8 @@
|
|
|
71
70
|
"files": [
|
|
72
71
|
"dist"
|
|
73
72
|
],
|
|
74
|
-
"scripts": {
|
|
75
|
-
"prepack": "pnpm build",
|
|
76
|
-
"build": "tsdown",
|
|
77
|
-
"dev": "tsdown --watch",
|
|
78
|
-
"bumpp": "bumpp package.json",
|
|
79
|
-
"release": "pnpm build && pnpm bumpp && pnpm publish --no-git-checks --access public",
|
|
80
|
-
"playground:nitro": "cd playgrounds/nitro && pnpm install && pnpm dev",
|
|
81
|
-
"playground:nuxt": "cd playgrounds/nuxt && pnpm install && pnpm dev",
|
|
82
|
-
"playground:federation": "cd playgrounds/federation && pnpm install && pnpm dev",
|
|
83
|
-
"docs:dev": "cd .docs && pnpm install && pnpm update:metadata && pnpm dev",
|
|
84
|
-
"docs:build": "cd .docs && pnpm install && pnpm update:metadata && pnpm build",
|
|
85
|
-
"docs:preview": "cd .docs && pnpm preview",
|
|
86
|
-
"lint": "eslint .",
|
|
87
|
-
"lint:fix": "eslint . --fix",
|
|
88
|
-
"test:types": "tsc --noEmit"
|
|
89
|
-
},
|
|
90
73
|
"peerDependencies": {
|
|
91
74
|
"@apollo/server": "^5.0.0",
|
|
92
|
-
"@apollo/utils.withrequired": "^3.0.0",
|
|
93
75
|
"graphql": "^16.11.0",
|
|
94
76
|
"h3": "^2.0.1-rc.2",
|
|
95
77
|
"nitro": "^3.0.1-alpha.0"
|
|
@@ -97,63 +79,69 @@
|
|
|
97
79
|
"peerDependenciesMeta": {
|
|
98
80
|
"@apollo/server": {
|
|
99
81
|
"optional": true
|
|
100
|
-
},
|
|
101
|
-
"@apollo/utils.withrequired": {
|
|
102
|
-
"optional": true
|
|
103
82
|
}
|
|
104
83
|
},
|
|
105
84
|
"dependencies": {
|
|
106
|
-
"@apollo/subgraph": "
|
|
107
|
-
"@graphql-codegen/core": "
|
|
108
|
-
"@graphql-codegen/import-types-preset": "
|
|
109
|
-
"@graphql-codegen/typescript": "
|
|
110
|
-
"@graphql-codegen/typescript-generic-sdk": "
|
|
111
|
-
"@graphql-codegen/typescript-operations": "
|
|
112
|
-
"@graphql-codegen/typescript-resolvers": "
|
|
113
|
-
"@graphql-tools/graphql-file-loader": "
|
|
114
|
-
"@graphql-tools/load": "
|
|
115
|
-
"@graphql-tools/load-files": "
|
|
116
|
-
"@graphql-tools/merge": "
|
|
117
|
-
"@graphql-tools/schema": "
|
|
118
|
-
"@graphql-tools/url-loader": "
|
|
119
|
-
"@graphql-tools/utils": "
|
|
120
|
-
"chokidar": "
|
|
121
|
-
"consola": "
|
|
122
|
-
"defu": "
|
|
123
|
-
"graphql-config": "
|
|
124
|
-
"graphql-scalars": "
|
|
125
|
-
"knitwork": "
|
|
126
|
-
"ohash": "
|
|
127
|
-
"oxc-parser": "
|
|
128
|
-
"pathe": "
|
|
129
|
-
"tinyglobby": "
|
|
85
|
+
"@apollo/subgraph": "^2.12.1",
|
|
86
|
+
"@graphql-codegen/core": "^5.0.0",
|
|
87
|
+
"@graphql-codegen/import-types-preset": "^3.0.1",
|
|
88
|
+
"@graphql-codegen/typescript": "^5.0.4",
|
|
89
|
+
"@graphql-codegen/typescript-generic-sdk": "^4.0.2",
|
|
90
|
+
"@graphql-codegen/typescript-operations": "^5.0.4",
|
|
91
|
+
"@graphql-codegen/typescript-resolvers": "^5.1.2",
|
|
92
|
+
"@graphql-tools/graphql-file-loader": "^8.1.6",
|
|
93
|
+
"@graphql-tools/load": "^8.1.6",
|
|
94
|
+
"@graphql-tools/load-files": "^7.0.1",
|
|
95
|
+
"@graphql-tools/merge": "^9.1.5",
|
|
96
|
+
"@graphql-tools/schema": "^10.0.29",
|
|
97
|
+
"@graphql-tools/url-loader": "^9.0.4",
|
|
98
|
+
"@graphql-tools/utils": "^10.10.3",
|
|
99
|
+
"chokidar": "^4.0.3",
|
|
100
|
+
"consola": "^3.4.2",
|
|
101
|
+
"defu": "^6.1.4",
|
|
102
|
+
"graphql-config": "^5.1.5",
|
|
103
|
+
"graphql-scalars": "^1.25.0",
|
|
104
|
+
"knitwork": "^1.3.0",
|
|
105
|
+
"ohash": "^2.0.11",
|
|
106
|
+
"oxc-parser": "^0.97.0",
|
|
107
|
+
"pathe": "^2.0.3",
|
|
108
|
+
"tinyglobby": "^0.2.15"
|
|
130
109
|
},
|
|
131
110
|
"devDependencies": {
|
|
132
|
-
"@antfu/eslint-config": "
|
|
133
|
-
"@nuxt/kit": "
|
|
134
|
-
"@nuxt/schema": "
|
|
135
|
-
"@types/node": "
|
|
136
|
-
"@vitejs/devtools": "
|
|
137
|
-
"bumpp": "
|
|
138
|
-
"changelogen": "
|
|
139
|
-
"crossws": "
|
|
140
|
-
"eslint": "
|
|
141
|
-
"graphql": "
|
|
142
|
-
"graphql-yoga": "
|
|
143
|
-
"h3": "
|
|
144
|
-
"nitro": "
|
|
145
|
-
"tsdown": "
|
|
146
|
-
"typescript": "
|
|
147
|
-
"vite": "
|
|
148
|
-
"vitepress-plugin-llms": "
|
|
149
|
-
},
|
|
150
|
-
"pnpm": {
|
|
151
|
-
"overrides": {
|
|
152
|
-
"nitro": "npm:nitro-nightly@latest",
|
|
153
|
-
"vite": "npm:rolldown-vite@latest"
|
|
154
|
-
}
|
|
111
|
+
"@antfu/eslint-config": "^6.2.0",
|
|
112
|
+
"@nuxt/kit": "^4.2.1",
|
|
113
|
+
"@nuxt/schema": "^4.2.1",
|
|
114
|
+
"@types/node": "^24.10.1",
|
|
115
|
+
"@vitejs/devtools": "^0.0.0-alpha.16",
|
|
116
|
+
"bumpp": "^10.3.1",
|
|
117
|
+
"changelogen": "^0.6.2",
|
|
118
|
+
"crossws": "^0.4.1",
|
|
119
|
+
"eslint": "^9.39.1",
|
|
120
|
+
"graphql": "^16.12.0",
|
|
121
|
+
"graphql-yoga": "^5.16.2",
|
|
122
|
+
"h3": "^2.0.1-rc.5",
|
|
123
|
+
"nitro": "npm:nitro-nightly@latest",
|
|
124
|
+
"tsdown": "^0.16.4",
|
|
125
|
+
"typescript": "^5.9.3",
|
|
126
|
+
"vite": "npm:rolldown-vite@latest",
|
|
127
|
+
"vitepress-plugin-llms": "^1.9.1"
|
|
155
128
|
},
|
|
156
129
|
"resolutions": {
|
|
157
130
|
"nitro-graphql": "link:."
|
|
131
|
+
},
|
|
132
|
+
"scripts": {
|
|
133
|
+
"build": "tsdown",
|
|
134
|
+
"dev": "tsdown --watch",
|
|
135
|
+
"bumpp": "bumpp package.json",
|
|
136
|
+
"release": "pnpm build && pnpm bumpp && pnpm publish --no-git-checks --access public",
|
|
137
|
+
"playground:nitro": "cd playgrounds/nitro && pnpm install && pnpm dev",
|
|
138
|
+
"playground:nuxt": "cd playgrounds/nuxt && pnpm install && pnpm dev",
|
|
139
|
+
"playground:federation": "cd playgrounds/federation && pnpm install && pnpm dev",
|
|
140
|
+
"docs:dev": "cd .docs && pnpm install && pnpm update:metadata && pnpm dev",
|
|
141
|
+
"docs:build": "cd .docs && pnpm install && pnpm update:metadata && pnpm build",
|
|
142
|
+
"docs:preview": "cd .docs && pnpm preview",
|
|
143
|
+
"lint": "eslint .",
|
|
144
|
+
"lint:fix": "eslint . --fix",
|
|
145
|
+
"test:types": "tsc --noEmit"
|
|
158
146
|
}
|
|
159
|
-
}
|
|
147
|
+
}
|