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.
- 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/9b9c571e-ce30-465b-8174-06afbdca446b.json +1 -0
- package/dist/client/index.html +7 -7
- package/dist/module.d.mts +199 -159
- package/dist/module.d.ts +199 -159
- package/dist/module.json +2 -2
- package/dist/module.mjs +938 -591
- package/dist/runtime/components/CodeFrame.vue +61 -0
- package/dist/runtime/components/DevModeOverlay.vue +60 -0
- package/dist/runtime/components/ErrorExtensions.vue +23 -0
- package/dist/runtime/components/ErrorGroup.vue +89 -0
- package/dist/runtime/composables/nuxtApp.d.ts +2 -2
- package/dist/runtime/composables/nuxtApp.js +19 -18
- package/dist/runtime/composables/useAsyncGraphqlQuery.d.ts +7 -7
- package/dist/runtime/composables/useAsyncGraphqlQuery.js +10 -2
- package/dist/runtime/composables/useGraphqlMutation.d.ts +4 -4
- package/dist/runtime/composables/useGraphqlMutation.js +1 -1
- package/dist/runtime/composables/useGraphqlQuery.d.ts +4 -4
- package/dist/runtime/composables/useGraphqlQuery.js +1 -1
- package/dist/runtime/composables/useGraphqlState.d.ts +1 -1
- package/dist/runtime/composables/useGraphqlUploadMutation.d.ts +4 -4
- package/dist/runtime/composables/useGraphqlUploadMutation.js +2 -2
- package/dist/runtime/css/output.css +1 -0
- package/dist/runtime/helpers/composables.d.ts +17 -20
- package/dist/runtime/helpers/composables.js +0 -5
- package/dist/runtime/plugins/devMode.d.ts +2 -0
- package/dist/runtime/plugins/devMode.js +23 -0
- package/dist/runtime/plugins/provideState.d.ts +1 -1
- package/dist/runtime/{serverHandler → server/api}/debug.js +3 -7
- 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 +13 -11
- 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/index.d.ts +1 -1
- package/dist/runtime/server/utils/index.js +1 -1
- package/dist/runtime/server/utils/useGraphqlMutation.d.ts +4 -4
- package/dist/runtime/server/utils/useGraphqlQuery.d.ts +4 -4
- package/dist/runtime/serverOptions/defineGraphqlServerOptions.d.ts +3 -2
- package/dist/runtime/settings/index.d.ts +49 -4
- package/dist/runtime/settings/index.js +19 -7
- package/dist/runtime/types.d.ts +8 -2
- package/package.json +21 -9
- package/dist/client/_nuxt/BS583yk8.js +0 -25
- package/dist/client/_nuxt/DpxjPVZy.js +0 -1
- package/dist/client/_nuxt/builds/meta/106a09af-649a-473b-b0c7-0e4ce5709429.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/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,93 +1,26 @@
|
|
|
1
|
-
import { loadSchema } from '@graphql-tools/load';
|
|
2
1
|
import { fileURLToPath } from 'url';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
|
11
|
-
import {
|
|
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
|
|
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.
|
|
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
|
|
46
|
+
} else if (existsSync(path)) {
|
|
131
47
|
return path;
|
|
132
48
|
}
|
|
133
49
|
const extension = extensions.find(
|
|
134
|
-
(extension2) => existsSync
|
|
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 ?
|
|
79
|
+
const icon = hasErrors ? color.red(SYMBOL_CROSS) : color.green(SYMBOL_CHECK);
|
|
271
80
|
const type = entry.type.padEnd(lengths.type);
|
|
272
|
-
const namePadded =
|
|
273
|
-
const name = hasErrors ?
|
|
274
|
-
const 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 =
|
|
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" +
|
|
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,
|
|
212
|
+
constructor(schema, helper) {
|
|
335
213
|
this.schema = schema;
|
|
336
|
-
this.
|
|
337
|
-
|
|
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
|
|
243
|
+
* The generated templates.
|
|
367
244
|
*/
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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 "./" +
|
|
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
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
-
|
|
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.
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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.
|
|
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(
|
|
392
|
+
logger.error(color.red(output));
|
|
497
393
|
}
|
|
498
394
|
/**
|
|
499
|
-
*
|
|
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
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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
|
|
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.
|
|
428
|
+
const nuxtConfigDocuments = this.helper.options.documents.join("\n\n");
|
|
519
429
|
if (nuxtConfigDocuments.length) {
|
|
520
|
-
const filePath = this.
|
|
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
|
-
|
|
549
|
-
if (!matching.includes(filePath)) {
|
|
461
|
+
if (!this.helper.matchesImportPattern(filePath)) {
|
|
550
462
|
return false;
|
|
551
463
|
}
|
|
552
|
-
await this.addFile(filePath);
|
|
553
|
-
return
|
|
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
|
|
473
|
+
return this.handleAdd(filePath);
|
|
559
474
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
|
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
|
-
*
|
|
653
|
+
* Downloads the schema and saves it to disk.
|
|
654
|
+
*
|
|
655
|
+
* @returns The schema contents.
|
|
626
656
|
*/
|
|
627
|
-
|
|
628
|
-
|
|
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
|
-
*
|
|
689
|
+
* Determine if the schema exists on disk.
|
|
690
|
+
*
|
|
691
|
+
* @returns True if the schema file exists on disk.
|
|
632
692
|
*/
|
|
633
|
-
|
|
634
|
-
return this.
|
|
693
|
+
hasSchemaOnDisk() {
|
|
694
|
+
return fs.access(this.helper.paths.schema).then(() => true).catch(() => false);
|
|
635
695
|
}
|
|
636
696
|
/**
|
|
637
|
-
*
|
|
697
|
+
* Load the schema either from disk or by downloading it.
|
|
698
|
+
*
|
|
699
|
+
* @param forceDownload - Forces downloading the schema.
|
|
638
700
|
*/
|
|
639
|
-
|
|
640
|
-
|
|
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
|
|
714
|
+
* Get the schema.
|
|
715
|
+
*
|
|
716
|
+
* @returns The parsed GraphQL schema object.
|
|
644
717
|
*/
|
|
645
|
-
|
|
646
|
-
|
|
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
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
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
|
-
|
|
685
|
-
|
|
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
|
-
|
|
711
|
-
nuxt.options.
|
|
712
|
-
|
|
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.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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
|
-
|
|
752
|
-
|
|
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
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
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
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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
|
-
|
|
789
|
-
|
|
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:
|
|
956
|
+
filename: template,
|
|
792
957
|
write: true,
|
|
793
|
-
getContents: () =>
|
|
794
|
-
})
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
958
|
+
getContents: () => content
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
addPlugin(path) {
|
|
963
|
+
addPlugin(this.resolvers.module.resolve(path), {
|
|
964
|
+
append: false
|
|
800
965
|
});
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
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
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
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
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
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
|
|
824
|
-
|
|
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
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
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
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
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
|
|
884
|
-
|
|
885
|
-
export type GraphqlResponseTyped = GraphqlResponse<GraphqlMiddlewareResponseUnion>
|
|
1072
|
+
export { serverOptions }`;
|
|
1073
|
+
}
|
|
886
1074
|
|
|
887
|
-
|
|
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
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
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
|
-
|
|
917
|
-
|
|
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
|
-
|
|
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
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
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
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
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
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
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
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
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
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
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
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
)
|
|
994
|
-
|
|
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
|
|