@lewebsimple/nuxt-graphql 0.6.19 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -74
- package/dist/module.d.mts +31 -5
- package/dist/module.json +3 -3
- package/dist/module.mjs +442 -341
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.d.ts +14 -10
- package/dist/runtime/app/composables/useAsyncGraphQLQuery.js +71 -80
- package/dist/runtime/app/composables/useGraphQLCache.client.d.ts +9 -14
- package/dist/runtime/app/composables/useGraphQLCache.client.js +40 -61
- package/dist/runtime/app/composables/useGraphQLLoadMore.d.ts +16 -9
- package/dist/runtime/app/composables/useGraphQLLoadMore.js +36 -40
- package/dist/runtime/app/composables/useGraphQLMutation.d.ts +29 -31
- package/dist/runtime/app/composables/useGraphQLMutation.js +17 -32
- package/dist/runtime/app/composables/useGraphQLQuery.d.ts +10 -3
- package/dist/runtime/app/composables/useGraphQLQuery.js +4 -14
- package/dist/runtime/app/composables/useGraphQLSubscription.client.d.ts +4 -5
- package/dist/runtime/app/composables/useGraphQLSubscription.client.js +7 -5
- package/dist/runtime/app/lib/cache-config.d.ts +18 -0
- package/dist/runtime/app/lib/cache-config.js +9 -0
- package/dist/runtime/app/lib/cache.d.ts +81 -49
- package/dist/runtime/app/lib/cache.js +65 -55
- package/dist/runtime/app/lib/persisted.d.ts +18 -12
- package/dist/runtime/app/lib/persisted.js +42 -45
- package/dist/runtime/app/plugins/graphql-sse.client.js +1 -2
- package/dist/runtime/app/plugins/graphql.d.ts +24 -0
- package/dist/runtime/app/plugins/graphql.js +16 -0
- package/dist/runtime/server/api/graphql.d.ts +6 -0
- package/dist/runtime/server/api/graphql.js +1 -1
- package/dist/runtime/server/{utils/defineGraphQLContext.d.ts → lib/context.d.ts} +10 -1
- package/dist/runtime/server/lib/remote-executor.d.ts +42 -19
- package/dist/runtime/server/lib/remote-executor.js +11 -13
- package/dist/runtime/server/lib/yoga.d.ts +0 -1
- package/dist/runtime/server/lib/yoga.js +1 -2
- package/dist/runtime/server/tsconfig.json +1 -1
- package/dist/runtime/server/utils/execute-schema.d.ts +11 -0
- package/dist/runtime/server/utils/execute-schema.js +24 -0
- package/dist/runtime/shared/lib/headers.d.ts +14 -2
- package/dist/runtime/shared/lib/headers.js +18 -1
- package/dist/runtime/shared/utils/error.d.ts +39 -0
- package/dist/runtime/shared/utils/error.js +67 -0
- package/dist/runtime/shared/utils/execute.d.ts +33 -0
- package/dist/runtime/shared/utils/execute.js +26 -0
- package/dist/runtime/shared/utils/registry.d.ts +72 -0
- package/dist/runtime/shared/utils/registry.js +37 -0
- package/package.json +48 -36
- package/dist/runtime/app/lib/in-flight.d.ts +0 -14
- package/dist/runtime/app/lib/in-flight.js +0 -19
- package/dist/runtime/app/plugins/execute-graphql.d.ts +0 -18
- package/dist/runtime/app/plugins/execute-graphql.js +0 -25
- package/dist/runtime/server/lib/execute-graphql-schema.d.ts +0 -3
- package/dist/runtime/server/lib/execute-graphql-schema.js +0 -22
- package/dist/runtime/server/utils/defineRemoteExecutorHooks.d.ts +0 -8
- package/dist/runtime/server/utils/defineRemoteExecutorHooks.js +0 -3
- package/dist/runtime/server/utils/useGraphQLOperation.d.ts +0 -16
- package/dist/runtime/server/utils/useGraphQLOperation.js +0 -12
- package/dist/runtime/shared/lib/error.d.ts +0 -42
- package/dist/runtime/shared/lib/error.js +0 -52
- package/dist/runtime/shared/lib/registry.d.ts +0 -12
- package/dist/runtime/shared/lib/registry.js +0 -8
- package/dist/runtime/shared/lib/types.d.ts +0 -30
- package/dist/runtime/shared/lib/types.js +0 -0
- package/dist/runtime/shared/utils/execute-graphql-http.d.ts +0 -7
- package/dist/runtime/shared/utils/execute-graphql-http.js +0 -31
- /package/dist/runtime/server/{utils/defineGraphQLContext.js → lib/context.js} +0 -0
package/dist/module.mjs
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { relative, resolve, dirname } from 'node:path';
|
|
3
|
-
import { defu } from 'defu';
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { relative, resolve, parse, dirname } from 'node:path';
|
|
4
3
|
import { stitchSchemas } from '@graphql-tools/stitch';
|
|
5
|
-
import { addTemplate,
|
|
4
|
+
import { createResolver, addTemplate, addTypeTemplate, defineNuxtModule, useLogger, addServerImports, updateTemplates, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
|
|
5
|
+
import { defu } from 'defu';
|
|
6
|
+
import { parse as parse$1, printSchema, lexicographicSortSchema, getIntrospectionQuery, buildClientSchema, GraphQLSchema, buildSchema } from 'graphql';
|
|
7
|
+
import { cyan } from 'picocolors';
|
|
8
|
+
import picomatch from 'picomatch';
|
|
6
9
|
import { hash } from 'ohash';
|
|
7
|
-
import {
|
|
8
|
-
import { printSchema, lexicographicSortSchema, buildSchema, getIntrospectionQuery, buildClientSchema, GraphQLSchema, Kind } from 'graphql';
|
|
9
|
-
import { loadDocuments } from '@graphql-tools/load';
|
|
10
|
+
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
|
|
10
11
|
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
|
|
12
|
+
import { loadDocuments as loadDocuments$1 } from '@graphql-tools/load';
|
|
11
13
|
import { codegen } from '@graphql-codegen/core';
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
14
|
+
import zodPreset from '@lewebsimple/graphql-codegen-zod';
|
|
15
|
+
import { createRequire } from 'node:module';
|
|
16
|
+
import { resolveCacheConfig } from '../dist/runtime/app/lib/cache-config.js';
|
|
17
|
+
|
|
18
|
+
const version = "0.7.0";
|
|
16
19
|
|
|
17
20
|
const buildCache = /* @__PURE__ */ new Map();
|
|
18
21
|
function getCachedLoader(baseKey, loader) {
|
|
@@ -30,22 +33,98 @@ function getCachedLoader(baseKey, loader) {
|
|
|
30
33
|
function clearBuildCache(baseKey) {
|
|
31
34
|
if (!baseKey) {
|
|
32
35
|
buildCache.clear();
|
|
36
|
+
return;
|
|
33
37
|
}
|
|
34
38
|
const baseKeys = Array.isArray(baseKey) ? baseKey : [baseKey];
|
|
35
39
|
for (const key of buildCache.keys()) {
|
|
36
|
-
for (const
|
|
37
|
-
if (key.startsWith(`${
|
|
40
|
+
for (const targetBaseKey of baseKeys) {
|
|
41
|
+
if (key.startsWith(`${targetBaseKey}:`)) {
|
|
38
42
|
buildCache.delete(key);
|
|
43
|
+
break;
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
function toRelativePath(from, to) {
|
|
50
|
+
let relativePath = relative(resolve(from), resolve(to));
|
|
51
|
+
relativePath = relativePath.replace(/\\/g, "/");
|
|
52
|
+
if (!relativePath.startsWith("./") && !relativePath.startsWith("../")) {
|
|
53
|
+
relativePath = `./${relativePath}`;
|
|
54
|
+
}
|
|
55
|
+
return relativePath;
|
|
56
|
+
}
|
|
57
|
+
function stripExtension(filePath) {
|
|
58
|
+
const { dir, name } = parse(filePath);
|
|
59
|
+
return dir ? `${dir}/${name}` : name;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function resolveContextInput({ paths }, nuxt) {
|
|
63
|
+
const { resolvePath } = createResolver(nuxt.options.rootDir);
|
|
64
|
+
return {
|
|
65
|
+
paths: await Promise.all(
|
|
66
|
+
paths.map(async (contextPath) => {
|
|
67
|
+
const path = await resolvePath(contextPath, { alias: nuxt.options.alias });
|
|
68
|
+
return path.replaceAll("\\", "/");
|
|
69
|
+
})
|
|
70
|
+
)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function getContextTemplate({ paths }) {
|
|
74
|
+
const imports = [
|
|
75
|
+
...paths.map(
|
|
76
|
+
(path, index) => `import factory${index} from ${JSON.stringify(stripExtension(path))};`
|
|
77
|
+
),
|
|
78
|
+
`import type { H3Event } from "h3";`
|
|
79
|
+
];
|
|
80
|
+
const factories = ["(_event: H3Event) => ({})", ...paths.map((_, index) => `factory${index}`)];
|
|
81
|
+
const types = ["{}", ...paths.map((_, index) => `Awaited<ReturnType<typeof factory${index}>>`)];
|
|
82
|
+
return [
|
|
83
|
+
...imports,
|
|
84
|
+
"",
|
|
85
|
+
`export type GraphQLContext = ${types.join(" & ")};`,
|
|
86
|
+
"",
|
|
87
|
+
`const factories = [${factories.join(", ")}];`,
|
|
88
|
+
"",
|
|
89
|
+
`export async function createContext(event: H3Event): Promise<GraphQLContext> {`,
|
|
90
|
+
` const contexts = await Promise.all(factories.map((factory) => factory(event)));`,
|
|
91
|
+
` return Object.assign({}, ...contexts);`,
|
|
92
|
+
`}`
|
|
93
|
+
].join("\n");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function resolveDocumentGlobs(globs, nuxt) {
|
|
97
|
+
const { resolvePath } = createResolver(nuxt.options.rootDir);
|
|
98
|
+
return Promise.all(
|
|
99
|
+
globs.map(
|
|
100
|
+
async (glob) => (await resolvePath(glob, { alias: nuxt.options.alias })).replaceAll("\\", "/")
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
async function loadDocuments(globs) {
|
|
105
|
+
if (!globs.length) return [];
|
|
106
|
+
try {
|
|
107
|
+
const docs = await loadDocuments$1(globs, {
|
|
108
|
+
loaders: [new GraphQLFileLoader(), new CodeFileLoader()],
|
|
109
|
+
ignore: ["**/.nuxt/**", "**/.output/**", "**/dist/**", "**/node_modules/**"]
|
|
110
|
+
});
|
|
111
|
+
const seen = /* @__PURE__ */ new Set();
|
|
112
|
+
return docs.filter((doc) => {
|
|
113
|
+
const key = `${doc.location ?? ""}:${doc.rawSDL ?? ""}`;
|
|
114
|
+
if (seen.has(key)) return false;
|
|
115
|
+
seen.add(key);
|
|
116
|
+
return Boolean(doc.document);
|
|
117
|
+
});
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (typeof error === "object" && error !== null && "name" in error && error.name === "NoTypeDefinitionsFound") {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
46
125
|
|
|
47
126
|
const require$1 = createRequire(import.meta.url);
|
|
48
|
-
function
|
|
127
|
+
function compileTsModule(ts) {
|
|
49
128
|
const tsCompiler = require$1("typescript");
|
|
50
129
|
const fileName = "module.ts";
|
|
51
130
|
const outputs = {};
|
|
@@ -53,121 +132,251 @@ function splitModule(ts) {
|
|
|
53
132
|
target: tsCompiler.ScriptTarget.ES2020,
|
|
54
133
|
module: tsCompiler.ModuleKind.ESNext,
|
|
55
134
|
moduleResolution: tsCompiler.ModuleResolutionKind.NodeNext,
|
|
56
|
-
declaration: true
|
|
57
|
-
importsNotUsedAsValues: tsCompiler.ImportsNotUsedAsValues.Remove,
|
|
58
|
-
preserveValueImports: false
|
|
135
|
+
declaration: true
|
|
59
136
|
};
|
|
60
137
|
const host = tsCompiler.createCompilerHost(compilerOptions, true);
|
|
61
138
|
host.getSourceFile = (name) => name === fileName ? tsCompiler.createSourceFile(fileName, ts, tsCompiler.ScriptTarget.ESNext, true) : void 0;
|
|
62
139
|
host.readFile = () => ts;
|
|
63
140
|
host.fileExists = (f) => f === fileName;
|
|
64
|
-
host.writeFile = (name, content) =>
|
|
65
|
-
outputs[name] = content;
|
|
66
|
-
};
|
|
141
|
+
host.writeFile = (name, content) => outputs[name] = content;
|
|
67
142
|
const program = tsCompiler.createProgram([fileName], compilerOptions, host);
|
|
68
143
|
program.emit();
|
|
69
144
|
return {
|
|
70
|
-
mjs:
|
|
71
|
-
dts:
|
|
145
|
+
mjs: getCompiledContent(outputs, ".js"),
|
|
146
|
+
dts: getCompiledContent(outputs, ".d.ts")
|
|
72
147
|
};
|
|
73
148
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
return { ts, ...splitModule(ts) };
|
|
149
|
+
function getCompiledContent(outputs, extension) {
|
|
150
|
+
return Object.entries(outputs).find(([name]) => name.endsWith(extension))?.[1]?.trim() ?? "";
|
|
151
|
+
}
|
|
152
|
+
async function addCompiledTemplate({ filename, getContents }, nuxt) {
|
|
153
|
+
if (nuxt.options.dev || nuxt.options._prepare) {
|
|
154
|
+
return addTemplate({ filename: `${filename}.ts`, getContents, write: true });
|
|
155
|
+
} else {
|
|
156
|
+
const { mjs, dts } = compileTsModule(await getContents());
|
|
157
|
+
addTemplate({
|
|
158
|
+
filename: `${filename}.d.ts`,
|
|
159
|
+
getContents: () => dts,
|
|
160
|
+
write: true
|
|
161
|
+
});
|
|
162
|
+
return addTemplate({
|
|
163
|
+
filename: `${filename}.mjs`,
|
|
164
|
+
getContents: () => mjs,
|
|
165
|
+
write: true
|
|
166
|
+
});
|
|
167
|
+
}
|
|
94
168
|
}
|
|
95
169
|
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
170
|
+
async function generateRegistryArtifacts({
|
|
171
|
+
schema,
|
|
172
|
+
documents
|
|
173
|
+
}) {
|
|
174
|
+
const generates = await zodPreset.buildGeneratesSection({
|
|
175
|
+
baseOutputDir: "registry.ts",
|
|
176
|
+
schema: parse$1(printSchema(schema)),
|
|
177
|
+
documents,
|
|
178
|
+
config: {},
|
|
179
|
+
pluginMap: {},
|
|
180
|
+
plugins: [],
|
|
181
|
+
presetConfig: {}
|
|
182
|
+
});
|
|
183
|
+
if (!documents.length) {
|
|
184
|
+
return {
|
|
185
|
+
"registry.ts": getRegistryFallback(),
|
|
186
|
+
"types.d.ts": getTypesFallback()
|
|
187
|
+
};
|
|
101
188
|
}
|
|
102
|
-
|
|
189
|
+
const files = {};
|
|
190
|
+
await Promise.all(
|
|
191
|
+
generates.map(
|
|
192
|
+
(generate) => codegen(generate).then((content) => {
|
|
193
|
+
files[generate.filename] = content;
|
|
194
|
+
})
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
const artifacts = {
|
|
198
|
+
...files,
|
|
199
|
+
"registry.ts": files["registry.ts"] || getRegistryFallback(),
|
|
200
|
+
"types.d.ts": files["types.d.ts"] || getTypesFallback()
|
|
201
|
+
};
|
|
202
|
+
return artifacts;
|
|
103
203
|
}
|
|
104
|
-
function
|
|
105
|
-
|
|
204
|
+
async function addRegistryArtifactTemplates(artifacts, nuxt) {
|
|
205
|
+
let registryDst = "";
|
|
206
|
+
let typesDts = "";
|
|
207
|
+
for (const [filename, content] of Object.entries(artifacts)) {
|
|
208
|
+
switch (filename) {
|
|
209
|
+
case "types.d.ts":
|
|
210
|
+
typesDts = addTypeTemplate(
|
|
211
|
+
{
|
|
212
|
+
filename: "graphql/types.d.ts",
|
|
213
|
+
getContents: () => content,
|
|
214
|
+
write: true
|
|
215
|
+
},
|
|
216
|
+
{ nitro: true, nuxt: true }
|
|
217
|
+
).dst;
|
|
218
|
+
break;
|
|
219
|
+
default: {
|
|
220
|
+
const template = await addCompiledTemplate(
|
|
221
|
+
{
|
|
222
|
+
filename: `graphql/${stripExtension(filename)}`,
|
|
223
|
+
getContents: () => content
|
|
224
|
+
},
|
|
225
|
+
nuxt
|
|
226
|
+
);
|
|
227
|
+
if (filename === "registry.ts") {
|
|
228
|
+
registryDst = template.dst;
|
|
229
|
+
}
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (!registryDst || !typesDts) {
|
|
235
|
+
throw new Error("Failed to register GraphQL registry artifacts");
|
|
236
|
+
}
|
|
237
|
+
return { registryDst, typesDts };
|
|
106
238
|
}
|
|
239
|
+
function getRegistryFallback() {
|
|
240
|
+
return `
|
|
241
|
+
import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
|
|
242
|
+
import type * as z from "zod";
|
|
107
243
|
|
|
108
|
-
|
|
109
|
-
const localImports = Object.entries(local).map(([name, { importPath }]) => `import { schema as ${name}LocalSchema } from ${JSON.stringify(importPath)};`);
|
|
110
|
-
const localSchemas = Object.keys(local).map((name) => `${name}LocalSchema`);
|
|
111
|
-
const mergedSchema = `mergeSchemas({ schemas: [${localSchemas.join(", ")}] })`;
|
|
112
|
-
const remoteImports = Object.entries(remote).map(([name, { importPath }]) => `import { schema as ${name}RemoteSchema } from ${JSON.stringify(importPath)};`);
|
|
113
|
-
const remoteSchemas = Object.keys(remote).map((name) => `${name}RemoteSchema`);
|
|
114
|
-
const ts = `
|
|
115
|
-
import { mergeSchemas } from "@graphql-tools/schema";
|
|
116
|
-
import { stitchSchemas } from "@graphql-tools/stitch";
|
|
117
|
-
${localImports.join("\n")}
|
|
118
|
-
${remoteImports.join("\n")}
|
|
244
|
+
type EnumEntry = { schema: z.ZodEnum<Record<string, string>> };
|
|
119
245
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
246
|
+
type FragmentEntry = { schema: z.ZodObject<z.ZodRawShape> };
|
|
247
|
+
|
|
248
|
+
type OperationEntry = {
|
|
249
|
+
kind: "query" | "mutation" | "subscription";
|
|
250
|
+
document: TypedDocumentNode<any, any>;
|
|
251
|
+
resultSchema: z.ZodObject<z.ZodRawShape>;
|
|
252
|
+
variablesSchema: z.ZodObject<z.ZodRawShape>;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export const enums: Record<string, EnumEntry> = {};
|
|
256
|
+
export const fragments: Record<string, FragmentEntry> = {};
|
|
257
|
+
export const operations: Record<string, OperationEntry> = {};
|
|
258
|
+
`.trim();
|
|
125
259
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const jiti = createJiti(import.meta.url, { interopDefault: true });
|
|
129
|
-
const module = await jiti.import(importPath);
|
|
130
|
-
if (!module.schema || !(module.schema instanceof Object) || typeof module.schema.getQueryType !== "function") {
|
|
131
|
-
throw new Error(`${importPath} must export a valid 'schema' of type GraphQLSchema.`);
|
|
132
|
-
}
|
|
133
|
-
return module.schema;
|
|
260
|
+
function getTypesFallback() {
|
|
261
|
+
return `export type {};`;
|
|
134
262
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
263
|
+
|
|
264
|
+
async function resolveSchemaDefs(schemaDefs, nuxt) {
|
|
265
|
+
const { resolvePath } = createResolver(nuxt.options.rootDir);
|
|
266
|
+
return Promise.all(
|
|
267
|
+
schemaDefs.map(async (schemaDef) => {
|
|
268
|
+
switch (schemaDef.type) {
|
|
269
|
+
case "local": {
|
|
270
|
+
const path = await resolvePath(schemaDef.path, { alias: nuxt.options.alias });
|
|
271
|
+
return {
|
|
272
|
+
type: "local",
|
|
273
|
+
path: path.replaceAll("\\", "/")
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case "remote": {
|
|
277
|
+
const hooks = await Promise.all(
|
|
278
|
+
(schemaDef.hooks ?? []).map(async (hookPath) => {
|
|
279
|
+
const path = await resolvePath(hookPath, { alias: nuxt.options.alias });
|
|
280
|
+
return path.replaceAll("\\", "/");
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
return {
|
|
284
|
+
type: "remote",
|
|
285
|
+
endpoint: schemaDef.endpoint,
|
|
286
|
+
headers: schemaDef.headers ?? {},
|
|
287
|
+
hooks
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
function getRemoteSchemaServerTemplate({
|
|
295
|
+
endpoint,
|
|
296
|
+
headers,
|
|
297
|
+
hooks,
|
|
298
|
+
sdl
|
|
299
|
+
}) {
|
|
300
|
+
const hookImports = hooks.map(
|
|
301
|
+
(hookPath, index) => `import hook${index} from ${JSON.stringify(hookPath)};`
|
|
302
|
+
);
|
|
303
|
+
const hookRefs = hooks.map((_, index) => `hook${index}`);
|
|
304
|
+
return `
|
|
143
305
|
import { getRemoteExecutor } from "#graphql/runtime/remote-executor";
|
|
144
|
-
|
|
306
|
+
import { buildSchema } from "graphql";
|
|
307
|
+
${hookImports.join("\n")}
|
|
145
308
|
|
|
146
309
|
const executor = getRemoteExecutor({
|
|
147
|
-
endpoint:
|
|
310
|
+
endpoint: ${JSON.stringify(endpoint)},
|
|
148
311
|
headers: ${JSON.stringify(headers)},
|
|
149
|
-
hooks: [${
|
|
312
|
+
hooks: [${hookRefs.join(", ")}],
|
|
150
313
|
});
|
|
151
314
|
|
|
152
|
-
const sdl = ${JSON.stringify(sdl)};
|
|
153
|
-
|
|
154
|
-
// SubschemaConfig exported for stitching
|
|
155
315
|
export const schema = {
|
|
156
|
-
schema: buildSchema(sdl),
|
|
316
|
+
schema: buildSchema(${JSON.stringify(sdl)}),
|
|
157
317
|
executor,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return { ts, ...splitModule(ts) };
|
|
318
|
+
};
|
|
319
|
+
`.trim();
|
|
161
320
|
}
|
|
162
|
-
|
|
321
|
+
function getSchemaServerTemplate({ localPaths, remotePaths }) {
|
|
322
|
+
const imports = [
|
|
323
|
+
...localPaths.map(
|
|
324
|
+
(schemaPath, index) => `import { schema as localSchema${index} } from ${JSON.stringify(schemaPath)};`
|
|
325
|
+
),
|
|
326
|
+
...remotePaths.map(
|
|
327
|
+
(schemaPath, index) => `import { schema as remoteSchema${index} } from ${JSON.stringify(schemaPath)};`
|
|
328
|
+
)
|
|
329
|
+
];
|
|
330
|
+
const localSchemaRefs = localPaths.map((_, index) => `localSchema${index}`);
|
|
331
|
+
const remoteSchemaRefs = remotePaths.map((_, index) => `remoteSchema${index}`);
|
|
332
|
+
const schemaRefs = [];
|
|
333
|
+
if (localSchemaRefs.length === 1) {
|
|
334
|
+
schemaRefs.push(localSchemaRefs[0]);
|
|
335
|
+
} else if (localSchemaRefs.length > 1) {
|
|
336
|
+
imports.unshift(`import { mergeSchemas } from "@graphql-tools/schema";`);
|
|
337
|
+
schemaRefs.push(`mergeSchemas({ schemas: [${localSchemaRefs.join(", ")}] })`);
|
|
338
|
+
}
|
|
339
|
+
schemaRefs.push(...remoteSchemaRefs);
|
|
340
|
+
let schemaRef;
|
|
341
|
+
if (schemaRefs.length === 0) {
|
|
342
|
+
imports.unshift(`import { buildSchema } from "graphql";`);
|
|
343
|
+
schemaRef = `buildSchema("type Query { _empty: String }")`;
|
|
344
|
+
} else if (schemaRefs.length === 1) {
|
|
345
|
+
schemaRef = schemaRefs[0];
|
|
346
|
+
} else {
|
|
347
|
+
imports.unshift(`import { stitchSchemas } from "@graphql-tools/stitch";`);
|
|
348
|
+
schemaRef = `stitchSchemas({ subschemas: [${schemaRefs.join(", ")}] })`;
|
|
349
|
+
}
|
|
350
|
+
return [...imports, "", `export const schema = ${schemaRef};`].join("\n");
|
|
351
|
+
}
|
|
352
|
+
async function loadLocalSchema(path, nuxt) {
|
|
353
|
+
const { createJiti } = await import('jiti');
|
|
354
|
+
const jiti = createJiti(import.meta.url, { interopDefault: true, alias: nuxt.options.alias });
|
|
355
|
+
const module = await jiti.import(path);
|
|
356
|
+
if (!module.schema || !(module.schema instanceof Object) || typeof module.schema.getQueryType !== "function") {
|
|
357
|
+
throw new Error(`${path} must export a valid 'schema' of type GraphQLSchema.`);
|
|
358
|
+
}
|
|
359
|
+
return module.schema;
|
|
360
|
+
}
|
|
361
|
+
async function loadRemoteSchema(endpoint, headers) {
|
|
163
362
|
const response = await fetch(endpoint, {
|
|
164
363
|
method: "POST",
|
|
165
|
-
headers: { "Content-Type": "application/json" },
|
|
364
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
166
365
|
body: JSON.stringify({ query: getIntrospectionQuery() })
|
|
167
366
|
});
|
|
367
|
+
if (!response.ok) {
|
|
368
|
+
throw new Error(
|
|
369
|
+
`Failed to introspect remote GraphQL schema at "${endpoint}" (HTTP ${response.status}).`
|
|
370
|
+
);
|
|
371
|
+
}
|
|
168
372
|
const json = await response.json();
|
|
169
373
|
if (json.errors) {
|
|
170
|
-
throw new Error(
|
|
374
|
+
throw new Error(
|
|
375
|
+
`Failed to introspect remote GraphQL schema at "${endpoint}": ${JSON.stringify(json.errors)}`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
if (!json.data || typeof json.data !== "object") {
|
|
379
|
+
throw new Error(`Remote GraphQL introspection at "${endpoint}" returned no data.`);
|
|
171
380
|
}
|
|
172
381
|
const schema = buildClientSchema(json.data);
|
|
173
382
|
return stripSubscriptions(schema);
|
|
@@ -187,284 +396,176 @@ function stripSubscriptions(schema) {
|
|
|
187
396
|
function getSchemaSDL(schema) {
|
|
188
397
|
return printSchema(lexicographicSortSchema(schema));
|
|
189
398
|
}
|
|
190
|
-
function getDefaultSchema() {
|
|
191
|
-
return buildSchema(`type Query { _empty: String }`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function addUniversalTemplate({ filename, getContents, emitTs }) {
|
|
195
|
-
let modulePath;
|
|
196
|
-
if (emitTs) {
|
|
197
|
-
modulePath = addTemplate({ filename: `${filename}.ts`, getContents: async () => (await getContents()).ts, write: true }).dst;
|
|
198
|
-
} else {
|
|
199
|
-
modulePath = addTemplate({ filename: `${filename}.mjs`, getContents: async () => (await getContents()).mjs, write: true }).dst;
|
|
200
|
-
addTemplate({ filename: `${filename}.d.ts`, getContents: async () => (await getContents()).dts });
|
|
201
|
-
}
|
|
202
|
-
addServerTemplate({ filename: `${filename}.mjs`, getContents: async () => (await getContents()).mjs });
|
|
203
|
-
return modulePath;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const version = "0.6.19";
|
|
207
|
-
|
|
208
|
-
async function getDocuments(documentsGlob) {
|
|
209
|
-
try {
|
|
210
|
-
return await loadDocuments([
|
|
211
|
-
documentsGlob,
|
|
212
|
-
"!**/.cache/**",
|
|
213
|
-
"!**/.nuxt/**",
|
|
214
|
-
"!**/.output/**",
|
|
215
|
-
"!**/dist/**",
|
|
216
|
-
"!**/node_modules/**"
|
|
217
|
-
], { loaders: [new GraphQLFileLoader()] });
|
|
218
|
-
} catch (error) {
|
|
219
|
-
if (typeof error === "object" && error !== null && "name" in error && error.name === "NoTypeDefinitionsFound") {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
async function getOperationsTemplate({ loadSchema, loadDocuments, documentGlob }) {
|
|
227
|
-
const ts = await codegen({
|
|
228
|
-
filename: "operations.ts",
|
|
229
|
-
schema: await loadSchema(),
|
|
230
|
-
documents: await loadDocuments(documentGlob),
|
|
231
|
-
plugins: [
|
|
232
|
-
{
|
|
233
|
-
typescript: {
|
|
234
|
-
avoidOptionals: {
|
|
235
|
-
field: true,
|
|
236
|
-
object: true,
|
|
237
|
-
inputValue: false,
|
|
238
|
-
defaultValue: false
|
|
239
|
-
},
|
|
240
|
-
defaultScalarType: "never",
|
|
241
|
-
enumsAsConst: true,
|
|
242
|
-
preResolveTypes: false,
|
|
243
|
-
strictScalars: true,
|
|
244
|
-
useTypeImports: true
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
typescriptOperations: {
|
|
249
|
-
avoidOptionals: {
|
|
250
|
-
field: true,
|
|
251
|
-
object: true,
|
|
252
|
-
inputValue: false,
|
|
253
|
-
defaultValue: false
|
|
254
|
-
},
|
|
255
|
-
defaultScalarType: "never",
|
|
256
|
-
enumsAsConst: true,
|
|
257
|
-
exportFragmentSpreadSubTypes: true,
|
|
258
|
-
inlineFragmentTypes: "combine",
|
|
259
|
-
operationResultSuffix: "Result",
|
|
260
|
-
operationVariablesSuffix: "Variables",
|
|
261
|
-
preResolveTypes: false,
|
|
262
|
-
skipTypename: true,
|
|
263
|
-
strictScalars: true,
|
|
264
|
-
useTypeImports: true
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
typedDocumentNode: {
|
|
269
|
-
documentVariableSuffix: "Document",
|
|
270
|
-
operationResultSuffix: "Result",
|
|
271
|
-
operationVariablesSuffix: "Variables",
|
|
272
|
-
optimizeDocumentNode: true,
|
|
273
|
-
useTypeImports: true
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
],
|
|
277
|
-
pluginMap: {
|
|
278
|
-
typescript: typescriptPlugin,
|
|
279
|
-
typescriptOperations: typescriptOperationsPlugin,
|
|
280
|
-
typedDocumentNode: typedDocumentNodePlugin
|
|
281
|
-
},
|
|
282
|
-
config: {}
|
|
283
|
-
});
|
|
284
|
-
return { ts, ...splitModule(ts) };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async function getRegistryTemplate({ loadDocuments, documentGlob }) {
|
|
288
|
-
const documents = await loadDocuments(documentGlob);
|
|
289
|
-
const operations = collectOperations(documents);
|
|
290
|
-
function capitalize(value) {
|
|
291
|
-
if (!value) return value;
|
|
292
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
293
|
-
}
|
|
294
|
-
const ts = `
|
|
295
|
-
import type { DocumentNode } from "graphql";
|
|
296
|
-
import {
|
|
297
|
-
${operations.map(({ name, kind }) => `${name}Document, type ${name}${capitalize(kind)}Variables, type ${name}${capitalize(kind)}Result,`).join("\n ")}
|
|
298
|
-
} from "./operations";
|
|
299
|
-
|
|
300
|
-
// Operation entry
|
|
301
|
-
export interface OperationEntry<TVariables, TResult, TKind extends "query" | "mutation" | "subscription"> {
|
|
302
|
-
kind: TKind;
|
|
303
|
-
variables: TVariables;
|
|
304
|
-
result: TResult;
|
|
305
|
-
document: DocumentNode;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Operation registry type
|
|
309
|
-
export type OperationRegistry = {
|
|
310
|
-
${operations.map(({ name, kind }) => `${name}: OperationEntry<${name}${capitalize(kind)}Variables, ${name}${capitalize(kind)}Result, "${kind}">;`).join("\n ")}
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
// Operation name types
|
|
314
|
-
export type OperationName = keyof OperationRegistry;
|
|
315
|
-
export type QueryName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "query" ? K : never }[keyof OperationRegistry];
|
|
316
|
-
export type MutationName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "mutation" ? K : never }[keyof OperationRegistry];
|
|
317
|
-
export type SubscriptionName = { [K in keyof OperationRegistry]: OperationRegistry[K]["kind"] extends "subscription" ? K : never }[keyof OperationRegistry];
|
|
318
|
-
|
|
319
|
-
// Projection helpers (variables / result)
|
|
320
|
-
export type VariablesOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["variables"];
|
|
321
|
-
export type ResultOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["result"];
|
|
322
|
-
|
|
323
|
-
export const registry: { [K in keyof OperationRegistry]: { kind: OperationRegistry[K]["kind"]; document: DocumentNode; }; } = {
|
|
324
|
-
${operations.map(({ name, kind }) => `${name}: { kind: "${kind}", document: ${name}Document },`).join("\n ")}
|
|
325
|
-
};`.trim();
|
|
326
|
-
return { ts, ...splitModule(ts) };
|
|
327
|
-
}
|
|
328
|
-
function collectOperations(documents) {
|
|
329
|
-
const operations = /* @__PURE__ */ new Map();
|
|
330
|
-
for (const source of documents) {
|
|
331
|
-
const doc = source.document;
|
|
332
|
-
if (!doc) continue;
|
|
333
|
-
for (const def of doc.definitions) {
|
|
334
|
-
if (def.kind !== Kind.OPERATION_DEFINITION) continue;
|
|
335
|
-
const name = def.name?.value;
|
|
336
|
-
if (!name) {
|
|
337
|
-
throw new Error("Anonymous GraphQL operations are not allowed");
|
|
338
|
-
}
|
|
339
|
-
if (operations.has(name)) {
|
|
340
|
-
throw new Error(`Duplicate GraphQL operation name "${name}"`);
|
|
341
|
-
}
|
|
342
|
-
operations.set(name, { name, kind: def.operation });
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return Array.from(operations.values());
|
|
346
|
-
}
|
|
347
399
|
|
|
348
400
|
const module$1 = defineNuxtModule({
|
|
349
401
|
meta: {
|
|
350
|
-
name: "
|
|
402
|
+
name: "nuxt-graphql",
|
|
351
403
|
configKey: "graphql"
|
|
352
404
|
},
|
|
353
405
|
defaults: {},
|
|
354
406
|
async setup(options, nuxt) {
|
|
355
407
|
const logger = useLogger("@lewebsimple/nuxt-graphql");
|
|
356
408
|
logger.info(`@lewebsimple/nuxt-graphql v${version} loaded`);
|
|
357
|
-
const { resolve: resolveModule } = createResolver(import.meta.url);
|
|
358
409
|
const { rootDir } = nuxt.options;
|
|
359
|
-
const { resolve:
|
|
360
|
-
|
|
361
|
-
return removeExtension(await rawResolveRootPath(path));
|
|
362
|
-
}
|
|
410
|
+
const { resolve: resolveModule } = createResolver(import.meta.url);
|
|
411
|
+
const { resolve: resolveRoot } = createResolver(rootDir);
|
|
363
412
|
const nuxtAliases = {};
|
|
364
413
|
const nitroAliases = {};
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
414
|
+
const transpileEntries = /* @__PURE__ */ new Set();
|
|
415
|
+
addServerImports({
|
|
416
|
+
name: "defineGraphQLContext",
|
|
417
|
+
from: resolveModule("runtime/server/lib/context")
|
|
418
|
+
});
|
|
419
|
+
const contextInput = await resolveContextInput({ paths: options.server?.context ?? [] }, nuxt);
|
|
420
|
+
contextInput.paths.forEach((path) => transpileEntries.add(dirname(path)));
|
|
421
|
+
const { dst: contextDst } = await addCompiledTemplate(
|
|
422
|
+
{ filename: "graphql/context", getContents: () => getContextTemplate(contextInput) },
|
|
423
|
+
nuxt
|
|
424
|
+
);
|
|
425
|
+
nitroAliases["#graphql/context"] = contextDst;
|
|
426
|
+
addServerImports({
|
|
427
|
+
name: "defineRemoteExecutorHooks",
|
|
428
|
+
from: resolveModule("runtime/server/lib/remote-executor")
|
|
429
|
+
});
|
|
430
|
+
nitroAliases["#graphql/runtime/remote-executor"] = resolveModule(
|
|
431
|
+
"runtime/server/lib/remote-executor"
|
|
432
|
+
);
|
|
433
|
+
const schemaDefs = await resolveSchemaDefs(options.server?.schema ?? [], nuxt);
|
|
434
|
+
const schemaInput = {
|
|
435
|
+
localPaths: [],
|
|
436
|
+
remotePaths: []
|
|
370
437
|
};
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
438
|
+
const schemaLoaders = [];
|
|
439
|
+
for (const [index, schemaDef] of schemaDefs.entries()) {
|
|
440
|
+
switch (schemaDef.type) {
|
|
441
|
+
case "local": {
|
|
442
|
+
const loadSchema = getCachedLoader(
|
|
443
|
+
`graphql:schema:local-${index}`,
|
|
444
|
+
async () => await loadLocalSchema(schemaDef.path, nuxt)
|
|
445
|
+
);
|
|
446
|
+
schemaLoaders.push(loadSchema);
|
|
447
|
+
transpileEntries.add(dirname(schemaDef.path));
|
|
448
|
+
schemaInput.localPaths.push(schemaDef.path);
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
case "remote": {
|
|
452
|
+
const schemaLoader = getCachedLoader(
|
|
453
|
+
`graphql:schema:remote-${index}`,
|
|
454
|
+
async () => await loadRemoteSchema(schemaDef.endpoint, schemaDef.headers ?? {})
|
|
455
|
+
);
|
|
456
|
+
schemaLoaders.push(schemaLoader);
|
|
457
|
+
(schemaDef.hooks ?? []).forEach((hookPath) => transpileEntries.add(dirname(hookPath)));
|
|
458
|
+
await addCompiledTemplate(
|
|
459
|
+
{
|
|
460
|
+
filename: `graphql/schemas/remote-${index}`,
|
|
461
|
+
getContents: async () => getRemoteSchemaServerTemplate({
|
|
462
|
+
...schemaDef,
|
|
463
|
+
sdl: getSchemaSDL(await schemaLoader())
|
|
464
|
+
})
|
|
465
|
+
},
|
|
466
|
+
nuxt
|
|
467
|
+
);
|
|
468
|
+
schemaInput.remotePaths.push(`./schemas/remote-${index}`);
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
395
471
|
}
|
|
396
472
|
}
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
473
|
+
const { dst: schemaDst } = await addCompiledTemplate(
|
|
474
|
+
{
|
|
475
|
+
filename: "graphql/schema",
|
|
476
|
+
getContents: () => getSchemaServerTemplate(schemaInput)
|
|
477
|
+
},
|
|
478
|
+
nuxt
|
|
479
|
+
);
|
|
480
|
+
nitroAliases["#graphql/schema"] = schemaDst;
|
|
481
|
+
const sdlPath = resolveRoot(options.saveSDL || ".nuxt/graphql/schema.graphql");
|
|
482
|
+
await mkdir(dirname(sdlPath), { recursive: true });
|
|
483
|
+
const loadSchemaCached = getCachedLoader("graphql:schema", async () => {
|
|
484
|
+
const schemas = await Promise.all(schemaLoaders.map((loader) => loader()));
|
|
485
|
+
let schema;
|
|
486
|
+
if (!schemas.length) {
|
|
487
|
+
if (!nuxt.options._prepare) {
|
|
488
|
+
logger.warn("No GraphQL schemas loaded: using default empty schema.");
|
|
489
|
+
}
|
|
490
|
+
schema = buildSchema("type Query { _empty: String }");
|
|
491
|
+
} else {
|
|
492
|
+
schema = stitchSchemas({ subschemas: schemas });
|
|
493
|
+
if (!schema) {
|
|
494
|
+
throw new Error("Failed to load GraphQL schema");
|
|
495
|
+
}
|
|
406
496
|
}
|
|
407
|
-
const schema = stitchSchemas({ subschemas });
|
|
408
497
|
if (nuxt.options.dev) {
|
|
409
498
|
const sdl = getSchemaSDL(schema);
|
|
410
|
-
|
|
411
|
-
writeFileSync(sdlPath, sdl, { encoding: "utf-8" });
|
|
412
|
-
logger.info(`Stitched GraphQL SDL saved to: ${cyan}${getRelativePath(rootDir, sdlPath)}${reset}`);
|
|
499
|
+
await writeFile(sdlPath, sdl);
|
|
413
500
|
}
|
|
414
501
|
return schema;
|
|
415
502
|
});
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
503
|
+
const documentGlobs = await resolveDocumentGlobs(
|
|
504
|
+
options.client?.documents ?? nuxt.options._prepare ? [] : ["app/**/*.{gql,ts,vue}", "server/**/*.{gql,ts}", "shared/**/*.{gql,ts}"],
|
|
505
|
+
nuxt
|
|
506
|
+
);
|
|
507
|
+
const loadDocumentsCached = getCachedLoader(
|
|
508
|
+
"graphql:documents",
|
|
509
|
+
async (globs) => loadDocuments(globs)
|
|
510
|
+
);
|
|
511
|
+
const generateRegistryCached = getCachedLoader(
|
|
512
|
+
"graphql:registry",
|
|
513
|
+
async (globs) => await generateRegistryArtifacts({
|
|
514
|
+
schema: await loadSchemaCached(),
|
|
515
|
+
documents: await loadDocumentsCached(globs)
|
|
516
|
+
})
|
|
517
|
+
);
|
|
518
|
+
const syncRegistryTemplates = async () => await addRegistryArtifactTemplates(await generateRegistryCached(documentGlobs), nuxt);
|
|
519
|
+
const { registryDst, typesDts } = await syncRegistryTemplates();
|
|
520
|
+
const typesPath = typesDts.replace(/\.d\.ts$/, "");
|
|
521
|
+
nuxtAliases["#graphql/registry"] = registryDst;
|
|
522
|
+
nitroAliases["#graphql/registry"] = registryDst;
|
|
523
|
+
nuxtAliases["#graphql/types"] = typesPath;
|
|
524
|
+
nitroAliases["#graphql/types"] = typesPath;
|
|
525
|
+
if (nuxt.options.dev) {
|
|
526
|
+
const schemaWatchPaths = schemaDefs.filter((schemaDef) => schemaDef.type === "local").map((schemaDef) => schemaDef.path);
|
|
527
|
+
const isDocument = picomatch(documentGlobs);
|
|
528
|
+
nuxt.hook("builder:watch", async (_event, path) => {
|
|
529
|
+
if (schemaWatchPaths.some((schemaPath) => path.includes(schemaPath))) {
|
|
530
|
+
logger.info(`Local schema change detected: ${path}`);
|
|
531
|
+
clearBuildCache(["graphql:schema", "graphql:registry"]);
|
|
532
|
+
await syncRegistryTemplates();
|
|
533
|
+
await updateTemplates({ filter: (template) => template.filename.startsWith("graphql/") });
|
|
534
|
+
}
|
|
535
|
+
if (isDocument(path)) {
|
|
536
|
+
logger.info(`Document change detected: ${path}`);
|
|
537
|
+
clearBuildCache(["graphql:documents", "graphql:registry"]);
|
|
538
|
+
await syncRegistryTemplates();
|
|
539
|
+
await updateTemplates({ filter: (template) => template.filename.startsWith("graphql/") });
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
}
|
|
431
543
|
if (nuxt.options.dev) {
|
|
432
544
|
const configPath = resolveRoot(options.saveConfig || "graphql.config.json");
|
|
433
545
|
const config = {
|
|
434
|
-
schema:
|
|
435
|
-
documents:
|
|
546
|
+
schema: toRelativePath(rootDir, sdlPath),
|
|
547
|
+
documents: documentGlobs.map((glob) => toRelativePath(rootDir, glob))
|
|
436
548
|
};
|
|
437
|
-
|
|
438
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8" });
|
|
439
|
-
logger.info(`GraphQL config saved to: ${cyan}${getRelativePath(rootDir, configPath)}${reset}`);
|
|
549
|
+
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
440
550
|
}
|
|
441
551
|
nuxt.options.alias = defu(nuxt.options.alias, nuxtAliases);
|
|
442
|
-
nuxt.
|
|
443
|
-
|
|
444
|
-
});
|
|
552
|
+
nuxt.options.nitro.alias = defu(nuxt.options.nitro.alias, nitroAliases);
|
|
553
|
+
nuxt.options.build.transpile = [...nuxt.options.build.transpile, ...transpileEntries];
|
|
445
554
|
nuxt.options.runtimeConfig.public.graphql = defu(nuxt.options.runtimeConfig.public.graphql, {
|
|
446
555
|
cacheConfig: resolveCacheConfig(options.client?.cache),
|
|
447
556
|
ssrForwardHeaders: options.client?.ssrForwardHeaders || ["authorization", "cookie"]
|
|
448
557
|
});
|
|
449
|
-
|
|
450
|
-
nuxt.hook("builder:watch", async (_event, changedPath) => {
|
|
451
|
-
if (changedPath.endsWith(".gql")) {
|
|
452
|
-
logger.info(`Documents change detected: ${cyan}${getRelativePath(rootDir, changedPath)}${reset}`);
|
|
453
|
-
clearBuildCache(["documents", "operations", "registry"]);
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
const handler = resolveModule("./runtime/server/api/graphql");
|
|
558
|
+
const handler = resolveModule("runtime/server/api/graphql");
|
|
458
559
|
addServerHandler({ route: "/api/graphql", handler });
|
|
459
560
|
nuxt.hook("listen", (_, { url }) => {
|
|
460
|
-
logger.success(`GraphQL
|
|
561
|
+
logger.success(`GraphQL endpoint available at ${cyan(`${url}api/graphql`)}`);
|
|
461
562
|
});
|
|
462
|
-
addPlugin(resolveModule("
|
|
463
|
-
addPlugin(resolveModule("
|
|
464
|
-
addImportsDir(resolveModule("
|
|
465
|
-
addImportsDir(resolveModule("
|
|
466
|
-
addServerImportsDir(resolveModule("
|
|
467
|
-
addServerImportsDir(resolveModule("
|
|
563
|
+
addPlugin(resolveModule("runtime/app/plugins/graphql"));
|
|
564
|
+
addPlugin(resolveModule("runtime/app/plugins/graphql-sse.client"));
|
|
565
|
+
addImportsDir(resolveModule("runtime/app/composables"));
|
|
566
|
+
addImportsDir(resolveModule("runtime/shared/utils"));
|
|
567
|
+
addServerImportsDir(resolveModule("runtime/server/utils"));
|
|
568
|
+
addServerImportsDir(resolveModule("runtime/shared/utils"));
|
|
468
569
|
}
|
|
469
570
|
});
|
|
470
571
|
|