nitro-graphql 1.4.3 → 1.5.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.
@@ -29,8 +29,7 @@ function pluginContent(_schema, _documents, _config, _info) {
29
29
  };
30
30
  }
31
31
  async function graphQLLoadSchemaSync(schemaPointers, data = {}) {
32
- const pointers = Array.isArray(schemaPointers) ? schemaPointers : [schemaPointers];
33
- const filteredPointers = [...pointers, "!**/vfs/**"];
32
+ const filteredPointers = [...Array.isArray(schemaPointers) ? schemaPointers : [schemaPointers], "!**/vfs/**"];
34
33
  let result;
35
34
  try {
36
35
  result = loadSchemaSync(filteredPointers, {
@@ -58,8 +57,7 @@ async function loadExternalSchema(service, buildDir) {
58
57
  const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
59
58
  const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
60
59
  if (existsSync(schemaFilePath)) try {
61
- const result$1 = loadSchemaSync([schemaFilePath], { loaders: [new GraphQLFileLoader()] });
62
- return result$1;
60
+ return loadSchemaSync([schemaFilePath], { loaders: [new GraphQLFileLoader()] });
63
61
  } catch {
64
62
  consola$1.warn(`[graphql:${service.name}] Cached schema invalid, loading from source`);
65
63
  }
@@ -70,14 +68,13 @@ async function loadExternalSchema(service, buildDir) {
70
68
  if (hasLocalFiles) loaders.push(new GraphQLFileLoader());
71
69
  if (hasUrls) loaders.push(new UrlLoader());
72
70
  if (loaders.length === 0) throw new Error("No appropriate loaders found for schema sources");
73
- const result = loadSchemaSync(schemas, {
71
+ return loadSchemaSync(schemas, {
74
72
  loaders,
75
73
  ...Object.keys(headers).length > 0 && { headers }
76
74
  });
77
- return result;
78
75
  } catch (error) {
79
76
  consola$1.error(`[graphql:${service.name}] Failed to load external schema:`, error);
80
- return void 0;
77
+ return;
81
78
  }
82
79
  }
83
80
  /**
@@ -91,7 +88,7 @@ function isUrl(path) {
91
88
  */
92
89
  async function downloadAndSaveSchema(service, buildDir) {
93
90
  const downloadMode = service.downloadSchema;
94
- if (!downloadMode || downloadMode === "manual") return void 0;
91
+ if (!downloadMode || downloadMode === "manual") return;
95
92
  const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
96
93
  const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
97
94
  try {
@@ -104,15 +101,13 @@ async function downloadAndSaveSchema(service, buildDir) {
104
101
  if (downloadMode === "always") {
105
102
  shouldDownload = true;
106
103
  if (fileExists && hasUrlSchemas) try {
107
- const remoteSchema = loadSchemaSync(schemas.filter(isUrl), {
104
+ const remoteSchemaString = printSchemaWithDirectives(loadSchemaSync(schemas.filter(isUrl), {
108
105
  loaders: [new UrlLoader()],
109
106
  ...Object.keys(headers).length > 0 && { headers }
110
- });
111
- const remoteSchemaString = printSchemaWithDirectives(remoteSchema);
107
+ }));
112
108
  const remoteHash = createHash("md5").update(remoteSchemaString).digest("hex");
113
109
  const localSchemaString = readFileSync(schemaFilePath, "utf-8");
114
- const localHash = createHash("md5").update(localSchemaString).digest("hex");
115
- if (remoteHash === localHash) {
110
+ if (remoteHash === createHash("md5").update(localSchemaString).digest("hex")) {
116
111
  shouldDownload = false;
117
112
  consola$1.info(`[graphql:${service.name}] Schema is up-to-date, using cached version`);
118
113
  }
@@ -137,24 +132,21 @@ async function downloadAndSaveSchema(service, buildDir) {
137
132
  } else if (downloadMode === true || downloadMode === "once") shouldDownload = !fileExists;
138
133
  if (shouldDownload) {
139
134
  if (hasUrlSchemas && hasLocalSchemas) {
140
- const schema = loadSchemaSync(schemas, {
135
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, {
141
136
  loaders: [new GraphQLFileLoader(), new UrlLoader()],
142
137
  ...Object.keys(headers).length > 0 && { headers }
143
- });
144
- const schemaString = printSchemaWithDirectives(schema);
138
+ }));
145
139
  mkdirSync(dirname(schemaFilePath), { recursive: true });
146
140
  writeFileSync(schemaFilePath, schemaString, "utf-8");
147
141
  } else if (hasUrlSchemas) {
148
- const schema = loadSchemaSync(schemas, {
142
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, {
149
143
  loaders: [new UrlLoader()],
150
144
  ...Object.keys(headers).length > 0 && { headers }
151
- });
152
- const schemaString = printSchemaWithDirectives(schema);
145
+ }));
153
146
  mkdirSync(dirname(schemaFilePath), { recursive: true });
154
147
  writeFileSync(schemaFilePath, schemaString, "utf-8");
155
148
  } else if (hasLocalSchemas) {
156
- const schema = loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] });
157
- const schemaString = printSchemaWithDirectives(schema);
149
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] }));
158
150
  mkdirSync(dirname(schemaFilePath), { recursive: true });
159
151
  writeFileSync(schemaFilePath, schemaString, "utf-8");
160
152
  }
@@ -162,13 +154,12 @@ async function downloadAndSaveSchema(service, buildDir) {
162
154
  return schemaFilePath;
163
155
  } catch (error) {
164
156
  consola$1.error(`[graphql:${service.name}] Failed to download/copy schema:`, error);
165
- return void 0;
157
+ return;
166
158
  }
167
159
  }
168
160
  async function loadGraphQLDocuments(patterns) {
169
161
  try {
170
- const result = await loadDocuments(patterns, { loaders: [new GraphQLFileLoader()] });
171
- return result;
162
+ return await loadDocuments(patterns, { loaders: [new GraphQLFileLoader()] });
172
163
  } catch (e) {
173
164
  if ((e.message || "").includes("Unable to find any GraphQL type definitions for the following pointers:")) return [];
174
165
  else throw e;
@@ -180,7 +171,7 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
180
171
  return false;
181
172
  }
182
173
  const serviceLabel = serviceName ? `:${serviceName}` : "";
183
- const defaultConfig = {
174
+ const mergedConfig = defu$1({
184
175
  emitLegacyCommonJSImports: false,
185
176
  useTypeImports: true,
186
177
  enumsAsTypes: true,
@@ -204,12 +195,11 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
204
195
  output: "File"
205
196
  }
206
197
  }
207
- };
208
- const mergedConfig = defu$1(defaultConfig, config);
198
+ }, config);
209
199
  const mergedSdkConfig = defu$1(mergedConfig, sdkConfig);
210
200
  try {
211
- if (docs.length === 0) {
212
- const output$1 = await codegen({
201
+ if (docs.length === 0) return {
202
+ types: await codegen({
213
203
  filename: outputPath || "client-types.generated.ts",
214
204
  schema: parse(printSchemaWithDirectives(schema)),
215
205
  documents: [],
@@ -219,8 +209,8 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
219
209
  pluginContent: { plugin: pluginContent },
220
210
  typescript: { plugin }
221
211
  }
222
- });
223
- const sdkContent$1 = `// THIS FILE IS GENERATED, DO NOT EDIT!
212
+ }),
213
+ sdk: `// THIS FILE IS GENERATED, DO NOT EDIT!
224
214
  /* eslint-disable eslint-comments/no-unlimited-disable */
225
215
  /* tslint:disable */
226
216
  /* eslint-disable */
@@ -244,12 +234,8 @@ export function getSdk(requester: Requester): Sdk {
244
234
  }
245
235
  }
246
236
  }
247
- `;
248
- return {
249
- types: output$1,
250
- sdk: sdkContent$1
251
- };
252
- }
237
+ `
238
+ };
253
239
  const output = await codegen({
254
240
  filename: outputPath || "client-types.generated.ts",
255
241
  schema: parse(printSchemaWithDirectives(schema)),
@@ -279,16 +265,14 @@ export function getSdk(requester: Requester): Sdk {
279
265
  typescriptGenericSdk: { plugin: plugin$1 }
280
266
  }
281
267
  });
282
- const results = await Promise.all(sdkOutput.map(async (config$1) => {
283
- return {
284
- file: config$1.filename,
285
- content: await codegen(config$1)
286
- };
287
- }));
288
- const sdkContent = results[0]?.content || "";
289
268
  return {
290
269
  types: output,
291
- sdk: sdkContent
270
+ sdk: (await Promise.all(sdkOutput.map(async (config$1) => {
271
+ return {
272
+ file: config$1.filename,
273
+ content: await codegen(config$1)
274
+ };
275
+ })))[0]?.content || ""
292
276
  };
293
277
  } catch (error) {
294
278
  consola$1.warn(`[graphql${serviceLabel}] Client type generation failed:`, error);
@@ -299,9 +283,7 @@ export function getSdk(requester: Requester): Sdk {
299
283
  * Generate client types for external GraphQL service
300
284
  */
301
285
  async function generateExternalClientTypes(service, schema, docs) {
302
- const config = service.codegen?.client || {};
303
- const sdkConfig = service.codegen?.clientSDK || {};
304
- return generateClientTypes(schema, docs, config, sdkConfig, void 0, service.name);
286
+ return generateClientTypes(schema, docs, service.codegen?.client || {}, service.codegen?.clientSDK || {}, void 0, service.name);
305
287
  }
306
288
 
307
289
  //#endregion
@@ -109,14 +109,12 @@ var DirectiveParser = class {
109
109
  */
110
110
  extractStringLiteral(node) {
111
111
  if (node?.type === "Literal" && typeof node.value === "string") return node.value;
112
- return void 0;
113
112
  }
114
113
  /**
115
114
  * Extract boolean literal value
116
115
  */
117
116
  extractBooleanLiteral(node) {
118
117
  if (node?.type === "Literal" && typeof node.value === "boolean") return node.value;
119
- return void 0;
120
118
  }
121
119
  /**
122
120
  * Extract array of strings
@@ -169,7 +167,6 @@ var DirectiveParser = class {
169
167
  */
170
168
  extractLiteralValue(node) {
171
169
  if (node?.type === "Literal") return node.value;
172
- return void 0;
173
170
  }
174
171
  };
175
172
  /**
@@ -177,15 +174,12 @@ var DirectiveParser = class {
177
174
  */
178
175
  function generateDirectiveSchema(directive) {
179
176
  let args = "";
180
- if (directive.args && Object.keys(directive.args).length > 0) {
181
- const argDefs = Object.entries(directive.args).map(([name, arg]) => {
182
- let defaultValue = "";
183
- if (arg.defaultValue !== void 0) if (typeof arg.defaultValue === "string") defaultValue = ` = "${arg.defaultValue}"`;
184
- else defaultValue = ` = ${arg.defaultValue}`;
185
- return `${name}: ${arg.type}${defaultValue}`;
186
- });
187
- args = `(${argDefs.join(", ")})`;
188
- }
177
+ if (directive.args && Object.keys(directive.args).length > 0) args = `(${Object.entries(directive.args).map(([name, arg]) => {
178
+ let defaultValue = "";
179
+ if (arg.defaultValue !== void 0) if (typeof arg.defaultValue === "string") defaultValue = ` = "${arg.defaultValue}"`;
180
+ else defaultValue = ` = ${arg.defaultValue}`;
181
+ return `${name}: ${arg.type}${defaultValue}`;
182
+ }).join(", ")})`;
189
183
  const locations = directive.locations.join(" | ");
190
184
  return `directive @${directive.name}${args} on ${locations}`;
191
185
  }
@@ -220,10 +214,7 @@ ${directiveSchemas.join("\n\n")}`;
220
214
  const targetDir = dirname(directivesPath);
221
215
  if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
222
216
  let shouldWrite = true;
223
- if (existsSync(directivesPath)) {
224
- const existingContent = readFileSync(directivesPath, "utf-8");
225
- shouldWrite = existingContent !== content;
226
- }
217
+ if (existsSync(directivesPath)) shouldWrite = readFileSync(directivesPath, "utf-8") !== content;
227
218
  if (shouldWrite) writeFileSync(directivesPath, content, "utf-8");
228
219
  if (!nitro.scanSchemas.includes(directivesPath)) nitro.scanSchemas.push(directivesPath);
229
220
  }
@@ -44,56 +44,83 @@ function relativeWithDot(from, to) {
44
44
  return RELATIVE_RE.test(rel) ? rel : `./${rel}`;
45
45
  }
46
46
  async function scanGraphql(nitro) {
47
- const files = await scanFiles(nitro, "graphql");
48
- return files.map((f) => f.fullPath);
47
+ return (await scanFiles(nitro, "graphql")).map((f) => f.fullPath);
49
48
  }
50
49
  async function scanResolvers(nitro) {
51
50
  const files = await scanFiles(nitro, "graphql", "**/*.resolver.{ts,js}");
52
51
  const exportName = [];
53
- for (const file of files) {
52
+ const VALID_DEFINE_FUNCTIONS = [
53
+ "defineResolver",
54
+ "defineQuery",
55
+ "defineMutation",
56
+ "defineType",
57
+ "defineSubscription",
58
+ "defineDirective"
59
+ ];
60
+ for (const file of files) try {
54
61
  const fileContent = await readFile(file.fullPath, "utf-8");
55
62
  const parsed = await parseAsync(file.fullPath, fileContent);
56
63
  const exports = {
57
64
  imports: [],
58
65
  specifier: file.fullPath
59
66
  };
60
- for (const node of parsed.program.body) if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
61
- for (const decl of node.declaration.declarations) if (decl.type === "VariableDeclarator" && decl.init && decl.id.type === "Identifier") {
62
- if (decl.init && decl.init.type === "CallExpression") {
63
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineResolver") exports.imports.push({
64
- name: decl.id.name,
65
- type: "resolver",
66
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
67
- });
68
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineQuery") exports.imports.push({
69
- name: decl.id.name,
70
- type: "query",
71
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
72
- });
73
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineMutation") exports.imports.push({
74
- name: decl.id.name,
75
- type: "mutation",
76
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
77
- });
78
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineType") exports.imports.push({
79
- name: decl.id.name,
80
- type: "type",
81
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
82
- });
83
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineSubscription") exports.imports.push({
84
- name: decl.id.name,
85
- type: "subscription",
86
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
87
- });
88
- if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineDirective") exports.imports.push({
89
- name: decl.id.name,
90
- type: "directive",
91
- as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
92
- });
67
+ let hasDefaultExport = false;
68
+ let hasNamedExport = false;
69
+ const namedExports = [];
70
+ for (const node of parsed.program.body) {
71
+ if (node.type === "ExportDefaultDeclaration") hasDefaultExport = true;
72
+ if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
73
+ for (const decl of node.declaration.declarations) if (decl.type === "VariableDeclarator" && decl.init && decl.id.type === "Identifier") {
74
+ hasNamedExport = true;
75
+ namedExports.push(decl.id.name);
76
+ if (decl.init && decl.init.type === "CallExpression") {
77
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineResolver") exports.imports.push({
78
+ name: decl.id.name,
79
+ type: "resolver",
80
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
81
+ });
82
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineQuery") exports.imports.push({
83
+ name: decl.id.name,
84
+ type: "query",
85
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
86
+ });
87
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineMutation") exports.imports.push({
88
+ name: decl.id.name,
89
+ type: "mutation",
90
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
91
+ });
92
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineType") exports.imports.push({
93
+ name: decl.id.name,
94
+ type: "type",
95
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
96
+ });
97
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineSubscription") exports.imports.push({
98
+ name: decl.id.name,
99
+ type: "subscription",
100
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
101
+ });
102
+ if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineDirective") exports.imports.push({
103
+ name: decl.id.name,
104
+ type: "directive",
105
+ as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
106
+ });
107
+ }
93
108
  }
94
109
  }
95
110
  }
111
+ if (nitro.options.dev) {
112
+ const relPath = relative(nitro.options.rootDir, file.fullPath);
113
+ 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.`);
114
+ if (exports.imports.length === 0 && hasNamedExport) {
115
+ const validFunctions = VALID_DEFINE_FUNCTIONS.join(", ");
116
+ nitro.logger.warn(`[nitro-graphql] ${relPath}: File has named exports [${namedExports.join(", ")}] but none use the required define functions (${validFunctions}). Exports will not be registered.`);
117
+ }
118
+ if (!hasDefaultExport && !hasNamedExport) nitro.logger.warn(`[nitro-graphql] ${relPath}: No exports found. Resolver files must export resolvers using defineResolver, defineQuery, defineMutation, etc.`);
119
+ }
96
120
  if (exports.imports.length > 0) exportName.push(exports);
121
+ } catch (error) {
122
+ const relPath = relative(nitro.options.rootDir, file.fullPath);
123
+ nitro.logger.error(`[nitro-graphql] Failed to parse resolver file ${relPath}:`, error);
97
124
  }
98
125
  return exportName;
99
126
  }
@@ -123,12 +150,10 @@ async function scanDirectives(nitro) {
123
150
  return exportName;
124
151
  }
125
152
  async function scanTypeDefs(nitro) {
126
- const files = await scanFiles(nitro, "graphql", "**/*.typedef.{ts,js}");
127
- return files.map((f) => f.fullPath);
153
+ return (await scanFiles(nitro, "graphql", "**/*.typedef.{ts,js}")).map((f) => f.fullPath);
128
154
  }
129
155
  async function scanSchemas(nitro) {
130
- const files = await scanFiles(nitro, "graphql", "**/*.graphql");
131
- return files.map((f) => f.fullPath);
156
+ return (await scanFiles(nitro, "graphql", "**/*.graphql")).map((f) => f.fullPath);
132
157
  }
133
158
  async function scanDocs(nitro) {
134
159
  const files = await scanDir(nitro, nitro.options.rootDir, nitro.graphql.dir.client, "**/*.graphql");
@@ -141,16 +166,12 @@ async function scanDocs(nitro) {
141
166
  seenPaths.add(file.fullPath);
142
167
  return true;
143
168
  });
144
- const externalServices = nitro.options.graphql?.externalServices || [];
145
- const externalPatterns = externalServices.flatMap((service) => service.documents || []);
169
+ const externalPatterns = (nitro.options.graphql?.externalServices || []).flatMap((service) => service.documents || []);
146
170
  return allFiles.filter((f) => !f.path.startsWith("external/")).filter((f) => {
147
171
  const relativePath = f.path;
148
172
  for (const pattern of externalPatterns) {
149
173
  const clientDirPattern = `${nitro.graphql.dir.client}/`;
150
- const cleanPattern = pattern.replace(/* @__PURE__ */ new RegExp(`^${clientDirPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "");
151
- const patternDir = cleanPattern.split("/")[0];
152
- const fileDir = relativePath.split("/")[0];
153
- if (patternDir === fileDir) return false;
174
+ if (pattern.replace(/* @__PURE__ */ new RegExp(`^${clientDirPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "").split("/")[0] === relativePath.split("/")[0]) return false;
154
175
  }
155
176
  return true;
156
177
  }).map((f) => f.fullPath);
@@ -213,7 +234,7 @@ async function scanFiles(nitro, name, globPattern = GLOB_SCAN_PATTERN) {
213
234
  });
214
235
  }
215
236
  async function scanDir(nitro, dir, name, globPattern = GLOB_SCAN_PATTERN) {
216
- const fileNames = await glob(join(name, globPattern), {
237
+ return (await glob(join(name, globPattern), {
217
238
  cwd: dir,
218
239
  dot: true,
219
240
  ignore: nitro.options.ignore,
@@ -224,8 +245,7 @@ async function scanDir(nitro, dir, name, globPattern = GLOB_SCAN_PATTERN) {
224
245
  return [];
225
246
  }
226
247
  throw error;
227
- });
228
- return fileNames.map((fullPath) => {
248
+ })).map((fullPath) => {
229
249
  return {
230
250
  fullPath,
231
251
  path: relative(join(dir, name), fullPath)
@@ -21,7 +21,7 @@ function pluginContent(_schema, _documents, _config, _info) {
21
21
  };
22
22
  }
23
23
  async function generateTypes(selectFremework, schema, config = {}, outputPath) {
24
- const defaultConfig = {
24
+ const mergedConfig = defu$1({
25
25
  scalars: {
26
26
  DateTime: DateTimeResolver.extensions.codegenScalarType,
27
27
  DateTimeISO: DateTimeISOResolver.extensions.codegenScalarType,
@@ -43,9 +43,8 @@ async function generateTypes(selectFremework, schema, config = {}, outputPath) {
43
43
  declarationKind: "interface",
44
44
  enumsAsTypes: true,
45
45
  ...config.federation?.enabled && { federation: true }
46
- };
47
- const mergedConfig = defu$1(defaultConfig, config.codegen?.server);
48
- const output = await codegen({
46
+ }, config.codegen?.server);
47
+ return await codegen({
49
48
  filename: outputPath || "types.generated.ts",
50
49
  schema: parse(printSchemaWithDirectives(schema)),
51
50
  documents: [],
@@ -131,7 +130,6 @@ type ResolverReturnTypeObject<T extends object> =
131
130
  consola.withTag("graphql").error("Error generating types:", e);
132
131
  return "";
133
132
  });
134
- return output;
135
133
  }
136
134
 
137
135
  //#endregion
@@ -31,8 +31,7 @@ function generateNuxtOfetchClient(clientDir, serviceName = "default") {
31
31
  const serviceDir = resolve(clientDir, serviceName);
32
32
  const ofetchPath = resolve(serviceDir, "ofetch.ts");
33
33
  if (!existsSync(serviceDir)) mkdirSync(serviceDir, { recursive: true });
34
- if (!existsSync(ofetchPath)) {
35
- const ofetchContent = `// This file is auto-generated once by nitro-graphql for quick start
34
+ if (!existsSync(ofetchPath)) writeFileSync(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
36
35
  // You can modify this file according to your needs
37
36
  import type { Requester } from './sdk'
38
37
  import { getSdk } from './sdk'
@@ -54,9 +53,7 @@ export function createGraphQLClient(endpoint: string): Requester {
54
53
  }
55
54
  }
56
55
 
57
- export const $sdk = getSdk(createGraphQLClient('/api/graphql'))`;
58
- writeFileSync(ofetchPath, ofetchContent, "utf-8");
59
- }
56
+ export const $sdk = getSdk(createGraphQLClient('/api/graphql'))`, "utf-8");
60
57
  }
61
58
  function generateExternalOfetchClient(clientDir, serviceName, endpoint) {
62
59
  const serviceDir = resolve(clientDir, serviceName);
@@ -64,7 +61,7 @@ function generateExternalOfetchClient(clientDir, serviceName, endpoint) {
64
61
  if (!existsSync(serviceDir)) mkdirSync(serviceDir, { recursive: true });
65
62
  if (!existsSync(ofetchPath)) {
66
63
  const capitalizedServiceName = serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
67
- const ofetchContent = `// This file is auto-generated once by nitro-graphql for quick start
64
+ writeFileSync(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
68
65
  // You can modify this file according to your needs
69
66
  import type { Sdk, Requester } from './sdk'
70
67
  import { getSdk } from './sdk'
@@ -86,8 +83,7 @@ export function create${capitalizedServiceName}GraphQLClient(endpoint: string =
86
83
  }
87
84
  }
88
85
 
89
- export const $${serviceName}Sdk: Sdk = getSdk(create${capitalizedServiceName}GraphQLClient())`;
90
- writeFileSync(ofetchPath, ofetchContent, "utf-8");
86
+ export const $${serviceName}Sdk: Sdk = getSdk(create${capitalizedServiceName}GraphQLClient())`, "utf-8");
91
87
  }
92
88
  }
93
89
  /**
@@ -127,8 +123,7 @@ function validateNoDuplicateTypes(schemas, schemaStrings) {
127
123
  schemaStrings.forEach((schemaContent, index) => {
128
124
  const fileName = basename(schemas[index]);
129
125
  try {
130
- const document = parse(schemaContent);
131
- document.definitions.forEach((def) => {
126
+ parse(schemaContent).definitions.forEach((def) => {
132
127
  if (def.kind === "ObjectTypeDefinition" || def.kind === "InterfaceTypeDefinition" || def.kind === "UnionTypeDefinition" || def.kind === "EnumTypeDefinition" || def.kind === "InputObjectTypeDefinition" || def.kind === "ScalarTypeDefinition") {
133
128
  const typeName = def.name.value;
134
129
  if ([
@@ -148,8 +143,7 @@ function validateNoDuplicateTypes(schemas, schemaStrings) {
148
143
  const content = schemaStrings[i];
149
144
  if (!content) return false;
150
145
  try {
151
- const doc = parse(content);
152
- return doc.definitions.some((d) => (d.kind === "ObjectTypeDefinition" || d.kind === "InterfaceTypeDefinition" || d.kind === "UnionTypeDefinition" || d.kind === "EnumTypeDefinition" || d.kind === "InputObjectTypeDefinition" || d.kind === "ScalarTypeDefinition") && d.name.value === typeName);
146
+ return parse(content).definitions.some((d) => (d.kind === "ObjectTypeDefinition" || d.kind === "InterfaceTypeDefinition" || d.kind === "UnionTypeDefinition" || d.kind === "EnumTypeDefinition" || d.kind === "InputObjectTypeDefinition" || d.kind === "ScalarTypeDefinition") && d.name.value === typeName);
153
147
  } catch {
154
148
  return false;
155
149
  }
@@ -189,10 +183,8 @@ async function serverTypeGeneration(app) {
189
183
  consola.info("No GraphQL definitions found for server type generation.");
190
184
  return;
191
185
  }
192
- const loadSchemas = loadFilesSync(schemas);
193
- const schemaStrings = loadSchemas.map((schema$1) => typeof schema$1 === "string" ? schema$1 : schema$1.loc?.source?.body || "").filter(Boolean);
194
- const isValid = validateNoDuplicateTypes(schemas, schemaStrings);
195
- if (!isValid) return;
186
+ const schemaStrings = loadFilesSync(schemas).map((schema$1) => typeof schema$1 === "string" ? schema$1 : schema$1.loc?.source?.body || "").filter(Boolean);
187
+ if (!validateNoDuplicateTypes(schemas, schemaStrings)) return;
196
188
  const federationEnabled = app.options.graphql?.federation?.enabled === true;
197
189
  const mergedSchemas = mergeTypeDefs([schemaStrings.join("\n\n")], {
198
190
  throwOnConflict: true,
@@ -214,8 +206,7 @@ async function serverTypeGeneration(app) {
214
206
  }
215
207
  async function clientTypeGeneration(nitro) {
216
208
  try {
217
- const hasServerSchema = nitro.scanSchemas && nitro.scanSchemas.length > 0;
218
- if (hasServerSchema) await generateMainClientTypes(nitro);
209
+ if (nitro.scanSchemas && nitro.scanSchemas.length > 0) await generateMainClientTypes(nitro);
219
210
  if (nitro.options.graphql?.externalServices?.length) await generateExternalServicesTypes(nitro);
220
211
  } catch (error) {
221
212
  consola.error("Client schema generation error:", error);
@@ -259,9 +250,7 @@ async function generateMainClientTypes(nitro) {
259
250
  return;
260
251
  }
261
252
  const graphqlString = readFileSync(schemaFilePath, "utf-8");
262
- const federationEnabled = nitro.options.graphql?.federation?.enabled === true;
263
- const schema = federationEnabled ? buildSubgraphSchema([{ typeDefs: parse(graphqlString) }]) : buildSchema(graphqlString);
264
- const types = await generateClientTypes(schema, loadDocs, nitro.options.graphql?.codegen?.client ?? {}, nitro.options.graphql?.codegen?.clientSDK ?? {});
253
+ const types = await generateClientTypes(nitro.options.graphql?.federation?.enabled === true ? buildSubgraphSchema([{ typeDefs: parse(graphqlString) }]) : buildSchema(graphqlString), loadDocs, nitro.options.graphql?.codegen?.client ?? {}, nitro.options.graphql?.codegen?.clientSDK ?? {});
265
254
  if (types === false) return;
266
255
  const clientTypesPath = resolve(nitro.options.buildDir, "types", "nitro-graphql-client.d.ts");
267
256
  const defaultServiceDir = resolve(nitro.graphql.clientDir, "default");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "1.4.3",
4
+ "version": "1.5.0",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
@@ -60,7 +60,6 @@
60
60
  ],
61
61
  "peerDependencies": {
62
62
  "@apollo/server": "^5.0.0",
63
- "@apollo/subgraph": "^2.0.0",
64
63
  "@apollo/utils.withrequired": "^3.0.0",
65
64
  "@as-integrations/h3": "^2.0.0",
66
65
  "graphql": "^16.11.0",
@@ -71,9 +70,6 @@
71
70
  "@apollo/server": {
72
71
  "optional": true
73
72
  },
74
- "@apollo/subgraph": {
75
- "optional": true
76
- },
77
73
  "@apollo/utils.withrequired": {
78
74
  "optional": true
79
75
  },
@@ -82,46 +78,46 @@
82
78
  }
83
79
  },
84
80
  "dependencies": {
85
- "@graphql-codegen/core": "^4.0.2",
81
+ "@apollo/subgraph": "^2.11.3",
82
+ "@graphql-codegen/core": "^5.0.0",
86
83
  "@graphql-codegen/import-types-preset": "^3.0.1",
87
- "@graphql-codegen/typescript": "^4.1.6",
84
+ "@graphql-codegen/typescript": "^5.0.2",
88
85
  "@graphql-codegen/typescript-generic-sdk": "^4.0.2",
89
- "@graphql-codegen/typescript-operations": "^4.6.1",
90
- "@graphql-codegen/typescript-resolvers": "^4.5.2",
91
- "@graphql-tools/graphql-file-loader": "^8.1.0",
86
+ "@graphql-codegen/typescript-operations": "^5.0.2",
87
+ "@graphql-codegen/typescript-resolvers": "^5.1.0",
88
+ "@graphql-tools/graphql-file-loader": "^8.1.2",
92
89
  "@graphql-tools/load": "^8.1.2",
93
90
  "@graphql-tools/load-files": "^7.0.1",
94
91
  "@graphql-tools/merge": "^9.1.1",
95
92
  "@graphql-tools/schema": "^10.0.25",
96
- "@graphql-tools/url-loader": "^8.0.33",
93
+ "@graphql-tools/url-loader": "^9.0.0",
97
94
  "@graphql-tools/utils": "^10.9.1",
98
95
  "chokidar": "^4.0.3",
99
96
  "consola": "^3.4.2",
100
97
  "defu": "^6.1.4",
101
98
  "graphql-config": "^5.1.5",
102
- "graphql-scalars": "^1.24.2",
99
+ "graphql-scalars": "^1.25.0",
103
100
  "knitwork": "^1.2.0",
104
101
  "ohash": "^2.0.11",
105
- "oxc-parser": "^0.86.0",
102
+ "oxc-parser": "^0.95.0",
106
103
  "pathe": "^2.0.3",
107
- "tinyglobby": "^0.2.14"
104
+ "tinyglobby": "^0.2.15"
108
105
  },
109
106
  "devDependencies": {
110
- "@antfu/eslint-config": "^5.2.2",
111
- "@apollo/subgraph": "^2.11.2",
112
- "@nuxt/kit": "^4.1.0",
113
- "@nuxt/schema": "^4.1.0",
114
- "@types/node": "^22.18.1",
115
- "bumpp": "^10.2.3",
107
+ "@antfu/eslint-config": "^6.0.0",
108
+ "@nuxt/kit": "^4.1.3",
109
+ "@nuxt/schema": "^4.1.3",
110
+ "@types/node": "^24.9.1",
111
+ "bumpp": "^10.3.1",
116
112
  "changelogen": "^0.6.2",
117
113
  "crossws": "0.3.5",
118
- "eslint": "^9.34.0",
114
+ "eslint": "^9.38.0",
119
115
  "graphql": "16.11.0",
120
- "graphql-yoga": "^5.15.1",
116
+ "graphql-yoga": "^5.16.0",
121
117
  "h3": "1.15.3",
122
- "nitropack": "^2.12.5",
123
- "tsdown": "^0.14.2",
124
- "typescript": "^5.9.2"
118
+ "nitropack": "^2.12.7",
119
+ "tsdown": "^0.15.9",
120
+ "typescript": "^5.9.3"
125
121
  },
126
122
  "resolutions": {
127
123
  "nitro-graphql": "link:."