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