nuxt-graphql-middleware 5.2.3 → 5.3.1
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 +2 -0
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/CqRv5mwS.js +2 -0
- package/dist/client/_nuxt/{gyQx9VSj.js → D95LLO0l.js} +1 -1
- package/dist/client/_nuxt/{DyBqp5hr.js → DZ-uq6Vd.js} +1 -1
- package/dist/client/_nuxt/DrXVleME.js +4 -0
- package/dist/client/_nuxt/{BPB7Y782.js → Dx-h1-qv.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/efa6c0a0-833e-4e5a-bc2d-ba9d0d3e4562.json +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +1 -1
- package/dist/module.json +3 -3
- package/dist/module.mjs +1526 -70
- package/dist/runtime/components/CodeFrame.d.vue.ts +8 -0
- package/dist/runtime/components/CodeFrame.vue.d.ts +2 -1
- package/dist/runtime/components/DevModeOverlay.d.vue.ts +4 -0
- package/dist/runtime/components/DevModeOverlay.vue.d.ts +2 -1
- package/dist/runtime/components/ErrorExtensions.d.vue.ts +6 -0
- package/dist/runtime/components/ErrorExtensions.vue.d.ts +2 -1
- package/dist/runtime/components/ErrorGroup.d.vue.ts +10 -0
- package/dist/runtime/components/ErrorGroup.vue.d.ts +2 -1
- package/dist/runtime/helpers/composables.d.ts +1 -40
- package/dist/runtime/helpers/composables.js +3 -12
- package/dist/runtime/helpers/shared-types.d.ts +40 -0
- package/dist/runtime/helpers/shared-types.js +12 -0
- package/dist/runtime/server/api/doRequest.d.ts +2 -0
- package/dist/runtime/server/api/doRequest.js +18 -0
- package/dist/runtime/server/helpers/index.js +1 -1
- package/dist/runtime/server/mcp/handler.d.ts +2 -0
- package/dist/runtime/server/mcp/handler.js +63 -0
- package/dist/runtime/server/mcp/resources/docs.d.ts +2 -0
- package/dist/runtime/server/mcp/resources/docs.js +36 -0
- package/dist/runtime/server/mcp/tools/fragments-get/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/fragments-get/index.js +35 -0
- package/dist/runtime/server/mcp/tools/fragments-get/types.d.ts +20 -0
- package/dist/runtime/server/mcp/tools/fragments-get/types.js +13 -0
- package/dist/runtime/server/mcp/tools/fragments-get-source/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/fragments-get-source/index.js +34 -0
- package/dist/runtime/server/mcp/tools/fragments-get-source/types.d.ts +10 -0
- package/dist/runtime/server/mcp/tools/fragments-get-source/types.js +9 -0
- package/dist/runtime/server/mcp/tools/fragments-list/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/fragments-list/index.js +36 -0
- package/dist/runtime/server/mcp/tools/fragments-list/types.d.ts +20 -0
- package/dist/runtime/server/mcp/tools/fragments-list/types.js +14 -0
- package/dist/runtime/server/mcp/tools/fragments-list-for-type/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/fragments-list-for-type/index.js +39 -0
- package/dist/runtime/server/mcp/tools/fragments-list-for-type/types.d.ts +31 -0
- package/dist/runtime/server/mcp/tools/fragments-list-for-type/types.js +23 -0
- package/dist/runtime/server/mcp/tools/graphql-execute/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/graphql-execute/index.js +59 -0
- package/dist/runtime/server/mcp/tools/module-get-config/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/module-get-config/index.js +23 -0
- package/dist/runtime/server/mcp/tools/module-get-config/types.d.ts +39 -0
- package/dist/runtime/server/mcp/tools/module-get-config/types.js +26 -0
- package/dist/runtime/server/mcp/tools/nitro-graphql-server-utils-example/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/nitro-graphql-server-utils-example/index.js +36 -0
- package/dist/runtime/server/mcp/tools/nitro-graphql-server-utils-example/types.d.ts +49 -0
- package/dist/runtime/server/mcp/tools/nitro-graphql-server-utils-example/types.js +24 -0
- package/dist/runtime/server/mcp/tools/operations-execute/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/operations-execute/index.js +63 -0
- package/dist/runtime/server/mcp/tools/operations-get/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/operations-get/index.js +40 -0
- package/dist/runtime/server/mcp/tools/operations-get/types.d.ts +32 -0
- package/dist/runtime/server/mcp/tools/operations-get/types.js +18 -0
- package/dist/runtime/server/mcp/tools/operations-get-field-usage/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/operations-get-field-usage/index.js +39 -0
- package/dist/runtime/server/mcp/tools/operations-get-field-usage/types.d.ts +38 -0
- package/dist/runtime/server/mcp/tools/operations-get-field-usage/types.js +19 -0
- package/dist/runtime/server/mcp/tools/operations-get-source/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/operations-get-source/index.js +39 -0
- package/dist/runtime/server/mcp/tools/operations-get-source/types.d.ts +10 -0
- package/dist/runtime/server/mcp/tools/operations-get-source/types.js +9 -0
- package/dist/runtime/server/mcp/tools/operations-list/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/operations-list/index.js +46 -0
- package/dist/runtime/server/mcp/tools/operations-list/types.d.ts +53 -0
- package/dist/runtime/server/mcp/tools/operations-list/types.js +33 -0
- package/dist/runtime/server/mcp/tools/schema-get-interface-implementors/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-get-interface-implementors/index.js +37 -0
- package/dist/runtime/server/mcp/tools/schema-get-interface-implementors/types.d.ts +24 -0
- package/dist/runtime/server/mcp/tools/schema-get-interface-implementors/types.js +16 -0
- package/dist/runtime/server/mcp/tools/schema-get-type/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-get-type/index.js +31 -0
- package/dist/runtime/server/mcp/tools/schema-get-type/types.d.ts +112 -0
- package/dist/runtime/server/mcp/tools/schema-get-type/types.js +45 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-definition/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-definition/index.js +33 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-definition/types.d.ts +10 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-definition/types.js +9 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-usage/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-usage/index.js +35 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-usage/types.d.ts +39 -0
- package/dist/runtime/server/mcp/tools/schema-get-type-usage/types.js +17 -0
- package/dist/runtime/server/mcp/tools/schema-get-union-members/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-get-union-members/index.js +35 -0
- package/dist/runtime/server/mcp/tools/schema-get-union-members/types.d.ts +24 -0
- package/dist/runtime/server/mcp/tools/schema-get-union-members/types.js +16 -0
- package/dist/runtime/server/mcp/tools/schema-list-types/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-list-types/index.js +37 -0
- package/dist/runtime/server/mcp/tools/schema-list-types/types.d.ts +53 -0
- package/dist/runtime/server/mcp/tools/schema-list-types/types.js +21 -0
- package/dist/runtime/server/mcp/tools/schema-validate-document/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/schema-validate-document/index.js +31 -0
- package/dist/runtime/server/mcp/tools/schema-validate-document/types.d.ts +26 -0
- package/dist/runtime/server/mcp/tools/schema-validate-document/types.js +21 -0
- package/dist/runtime/server/mcp/tools/vue-graphql-composable-example/index.d.ts +1 -0
- package/dist/runtime/server/mcp/tools/vue-graphql-composable-example/index.js +36 -0
- package/dist/runtime/server/mcp/tools/vue-graphql-composable-example/types.d.ts +49 -0
- package/dist/runtime/server/mcp/tools/vue-graphql-composable-example/types.js +24 -0
- package/dist/runtime/server/mcp/utils/index.d.ts +48 -0
- package/dist/runtime/server/mcp/utils/index.js +35 -0
- package/dist/runtime/server/utils/useGraphqlMutation.d.ts +1 -1
- package/dist/runtime/server/utils/useGraphqlMutation.js +1 -1
- package/dist/runtime/server/utils/useGraphqlQuery.d.ts +1 -1
- package/dist/runtime/server/utils/useGraphqlQuery.js +1 -1
- package/dist/shared/{nuxt-graphql-middleware.ct2xvPoD.d.mts → nuxt-graphql-middleware.COufMnWs.d.mts} +119 -2
- package/dist/utils.d.mts +1 -1
- package/docs/composables/useAsyncGraphqlQuery.md +313 -0
- package/docs/composables/useGraphqlMutation.md +29 -0
- package/docs/composables/useGraphqlQuery.md +73 -0
- package/docs/composables/useGraphqlState.md +58 -0
- package/docs/composables/useGraphqlUploadMutation.md +57 -0
- package/docs/configuration/client-options.md +121 -0
- package/docs/configuration/module-hooks.md +112 -0
- package/docs/configuration/module-utils.md +53 -0
- package/docs/configuration/module.md +415 -0
- package/docs/configuration/runtime-config.md +23 -0
- package/docs/configuration/server-options.md +230 -0
- package/package.json +101 -44
- package/dist/client/_nuxt/Bkyil6hz.js +0 -2
- package/dist/client/_nuxt/C9p-Va5c.js +0 -29
- package/dist/client/_nuxt/builds/meta/77b9a31d-6d5c-4e28-9320-cbd287a46883.json +0 -1
- package/dist/runtime/server/tsconfig.json +0 -3
package/dist/module.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { fileURLToPath } from 'url';
|
|
2
|
-
import { useLogger, addTemplate, addServerTemplate,
|
|
3
|
-
import { existsSync, promises } from 'node:fs';
|
|
4
|
-
import { basename } from 'node:path';
|
|
2
|
+
import { useLogger, addTemplate, addServerTemplate, createResolver, resolveAlias, resolveFiles, addPlugin, addServerHandler, addImports, addServerImports, useNitro, defineNuxtModule, addDevServerHandler } from '@nuxt/kit';
|
|
3
|
+
import { existsSync, promises, readFileSync } from 'node:fs';
|
|
4
|
+
import { basename, join as join$1, dirname, isAbsolute, relative as relative$1 } from 'node:path';
|
|
5
5
|
import { relative, join } from 'pathe';
|
|
6
|
-
import { printSourceLocation, parse, Source, OperationTypeNode } from 'graphql';
|
|
6
|
+
import { printSourceLocation, parse, Source, OperationTypeNode, isObjectType, isInputObjectType, isEnumType, isUnionType, isInterfaceType, isScalarType, isNonNullType, isListType, printType, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
|
|
7
7
|
import { Generator, FieldNotFoundError, TypeNotFoundError, FragmentNotFoundError } from 'graphql-typescript-deluxe';
|
|
8
8
|
import color from 'picocolors';
|
|
9
9
|
import { validateGraphQlDocuments } from '@graphql-tools/utils';
|
|
@@ -18,9 +18,10 @@ import isUnicodeSupported from 'is-unicode-supported';
|
|
|
18
18
|
import { hash } from 'ohash';
|
|
19
19
|
import { existsSync as existsSync$1 } from 'fs';
|
|
20
20
|
import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
|
|
21
|
+
import { defineEventHandler, readBody, createError } from 'h3';
|
|
21
22
|
|
|
22
23
|
const name = "nuxt-graphql-middleware";
|
|
23
|
-
const version = "5.
|
|
24
|
+
const version = "5.3.1";
|
|
24
25
|
|
|
25
26
|
const logger = useLogger("nuxt-graphql-middleware");
|
|
26
27
|
const defaultOptions = {
|
|
@@ -33,6 +34,7 @@ const defaultOptions = {
|
|
|
33
34
|
documents: [],
|
|
34
35
|
devtools: true,
|
|
35
36
|
errorOverlay: true,
|
|
37
|
+
logOnlyErrors: true,
|
|
36
38
|
graphqlConfigFilePath: "./graphql.config.ts",
|
|
37
39
|
experimental: {
|
|
38
40
|
improvedQueryParamEncoding: false
|
|
@@ -40,6 +42,9 @@ const defaultOptions = {
|
|
|
40
42
|
clientCache: {
|
|
41
43
|
enabled: false,
|
|
42
44
|
maxSize: 100
|
|
45
|
+
},
|
|
46
|
+
mcp: {
|
|
47
|
+
enabled: false
|
|
43
48
|
}
|
|
44
49
|
};
|
|
45
50
|
function validateOptions(options) {
|
|
@@ -161,6 +166,8 @@ class Collector {
|
|
|
161
166
|
mappedOptions.output.buildTypeDocFilePath = (filePath) => {
|
|
162
167
|
if (filePath.startsWith("/")) {
|
|
163
168
|
return this.filePathToBuildRelative(filePath);
|
|
169
|
+
} else if (filePath.startsWith("hook:")) {
|
|
170
|
+
return "./../nuxt-graphql-middleware/hook-documents.graphql";
|
|
164
171
|
}
|
|
165
172
|
return filePath;
|
|
166
173
|
};
|
|
@@ -199,6 +206,14 @@ class Collector {
|
|
|
199
206
|
* The generated template contents.
|
|
200
207
|
*/
|
|
201
208
|
templateResult = /* @__PURE__ */ new Map();
|
|
209
|
+
/**
|
|
210
|
+
* Operations with full metadata for MCP tools.
|
|
211
|
+
*/
|
|
212
|
+
operations = [];
|
|
213
|
+
/**
|
|
214
|
+
* Fragments with full metadata for MCP tools.
|
|
215
|
+
*/
|
|
216
|
+
fragments = [];
|
|
202
217
|
isInitialised = false;
|
|
203
218
|
async reset() {
|
|
204
219
|
this.files.clear();
|
|
@@ -218,6 +233,9 @@ class Collector {
|
|
|
218
233
|
filePathToSourceRelative(filePath) {
|
|
219
234
|
if (filePath.startsWith("/")) {
|
|
220
235
|
return "./" + relative(process.cwd(), filePath);
|
|
236
|
+
} else if (filePath.startsWith("hook:")) {
|
|
237
|
+
const hookPathAbsolute = this.helper.paths.moduleBuildDir + "/hook-documents.graphql";
|
|
238
|
+
return "./" + relative(process.cwd(), hookPathAbsolute);
|
|
221
239
|
}
|
|
222
240
|
return filePath;
|
|
223
241
|
}
|
|
@@ -292,7 +310,7 @@ class Collector {
|
|
|
292
310
|
} else {
|
|
293
311
|
this.operationTimestamps.set(operation.graphqlName, operation.timestamp);
|
|
294
312
|
}
|
|
295
|
-
const shouldLog = errors.length || !this.helper.options.logOnlyErrors;
|
|
313
|
+
const shouldLog = errors.length || !this.helper.isPrepare && !this.helper.options.logOnlyErrors;
|
|
296
314
|
if (shouldLog) {
|
|
297
315
|
logEntries.push(this.operationToLogEntry(operation, errors));
|
|
298
316
|
}
|
|
@@ -306,6 +324,40 @@ class Collector {
|
|
|
306
324
|
throw new Error("GraphQL errors");
|
|
307
325
|
}
|
|
308
326
|
await this.helper.nuxt.callHook("nuxt-graphql-middleware:build", { output });
|
|
327
|
+
if (this.helper.isDev) {
|
|
328
|
+
this.operations = operations.map((op) => {
|
|
329
|
+
const fragmentDeps = op.getGraphQLFragmentDependencies().map((name) => fragmentMap.get(name) || "").join("\n");
|
|
330
|
+
const source = operationSourceMap.get(op.graphqlName) || "";
|
|
331
|
+
const sourceFull = [source, fragmentDeps].join("\n");
|
|
332
|
+
return {
|
|
333
|
+
name: op.graphqlName,
|
|
334
|
+
type: op.operationType,
|
|
335
|
+
filePath: op.filePath,
|
|
336
|
+
relativeFilePath: this.filePathToSourceRelative(op.filePath),
|
|
337
|
+
hasVariables: op.hasVariables,
|
|
338
|
+
needsVariables: op.needsVariables,
|
|
339
|
+
variablesTypeName: op.variablesTypeName,
|
|
340
|
+
responseTypeName: op.typeName,
|
|
341
|
+
source,
|
|
342
|
+
sourceFull
|
|
343
|
+
};
|
|
344
|
+
});
|
|
345
|
+
const outputFragments = output.getFragments();
|
|
346
|
+
this.fragments = outputFragments.map((frag) => {
|
|
347
|
+
const source = fragmentMap.get(frag.node.name.value) || "";
|
|
348
|
+
const fragmentDeps = frag.getGraphQLFragmentDependencies().map((name) => fragmentMap.get(name) || "").join("\n");
|
|
349
|
+
const sourceFull = [source, fragmentDeps].join("\n");
|
|
350
|
+
return {
|
|
351
|
+
name: frag.node.name.value,
|
|
352
|
+
typeName: frag.node.typeCondition.name.value,
|
|
353
|
+
filePath: frag.filePath,
|
|
354
|
+
relativeFilePath: this.filePathToSourceRelative(frag.filePath),
|
|
355
|
+
source,
|
|
356
|
+
sourceFull,
|
|
357
|
+
dependencies: frag.getGraphQLFragmentDependencies()
|
|
358
|
+
};
|
|
359
|
+
});
|
|
360
|
+
}
|
|
309
361
|
if (this.helper.isDev) {
|
|
310
362
|
for (const code of generatedCode) {
|
|
311
363
|
const id = `${code.identifier}_${code.graphqlName}`;
|
|
@@ -313,7 +365,7 @@ class Collector {
|
|
|
313
365
|
if (this.rpcItems.get(id)?.timestamp === code.timestamp) {
|
|
314
366
|
continue;
|
|
315
367
|
}
|
|
316
|
-
const fragmentDepdendencies = code.getGraphQLFragmentDependencies().map((name) => fragmentMap.get(name) || "").join("\n
|
|
368
|
+
const fragmentDepdendencies = code.getGraphQLFragmentDependencies().map((name) => fragmentMap.get(name) || "").join("\n");
|
|
317
369
|
this.rpcItems.set(id, {
|
|
318
370
|
id,
|
|
319
371
|
timestamp: code.timestamp,
|
|
@@ -426,7 +478,9 @@ class Collector {
|
|
|
426
478
|
await this.addFile(filePath);
|
|
427
479
|
}
|
|
428
480
|
await this.buildState();
|
|
429
|
-
|
|
481
|
+
if (!this.helper.isPrepare) {
|
|
482
|
+
logger.success("All GraphQL documents are valid.");
|
|
483
|
+
}
|
|
430
484
|
} catch (e) {
|
|
431
485
|
this.logError(e);
|
|
432
486
|
throw new Error("GraphQL document validation failed.");
|
|
@@ -586,16 +640,10 @@ class Collector {
|
|
|
586
640
|
if (template.buildTypes) {
|
|
587
641
|
const path = template.options.path;
|
|
588
642
|
const filename = template.options.path + ".d.ts";
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
getContents: () => this.getTemplate(path, "types")
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
nuxt: true,
|
|
597
|
-
nitro: true
|
|
598
|
-
}
|
|
643
|
+
this.helper.registerTypeTemplate(
|
|
644
|
+
filename,
|
|
645
|
+
() => this.getTemplate(path, "types"),
|
|
646
|
+
template.options.context
|
|
599
647
|
);
|
|
600
648
|
}
|
|
601
649
|
}
|
|
@@ -616,6 +664,30 @@ class Collector {
|
|
|
616
664
|
getHookFiles() {
|
|
617
665
|
return [...this.hookFiles.values()];
|
|
618
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* Get all operations with metadata (for MCP tools).
|
|
669
|
+
*/
|
|
670
|
+
getOperations() {
|
|
671
|
+
return this.operations;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Get all fragments for a specific GraphQL type (for MCP tools).
|
|
675
|
+
*/
|
|
676
|
+
getFragmentsForType(typeName) {
|
|
677
|
+
return this.fragments.filter((frag) => frag.typeName === typeName);
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Get all fragments (for MCP tools).
|
|
681
|
+
*/
|
|
682
|
+
getFragments() {
|
|
683
|
+
return this.fragments;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Get a fragment by name (for MCP tools).
|
|
687
|
+
*/
|
|
688
|
+
getFragment(name) {
|
|
689
|
+
return this.fragments.find((frag) => frag.name === name);
|
|
690
|
+
}
|
|
619
691
|
}
|
|
620
692
|
|
|
621
693
|
class SchemaProvider {
|
|
@@ -667,7 +739,11 @@ class SchemaProvider {
|
|
|
667
739
|
);
|
|
668
740
|
throw new Error("Missing GraphQL schema.");
|
|
669
741
|
}
|
|
670
|
-
|
|
742
|
+
if (!this.helper.isPrepare) {
|
|
743
|
+
logger.info(
|
|
744
|
+
`Loading GraphQL schema from disk: ${this.helper.paths.schema}`
|
|
745
|
+
);
|
|
746
|
+
}
|
|
671
747
|
return await fs.readFile(this.helper.paths.schema).then((v) => v.toString());
|
|
672
748
|
}
|
|
673
749
|
/**
|
|
@@ -720,7 +796,7 @@ class SchemaProvider {
|
|
|
720
796
|
* @param forceDownload - Forces downloading the schema.
|
|
721
797
|
*/
|
|
722
798
|
async loadSchema(opts) {
|
|
723
|
-
if (opts?.forceDisk) {
|
|
799
|
+
if (opts?.forceDisk || this.helper.isPrepare) {
|
|
724
800
|
this.schemaContent = await this.loadSchemaFromDisk();
|
|
725
801
|
} else if (this.helper.options.downloadSchema || opts?.forceDownload) {
|
|
726
802
|
this.schemaContent = await this.downloadSchema();
|
|
@@ -817,9 +893,72 @@ ${color.cyan(S_BAR_END)}
|
|
|
817
893
|
}
|
|
818
894
|
}
|
|
819
895
|
|
|
896
|
+
function defineImport(name, description, context) {
|
|
897
|
+
const docsPath = context === "nuxt" ? "composables" : "server-utils";
|
|
898
|
+
return {
|
|
899
|
+
name,
|
|
900
|
+
description,
|
|
901
|
+
context,
|
|
902
|
+
docsUrl: `https://nuxt-graphql-middleware.dulnan.net/${docsPath}/${name}.html`
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
const useGraphqlQuery = defineImport(
|
|
906
|
+
"useGraphqlQuery",
|
|
907
|
+
"Perform a GraphQL query via the middleware. Returns a promise. Can be used anywhere - in components, plugins, other composables, event handlers, or inside useAsyncData.",
|
|
908
|
+
"nuxt"
|
|
909
|
+
);
|
|
910
|
+
const useAsyncGraphqlQuery = defineImport(
|
|
911
|
+
"useAsyncGraphqlQuery",
|
|
912
|
+
"SSR-compatible, reactive data fetching. Must be called at the root of a component setup or inside another composable. Same limitations as useAsyncData.",
|
|
913
|
+
"nuxt"
|
|
914
|
+
);
|
|
915
|
+
const useGraphqlMutation = defineImport(
|
|
916
|
+
"useGraphqlMutation",
|
|
917
|
+
"Perform a GraphQL mutation via the middleware. Returns a promise. Can be used anywhere - in components, plugins, other composables, or event handlers.",
|
|
918
|
+
"nuxt"
|
|
919
|
+
);
|
|
920
|
+
const useGraphqlUploadMutation = defineImport(
|
|
921
|
+
"useGraphqlUploadMutation",
|
|
922
|
+
"Perform a GraphQL mutation via the middleware with support for file uploads. Returns a promise. Can be used anywhere - in components, plugins, other composables, or event handlers.",
|
|
923
|
+
"nuxt"
|
|
924
|
+
);
|
|
925
|
+
const useGraphqlState = defineImport(
|
|
926
|
+
"useGraphqlState",
|
|
927
|
+
"allows you to set fetch options for the useGraphqlQuery, useAsyncGraphqlQuery and useGraphqlMutation composables. One common use case is to pass custom request headers to the GraphQL middleware request.",
|
|
928
|
+
"nuxt"
|
|
929
|
+
);
|
|
930
|
+
const COMPOSABLES = {
|
|
931
|
+
useGraphqlQuery,
|
|
932
|
+
useGraphqlMutation,
|
|
933
|
+
useAsyncGraphqlQuery,
|
|
934
|
+
useGraphqlUploadMutation,
|
|
935
|
+
useGraphqlState
|
|
936
|
+
};
|
|
937
|
+
const serverUseGraphqlQuery = defineImport(
|
|
938
|
+
"useGraphqlQuery",
|
|
939
|
+
"Perform a GraphQL query via the middleware in a Nitro server context. Auto-imported and available in event handlers, server plugins, and other server-side code.",
|
|
940
|
+
"nitro"
|
|
941
|
+
);
|
|
942
|
+
const serverUseGraphqlMutation = defineImport(
|
|
943
|
+
"useGraphqlMutation",
|
|
944
|
+
"Perform a GraphQL mutation via the middleware in a Nitro server context. Auto-imported and available in event handlers, server plugins, and other server-side code.",
|
|
945
|
+
"nitro"
|
|
946
|
+
);
|
|
947
|
+
const doGraphqlRequest = defineImport(
|
|
948
|
+
"doGraphqlRequest",
|
|
949
|
+
"Perform a raw GraphQL request in a Nitro server context. Provides low-level access to execute arbitrary GraphQL queries and mutations.",
|
|
950
|
+
"nitro"
|
|
951
|
+
);
|
|
952
|
+
const SERVER_UTILS = {
|
|
953
|
+
useGraphqlQuery: serverUseGraphqlQuery,
|
|
954
|
+
useGraphqlMutation: serverUseGraphqlMutation,
|
|
955
|
+
doGraphqlRequest
|
|
956
|
+
};
|
|
957
|
+
|
|
820
958
|
class ModuleHelper {
|
|
821
959
|
constructor(nuxt, moduleUrl, options) {
|
|
822
960
|
this.nuxt = nuxt;
|
|
961
|
+
this.isPrepare = nuxt.options._prepare;
|
|
823
962
|
const mergedOptions = defu(
|
|
824
963
|
{},
|
|
825
964
|
options,
|
|
@@ -897,6 +1036,7 @@ class ModuleHelper {
|
|
|
897
1036
|
resolvers;
|
|
898
1037
|
paths;
|
|
899
1038
|
isDev;
|
|
1039
|
+
isPrepare;
|
|
900
1040
|
options;
|
|
901
1041
|
prompt = new ConsolePrompt();
|
|
902
1042
|
nitroExternals = [];
|
|
@@ -926,7 +1066,9 @@ class ModuleHelper {
|
|
|
926
1066
|
);
|
|
927
1067
|
}
|
|
928
1068
|
}
|
|
929
|
-
|
|
1069
|
+
if (!this.isPrepare) {
|
|
1070
|
+
logger.info("No graphqlMiddleware.serverOptions file found.");
|
|
1071
|
+
}
|
|
930
1072
|
return null;
|
|
931
1073
|
}
|
|
932
1074
|
findClientOptions() {
|
|
@@ -1029,10 +1171,38 @@ ${content.trim()}`;
|
|
|
1029
1171
|
template.buildTypes(this)
|
|
1030
1172
|
);
|
|
1031
1173
|
const filename = template.options.path + ".d.ts";
|
|
1032
|
-
|
|
1174
|
+
this.registerTypeTemplate(
|
|
1033
1175
|
filename,
|
|
1034
|
-
|
|
1035
|
-
|
|
1176
|
+
() => content,
|
|
1177
|
+
template.options.context
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Register a type template without adding to globalTypeFiles.
|
|
1183
|
+
*
|
|
1184
|
+
* Uses addTemplate instead of addTypeTemplate to avoid Vue compiler-sfc
|
|
1185
|
+
* issue where exported types from globalTypeFiles cannot be resolved.
|
|
1186
|
+
* @see https://github.com/nuxt/nuxt/issues/33694
|
|
1187
|
+
*/
|
|
1188
|
+
registerTypeTemplate(filename, getContents, context) {
|
|
1189
|
+
const resolvedTemplate = addTemplate({
|
|
1190
|
+
filename,
|
|
1191
|
+
write: true,
|
|
1192
|
+
getContents
|
|
1193
|
+
});
|
|
1194
|
+
const forNuxt = context === "nuxt" || context === "both";
|
|
1195
|
+
const forNitro = context === "nitro" || context === "both";
|
|
1196
|
+
if (forNuxt) {
|
|
1197
|
+
this.nuxt.hook("prepare:types", (payload) => {
|
|
1198
|
+
payload.references ||= [];
|
|
1199
|
+
payload.references.push({ path: resolvedTemplate.dst });
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
if (forNitro) {
|
|
1203
|
+
this.nuxt.hook("nitro:prepare:types", (payload) => {
|
|
1204
|
+
payload.references ||= [];
|
|
1205
|
+
payload.references.push({ path: resolvedTemplate.dst });
|
|
1036
1206
|
});
|
|
1037
1207
|
}
|
|
1038
1208
|
}
|
|
@@ -1049,16 +1219,26 @@ ${content.trim()}`;
|
|
|
1049
1219
|
});
|
|
1050
1220
|
}
|
|
1051
1221
|
addComposable(name) {
|
|
1222
|
+
const composable = COMPOSABLES[name];
|
|
1052
1223
|
addImports({
|
|
1053
1224
|
from: this.resolvers.module.resolve("./runtime/composables/" + name),
|
|
1054
|
-
name
|
|
1225
|
+
name,
|
|
1226
|
+
meta: {
|
|
1227
|
+
description: composable.description,
|
|
1228
|
+
docsUrl: composable.docsUrl
|
|
1229
|
+
}
|
|
1055
1230
|
});
|
|
1056
1231
|
}
|
|
1057
1232
|
addServerUtil(name) {
|
|
1233
|
+
const serverUtil = SERVER_UTILS[name];
|
|
1058
1234
|
addServerImports([
|
|
1059
1235
|
{
|
|
1060
1236
|
from: this.resolvers.module.resolve("./runtime/server/utils/" + name),
|
|
1061
|
-
name
|
|
1237
|
+
name,
|
|
1238
|
+
meta: {
|
|
1239
|
+
description: serverUtil.description,
|
|
1240
|
+
docsUrl: serverUtil.docsUrl
|
|
1241
|
+
}
|
|
1062
1242
|
}
|
|
1063
1243
|
]);
|
|
1064
1244
|
}
|
|
@@ -1082,7 +1262,7 @@ function defineStaticTemplate(options, build, buildTypes) {
|
|
|
1082
1262
|
}
|
|
1083
1263
|
|
|
1084
1264
|
const ClientOptions = defineStaticTemplate(
|
|
1085
|
-
{ path: "nuxt-graphql-middleware/client-options" },
|
|
1265
|
+
{ path: "nuxt-graphql-middleware/client-options", context: "both" },
|
|
1086
1266
|
(helper) => {
|
|
1087
1267
|
if (helper.paths.clientOptions) {
|
|
1088
1268
|
const pathRelative = helper.toModuleBuildRelative(
|
|
@@ -1102,21 +1282,21 @@ export { clientOptions }
|
|
|
1102
1282
|
return `import type { GraphqlClientOptions } from '${helper.paths.runtimeTypes}'
|
|
1103
1283
|
import clientOptionsImport from '${pathRelative}'
|
|
1104
1284
|
|
|
1105
|
-
declare
|
|
1285
|
+
export declare const clientOptions: GraphqlClientOptions|undefined
|
|
1106
1286
|
export type GraphqlClientContext = typeof clientOptionsImport extends GraphqlClientOptions<infer R> ? R : {}
|
|
1107
1287
|
`;
|
|
1108
1288
|
}
|
|
1109
1289
|
return `
|
|
1110
1290
|
import type { GraphqlClientOptions } from '${helper.paths.runtimeTypes}'
|
|
1111
1291
|
|
|
1112
|
-
declare
|
|
1292
|
+
export declare const clientOptions: GraphqlClientOptions|undefined
|
|
1113
1293
|
export type GraphqlClientContext = {}
|
|
1114
1294
|
`;
|
|
1115
1295
|
}
|
|
1116
1296
|
);
|
|
1117
1297
|
|
|
1118
1298
|
const Config = defineStaticTemplate(
|
|
1119
|
-
{ path: "nuxt-graphql-middleware/config" },
|
|
1299
|
+
{ path: "nuxt-graphql-middleware/config", context: "both" },
|
|
1120
1300
|
(helper) => {
|
|
1121
1301
|
const experimentalQueryParamEncoding = !!helper.options.experimental.improvedQueryParamEncoding;
|
|
1122
1302
|
const clientCacheEnabledAtBuild = !!helper.options.clientCache.enabled;
|
|
@@ -1129,16 +1309,20 @@ export const importMetaClient = import.meta.client
|
|
|
1129
1309
|
},
|
|
1130
1310
|
() => {
|
|
1131
1311
|
return `
|
|
1132
|
-
declare
|
|
1133
|
-
declare
|
|
1134
|
-
declare
|
|
1135
|
-
declare
|
|
1312
|
+
export declare const experimentalQueryParamEncoding: boolean
|
|
1313
|
+
export declare const clientCacheEnabledAtBuild: boolean
|
|
1314
|
+
export declare const importMetaServer: boolean
|
|
1315
|
+
export declare const importMetaClient: boolean
|
|
1136
1316
|
`;
|
|
1137
1317
|
}
|
|
1138
1318
|
);
|
|
1139
1319
|
|
|
1140
1320
|
const Documents = defineGeneratorTemplate(
|
|
1141
|
-
{
|
|
1321
|
+
{
|
|
1322
|
+
path: "nuxt-graphql-middleware/documents",
|
|
1323
|
+
virtual: true,
|
|
1324
|
+
context: "nitro"
|
|
1325
|
+
},
|
|
1142
1326
|
(output, helper) => {
|
|
1143
1327
|
return output.getOperationsFile({
|
|
1144
1328
|
exportName: "documents",
|
|
@@ -1160,7 +1344,7 @@ declare module '#nuxt-graphql-middleware/documents' {
|
|
|
1160
1344
|
);
|
|
1161
1345
|
|
|
1162
1346
|
const GraphqlConfig = defineStaticTemplate(
|
|
1163
|
-
{ path: "nuxt-graphql-middleware/graphql.config" },
|
|
1347
|
+
{ path: "nuxt-graphql-middleware/graphql.config", context: "nuxt" },
|
|
1164
1348
|
(helper) => {
|
|
1165
1349
|
const patterns = helper.options.autoImportPatterns || [];
|
|
1166
1350
|
const configPath = helper.resolvers.root.resolve(
|
|
@@ -1203,15 +1387,15 @@ import type { IGraphQLProject } from 'graphql-config'
|
|
|
1203
1387
|
|
|
1204
1388
|
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
|
1205
1389
|
|
|
1206
|
-
const config: WithRequired<IGraphQLProject, 'schema' | 'documents'
|
|
1390
|
+
declare const config: WithRequired<IGraphQLProject, 'schema' | 'documents'>
|
|
1207
1391
|
|
|
1208
|
-
export default config
|
|
1392
|
+
export default config
|
|
1209
1393
|
`;
|
|
1210
1394
|
}
|
|
1211
1395
|
);
|
|
1212
1396
|
|
|
1213
1397
|
const Helpers = defineStaticTemplate(
|
|
1214
|
-
{ path: "nuxt-graphql-middleware/helpers" },
|
|
1398
|
+
{ path: "nuxt-graphql-middleware/helpers", context: "both" },
|
|
1215
1399
|
(helper) => {
|
|
1216
1400
|
return `export const serverApiPrefix = '${helper.options.serverApiPrefix}'
|
|
1217
1401
|
export function getEndpoint(operation, operationName) {
|
|
@@ -1220,8 +1404,8 @@ export function getEndpoint(operation, operationName) {
|
|
|
1220
1404
|
`;
|
|
1221
1405
|
},
|
|
1222
1406
|
() => {
|
|
1223
|
-
return `export const serverApiPrefix: string
|
|
1224
|
-
export function getEndpoint(operation: string, operationName: string): string`;
|
|
1407
|
+
return `export declare const serverApiPrefix: string
|
|
1408
|
+
export declare function getEndpoint(operation: string, operationName: string): string`;
|
|
1225
1409
|
}
|
|
1226
1410
|
);
|
|
1227
1411
|
|
|
@@ -1229,7 +1413,8 @@ const HookDocuments = defineGeneratorTemplate(
|
|
|
1229
1413
|
{
|
|
1230
1414
|
path: "nuxt-graphql-middleware/hook-documents.graphql",
|
|
1231
1415
|
virtual: false,
|
|
1232
|
-
isFullPath: true
|
|
1416
|
+
isFullPath: true,
|
|
1417
|
+
context: "nuxt"
|
|
1233
1418
|
},
|
|
1234
1419
|
(_output, _helper, collector) => {
|
|
1235
1420
|
return collector.getHookDocuments().map((v) => {
|
|
@@ -1245,7 +1430,8 @@ ${v.source}
|
|
|
1245
1430
|
const HookFiles = defineGeneratorTemplate(
|
|
1246
1431
|
{
|
|
1247
1432
|
path: "nuxt-graphql-middleware/hook-files",
|
|
1248
|
-
virtual: false
|
|
1433
|
+
virtual: false,
|
|
1434
|
+
context: "nuxt"
|
|
1249
1435
|
},
|
|
1250
1436
|
(_output, helper, collector) => {
|
|
1251
1437
|
const configPath = helper.resolvers.root.resolve(
|
|
@@ -1259,11 +1445,13 @@ const HookFiles = defineGeneratorTemplate(
|
|
|
1259
1445
|
});
|
|
1260
1446
|
return `export const hookFiles = ${JSON.stringify(files, null, 2)}`;
|
|
1261
1447
|
},
|
|
1262
|
-
|
|
1448
|
+
() => {
|
|
1449
|
+
return `export declare const hookFiles: string[]`;
|
|
1450
|
+
}
|
|
1263
1451
|
);
|
|
1264
1452
|
|
|
1265
1453
|
const NitroTypes = defineGeneratorTemplate(
|
|
1266
|
-
{ path: "nuxt-graphql-middleware/nitro" },
|
|
1454
|
+
{ path: "nuxt-graphql-middleware/nitro", context: "nitro" },
|
|
1267
1455
|
null,
|
|
1268
1456
|
(output, helper) => {
|
|
1269
1457
|
const operations = output.getCollectedOperations();
|
|
@@ -1293,7 +1481,11 @@ ${endpoints.sort().join("\n")}
|
|
|
1293
1481
|
);
|
|
1294
1482
|
|
|
1295
1483
|
const OperationHashes = defineGeneratorTemplate(
|
|
1296
|
-
{
|
|
1484
|
+
{
|
|
1485
|
+
path: "nuxt-graphql-middleware/operation-hashes",
|
|
1486
|
+
virtual: true,
|
|
1487
|
+
context: "nuxt"
|
|
1488
|
+
},
|
|
1297
1489
|
(output, helper) => {
|
|
1298
1490
|
if (helper.isDev) {
|
|
1299
1491
|
return `export const operationHashes = {}`;
|
|
@@ -1333,7 +1525,7 @@ declare module '#nuxt-graphql-middleware/operation-hashes' {
|
|
|
1333
1525
|
);
|
|
1334
1526
|
|
|
1335
1527
|
const OperationTypesAll = defineGeneratorTemplate(
|
|
1336
|
-
{ path: "nuxt-graphql-middleware/operation-types" },
|
|
1528
|
+
{ path: "nuxt-graphql-middleware/operation-types", context: "both" },
|
|
1337
1529
|
() => `export {}`,
|
|
1338
1530
|
(output) => {
|
|
1339
1531
|
return output.getOperationTypesFile({
|
|
@@ -1343,7 +1535,7 @@ const OperationTypesAll = defineGeneratorTemplate(
|
|
|
1343
1535
|
);
|
|
1344
1536
|
|
|
1345
1537
|
const Operations = defineGeneratorTemplate(
|
|
1346
|
-
{ path: "graphql-operations/index" },
|
|
1538
|
+
{ path: "graphql-operations/index", context: "both" },
|
|
1347
1539
|
(output) => {
|
|
1348
1540
|
const typesFile = output.getOperations("js");
|
|
1349
1541
|
return typesFile.getSource();
|
|
@@ -1355,7 +1547,7 @@ const Operations = defineGeneratorTemplate(
|
|
|
1355
1547
|
);
|
|
1356
1548
|
|
|
1357
1549
|
const OperationVariables = defineGeneratorTemplate(
|
|
1358
|
-
{ path: "nuxt-graphql-middleware/operation-variables" },
|
|
1550
|
+
{ path: "nuxt-graphql-middleware/operation-variables", context: "nitro" },
|
|
1359
1551
|
(output) => {
|
|
1360
1552
|
const operations = output.getCollectedOperations().reduce((acc, collectedOperation) => {
|
|
1361
1553
|
const node = collectedOperation.node;
|
|
@@ -1368,13 +1560,13 @@ const OperationVariables = defineGeneratorTemplate(
|
|
|
1368
1560
|
},
|
|
1369
1561
|
() => {
|
|
1370
1562
|
return `
|
|
1371
|
-
declare
|
|
1563
|
+
export declare const operationVariables: Record<string, string[]>
|
|
1372
1564
|
`;
|
|
1373
1565
|
}
|
|
1374
1566
|
);
|
|
1375
1567
|
|
|
1376
1568
|
const Response = defineGeneratorTemplate(
|
|
1377
|
-
{ path: "nuxt-graphql-middleware/response" },
|
|
1569
|
+
{ path: "nuxt-graphql-middleware/response", context: "both" },
|
|
1378
1570
|
null,
|
|
1379
1571
|
(output, helper) => {
|
|
1380
1572
|
const operations = output.getCollectedOperations();
|
|
@@ -1396,7 +1588,7 @@ declare module '#nuxt-graphql-middleware/response' {
|
|
|
1396
1588
|
);
|
|
1397
1589
|
|
|
1398
1590
|
const ServerOptions = defineStaticTemplate(
|
|
1399
|
-
{ path: "nuxt-graphql-middleware/server-options" },
|
|
1591
|
+
{ path: "nuxt-graphql-middleware/server-options", context: "both" },
|
|
1400
1592
|
(helper) => {
|
|
1401
1593
|
const resolvedPathRelative = helper.paths.serverOptions ? helper.toModuleBuildRelative(helper.paths.serverOptions) : null;
|
|
1402
1594
|
const serverOptionsLine = resolvedPathRelative ? `import serverOptions from '${resolvedPathRelative}'` : `const serverOptions = {}`;
|
|
@@ -1418,13 +1610,13 @@ type AdditionsFromServerOptions = typeof serverOptionsImport extends GraphqlMidd
|
|
|
1418
1610
|
|
|
1419
1611
|
export type GraphqlResponseAdditions = Omit<AdditionsFromServerOptions, 'data' | 'errors'>
|
|
1420
1612
|
|
|
1421
|
-
declare
|
|
1613
|
+
export declare const serverOptions: GraphqlMiddlewareServerOptions
|
|
1422
1614
|
`;
|
|
1423
1615
|
}
|
|
1424
1616
|
return `
|
|
1425
1617
|
import type { GraphqlMiddlewareServerOptions } from '${helper.paths.runtimeTypes}'
|
|
1426
1618
|
|
|
1427
|
-
declare
|
|
1619
|
+
export declare const serverOptions: GraphqlMiddlewareServerOptions
|
|
1428
1620
|
|
|
1429
1621
|
export type GraphqlResponseAdditions = object
|
|
1430
1622
|
`;
|
|
@@ -1432,7 +1624,7 @@ export type GraphqlResponseAdditions = object
|
|
|
1432
1624
|
);
|
|
1433
1625
|
|
|
1434
1626
|
const Sources = defineGeneratorTemplate(
|
|
1435
|
-
{ path: "nuxt-graphql-middleware/sources" },
|
|
1627
|
+
{ path: "nuxt-graphql-middleware/sources", context: "nuxt" },
|
|
1436
1628
|
(output, helper) => {
|
|
1437
1629
|
const operations = output.getCollectedOperations();
|
|
1438
1630
|
const srcDir = helper.paths.root;
|
|
@@ -1450,7 +1642,125 @@ export const operationSources = {
|
|
|
1450
1642
|
`;
|
|
1451
1643
|
},
|
|
1452
1644
|
() => {
|
|
1453
|
-
return `export const operationSources: Record<string, string>`;
|
|
1645
|
+
return `export declare const operationSources: Record<string, string>`;
|
|
1646
|
+
}
|
|
1647
|
+
);
|
|
1648
|
+
|
|
1649
|
+
const DOCS = [
|
|
1650
|
+
// Composables
|
|
1651
|
+
{
|
|
1652
|
+
path: "composables/useGraphqlQuery",
|
|
1653
|
+
file: "composables/useGraphqlQuery.md",
|
|
1654
|
+
name: "useGraphqlQuery",
|
|
1655
|
+
description: "Execute a GraphQL query using $fetch"
|
|
1656
|
+
},
|
|
1657
|
+
{
|
|
1658
|
+
path: "composables/useGraphqlMutation",
|
|
1659
|
+
file: "composables/useGraphqlMutation.md",
|
|
1660
|
+
name: "useGraphqlMutation",
|
|
1661
|
+
description: "Execute a GraphQL mutation using $fetch"
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
path: "composables/useAsyncGraphqlQuery",
|
|
1665
|
+
file: "composables/useAsyncGraphqlQuery.md",
|
|
1666
|
+
name: "useAsyncGraphqlQuery",
|
|
1667
|
+
description: "SSR-compatible GraphQL query with useAsyncData"
|
|
1668
|
+
},
|
|
1669
|
+
{
|
|
1670
|
+
path: "composables/useGraphqlState",
|
|
1671
|
+
file: "composables/useGraphqlState.md",
|
|
1672
|
+
name: "useGraphqlState",
|
|
1673
|
+
description: "Access cached GraphQL query state"
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
path: "composables/useGraphqlUploadMutation",
|
|
1677
|
+
file: "composables/useGraphqlUploadMutation.md",
|
|
1678
|
+
name: "useGraphqlUploadMutation",
|
|
1679
|
+
description: "GraphQL mutation with file upload support"
|
|
1680
|
+
},
|
|
1681
|
+
// Configuration
|
|
1682
|
+
{
|
|
1683
|
+
path: "configuration/module",
|
|
1684
|
+
file: "configuration/module.md",
|
|
1685
|
+
name: "Module Configuration",
|
|
1686
|
+
description: "Configure the nuxt-graphql-middleware module options"
|
|
1687
|
+
},
|
|
1688
|
+
{
|
|
1689
|
+
path: "configuration/client-options",
|
|
1690
|
+
file: "configuration/client-options.md",
|
|
1691
|
+
name: "Client Options",
|
|
1692
|
+
description: "Configure client-side GraphQL request behavior"
|
|
1693
|
+
},
|
|
1694
|
+
{
|
|
1695
|
+
path: "configuration/server-options",
|
|
1696
|
+
file: "configuration/server-options.md",
|
|
1697
|
+
name: "Server Options",
|
|
1698
|
+
description: "Configure server-side GraphQL request handling"
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
path: "configuration/module-hooks",
|
|
1702
|
+
file: "configuration/module-hooks.md",
|
|
1703
|
+
name: "Module Hooks",
|
|
1704
|
+
description: "Use Nuxt hooks to customize module behavior"
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
path: "configuration/module-utils",
|
|
1708
|
+
file: "configuration/module-utils.md",
|
|
1709
|
+
name: "Module Utils",
|
|
1710
|
+
description: "Utility functions for working with the module"
|
|
1711
|
+
},
|
|
1712
|
+
{
|
|
1713
|
+
path: "configuration/runtime-config",
|
|
1714
|
+
file: "configuration/runtime-config.md",
|
|
1715
|
+
name: "Runtime Config",
|
|
1716
|
+
description: "Configure runtime settings via Nuxt runtime config"
|
|
1717
|
+
}
|
|
1718
|
+
];
|
|
1719
|
+
const MCP = defineStaticTemplate(
|
|
1720
|
+
{ path: "nuxt-graphql-middleware/mcp", context: "nitro" },
|
|
1721
|
+
(helper) => {
|
|
1722
|
+
const mcpServerRoute = helper.options.mcp.route ?? "/mcp/nuxt-graphql-middleware";
|
|
1723
|
+
const devServerUrl = helper.isDev ? `http://${helper.nuxt.options.devServer.host || "localhost"}:${helper.nuxt.options.devServer.port || 3e3}` : "";
|
|
1724
|
+
const docsDir = helper.resolvers.module.resolve("../docs");
|
|
1725
|
+
const entries = [];
|
|
1726
|
+
if (helper.isDev || helper.isPrepare) {
|
|
1727
|
+
for (const doc of DOCS) {
|
|
1728
|
+
const filePath = join$1(docsDir, doc.file);
|
|
1729
|
+
try {
|
|
1730
|
+
const content = readFileSync(filePath, "utf-8");
|
|
1731
|
+
entries.push({
|
|
1732
|
+
uri: `docs://${doc.path}`,
|
|
1733
|
+
name: doc.name,
|
|
1734
|
+
description: doc.description,
|
|
1735
|
+
content
|
|
1736
|
+
});
|
|
1737
|
+
} catch {
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
const includeComposables = !!helper.options.includeComposables;
|
|
1742
|
+
return `
|
|
1743
|
+
export const mcpServerRoute = ${JSON.stringify(mcpServerRoute)}
|
|
1744
|
+
export const devServerUrl = ${JSON.stringify(devServerUrl)}
|
|
1745
|
+
export const includeComposables = ${JSON.stringify(includeComposables)}
|
|
1746
|
+
export const docs = ${JSON.stringify(entries, null, 2)}
|
|
1747
|
+
`;
|
|
1748
|
+
},
|
|
1749
|
+
() => {
|
|
1750
|
+
return `
|
|
1751
|
+
export declare const mcpServerRoute: string
|
|
1752
|
+
export declare const devServerUrl: string
|
|
1753
|
+
export declare const includeComposables: boolean
|
|
1754
|
+
|
|
1755
|
+
export type Doc = {
|
|
1756
|
+
uri: string
|
|
1757
|
+
name: string
|
|
1758
|
+
description: string
|
|
1759
|
+
content: string
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
export declare const docs: Doc[]
|
|
1763
|
+
`;
|
|
1454
1764
|
}
|
|
1455
1765
|
);
|
|
1456
1766
|
|
|
@@ -1469,7 +1779,8 @@ const TEMPLATES = [
|
|
|
1469
1779
|
OperationVariables,
|
|
1470
1780
|
Response,
|
|
1471
1781
|
ServerOptions,
|
|
1472
|
-
Sources
|
|
1782
|
+
Sources,
|
|
1783
|
+
MCP
|
|
1473
1784
|
];
|
|
1474
1785
|
|
|
1475
1786
|
const DEVTOOLS_UI_ROUTE = "/__nuxt-graphql-middleware";
|
|
@@ -1533,6 +1844,8 @@ class DevModeHandler {
|
|
|
1533
1844
|
this.onViteServerCreated.bind(this)
|
|
1534
1845
|
);
|
|
1535
1846
|
this.nuxt.hook("builder:watch", this.onBuilderWatch.bind(this));
|
|
1847
|
+
const additionalFoldersToWatch = this.getAdditionalWatchFolders();
|
|
1848
|
+
this.helper.nuxt.options.watch.push(...additionalFoldersToWatch);
|
|
1536
1849
|
if (this.helper.options.devtools) {
|
|
1537
1850
|
const clientPath = this.helper.resolvers.module.resolve("./client");
|
|
1538
1851
|
setupDevToolsUI(this.nuxt, clientPath);
|
|
@@ -1642,6 +1955,34 @@ class DevModeHandler {
|
|
|
1642
1955
|
data: { operations }
|
|
1643
1956
|
});
|
|
1644
1957
|
}
|
|
1958
|
+
/**
|
|
1959
|
+
* Get additional folders that need to be watched.
|
|
1960
|
+
*/
|
|
1961
|
+
getAdditionalWatchFolders() {
|
|
1962
|
+
const folders = /* @__PURE__ */ new Set();
|
|
1963
|
+
const srcDir = this.helper.nuxt.options.srcDir;
|
|
1964
|
+
const rootDir = this.helper.nuxt.options.rootDir;
|
|
1965
|
+
for (const pattern of this.helper.options.autoImportPatterns) {
|
|
1966
|
+
if (pattern.startsWith("!")) {
|
|
1967
|
+
continue;
|
|
1968
|
+
}
|
|
1969
|
+
const match = pattern.match(/[*?{[]/);
|
|
1970
|
+
if (!match || match.index === void 0) {
|
|
1971
|
+
folders.add(dirname(pattern));
|
|
1972
|
+
} else {
|
|
1973
|
+
const pathBeforeGlob = pattern.slice(0, match.index);
|
|
1974
|
+
const folder = pathBeforeGlob.endsWith("/") ? pathBeforeGlob.slice(0, -1) : dirname(pathBeforeGlob);
|
|
1975
|
+
if (folder && folder !== ".") {
|
|
1976
|
+
folders.add(folder);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
return [...folders].filter((folder) => {
|
|
1981
|
+
return !folder.startsWith(srcDir) && folder !== rootDir;
|
|
1982
|
+
}).map((folder) => {
|
|
1983
|
+
return relative(srcDir, folder);
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1645
1986
|
}
|
|
1646
1987
|
|
|
1647
1988
|
class ModuleContext {
|
|
@@ -1722,7 +2063,1108 @@ class ModuleContext {
|
|
|
1722
2063
|
}
|
|
1723
2064
|
}
|
|
1724
2065
|
|
|
1725
|
-
|
|
2066
|
+
function createNameFilter(pattern) {
|
|
2067
|
+
try {
|
|
2068
|
+
const regex = new RegExp(pattern);
|
|
2069
|
+
return (name) => regex.test(name);
|
|
2070
|
+
} catch {
|
|
2071
|
+
return (name) => name.includes(pattern);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
function handleListOperations(collector, nameFilter, typeFilter) {
|
|
2076
|
+
let operations = collector.getOperations();
|
|
2077
|
+
if (nameFilter) {
|
|
2078
|
+
const filterFn = createNameFilter(nameFilter);
|
|
2079
|
+
operations = operations.filter((op) => filterFn(op.name));
|
|
2080
|
+
}
|
|
2081
|
+
if (typeFilter) {
|
|
2082
|
+
operations = operations.filter((op) => op.type === typeFilter);
|
|
2083
|
+
}
|
|
2084
|
+
return { operations };
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
function handleGetOperation(collector, name) {
|
|
2088
|
+
const operations = collector.getOperations();
|
|
2089
|
+
const operation = operations.find((op) => op.name === name);
|
|
2090
|
+
if (!operation) {
|
|
2091
|
+
return { operation: null, error: `Operation "${name}" not found` };
|
|
2092
|
+
}
|
|
2093
|
+
return { operation };
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
function handleGetOperationSource(collector, name, includeDependencies = false) {
|
|
2097
|
+
const operations = collector.getOperations();
|
|
2098
|
+
const operation = operations.find((op) => op.name === name);
|
|
2099
|
+
if (!operation) {
|
|
2100
|
+
return { source: null, error: `Operation "${name}" not found` };
|
|
2101
|
+
}
|
|
2102
|
+
const source = includeDependencies ? operation.sourceFull : operation.source;
|
|
2103
|
+
return { source };
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
function handleListFragments(collector, nameFilter) {
|
|
2107
|
+
let fragments = collector.getFragments();
|
|
2108
|
+
if (nameFilter) {
|
|
2109
|
+
const filterFn = createNameFilter(nameFilter);
|
|
2110
|
+
fragments = fragments.filter((frag) => filterFn(frag.name));
|
|
2111
|
+
}
|
|
2112
|
+
return { fragments };
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
function handleGetFragment(collector, name) {
|
|
2116
|
+
const fragment = collector.getFragment(name);
|
|
2117
|
+
if (!fragment) {
|
|
2118
|
+
return { fragment: null, error: `Fragment "${name}" not found` };
|
|
2119
|
+
}
|
|
2120
|
+
return { fragment };
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
function handleGetFragmentSource(collector, name, includeDependencies = false) {
|
|
2124
|
+
const fragment = collector.getFragment(name);
|
|
2125
|
+
if (!fragment) {
|
|
2126
|
+
return { source: null, error: `Fragment "${name}" not found` };
|
|
2127
|
+
}
|
|
2128
|
+
const source = includeDependencies ? fragment.sourceFull : fragment.source;
|
|
2129
|
+
return { source };
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
function handleGetFragmentsForType(collector, name) {
|
|
2133
|
+
return { fragments: collector.getFragmentsForType(name) };
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
function formatType$2(type) {
|
|
2137
|
+
return type.toString();
|
|
2138
|
+
}
|
|
2139
|
+
function isNonNull(type) {
|
|
2140
|
+
return isNonNullType(type);
|
|
2141
|
+
}
|
|
2142
|
+
function isList(type) {
|
|
2143
|
+
if (isNonNullType(type)) {
|
|
2144
|
+
return isListType(type.ofType);
|
|
2145
|
+
}
|
|
2146
|
+
return isListType(type);
|
|
2147
|
+
}
|
|
2148
|
+
function mapField(field) {
|
|
2149
|
+
return {
|
|
2150
|
+
name: field.name,
|
|
2151
|
+
description: field.description || null,
|
|
2152
|
+
type: formatType$2(field.type),
|
|
2153
|
+
isNonNull: isNonNull(field.type),
|
|
2154
|
+
isList: isList(field.type),
|
|
2155
|
+
deprecationReason: "deprecationReason" in field ? field.deprecationReason || null : null
|
|
2156
|
+
};
|
|
2157
|
+
}
|
|
2158
|
+
function mapEnumValue(value) {
|
|
2159
|
+
return {
|
|
2160
|
+
name: value.name,
|
|
2161
|
+
description: value.description || null
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
function handleGetSchemaType(schema, name) {
|
|
2165
|
+
const type = schema.getType(name);
|
|
2166
|
+
if (!type) {
|
|
2167
|
+
return { type: null, error: `Type "${name}" not found in schema` };
|
|
2168
|
+
}
|
|
2169
|
+
const info = {
|
|
2170
|
+
name: type.name,
|
|
2171
|
+
kind: "UNKNOWN",
|
|
2172
|
+
description: type.description || null,
|
|
2173
|
+
fields: null,
|
|
2174
|
+
enumValues: null,
|
|
2175
|
+
possibleTypes: null,
|
|
2176
|
+
interfaces: null
|
|
2177
|
+
};
|
|
2178
|
+
if (isObjectType(type)) {
|
|
2179
|
+
info.kind = "OBJECT";
|
|
2180
|
+
info.fields = Object.values(type.getFields()).map(mapField);
|
|
2181
|
+
info.interfaces = type.getInterfaces().map((i) => i.name);
|
|
2182
|
+
} else if (isInputObjectType(type)) {
|
|
2183
|
+
info.kind = "INPUT_OBJECT";
|
|
2184
|
+
info.fields = Object.values(type.getFields()).map(mapField);
|
|
2185
|
+
} else if (isEnumType(type)) {
|
|
2186
|
+
info.kind = "ENUM";
|
|
2187
|
+
info.enumValues = type.getValues().map(mapEnumValue);
|
|
2188
|
+
} else if (isUnionType(type)) {
|
|
2189
|
+
info.kind = "UNION";
|
|
2190
|
+
info.possibleTypes = type.getTypes().map((t) => t.name);
|
|
2191
|
+
} else if (isInterfaceType(type)) {
|
|
2192
|
+
info.kind = "INTERFACE";
|
|
2193
|
+
info.fields = Object.values(type.getFields()).map(mapField);
|
|
2194
|
+
} else if (isScalarType(type)) {
|
|
2195
|
+
info.kind = "SCALAR";
|
|
2196
|
+
}
|
|
2197
|
+
return { type: info };
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
function handleGetSchemaTypeDefinition(schema, name) {
|
|
2201
|
+
const type = schema.getType(name);
|
|
2202
|
+
if (!type) {
|
|
2203
|
+
return { definition: null, error: `Type "${name}" not found in schema` };
|
|
2204
|
+
}
|
|
2205
|
+
return { definition: printType(type) };
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
function getTypeKind(type) {
|
|
2209
|
+
if (isObjectType(type)) return "OBJECT";
|
|
2210
|
+
if (isInputObjectType(type)) return "INPUT_OBJECT";
|
|
2211
|
+
if (isEnumType(type)) return "ENUM";
|
|
2212
|
+
if (isUnionType(type)) return "UNION";
|
|
2213
|
+
if (isInterfaceType(type)) return "INTERFACE";
|
|
2214
|
+
if (isScalarType(type)) return "SCALAR";
|
|
2215
|
+
return null;
|
|
2216
|
+
}
|
|
2217
|
+
function handleListSchemaTypes(schema, kind) {
|
|
2218
|
+
const typeMap = schema.getTypeMap();
|
|
2219
|
+
const types = [];
|
|
2220
|
+
for (const [name, type] of Object.entries(typeMap)) {
|
|
2221
|
+
if (name.startsWith("__")) {
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
const typeKind = getTypeKind(type);
|
|
2225
|
+
if (!typeKind) {
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (kind && typeKind !== kind) {
|
|
2229
|
+
continue;
|
|
2230
|
+
}
|
|
2231
|
+
types.push({
|
|
2232
|
+
name: type.name,
|
|
2233
|
+
kind: typeKind,
|
|
2234
|
+
description: type.description || null
|
|
2235
|
+
});
|
|
2236
|
+
}
|
|
2237
|
+
types.sort((a, b) => a.name.localeCompare(b.name));
|
|
2238
|
+
return { types };
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
function handleGetTypesImplementingInterface(schema, interfaceName) {
|
|
2242
|
+
const interfaceType = schema.getType(interfaceName);
|
|
2243
|
+
if (!interfaceType) {
|
|
2244
|
+
return {
|
|
2245
|
+
interfaceName,
|
|
2246
|
+
types: [],
|
|
2247
|
+
error: `Type "${interfaceName}" not found in schema`
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
if (!isInterfaceType(interfaceType)) {
|
|
2251
|
+
return {
|
|
2252
|
+
interfaceName,
|
|
2253
|
+
types: [],
|
|
2254
|
+
error: `Type "${interfaceName}" is not an interface`
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
const implementingTypes = schema.getPossibleTypes(interfaceType);
|
|
2258
|
+
const types = implementingTypes.map((type) => ({
|
|
2259
|
+
name: type.name,
|
|
2260
|
+
description: type.description || null
|
|
2261
|
+
}));
|
|
2262
|
+
types.sort((a, b) => a.name.localeCompare(b.name));
|
|
2263
|
+
return { interfaceName, types };
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
function handleGetUnionMembers(schema, unionName) {
|
|
2267
|
+
const unionType = schema.getType(unionName);
|
|
2268
|
+
if (!unionType) {
|
|
2269
|
+
return {
|
|
2270
|
+
unionName,
|
|
2271
|
+
members: [],
|
|
2272
|
+
error: `Type "${unionName}" not found in schema`
|
|
2273
|
+
};
|
|
2274
|
+
}
|
|
2275
|
+
if (!isUnionType(unionType)) {
|
|
2276
|
+
return {
|
|
2277
|
+
unionName,
|
|
2278
|
+
members: [],
|
|
2279
|
+
error: `Type "${unionName}" is not a union`
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
const memberTypes = unionType.getTypes();
|
|
2283
|
+
const members = memberTypes.map((type) => ({
|
|
2284
|
+
name: type.name,
|
|
2285
|
+
description: type.description || null
|
|
2286
|
+
}));
|
|
2287
|
+
members.sort((a, b) => a.name.localeCompare(b.name));
|
|
2288
|
+
return { unionName, members };
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
function getNamedType(type) {
|
|
2292
|
+
if (isNonNullType(type) || isListType(type)) {
|
|
2293
|
+
return getNamedType(type.ofType);
|
|
2294
|
+
}
|
|
2295
|
+
return "name" in type ? type.name : "";
|
|
2296
|
+
}
|
|
2297
|
+
function handleGetTypeUsage(schema, typeName) {
|
|
2298
|
+
const targetType = schema.getType(typeName);
|
|
2299
|
+
if (!targetType) {
|
|
2300
|
+
return {
|
|
2301
|
+
typeName,
|
|
2302
|
+
usages: [],
|
|
2303
|
+
error: `Type "${typeName}" not found in schema`
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
const usages = [];
|
|
2307
|
+
const typeMap = schema.getTypeMap();
|
|
2308
|
+
for (const [name, type] of Object.entries(typeMap)) {
|
|
2309
|
+
if (name.startsWith("__")) {
|
|
2310
|
+
continue;
|
|
2311
|
+
}
|
|
2312
|
+
if (isObjectType(type) || isInterfaceType(type)) {
|
|
2313
|
+
const fields = type.getFields();
|
|
2314
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
2315
|
+
const returnTypeName = getNamedType(field.type);
|
|
2316
|
+
if (returnTypeName === typeName) {
|
|
2317
|
+
usages.push({
|
|
2318
|
+
typeName: name,
|
|
2319
|
+
fieldName,
|
|
2320
|
+
usageType: "return_type"
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
for (const arg of field.args) {
|
|
2324
|
+
const argTypeName = getNamedType(arg.type);
|
|
2325
|
+
if (argTypeName === typeName) {
|
|
2326
|
+
usages.push({
|
|
2327
|
+
typeName: name,
|
|
2328
|
+
fieldName: `${fieldName}(${arg.name})`,
|
|
2329
|
+
usageType: "argument"
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
if (isInputObjectType(type)) {
|
|
2336
|
+
const fields = type.getFields();
|
|
2337
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
2338
|
+
const fieldTypeName = getNamedType(field.type);
|
|
2339
|
+
if (fieldTypeName === typeName) {
|
|
2340
|
+
usages.push({
|
|
2341
|
+
typeName: name,
|
|
2342
|
+
fieldName,
|
|
2343
|
+
usageType: "input_field"
|
|
2344
|
+
});
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
usages.sort((a, b) => {
|
|
2350
|
+
const typeCompare = a.typeName.localeCompare(b.typeName);
|
|
2351
|
+
if (typeCompare !== 0) return typeCompare;
|
|
2352
|
+
return a.fieldName.localeCompare(b.fieldName);
|
|
2353
|
+
});
|
|
2354
|
+
return { typeName, usages };
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
function handleGetFieldUsage(collector, schema, typeName, fieldName) {
|
|
2358
|
+
const type = schema.getType(typeName);
|
|
2359
|
+
if (!type) {
|
|
2360
|
+
return {
|
|
2361
|
+
typeName,
|
|
2362
|
+
fieldName,
|
|
2363
|
+
usages: [],
|
|
2364
|
+
error: `Type "${typeName}" not found in schema`
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
if (!isObjectType(type) && !isInterfaceType(type)) {
|
|
2368
|
+
return {
|
|
2369
|
+
typeName,
|
|
2370
|
+
fieldName,
|
|
2371
|
+
usages: [],
|
|
2372
|
+
error: `Type "${typeName}" is not an object or interface type`
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
const fields = type.getFields();
|
|
2376
|
+
if (!fields[fieldName]) {
|
|
2377
|
+
return {
|
|
2378
|
+
typeName,
|
|
2379
|
+
fieldName,
|
|
2380
|
+
usages: [],
|
|
2381
|
+
error: `Field "${fieldName}" not found on type "${typeName}"`
|
|
2382
|
+
};
|
|
2383
|
+
}
|
|
2384
|
+
const usages = [];
|
|
2385
|
+
const operations = collector.getOperations();
|
|
2386
|
+
const fragments = collector.getFragments();
|
|
2387
|
+
for (const operation of operations) {
|
|
2388
|
+
if (hasFieldUsage(schema, operation.source, typeName, fieldName)) {
|
|
2389
|
+
usages.push({
|
|
2390
|
+
kind: "operation",
|
|
2391
|
+
name: operation.name,
|
|
2392
|
+
filePath: operation.relativeFilePath
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
for (const fragment of fragments) {
|
|
2397
|
+
if (hasFieldUsage(schema, fragment.source, typeName, fieldName)) {
|
|
2398
|
+
usages.push({
|
|
2399
|
+
kind: "fragment",
|
|
2400
|
+
name: fragment.name,
|
|
2401
|
+
filePath: fragment.relativeFilePath
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
return {
|
|
2406
|
+
typeName,
|
|
2407
|
+
fieldName,
|
|
2408
|
+
usages
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
function hasFieldUsage(schema, source, targetTypeName, targetFieldName) {
|
|
2412
|
+
try {
|
|
2413
|
+
const document = parse(source);
|
|
2414
|
+
const typeInfo = new TypeInfo(schema);
|
|
2415
|
+
let found = false;
|
|
2416
|
+
visit(
|
|
2417
|
+
document,
|
|
2418
|
+
visitWithTypeInfo(typeInfo, {
|
|
2419
|
+
Field: {
|
|
2420
|
+
enter(node) {
|
|
2421
|
+
if (found) return;
|
|
2422
|
+
const parentType = typeInfo.getParentType();
|
|
2423
|
+
if (!parentType) return;
|
|
2424
|
+
const parentTypeName = parentType.name;
|
|
2425
|
+
const fieldName = node.name.value;
|
|
2426
|
+
if (parentTypeName === targetTypeName && fieldName === targetFieldName) {
|
|
2427
|
+
found = true;
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
if (isObjectType(parentType)) {
|
|
2431
|
+
const interfaces = parentType.getInterfaces();
|
|
2432
|
+
for (const iface of interfaces) {
|
|
2433
|
+
if (iface.name === targetTypeName && fieldName === targetFieldName) {
|
|
2434
|
+
const ifaceFields = iface.getFields();
|
|
2435
|
+
if (ifaceFields[targetFieldName]) {
|
|
2436
|
+
found = true;
|
|
2437
|
+
return;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
const targetType = schema.getType(targetTypeName);
|
|
2443
|
+
if (targetType && isObjectType(targetType)) {
|
|
2444
|
+
const targetInterfaces = targetType.getInterfaces();
|
|
2445
|
+
for (const iface of targetInterfaces) {
|
|
2446
|
+
if (parentTypeName === iface.name && fieldName === targetFieldName) {
|
|
2447
|
+
found = true;
|
|
2448
|
+
return;
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
})
|
|
2455
|
+
);
|
|
2456
|
+
return found;
|
|
2457
|
+
} catch {
|
|
2458
|
+
return false;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
function collectFragmentInfo(documentSource) {
|
|
2463
|
+
const usedFragments = /* @__PURE__ */ new Set();
|
|
2464
|
+
const definedFragments = /* @__PURE__ */ new Set();
|
|
2465
|
+
try {
|
|
2466
|
+
const document = parse(documentSource);
|
|
2467
|
+
visit(document, {
|
|
2468
|
+
FragmentSpread(node) {
|
|
2469
|
+
usedFragments.add(node.name.value);
|
|
2470
|
+
},
|
|
2471
|
+
FragmentDefinition(node) {
|
|
2472
|
+
definedFragments.add(node.name.value);
|
|
2473
|
+
}
|
|
2474
|
+
});
|
|
2475
|
+
} catch {
|
|
2476
|
+
}
|
|
2477
|
+
return { usedFragments, definedFragments };
|
|
2478
|
+
}
|
|
2479
|
+
function collectRequiredFragments(fragmentNames, collector, collected = /* @__PURE__ */ new Map()) {
|
|
2480
|
+
for (const name of fragmentNames) {
|
|
2481
|
+
if (collected.has(name)) {
|
|
2482
|
+
continue;
|
|
2483
|
+
}
|
|
2484
|
+
const fragment = collector.getFragment(name);
|
|
2485
|
+
if (!fragment) {
|
|
2486
|
+
continue;
|
|
2487
|
+
}
|
|
2488
|
+
collected.set(name, fragment.source);
|
|
2489
|
+
if (fragment.dependencies.length > 0) {
|
|
2490
|
+
collectRequiredFragments(
|
|
2491
|
+
new Set(fragment.dependencies),
|
|
2492
|
+
collector,
|
|
2493
|
+
collected
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
return collected;
|
|
2498
|
+
}
|
|
2499
|
+
function handleValidateDocument(schema, collector, documentSource) {
|
|
2500
|
+
try {
|
|
2501
|
+
const { usedFragments, definedFragments } = collectFragmentInfo(documentSource);
|
|
2502
|
+
const missingFragments = /* @__PURE__ */ new Set();
|
|
2503
|
+
for (const name of usedFragments) {
|
|
2504
|
+
if (!definedFragments.has(name)) {
|
|
2505
|
+
missingFragments.add(name);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
const requiredFragments = collectRequiredFragments(
|
|
2509
|
+
missingFragments,
|
|
2510
|
+
collector
|
|
2511
|
+
);
|
|
2512
|
+
let fullDocument = documentSource;
|
|
2513
|
+
if (requiredFragments.size > 0) {
|
|
2514
|
+
const fragmentSources = [...requiredFragments.values()].join("\n\n");
|
|
2515
|
+
fullDocument = `${documentSource}
|
|
2516
|
+
|
|
2517
|
+
${fragmentSources}`;
|
|
2518
|
+
}
|
|
2519
|
+
const source = new Source(fullDocument, "input");
|
|
2520
|
+
const document = parse(source);
|
|
2521
|
+
const errors = validateGraphQlDocuments(schema, [document]);
|
|
2522
|
+
if (errors.length === 0) {
|
|
2523
|
+
return {
|
|
2524
|
+
valid: true,
|
|
2525
|
+
errors: []
|
|
2526
|
+
};
|
|
2527
|
+
}
|
|
2528
|
+
return {
|
|
2529
|
+
valid: false,
|
|
2530
|
+
errors: errors.map((error) => ({
|
|
2531
|
+
message: error.message,
|
|
2532
|
+
locations: error.locations?.map((loc) => ({
|
|
2533
|
+
line: loc.line,
|
|
2534
|
+
column: loc.column
|
|
2535
|
+
}))
|
|
2536
|
+
}))
|
|
2537
|
+
};
|
|
2538
|
+
} catch (error) {
|
|
2539
|
+
const message = error instanceof Error ? error.message : "Unknown parsing error";
|
|
2540
|
+
const locations = error && typeof error === "object" && "locations" in error && Array.isArray(error.locations) ? error.locations.map((loc) => ({
|
|
2541
|
+
line: loc.line,
|
|
2542
|
+
column: loc.column
|
|
2543
|
+
})) : void 0;
|
|
2544
|
+
return {
|
|
2545
|
+
valid: false,
|
|
2546
|
+
errors: [{ message, locations }]
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
function getMockValueForType$1(typeNode, varName) {
|
|
2552
|
+
if (typeNode.kind === "NonNullType") {
|
|
2553
|
+
return getMockValueForType$1(typeNode.type, varName);
|
|
2554
|
+
}
|
|
2555
|
+
if (typeNode.kind === "ListType") {
|
|
2556
|
+
const innerValue = getMockValueForType$1(typeNode.type, varName);
|
|
2557
|
+
return `[${innerValue}]`;
|
|
2558
|
+
}
|
|
2559
|
+
if (typeNode.kind === "NamedType") {
|
|
2560
|
+
const typeName = typeNode.name.value;
|
|
2561
|
+
switch (typeName) {
|
|
2562
|
+
case "String":
|
|
2563
|
+
return `'${varName}_value'`;
|
|
2564
|
+
case "Int":
|
|
2565
|
+
return "1";
|
|
2566
|
+
case "Float":
|
|
2567
|
+
return "1.0";
|
|
2568
|
+
case "Boolean":
|
|
2569
|
+
return "true";
|
|
2570
|
+
case "ID":
|
|
2571
|
+
return `'${varName}_id'`;
|
|
2572
|
+
default:
|
|
2573
|
+
return `{ /* placeholder for: ${typeName} */ }`;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
return `'${varName}'`;
|
|
2577
|
+
}
|
|
2578
|
+
function formatType$1(typeNode) {
|
|
2579
|
+
if (typeNode.kind === "NonNullType") {
|
|
2580
|
+
return `${formatType$1(typeNode.type)}!`;
|
|
2581
|
+
}
|
|
2582
|
+
if (typeNode.kind === "ListType") {
|
|
2583
|
+
return `[${formatType$1(typeNode.type)}]`;
|
|
2584
|
+
}
|
|
2585
|
+
if (typeNode.kind === "NamedType") {
|
|
2586
|
+
return typeNode.name.value;
|
|
2587
|
+
}
|
|
2588
|
+
return "unknown";
|
|
2589
|
+
}
|
|
2590
|
+
function getBaseTypeName$1(typeNode) {
|
|
2591
|
+
if (typeNode.kind === "NonNullType") {
|
|
2592
|
+
return getBaseTypeName$1(typeNode.type);
|
|
2593
|
+
}
|
|
2594
|
+
if (typeNode.kind === "ListType") {
|
|
2595
|
+
return getBaseTypeName$1(typeNode.type);
|
|
2596
|
+
}
|
|
2597
|
+
if (typeNode.kind === "NamedType") {
|
|
2598
|
+
return typeNode.name.value;
|
|
2599
|
+
}
|
|
2600
|
+
return null;
|
|
2601
|
+
}
|
|
2602
|
+
function extractVariables$1(source) {
|
|
2603
|
+
try {
|
|
2604
|
+
const doc = parse(source);
|
|
2605
|
+
const operation = doc.definitions.find(
|
|
2606
|
+
(def) => def.kind === "OperationDefinition"
|
|
2607
|
+
);
|
|
2608
|
+
if (!operation || operation.kind !== "OperationDefinition") {
|
|
2609
|
+
return [];
|
|
2610
|
+
}
|
|
2611
|
+
const variables = operation.variableDefinitions || [];
|
|
2612
|
+
return variables.map((varDef) => ({
|
|
2613
|
+
name: varDef.variable.name.value,
|
|
2614
|
+
type: formatType$1(varDef.type),
|
|
2615
|
+
mockValue: getMockValueForType$1(varDef.type, varDef.variable.name.value)
|
|
2616
|
+
}));
|
|
2617
|
+
} catch {
|
|
2618
|
+
return [];
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
function extractVariableTypeNames$1(source) {
|
|
2622
|
+
try {
|
|
2623
|
+
const doc = parse(source);
|
|
2624
|
+
const operation = doc.definitions.find(
|
|
2625
|
+
(def) => def.kind === "OperationDefinition"
|
|
2626
|
+
);
|
|
2627
|
+
if (!operation || operation.kind !== "OperationDefinition") {
|
|
2628
|
+
return [];
|
|
2629
|
+
}
|
|
2630
|
+
const typeNames = /* @__PURE__ */ new Set();
|
|
2631
|
+
const variables = operation.variableDefinitions || [];
|
|
2632
|
+
for (const varDef of variables) {
|
|
2633
|
+
const typeName = getBaseTypeName$1(varDef.type);
|
|
2634
|
+
if (typeName) {
|
|
2635
|
+
typeNames.add(typeName);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
return Array.from(typeNames);
|
|
2639
|
+
} catch {
|
|
2640
|
+
return [];
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
function buildImports$1(schema, variablesTypeName, responseTypeName, variableTypeNames, hasVariables) {
|
|
2644
|
+
const imports = [];
|
|
2645
|
+
imports.push({
|
|
2646
|
+
typeName: responseTypeName,
|
|
2647
|
+
description: "Response type for the operation"
|
|
2648
|
+
});
|
|
2649
|
+
if (hasVariables) {
|
|
2650
|
+
imports.push({
|
|
2651
|
+
typeName: variablesTypeName,
|
|
2652
|
+
description: "Variables type for the operation"
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
for (const typeName of variableTypeNames) {
|
|
2656
|
+
const schemaType = schema.getType(typeName);
|
|
2657
|
+
if (!schemaType) continue;
|
|
2658
|
+
if (isScalarType(schemaType)) continue;
|
|
2659
|
+
if (isEnumType(schemaType)) {
|
|
2660
|
+
imports.push({
|
|
2661
|
+
typeName,
|
|
2662
|
+
description: `Enum type used in variables`
|
|
2663
|
+
});
|
|
2664
|
+
} else if (isInputObjectType(schemaType)) {
|
|
2665
|
+
imports.push({
|
|
2666
|
+
typeName,
|
|
2667
|
+
description: `Input object type used in variables`
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
return imports;
|
|
2672
|
+
}
|
|
2673
|
+
function generateExamples$1(operationName, operationType, variables, variablesTypeName, responseTypeName) {
|
|
2674
|
+
const examples = [];
|
|
2675
|
+
const hasVariables = variables.length > 0;
|
|
2676
|
+
const variablesObject = hasVariables ? `{ ${variables.map((v) => `${v.name}: ${v.mockValue}`).join(", ")} }` : "";
|
|
2677
|
+
const variablesObjectIndented = hasVariables ? `{
|
|
2678
|
+
${variables.map((v) => `${v.name}: ${v.mockValue}`).join(",\n ")},
|
|
2679
|
+
}` : "";
|
|
2680
|
+
if (operationType === "query") {
|
|
2681
|
+
const transformDescription = `// The type of "graphqlResponse.data" is ${responseTypeName}. Prepare the data here before returning it.`;
|
|
2682
|
+
if (hasVariables) {
|
|
2683
|
+
examples.push({
|
|
2684
|
+
description: COMPOSABLES.useAsyncGraphqlQuery.description,
|
|
2685
|
+
documentationUrl: COMPOSABLES.useAsyncGraphqlQuery.docsUrl,
|
|
2686
|
+
code: `import type { ${variablesTypeName} } from '#graphql-operations'
|
|
2687
|
+
|
|
2688
|
+
const variables = computed<${variablesTypeName}>(() => {
|
|
2689
|
+
return ${variablesObjectIndented}
|
|
2690
|
+
})
|
|
2691
|
+
|
|
2692
|
+
const { data } = await useAsyncGraphqlQuery(
|
|
2693
|
+
'${operationName}',
|
|
2694
|
+
variables,
|
|
2695
|
+
// Same options as useAsyncData.
|
|
2696
|
+
{
|
|
2697
|
+
transform: function (graphqlResponse) {
|
|
2698
|
+
// ${transformDescription}
|
|
2699
|
+
return graphqlResponse.data
|
|
2700
|
+
},
|
|
2701
|
+
},
|
|
2702
|
+
)
|
|
2703
|
+
|
|
2704
|
+
// data is reactive, data.value is ${responseTypeName} | undefined
|
|
2705
|
+
console.log(data.value)`
|
|
2706
|
+
});
|
|
2707
|
+
} else {
|
|
2708
|
+
examples.push({
|
|
2709
|
+
description: COMPOSABLES.useAsyncGraphqlQuery.description,
|
|
2710
|
+
documentationUrl: COMPOSABLES.useAsyncGraphqlQuery.docsUrl,
|
|
2711
|
+
code: `const { data } = await useAsyncGraphqlQuery(
|
|
2712
|
+
'${operationName}',
|
|
2713
|
+
null,
|
|
2714
|
+
// Same options as useAsyncData.
|
|
2715
|
+
{
|
|
2716
|
+
transform: function (graphqlResponse) {
|
|
2717
|
+
// ${transformDescription}
|
|
2718
|
+
return graphqlResponse.data
|
|
2719
|
+
},
|
|
2720
|
+
},
|
|
2721
|
+
)
|
|
2722
|
+
|
|
2723
|
+
// data is reactive, data.value is ${responseTypeName} | undefined
|
|
2724
|
+
console.log(data.value)`
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
if (hasVariables) {
|
|
2728
|
+
examples.push({
|
|
2729
|
+
description: COMPOSABLES.useGraphqlQuery.description,
|
|
2730
|
+
documentationUrl: COMPOSABLES.useGraphqlQuery.docsUrl,
|
|
2731
|
+
code: `const response = await useGraphqlQuery('${operationName}', ${variablesObject})
|
|
2732
|
+
|
|
2733
|
+
// response.data is ${responseTypeName} | undefined
|
|
2734
|
+
console.log(response.data)`
|
|
2735
|
+
});
|
|
2736
|
+
} else {
|
|
2737
|
+
examples.push({
|
|
2738
|
+
description: COMPOSABLES.useGraphqlQuery.description,
|
|
2739
|
+
documentationUrl: COMPOSABLES.useGraphqlQuery.docsUrl,
|
|
2740
|
+
code: `const response = await useGraphqlQuery('${operationName}')
|
|
2741
|
+
|
|
2742
|
+
// response.data is ${responseTypeName} | undefined
|
|
2743
|
+
console.log(response.data)`
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2746
|
+
} else {
|
|
2747
|
+
if (hasVariables) {
|
|
2748
|
+
examples.push({
|
|
2749
|
+
description: COMPOSABLES.useGraphqlMutation.description,
|
|
2750
|
+
documentationUrl: COMPOSABLES.useGraphqlMutation.docsUrl,
|
|
2751
|
+
code: `const response = await useGraphqlMutation('${operationName}', ${variablesObject})
|
|
2752
|
+
|
|
2753
|
+
// response.data is ${responseTypeName} | undefined
|
|
2754
|
+
console.log(response.data)`
|
|
2755
|
+
});
|
|
2756
|
+
} else {
|
|
2757
|
+
examples.push({
|
|
2758
|
+
description: COMPOSABLES.useGraphqlMutation.description,
|
|
2759
|
+
documentationUrl: COMPOSABLES.useGraphqlMutation.docsUrl,
|
|
2760
|
+
code: `const response = await useGraphqlMutation('${operationName}')
|
|
2761
|
+
|
|
2762
|
+
// response.data is ${responseTypeName} | undefined
|
|
2763
|
+
console.log(response.data)`
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
return examples;
|
|
2768
|
+
}
|
|
2769
|
+
function handleGetComposableExamples(collector, schema, operationName) {
|
|
2770
|
+
const operations = collector.getOperations();
|
|
2771
|
+
const operation = operations.find((op) => op.name === operationName);
|
|
2772
|
+
if (!operation) {
|
|
2773
|
+
return { error: `Operation "${operationName}" not found` };
|
|
2774
|
+
}
|
|
2775
|
+
const variables = extractVariables$1(operation.source);
|
|
2776
|
+
const variableTypeNames = extractVariableTypeNames$1(operation.source);
|
|
2777
|
+
const examples = generateExamples$1(
|
|
2778
|
+
operationName,
|
|
2779
|
+
operation.type,
|
|
2780
|
+
variables,
|
|
2781
|
+
operation.variablesTypeName,
|
|
2782
|
+
operation.responseTypeName
|
|
2783
|
+
);
|
|
2784
|
+
const imports = buildImports$1(
|
|
2785
|
+
schema,
|
|
2786
|
+
operation.variablesTypeName,
|
|
2787
|
+
operation.responseTypeName,
|
|
2788
|
+
variableTypeNames,
|
|
2789
|
+
variables.length > 0
|
|
2790
|
+
);
|
|
2791
|
+
return { examples, imports };
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
function getMockValueForType(typeNode, varName) {
|
|
2795
|
+
if (typeNode.kind === "NonNullType") {
|
|
2796
|
+
return getMockValueForType(typeNode.type, varName);
|
|
2797
|
+
}
|
|
2798
|
+
if (typeNode.kind === "ListType") {
|
|
2799
|
+
const innerValue = getMockValueForType(typeNode.type, varName);
|
|
2800
|
+
return `[${innerValue}]`;
|
|
2801
|
+
}
|
|
2802
|
+
if (typeNode.kind === "NamedType") {
|
|
2803
|
+
const typeName = typeNode.name.value;
|
|
2804
|
+
switch (typeName) {
|
|
2805
|
+
case "String":
|
|
2806
|
+
return `'${varName}_value'`;
|
|
2807
|
+
case "Int":
|
|
2808
|
+
return "1";
|
|
2809
|
+
case "Float":
|
|
2810
|
+
return "1.0";
|
|
2811
|
+
case "Boolean":
|
|
2812
|
+
return "true";
|
|
2813
|
+
case "ID":
|
|
2814
|
+
return `'${varName}_id'`;
|
|
2815
|
+
default:
|
|
2816
|
+
return `{ /* placeholder for: ${typeName} */ }`;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
return `'${varName}'`;
|
|
2820
|
+
}
|
|
2821
|
+
function formatType(typeNode) {
|
|
2822
|
+
if (typeNode.kind === "NonNullType") {
|
|
2823
|
+
return `${formatType(typeNode.type)}!`;
|
|
2824
|
+
}
|
|
2825
|
+
if (typeNode.kind === "ListType") {
|
|
2826
|
+
return `[${formatType(typeNode.type)}]`;
|
|
2827
|
+
}
|
|
2828
|
+
if (typeNode.kind === "NamedType") {
|
|
2829
|
+
return typeNode.name.value;
|
|
2830
|
+
}
|
|
2831
|
+
return "unknown";
|
|
2832
|
+
}
|
|
2833
|
+
function getBaseTypeName(typeNode) {
|
|
2834
|
+
if (typeNode.kind === "NonNullType") {
|
|
2835
|
+
return getBaseTypeName(typeNode.type);
|
|
2836
|
+
}
|
|
2837
|
+
if (typeNode.kind === "ListType") {
|
|
2838
|
+
return getBaseTypeName(typeNode.type);
|
|
2839
|
+
}
|
|
2840
|
+
if (typeNode.kind === "NamedType") {
|
|
2841
|
+
return typeNode.name.value;
|
|
2842
|
+
}
|
|
2843
|
+
return null;
|
|
2844
|
+
}
|
|
2845
|
+
function extractVariables(source) {
|
|
2846
|
+
try {
|
|
2847
|
+
const doc = parse(source);
|
|
2848
|
+
const operation = doc.definitions.find(
|
|
2849
|
+
(def) => def.kind === "OperationDefinition"
|
|
2850
|
+
);
|
|
2851
|
+
if (!operation || operation.kind !== "OperationDefinition") {
|
|
2852
|
+
return [];
|
|
2853
|
+
}
|
|
2854
|
+
const variables = operation.variableDefinitions || [];
|
|
2855
|
+
return variables.map((varDef) => ({
|
|
2856
|
+
name: varDef.variable.name.value,
|
|
2857
|
+
type: formatType(varDef.type),
|
|
2858
|
+
mockValue: getMockValueForType(varDef.type, varDef.variable.name.value)
|
|
2859
|
+
}));
|
|
2860
|
+
} catch {
|
|
2861
|
+
return [];
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
function extractVariableTypeNames(source) {
|
|
2865
|
+
try {
|
|
2866
|
+
const doc = parse(source);
|
|
2867
|
+
const operation = doc.definitions.find(
|
|
2868
|
+
(def) => def.kind === "OperationDefinition"
|
|
2869
|
+
);
|
|
2870
|
+
if (!operation || operation.kind !== "OperationDefinition") {
|
|
2871
|
+
return [];
|
|
2872
|
+
}
|
|
2873
|
+
const typeNames = /* @__PURE__ */ new Set();
|
|
2874
|
+
const variables = operation.variableDefinitions || [];
|
|
2875
|
+
for (const varDef of variables) {
|
|
2876
|
+
const typeName = getBaseTypeName(varDef.type);
|
|
2877
|
+
if (typeName) {
|
|
2878
|
+
typeNames.add(typeName);
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
return Array.from(typeNames);
|
|
2882
|
+
} catch {
|
|
2883
|
+
return [];
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
function buildImports(schema, variablesTypeName, responseTypeName, variableTypeNames, hasVariables) {
|
|
2887
|
+
const imports = [];
|
|
2888
|
+
imports.push({
|
|
2889
|
+
typeName: responseTypeName,
|
|
2890
|
+
description: "Response type for the operation"
|
|
2891
|
+
});
|
|
2892
|
+
if (hasVariables) {
|
|
2893
|
+
imports.push({
|
|
2894
|
+
typeName: variablesTypeName,
|
|
2895
|
+
description: "Variables type for the operation"
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2898
|
+
for (const typeName of variableTypeNames) {
|
|
2899
|
+
const schemaType = schema.getType(typeName);
|
|
2900
|
+
if (!schemaType) continue;
|
|
2901
|
+
if (isScalarType(schemaType)) continue;
|
|
2902
|
+
if (isEnumType(schemaType)) {
|
|
2903
|
+
imports.push({
|
|
2904
|
+
typeName,
|
|
2905
|
+
description: `Enum type used in variables`
|
|
2906
|
+
});
|
|
2907
|
+
} else if (isInputObjectType(schemaType)) {
|
|
2908
|
+
imports.push({
|
|
2909
|
+
typeName,
|
|
2910
|
+
description: `Input object type used in variables`
|
|
2911
|
+
});
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
return imports;
|
|
2915
|
+
}
|
|
2916
|
+
function generateExamples(operationName, operationType, variables, responseTypeName) {
|
|
2917
|
+
const examples = [];
|
|
2918
|
+
const hasVariables = variables.length > 0;
|
|
2919
|
+
const variablesObject = hasVariables ? `{ ${variables.map((v) => `${v.name}: ${v.mockValue}`).join(", ")} }` : "";
|
|
2920
|
+
if (operationType === "query") {
|
|
2921
|
+
if (hasVariables) {
|
|
2922
|
+
examples.push({
|
|
2923
|
+
description: SERVER_UTILS.useGraphqlQuery.description,
|
|
2924
|
+
documentationUrl: SERVER_UTILS.useGraphqlQuery.docsUrl,
|
|
2925
|
+
code: `export default defineEventHandler(async (event) => {
|
|
2926
|
+
const response = await useGraphqlQuery('${operationName}', ${variablesObject})
|
|
2927
|
+
|
|
2928
|
+
// response.data is ${responseTypeName} | undefined
|
|
2929
|
+
return response.data
|
|
2930
|
+
})`
|
|
2931
|
+
});
|
|
2932
|
+
} else {
|
|
2933
|
+
examples.push({
|
|
2934
|
+
description: SERVER_UTILS.useGraphqlQuery.description,
|
|
2935
|
+
documentationUrl: SERVER_UTILS.useGraphqlQuery.docsUrl,
|
|
2936
|
+
code: `export default defineEventHandler(async (event) => {
|
|
2937
|
+
const response = await useGraphqlQuery('${operationName}')
|
|
2938
|
+
|
|
2939
|
+
// response.data is ${responseTypeName} | undefined
|
|
2940
|
+
return response.data
|
|
2941
|
+
})`
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
} else {
|
|
2945
|
+
if (hasVariables) {
|
|
2946
|
+
examples.push({
|
|
2947
|
+
description: SERVER_UTILS.useGraphqlMutation.description,
|
|
2948
|
+
documentationUrl: SERVER_UTILS.useGraphqlMutation.docsUrl,
|
|
2949
|
+
code: `export default defineEventHandler(async (event) => {
|
|
2950
|
+
const response = await useGraphqlMutation('${operationName}', ${variablesObject})
|
|
2951
|
+
|
|
2952
|
+
// response.data is ${responseTypeName} | undefined
|
|
2953
|
+
return response.data
|
|
2954
|
+
})`
|
|
2955
|
+
});
|
|
2956
|
+
} else {
|
|
2957
|
+
examples.push({
|
|
2958
|
+
description: SERVER_UTILS.useGraphqlMutation.description,
|
|
2959
|
+
documentationUrl: SERVER_UTILS.useGraphqlMutation.docsUrl,
|
|
2960
|
+
code: `export default defineEventHandler(async (event) => {
|
|
2961
|
+
const response = await useGraphqlMutation('${operationName}')
|
|
2962
|
+
|
|
2963
|
+
// response.data is ${responseTypeName} | undefined
|
|
2964
|
+
return response.data
|
|
2965
|
+
})`
|
|
2966
|
+
});
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
examples.push({
|
|
2970
|
+
description: SERVER_UTILS.doGraphqlRequest.description,
|
|
2971
|
+
documentationUrl: SERVER_UTILS.doGraphqlRequest.docsUrl,
|
|
2972
|
+
code: `export default defineEventHandler(async (event) => {
|
|
2973
|
+
// Use doGraphqlRequest for raw GraphQL requests with custom query strings
|
|
2974
|
+
const response = await doGraphqlRequest({
|
|
2975
|
+
query: \`
|
|
2976
|
+
${operationType} ${operationName}${hasVariables ? `(${variables.map((v) => `$${v.name}: ${v.type}`).join(", ")})` : ""} {
|
|
2977
|
+
# Your query fields here
|
|
2978
|
+
}
|
|
2979
|
+
\`,${hasVariables ? `
|
|
2980
|
+
variables: ${variablesObject},` : ""}
|
|
2981
|
+
operationName: '${operationName}',
|
|
2982
|
+
})
|
|
2983
|
+
|
|
2984
|
+
return response.data
|
|
2985
|
+
})`
|
|
2986
|
+
});
|
|
2987
|
+
return examples;
|
|
2988
|
+
}
|
|
2989
|
+
function handleGetServerUtilsExamples(collector, schema, operationName) {
|
|
2990
|
+
const operations = collector.getOperations();
|
|
2991
|
+
const operation = operations.find((op) => op.name === operationName);
|
|
2992
|
+
if (!operation) {
|
|
2993
|
+
return { error: `Operation "${operationName}" not found` };
|
|
2994
|
+
}
|
|
2995
|
+
const variables = extractVariables(operation.source);
|
|
2996
|
+
const variableTypeNames = extractVariableTypeNames(operation.source);
|
|
2997
|
+
const examples = generateExamples(
|
|
2998
|
+
operationName,
|
|
2999
|
+
operation.type,
|
|
3000
|
+
variables,
|
|
3001
|
+
operation.responseTypeName
|
|
3002
|
+
);
|
|
3003
|
+
const imports = buildImports(
|
|
3004
|
+
schema,
|
|
3005
|
+
operation.variablesTypeName,
|
|
3006
|
+
operation.responseTypeName,
|
|
3007
|
+
variableTypeNames,
|
|
3008
|
+
variables.length > 0
|
|
3009
|
+
);
|
|
3010
|
+
return { examples, imports };
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
function makeRelative(rootDir, path) {
|
|
3014
|
+
if (!path) {
|
|
3015
|
+
return null;
|
|
3016
|
+
}
|
|
3017
|
+
if (isAbsolute(path)) {
|
|
3018
|
+
const rel = relative$1(rootDir, path);
|
|
3019
|
+
if (!rel.startsWith(".")) {
|
|
3020
|
+
return "./" + rel;
|
|
3021
|
+
}
|
|
3022
|
+
return rel;
|
|
3023
|
+
}
|
|
3024
|
+
if (!path.startsWith(".")) {
|
|
3025
|
+
return "./" + path;
|
|
3026
|
+
}
|
|
3027
|
+
return path;
|
|
3028
|
+
}
|
|
3029
|
+
function handleGetModuleConfig(helper) {
|
|
3030
|
+
const rootDir = helper.nuxt.options.rootDir;
|
|
3031
|
+
return {
|
|
3032
|
+
autoImportPatterns: (helper.options.autoImportPatterns || []).map(
|
|
3033
|
+
(pattern) => makeRelative(rootDir, pattern)
|
|
3034
|
+
),
|
|
3035
|
+
paths: {
|
|
3036
|
+
runtimeTypes: makeRelative(rootDir, helper.paths.runtimeTypes),
|
|
3037
|
+
schema: makeRelative(rootDir, helper.paths.schema),
|
|
3038
|
+
serverOptions: makeRelative(rootDir, helper.paths.serverOptions),
|
|
3039
|
+
clientOptions: makeRelative(rootDir, helper.paths.clientOptions),
|
|
3040
|
+
documentTypes: makeRelative(
|
|
3041
|
+
rootDir,
|
|
3042
|
+
helper.paths.moduleTypesDir + "/index.d.ts"
|
|
3043
|
+
)
|
|
3044
|
+
}
|
|
3045
|
+
};
|
|
3046
|
+
}
|
|
3047
|
+
|
|
3048
|
+
function requireName(body) {
|
|
3049
|
+
const name = body.name;
|
|
3050
|
+
if (!name) {
|
|
3051
|
+
throw createError({
|
|
3052
|
+
statusCode: 400,
|
|
3053
|
+
message: 'Missing "name" parameter in request body'
|
|
3054
|
+
});
|
|
3055
|
+
}
|
|
3056
|
+
return name;
|
|
3057
|
+
}
|
|
3058
|
+
function createMcpDevHandler(collector, schemaProvider, helper) {
|
|
3059
|
+
return defineEventHandler(async (event) => {
|
|
3060
|
+
const body = await readBody(event);
|
|
3061
|
+
const tool = body?.tool;
|
|
3062
|
+
if (!tool) {
|
|
3063
|
+
throw createError({
|
|
3064
|
+
statusCode: 400,
|
|
3065
|
+
message: 'Missing "tool" parameter in request body'
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3068
|
+
switch (tool) {
|
|
3069
|
+
// Operation tools
|
|
3070
|
+
case "operations-list":
|
|
3071
|
+
return handleListOperations(
|
|
3072
|
+
collector,
|
|
3073
|
+
body.nameFilter,
|
|
3074
|
+
body.type
|
|
3075
|
+
);
|
|
3076
|
+
case "operations-get":
|
|
3077
|
+
return handleGetOperation(collector, requireName(body));
|
|
3078
|
+
case "operations-get-source":
|
|
3079
|
+
return handleGetOperationSource(
|
|
3080
|
+
collector,
|
|
3081
|
+
requireName(body),
|
|
3082
|
+
body.includeDependencies
|
|
3083
|
+
);
|
|
3084
|
+
// Fragment tools
|
|
3085
|
+
case "fragments-list":
|
|
3086
|
+
return handleListFragments(
|
|
3087
|
+
collector,
|
|
3088
|
+
body.nameFilter
|
|
3089
|
+
);
|
|
3090
|
+
case "fragments-get":
|
|
3091
|
+
return handleGetFragment(collector, requireName(body));
|
|
3092
|
+
case "fragments-get-source":
|
|
3093
|
+
return handleGetFragmentSource(
|
|
3094
|
+
collector,
|
|
3095
|
+
requireName(body),
|
|
3096
|
+
body.includeDependencies
|
|
3097
|
+
);
|
|
3098
|
+
case "fragments-list-for-type":
|
|
3099
|
+
return handleGetFragmentsForType(collector, requireName(body));
|
|
3100
|
+
// Schema tools
|
|
3101
|
+
case "schema-get-type":
|
|
3102
|
+
return handleGetSchemaType(
|
|
3103
|
+
schemaProvider.getSchema(),
|
|
3104
|
+
requireName(body)
|
|
3105
|
+
);
|
|
3106
|
+
case "schema-get-type-definition":
|
|
3107
|
+
return handleGetSchemaTypeDefinition(
|
|
3108
|
+
schemaProvider.getSchema(),
|
|
3109
|
+
requireName(body)
|
|
3110
|
+
);
|
|
3111
|
+
case "schema-list-types":
|
|
3112
|
+
return handleListSchemaTypes(
|
|
3113
|
+
schemaProvider.getSchema(),
|
|
3114
|
+
body.kind
|
|
3115
|
+
);
|
|
3116
|
+
case "schema-get-interface-implementors":
|
|
3117
|
+
return handleGetTypesImplementingInterface(
|
|
3118
|
+
schemaProvider.getSchema(),
|
|
3119
|
+
requireName(body)
|
|
3120
|
+
);
|
|
3121
|
+
case "schema-get-union-members":
|
|
3122
|
+
return handleGetUnionMembers(
|
|
3123
|
+
schemaProvider.getSchema(),
|
|
3124
|
+
requireName(body)
|
|
3125
|
+
);
|
|
3126
|
+
case "schema-get-type-usage":
|
|
3127
|
+
return handleGetTypeUsage(schemaProvider.getSchema(), requireName(body));
|
|
3128
|
+
case "operations-get-field-usage":
|
|
3129
|
+
return handleGetFieldUsage(
|
|
3130
|
+
collector,
|
|
3131
|
+
schemaProvider.getSchema(),
|
|
3132
|
+
body.typeName,
|
|
3133
|
+
body.fieldName
|
|
3134
|
+
);
|
|
3135
|
+
case "schema-validate-document":
|
|
3136
|
+
return handleValidateDocument(
|
|
3137
|
+
schemaProvider.getSchema(),
|
|
3138
|
+
collector,
|
|
3139
|
+
body.document
|
|
3140
|
+
);
|
|
3141
|
+
// Composable examples tool
|
|
3142
|
+
case "vue-graphql-composable-example":
|
|
3143
|
+
return handleGetComposableExamples(
|
|
3144
|
+
collector,
|
|
3145
|
+
schemaProvider.getSchema(),
|
|
3146
|
+
requireName(body)
|
|
3147
|
+
);
|
|
3148
|
+
// Server utils examples tool
|
|
3149
|
+
case "nitro-graphql-server-utils-example":
|
|
3150
|
+
return handleGetServerUtilsExamples(
|
|
3151
|
+
collector,
|
|
3152
|
+
schemaProvider.getSchema(),
|
|
3153
|
+
requireName(body)
|
|
3154
|
+
);
|
|
3155
|
+
// Module config tool
|
|
3156
|
+
case "module-get-config":
|
|
3157
|
+
return handleGetModuleConfig(helper);
|
|
3158
|
+
default:
|
|
3159
|
+
throw createError({
|
|
3160
|
+
statusCode: 400,
|
|
3161
|
+
message: `Unknown tool: ${tool}`
|
|
3162
|
+
});
|
|
3163
|
+
}
|
|
3164
|
+
});
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
const module$1 = defineNuxtModule({
|
|
1726
3168
|
meta: {
|
|
1727
3169
|
name,
|
|
1728
3170
|
configKey: "graphqlMiddleware",
|
|
@@ -1783,22 +3225,36 @@ const module = defineNuxtModule({
|
|
|
1783
3225
|
collector.addTemplate(template);
|
|
1784
3226
|
}
|
|
1785
3227
|
});
|
|
1786
|
-
helper.
|
|
3228
|
+
if (helper.isDev) {
|
|
3229
|
+
const devModeHandler = new DevModeHandler(
|
|
3230
|
+
nuxt,
|
|
3231
|
+
schemaProvider,
|
|
3232
|
+
collector,
|
|
3233
|
+
helper
|
|
3234
|
+
);
|
|
3235
|
+
devModeHandler.init();
|
|
3236
|
+
}
|
|
3237
|
+
const mcpToolkitInstalled = nuxt.options.modules.some(
|
|
3238
|
+
(v) => v === "@nuxtjs/mcp-toolkit"
|
|
3239
|
+
);
|
|
3240
|
+
if (helper.isDev && mcpToolkitInstalled && helper.options.mcp.enabled) {
|
|
3241
|
+
nuxt.hook("mcp:definitions:paths", (paths) => {
|
|
3242
|
+
const mcpPath = helper.resolvers.module.resolve("./runtime/server/mcp");
|
|
3243
|
+
paths.handlers ||= [];
|
|
3244
|
+
paths.handlers.push(mcpPath);
|
|
3245
|
+
});
|
|
3246
|
+
addDevServerHandler({
|
|
3247
|
+
route: "/__nuxt_graphql_middleware/mcp",
|
|
3248
|
+
handler: createMcpDevHandler(collector, schemaProvider, helper)
|
|
3249
|
+
});
|
|
3250
|
+
helper.addServerHandler("doRequest", "/do-request", "post");
|
|
3251
|
+
}
|
|
1787
3252
|
nuxt.hooks.hookOnce("modules:done", async () => {
|
|
1788
3253
|
await nuxt.hooks.callHook("nuxt-graphql-middleware:init", moduleContext);
|
|
1789
3254
|
await collector.init();
|
|
1790
3255
|
});
|
|
1791
|
-
|
|
1792
|
-
return;
|
|
1793
|
-
}
|
|
1794
|
-
const devModeHandler = new DevModeHandler(
|
|
1795
|
-
nuxt,
|
|
1796
|
-
schemaProvider,
|
|
1797
|
-
collector,
|
|
1798
|
-
helper
|
|
1799
|
-
);
|
|
1800
|
-
devModeHandler.init();
|
|
3256
|
+
helper.applyBuildConfig();
|
|
1801
3257
|
}
|
|
1802
3258
|
});
|
|
1803
3259
|
|
|
1804
|
-
export { module as default };
|
|
3260
|
+
export { module$1 as default };
|