nuxt-graphql-middleware 5.0.0-alpha.4 → 5.0.0-alpha.6

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.
Files changed (62) hide show
  1. package/dist/client/200.html +7 -7
  2. package/dist/client/404.html +7 -7
  3. package/dist/client/_nuxt/{CZ2Qwgdk.js → B4KMzhZo.js} +1 -1
  4. package/dist/client/_nuxt/BawWjxPx.js +25 -0
  5. package/dist/client/_nuxt/BtHrwWER.js +1 -0
  6. package/dist/client/_nuxt/BvMfLM9s.js +1 -0
  7. package/dist/client/_nuxt/{GOrnHr4p.js → DkAo05uu.js} +1 -1
  8. package/dist/client/_nuxt/builds/latest.json +1 -1
  9. package/dist/client/_nuxt/builds/meta/9b9c571e-ce30-465b-8174-06afbdca446b.json +1 -0
  10. package/dist/client/index.html +7 -7
  11. package/dist/module.d.mts +199 -159
  12. package/dist/module.d.ts +199 -159
  13. package/dist/module.json +2 -2
  14. package/dist/module.mjs +938 -591
  15. package/dist/runtime/components/CodeFrame.vue +61 -0
  16. package/dist/runtime/components/DevModeOverlay.vue +60 -0
  17. package/dist/runtime/components/ErrorExtensions.vue +23 -0
  18. package/dist/runtime/components/ErrorGroup.vue +89 -0
  19. package/dist/runtime/composables/nuxtApp.d.ts +2 -2
  20. package/dist/runtime/composables/nuxtApp.js +19 -18
  21. package/dist/runtime/composables/useAsyncGraphqlQuery.d.ts +7 -7
  22. package/dist/runtime/composables/useAsyncGraphqlQuery.js +10 -2
  23. package/dist/runtime/composables/useGraphqlMutation.d.ts +4 -4
  24. package/dist/runtime/composables/useGraphqlMutation.js +1 -1
  25. package/dist/runtime/composables/useGraphqlQuery.d.ts +4 -4
  26. package/dist/runtime/composables/useGraphqlQuery.js +1 -1
  27. package/dist/runtime/composables/useGraphqlState.d.ts +1 -1
  28. package/dist/runtime/composables/useGraphqlUploadMutation.d.ts +4 -4
  29. package/dist/runtime/composables/useGraphqlUploadMutation.js +2 -2
  30. package/dist/runtime/css/output.css +1 -0
  31. package/dist/runtime/helpers/composables.d.ts +17 -20
  32. package/dist/runtime/helpers/composables.js +0 -5
  33. package/dist/runtime/plugins/devMode.d.ts +2 -0
  34. package/dist/runtime/plugins/devMode.js +23 -0
  35. package/dist/runtime/plugins/provideState.d.ts +1 -1
  36. package/dist/runtime/{serverHandler → server/api}/debug.js +3 -7
  37. package/dist/runtime/server/api/mutation.js +28 -0
  38. package/dist/runtime/server/api/query.js +29 -0
  39. package/dist/runtime/server/api/upload.d.ts +2 -0
  40. package/dist/runtime/{serverHandler → server/api}/upload.js +13 -11
  41. package/dist/runtime/{serverHandler → server}/helpers/index.d.ts +8 -10
  42. package/dist/runtime/{serverHandler → server}/helpers/index.js +8 -25
  43. package/dist/runtime/server/utils/doGraphqlRequest.d.ts +18 -0
  44. package/dist/runtime/server/utils/doGraphqlRequest.js +67 -0
  45. package/dist/runtime/server/utils/index.d.ts +1 -1
  46. package/dist/runtime/server/utils/index.js +1 -1
  47. package/dist/runtime/server/utils/useGraphqlMutation.d.ts +4 -4
  48. package/dist/runtime/server/utils/useGraphqlQuery.d.ts +4 -4
  49. package/dist/runtime/serverOptions/defineGraphqlServerOptions.d.ts +3 -2
  50. package/dist/runtime/settings/index.d.ts +49 -4
  51. package/dist/runtime/settings/index.js +19 -7
  52. package/dist/runtime/types.d.ts +8 -2
  53. package/package.json +21 -9
  54. package/dist/client/_nuxt/BS583yk8.js +0 -25
  55. package/dist/client/_nuxt/DpxjPVZy.js +0 -1
  56. package/dist/client/_nuxt/builds/meta/106a09af-649a-473b-b0c7-0e4ce5709429.json +0 -1
  57. package/dist/client/_nuxt/exxdaCPN.js +0 -1
  58. package/dist/runtime/serverHandler/index.js +0 -78
  59. package/dist/runtime/serverHandler/tsconfig.json +0 -3
  60. /package/dist/runtime/{serverHandler → server/api}/debug.d.ts +0 -0
  61. /package/dist/runtime/{serverHandler/index.d.ts → server/api/mutation.d.ts} +0 -0
  62. /package/dist/runtime/{serverHandler/upload.d.ts → server/api/query.d.ts} +0 -0
package/dist/module.mjs CHANGED
@@ -1,93 +1,26 @@
1
- import { loadSchema } from '@graphql-tools/load';
2
1
  import { fileURLToPath } from 'url';
3
- import { relative } from 'pathe';
4
- import { defu } from 'defu';
5
- import { useLogger, resolveFiles, defineNuxtModule, resolveAlias, createResolver, addImports, addServerImports, addTemplate, addServerHandler, addPlugin } from '@nuxt/kit';
6
- import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
7
- import { existsSync } from 'fs';
8
- import { GraphqlMiddlewareTemplate } from '../dist/runtime/settings/index.js';
2
+ import { useLogger, addTemplate, addServerTemplate, addTypeTemplate, resolveAlias, createResolver, resolveFiles, addPlugin, addServerHandler, addImports, addServerImports, useNitro, defineNuxtModule } from '@nuxt/kit';
3
+ import { Template } from '../dist/runtime/settings/index.js';
9
4
  import fs from 'node:fs/promises';
10
- import { existsSync as existsSync$1, promises } from 'node:fs';
11
- import { generate } from '@graphql-codegen/cli';
12
- import * as PluginSchemaAst from '@graphql-codegen/schema-ast';
5
+ import { existsSync, promises } from 'node:fs';
6
+ import { relative } from 'pathe';
13
7
  import { basename } from 'node:path';
14
- import { printSourceLocation, parse, Source } from 'graphql';
8
+ import { printSourceLocation, parse, OperationTypeNode, Source } from 'graphql';
15
9
  import { Generator, FieldNotFoundError, TypeNotFoundError, FragmentNotFoundError } from 'graphql-typescript-deluxe';
16
- import { pascalCase } from 'change-case-all';
17
- import colors from 'picocolors';
10
+ import color from 'picocolors';
18
11
  import { validateGraphQlDocuments } from '@graphql-tools/utils';
12
+ import { generate } from '@graphql-codegen/cli';
13
+ import * as PluginSchemaAst from '@graphql-codegen/schema-ast';
14
+ import { loadSchema } from '@graphql-tools/load';
15
+ import { defu } from 'defu';
16
+ import * as micromatch from 'micromatch';
17
+ import { ConfirmPrompt } from '@clack/core';
18
+ import isUnicodeSupported from 'is-unicode-supported';
19
+ import { existsSync as existsSync$1 } from 'fs';
20
+ import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
19
21
 
20
22
  const name = "nuxt-graphql-middleware";
21
- const version = "5.0.0-alpha.4";
22
-
23
- const DEVTOOLS_UI_ROUTE = "/__nuxt-graphql-middleware";
24
- const DEVTOOLS_UI_LOCAL_PORT = 3300;
25
- function setupDevToolsUI(nuxt, clientPath) {
26
- const isProductionBuild = existsSync(clientPath);
27
- if (isProductionBuild) {
28
- nuxt.hook("vite:serverCreated", async (server) => {
29
- const sirv = await import('sirv').then((r) => r.default || r);
30
- server.middlewares.use(
31
- DEVTOOLS_UI_ROUTE,
32
- sirv(clientPath, { dev: true, single: true })
33
- );
34
- });
35
- } else {
36
- nuxt.hook("vite:extendConfig", (config) => {
37
- config.server = config.server || {};
38
- config.server.proxy = config.server.proxy || {};
39
- config.server.proxy[DEVTOOLS_UI_ROUTE] = {
40
- target: "http://localhost:" + DEVTOOLS_UI_LOCAL_PORT + DEVTOOLS_UI_ROUTE,
41
- changeOrigin: true,
42
- followRedirects: true,
43
- rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
44
- };
45
- });
46
- }
47
- nuxt.hook("devtools:customTabs", (tabs) => {
48
- tabs.push({
49
- // unique identifier
50
- name: "nuxt-graphql-middleware",
51
- // title to display in the tab
52
- title: "GraphQL Middleware",
53
- // any icon from Iconify, or a URL to an image
54
- icon: "akar-icons:graphql-fill",
55
- // iframe view
56
- view: {
57
- type: "iframe",
58
- src: DEVTOOLS_UI_ROUTE
59
- }
60
- });
61
- });
62
- }
63
-
64
- function pluginLoader(name) {
65
- switch (name) {
66
- case "@graphql-codegen/schema-ast":
67
- return Promise.resolve(PluginSchemaAst);
68
- }
69
- throw new Error(`graphql-codegen plugin not found: ${name}`);
70
- }
71
- function generateSchema(moduleOptions, dest, writeToDisk) {
72
- const pluginConfig = moduleOptions.codegenSchemaConfig?.urlSchemaOptions;
73
- const schemaAstConfig = moduleOptions.codegenSchemaConfig?.schemaAstConfig || {
74
- sort: true
75
- };
76
- const config = {
77
- schema: moduleOptions.graphqlEndpoint,
78
- pluginLoader,
79
- silent: true,
80
- errorsOnly: true,
81
- config: pluginConfig,
82
- generates: {
83
- [dest]: {
84
- plugins: ["schema-ast"],
85
- config: schemaAstConfig
86
- }
87
- }
88
- };
89
- return generate(config, writeToDisk).then((v) => v[0]);
90
- }
23
+ const version = "5.0.0-alpha.6";
91
24
 
92
25
  const logger = useLogger(name);
93
26
  const defaultOptions = {
@@ -98,151 +31,27 @@ const defaultOptions = {
98
31
  debug: false,
99
32
  includeComposables: true,
100
33
  documents: [],
101
- devtools: true
34
+ devtools: true,
35
+ errorOverlay: true,
36
+ graphqlConfigFilePath: "./graphql.config.ts"
102
37
  };
103
38
  function validateOptions(options) {
104
39
  if (!options.graphqlEndpoint) {
105
40
  throw new Error("Missing graphqlEndpoint.");
106
41
  }
107
42
  }
108
- async function getSchemaPath(schemaPath, options, resolver, writeToDisk = false) {
109
- const dest = resolver(schemaPath);
110
- if (!options.downloadSchema) {
111
- const fileExists2 = await fs.access(dest).then(() => true).catch(() => false);
112
- if (!fileExists2) {
113
- logger.error(
114
- '"downloadSchema" is set to false but no schema exists at ' + dest
115
- );
116
- throw new Error("Missing GraphQL schema.");
117
- }
118
- const schemaContent = await fs.readFile(dest).then((v) => v.toString());
119
- return { schemaPath, schemaContent };
120
- }
121
- if (!options.graphqlEndpoint) {
122
- throw new Error("Missing graphqlEndpoint config.");
123
- }
124
- const result = await generateSchema(options, dest, writeToDisk);
125
- return { schemaPath, schemaContent: result.content };
126
- }
127
43
  const fileExists = (path, extensions = ["js", "ts", "mjs"]) => {
128
44
  if (!path) {
129
45
  return null;
130
- } else if (existsSync$1(path)) {
46
+ } else if (existsSync(path)) {
131
47
  return path;
132
48
  }
133
49
  const extension = extensions.find(
134
- (extension2) => existsSync$1(`${path}.${extension2}`)
50
+ (extension2) => existsSync(`${path}.${extension2}`)
135
51
  );
136
52
  return extension ? `${path}.${extension}` : null;
137
53
  };
138
54
 
139
- function groupOperationsByType(ops) {
140
- const result = {
141
- query: {},
142
- mutation: {},
143
- subscription: {}
144
- };
145
- for (const op of ops) {
146
- result[op.operationType][op.graphqlName] = {
147
- hasVariables: op.hasVariables,
148
- variablesOptional: !op.needsVariables
149
- };
150
- }
151
- return result;
152
- }
153
- function buildOperationTypeCode(operationMetadata, typeName, serverApiPrefix) {
154
- const imports = [];
155
- const resultTypes = [];
156
- let code = "";
157
- let nitroCode = "";
158
- const operationNames = Object.keys(operationMetadata);
159
- if (operationNames.length === 0) {
160
- return { code, nitroCode, imports, resultTypes };
161
- }
162
- const lines = [];
163
- const nitroLines = [];
164
- for (const name of operationNames) {
165
- const nameResult = pascalCase(`${name}${typeName}`);
166
- const nameVariables = pascalCase(`${name}${typeName}Variables`);
167
- resultTypes.push(nameResult);
168
- imports.push(nameResult);
169
- const { hasVariables, variablesOptional } = operationMetadata[name];
170
- if (hasVariables) {
171
- imports.push(nameVariables);
172
- }
173
- const variablesType = hasVariables ? nameVariables : "null";
174
- lines.push(
175
- ` ${name}: [${variablesType}, ${variablesOptional ? "true" : "false"}, ${nameResult}]`
176
- );
177
- nitroLines.push(`
178
- '${serverApiPrefix}/${typeName.toLowerCase()}/${name}': {
179
- 'default': GraphqlResponse<${nameResult}>
180
- }`);
181
- }
182
- code += ` export type GraphqlMiddleware${typeName} = {
183
- ${lines.join(",\n")}
184
- }
185
- `;
186
- nitroCode += nitroLines.join("\n");
187
- return { code, nitroCode, imports, resultTypes };
188
- }
189
- function generateContextTemplate(collectedOperations, serverApiPrefix) {
190
- const grouped = groupOperationsByType(collectedOperations);
191
- const queryResult = buildOperationTypeCode(
192
- grouped.query,
193
- "Query",
194
- serverApiPrefix
195
- );
196
- const mutationResult = buildOperationTypeCode(
197
- grouped.mutation,
198
- "Mutation",
199
- serverApiPrefix
200
- );
201
- const subscriptionResult = buildOperationTypeCode(
202
- grouped.subscription,
203
- "Subscription",
204
- serverApiPrefix
205
- );
206
- const allImports = [
207
- ...queryResult.imports,
208
- ...mutationResult.imports,
209
- ...subscriptionResult.imports
210
- ];
211
- const allResultTypes = [
212
- ...queryResult.resultTypes,
213
- ...mutationResult.resultTypes,
214
- ...subscriptionResult.resultTypes
215
- ];
216
- const combinedCode = [
217
- queryResult.code,
218
- mutationResult.code,
219
- subscriptionResult.code
220
- ].filter(Boolean).join("\n");
221
- const combinedNitroCode = [
222
- queryResult.nitroCode,
223
- mutationResult.nitroCode,
224
- subscriptionResult.nitroCode
225
- ].join("\n");
226
- const typeImports = allImports.length ? `import type {
227
- ${allImports.join(",\n ")}
228
- } from './../graphql-operations'` : "";
229
- return `
230
- import type { GraphqlResponse } from '#graphql-middleware-server-options-build'
231
- ${typeImports}
232
-
233
- declare module '#nuxt-graphql-middleware/generated-types' {
234
- export type GraphqlMiddlewareResponseUnion = ${allResultTypes.join(" | ") || "never"}
235
- ${combinedCode}
236
- }
237
-
238
- declare module 'nitropack' {
239
- interface InternalApi {
240
- ${combinedNitroCode}
241
- }
242
- }
243
- `;
244
- }
245
-
246
55
  const SYMBOL_CROSS = "x";
247
56
  const SYMBOL_CHECK = "\u2714";
248
57
  function getMaxLengths(entries) {
@@ -267,11 +76,11 @@ function logAllEntries(entries) {
267
76
  let prevHadError = false;
268
77
  for (const entry of entries) {
269
78
  const hasErrors = entry.errors.length > 0;
270
- const icon = hasErrors ? colors.red(SYMBOL_CROSS) : colors.green(SYMBOL_CHECK);
79
+ const icon = hasErrors ? color.red(SYMBOL_CROSS) : color.green(SYMBOL_CHECK);
271
80
  const type = entry.type.padEnd(lengths.type);
272
- const namePadded = colors.bold(entry.name.padEnd(lengths.name));
273
- const name = hasErrors ? colors.red(namePadded) : colors.green(namePadded);
274
- const path = colors.dim(entry.path);
81
+ const namePadded = color.bold(entry.name.padEnd(lengths.name));
82
+ const name = hasErrors ? color.red(namePadded) : color.green(namePadded);
83
+ const path = color.dim(entry.path);
275
84
  const parts = [icon, type, name, path];
276
85
  if (hasErrors && !prevHadError) {
277
86
  process.stdout.write("-".repeat(process.stdout.columns) + "\n");
@@ -280,10 +89,10 @@ function logAllEntries(entries) {
280
89
  if (hasErrors) {
281
90
  const errorLines = [];
282
91
  entry.errors.forEach((error) => {
283
- let output = colors.red(error.message);
92
+ let output = color.red(error.message);
284
93
  if (error.source && error.locations) {
285
94
  for (const location of error.locations) {
286
- output += "\n\n" + colors.red(printSourceLocation(error.source, location));
95
+ output += "\n\n" + color.red(printSourceLocation(error.source, location));
287
96
  }
288
97
  }
289
98
  errorLines.push(output);
@@ -330,12 +139,80 @@ class CollectedFile {
330
139
  }
331
140
  }
332
141
 
142
+ function ResponseTypes(operations, helper) {
143
+ const allTypes = operations.map((v) => v.typeName).sort();
144
+ return `import type {
145
+ ${allTypes.join(",\n ")}
146
+ } from './../graphql-operations'
147
+ import type { GraphqlResponseAdditions } from './server-options'
148
+ import type { GraphqlServerResponse } from '${helper.paths.runtimeTypes}'
149
+
150
+ declare module '#nuxt-graphql-middleware/response' {
151
+ export type GraphqlMiddlewareResponseUnion =
152
+ | ${allTypes.join("\n | ") || "never"}
153
+
154
+ export type GraphqlResponse<T> = GraphqlServerResponse<T> & GraphqlResponseAdditions
155
+ export type GraphqlResponseTyped = GraphqlResponse<GraphqlMiddlewareResponseUnion>
156
+ }`;
157
+ }
158
+
159
+ function NitroTypes(operations, serverApiPrefix) {
160
+ const endpoints = [];
161
+ const imports = [];
162
+ for (const operation of operations) {
163
+ imports.push(operation.typeName);
164
+ const method = operation.operationType === OperationTypeNode.QUERY ? "get" : "post";
165
+ endpoints.push(
166
+ ` '${serverApiPrefix}/${operation.operationType}/${operation.graphqlName}': {
167
+ '${method}': GraphqlResponse<${operation.typeName}>
168
+ }`
169
+ );
170
+ }
171
+ return `import type { GraphqlResponse } from './response'
172
+ import type {
173
+ ${imports.sort().join(",\n ")}
174
+ } from './../graphql-operations'
175
+
176
+ declare module 'nitropack/types' {
177
+ interface InternalApi {
178
+ ${endpoints.sort().join("\n")}
179
+ }
180
+ }`;
181
+ }
182
+
183
+ function OperationSources(operations, srcDir) {
184
+ const lines = [];
185
+ for (const operation of operations) {
186
+ const filePath = relative(srcDir, operation.filePath);
187
+ lines.push(
188
+ `${operation.operationType}_${operation.graphqlName}: '${filePath}',`
189
+ );
190
+ }
191
+ return `
192
+ export const operationSources = {
193
+ ${lines.join("\n ")}
194
+ }
195
+ `;
196
+ }
197
+
198
+ function OperationTypes(generatorOutput) {
199
+ const typesFile = generatorOutput.getTypes();
200
+ let output = "";
201
+ const enumImports = typesFile.getTypeScriptEnumDependencies();
202
+ if (enumImports.length) {
203
+ output += `import type { ${enumImports.join(", ")} } from './enums'
204
+
205
+ `;
206
+ }
207
+ output += typesFile.getSource();
208
+ return output;
209
+ }
210
+
333
211
  class Collector {
334
- constructor(schema, context, nuxtConfigDocuments = [], generatorOptions = {}) {
212
+ constructor(schema, helper) {
335
213
  this.schema = schema;
336
- this.context = context;
337
- this.nuxtConfigDocuments = nuxtConfigDocuments;
338
- const mappedOptions = { ...generatorOptions };
214
+ this.helper = helper;
215
+ const mappedOptions = { ...helper.options.codegenConfig };
339
216
  if (!mappedOptions.output) {
340
217
  mappedOptions.output = {};
341
218
  }
@@ -363,23 +240,23 @@ class Collector {
363
240
  */
364
241
  rpcItems = /* @__PURE__ */ new Map();
365
242
  /**
366
- * The generated TypeScript type template output.
243
+ * The generated templates.
367
244
  */
368
- outputTypes = "";
369
- /**
370
- * The generated TypeScript enum template output.
371
- */
372
- outputEnums = "";
373
- /**
374
- * The generated oeprations file.
375
- */
376
- outputOperations = "";
377
- /**
378
- * The generated context template file.
379
- */
380
- outputContext = "";
245
+ templates = /* @__PURE__ */ new Map();
246
+ async reset() {
247
+ this.files.clear();
248
+ this.generator.reset();
249
+ this.operationTimestamps.clear();
250
+ this.rpcItems.clear();
251
+ }
252
+ async updateSchema(schema) {
253
+ this.schema = schema;
254
+ this.generator.updateSchema(schema);
255
+ await this.reset();
256
+ await this.initDocuments();
257
+ }
381
258
  filePathToBuildRelative(filePath) {
382
- return "./" + relative(this.context.buildDir, filePath);
259
+ return "./" + this.helper.toBuildRelative(filePath);
383
260
  }
384
261
  filePathToSourceRelative(filePath) {
385
262
  return "./" + relative(process.cwd(), filePath);
@@ -392,16 +269,15 @@ class Collector {
392
269
  errors
393
270
  };
394
271
  }
395
- buildOutputTypes(file) {
396
- let output = "";
397
- const enumImports = file.getTypeScriptEnumDependencies();
398
- if (enumImports.length) {
399
- output += `import type { ${enumImports.join(", ")} } from './enums'
400
-
401
- `;
272
+ updateTemplate(template, content) {
273
+ this.templates.set(template, content);
274
+ }
275
+ getTemplate(template) {
276
+ const content = this.templates.get(template);
277
+ if (content === void 0) {
278
+ throw new Error(`Missing template content: ${template}`);
402
279
  }
403
- output += file.getSource();
404
- return output;
280
+ return content;
405
281
  }
406
282
  /**
407
283
  * Executes code gen and performs validation for operations.
@@ -410,12 +286,32 @@ class Collector {
410
286
  const output = this.generator.build();
411
287
  const operations = output.getCollectedOperations();
412
288
  const generatedCode = output.getGeneratedCode();
413
- this.outputOperations = output.getOperationsFile().getSource();
414
- this.outputEnums = output.buildFile(["enum"]).getSource();
415
- this.outputTypes = this.buildOutputTypes(output.getTypes());
416
- this.outputContext = generateContextTemplate(
417
- operations,
418
- this.context.serverApiPrefix
289
+ this.updateTemplate(
290
+ Template.Documents,
291
+ output.getOperationsFile({
292
+ exportName: "documents",
293
+ minify: !this.helper.isDev
294
+ }).getSource()
295
+ );
296
+ this.updateTemplate(
297
+ Template.OperationTypesAll,
298
+ output.getOperationTypesFile({
299
+ importFrom: "./../graphql-operations"
300
+ }).getSource()
301
+ );
302
+ this.updateTemplate(
303
+ Template.NitroTypes,
304
+ NitroTypes(operations, this.helper.options.serverApiPrefix)
305
+ );
306
+ this.updateTemplate(Template.OperationTypes, OperationTypes(output));
307
+ this.updateTemplate(
308
+ Template.ResponseTypes,
309
+ ResponseTypes(operations, this.helper)
310
+ );
311
+ this.updateTemplate(Template.Enums, output.buildFile(["enum"]).getSource());
312
+ this.updateTemplate(
313
+ Template.OperationSources,
314
+ OperationSources(operations, this.helper.paths.root)
419
315
  );
420
316
  const fragmentMap = /* @__PURE__ */ new Map();
421
317
  const operationSourceMap = /* @__PURE__ */ new Map();
@@ -445,7 +341,7 @@ class Collector {
445
341
  } else {
446
342
  this.operationTimestamps.set(operation.graphqlName, operation.timestamp);
447
343
  }
448
- const shouldLog = errors.length || !this.context.logOnlyErrors;
344
+ const shouldLog = errors.length || !this.helper.options.logOnlyErrors;
449
345
  if (shouldLog) {
450
346
  logEntries.push(this.operationToLogEntry(operation, errors));
451
347
  }
@@ -493,31 +389,45 @@ class Collector {
493
389
  logError(error) {
494
390
  let output = `${SYMBOL_CROSS}`;
495
391
  output += this.buildErrorMessage(error);
496
- logger.error(colors.red(output));
392
+ logger.error(color.red(output));
497
393
  }
498
394
  /**
499
- * Get all file paths that match the import patterns.
395
+ * Initialise the collector.
396
+ *
397
+ * In dev mode, the method will call itself recursively until all documents
398
+ * are valid.
399
+ *
400
+ * If not in dev mode the method will throw an error when documents are not
401
+ * valid.
500
402
  */
501
- async getImportPatternFiles() {
502
- if (this.context.patterns.length) {
503
- return resolveFiles(this.context.srcDir, this.context.patterns, {
504
- followSymbolicLinks: false
505
- });
403
+ async init() {
404
+ try {
405
+ await this.initDocuments();
406
+ } catch (e) {
407
+ if (this.helper.isDev) {
408
+ const shouldRevalidate = await this.helper.prompt.confirm(
409
+ "Do you want to revalidate the GraphQL documents?"
410
+ );
411
+ if (shouldRevalidate === "yes") {
412
+ await this.reset();
413
+ return this.init();
414
+ }
415
+ }
416
+ throw new Error("Graphql document validation failed.");
506
417
  }
507
- return [];
508
418
  }
509
419
  /**
510
420
  * Initialise the collector.
511
421
  */
512
- async init() {
422
+ async initDocuments() {
513
423
  try {
514
- const files = await this.getImportPatternFiles();
424
+ const files = await this.helper.getImportPatternFiles();
515
425
  for (const filePath of files) {
516
426
  await this.addFile(filePath);
517
427
  }
518
- const nuxtConfigDocuments = this.nuxtConfigDocuments.join("\n\n");
428
+ const nuxtConfigDocuments = this.helper.options.documents.join("\n\n");
519
429
  if (nuxtConfigDocuments.length) {
520
- const filePath = this.context.nuxtConfigPath;
430
+ const filePath = this.helper.paths.nuxtConfig;
521
431
  const file = new CollectedFile(filePath, nuxtConfigDocuments, false);
522
432
  this.files.set(filePath, file);
523
433
  this.generator.add({
@@ -537,6 +447,9 @@ class Collector {
537
447
  */
538
448
  async addFile(filePath) {
539
449
  const file = await CollectedFile.fromFilePath(filePath);
450
+ if (!file.fileContents) {
451
+ return null;
452
+ }
540
453
  this.files.set(filePath, file);
541
454
  this.generator.add({
542
455
  filePath,
@@ -545,26 +458,32 @@ class Collector {
545
458
  return file;
546
459
  }
547
460
  async handleAdd(filePath) {
548
- const matching = await this.getImportPatternFiles();
549
- if (!matching.includes(filePath)) {
461
+ if (!this.helper.matchesImportPattern(filePath)) {
550
462
  return false;
551
463
  }
552
- await this.addFile(filePath);
553
- return true;
464
+ const result = await this.addFile(filePath);
465
+ return !!result;
554
466
  }
555
467
  async handleChange(filePath) {
468
+ if (!this.helper.matchesImportPattern(filePath)) {
469
+ return false;
470
+ }
556
471
  const file = this.files.get(filePath);
557
472
  if (!file) {
558
- return false;
473
+ return this.handleAdd(filePath);
559
474
  }
560
- const needsUpdate = await file.update();
561
- if (!needsUpdate) {
562
- return false;
475
+ try {
476
+ const needsUpdate = await file.update();
477
+ if (!needsUpdate) {
478
+ return false;
479
+ }
480
+ this.generator.update({
481
+ filePath,
482
+ documentNode: file.parsed
483
+ });
484
+ } catch {
485
+ return this.handleUnlink(filePath);
563
486
  }
564
- this.generator.update({
565
- filePath,
566
- documentNode: file.parsed
567
- });
568
487
  return true;
569
488
  }
570
489
  handleUnlink(filePath) {
@@ -593,6 +512,7 @@ class Collector {
593
512
  */
594
513
  async handleWatchEvent(event, filePath) {
595
514
  let hasChanged = false;
515
+ const oldOperationTimestamps = new Map(this.operationTimestamps);
596
516
  try {
597
517
  if (event === "add") {
598
518
  hasChanged = await this.handleAdd(filePath);
@@ -602,7 +522,6 @@ class Collector {
602
522
  hasChanged = this.handleUnlink(filePath);
603
523
  } else if (event === "unlinkDir") {
604
524
  hasChanged = this.handleUnlinkDir(filePath);
605
- } else if (event === "addDir") {
606
525
  }
607
526
  if (hasChanged) {
608
527
  this.buildState();
@@ -613,392 +532,820 @@ class Collector {
613
532
  this.logError(e);
614
533
  return {
615
534
  hasChanged: false,
535
+ affectedOperations: [],
616
536
  error: { message: this.buildErrorMessage(e) }
617
537
  };
618
538
  }
539
+ const affectedOperations = [];
619
540
  if (hasChanged) {
620
541
  logger.success("Finished GraphQL code update successfully.");
542
+ for (const [name, newTimestamp] of this.operationTimestamps) {
543
+ const oldTimestamp = oldOperationTimestamps.get(name);
544
+ if (!oldTimestamp || oldTimestamp !== newTimestamp) {
545
+ affectedOperations.push(name);
546
+ }
547
+ }
548
+ }
549
+ return { hasChanged, affectedOperations };
550
+ }
551
+ /**
552
+ * Adds a virtual template (not written to disk) for both Nuxt and Nitro.
553
+ *
554
+ * For some reason a template written to disk works for both Nuxt and Nitro,
555
+ * but a virtual template requires adding two templates.
556
+ */
557
+ addVirtualTemplate(template) {
558
+ const getContents = () => this.getTemplate(template);
559
+ addTemplate({
560
+ filename: template,
561
+ getContents
562
+ });
563
+ addServerTemplate({
564
+ // Since this is a virtual template, the name must match the final
565
+ // alias, example:
566
+ // - nuxt-graphql-middleware/foobar.mjs => #nuxt-graphql-middleware/foobar
567
+ //
568
+ // That way we can reference the same template using the alias in both
569
+ // Nuxt and Nitro environments.
570
+ filename: "#" + template.replace(".mjs", ""),
571
+ getContents
572
+ });
573
+ }
574
+ /**
575
+ * Adds a template that dependes on Collector state.
576
+ */
577
+ addTemplate(template) {
578
+ if (template.endsWith(".d.ts")) {
579
+ addTypeTemplate(
580
+ {
581
+ filename: template,
582
+ write: true,
583
+ getContents: () => this.getTemplate(template)
584
+ },
585
+ {
586
+ nuxt: true,
587
+ nitro: true
588
+ }
589
+ );
590
+ } else {
591
+ addTemplate({
592
+ filename: template,
593
+ write: true,
594
+ getContents: () => this.getTemplate(template)
595
+ });
596
+ }
597
+ }
598
+ }
599
+
600
+ class SchemaProvider {
601
+ constructor(helper) {
602
+ this.helper = helper;
603
+ }
604
+ /**
605
+ * The raw schema content.
606
+ */
607
+ schemaContent = "";
608
+ /**
609
+ * The parsed schema object.
610
+ */
611
+ schema = null;
612
+ async init() {
613
+ try {
614
+ await this.loadSchema();
615
+ } catch (error) {
616
+ logger.error(error);
617
+ const hasLoaded = await this.loadFromDiskFallback();
618
+ if (!hasLoaded) {
619
+ throw new Error("Failed to load GraphQL schema.");
620
+ }
621
+ }
622
+ }
623
+ async loadFromDiskFallback() {
624
+ const hasSchemaOnDisk = await this.hasSchemaOnDisk();
625
+ if (this.helper.isDev && hasSchemaOnDisk && this.helper.options.downloadSchema) {
626
+ const shouldUseFromDisk = await this.helper.prompt.confirm(
627
+ "Do you want to continue with the previously downloaded schema from disk?"
628
+ );
629
+ if (shouldUseFromDisk === "yes") {
630
+ await this.loadSchema({ forceDisk: true });
631
+ return true;
632
+ }
621
633
  }
622
- return { hasChanged };
634
+ return false;
635
+ }
636
+ /**
637
+ * Loads the schema from disk.
638
+ *
639
+ * @returns The schema contents from disk.
640
+ */
641
+ async loadSchemaFromDisk() {
642
+ const fileExists = await this.hasSchemaOnDisk();
643
+ if (!fileExists) {
644
+ logger.error(
645
+ '"downloadSchema" is set to false but no schema exists at ' + this.helper.paths.schema
646
+ );
647
+ throw new Error("Missing GraphQL schema.");
648
+ }
649
+ logger.info(`Loading GraphQL schema from disk: ${this.helper.paths.schema}`);
650
+ return await fs.readFile(this.helper.paths.schema).then((v) => v.toString());
623
651
  }
624
652
  /**
625
- * Get the TypeScript types template contents.
653
+ * Downloads the schema and saves it to disk.
654
+ *
655
+ * @returns The schema contents.
626
656
  */
627
- getTemplateTypes() {
628
- return this.outputTypes;
657
+ downloadSchema() {
658
+ const endpoint = this.helper.options.graphqlEndpoint;
659
+ if (!endpoint) {
660
+ throw new Error("Missing graphqlEndpoint config.");
661
+ }
662
+ const pluginConfig = this.helper.options.codegenSchemaConfig?.urlSchemaOptions;
663
+ const schemaAstConfig = this.helper.options.codegenSchemaConfig?.schemaAstConfig || {
664
+ sort: true
665
+ };
666
+ const config = {
667
+ schema: endpoint,
668
+ pluginLoader: (name) => {
669
+ switch (name) {
670
+ case "@graphql-codegen/schema-ast":
671
+ return Promise.resolve(PluginSchemaAst);
672
+ }
673
+ throw new Error(`graphql-codegen plugin not found: ${name}`);
674
+ },
675
+ silent: true,
676
+ errorsOnly: true,
677
+ config: pluginConfig,
678
+ generates: {
679
+ [this.helper.paths.schema]: {
680
+ plugins: ["schema-ast"],
681
+ config: schemaAstConfig
682
+ }
683
+ }
684
+ };
685
+ logger.info(`Downloading GraphQL schema from "${endpoint}".`);
686
+ return generate(config, true).then((v) => v[0]?.content);
629
687
  }
630
688
  /**
631
- * Get the TypeScript Enums template contents.
689
+ * Determine if the schema exists on disk.
690
+ *
691
+ * @returns True if the schema file exists on disk.
632
692
  */
633
- getTemplateEnums() {
634
- return this.outputEnums;
693
+ hasSchemaOnDisk() {
694
+ return fs.access(this.helper.paths.schema).then(() => true).catch(() => false);
635
695
  }
636
696
  /**
637
- * Get the context template contents.
697
+ * Load the schema either from disk or by downloading it.
698
+ *
699
+ * @param forceDownload - Forces downloading the schema.
638
700
  */
639
- getTemplateContext() {
640
- return this.outputContext;
701
+ async loadSchema(opts) {
702
+ if (opts?.forceDisk) {
703
+ this.schemaContent = await this.loadSchemaFromDisk();
704
+ } else if (this.helper.options.downloadSchema || opts?.forceDownload) {
705
+ this.schemaContent = await this.downloadSchema();
706
+ } else {
707
+ this.schemaContent = await this.loadSchemaFromDisk();
708
+ }
709
+ this.schema = await loadSchema(this.schemaContent, {
710
+ loaders: []
711
+ });
641
712
  }
642
713
  /**
643
- * Get the operations template contents.
714
+ * Get the schema.
715
+ *
716
+ * @returns The parsed GraphQL schema object.
644
717
  */
645
- getTemplateOperations() {
646
- return this.outputOperations;
718
+ getSchema() {
719
+ if (!this.schema) {
720
+ throw new Error("Failed to load schema.");
721
+ }
722
+ return this.schema;
647
723
  }
648
724
  }
649
725
 
650
- function useViteWebSocket(nuxt) {
651
- return new Promise((resolve) => {
652
- nuxt.hooks.hook("vite:serverCreated", (viteServer) => {
653
- resolve(viteServer.ws);
726
+ const unicode = isUnicodeSupported();
727
+ const s = (c, fallback) => unicode ? c : fallback;
728
+ const S_BAR = s("\u2502", "|");
729
+ const S_STEP_ACTIVE = s("\u25C6", "*");
730
+ const S_STEP_CANCEL = s("\u25A0", "x");
731
+ const S_STEP_ERROR = s("\u25B2", "x");
732
+ const S_STEP_SUBMIT = s("\u25C7", "o");
733
+ const S_RADIO_ACTIVE = s("\u25CF", ">");
734
+ const S_RADIO_INACTIVE = s("\u25CB", " ");
735
+ const S_BAR_END = s("\u2514", "\u2014");
736
+ const symbol = (state) => {
737
+ switch (state) {
738
+ case "initial":
739
+ case "active":
740
+ return color.cyan(S_STEP_ACTIVE);
741
+ case "cancel":
742
+ return color.red(S_STEP_CANCEL);
743
+ case "error":
744
+ return color.yellow(S_STEP_ERROR);
745
+ case "submit":
746
+ return color.green(S_STEP_SUBMIT);
747
+ }
748
+ };
749
+ class ConsolePrompt {
750
+ abortController = null;
751
+ confirm(message) {
752
+ this.abort();
753
+ this.abortController = new AbortController();
754
+ const active = "Yes";
755
+ const inactive = "No";
756
+ return new ConfirmPrompt({
757
+ active,
758
+ inactive,
759
+ initialValue: true,
760
+ signal: this.abortController.signal,
761
+ render() {
762
+ const title = `${color.gray(S_BAR)}
763
+ ${symbol(this.state)} ${message}
764
+ `;
765
+ const value = this.value ? active : inactive;
766
+ switch (this.state) {
767
+ case "submit":
768
+ return `${title}${color.gray(S_BAR)} ${color.dim(value)}`;
769
+ case "cancel":
770
+ return `${title}${color.gray(S_BAR)} ${color.strikethrough(
771
+ color.dim(value)
772
+ )}
773
+ ${color.gray(S_BAR)}`;
774
+ default: {
775
+ return `${title}${color.cyan(S_BAR)} ${this.value ? `${color.green(S_RADIO_ACTIVE)} ${active}` : `${color.dim(S_RADIO_INACTIVE)} ${color.dim(active)}`} ${color.dim("/")} ${!this.value ? `${color.green(S_RADIO_ACTIVE)} ${inactive}` : `${color.dim(S_RADIO_INACTIVE)} ${color.dim(inactive)}`}
776
+ ${color.cyan(S_BAR_END)}
777
+ `;
778
+ }
779
+ }
780
+ }
781
+ }).prompt().then((v) => {
782
+ const result = v;
783
+ if (result === true) {
784
+ return "yes";
785
+ } else if (result === false) {
786
+ return "no";
787
+ }
788
+ return "cancel";
654
789
  });
655
- });
656
- }
657
- const RPC_NAMESPACE = "nuxt-graphql-middleware";
658
- const module = defineNuxtModule({
659
- meta: {
660
- name,
661
- configKey: "graphqlMiddleware",
662
- version,
663
- compatibility: {
664
- nuxt: ">=3.13.0"
665
- }
666
- },
667
- defaults: defaultOptions,
668
- async setup(passedOptions, nuxt) {
669
- const options = defu({}, passedOptions, defaultOptions);
670
- function addAlias(name2, arg) {
671
- const aliasPath = typeof arg === "string" ? arg : arg.dst;
672
- nuxt.options.alias[name2] = aliasPath;
790
+ }
791
+ abort() {
792
+ if (this.abortController) {
793
+ this.abortController.abort();
794
+ this.abortController = null;
673
795
  }
796
+ }
797
+ }
798
+
799
+ class ModuleHelper {
800
+ constructor(nuxt, moduleUrl, options) {
801
+ this.nuxt = nuxt;
674
802
  const isModuleBuild = process.env.MODULE_BUILD === "true" && nuxt.options._prepare;
803
+ const mergedOptions = defu({}, options, defaultOptions);
804
+ if (!mergedOptions.autoImportPatterns) {
805
+ mergedOptions.autoImportPatterns = [
806
+ "~~/**/*.{gql,graphql}",
807
+ "!node_modules"
808
+ ];
809
+ }
675
810
  if (isModuleBuild) {
676
- options.graphqlEndpoint = "http://localhost";
677
- options.downloadSchema = false;
678
- options.schemaPath = "~~/schema.graphql";
679
- options.autoImportPatterns = [
811
+ mergedOptions.graphqlEndpoint = "http://localhost";
812
+ mergedOptions.downloadSchema = false;
813
+ mergedOptions.schemaPath = "~~/schema.graphql";
814
+ mergedOptions.autoImportPatterns = [
680
815
  "~~/playground/**/*.{gql,graphql}",
681
816
  "!node_modules"
682
817
  ];
683
818
  }
684
- if (!passedOptions.autoImportPatterns) {
685
- options.autoImportPatterns = ["~~/**/*.{gql,graphql}", "!node_modules"];
686
- }
687
- options.autoImportPatterns = (options.autoImportPatterns || []).map(
688
- (pattern) => {
689
- return resolveAlias(pattern);
690
- }
691
- );
692
- if (!nuxt.options._prepare) {
693
- validateOptions(options);
694
- }
695
- const moduleResolver = createResolver(import.meta.url);
696
- const serverResolver = createResolver(nuxt.options.serverDir);
697
- const srcResolver = createResolver(nuxt.options.srcDir);
698
- const appResolver = createResolver(nuxt.options.dir.app);
699
- const rootDir = nuxt.options.rootDir;
700
- const rootResolver = createResolver(rootDir);
701
- const { schemaPath, schemaContent } = await getSchemaPath(
702
- resolveAlias(options.schemaPath),
703
- options,
704
- rootResolver.resolve,
705
- options.downloadSchema
706
- );
707
- const schema = await loadSchema(schemaContent, {
708
- loaders: []
819
+ mergedOptions.autoImportPatterns = (mergedOptions.autoImportPatterns || []).map((pattern) => {
820
+ return resolveAlias(pattern);
709
821
  });
710
- const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url));
711
- nuxt.options.build.transpile.push(runtimeDir);
712
- const collector = new Collector(
713
- schema,
714
- {
715
- patterns: options.autoImportPatterns || [],
716
- srcDir: nuxt.options.srcDir,
717
- buildDir: srcResolver.resolve(nuxt.options.buildDir),
718
- nuxtConfigPath: rootResolver.resolve("nuxt.config.ts"),
719
- schemaPath,
720
- serverApiPrefix: options.serverApiPrefix,
721
- logOnlyErrors: !!options.logOnlyErrors
722
- },
723
- options.documents,
724
- options.codegenConfig
725
- );
726
- await collector.init();
727
- const isDevToolsEnabled = nuxt.options.dev && options.devtools;
728
- let rpc;
729
- if (isDevToolsEnabled) {
730
- const clientPath = moduleResolver.resolve("./client");
731
- setupDevToolsUI(nuxt, clientPath);
732
- onDevToolsInitialized(() => {
733
- rpc = extendServerRpc(RPC_NAMESPACE, {
734
- // register server RPC functions
735
- getModuleOptions() {
736
- return options;
737
- },
738
- getDocuments() {
739
- return [...collector.rpcItems.values()];
740
- }
741
- });
742
- });
822
+ this.options = mergedOptions;
823
+ if (!nuxt.options._prepare) {
824
+ validateOptions(this.options);
743
825
  }
744
- nuxt.options.runtimeConfig.public["nuxt-graphql-middleware"] = {
745
- serverApiPrefix: options.serverApiPrefix
746
- };
747
- nuxt.options.appConfig.graphqlMiddleware = {
748
- clientCacheEnabled: !!options.clientCache?.enabled,
749
- clientCacheMaxSize: options.clientCache?.maxSize || 100
826
+ this.isDev = nuxt.options.dev;
827
+ this.resolvers = {
828
+ module: createResolver(moduleUrl),
829
+ server: createResolver(nuxt.options.serverDir),
830
+ src: createResolver(nuxt.options.srcDir),
831
+ app: createResolver(nuxt.options.dir.app),
832
+ root: createResolver(nuxt.options.rootDir)
750
833
  };
751
- nuxt.options.runtimeConfig.graphqlMiddleware = {
752
- graphqlEndpoint: options.graphqlEndpoint || ""
834
+ this.paths = {
835
+ runtimeTypes: "",
836
+ root: nuxt.options.rootDir,
837
+ nuxtConfig: this.resolvers.root.resolve("nuxt.config.ts"),
838
+ serverDir: nuxt.options.serverDir,
839
+ schema: this.resolvers.root.resolve(
840
+ resolveAlias(this.options.schemaPath)
841
+ ),
842
+ serverOptions: this.findServerOptions(),
843
+ clientOptions: this.findClientOptions(),
844
+ moduleBuildDir: nuxt.options.buildDir + "/nuxt-graphql-middleware",
845
+ moduleTypesDir: nuxt.options.buildDir + "/graphql-operations"
753
846
  };
754
- if (options.includeComposables) {
755
- const nuxtComposables = [
756
- "useGraphqlQuery",
757
- "useGraphqlMutation",
758
- "useGraphqlState",
759
- "useAsyncGraphqlQuery"
760
- ];
761
- if (options.enableFileUploads) {
762
- nuxtComposables.push("useGraphqlUploadMutation");
847
+ this.paths.runtimeTypes = this.toModuleBuildRelative(
848
+ this.resolvers.module.resolve("./runtime/types.ts")
849
+ );
850
+ }
851
+ resolvers;
852
+ paths;
853
+ isDev;
854
+ options;
855
+ prompt = new ConsolePrompt();
856
+ /**
857
+ * Find the path to the graphqlMiddleware.serverOptions.ts file.
858
+ */
859
+ findServerOptions() {
860
+ const newPath = this.resolvers.server.resolve(
861
+ "graphqlMiddleware.serverOptions"
862
+ );
863
+ const serverPath = fileExists(newPath);
864
+ if (serverPath) {
865
+ return serverPath;
866
+ }
867
+ const candidates = [
868
+ this.resolvers.root.resolve("graphqlMiddleware.serverOptions"),
869
+ this.resolvers.root.resolve("app/graphqlMiddleware.serverOptions"),
870
+ this.resolvers.src.resolve("graphqlMiddleware.serverOptions")
871
+ ];
872
+ for (let i = 0; i < candidates.length; i++) {
873
+ const path = candidates[i];
874
+ const filePath = fileExists(path);
875
+ if (filePath) {
876
+ throw new Error(
877
+ `The graphqlMiddleware.serverOptions file should be placed in Nuxt's <serverDir> ("${this.paths.serverDir}/graphqlMiddleware.serverOptions.ts").`
878
+ );
763
879
  }
764
- nuxtComposables.forEach((name2) => {
765
- addImports({
766
- from: moduleResolver.resolve("./runtime/composables/" + name2),
767
- name: name2
768
- });
769
- });
770
- const serverUtils = ["useGraphqlQuery", "useGraphqlMutation"].map(
771
- (name2) => {
772
- return {
773
- from: moduleResolver.resolve("./runtime/server/utils/" + name2),
774
- name: name2
775
- };
776
- }
777
- );
778
- addServerImports(serverUtils);
779
880
  }
780
- addAlias(
781
- "#graphql-operations",
782
- addTemplate({
783
- filename: GraphqlMiddlewareTemplate.OperationTypes,
784
- write: true,
785
- getContents: () => collector.getTemplateTypes()
786
- })
881
+ logger.info("No graphqlMiddleware.serverOptions file found.");
882
+ return null;
883
+ }
884
+ findClientOptions() {
885
+ const clientOptionsPath = this.resolvers.app.resolve(
886
+ "graphqlMiddleware.clientOptions"
887
+ );
888
+ if (fileExists(clientOptionsPath)) {
889
+ return clientOptionsPath;
890
+ }
891
+ return null;
892
+ }
893
+ /**
894
+ * Transform the path relative to the module's build directory.
895
+ *
896
+ * @param path - The absolute path.
897
+ *
898
+ * @returns The path relative to the module's build directory.
899
+ */
900
+ toModuleBuildRelative(path) {
901
+ return relative(this.paths.moduleBuildDir, path);
902
+ }
903
+ /**
904
+ * Transform the path relative to the Nuxt build directory.
905
+ *
906
+ * @param path - The absolute path.
907
+ *
908
+ * @returns The path relative to the module's build directory.
909
+ */
910
+ toBuildRelative(path) {
911
+ return relative(this.nuxt.options.buildDir, path);
912
+ }
913
+ /**
914
+ * Get all file paths that match the import patterns.
915
+ */
916
+ async getImportPatternFiles() {
917
+ return resolveFiles(
918
+ this.nuxt.options.srcDir,
919
+ this.options.autoImportPatterns,
920
+ {
921
+ followSymbolicLinks: false
922
+ }
787
923
  );
788
- addAlias(
789
- "#graphql-operations/enums",
924
+ }
925
+ matchesImportPattern(filePath) {
926
+ return micromatch.isMatch(filePath, this.options.autoImportPatterns);
927
+ }
928
+ addAlias(name, path) {
929
+ this.nuxt.options.alias[name] = path;
930
+ const pathFromName = `./${name.substring(1)}`;
931
+ this.nuxt.options.nitro.typescript ||= {};
932
+ this.nuxt.options.nitro.typescript.tsConfig ||= {};
933
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions ||= {};
934
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths ||= {};
935
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths[name] = [
936
+ pathFromName
937
+ ];
938
+ this.nuxt.options.nitro.typescript.tsConfig.compilerOptions.paths[name + "/*"] = [pathFromName + "/*"];
939
+ }
940
+ inlineNitroExternals(arg) {
941
+ const path = typeof arg === "string" ? arg : arg.dst;
942
+ this.nuxt.options.nitro.externals = this.nuxt.options.nitro.externals || {};
943
+ this.nuxt.options.nitro.externals.inline = this.nuxt.options.nitro.externals.inline || [];
944
+ this.nuxt.options.nitro.externals.inline.push(path);
945
+ }
946
+ addTemplate(template, cb) {
947
+ const content = cb(this);
948
+ if (template.endsWith("d.ts")) {
949
+ addTypeTemplate({
950
+ filename: template,
951
+ write: true,
952
+ getContents: () => content
953
+ });
954
+ } else {
790
955
  addTemplate({
791
- filename: GraphqlMiddlewareTemplate.Enums,
956
+ filename: template,
792
957
  write: true,
793
- getContents: () => collector.getTemplateEnums()
794
- })
795
- );
796
- const templateDocuments = addTemplate({
797
- filename: GraphqlMiddlewareTemplate.Documents,
798
- write: true,
799
- getContents: () => collector.getTemplateOperations()
958
+ getContents: () => content
959
+ });
960
+ }
961
+ }
962
+ addPlugin(path) {
963
+ addPlugin(this.resolvers.module.resolve(path), {
964
+ append: false
800
965
  });
801
- addAlias("#graphql-documents", templateDocuments.dst);
802
- const templateContext = addTemplate({
803
- filename: GraphqlMiddlewareTemplate.ComposableContext,
804
- write: true,
805
- getContents: () => collector.getTemplateContext()
966
+ }
967
+ addServerHandler(name, path, method) {
968
+ addServerHandler({
969
+ handler: this.resolvers.module.resolve("./runtime/server/api/" + name),
970
+ route: this.options.serverApiPrefix + path,
971
+ method
806
972
  });
807
- addAlias("#nuxt-graphql-middleware/generated-types", templateContext.dst);
808
- addTemplate({
809
- write: true,
810
- filename: "nuxt-graphql-middleware/graphql-documents.d.ts",
811
- getContents: () => {
812
- return `
813
- import type {
814
- GraphqlMiddlewareQuery,
815
- GraphqlMiddlewareMutation,
816
- } from '#nuxt-graphql-middleware/generated-types'
973
+ }
974
+ addComposable(name) {
975
+ addImports({
976
+ from: this.resolvers.module.resolve("./runtime/composables/" + name),
977
+ name
978
+ });
979
+ }
980
+ addServerUtil(name) {
981
+ addServerImports([
982
+ {
983
+ from: this.resolvers.module.resolve("./runtime/server/utils/" + name),
984
+ name
985
+ }
986
+ ]);
987
+ }
988
+ }
817
989
 
818
- declare module '#graphql-documents' {
819
- type Operations = {
820
- query: GraphqlMiddlewareQuery
821
- mutation: GraphqlMiddlewareMutation
990
+ function GraphqlConfig(helper) {
991
+ const patterns = helper.options.autoImportPatterns || [];
992
+ const configPath = helper.resolvers.root.resolve(
993
+ (helper.options.graphqlConfigFilePath || "").replace(
994
+ "/graphql.config.ts",
995
+ ""
996
+ )
997
+ );
998
+ const schemaPath = "./" + relative(configPath, helper.paths.schema);
999
+ const documents = patterns.filter((v) => !v.includes("!")).map((pattern) => {
1000
+ return "./" + relative(configPath, helper.resolvers.root.resolve(pattern));
1001
+ });
1002
+ return `
1003
+ import type { IGraphQLConfig } from 'graphql-config'
1004
+
1005
+ const schema = ${JSON.stringify(schemaPath)}
1006
+
1007
+ const documents: string[] = ${JSON.stringify(documents, null, 2)};
1008
+
1009
+ const config: IGraphQLConfig = {
1010
+ schema,
1011
+ documents,
1012
+ }
1013
+
1014
+ export default config
1015
+ `;
1016
+ }
1017
+
1018
+ function DocumentTypes() {
1019
+ return `
1020
+ import type { Query, Mutation } from './operations'
1021
+
1022
+ declare module '#nuxt-graphql-middleware/documents' {
1023
+ export type Documents = {
1024
+ query: Record<keyof Query, string>
1025
+ mutation: Record<keyof Mutation, string>
822
1026
  }
823
- const operations: Operations
824
- export { operations, Operations }
1027
+ export const documents: Documents
1028
+ }`;
1029
+ }
1030
+
1031
+ function Types() {
1032
+ return `declare module '#nuxt-graphql-middleware/sources' {
1033
+ export const operationSources: Record<string, string>
1034
+ }`;
1035
+ }
1036
+
1037
+ function HelpersTypes() {
1038
+ return `export const serverApiPrefix: string;
1039
+ export function getEndpoint(operation: string, operationName: string): string`;
1040
+ }
1041
+
1042
+ function Helpers(helper) {
1043
+ return `export const serverApiPrefix = '${helper.options.serverApiPrefix}'
1044
+ export function getEndpoint(operation, operationName) {
1045
+ return '${helper.options.serverApiPrefix}' + '/' + operation + '/' + operationName
825
1046
  }
826
1047
  `;
827
- }
828
- });
829
- const findServerOptions = () => {
830
- const newPath = serverResolver.resolve("graphqlMiddleware.serverOptions");
831
- const serverPath = fileExists(newPath);
832
- if (serverPath) {
833
- return serverPath;
834
- }
835
- const candidates = [
836
- rootResolver.resolve("graphqlMiddleware.serverOptions"),
837
- rootResolver.resolve("app/graphqlMiddleware.serverOptions"),
838
- srcResolver.resolve("graphqlMiddleware.serverOptions")
839
- ];
840
- for (let i = 0; i < candidates.length; i++) {
841
- const path = candidates[i];
842
- const filePath = fileExists(path);
843
- if (filePath) {
844
- logger.warn(
845
- `The graphqlMiddleware.serverOptions file should be placed in Nuxt's <serverDir> ("${nuxt.options.serverDir}/graphqlMiddleware.serverOptions.ts"). The new path will be enforced in the next major release.`
846
- );
847
- return filePath;
848
- }
849
- }
850
- logger.info("No graphqlMiddleware.serverOptions file found.");
851
- };
852
- const resolvedServerOptionsPath = findServerOptions();
853
- const moduleTypesPath = relative(
854
- nuxt.options.buildDir,
855
- moduleResolver.resolve("./types")
856
- );
857
- const resolvedPathRelative = resolvedServerOptionsPath ? relative(nuxt.options.buildDir, resolvedServerOptionsPath) : null;
858
- const template = addTemplate({
859
- filename: "graphqlMiddleware.serverOptions.mjs",
860
- write: true,
861
- getContents: () => {
862
- const serverOptionsLine = resolvedPathRelative ? `import serverOptions from '${resolvedPathRelative}'` : `const serverOptions = {}`;
863
- return `
1048
+ }
1049
+
1050
+ function ServerOptions(helper) {
1051
+ const resolvedPathRelative = helper.paths.serverOptions ? helper.toModuleBuildRelative(helper.paths.serverOptions) : null;
1052
+ const serverOptionsLine = resolvedPathRelative ? `import serverOptions from '${resolvedPathRelative}'` : `const serverOptions = {}`;
1053
+ return `
864
1054
  ${serverOptionsLine}
865
1055
  export { serverOptions }
866
1056
  `;
867
- }
868
- });
869
- addTemplate({
870
- filename: "graphqlMiddleware.serverOptions.d.ts",
871
- write: true,
872
- getContents: () => {
873
- const serverOptionsLineTypes = resolvedPathRelative ? `import serverOptions from '${resolvedPathRelative}'` : `const serverOptions: GraphqlMiddlewareServerOptions = {}`;
874
- return `
1057
+ }
1058
+
1059
+ function ServerOptionsTypes(helper) {
1060
+ const resolvedPathRelative = helper.paths.serverOptions ? helper.toModuleBuildRelative(helper.paths.serverOptions) : null;
1061
+ const serverOptionsLineTypes = resolvedPathRelative ? `import serverOptions from '${resolvedPathRelative}'` : `const serverOptions: GraphqlMiddlewareServerOptions = {}`;
1062
+ const moduleTypesPath = helper.toModuleBuildRelative(
1063
+ helper.resolvers.module.resolve("./types")
1064
+ );
1065
+ return `
875
1066
  import type { GraphqlMiddlewareServerOptions } from '${moduleTypesPath}'
876
1067
  ${serverOptionsLineTypes}
877
- import type { GraphqlServerResponse } from '${runtimeTypesPath}'
878
- import type { GraphqlMiddlewareResponseUnion } from '#nuxt-graphql-middleware/generated-types'
879
1068
 
880
- type GraphqlResponseAdditions =
1069
+ export type GraphqlResponseAdditions =
881
1070
  typeof serverOptions extends GraphqlMiddlewareServerOptions<infer R, any, any> ? R : {}
882
1071
 
883
- export type GraphqlResponse<T> = GraphqlServerResponse<T> & GraphqlResponseAdditions
884
-
885
- export type GraphqlResponseTyped = GraphqlResponse<GraphqlMiddlewareResponseUnion>
1072
+ export { serverOptions }`;
1073
+ }
886
1074
 
887
- export { serverOptions }
1075
+ function ClientOptions(helper) {
1076
+ if (helper.paths.clientOptions) {
1077
+ const pathRelative = helper.toModuleBuildRelative(
1078
+ helper.paths.clientOptions
1079
+ );
1080
+ return `import clientOptions from '${pathRelative}'
1081
+ export { clientOptions }
888
1082
  `;
889
- }
890
- });
891
- const getClientOptionsImport = () => {
892
- const clientOptionsPath = appResolver.resolve(
893
- "graphqlMiddleware.clientOptions"
894
- );
895
- if (fileExists(clientOptionsPath)) {
896
- const pathRelative = relative(nuxt.options.buildDir, clientOptionsPath);
897
- return `import clientOptions from '${pathRelative}'`;
898
- }
899
- };
900
- const clientOptionsImport = getClientOptionsImport();
901
- const clientOptionsTemplate = addTemplate({
902
- filename: "graphqlMiddleware.clientOptions.mjs",
903
- write: true,
904
- getContents: () => {
905
- if (clientOptionsImport) {
906
- return `${clientOptionsImport}
907
- export { clientOptions }`;
908
- }
909
- return `export const clientOptions = {}`;
910
- }
911
- });
912
- const runtimeTypesPath = relative(
913
- nuxt.options.buildDir,
914
- moduleResolver.resolve("./runtime/types.ts")
1083
+ }
1084
+ return `export const clientOptions = {}`;
1085
+ }
1086
+
1087
+ function ClientOptionsTypes(helper) {
1088
+ if (helper.paths.clientOptions) {
1089
+ const pathRelative = helper.toModuleBuildRelative(
1090
+ helper.paths.clientOptions
915
1091
  );
916
- addTemplate({
917
- filename: "graphqlMiddleware.clientOptions.d.ts",
918
- write: true,
919
- getContents: () => {
920
- if (clientOptionsImport) {
921
- return `import type { GraphqlClientOptions } from '${runtimeTypesPath}'
922
- ${clientOptionsImport}
1092
+ return `import type { GraphqlClientOptions } from '${helper.paths.runtimeTypes}'
1093
+ import { clientOptions } from '${pathRelative}'
923
1094
 
924
1095
  export type GraphqlClientContext = typeof clientOptions extends GraphqlClientOptions<infer R> ? R : {}
925
1096
 
926
1097
  export { clientOptions }`;
927
- }
928
- return `import type { GraphqlClientOptions } from '${runtimeTypesPath}'
1098
+ }
1099
+ return `
1100
+ import type { GraphqlClientOptions } from '${helper.paths.runtimeTypes}'
929
1101
  export const clientOptions: GraphqlClientOptions
930
1102
 
931
1103
  export type GraphqlClientContext = {}
932
1104
  `;
933
- }
934
- });
935
- addAlias("#graphql-middleware-client-options", clientOptionsTemplate.dst);
936
- nuxt.options.nitro.externals = nuxt.options.nitro.externals || {};
937
- nuxt.options.nitro.externals.inline = nuxt.options.nitro.externals.inline || [];
938
- nuxt.options.nitro.externals.inline.push(template.dst);
939
- nuxt.options.nitro.externals.inline.push(templateDocuments.dst);
940
- addAlias("#graphql-middleware-server-options-build", template.dst);
941
- addAlias(
942
- "#graphql-middleware/types",
943
- moduleResolver.resolve("./runtime/types.ts")
944
- );
945
- addServerHandler({
946
- handler: moduleResolver.resolve("./runtime/serverHandler/index"),
947
- route: options.serverApiPrefix + "/:operation/:name"
1105
+ }
1106
+
1107
+ const DEVTOOLS_UI_ROUTE = "/__nuxt-graphql-middleware";
1108
+ const DEVTOOLS_UI_LOCAL_PORT = 3300;
1109
+ function setupDevToolsUI(nuxt, clientPath) {
1110
+ const isProductionBuild = existsSync$1(clientPath);
1111
+ if (isProductionBuild) {
1112
+ nuxt.hook("vite:serverCreated", async (server) => {
1113
+ const sirv = await import('sirv').then((r) => r.default || r);
1114
+ server.middlewares.use(
1115
+ DEVTOOLS_UI_ROUTE,
1116
+ sirv(clientPath, { dev: true, single: true })
1117
+ );
948
1118
  });
949
- if (options.enableFileUploads) {
950
- addServerHandler({
951
- handler: moduleResolver.resolve("./runtime/serverHandler/upload"),
952
- route: options.serverApiPrefix + "/upload/:name"
953
- });
954
- }
955
- addPlugin(moduleResolver.resolve("./runtime/plugins/provideState"), {
956
- append: false
1119
+ } else {
1120
+ nuxt.hook("vite:extendConfig", (config) => {
1121
+ config.server = config.server || {};
1122
+ config.server.proxy = config.server.proxy || {};
1123
+ config.server.proxy[DEVTOOLS_UI_ROUTE] = {
1124
+ target: "http://localhost:" + DEVTOOLS_UI_LOCAL_PORT + DEVTOOLS_UI_ROUTE,
1125
+ changeOrigin: true,
1126
+ followRedirects: true,
1127
+ rewrite: (path) => path.replace(DEVTOOLS_UI_ROUTE, "")
1128
+ };
957
1129
  });
958
- nuxt.hook("nitro:config", (nitroConfig) => {
959
- nitroConfig.externals = defu(
960
- typeof nitroConfig.externals === "object" ? nitroConfig.externals : {},
961
- {
962
- inline: [moduleResolver.resolve("./runtime")]
963
- }
964
- );
1130
+ }
1131
+ nuxt.hook("devtools:customTabs", (tabs) => {
1132
+ tabs.push({
1133
+ // unique identifier
1134
+ name: "nuxt-graphql-middleware",
1135
+ // title to display in the tab
1136
+ title: "GraphQL Middleware",
1137
+ // any icon from Iconify, or a URL to an image
1138
+ icon: "akar-icons:graphql-fill",
1139
+ // iframe view
1140
+ view: {
1141
+ type: "iframe",
1142
+ src: DEVTOOLS_UI_ROUTE
1143
+ }
965
1144
  });
966
- if (nuxt.options.dev || nuxt.options._prepare) {
967
- let sendError = function(error) {
968
- wsPromise.then((ws) => {
969
- ws.send({
970
- type: "error",
971
- err: {
972
- message: error.message,
973
- stack: ""
1145
+ });
1146
+ }
1147
+
1148
+ const RPC_NAMESPACE = "nuxt-graphql-middleware";
1149
+ class DevModeHandler {
1150
+ constructor(nuxt, schemaProvider, collector, helper) {
1151
+ this.nuxt = nuxt;
1152
+ this.schemaProvider = schemaProvider;
1153
+ this.collector = collector;
1154
+ this.helper = helper;
1155
+ }
1156
+ devToolsRpc = null;
1157
+ nitro = null;
1158
+ viteWebSocket = null;
1159
+ operationsToReload = /* @__PURE__ */ new Set();
1160
+ init() {
1161
+ this.nuxt.hooks.hookOnce("ready", this.onReady.bind(this));
1162
+ this.nuxt.hooks.hookOnce(
1163
+ "vite:serverCreated",
1164
+ this.onViteServerCreated.bind(this)
1165
+ );
1166
+ this.nuxt.hook("builder:watch", this.onBuilderWatch.bind(this));
1167
+ if (this.helper.options.devtools) {
1168
+ const clientPath = this.helper.resolvers.module.resolve("./client");
1169
+ setupDevToolsUI(this.nuxt, clientPath);
1170
+ onDevToolsInitialized(() => {
1171
+ this.devToolsRpc = extendServerRpc(
1172
+ RPC_NAMESPACE,
1173
+ {
1174
+ // register server RPC functions
1175
+ getModuleOptions: () => {
1176
+ return this.helper.options;
1177
+ },
1178
+ getDocuments: () => {
1179
+ return [...this.collector.rpcItems.values()];
974
1180
  }
975
- });
976
- });
977
- };
978
- addServerHandler({
979
- handler: moduleResolver.resolve("./runtime/serverHandler/debug"),
980
- route: options.serverApiPrefix + "/debug"
1181
+ }
1182
+ );
981
1183
  });
982
- const wsPromise = useViteWebSocket(nuxt);
983
- nuxt.hook("builder:watch", async (event, pathAbsolute) => {
984
- if (pathAbsolute === schemaPath) {
985
- return;
986
- }
987
- if (!pathAbsolute.match(/\.(gql|graphql)$/)) {
1184
+ }
1185
+ }
1186
+ onReady() {
1187
+ this.nitro = useNitro();
1188
+ this.nitro.hooks.hook("compiled", this.onNitroCompiled.bind(this));
1189
+ }
1190
+ async onBuilderWatch(event, pathAbsolute) {
1191
+ if (pathAbsolute === this.helper.paths.schema) {
1192
+ return;
1193
+ }
1194
+ if (!pathAbsolute.match(/\.(gql|graphql)$/)) {
1195
+ return;
1196
+ }
1197
+ this.helper.prompt.abort();
1198
+ const { hasChanged, affectedOperations, error } = await this.collector.handleWatchEvent(event, pathAbsolute);
1199
+ if (error) {
1200
+ this.sendError(error);
1201
+ await this.helper.prompt.confirm("Do you want to download and update the GraphQL schema?").then(async (shouldReload) => {
1202
+ if (shouldReload !== "yes") {
988
1203
  return;
989
1204
  }
990
- const { hasChanged, error } = await collector.handleWatchEvent(
991
- event,
992
- pathAbsolute
993
- );
994
- if (error) {
995
- sendError(error);
996
- }
997
- if (hasChanged && rpc) {
998
- rpc.broadcast.documentsUpdated([...collector.rpcItems.values()]);
1205
+ try {
1206
+ await this.schemaProvider.loadSchema({ forceDownload: true });
1207
+ await this.collector.updateSchema(this.schemaProvider.getSchema());
1208
+ } catch (e) {
1209
+ logger.error(e);
999
1210
  }
1000
1211
  });
1212
+ return;
1213
+ }
1214
+ if (!hasChanged) {
1215
+ return;
1216
+ }
1217
+ if (this.nitro) {
1218
+ await this.nitro.hooks.callHook("rollup:reload");
1219
+ }
1220
+ if (affectedOperations.length) {
1221
+ affectedOperations.forEach(
1222
+ (operation) => this.operationsToReload.add(operation)
1223
+ );
1224
+ }
1225
+ if (this.devToolsRpc) {
1226
+ try {
1227
+ this.devToolsRpc.broadcast.documentsUpdated([
1228
+ ...this.collector.rpcItems.values()
1229
+ ]);
1230
+ } catch {
1231
+ logger.info(
1232
+ "Failed to update GraphQL documents in dev tools. The documents might be stale."
1233
+ );
1234
+ }
1235
+ }
1236
+ }
1237
+ onViteServerCreated(server) {
1238
+ this.viteWebSocket = server.ws;
1239
+ }
1240
+ sendError(error) {
1241
+ if (!this.viteWebSocket) {
1242
+ return;
1243
+ }
1244
+ this.viteWebSocket.send({
1245
+ type: "error",
1246
+ err: {
1247
+ message: error.message,
1248
+ stack: ""
1249
+ }
1250
+ });
1251
+ }
1252
+ onNitroCompiled() {
1253
+ if (!this.operationsToReload.size) {
1254
+ return;
1255
+ }
1256
+ const operations = [...this.operationsToReload.values()];
1257
+ this.operationsToReload.clear();
1258
+ if (!this.viteWebSocket) {
1259
+ return;
1260
+ }
1261
+ this.viteWebSocket.send({
1262
+ type: "custom",
1263
+ event: "nuxt-graphql-middleware:reload",
1264
+ data: { operations }
1265
+ });
1266
+ }
1267
+ }
1268
+
1269
+ const module = defineNuxtModule({
1270
+ meta: {
1271
+ name,
1272
+ configKey: "graphqlMiddleware",
1273
+ version,
1274
+ compatibility: {
1275
+ nuxt: ">=3.16.0"
1276
+ }
1277
+ },
1278
+ defaults: defaultOptions,
1279
+ async setup(passedOptions, nuxt) {
1280
+ const helper = new ModuleHelper(nuxt, import.meta.url, passedOptions);
1281
+ const schemaProvider = new SchemaProvider(helper);
1282
+ await schemaProvider.init();
1283
+ const collector = new Collector(schemaProvider.getSchema(), helper);
1284
+ await collector.init();
1285
+ nuxt.options.appConfig.graphqlMiddleware = {
1286
+ clientCacheEnabled: !!helper.options.clientCache?.enabled,
1287
+ clientCacheMaxSize: helper.options.clientCache?.maxSize ?? 100
1288
+ };
1289
+ nuxt.options.runtimeConfig.graphqlMiddleware = {
1290
+ graphqlEndpoint: helper.options.graphqlEndpoint || ""
1291
+ };
1292
+ nuxt.options.build.transpile.push(
1293
+ fileURLToPath(new URL("./runtime", import.meta.url))
1294
+ );
1295
+ helper.inlineNitroExternals(helper.resolvers.module.resolve("./runtime"));
1296
+ helper.inlineNitroExternals(helper.paths.moduleBuildDir);
1297
+ helper.addAlias("#nuxt-graphql-middleware", helper.paths.moduleBuildDir);
1298
+ helper.addAlias("#graphql-operations", helper.paths.moduleTypesDir);
1299
+ helper.addPlugin("./runtime/plugins/provideState");
1300
+ if (helper.isDev && helper.options.errorOverlay) {
1301
+ helper.addPlugin("./runtime/plugins/devMode");
1302
+ }
1303
+ helper.addServerHandler("query", "/query/:name", "get");
1304
+ helper.addServerHandler("mutation", "/mutation/:name", "post");
1305
+ if (helper.options.enableFileUploads) {
1306
+ helper.addServerHandler("upload", "/upload/:name", "post");
1001
1307
  }
1308
+ if (helper.isDev) {
1309
+ helper.addServerHandler("debug", "/debug", "get");
1310
+ }
1311
+ if (helper.options.includeComposables) {
1312
+ helper.addComposable("useGraphqlQuery");
1313
+ helper.addComposable("useGraphqlMutation");
1314
+ helper.addComposable("useGraphqlState");
1315
+ helper.addComposable("useAsyncGraphqlQuery");
1316
+ if (helper.options.enableFileUploads) {
1317
+ helper.addComposable("useGraphqlUploadMutation");
1318
+ }
1319
+ helper.addServerUtil("useGraphqlQuery");
1320
+ helper.addServerUtil("useGraphqlMutation");
1321
+ helper.addServerUtil("doGraphqlRequest");
1322
+ }
1323
+ helper.addTemplate(Template.ClientOptions, ClientOptions);
1324
+ helper.addTemplate(Template.ClientOptionsTypes, ClientOptionsTypes);
1325
+ helper.addTemplate(Template.DocumentTypes, DocumentTypes);
1326
+ helper.addTemplate(Template.GraphqlConfig, GraphqlConfig);
1327
+ helper.addTemplate(Template.Helpers, Helpers);
1328
+ helper.addTemplate(Template.HelpersTypes, HelpersTypes);
1329
+ helper.addTemplate(Template.ServerOptions, ServerOptions);
1330
+ helper.addTemplate(Template.ServerOptionsTypes, ServerOptionsTypes);
1331
+ helper.addTemplate(Template.Types, Types);
1332
+ collector.addTemplate(Template.Enums);
1333
+ collector.addTemplate(Template.NitroTypes);
1334
+ collector.addTemplate(Template.OperationSources);
1335
+ collector.addTemplate(Template.OperationTypes);
1336
+ collector.addTemplate(Template.OperationTypesAll);
1337
+ collector.addTemplate(Template.ResponseTypes);
1338
+ collector.addVirtualTemplate(Template.Documents);
1339
+ if (!helper.isDev) {
1340
+ return;
1341
+ }
1342
+ const devModeHandler = new DevModeHandler(
1343
+ nuxt,
1344
+ schemaProvider,
1345
+ collector,
1346
+ helper
1347
+ );
1348
+ devModeHandler.init();
1002
1349
  }
1003
1350
  });
1004
1351