@lewebsimple/nuxt-graphql 0.5.5 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, relative, resolve } from 'node:path';
|
|
3
3
|
import { defu } from 'defu';
|
|
4
|
-
import {
|
|
4
|
+
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
|
|
5
|
+
import { loadDocuments } from '@graphql-tools/load';
|
|
5
6
|
import { stitchSchemas } from '@graphql-tools/stitch';
|
|
6
7
|
import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addPlugin, addImportsDir, addServerImportsDir } from '@nuxt/kit';
|
|
7
|
-
import { loadDocuments as loadDocuments$1 } from '@graphql-tools/load';
|
|
8
|
-
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
|
|
9
|
-
import { Kind, getIntrospectionQuery, buildClientSchema, GraphQLSchema } from 'graphql';
|
|
10
8
|
import { codegen } from '@graphql-codegen/core';
|
|
11
9
|
import * as typescriptPlugin from '@graphql-codegen/typescript';
|
|
12
10
|
import * as typescriptOperationsPlugin from '@graphql-codegen/typescript-operations';
|
|
13
11
|
import * as typedDocumentNodePlugin from '@graphql-codegen/typed-document-node';
|
|
12
|
+
import { Kind, getIntrospectionQuery, buildClientSchema, GraphQLSchema } from 'graphql';
|
|
14
13
|
import { mergeHeaders } from '../dist/runtime/shared/lib/headers.js';
|
|
15
14
|
import { resolveCacheConfig } from '../dist/runtime/shared/lib/cache.js';
|
|
15
|
+
import { hash } from 'ohash';
|
|
16
16
|
|
|
17
17
|
const cyan = "\x1B[36m";
|
|
18
18
|
const reset = "\x1B[0m";
|
|
@@ -41,50 +41,9 @@ declare module "#graphql/context" {
|
|
|
41
41
|
}`.trim();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async function loadDocuments(documents) {
|
|
45
|
-
try {
|
|
46
|
-
return await loadDocuments$1([
|
|
47
|
-
documents,
|
|
48
|
-
"!**/.cache/**",
|
|
49
|
-
"!**/.nuxt/**",
|
|
50
|
-
"!**/.output/**",
|
|
51
|
-
"!**/dist/**",
|
|
52
|
-
"!**/node_modules/**"
|
|
53
|
-
], { loaders: [new GraphQLFileLoader()] });
|
|
54
|
-
} catch {
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function renderFragmentsTemplate({ documents }) {
|
|
60
|
-
const fragments = collectFragments(documents);
|
|
61
|
-
return fragments.length === 0 ? "export { }" : `
|
|
62
|
-
export type {
|
|
63
|
-
${fragments.map((name) => ` ${name}Fragment,`).join("\n")}
|
|
64
|
-
} from "./operations";`.trim();
|
|
65
|
-
}
|
|
66
|
-
function collectFragments(documents) {
|
|
67
|
-
const fragments = /* @__PURE__ */ new Set();
|
|
68
|
-
for (const source of documents) {
|
|
69
|
-
const doc = source.document;
|
|
70
|
-
if (!doc) continue;
|
|
71
|
-
for (const def of doc.definitions) {
|
|
72
|
-
if (def.kind !== Kind.FRAGMENT_DEFINITION) continue;
|
|
73
|
-
const name = def.name?.value;
|
|
74
|
-
if (!name) continue;
|
|
75
|
-
if (fragments.has(name)) {
|
|
76
|
-
throw new Error(`Duplicate GraphQL fragment name "${name}"`);
|
|
77
|
-
}
|
|
78
|
-
fragments.add(name);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return [...fragments.values()];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
44
|
async function renderOperationsTemplate({ schema, documents }) {
|
|
85
|
-
|
|
45
|
+
const content = await codegen({
|
|
86
46
|
filename: "operations.ts",
|
|
87
|
-
// @graphql-codegen/core codegen supports GraphQLSchema at runtime, but types expect DocumentNode
|
|
88
47
|
schema,
|
|
89
48
|
documents,
|
|
90
49
|
plugins: [
|
|
@@ -134,14 +93,42 @@ async function renderOperationsTemplate({ schema, documents }) {
|
|
|
134
93
|
},
|
|
135
94
|
config: {}
|
|
136
95
|
});
|
|
96
|
+
const docs = splitDocuments(content);
|
|
97
|
+
const module = docs.map(({ name, object }) => `export const ${name} = ${object};`).join("\n");
|
|
98
|
+
const types = `${content.replace(/export const \w+ = [\s\S]*?;\n?/g, "")}
|
|
99
|
+
declare module "#graphql/operations" {
|
|
100
|
+
${docs.map(({ name, type }) => `export type ${name} = ${type};`).join("\n ")}
|
|
101
|
+
}`.trim();
|
|
102
|
+
return { module, types };
|
|
103
|
+
}
|
|
104
|
+
function splitDocuments(content) {
|
|
105
|
+
const documents = [];
|
|
106
|
+
const documentRegex = /export const (\w+) = ([\s\S]*?) as unknown as (DocumentNode<[^>]+>);/g;
|
|
107
|
+
let match;
|
|
108
|
+
while (match = documentRegex.exec(content)) {
|
|
109
|
+
const [, name, object, type] = match;
|
|
110
|
+
if (!name || !object || !type) {
|
|
111
|
+
throw new Error("Invalid typed document matched while splitting documents.");
|
|
112
|
+
}
|
|
113
|
+
documents.push({ name, object: object.trim(), type });
|
|
114
|
+
}
|
|
115
|
+
return documents;
|
|
137
116
|
}
|
|
138
117
|
|
|
139
118
|
async function renderRegistryTemplate({ documents }) {
|
|
140
119
|
const operations = collectOperations(documents);
|
|
141
|
-
|
|
142
|
-
import type { DocumentNode } from "graphql";
|
|
120
|
+
const module = `
|
|
143
121
|
import {
|
|
144
|
-
${operations.map(({ name }) =>
|
|
122
|
+
${operations.map(({ name }) => `${name}Document`).join(",\n ")}
|
|
123
|
+
} from "./operations";
|
|
124
|
+
|
|
125
|
+
export const registry = {
|
|
126
|
+
${operations.map(({ name, kind }) => `${name}: { kind: "${kind}", document: ${name}Document },`).join("\n ")}
|
|
127
|
+
};`.trim();
|
|
128
|
+
const types = `
|
|
129
|
+
import type { DocumentNode } from "graphql";
|
|
130
|
+
import type {
|
|
131
|
+
${operations.map(({ name, kind }) => `${name}${capitalize(kind)}Variables, ${name}${capitalize(kind)}Result,`).join("\n ")}
|
|
145
132
|
} from "./operations";
|
|
146
133
|
|
|
147
134
|
// Operation entry
|
|
@@ -154,7 +141,7 @@ export interface OperationEntry<TVariables, TResult, TKind extends "query" | "mu
|
|
|
154
141
|
|
|
155
142
|
// Operation registry type
|
|
156
143
|
export type OperationRegistry = {
|
|
157
|
-
${operations.map(({ name, kind }) =>
|
|
144
|
+
${operations.map(({ name, kind }) => `${name}: OperationEntry<${name}${capitalize(kind)}Variables, ${name}${capitalize(kind)}Result, "${kind}">;`).join("\n ")}
|
|
158
145
|
};
|
|
159
146
|
|
|
160
147
|
// Operation name types
|
|
@@ -167,11 +154,11 @@ export type SubscriptionName = { [K in keyof OperationRegistry]: OperationRegist
|
|
|
167
154
|
export type VariablesOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["variables"];
|
|
168
155
|
export type ResultOf<TName extends keyof OperationRegistry> = OperationRegistry[TName]["result"];
|
|
169
156
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
export
|
|
173
|
-
|
|
174
|
-
}
|
|
157
|
+
declare module "#graphql/registry" {
|
|
158
|
+
export const registry: { [K in keyof OperationRegistry]: { kind: OperationRegistry[K]["kind"]; document: DocumentNode; }; };
|
|
159
|
+
export type { OperationRegistry, OperationName, QueryName, MutationName, SubscriptionName, VariablesOf, ResultOf };
|
|
160
|
+
}`.trim();
|
|
161
|
+
return { module, types };
|
|
175
162
|
}
|
|
176
163
|
function collectOperations(documents) {
|
|
177
164
|
const operations = /* @__PURE__ */ new Map();
|
|
@@ -187,13 +174,14 @@ function collectOperations(documents) {
|
|
|
187
174
|
if (operations.has(name)) {
|
|
188
175
|
throw new Error(`Duplicate GraphQL operation name "${name}"`);
|
|
189
176
|
}
|
|
190
|
-
operations.set(name, {
|
|
191
|
-
name,
|
|
192
|
-
kind: def.operation
|
|
193
|
-
});
|
|
177
|
+
operations.set(name, { name, kind: def.operation });
|
|
194
178
|
}
|
|
195
179
|
}
|
|
196
|
-
return
|
|
180
|
+
return Array.from(operations.values());
|
|
181
|
+
}
|
|
182
|
+
function capitalize(value) {
|
|
183
|
+
if (!value) return value;
|
|
184
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
197
185
|
}
|
|
198
186
|
|
|
199
187
|
function renderLocalSchemaTemplate({ schemaModule }) {
|
|
@@ -373,36 +361,38 @@ const module$1 = defineNuxtModule({
|
|
|
373
361
|
}
|
|
374
362
|
nuxt.options.alias ||= {};
|
|
375
363
|
nuxt.options.alias["#graphql"] ||= resolveBuild("graphql");
|
|
364
|
+
const buildCache = /* @__PURE__ */ new Map();
|
|
365
|
+
function cachedLoader(baseKey, loader) {
|
|
366
|
+
return async (...args) => {
|
|
367
|
+
const key = `${baseKey}:${hash(args)}`;
|
|
368
|
+
const cached = buildCache.get(key);
|
|
369
|
+
if (cached?.key === key) {
|
|
370
|
+
return cached.data;
|
|
371
|
+
}
|
|
372
|
+
const data = await loader(...args);
|
|
373
|
+
buildCache.set(key, { key, data });
|
|
374
|
+
return data;
|
|
375
|
+
};
|
|
376
|
+
}
|
|
376
377
|
const contextModules = await Promise.all((options.yoga?.context || []).map((path) => resolveRootPath(path, true)));
|
|
377
378
|
addTemplate({ filename: "graphql/context.mjs", getContents: () => renderContextTemplate({ contextModules }), write: true });
|
|
378
379
|
addTemplate({ filename: "graphql/context.d.ts", getContents: () => renderContextTypesTemplate({ contextModules }), write: true });
|
|
379
380
|
addServerTemplate({ filename: "#graphql/context.mjs", getContents: () => renderContextTemplate({ contextModules }) });
|
|
380
|
-
const schemasCache = /* @__PURE__ */ new Map([]);
|
|
381
|
-
function cachedSchemaLoader(schemaDef, loader) {
|
|
382
|
-
return async () => {
|
|
383
|
-
const key = `schemaDef:${hash(schemaDef)}`;
|
|
384
|
-
const cached = schemasCache.get(key);
|
|
385
|
-
if (cached?.key === key) return cached.data;
|
|
386
|
-
const schema = await loader();
|
|
387
|
-
schemasCache.set(key, { key, data: schema });
|
|
388
|
-
return schema;
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
381
|
const remoteExecutorModule = resolveModule("./runtime/server/lib/remote-executor");
|
|
392
|
-
const
|
|
382
|
+
const schemaCachedLoaders = {};
|
|
393
383
|
for (const [schemaName, schemaDef] of Object.entries(options.yoga?.schemas || {})) {
|
|
394
384
|
if (schemaDef.type === "local") {
|
|
395
385
|
const schemaModule = await resolveRootPath(schemaDef.path, true);
|
|
396
|
-
|
|
386
|
+
schemaCachedLoaders[schemaName] = cachedLoader(`schema:local:${schemaName}`, async () => await loadLocalSchema({ schemaModule }));
|
|
397
387
|
addTemplate({ filename: `graphql/schemas/${schemaName}.mjs`, getContents: async () => renderLocalSchemaTemplate({ schemaModule }), write: true });
|
|
398
388
|
addServerTemplate({ filename: `#graphql/schemas/${schemaName}.mjs`, getContents: async () => renderLocalSchemaTemplate({ schemaModule }) });
|
|
399
389
|
} else if (schemaDef.type === "remote") {
|
|
400
|
-
|
|
390
|
+
schemaCachedLoaders[schemaName] = cachedLoader(`schema:remote:${schemaName}`, async () => await introspectRemoteSchema(schemaDef));
|
|
401
391
|
const input = {
|
|
402
392
|
remoteExecutorModule,
|
|
403
393
|
hooksModules: await Promise.all((schemaDef.hooks || []).map((hookPath) => resolveRootPath(hookPath, true))),
|
|
404
394
|
schemaDef,
|
|
405
|
-
schemaLoader:
|
|
395
|
+
schemaLoader: schemaCachedLoaders[schemaName]
|
|
406
396
|
};
|
|
407
397
|
addTemplate({ filename: `graphql/schemas/${schemaName}.mjs`, getContents: async () => await renderRemoteSchemaTemplate(input), write: true });
|
|
408
398
|
addServerTemplate({ filename: `#graphql/schemas/${schemaName}.mjs`, getContents: async () => await renderRemoteSchemaTemplate(input) });
|
|
@@ -411,9 +401,9 @@ const module$1 = defineNuxtModule({
|
|
|
411
401
|
}
|
|
412
402
|
}
|
|
413
403
|
const sdlPath = resolveRoot(options.saveSDL || "server/graphql/schema.graphql");
|
|
414
|
-
const
|
|
404
|
+
const loadCachedSchema = cachedLoader("schema:stitched", async () => {
|
|
415
405
|
const schema = stitchSchemas({
|
|
416
|
-
subschemas: await Promise.all(Object.values(
|
|
406
|
+
subschemas: await Promise.all(Object.values(schemaCachedLoaders).map((loader) => loader()))
|
|
417
407
|
});
|
|
418
408
|
const sdl = await printSchemaSDL(schema);
|
|
419
409
|
mkdirSync(dirname(sdlPath), { recursive: true });
|
|
@@ -424,39 +414,48 @@ const module$1 = defineNuxtModule({
|
|
|
424
414
|
addTemplate({ filename: "graphql/schema.mjs", getContents: () => renderSchemaTemplate({ schemaNames: Object.keys(options.yoga?.schemas || {}) }), write: true });
|
|
425
415
|
addTemplate({ filename: "graphql/schema.d.ts", getContents: () => renderSchemaTypesTemplate(), write: true });
|
|
426
416
|
addServerTemplate({ filename: "#graphql/schema.mjs", getContents: () => renderSchemaTemplate({ schemaNames: Object.keys(options.yoga?.schemas || {}) }) });
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
417
|
+
const loadCachedDocuments = cachedLoader("documents", async (documentsGlob) => {
|
|
418
|
+
try {
|
|
419
|
+
return await loadDocuments([
|
|
420
|
+
documentsGlob,
|
|
421
|
+
"!**/.cache/**",
|
|
422
|
+
"!**/.nuxt/**",
|
|
423
|
+
"!**/.output/**",
|
|
424
|
+
"!**/dist/**",
|
|
425
|
+
"!**/node_modules/**"
|
|
426
|
+
], { loaders: [new GraphQLFileLoader()] });
|
|
427
|
+
} catch {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
const loadCachedOperations = cachedLoader("operations", async (documentsGlob) => {
|
|
432
|
+
const schema = await loadCachedSchema();
|
|
433
|
+
const documents = await loadCachedDocuments(documentsGlob);
|
|
434
|
+
return await renderOperationsTemplate({ schema, documents });
|
|
435
|
+
});
|
|
436
|
+
addTemplate({ filename: "graphql/operations.mjs", getContents: async () => (await loadCachedOperations(options.client?.documents || "**/*.gql")).module, write: true });
|
|
437
|
+
addServerTemplate({ filename: "#graphql/operations.mjs", getContents: async () => (await loadCachedOperations(options.client?.documents || "**/*.gql")).module });
|
|
438
|
+
addTemplate({ filename: "graphql/operations.d.ts", getContents: async () => (await loadCachedOperations(options.client?.documents || "**/*.gql")).types, write: true });
|
|
439
|
+
const loadCachedRegistry = cachedLoader("registry", async (documentsGlob) => {
|
|
440
|
+
const documents = await loadCachedDocuments(documentsGlob);
|
|
441
|
+
return await renderRegistryTemplate({ documents });
|
|
443
442
|
});
|
|
444
443
|
addTemplate({
|
|
445
|
-
filename: "graphql/
|
|
446
|
-
getContents: async () => await
|
|
447
|
-
documents: await loadDocumentsCached(documentsGlob)
|
|
448
|
-
}),
|
|
444
|
+
filename: "graphql/registry.mjs",
|
|
445
|
+
getContents: async () => (await loadCachedRegistry(options.client?.documents || "**/*.gql")).module,
|
|
449
446
|
write: true
|
|
450
447
|
});
|
|
448
|
+
addServerTemplate({
|
|
449
|
+
filename: "#graphql/registry.mjs",
|
|
450
|
+
getContents: async () => (await loadCachedRegistry(options.client?.documents || "**/*.gql")).module
|
|
451
|
+
});
|
|
451
452
|
addTemplate({
|
|
452
|
-
filename: "graphql/registry.ts",
|
|
453
|
-
getContents: async () => await
|
|
454
|
-
documents: await loadDocumentsCached(documentsGlob)
|
|
455
|
-
}),
|
|
453
|
+
filename: "graphql/registry.d.ts",
|
|
454
|
+
getContents: async () => (await loadCachedRegistry(options.client?.documents || "**/*.gql")).types,
|
|
456
455
|
write: true
|
|
457
456
|
});
|
|
458
457
|
const configPath = resolveRoot(options.saveConfig || "graphql.config.json");
|
|
459
|
-
const config = { schema: getRelativePath(sdlPath), documents:
|
|
458
|
+
const config = { schema: getRelativePath(sdlPath), documents: options.client?.documents || "**/*.gql" };
|
|
460
459
|
mkdirSync(dirname(configPath), { recursive: true });
|
|
461
460
|
writeFileSync(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8" });
|
|
462
461
|
logger.info(`GraphQL config saved to: ${cyan}${getRelativePath(configPath)}${reset}`);
|
|
@@ -471,7 +470,8 @@ const module$1 = defineNuxtModule({
|
|
|
471
470
|
nuxt.hook("builder:watch", async (_event, changedPath) => {
|
|
472
471
|
if (changedPath.endsWith(".gql")) {
|
|
473
472
|
logger.info(`Documents change detected: ${cyan}${getRelativePath(changedPath)}${reset}`);
|
|
474
|
-
|
|
473
|
+
buildCache.delete("documents");
|
|
474
|
+
buildCache.delete("operations");
|
|
475
475
|
}
|
|
476
476
|
});
|
|
477
477
|
}
|
|
@@ -3,8 +3,10 @@ type GraphQLContextFactory<TContext extends Record<string, unknown>> = (event: H
|
|
|
3
3
|
/**
|
|
4
4
|
* Define a GraphQL context factory with proper typing.
|
|
5
5
|
*
|
|
6
|
-
* @param
|
|
6
|
+
* @param createContext Context factory function.
|
|
7
7
|
* @returns The same factory, typed for inference.
|
|
8
8
|
*/
|
|
9
|
-
export declare function defineGraphQLContext<TContext extends Record<string, unknown>>(
|
|
9
|
+
export declare function defineGraphQLContext<TContext extends Record<string, unknown>>(createContext: GraphQLContextFactory<TContext>): {
|
|
10
|
+
createContext: GraphQLContextFactory<TContext>;
|
|
11
|
+
};
|
|
10
12
|
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function defineGraphQLContext(
|
|
2
|
-
return
|
|
1
|
+
export function defineGraphQLContext(createContext) {
|
|
2
|
+
return { createContext };
|
|
3
3
|
}
|