nuxt-graphql-middleware 4.3.1 → 5.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.mjs CHANGED
@@ -1,27 +1,23 @@
1
+ import { loadSchema } from '@graphql-tools/load';
1
2
  import { fileURLToPath } from 'url';
2
- import { dirname, resolve, relative, parse as parse$1, join } from 'pathe';
3
+ import { relative } from 'pathe';
3
4
  import { defu } from 'defu';
4
- import { useLogger, resolveAlias, resolveFiles, defineNuxtModule, createResolver, addImports, addServerImports, addTemplate, addServerHandler, addPlugin, updateTemplates } from '@nuxt/kit';
5
- import inquirer from 'inquirer';
5
+ import { useLogger, resolveFiles, defineNuxtModule, resolveAlias, createResolver, addImports, addServerImports, addTemplate, addServerHandler, addPlugin } from '@nuxt/kit';
6
6
  import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
7
7
  import { existsSync } from 'fs';
8
8
  import { GraphqlMiddlewareTemplate } from '../dist/runtime/settings/index.js';
9
- import * as fs from 'node:fs';
10
9
  import { promises, existsSync as existsSync$1 } from 'node:fs';
11
- import { oldVisit } from '@graphql-codegen/plugin-helpers';
12
- import { validateGraphQlDocuments } from '@graphql-tools/utils';
13
- import { loadSchema } from '@graphql-tools/load';
14
- import { concatAST, parse, print, visit, Kind, Source } from 'graphql';
15
- import { falsy } from '../dist/runtime/helpers/index.js';
16
- import { generate as generate$1, executeCodegen } from '@graphql-codegen/cli';
17
- import * as PluginTypescript from '@graphql-codegen/typescript';
18
- import * as PluginTypescriptOperations from '@graphql-codegen/typescript-operations';
10
+ import { generate } from '@graphql-codegen/cli';
19
11
  import * as PluginSchemaAst from '@graphql-codegen/schema-ast';
12
+ import { basename } from 'node:path';
13
+ import { Source, parse, printSourceLocation } from 'graphql';
14
+ import { Generator } from 'graphql-typescript-deluxe';
20
15
  import { pascalCase } from 'change-case-all';
21
16
  import colors from 'picocolors';
17
+ import { validateGraphQlDocuments } from '@graphql-tools/utils';
22
18
 
23
19
  const name = "nuxt-graphql-middleware";
24
- const version = "4.3.1";
20
+ const version = "5.0.0-alpha.0";
25
21
 
26
22
  const DEVTOOLS_UI_ROUTE = "/__nuxt-graphql-middleware";
27
23
  const DEVTOOLS_UI_LOCAL_PORT = 3300;
@@ -64,236 +60,8 @@ function setupDevToolsUI(nuxt, clientPath) {
64
60
  });
65
61
  }
66
62
 
67
- const importSyntaxRE = /^#import (?:'([^']*)'|"([^"]*)")/;
68
- const matchImport = (value = "") => {
69
- if (!value) {
70
- return void 0;
71
- }
72
- if (value.indexOf("#import") !== 0) {
73
- return void 0;
74
- }
75
- const matched = value.match(importSyntaxRE);
76
- if (matched === null) {
77
- return void 0;
78
- }
79
- const importIdentifierMatch = value.match(importSyntaxRE) || [];
80
- const importIdentifier = importIdentifierMatch[1] ?? importIdentifierMatch[2];
81
- if (importIdentifier === void 0) {
82
- return void 0;
83
- }
84
- return { importIdentifier };
85
- };
86
-
87
- const lineEndingRE = /\r\n|\n/;
88
- function* linesWithInlinedImportsOf(fileContents, inlineImportsOptions, visited) {
89
- const {
90
- resolveOptions = {},
91
- resolveImport,
92
- fs: nodeFs = fs,
93
- throwIfImportNotFound
94
- } = inlineImportsOptions;
95
- const { basedir } = resolveOptions;
96
- if (typeof basedir !== "string") {
97
- throw new TypeError(
98
- "inlineImports requires options.resolverOptions.basedir be set"
99
- );
100
- }
101
- if (!resolveImport) {
102
- throw new TypeError("inlineImports requires options.resolveImport be set");
103
- }
104
- let lineNumber = 0;
105
- for (const line of fileContents.split(lineEndingRE)) {
106
- ++lineNumber;
107
- const matched = matchImport(line);
108
- if (matched) {
109
- const importIdentifier = matched.importIdentifier;
110
- let filename;
111
- try {
112
- filename = resolveImport(importIdentifier, resolveOptions);
113
- } catch (err) {
114
- if (throwIfImportNotFound === false) {
115
- continue;
116
- }
117
- throw err;
118
- }
119
- if (visited.has(filename)) {
120
- continue;
121
- } else {
122
- visited.add(filename);
123
- }
124
- const fragmentSource = nodeFs.readFileSync(filename, "utf8");
125
- const line2 = inlineImportsWithLineToImports(
126
- fragmentSource,
127
- {
128
- resolveImport,
129
- resolveOptions: {
130
- basedir: dirname(filename)
131
- }
132
- },
133
- visited
134
- );
135
- yield { line: line2.inlineImports, match: true, lineNumber, filename };
136
- } else {
137
- yield { line, match: false, lineNumber };
138
- }
139
- }
140
- }
141
- function inlineImportsWithLineToImports(fileContents, options, visited = /* @__PURE__ */ new Set()) {
142
- const inlineImportsResult = [];
143
- const lineToImports = /* @__PURE__ */ new Map();
144
- for (const { line, match, lineNumber, filename } of linesWithInlinedImportsOf(
145
- fileContents,
146
- options,
147
- visited
148
- )) {
149
- inlineImportsResult.push(line);
150
- if (match) {
151
- lineToImports.set(lineNumber, { filename, line });
152
- }
153
- }
154
- return {
155
- inlineImports: inlineImportsResult.join("\n"),
156
- lineToImports
157
- };
158
- }
159
-
160
- function getCodeResult(operations, typeName, serverApiPrefix) {
161
- const imports = [];
162
- const resultTypes = [];
163
- let code = "";
164
- let nitroCode = "";
165
- const names = Object.keys(operations);
166
- if (names.length) {
167
- const lines = [];
168
- const nitroLines = [];
169
- names.forEach((name) => {
170
- const nameResult = pascalCase(name + typeName);
171
- resultTypes.push(nameResult);
172
- imports.push(nameResult);
173
- const nameVariables = pascalCase(name + typeName + "Variables");
174
- const { hasVariables, variablesOptional } = operations[name];
175
- if (hasVariables) {
176
- imports.push(nameVariables);
177
- }
178
- const variablesType = hasVariables ? nameVariables : "null";
179
- lines.push(
180
- ` ${name}: [${variablesType}, ${variablesOptional ? "true" : "false"}, ${nameResult}]`
181
- );
182
- nitroLines.push(
183
- ` '${serverApiPrefix}/${typeName.toLowerCase()}/${name}': {
184
- 'default': GraphqlResponse<${nameResult}>
185
- }`
186
- );
187
- });
188
- code += ` export type GraphqlMiddleware${typeName} = {
189
- ${lines.join(",\n")}
190
- }
191
- `;
192
- nitroCode += `${nitroLines.join("\n")}`;
193
- }
194
- return { code, imports, nitroCode, resultTypes };
195
- }
196
- const plugin$1 = (_schema, documents, config) => {
197
- const allAst = concatAST(documents.map((v) => v.document).filter(falsy));
198
- const operations = {
199
- query: {},
200
- mutation: {}
201
- };
202
- oldVisit(allAst, {
203
- enter: {
204
- OperationDefinition: (node) => {
205
- if ("name" in node && node.name?.value && "operation" in node && (node.operation === "query" || node.operation === "mutation")) {
206
- operations[node.operation][node.name.value] = {
207
- hasVariables: !!node.variableDefinitions?.length,
208
- variablesOptional: !!node.variableDefinitions?.every((v) => {
209
- return v.defaultValue;
210
- })
211
- };
212
- }
213
- }
214
- }
215
- });
216
- let code = "";
217
- let nitroCode = "";
218
- const imports = [];
219
- const resultTypes = [];
220
- const resultQuery = getCodeResult(
221
- operations.query,
222
- "Query",
223
- config.serverApiPrefix
224
- );
225
- code += resultQuery.code;
226
- nitroCode += resultQuery.nitroCode;
227
- imports.push(...resultQuery.imports);
228
- resultTypes.push(...resultQuery.resultTypes);
229
- const resultMutation = getCodeResult(
230
- operations.mutation,
231
- "Mutation",
232
- config.serverApiPrefix
233
- );
234
- code += "\n" + resultMutation.code;
235
- nitroCode += "\n" + resultMutation.nitroCode;
236
- imports.push(...resultMutation.imports);
237
- resultTypes.push(...resultMutation.resultTypes);
238
- return `
239
- import type { GraphqlResponse } from '#graphql-middleware-server-options-build'
240
- import type {
241
- ${imports.join(",\n ")}
242
- } from './../graphql-operations'
243
-
244
-
245
- declare module '#nuxt-graphql-middleware/generated-types' {
246
- export type GraphqlMiddlewareResponseUnion = ${resultTypes.join(" | ")}
247
- ${code}
248
- }
249
-
250
- declare module 'nitropack' {
251
- interface InternalApi {
252
- ${nitroCode}
253
- }
254
- }
255
- `;
256
- };
257
-
258
- const PluginNuxtGraphqlMiddleware = {
259
- __proto__: null,
260
- plugin: plugin$1
261
- };
262
-
263
- const plugin = (_schema, documents, _config) => {
264
- const allAst = concatAST(documents.map((v) => v.document).filter(falsy));
265
- const operations = {
266
- query: {},
267
- mutation: {}
268
- };
269
- oldVisit(allAst, {
270
- enter: {
271
- OperationDefinition: (node) => {
272
- if (node.name?.value && node.loc?.source && (node.operation === "query" || node.operation === "mutation")) {
273
- operations[node.operation][node.name.value] = node.loc.source.body;
274
- }
275
- }
276
- }
277
- });
278
- return `const documents = ${JSON.stringify(operations, null, 2)};
279
- export { documents };`;
280
- };
281
-
282
- const PluginNuxtGraphqlMiddlewareDocuments = {
283
- __proto__: null,
284
- plugin: plugin
285
- };
286
-
287
63
  function pluginLoader(name) {
288
64
  switch (name) {
289
- case "@graphql-codegen/typescript":
290
- return Promise.resolve(PluginTypescript);
291
- case "@graphql-codegen/typescript-operations":
292
- return Promise.resolve(PluginTypescriptOperations);
293
- case "@graphql-codegen/typescript-nuxt-graphql-middleware":
294
- return Promise.resolve(PluginNuxtGraphqlMiddleware);
295
- case "@graphql-codegen/typescript-nuxt-graphql-middleware-documents":
296
- return Promise.resolve(PluginNuxtGraphqlMiddlewareDocuments);
297
65
  case "@graphql-codegen/schema-ast":
298
66
  return Promise.resolve(PluginSchemaAst);
299
67
  }
@@ -317,88 +85,11 @@ function generateSchema(moduleOptions, dest, writeToDisk) {
317
85
  }
318
86
  }
319
87
  };
320
- return generate$1(config, writeToDisk).then((v) => v[0]);
321
- }
322
- function generateTemplates(documents, schemaPath, options) {
323
- return executeCodegen({
324
- schema: schemaPath,
325
- pluginLoader,
326
- silent: true,
327
- errorsOnly: true,
328
- documents,
329
- generates: {
330
- [GraphqlMiddlewareTemplate.OperationTypes]: {
331
- plugins: ["typescript", "typescript-operations"],
332
- config: options.codegenConfig
333
- },
334
- [GraphqlMiddlewareTemplate.ComposableContext]: {
335
- plugins: ["typescript-nuxt-graphql-middleware"],
336
- config: {
337
- serverApiPrefix: options.serverApiPrefix
338
- }
339
- },
340
- [GraphqlMiddlewareTemplate.Documents]: {
341
- plugins: ["typescript-nuxt-graphql-middleware-documents"]
342
- }
343
- }
344
- });
345
- }
346
-
347
- function getMaxLengths(documents) {
348
- let longestOperation = 0;
349
- let longestName = 0;
350
- let longestPath = 0;
351
- for (const { operation, name, relativePath } of documents) {
352
- if (operation && operation.length > longestOperation) {
353
- longestOperation = operation.length;
354
- }
355
- if (name && name.length > longestName) {
356
- longestName = name.length;
357
- }
358
- if (relativePath && relativePath.length > longestPath) {
359
- longestPath = relativePath.length;
360
- }
361
- }
362
- return { longestOperation, longestName, longestPath };
363
- }
364
- function logDocuments(logger, documents, logEverything) {
365
- const { longestOperation, longestName, longestPath } = getMaxLengths(documents);
366
- logger.log(colors.green("GraphQL Document Validation"));
367
- for (const { operation, name, relativePath, isValid, errors } of documents) {
368
- if (logEverything || !isValid) {
369
- let log = "";
370
- log += (operation || "").padEnd(longestOperation + 2);
371
- log += colors.cyan((name || "").padEnd(longestName + 2));
372
- log += colors.dim((relativePath || "").padEnd(longestPath + 2));
373
- log += isValid ? colors.green("\u2713") : colors.red("x");
374
- if (!isValid && errors) {
375
- log += "\n" + errors.map((error) => colors.red(error)).join("\n");
376
- }
377
- logger.log(log);
378
- }
379
- }
380
- process.stdout.write("\n");
381
- logger.restoreStd();
382
- if (documents.some((v) => !v.isValid)) {
383
- logger.error("GraphQL document validation failed with errors.");
384
- } else {
385
- logger.success("GraphQL document validation completed successfully.");
386
- }
88
+ return generate(config, writeToDisk).then((v) => v[0]);
387
89
  }
388
90
 
389
91
  const logger = useLogger(name);
390
92
  const defaultOptions = {
391
- codegenConfig: {
392
- exportFragmentSpreadSubTypes: true,
393
- preResolveTypes: true,
394
- skipTypeNameForRoot: true,
395
- skipTypename: true,
396
- useTypeImports: true,
397
- onlyOperationTypes: true,
398
- namingConvention: {
399
- enumValues: "change-case-all#upperCaseFirst"
400
- }
401
- },
402
93
  downloadSchema: true,
403
94
  schemaPath: "~~/schema.graphql",
404
95
  serverApiPrefix: "/api/graphql_middleware",
@@ -408,16 +99,6 @@ const defaultOptions = {
408
99
  documents: [],
409
100
  devtools: true
410
101
  };
411
- function inlineFragments(source, resolver) {
412
- return inlineImportsWithLineToImports(source, {
413
- resolveImport(identifier) {
414
- return resolver(identifier);
415
- },
416
- resolveOptions: {
417
- basedir: "./"
418
- }
419
- }).inlineImports;
420
- }
421
102
  function validateOptions(options) {
422
103
  if (!options.graphqlEndpoint) {
423
104
  throw new Error("Missing graphqlEndpoint.");
@@ -433,321 +114,443 @@ async function getSchemaPath(schemaPath, options, resolver, writeToDisk = false)
433
114
  );
434
115
  throw new Error("Missing GraphQL schema.");
435
116
  }
436
- return dest;
117
+ const schemaContent = await promises.readFile(dest).then((v) => v.toString());
118
+ return { schemaPath, schemaContent };
437
119
  }
438
120
  if (!options.graphqlEndpoint) {
439
121
  throw new Error("Missing graphqlEndpoint config.");
440
122
  }
441
- await generateSchema(options, dest, writeToDisk);
442
- return dest;
123
+ const result = await generateSchema(options, dest, writeToDisk);
124
+ return { schemaPath, schemaContent: result.content };
443
125
  }
444
- async function autoImportDocuments(patterns = [], srcResolver) {
445
- if (!patterns.length) {
446
- return Promise.resolve([]);
126
+ const fileExists = (path, extensions = ["js", "ts", "mjs"]) => {
127
+ if (!path) {
128
+ return null;
129
+ } else if (existsSync$1(path)) {
130
+ return path;
447
131
  }
448
- const files = (await resolveFiles(srcResolver(), patterns, {
449
- followSymbolicLinks: false
450
- })).filter((path) => {
451
- return !path.includes("schema.gql") && !path.includes("schema.graphql");
452
- });
453
- return Promise.all(
454
- files.map((filename) => {
455
- return promises.readFile(filename).then((v) => {
456
- const content = v.toString().trim();
457
- return {
458
- content,
459
- filename
460
- };
461
- });
462
- })
132
+ const extension = extensions.find(
133
+ (extension2) => existsSync$1(`${path}.${extension2}`)
134
+ );
135
+ return extension ? `${path}.${extension}` : null;
136
+ };
137
+
138
+ function groupOperationsByType(ops) {
139
+ const result = {
140
+ query: {},
141
+ mutation: {},
142
+ subscription: {}
143
+ };
144
+ for (const op of ops) {
145
+ result[op.operationType][op.graphqlName] = {
146
+ hasVariables: op.hasVariables,
147
+ variablesOptional: !op.needsVariables
148
+ };
149
+ }
150
+ return result;
151
+ }
152
+ function buildOperationTypeCode(operationMetadata, typeName, serverApiPrefix) {
153
+ const imports = [];
154
+ const resultTypes = [];
155
+ let code = "";
156
+ let nitroCode = "";
157
+ const operationNames = Object.keys(operationMetadata);
158
+ if (operationNames.length === 0) {
159
+ return { code, nitroCode, imports, resultTypes };
160
+ }
161
+ const lines = [];
162
+ const nitroLines = [];
163
+ for (const name of operationNames) {
164
+ const nameResult = pascalCase(`${name}${typeName}`);
165
+ const nameVariables = pascalCase(`${name}${typeName}Variables`);
166
+ resultTypes.push(nameResult);
167
+ imports.push(nameResult);
168
+ const { hasVariables, variablesOptional } = operationMetadata[name];
169
+ if (hasVariables) {
170
+ imports.push(nameVariables);
171
+ }
172
+ const variablesType = hasVariables ? nameVariables : "null";
173
+ lines.push(
174
+ ` ${name}: [${variablesType}, ${variablesOptional ? "true" : "false"}, ${nameResult}]`
175
+ );
176
+ nitroLines.push(`
177
+ '${serverApiPrefix}/${typeName.toLowerCase()}/${name}': {
178
+ 'default': GraphqlResponse<${nameResult}>
179
+ }`);
180
+ }
181
+ code += ` export type GraphqlMiddleware${typeName} = {
182
+ ${lines.join(",\n")}
183
+ }
184
+ `;
185
+ nitroCode += nitroLines.join("\n");
186
+ return { code, nitroCode, imports, resultTypes };
187
+ }
188
+ function generateContextTemplate(collectedOperations, serverApiPrefix) {
189
+ const grouped = groupOperationsByType(collectedOperations);
190
+ const queryResult = buildOperationTypeCode(
191
+ grouped.query,
192
+ "Query",
193
+ serverApiPrefix
463
194
  );
195
+ const mutationResult = buildOperationTypeCode(
196
+ grouped.mutation,
197
+ "Mutation",
198
+ serverApiPrefix
199
+ );
200
+ const subscriptionResult = buildOperationTypeCode(
201
+ grouped.subscription,
202
+ "Subscription",
203
+ serverApiPrefix
204
+ );
205
+ const allImports = [
206
+ ...queryResult.imports,
207
+ ...mutationResult.imports,
208
+ ...subscriptionResult.imports
209
+ ];
210
+ const allResultTypes = [
211
+ ...queryResult.resultTypes,
212
+ ...mutationResult.resultTypes,
213
+ ...subscriptionResult.resultTypes
214
+ ];
215
+ const combinedCode = [
216
+ queryResult.code,
217
+ mutationResult.code,
218
+ subscriptionResult.code
219
+ ].join("\n");
220
+ const combinedNitroCode = [
221
+ queryResult.nitroCode,
222
+ mutationResult.nitroCode,
223
+ subscriptionResult.nitroCode
224
+ ].join("\n");
225
+ return `
226
+ import type { GraphqlResponse } from '#graphql-middleware-server-options-build'
227
+ import type {
228
+ ${allImports.join(",\n ")}
229
+ } from './../graphql-operations'
230
+
231
+ declare module '#nuxt-graphql-middleware/generated-types' {
232
+ export type GraphqlMiddlewareResponseUnion = ${allResultTypes.join(" | ")}
233
+ ${combinedCode}
464
234
  }
465
- function inlineNestedFragments(document, fragmentMap) {
466
- const parsed = parse(document);
467
- const fragmentsToInline = /* @__PURE__ */ new Set();
468
- visit(parsed, {
469
- FragmentSpread(node) {
470
- fragmentsToInline.add(node.name.value);
235
+
236
+ declare module 'nitropack' {
237
+ interface InternalApi {
238
+ ${combinedNitroCode}
239
+ }
240
+ }
241
+ `;
242
+ }
243
+
244
+ function getMaxLengths(entries) {
245
+ let name = 0;
246
+ let path = 0;
247
+ let type = 0;
248
+ for (const entry of entries) {
249
+ if (entry.type.length > type) {
250
+ type = entry.type.length;
471
251
  }
472
- });
473
- fragmentsToInline.forEach((fragmentName) => {
474
- const fragment = fragmentMap[fragmentName];
475
- if (fragment) {
476
- document += "\n" + fragment;
477
- const nestedFragmentNames = /* @__PURE__ */ new Set();
478
- visit(parse(fragment), {
479
- FragmentSpread(node) {
480
- nestedFragmentNames.add(node.name.value);
481
- }
482
- });
483
- nestedFragmentNames.forEach((nestedFragmentName) => {
484
- if (!fragmentsToInline.has(nestedFragmentName)) {
485
- fragmentsToInline.add(nestedFragmentName);
486
- const nestedFragment = fragmentMap[nestedFragmentName];
487
- if (nestedFragment) {
488
- document += "\n" + nestedFragment;
252
+ if (entry.name.length > name) {
253
+ name = entry.name.length;
254
+ }
255
+ if (entry.path.length > path) {
256
+ path = entry.path.length;
257
+ }
258
+ }
259
+ return { name, path, type };
260
+ }
261
+ function logAllEntries(entries) {
262
+ const lengths = getMaxLengths(entries);
263
+ let prevHadError = false;
264
+ for (const entry of entries) {
265
+ const hasErrors = entry.errors.length > 0;
266
+ const icon = hasErrors ? colors.red(" x ") : colors.green(" \u2713 ");
267
+ const type = entry.type.padEnd(lengths.type);
268
+ const namePadded = colors.bold(entry.name.padEnd(lengths.name));
269
+ const name = hasErrors ? colors.red(namePadded) : colors.green(namePadded);
270
+ const path = colors.dim(entry.path.padEnd(lengths.path));
271
+ const parts = [icon, type, name, path];
272
+ if (hasErrors && !prevHadError) {
273
+ process.stdout.write("-".repeat(process.stdout.columns) + "\n");
274
+ }
275
+ logger.log(parts.join(" | "));
276
+ if (hasErrors) {
277
+ const errorLines = [];
278
+ entry.errors.forEach((error) => {
279
+ let output = colors.red(error.message);
280
+ if (error.source && error.locations) {
281
+ for (const location of error.locations) {
282
+ output += "\n\n" + colors.red(printSourceLocation(error.source, location));
489
283
  }
490
284
  }
285
+ errorLines.push(output);
491
286
  });
287
+ logger.log(
288
+ errorLines.join("\n").split("\n").map((v) => " " + v).join("\n")
289
+ );
290
+ process.stdout.write("-".repeat(process.stdout.columns) + "\n");
492
291
  }
493
- });
494
- return document;
292
+ prevHadError = hasErrors;
293
+ }
294
+ logger.restoreStd();
495
295
  }
496
- async function buildDocuments(providedDocuments = [], autoImportPatterns, resolver, autoInlineFragments) {
497
- const documents = await autoImportDocuments(autoImportPatterns, resolver).then((importedDocuments) => [
498
- ...importedDocuments,
499
- ...providedDocuments.map((content) => ({
500
- content,
501
- filename: "nuxt.config.ts"
502
- }))
503
- ]).then((documents2) => {
504
- if (autoInlineFragments) {
505
- return documents2;
506
- }
507
- return documents2.map((v) => {
508
- if (!v.content.trim()) {
509
- return null;
296
+ class CollectedFile {
297
+ filePath;
298
+ fileContents;
299
+ isOnDisk;
300
+ parsed;
301
+ constructor(filePath, fileContents, isOnDisk = false) {
302
+ this.filePath = filePath;
303
+ this.fileContents = fileContents;
304
+ this.isOnDisk = isOnDisk;
305
+ this.parsed = parse(fileContents);
306
+ }
307
+ static async fromFilePath(filePath) {
308
+ const content = (await promises.readFile(filePath)).toString();
309
+ return new CollectedFile(filePath, content, true);
310
+ }
311
+ /**
312
+ * If isOnDisk, re-read file contents from disk, then parse it (syntax only).
313
+ */
314
+ async update() {
315
+ if (this.isOnDisk) {
316
+ const newContents = (await promises.readFile(this.filePath)).toString();
317
+ if (newContents === this.fileContents) {
318
+ return false;
510
319
  }
511
- try {
512
- return {
513
- content: inlineFragments(v.content, resolveAlias),
514
- filename: v.filename
515
- };
516
- } catch (e) {
517
- logger.error(e);
518
- logger.error(
519
- "Failed to inline fragments for document: " + v.filename
520
- );
521
- }
522
- return null;
523
- }).filter(falsy);
524
- }).then((docs) => {
525
- return docs.filter((v) => v.content.trim());
526
- });
527
- if (!autoInlineFragments) {
528
- return documents;
320
+ this.fileContents = newContents;
321
+ this.parsed = parse(newContents);
322
+ return true;
323
+ }
324
+ return false;
529
325
  }
530
- const fragmentMap = {};
531
- documents.forEach((doc) => {
532
- const parsed = parse(doc.content);
533
- visit(parsed, {
534
- FragmentDefinition(node) {
535
- fragmentMap[node.name.value] = print(node);
536
- }
537
- });
538
- });
539
- documents.forEach((doc) => {
540
- doc.content = inlineNestedFragments(doc.content, fragmentMap);
541
- });
542
- return documents;
543
326
  }
544
- function parseDocument(document, rootDir) {
545
- let name2 = document.filename ? document.filename.replace(rootDir, "") : "";
546
- if (name2.charAt(0) === "/") {
547
- name2 = name2.slice(1);
327
+ class Collector {
328
+ constructor(schema, context, nuxtConfigDocuments = [], generatorOptions) {
329
+ this.schema = schema;
330
+ this.context = context;
331
+ this.nuxtConfigDocuments = nuxtConfigDocuments;
332
+ this.generator = new Generator(schema, generatorOptions);
333
+ }
334
+ /**
335
+ * All collected files.
336
+ */
337
+ files = /* @__PURE__ */ new Map();
338
+ /**
339
+ * The code generator.
340
+ */
341
+ generator;
342
+ /**
343
+ * A map of operation name and timestamp when the operation was last validated.
344
+ */
345
+ operationTimestamps = /* @__PURE__ */ new Map();
346
+ /**
347
+ * The generated TypeScript type template output.
348
+ */
349
+ outputTypes = "";
350
+ /**
351
+ * The generated oeprations file.
352
+ */
353
+ outputOperations = "";
354
+ /**
355
+ * The generated context template file.
356
+ */
357
+ outputContext = "";
358
+ /**
359
+ * Whether we need to rebuild the Generator state.
360
+ */
361
+ needsRebuild = false;
362
+ filePathToRelative(filePath) {
363
+ return filePath.replace(this.context.srcDir, "~");
364
+ }
365
+ operationToLogEntry(operation, errors) {
366
+ return {
367
+ name: operation.graphqlName,
368
+ type: operation.operationType,
369
+ path: this.filePathToRelative(operation.filePath),
370
+ errors
371
+ };
548
372
  }
549
- const source = new Source(document.content, name2);
550
- return parse(source);
551
- }
552
- function validateDocuments(schema, documents, rootDir) {
553
- const validated = [];
554
- for (let i = 0; i < documents.length; i++) {
555
- const document = { ...documents[i] };
556
- if (document.filename) {
557
- document.relativePath = document.filename.replace(rootDir + "/", "");
373
+ /**
374
+ * Executes code gen and performs validation for operations.
375
+ */
376
+ buildState() {
377
+ const output = this.generator.build();
378
+ const operations = output.getCollectedOperations();
379
+ const generatedCode = output.getGeneratedCode();
380
+ this.outputOperations = output.getOperationsFile();
381
+ this.outputTypes = output.getEverything();
382
+ this.outputContext = generateContextTemplate(
383
+ operations,
384
+ this.context.serverApiPrefix
385
+ );
386
+ const fragmentMap = /* @__PURE__ */ new Map();
387
+ const operationSourceMap = /* @__PURE__ */ new Map();
388
+ for (const code of generatedCode) {
389
+ if (code.type === "fragment" && code.graphqlName && code.source) {
390
+ fragmentMap.set(code.graphqlName, code.source);
391
+ } else if (code.type === "operation" && code.graphqlName && code.source) {
392
+ operationSourceMap.set(code.graphqlName, code.source);
393
+ }
558
394
  }
559
- try {
560
- const node = parseDocument(document, rootDir);
561
- document.content = print(node);
562
- document.errors = validateGraphQlDocuments(schema, [
563
- node
564
- ]);
565
- const operation = node.definitions.find(
566
- (v) => v.kind === "OperationDefinition"
395
+ let hasErrors = false;
396
+ const logEntries = [];
397
+ for (const operation of operations) {
398
+ const previousTimestamp = this.operationTimestamps.get(
399
+ operation.graphqlName
567
400
  );
568
- if (operation) {
569
- document.name = operation.name?.value;
570
- document.operation = operation.operation;
401
+ if (previousTimestamp === operation.timestamp) {
402
+ continue;
403
+ }
404
+ const fragments = operation.dependencies.map(
405
+ (v) => v.type === "fragment-name" ? fragmentMap.get(v.value) || "" : ""
406
+ ).join("\n");
407
+ const fullOperation = operationSourceMap.get(operation.graphqlName) + fragments;
408
+ const source = new Source(fullOperation, basename(operation.filePath));
409
+ const document = parse(source);
410
+ const errors = validateGraphQlDocuments(this.schema, [document]);
411
+ if (errors.length) {
412
+ hasErrors = true;
571
413
  } else {
572
- document.name = document.relativePath;
414
+ this.operationTimestamps.set(operation.graphqlName, operation.timestamp);
573
415
  }
574
- document.isValid = document.errors.length === 0;
575
- } catch (e) {
576
- document.errors = [e];
577
- document.isValid = false;
416
+ logEntries.push(this.operationToLogEntry(operation, errors));
578
417
  }
579
- document.id = [document.operation, document.name, document.filename].filter(Boolean).join("_");
580
- validated.push(document);
581
- if (!document.isValid) {
582
- break;
418
+ logAllEntries(logEntries);
419
+ if (hasErrors) {
420
+ throw new Error("GraphQL errors");
583
421
  }
584
422
  }
585
- return validated;
586
- }
587
- function cleanGraphqlDocument(graphqlContent, operationName) {
588
- const document = parse(graphqlContent);
589
- let selectedOperation = null;
590
- const fragments = {};
591
- const usedFragments = /* @__PURE__ */ new Set();
592
- visit(document, {
593
- OperationDefinition(node) {
594
- if (node.name?.value === operationName) {
595
- selectedOperation = node;
596
- }
597
- },
598
- FragmentDefinition(node) {
599
- fragments[node.name.value] = node;
423
+ /**
424
+ * Get all file paths that match the import patterns.
425
+ */
426
+ async getImportPatternFiles() {
427
+ if (this.context.patterns.length) {
428
+ return resolveFiles(this.context.srcDir, this.context.patterns, {
429
+ followSymbolicLinks: false
430
+ });
600
431
  }
601
- });
602
- if (!selectedOperation) {
603
- throw new Error(`Operation named "${operationName}" not found`);
432
+ return [];
433
+ }
434
+ /**
435
+ * Initialise the collector.
436
+ */
437
+ async init() {
438
+ const files = await this.getImportPatternFiles();
439
+ for (const filePath of files) {
440
+ await this.addFile(filePath);
441
+ }
442
+ this.nuxtConfigDocuments.forEach((docString, i) => {
443
+ const pseudoPath = `nuxt.config.ts[${i}]`;
444
+ const file = new CollectedFile(pseudoPath, docString, false);
445
+ this.files.set(pseudoPath, file);
446
+ this.generator.add({
447
+ filePath: "~/nuxt.config.ts",
448
+ documentNode: file.parsed
449
+ });
450
+ });
451
+ this.buildState();
452
+ }
453
+ /**
454
+ * Add a file.
455
+ */
456
+ async addFile(filePath) {
457
+ const file = await CollectedFile.fromFilePath(filePath);
458
+ this.files.set(filePath, file);
459
+ this.generator.add({
460
+ filePath: this.filePathToRelative(filePath),
461
+ documentNode: file.parsed
462
+ });
463
+ return file;
604
464
  }
605
- visit(selectedOperation, {
606
- FragmentSpread(node) {
607
- usedFragments.add(node.name.value);
465
+ async handleAdd(filePath) {
466
+ await this.addFile(filePath);
467
+ return true;
468
+ }
469
+ async handleChange(filePath) {
470
+ const file = this.files.get(filePath);
471
+ if (!file) {
472
+ return false;
608
473
  }
609
- });
610
- let hasNewFragments = true;
611
- while (hasNewFragments) {
612
- hasNewFragments = false;
613
- for (const fragmentName of usedFragments) {
614
- visit(fragments[fragmentName], {
615
- FragmentSpread(node) {
616
- if (!usedFragments.has(node.name.value)) {
617
- usedFragments.add(node.name.value);
618
- hasNewFragments = true;
619
- }
474
+ const needsUpdate = await file.update();
475
+ if (!needsUpdate) {
476
+ return false;
477
+ }
478
+ this.generator.update({
479
+ filePath: this.filePathToRelative(filePath),
480
+ documentNode: file.parsed
481
+ });
482
+ return true;
483
+ }
484
+ handleUnlink(filePath) {
485
+ const file = this.files.get(filePath);
486
+ if (!file) {
487
+ return false;
488
+ }
489
+ this.files.delete(filePath);
490
+ this.generator.remove(this.filePathToRelative(filePath));
491
+ return true;
492
+ }
493
+ handleUnlinkDir(folderPath) {
494
+ let anyHasChanged = false;
495
+ for (const filePath of [...this.files.keys()]) {
496
+ if (filePath.startsWith(folderPath)) {
497
+ const hasChanged = this.handleUnlink(filePath);
498
+ if (hasChanged) {
499
+ anyHasChanged = true;
620
500
  }
621
- });
501
+ }
622
502
  }
503
+ return anyHasChanged;
623
504
  }
624
- return {
625
- kind: Kind.DOCUMENT,
626
- definitions: [
627
- selectedOperation,
628
- ...Array.from(usedFragments).map(
629
- (fragmentName) => fragments[fragmentName]
630
- )
631
- ]
632
- };
633
- }
634
- async function generate(options, schemaPath, resolver, rootDir, logEverything = false) {
635
- const schemaContent = await promises.readFile(schemaPath).then((v) => v.toString());
636
- const schema = await loadSchema(schemaContent, { loaders: [] });
637
- const documents = await buildDocuments(
638
- options.documents,
639
- options.autoImportPatterns,
640
- resolver,
641
- !!options.autoInlineFragments
642
- );
643
- const validated = validateDocuments(schema, documents, rootDir);
644
- const extracted = validated.filter(
645
- (v) => !v.operation
646
- );
647
- for (let i = 0; i < validated.length; i++) {
648
- const v = validated[i];
649
- if (!v) {
650
- continue;
651
- }
652
- if (v.isValid) {
653
- try {
654
- const node = parse(v.content);
655
- oldVisit(node, {
656
- enter: {
657
- OperationDefinition: (node2) => {
658
- if (node2.name?.value && node2.loc?.source && (node2.operation === "query" || node2.operation === "mutation")) {
659
- const document = { ...v };
660
- const cleaned = cleanGraphqlDocument(
661
- node2.loc.source.body,
662
- node2.name.value
663
- );
664
- const errors = validateGraphQlDocuments(schema, [cleaned]);
665
- document.errors = document.errors || [];
666
- document.errors.push(...errors);
667
- document.isValid = !document.errors.length;
668
- document.name = node2.name.value;
669
- document.operation = node2.operation;
670
- document.content = print(cleaned);
671
- document.id = [
672
- document.operation,
673
- document.name,
674
- document.filename
675
- ].filter(Boolean).join("_");
676
- extracted.push(document);
677
- }
678
- }
679
- }
680
- });
681
- } catch (e) {
682
- logger.error(e);
683
- extracted.push(v);
684
- break;
505
+ /**
506
+ * Handle the watcher event for the given file path.
507
+ */
508
+ async handleWatchEvent(event, filePath) {
509
+ try {
510
+ let hasChanged = false;
511
+ if (event === "add") {
512
+ hasChanged = await this.handleAdd(filePath);
513
+ } else if (event === "change") {
514
+ hasChanged = await this.handleChange(filePath);
515
+ } else if (event === "unlink") {
516
+ hasChanged = this.handleUnlink(filePath);
517
+ } else if (event === "unlinkDir") {
518
+ hasChanged = this.handleUnlinkDir(filePath);
519
+ } else if (event === "addDir") {
520
+ }
521
+ if (hasChanged) {
522
+ this.buildState();
685
523
  }
686
- } else {
687
- extracted.push(v);
688
- break;
524
+ } catch (e) {
525
+ this.generator.resetCaches();
526
+ console.log(e);
689
527
  }
690
528
  }
691
- const templates = await generateTemplates(
692
- extracted.filter((v) => v.isValid).map((v) => v.content),
693
- schemaPath,
694
- options
695
- );
696
- const hasErrors = extracted.some((v) => !v.isValid) || validated.some((v) => !v.isValid);
697
- if (hasErrors || logEverything) {
698
- logDocuments(logger, extracted, logEverything);
529
+ /**
530
+ * Get the TypeScript types template contents.
531
+ */
532
+ getTemplateTypes() {
533
+ return this.outputTypes;
699
534
  }
700
- process.stdout.write("\n");
701
- logger.restoreStd();
702
- hasErrors ? logger.error("GraphQL code generation failed with errors.") : logger.success("Finished GraphQL code generation.");
703
- return {
704
- templates: templates.sort((a, b) => {
705
- return a.filename.localeCompare(b.filename);
706
- }),
707
- hasErrors,
708
- documents: extracted.sort((a, b) => {
709
- const nameA = a.name || "";
710
- const nameB = b.name || "";
711
- return nameA.localeCompare(nameB);
712
- })
713
- };
714
- }
715
- const fileExists = (path, extensions = ["js", "ts", "mjs"]) => {
716
- if (!path) {
717
- return null;
718
- } else if (existsSync$1(path)) {
719
- return path;
535
+ /**
536
+ * Get the context template contents.
537
+ */
538
+ getTemplateContext() {
539
+ return this.outputContext;
720
540
  }
721
- const extension = extensions.find(
722
- (extension2) => existsSync$1(`${path}.${extension2}`)
723
- );
724
- return extension ? `${path}.${extension}` : null;
725
- };
726
- async function outputDocuments(outputPath, documents) {
727
- await promises.mkdir(outputPath, { recursive: true });
728
- documents.forEach((v) => {
729
- if (v.operation && v.name) {
730
- const fileName = [v.operation, v.name, "graphql"].join(".");
731
- const filePath = resolve(outputPath, fileName);
732
- promises.writeFile(filePath, v.content);
733
- }
734
- });
735
- }
736
- async function getOutputDocumentsPath(optionsOutputDocuments, nuxtBuildDir, resolvePath) {
737
- if (!optionsOutputDocuments) {
738
- return null;
541
+ /**
542
+ * Get the operations template contents.
543
+ */
544
+ getTemplateOperations() {
545
+ return this.outputOperations;
739
546
  }
740
- if (typeof optionsOutputDocuments === "boolean") {
741
- return resolve(nuxtBuildDir, `${name}/documents`);
742
- } else {
743
- return await resolvePath(optionsOutputDocuments);
547
+ /**
548
+ * Log results (including parse/validation errors).
549
+ */
550
+ logDocuments(logEverything) {
744
551
  }
745
552
  }
746
553
 
747
- function pathWithoutExtension(fullPath) {
748
- const parsed = parse$1(fullPath);
749
- return join(parsed.dir, parsed.name);
750
- }
751
554
  const RPC_NAMESPACE = "nuxt-graphql-middleware";
752
555
  const module = defineNuxtModule({
753
556
  meta: {
@@ -761,12 +564,14 @@ const module = defineNuxtModule({
761
564
  defaults: defaultOptions,
762
565
  async setup(passedOptions, nuxt) {
763
566
  const options = defu({}, passedOptions, defaultOptions);
567
+ function addAlias(name2, aliasPath) {
568
+ nuxt.options.alias[name2] = aliasPath;
569
+ }
764
570
  const isModuleBuild = process.env.MODULE_BUILD === "true" && nuxt.options._prepare;
765
571
  if (isModuleBuild) {
766
572
  options.graphqlEndpoint = "http://localhost";
767
573
  options.downloadSchema = false;
768
574
  options.schemaPath = "~~/schema.graphql";
769
- options.autoInlineFragments = true;
770
575
  options.autoImportPatterns = [
771
576
  "~~/playground/**/*.{gql,graphql}",
772
577
  "!node_modules"
@@ -783,37 +588,47 @@ const module = defineNuxtModule({
783
588
  if (!nuxt.options._prepare) {
784
589
  validateOptions(options);
785
590
  }
786
- const schemaPathReplaced = resolveAlias(options.schemaPath);
787
591
  const moduleResolver = createResolver(import.meta.url);
788
592
  const serverResolver = createResolver(nuxt.options.serverDir);
789
593
  const srcResolver = createResolver(nuxt.options.srcDir);
790
594
  const appResolver = createResolver(nuxt.options.dir.app);
791
595
  const rootDir = nuxt.options.rootDir;
792
596
  const rootResolver = createResolver(rootDir);
793
- const schemaPath = await getSchemaPath(
794
- schemaPathReplaced,
597
+ const { schemaPath, schemaContent } = await getSchemaPath(
598
+ resolveAlias(options.schemaPath),
795
599
  options,
796
600
  rootResolver.resolve,
797
601
  options.downloadSchema
798
602
  );
603
+ const schema = await loadSchema(schemaContent, {
604
+ loaders: []
605
+ });
799
606
  const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url));
800
607
  nuxt.options.build.transpile.push(runtimeDir);
801
- const ctx = {
802
- templates: [],
803
- documents: []
608
+ const context = {
609
+ patterns: options.autoImportPatterns || [],
610
+ srcDir: nuxt.options.srcDir,
611
+ schemaPath,
612
+ serverApiPrefix: options.serverApiPrefix
804
613
  };
805
- let rpc = null;
614
+ const collector = new Collector(
615
+ schema,
616
+ context,
617
+ options.documents,
618
+ options.codegenConfig
619
+ );
620
+ await collector.init();
806
621
  if (options.devtools) {
807
622
  const clientPath = moduleResolver.resolve("./client");
808
623
  setupDevToolsUI(nuxt, clientPath);
809
624
  const setupRpc = () => {
810
- rpc = extendServerRpc(RPC_NAMESPACE, {
625
+ extendServerRpc(RPC_NAMESPACE, {
811
626
  // register server RPC functions
812
627
  getModuleOptions() {
813
628
  return options;
814
629
  },
815
630
  getDocuments() {
816
- return ctx.documents;
631
+ return [];
817
632
  }
818
633
  });
819
634
  };
@@ -825,70 +640,6 @@ const module = defineNuxtModule({
825
640
  });
826
641
  }
827
642
  }
828
- let prompt = null;
829
- const generateHandler = async (isFirst = false) => {
830
- if (prompt && prompt.ui) {
831
- prompt.ui.close();
832
- prompt = null;
833
- }
834
- try {
835
- const { templates, hasErrors, documents } = await generate(
836
- options,
837
- schemaPath,
838
- rootResolver.resolve,
839
- rootDir,
840
- isFirst
841
- );
842
- ctx.templates = templates;
843
- ctx.documents = documents;
844
- rpc?.broadcast.documentsUpdated(documents);
845
- const outputDocumentsPath = await getOutputDocumentsPath(
846
- options.outputDocuments,
847
- nuxt.options.buildDir,
848
- rootResolver.resolvePath
849
- );
850
- if (outputDocumentsPath) {
851
- outputDocuments(outputDocumentsPath, documents);
852
- if (isFirst) {
853
- logger.info("Documents generated at " + outputDocumentsPath);
854
- }
855
- }
856
- if (hasErrors) {
857
- throw new Error("Documents has errors.");
858
- }
859
- } catch (e) {
860
- console.log(e);
861
- logger.error("Failed to generate GraphQL files.");
862
- if (isFirst) {
863
- process.exit(1);
864
- }
865
- if (!options.downloadSchema) {
866
- return;
867
- }
868
- if (!nuxt.options.dev) {
869
- return;
870
- }
871
- process.stdout.write("\n");
872
- logger.restoreStd();
873
- prompt = inquirer.prompt({
874
- type: "confirm",
875
- name: "accept",
876
- message: "Do you want to reload the GraphQL schema?"
877
- });
878
- prompt.then(async ({ accept }) => {
879
- if (accept) {
880
- await getSchemaPath(
881
- schemaPathReplaced,
882
- options,
883
- rootResolver.resolve,
884
- true
885
- );
886
- await generateHandler();
887
- }
888
- });
889
- }
890
- };
891
- await generateHandler(true);
892
643
  nuxt.options.runtimeConfig.public["nuxt-graphql-middleware"] = {
893
644
  serverApiPrefix: options.serverApiPrefix
894
645
  };
@@ -925,32 +676,27 @@ const module = defineNuxtModule({
925
676
  );
926
677
  addServerImports(serverUtils);
927
678
  }
928
- Object.values(GraphqlMiddlewareTemplate).forEach((filename) => {
929
- const result = addTemplate({
930
- write: true,
931
- filename,
932
- options: {
933
- nuxtGraphqlMiddleware: true
934
- },
935
- getContents: () => {
936
- return ctx.templates.find((v) => v.filename === filename)?.content || "";
937
- }
938
- });
939
- if (result.dst.includes(GraphqlMiddlewareTemplate.Documents)) {
940
- nuxt.options.alias["#graphql-documents"] = pathWithoutExtension(
941
- result.dst
942
- );
943
- } else if (result.dst.includes(GraphqlMiddlewareTemplate.OperationTypes)) {
944
- nuxt.options.alias["#graphql-operations"] = pathWithoutExtension(
945
- result.dst
946
- );
947
- } else if (result.dst.includes(GraphqlMiddlewareTemplate.ComposableContext)) {
948
- nuxt.options.alias["#nuxt-graphql-middleware/generated-types"] = pathWithoutExtension(result.dst);
949
- }
679
+ const templateTypescript = addTemplate({
680
+ filename: GraphqlMiddlewareTemplate.OperationTypes,
681
+ write: true,
682
+ getContents: () => collector.getTemplateTypes()
683
+ });
684
+ addAlias("#graphql-operations", templateTypescript.dst);
685
+ const templateDocuments = addTemplate({
686
+ filename: GraphqlMiddlewareTemplate.Documents,
687
+ write: true,
688
+ getContents: () => collector.getTemplateOperations()
689
+ });
690
+ addAlias("#graphql-documents", templateDocuments.dst);
691
+ const templateContext = addTemplate({
692
+ filename: GraphqlMiddlewareTemplate.ComposableContext,
693
+ write: true,
694
+ getContents: () => collector.getTemplateContext()
950
695
  });
696
+ addAlias("#nuxt-graphql-middleware/generated-types", templateContext.dst);
951
697
  addTemplate({
952
698
  write: true,
953
- filename: "graphql-documents.d.ts",
699
+ filename: "nuxt-graphql-middleware/graphql-documents.d.ts",
954
700
  getContents: () => {
955
701
  return `
956
702
  import type {
@@ -959,12 +705,12 @@ import type {
959
705
  } from '#nuxt-graphql-middleware/generated-types'
960
706
 
961
707
  declare module '#graphql-documents' {
962
- type Documents = {
708
+ type Operations = {
963
709
  query: GraphqlMiddlewareQuery
964
710
  mutation: GraphqlMiddlewareMutation
965
711
  }
966
- const documents: Documents
967
- export { documents, Documents }
712
+ const operations: Operations
713
+ export { operations, Operations }
968
714
  }
969
715
  `;
970
716
  }
@@ -1075,12 +821,14 @@ export type GraphqlClientContext = {}
1075
821
  `;
1076
822
  }
1077
823
  });
1078
- nuxt.options.alias["#graphql-middleware-client-options"] = pathWithoutExtension(clientOptionsTemplate.dst);
824
+ addAlias("#graphql-middleware-client-options", clientOptionsTemplate.dst);
1079
825
  nuxt.options.nitro.externals = nuxt.options.nitro.externals || {};
1080
826
  nuxt.options.nitro.externals.inline = nuxt.options.nitro.externals.inline || [];
1081
827
  nuxt.options.nitro.externals.inline.push(template.dst);
1082
- nuxt.options.alias["#graphql-middleware-server-options-build"] = pathWithoutExtension(template.dst);
1083
- nuxt.options.alias["#graphql-middleware/types"] = pathWithoutExtension(
828
+ nuxt.options.nitro.externals.inline.push(templateDocuments.dst);
829
+ addAlias("#graphql-middleware-server-options-build", template.dst);
830
+ addAlias(
831
+ "#graphql-middleware/types",
1084
832
  moduleResolver.resolve("./runtime/types.ts")
1085
833
  );
1086
834
  addServerHandler({
@@ -1109,26 +857,14 @@ export type GraphqlClientContext = {}
1109
857
  handler: moduleResolver.resolve("./runtime/serverHandler/debug"),
1110
858
  route: options.serverApiPrefix + "/debug"
1111
859
  });
1112
- nuxt.hook("nitro:build:before", (nitro) => {
1113
- nuxt.hook("builder:watch", async (_event, path) => {
1114
- path = relative(
1115
- nuxt.options.srcDir,
1116
- resolve(nuxt.options.srcDir, path)
1117
- );
1118
- if (!path.match(/\.(gql|graphql)$/)) {
1119
- return;
1120
- }
1121
- if (schemaPath.includes(path)) {
1122
- return;
1123
- }
1124
- await generateHandler();
1125
- await updateTemplates({
1126
- filter: (template2) => {
1127
- return template2.options && template2.options.nuxtGraphqlMiddleware;
1128
- }
1129
- });
1130
- await nitro.hooks.callHook("dev:reload");
1131
- });
860
+ nuxt.hook("builder:watch", async (event, pathAbsolute) => {
861
+ if (pathAbsolute === schemaPath) {
862
+ return;
863
+ }
864
+ if (!pathAbsolute.match(/\.(gql|graphql)$/)) {
865
+ return;
866
+ }
867
+ await collector.handleWatchEvent(event, pathAbsolute);
1132
868
  });
1133
869
  }
1134
870
  }