nitro-graphql 2.0.0-beta.31 → 2.0.0-beta.33
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/codegen/client-types.d.mts +13 -0
- package/dist/codegen/client-types.mjs +131 -0
- package/dist/codegen/external-types.d.mts +12 -0
- package/dist/codegen/external-types.mjs +88 -0
- package/dist/codegen/index.d.mts +18 -0
- package/dist/codegen/index.mjs +24 -0
- package/dist/codegen/server-types.d.mts +13 -0
- package/dist/codegen/server-types.mjs +64 -0
- package/dist/codegen/validation.d.mts +13 -0
- package/dist/codegen/validation.mjs +96 -0
- package/dist/config/defaults.mjs +36 -0
- package/dist/constants/scalars.mjs +27 -0
- package/dist/constants.mjs +106 -0
- package/dist/ecosystem/nuxt.mjs +3 -3
- package/dist/rollup.d.mts +2 -8
- package/dist/rollup.mjs +24 -199
- package/dist/routes/apollo-server.d.mts +2 -2
- package/dist/routes/apollo-server.mjs +7 -51
- package/dist/routes/debug-template.d.mts +15 -0
- package/dist/routes/debug-template.mjs +385 -0
- package/dist/routes/debug.d.mts +2 -2
- package/dist/routes/debug.mjs +1 -344
- package/dist/routes/graphql-yoga.d.mts +2 -2
- package/dist/routes/graphql-yoga.mjs +7 -51
- package/dist/routes/health.d.mts +2 -2
- package/dist/setup/file-watcher.mjs +84 -0
- package/dist/setup/graphql-scanner.mjs +25 -0
- package/dist/setup/rollup-integration.mjs +90 -0
- package/dist/setup/scaffold-generator.mjs +109 -0
- package/dist/setup/ts-config.mjs +69 -0
- package/dist/setup.d.mts +2 -2
- package/dist/setup.mjs +147 -303
- package/dist/types/index.d.mts +2 -2
- package/dist/utils/client-codegen.d.mts +1 -1
- package/dist/utils/client-codegen.mjs +5 -28
- package/dist/utils/codegen-plugin.d.mts +20 -0
- package/dist/utils/codegen-plugin.mjs +30 -0
- package/dist/utils/directive-parser.d.mts +2 -1
- package/dist/utils/directive-parser.mjs +4 -2
- package/dist/utils/federation.d.mts +29 -0
- package/dist/utils/federation.mjs +40 -0
- package/dist/utils/file-generator.mjs +1 -1
- package/dist/utils/file-writer.d.mts +35 -0
- package/dist/utils/file-writer.mjs +32 -0
- package/dist/utils/imports.d.mts +15 -0
- package/dist/utils/imports.mjs +25 -0
- package/dist/utils/index.d.mts +11 -38
- package/dist/utils/index.mjs +10 -287
- package/dist/utils/layers.d.mts +22 -0
- package/dist/utils/layers.mjs +28 -0
- package/dist/utils/ofetch-templates.d.mts +30 -0
- package/dist/utils/ofetch-templates.mjs +135 -0
- package/dist/utils/path-resolver.d.mts +2 -2
- package/dist/utils/path-resolver.mjs +2 -2
- package/dist/utils/scanning/common.d.mts +23 -0
- package/dist/utils/scanning/common.mjs +39 -0
- package/dist/utils/scanning/directives.d.mts +11 -0
- package/dist/utils/scanning/directives.mjs +43 -0
- package/dist/utils/scanning/documents.d.mts +15 -0
- package/dist/utils/scanning/documents.mjs +46 -0
- package/dist/utils/scanning/index.d.mts +6 -0
- package/dist/utils/scanning/index.mjs +7 -0
- package/dist/utils/scanning/resolvers.d.mts +11 -0
- package/dist/utils/scanning/resolvers.mjs +100 -0
- package/dist/utils/scanning/schemas.d.mts +15 -0
- package/dist/utils/scanning/schemas.mjs +29 -0
- package/dist/utils/schema-builder.d.mts +48 -0
- package/dist/utils/schema-builder.mjs +51 -0
- package/dist/utils/server-codegen.mjs +4 -27
- package/dist/utils/type-generation.d.mts +6 -12
- package/dist/utils/type-generation.mjs +6 -419
- package/dist/utils/validation.d.mts +11 -0
- package/dist/utils/validation.mjs +34 -0
- package/dist/virtual/generators/config.d.mts +22 -0
- package/dist/virtual/generators/config.mjs +36 -0
- package/dist/virtual/generators/debug.d.mts +14 -0
- package/dist/virtual/generators/debug.mjs +53 -0
- package/dist/virtual/generators/directives.d.mts +14 -0
- package/dist/virtual/generators/directives.mjs +52 -0
- package/dist/virtual/generators/index.d.mts +6 -0
- package/dist/virtual/generators/index.mjs +7 -0
- package/dist/virtual/generators/resolvers.d.mts +14 -0
- package/dist/virtual/generators/resolvers.mjs +55 -0
- package/dist/virtual/generators/schemas.d.mts +14 -0
- package/dist/virtual/generators/schemas.mjs +43 -0
- package/package.json +75 -57
|
@@ -181,9 +181,10 @@ function generateDirectiveSchema(directive) {
|
|
|
181
181
|
}
|
|
182
182
|
/**
|
|
183
183
|
* Generate directive schemas file from scanned directives
|
|
184
|
+
* @returns The path to the generated _directives.graphql file, or null if no directives
|
|
184
185
|
*/
|
|
185
186
|
async function generateDirectiveSchemas(nitro, directives) {
|
|
186
|
-
if (directives.length === 0) return;
|
|
187
|
+
if (directives.length === 0) return null;
|
|
187
188
|
const { existsSync, readFileSync, writeFileSync, mkdirSync } = await import("node:fs");
|
|
188
189
|
const { readFile } = await import("node:fs/promises");
|
|
189
190
|
const { resolve, dirname } = await import("pathe");
|
|
@@ -212,8 +213,9 @@ ${directiveSchemas.join("\n\n")}`;
|
|
|
212
213
|
let shouldWrite = true;
|
|
213
214
|
if (existsSync(directivesPath)) shouldWrite = readFileSync(directivesPath, "utf-8") !== content;
|
|
214
215
|
if (shouldWrite) writeFileSync(directivesPath, content, "utf-8");
|
|
215
|
-
|
|
216
|
+
return directivesPath;
|
|
216
217
|
}
|
|
218
|
+
return null;
|
|
217
219
|
}
|
|
218
220
|
/**
|
|
219
221
|
* Singleton instance for reuse
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DocumentNode, GraphQLSchema } from "graphql";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/federation.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Type for buildSubgraphSchema function from @apollo/subgraph
|
|
7
|
+
*/
|
|
8
|
+
type BuildSubgraphSchemaFn = (options: {
|
|
9
|
+
typeDefs: DocumentNode;
|
|
10
|
+
resolvers: Record<string, unknown>;
|
|
11
|
+
}) => GraphQLSchema;
|
|
12
|
+
/**
|
|
13
|
+
* Dynamically load @apollo/subgraph for federation support.
|
|
14
|
+
* Returns the buildSubgraphSchema function if available, or false if the package is not installed.
|
|
15
|
+
* Result is cached for subsequent calls.
|
|
16
|
+
*/
|
|
17
|
+
declare function loadFederationSupport(): Promise<BuildSubgraphSchemaFn | false>;
|
|
18
|
+
/**
|
|
19
|
+
* Log a warning when federation is enabled but @apollo/subgraph is not available.
|
|
20
|
+
* Uses consola logger instead of console.warn for consistent logging.
|
|
21
|
+
*/
|
|
22
|
+
declare function warnFederationUnavailable(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Reset the federation support cache.
|
|
25
|
+
* Useful for testing or when the module needs to be reloaded.
|
|
26
|
+
*/
|
|
27
|
+
declare function resetFederationCache(): void;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { loadFederationSupport, resetFederationCache, warnFederationUnavailable };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LOG_TAG } from "../constants.mjs";
|
|
2
|
+
import { consola as consola$1 } from "consola";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/federation.ts
|
|
5
|
+
const logger = consola$1.withTag(LOG_TAG);
|
|
6
|
+
/**
|
|
7
|
+
* Cached result: function if available, false if not available, null if not checked yet
|
|
8
|
+
*/
|
|
9
|
+
let buildSubgraphSchemaCache = null;
|
|
10
|
+
/**
|
|
11
|
+
* Dynamically load @apollo/subgraph for federation support.
|
|
12
|
+
* Returns the buildSubgraphSchema function if available, or false if the package is not installed.
|
|
13
|
+
* Result is cached for subsequent calls.
|
|
14
|
+
*/
|
|
15
|
+
async function loadFederationSupport() {
|
|
16
|
+
if (buildSubgraphSchemaCache !== null) return buildSubgraphSchemaCache;
|
|
17
|
+
try {
|
|
18
|
+
buildSubgraphSchemaCache = (await import("@apollo/subgraph")).buildSubgraphSchema;
|
|
19
|
+
} catch {
|
|
20
|
+
buildSubgraphSchemaCache = false;
|
|
21
|
+
}
|
|
22
|
+
return buildSubgraphSchemaCache;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Log a warning when federation is enabled but @apollo/subgraph is not available.
|
|
26
|
+
* Uses consola logger instead of console.warn for consistent logging.
|
|
27
|
+
*/
|
|
28
|
+
function warnFederationUnavailable() {
|
|
29
|
+
logger.warn("Federation enabled but @apollo/subgraph not available, falling back to regular schema");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Reset the federation support cache.
|
|
33
|
+
* Useful for testing or when the module needs to be reloaded.
|
|
34
|
+
*/
|
|
35
|
+
function resetFederationCache() {
|
|
36
|
+
buildSubgraphSchemaCache = null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { loadFederationSupport, resetFederationCache, warnFederationUnavailable };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { PathPlaceholders } from "./path-resolver.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/file-writer.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for writing generated files
|
|
7
|
+
*/
|
|
8
|
+
interface WriteGeneratedFileOptions {
|
|
9
|
+
/** Path configuration (string path, boolean, or undefined) */
|
|
10
|
+
pathConfig: string | boolean | undefined;
|
|
11
|
+
/** Whether the category is enabled */
|
|
12
|
+
categoryEnabled: boolean | undefined;
|
|
13
|
+
/** Default path template with placeholders */
|
|
14
|
+
defaultPath: string;
|
|
15
|
+
/** Content to write */
|
|
16
|
+
content: string;
|
|
17
|
+
/** Path placeholders for resolution */
|
|
18
|
+
placeholders: PathPlaceholders;
|
|
19
|
+
/** Description for logging (e.g., "client types", "SDK") */
|
|
20
|
+
description: string;
|
|
21
|
+
/** Whether to suppress success logs */
|
|
22
|
+
silent?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Write a generated file with path resolution and directory creation
|
|
26
|
+
* Returns the resolved path if file was written, undefined otherwise
|
|
27
|
+
*/
|
|
28
|
+
declare function writeGeneratedFile(options: WriteGeneratedFileOptions): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Write multiple generated files
|
|
31
|
+
* Returns array of resolved paths for files that were written
|
|
32
|
+
*/
|
|
33
|
+
declare function writeGeneratedFiles(files: WriteGeneratedFileOptions[]): (string | undefined)[];
|
|
34
|
+
//#endregion
|
|
35
|
+
export { WriteGeneratedFileOptions, writeGeneratedFile, writeGeneratedFiles };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { LOG_TAG } from "../constants.mjs";
|
|
2
|
+
import { resolveFilePath } from "./path-resolver.mjs";
|
|
3
|
+
import consola from "consola";
|
|
4
|
+
import { dirname } from "pathe";
|
|
5
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
|
+
|
|
7
|
+
//#region src/utils/file-writer.ts
|
|
8
|
+
const logger = consola.withTag(LOG_TAG);
|
|
9
|
+
/**
|
|
10
|
+
* Write a generated file with path resolution and directory creation
|
|
11
|
+
* Returns the resolved path if file was written, undefined otherwise
|
|
12
|
+
*/
|
|
13
|
+
function writeGeneratedFile(options) {
|
|
14
|
+
const { pathConfig, categoryEnabled, defaultPath, content, placeholders, description, silent = false } = options;
|
|
15
|
+
const resolvedPath = resolveFilePath(pathConfig, categoryEnabled, true, defaultPath, placeholders);
|
|
16
|
+
if (resolvedPath) {
|
|
17
|
+
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
18
|
+
writeFileSync(resolvedPath, content, "utf-8");
|
|
19
|
+
if (!silent) logger.success(`Generated ${description} at: ${resolvedPath}`);
|
|
20
|
+
return resolvedPath;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Write multiple generated files
|
|
25
|
+
* Returns array of resolved paths for files that were written
|
|
26
|
+
*/
|
|
27
|
+
function writeGeneratedFiles(files) {
|
|
28
|
+
return files.map((file) => writeGeneratedFile(file));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { writeGeneratedFile, writeGeneratedFiles };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/utils/imports.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Import utilities
|
|
4
|
+
* Helpers for generating import IDs and relative paths
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generate a unique import ID for a file path
|
|
8
|
+
*/
|
|
9
|
+
declare function getImportId(p: string, lazy?: boolean): string;
|
|
10
|
+
/**
|
|
11
|
+
* Get relative path with a leading dot for module resolution
|
|
12
|
+
*/
|
|
13
|
+
declare function relativeWithDot(from: string, to: string): string;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { getImportId, relativeWithDot };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { relative } from "pathe";
|
|
2
|
+
import { hash } from "ohash";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/imports.ts
|
|
5
|
+
/**
|
|
6
|
+
* Import utilities
|
|
7
|
+
* Helpers for generating import IDs and relative paths
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Generate a unique import ID for a file path
|
|
11
|
+
*/
|
|
12
|
+
function getImportId(p, lazy) {
|
|
13
|
+
return (lazy ? "_lazy_" : "_") + hash(p).replace(/-/g, "").slice(0, 6);
|
|
14
|
+
}
|
|
15
|
+
const RELATIVE_RE = /^\.{1,2}\//;
|
|
16
|
+
/**
|
|
17
|
+
* Get relative path with a leading dot for module resolution
|
|
18
|
+
*/
|
|
19
|
+
function relativeWithDot(from, to) {
|
|
20
|
+
const rel = relative(from, to);
|
|
21
|
+
return RELATIVE_RE.test(rel) ? rel : `./${rel}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { getImportId, relativeWithDot };
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,40 +1,13 @@
|
|
|
1
|
-
import { GenImport } from "../types/index.mjs";
|
|
2
1
|
import { directiveParser, generateDirectiveSchema, generateDirectiveSchemas } from "./directive-parser.mjs";
|
|
3
2
|
import { createDefaultMaskError } from "./errors.mjs";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
declare function getLayerServerDirectories(nitro: Nitro): string[];
|
|
16
|
-
/**
|
|
17
|
-
* Get all Nuxt layer app directories from Nitro config
|
|
18
|
-
*/
|
|
19
|
-
declare function getLayerAppDirectories(nitro: Nitro): string[];
|
|
20
|
-
/**
|
|
21
|
-
* Generate layer-aware ignore patterns for auto-generated files
|
|
22
|
-
*/
|
|
23
|
-
declare function generateLayerIgnorePatterns(): string[];
|
|
24
|
-
declare function getImportId(p: string, lazy?: boolean): string;
|
|
25
|
-
declare function relativeWithDot(from: string, to: string): string;
|
|
26
|
-
declare function scanGraphql(nitro: Nitro): Promise<string[]>;
|
|
27
|
-
declare function scanResolvers(nitro: Nitro): Promise<GenImport[]>;
|
|
28
|
-
declare function scanDirectives(nitro: Nitro): Promise<GenImport[]>;
|
|
29
|
-
declare function scanSchemas(nitro: Nitro): Promise<string[]>;
|
|
30
|
-
declare function scanDocs(nitro: Nitro): Promise<string[]>;
|
|
31
|
-
/**
|
|
32
|
-
* Scan documents for a specific external service
|
|
33
|
-
*/
|
|
34
|
-
declare function scanExternalServiceDocs(nitro: Nitro, serviceName: string, patterns: string[]): Promise<string[]>;
|
|
35
|
-
/**
|
|
36
|
-
* Validate external GraphQL service configuration
|
|
37
|
-
*/
|
|
38
|
-
declare function validateExternalServices(services: unknown[]): string[];
|
|
39
|
-
//#endregion
|
|
40
|
-
export { GLOB_SCAN_PATTERN, createDefaultMaskError, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };
|
|
3
|
+
import { loadFederationSupport, resetFederationCache, warnFederationUnavailable } from "./federation.mjs";
|
|
4
|
+
import { getImportId, relativeWithDot } from "./imports.mjs";
|
|
5
|
+
import { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories } from "./layers.mjs";
|
|
6
|
+
import { FileInfo, deduplicateFiles, scanDir } from "./scanning/common.mjs";
|
|
7
|
+
import { scanDirectives } from "./scanning/directives.mjs";
|
|
8
|
+
import { scanDocuments, scanExternalServiceDocs } from "./scanning/documents.mjs";
|
|
9
|
+
import { scanResolvers } from "./scanning/resolvers.mjs";
|
|
10
|
+
import { scanGraphql, scanSchemas } from "./scanning/schemas.mjs";
|
|
11
|
+
import "./scanning/index.mjs";
|
|
12
|
+
import { validateExternalServices } from "./validation.mjs";
|
|
13
|
+
export { type FileInfo, createDefaultMaskError, deduplicateFiles, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, loadFederationSupport, relativeWithDot, resetFederationCache, scanDir, scanDirectives, scanDocuments, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices, warnFederationUnavailable };
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,290 +1,13 @@
|
|
|
1
|
+
import { loadFederationSupport, resetFederationCache, warnFederationUnavailable } from "./federation.mjs";
|
|
1
2
|
import { directiveParser, generateDirectiveSchema, generateDirectiveSchemas } from "./directive-parser.mjs";
|
|
2
3
|
import { createDefaultMaskError } from "./errors.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { getImportId, relativeWithDot } from "./imports.mjs";
|
|
5
|
+
import { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories } from "./layers.mjs";
|
|
6
|
+
import { deduplicateFiles, scanDir } from "./scanning/common.mjs";
|
|
7
|
+
import { scanDirectives } from "./scanning/directives.mjs";
|
|
8
|
+
import { scanDocuments, scanExternalServiceDocs } from "./scanning/documents.mjs";
|
|
9
|
+
import { scanResolvers } from "./scanning/resolvers.mjs";
|
|
10
|
+
import { scanGraphql, scanSchemas } from "./scanning/schemas.mjs";
|
|
11
|
+
import { validateExternalServices } from "./validation.mjs";
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
const GLOB_SCAN_PATTERN = "**/*.{graphql,gql,js,mjs,cjs,ts,mts,cts,tsx,jsx}";
|
|
11
|
-
/**
|
|
12
|
-
* Get all Nuxt layer directories from Nitro config
|
|
13
|
-
*/
|
|
14
|
-
function getLayerDirectories(nitro) {
|
|
15
|
-
return nitro.options.graphql?.layerDirectories || [];
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Get all Nuxt layer server directories from Nitro config
|
|
19
|
-
*/
|
|
20
|
-
function getLayerServerDirectories(nitro) {
|
|
21
|
-
return nitro.options.graphql?.layerServerDirs || [];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Get all Nuxt layer app directories from Nitro config
|
|
25
|
-
*/
|
|
26
|
-
function getLayerAppDirectories(nitro) {
|
|
27
|
-
return nitro.options.graphql?.layerAppDirs || [];
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Generate layer-aware ignore patterns for auto-generated files
|
|
31
|
-
*/
|
|
32
|
-
function generateLayerIgnorePatterns() {
|
|
33
|
-
return [];
|
|
34
|
-
}
|
|
35
|
-
function getImportId(p, lazy) {
|
|
36
|
-
return (lazy ? "_lazy_" : "_") + hash(p).replace(/-/g, "").slice(0, 6);
|
|
37
|
-
}
|
|
38
|
-
const RELATIVE_RE = /^\.{1,2}\//;
|
|
39
|
-
function relativeWithDot(from, to) {
|
|
40
|
-
const rel = relative(from, to);
|
|
41
|
-
return RELATIVE_RE.test(rel) ? rel : `./${rel}`;
|
|
42
|
-
}
|
|
43
|
-
async function scanGraphql(nitro) {
|
|
44
|
-
const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
45
|
-
const files = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.{graphql,gql}");
|
|
46
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
47
|
-
const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.{graphql,gql}"))).then((r) => r.flat());
|
|
48
|
-
const allFiles = [...files, ...layerFiles];
|
|
49
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
50
|
-
return allFiles.filter((file) => {
|
|
51
|
-
if (seenPaths.has(file.fullPath)) return false;
|
|
52
|
-
seenPaths.add(file.fullPath);
|
|
53
|
-
return true;
|
|
54
|
-
}).map((f) => f.fullPath);
|
|
55
|
-
}
|
|
56
|
-
async function scanResolvers(nitro) {
|
|
57
|
-
const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
58
|
-
const regularFiles = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.resolver.{ts,js}");
|
|
59
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
60
|
-
const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.resolver.{ts,js}"))).then((r) => r.flat());
|
|
61
|
-
const allFiles = [...regularFiles, ...layerFiles];
|
|
62
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
63
|
-
const files = allFiles.filter((file) => {
|
|
64
|
-
if (seenPaths.has(file.fullPath)) return false;
|
|
65
|
-
seenPaths.add(file.fullPath);
|
|
66
|
-
return true;
|
|
67
|
-
});
|
|
68
|
-
const exportName = [];
|
|
69
|
-
const VALID_DEFINE_FUNCTIONS = [
|
|
70
|
-
"defineResolver",
|
|
71
|
-
"defineQuery",
|
|
72
|
-
"defineMutation",
|
|
73
|
-
"defineField",
|
|
74
|
-
"defineSubscription",
|
|
75
|
-
"defineDirective"
|
|
76
|
-
];
|
|
77
|
-
for (const file of files) try {
|
|
78
|
-
const fileContent = await readFile(file.fullPath, "utf-8");
|
|
79
|
-
const parsed = parseSync(file.fullPath, fileContent);
|
|
80
|
-
if (parsed.errors && parsed.errors.length > 0) {
|
|
81
|
-
if (nitro.options.dev) {
|
|
82
|
-
const fileName = basename(file.fullPath);
|
|
83
|
-
const firstError = parsed.errors[0];
|
|
84
|
-
const location = firstError?.labels?.[0];
|
|
85
|
-
const lineInfo = location ? `:${location.start}` : "";
|
|
86
|
-
const message = firstError?.message.split(",")[0] || "Syntax error";
|
|
87
|
-
console.error(`✖ ${fileName}${lineInfo} - ${message}`);
|
|
88
|
-
}
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const exports = {
|
|
92
|
-
imports: [],
|
|
93
|
-
specifier: file.fullPath
|
|
94
|
-
};
|
|
95
|
-
let hasDefaultExport = false;
|
|
96
|
-
let hasNamedExport = false;
|
|
97
|
-
const namedExports = [];
|
|
98
|
-
for (const node of parsed.program.body) {
|
|
99
|
-
if (node.type === "ExportDefaultDeclaration") hasDefaultExport = true;
|
|
100
|
-
if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
|
|
101
|
-
for (const decl of node.declaration.declarations) if (decl.type === "VariableDeclarator" && decl.init && decl.id.type === "Identifier") {
|
|
102
|
-
hasNamedExport = true;
|
|
103
|
-
namedExports.push(decl.id.name);
|
|
104
|
-
if (decl.init && decl.init.type === "CallExpression") {
|
|
105
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineResolver") exports.imports.push({
|
|
106
|
-
name: decl.id.name,
|
|
107
|
-
type: "resolver",
|
|
108
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
109
|
-
});
|
|
110
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineQuery") exports.imports.push({
|
|
111
|
-
name: decl.id.name,
|
|
112
|
-
type: "query",
|
|
113
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
114
|
-
});
|
|
115
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineMutation") exports.imports.push({
|
|
116
|
-
name: decl.id.name,
|
|
117
|
-
type: "mutation",
|
|
118
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
119
|
-
});
|
|
120
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineField") exports.imports.push({
|
|
121
|
-
name: decl.id.name,
|
|
122
|
-
type: "type",
|
|
123
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
124
|
-
});
|
|
125
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineSubscription") exports.imports.push({
|
|
126
|
-
name: decl.id.name,
|
|
127
|
-
type: "subscription",
|
|
128
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
129
|
-
});
|
|
130
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineDirective") exports.imports.push({
|
|
131
|
-
name: decl.id.name,
|
|
132
|
-
type: "directive",
|
|
133
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (nitro.options.dev) {
|
|
140
|
-
const relPath = relative(nitro.options.rootDir, file.fullPath);
|
|
141
|
-
if (hasDefaultExport && !hasNamedExport) nitro.logger.warn(`[nitro-graphql] ${relPath}: Using default export instead of named export. Resolvers must use named exports like "export const myResolver = defineQuery(...)". Default exports are not detected.`);
|
|
142
|
-
if (exports.imports.length === 0 && hasNamedExport) {
|
|
143
|
-
const validFunctions = VALID_DEFINE_FUNCTIONS.join(", ");
|
|
144
|
-
nitro.logger.warn(`[nitro-graphql] ${relPath}: File has named exports [${namedExports.join(", ")}] but none use the required define functions (${validFunctions}). Exports will not be registered.`);
|
|
145
|
-
}
|
|
146
|
-
if (!hasDefaultExport && !hasNamedExport) nitro.logger.warn(`[nitro-graphql] ${relPath}: No exports found. Resolver files must export resolvers using defineResolver, defineQuery, defineMutation, etc.`);
|
|
147
|
-
}
|
|
148
|
-
if (exports.imports.length > 0) exportName.push(exports);
|
|
149
|
-
} catch (error) {
|
|
150
|
-
const relPath = relative(nitro.options.rootDir, file.fullPath);
|
|
151
|
-
nitro.logger.error(`[nitro-graphql] Failed to parse resolver file ${relPath}:`, error);
|
|
152
|
-
}
|
|
153
|
-
return exportName;
|
|
154
|
-
}
|
|
155
|
-
async function scanDirectives(nitro) {
|
|
156
|
-
const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
157
|
-
const regularFiles = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.directive.{ts,js}");
|
|
158
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
159
|
-
const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.directive.{ts,js}"))).then((r) => r.flat());
|
|
160
|
-
const allFiles = [...regularFiles, ...layerFiles];
|
|
161
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
162
|
-
const files = allFiles.filter((file) => {
|
|
163
|
-
if (seenPaths.has(file.fullPath)) return false;
|
|
164
|
-
seenPaths.add(file.fullPath);
|
|
165
|
-
return true;
|
|
166
|
-
});
|
|
167
|
-
const exportName = [];
|
|
168
|
-
for (const file of files) {
|
|
169
|
-
const fileContent = await readFile(file.fullPath, "utf-8");
|
|
170
|
-
const parsed = parseSync(file.fullPath, fileContent);
|
|
171
|
-
const exports = {
|
|
172
|
-
imports: [],
|
|
173
|
-
specifier: file.fullPath
|
|
174
|
-
};
|
|
175
|
-
for (const node of parsed.program.body) if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
|
|
176
|
-
for (const decl of node.declaration.declarations) if (decl.type === "VariableDeclarator" && decl.init && decl.id.type === "Identifier") {
|
|
177
|
-
if (decl.init && decl.init.type === "CallExpression") {
|
|
178
|
-
if (decl.init.callee.type === "Identifier" && decl.init.callee.name === "defineDirective") exports.imports.push({
|
|
179
|
-
name: decl.id.name,
|
|
180
|
-
type: "directive",
|
|
181
|
-
as: `_${hash(decl.id.name + file.fullPath).replace(/-/g, "").slice(0, 6)}`
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (exports.imports.length > 0) exportName.push(exports);
|
|
187
|
-
}
|
|
188
|
-
return exportName;
|
|
189
|
-
}
|
|
190
|
-
async function scanSchemas(nitro) {
|
|
191
|
-
const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
192
|
-
const files = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.graphql");
|
|
193
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
194
|
-
const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.graphql"))).then((r) => r.flat());
|
|
195
|
-
const allFiles = [...files, ...layerFiles];
|
|
196
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
197
|
-
return allFiles.filter((file) => {
|
|
198
|
-
if (seenPaths.has(file.fullPath)) return false;
|
|
199
|
-
seenPaths.add(file.fullPath);
|
|
200
|
-
return true;
|
|
201
|
-
}).map((f) => f.fullPath);
|
|
202
|
-
}
|
|
203
|
-
async function scanDocs(nitro) {
|
|
204
|
-
const files = await scanDir(nitro, nitro.options.rootDir, nitro.graphql.dir.client, "**/*.graphql");
|
|
205
|
-
const layerAppDirs = getLayerAppDirectories(nitro);
|
|
206
|
-
const layerFiles = await Promise.all(layerAppDirs.map((layerAppDir) => scanDir(nitro, layerAppDir, "graphql", "**/*.graphql"))).then((r) => r.flat());
|
|
207
|
-
const combinedFiles = [...files, ...layerFiles];
|
|
208
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
209
|
-
const allFiles = combinedFiles.filter((file) => {
|
|
210
|
-
if (seenPaths.has(file.fullPath)) return false;
|
|
211
|
-
seenPaths.add(file.fullPath);
|
|
212
|
-
return true;
|
|
213
|
-
});
|
|
214
|
-
const externalPatterns = (nitro.options.graphql?.externalServices || []).flatMap((service) => service.documents || []);
|
|
215
|
-
return allFiles.filter((f) => !f.path.startsWith("external/")).filter((f) => {
|
|
216
|
-
const relativePath = f.path;
|
|
217
|
-
for (const pattern of externalPatterns) {
|
|
218
|
-
const clientDirPattern = `${nitro.graphql.dir.client}/`;
|
|
219
|
-
if (pattern.replace(/* @__PURE__ */ new RegExp(`^${clientDirPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "").split("/")[0] === relativePath.split("/")[0]) return false;
|
|
220
|
-
}
|
|
221
|
-
return true;
|
|
222
|
-
}).map((f) => f.fullPath);
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Scan documents for a specific external service
|
|
226
|
-
*/
|
|
227
|
-
async function scanExternalServiceDocs(nitro, serviceName, patterns) {
|
|
228
|
-
if (!patterns.length) return [];
|
|
229
|
-
const files = [];
|
|
230
|
-
for (const pattern of patterns) try {
|
|
231
|
-
const serviceFiles = await glob(pattern, {
|
|
232
|
-
cwd: nitro.options.rootDir,
|
|
233
|
-
dot: true,
|
|
234
|
-
ignore: nitro.options.ignore,
|
|
235
|
-
absolute: true
|
|
236
|
-
});
|
|
237
|
-
files.push(...serviceFiles);
|
|
238
|
-
} catch (error) {
|
|
239
|
-
nitro.logger.warn(`[graphql:${serviceName}] Error scanning documents with pattern "${pattern}":`, error);
|
|
240
|
-
}
|
|
241
|
-
return files.filter((file, index, self) => self.indexOf(file) === index);
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Validate external GraphQL service configuration
|
|
245
|
-
*/
|
|
246
|
-
function validateExternalServices(services) {
|
|
247
|
-
const errors = [];
|
|
248
|
-
const serviceNames = /* @__PURE__ */ new Set();
|
|
249
|
-
for (const [index, service] of services.entries()) {
|
|
250
|
-
const prefix = `externalServices[${index}]`;
|
|
251
|
-
if (!service || typeof service !== "object") {
|
|
252
|
-
errors.push(`${prefix} must be an object`);
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
if (!("name" in service) || typeof service.name !== "string") errors.push(`${prefix}.name is required and must be a string`);
|
|
256
|
-
else if (serviceNames.has(service.name)) errors.push(`${prefix}.name "${service.name}" must be unique`);
|
|
257
|
-
else serviceNames.add(service.name);
|
|
258
|
-
if (!("schema" in service) || !service.schema) errors.push(`${prefix}.schema is required`);
|
|
259
|
-
if (!("endpoint" in service) || typeof service.endpoint !== "string") errors.push(`${prefix}.endpoint is required and must be a string`);
|
|
260
|
-
else try {
|
|
261
|
-
new URL(service.endpoint);
|
|
262
|
-
} catch {
|
|
263
|
-
errors.push(`${prefix}.endpoint "${service.endpoint}" must be a valid URL`);
|
|
264
|
-
}
|
|
265
|
-
if ("name" in service && service.name && typeof service.name === "string" && !/^[a-z]\w*$/i.test(service.name)) errors.push(`${prefix}.name "${service.name}" must be a valid identifier (letters, numbers, underscore, starting with letter)`);
|
|
266
|
-
}
|
|
267
|
-
return errors;
|
|
268
|
-
}
|
|
269
|
-
async function scanDir(nitro, dir, name, globPattern = GLOB_SCAN_PATTERN) {
|
|
270
|
-
return (await glob(join(name, globPattern), {
|
|
271
|
-
cwd: dir,
|
|
272
|
-
dot: true,
|
|
273
|
-
ignore: nitro.options.ignore,
|
|
274
|
-
absolute: true
|
|
275
|
-
}).catch((error) => {
|
|
276
|
-
if (error?.code === "ENOTDIR") {
|
|
277
|
-
nitro.logger.warn(`Ignoring \`${join(dir, name)}\`. It must be a directory.`);
|
|
278
|
-
return [];
|
|
279
|
-
}
|
|
280
|
-
throw error;
|
|
281
|
-
})).map((fullPath) => {
|
|
282
|
-
return {
|
|
283
|
-
fullPath,
|
|
284
|
-
path: relative(join(dir, name), fullPath)
|
|
285
|
-
};
|
|
286
|
-
}).sort((a, b) => a.path.localeCompare(b.path));
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
//#endregion
|
|
290
|
-
export { GLOB_SCAN_PATTERN, createDefaultMaskError, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };
|
|
13
|
+
export { createDefaultMaskError, deduplicateFiles, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, loadFederationSupport, relativeWithDot, resetFederationCache, scanDir, scanDirectives, scanDocuments, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices, warnFederationUnavailable };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Nitro } from "nitro/types";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/layers.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get all Nuxt layer directories from Nitro config
|
|
7
|
+
*/
|
|
8
|
+
declare function getLayerDirectories(nitro: Nitro): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Get all Nuxt layer server directories from Nitro config
|
|
11
|
+
*/
|
|
12
|
+
declare function getLayerServerDirectories(nitro: Nitro): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Get all Nuxt layer app directories from Nitro config
|
|
15
|
+
*/
|
|
16
|
+
declare function getLayerAppDirectories(nitro: Nitro): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Generate layer-aware ignore patterns for auto-generated files
|
|
19
|
+
*/
|
|
20
|
+
declare function generateLayerIgnorePatterns(): string[];
|
|
21
|
+
//#endregion
|
|
22
|
+
export { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/utils/layers.ts
|
|
2
|
+
/**
|
|
3
|
+
* Get all Nuxt layer directories from Nitro config
|
|
4
|
+
*/
|
|
5
|
+
function getLayerDirectories(nitro) {
|
|
6
|
+
return nitro.options.graphql?.layerDirectories || [];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get all Nuxt layer server directories from Nitro config
|
|
10
|
+
*/
|
|
11
|
+
function getLayerServerDirectories(nitro) {
|
|
12
|
+
return nitro.options.graphql?.layerServerDirs || [];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get all Nuxt layer app directories from Nitro config
|
|
16
|
+
*/
|
|
17
|
+
function getLayerAppDirectories(nitro) {
|
|
18
|
+
return nitro.options.graphql?.layerAppDirs || [];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generate layer-aware ignore patterns for auto-generated files
|
|
22
|
+
*/
|
|
23
|
+
function generateLayerIgnorePatterns() {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/utils/ofetch-templates.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared ofetch template generation utilities
|
|
4
|
+
* Used by both main client and external service code generation
|
|
5
|
+
*/
|
|
6
|
+
interface OfetchTemplateOptions {
|
|
7
|
+
/** Service name (e.g., 'default', 'github') */
|
|
8
|
+
serviceName: string;
|
|
9
|
+
/** Whether to use Nuxt composables ($fetch, useRequestHeaders) */
|
|
10
|
+
isNuxt: boolean;
|
|
11
|
+
/** Endpoint URL for the GraphQL service */
|
|
12
|
+
endpoint: string;
|
|
13
|
+
/** Whether this is an external service (affects naming convention) */
|
|
14
|
+
isExternal?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate ofetch client template content
|
|
18
|
+
*
|
|
19
|
+
* For main (default) service:
|
|
20
|
+
* - SDK exported as `$sdk`
|
|
21
|
+
* - Client function is `createGraphQLClient`
|
|
22
|
+
*
|
|
23
|
+
* For external services:
|
|
24
|
+
* - SDK exported as `$${serviceName}Sdk`
|
|
25
|
+
* - Client function is `create${ServiceName}GraphQLClient`
|
|
26
|
+
* - Endpoint has default value
|
|
27
|
+
*/
|
|
28
|
+
declare function generateOfetchTemplate(options: OfetchTemplateOptions): string;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { OfetchTemplateOptions, generateOfetchTemplate };
|