nitro-graphql 2.0.0-beta.32 → 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.
Files changed (71) hide show
  1. package/dist/codegen/client-types.mjs +9 -54
  2. package/dist/codegen/external-types.mjs +7 -48
  3. package/dist/codegen/index.d.mts +4 -11
  4. package/dist/codegen/index.mjs +1 -15
  5. package/dist/codegen/server-types.mjs +2 -14
  6. package/dist/constants/scalars.mjs +27 -0
  7. package/dist/constants.mjs +16 -1
  8. package/dist/rollup.d.mts +1 -7
  9. package/dist/rollup.mjs +12 -187
  10. package/dist/routes/apollo-server.d.mts +2 -2
  11. package/dist/routes/apollo-server.mjs +7 -51
  12. package/dist/routes/debug-template.d.mts +15 -0
  13. package/dist/routes/debug-template.mjs +385 -0
  14. package/dist/routes/debug.d.mts +2 -2
  15. package/dist/routes/debug.mjs +1 -344
  16. package/dist/routes/graphql-yoga.d.mts +2 -2
  17. package/dist/routes/graphql-yoga.mjs +7 -51
  18. package/dist/routes/health.d.mts +2 -2
  19. package/dist/setup/file-watcher.mjs +9 -5
  20. package/dist/setup/graphql-scanner.mjs +25 -0
  21. package/dist/setup/scaffold-generator.mjs +1 -1
  22. package/dist/setup/ts-config.mjs +1 -1
  23. package/dist/setup.mjs +38 -47
  24. package/dist/types/index.d.mts +1 -1
  25. package/dist/utils/client-codegen.mjs +4 -30
  26. package/dist/utils/codegen-plugin.d.mts +20 -0
  27. package/dist/utils/codegen-plugin.mjs +30 -0
  28. package/dist/utils/federation.d.mts +29 -0
  29. package/dist/utils/federation.mjs +40 -0
  30. package/dist/utils/file-writer.d.mts +35 -0
  31. package/dist/utils/file-writer.mjs +32 -0
  32. package/dist/utils/imports.d.mts +15 -0
  33. package/dist/utils/imports.mjs +25 -0
  34. package/dist/utils/index.d.mts +11 -38
  35. package/dist/utils/index.mjs +10 -287
  36. package/dist/utils/layers.d.mts +22 -0
  37. package/dist/utils/layers.mjs +28 -0
  38. package/dist/utils/ofetch-templates.d.mts +30 -0
  39. package/dist/utils/ofetch-templates.mjs +135 -0
  40. package/dist/utils/scanning/common.d.mts +23 -0
  41. package/dist/utils/scanning/common.mjs +39 -0
  42. package/dist/utils/scanning/directives.d.mts +11 -0
  43. package/dist/utils/scanning/directives.mjs +43 -0
  44. package/dist/utils/scanning/documents.d.mts +15 -0
  45. package/dist/utils/scanning/documents.mjs +46 -0
  46. package/dist/utils/scanning/index.d.mts +6 -0
  47. package/dist/utils/scanning/index.mjs +7 -0
  48. package/dist/utils/scanning/resolvers.d.mts +11 -0
  49. package/dist/utils/scanning/resolvers.mjs +100 -0
  50. package/dist/utils/scanning/schemas.d.mts +15 -0
  51. package/dist/utils/scanning/schemas.mjs +29 -0
  52. package/dist/utils/schema-builder.d.mts +48 -0
  53. package/dist/utils/schema-builder.mjs +51 -0
  54. package/dist/utils/server-codegen.mjs +3 -29
  55. package/dist/utils/type-generation.d.mts +2 -2
  56. package/dist/utils/type-generation.mjs +2 -2
  57. package/dist/utils/validation.d.mts +11 -0
  58. package/dist/utils/validation.mjs +34 -0
  59. package/dist/virtual/generators/config.d.mts +22 -0
  60. package/dist/virtual/generators/config.mjs +36 -0
  61. package/dist/virtual/generators/debug.d.mts +14 -0
  62. package/dist/virtual/generators/debug.mjs +53 -0
  63. package/dist/virtual/generators/directives.d.mts +14 -0
  64. package/dist/virtual/generators/directives.mjs +52 -0
  65. package/dist/virtual/generators/index.d.mts +6 -0
  66. package/dist/virtual/generators/index.mjs +7 -0
  67. package/dist/virtual/generators/resolvers.d.mts +14 -0
  68. package/dist/virtual/generators/resolvers.mjs +55 -0
  69. package/dist/virtual/generators/schemas.d.mts +14 -0
  70. package/dist/virtual/generators/schemas.mjs +43 -0
  71. package/package.json +73 -61
@@ -1,10 +1,10 @@
1
1
  import { StandardSchemaV1 } from "./standard-schema.mjs";
2
- import { ESMCodeGenOptions } from "knitwork";
3
2
  import { TypeScriptPluginConfig } from "@graphql-codegen/typescript";
4
3
  import { plugin as plugin$1 } from "@graphql-codegen/typescript-generic-sdk";
5
4
  import { TypeScriptDocumentsPluginConfig } from "@graphql-codegen/typescript-operations";
6
5
  import { IResolvers } from "@graphql-tools/utils";
7
6
  import { TypeScriptResolversPluginConfig } from "@graphql-codegen/typescript-resolvers";
7
+ import { ESMCodeGenOptions } from "knitwork";
8
8
 
9
9
  //#region src/types/index.d.ts
10
10
  type CodegenServerConfig = TypeScriptPluginConfig & TypeScriptResolversPluginConfig;
@@ -1,8 +1,10 @@
1
+ import { DEFAULT_GRAPHQL_SCALARS } from "../constants/scalars.mjs";
2
+ import { pluginContent } from "./codegen-plugin.mjs";
1
3
  import { defu as defu$1 } from "defu";
2
4
  import { consola as consola$1 } from "consola";
3
5
  import { dirname, resolve } from "pathe";
4
- import { parse } from "graphql";
5
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { parse } from "graphql";
6
8
  import { createHash } from "node:crypto";
7
9
  import { codegen } from "@graphql-codegen/core";
8
10
  import { preset } from "@graphql-codegen/import-types-preset";
@@ -13,24 +15,8 @@ import { GraphQLFileLoader } from "@graphql-tools/graphql-file-loader";
13
15
  import { loadDocuments, loadSchemaSync } from "@graphql-tools/load";
14
16
  import { UrlLoader } from "@graphql-tools/url-loader";
15
17
  import { printSchemaWithDirectives } from "@graphql-tools/utils";
16
- import { CurrencyResolver, DateTimeISOResolver, DateTimeResolver, JSONObjectResolver, JSONResolver, NonEmptyStringResolver, UUIDResolver } from "graphql-scalars";
17
18
 
18
19
  //#region src/utils/client-codegen.ts
19
- /**
20
- * Plugin to add prepend comments to generated files
21
- */
22
- function pluginContent(_schema, _documents, _config, _info) {
23
- return {
24
- prepend: [
25
- "// THIS FILE IS GENERATED, DO NOT EDIT!",
26
- "/* eslint-disable eslint-comments/no-unlimited-disable */",
27
- "/* tslint:disable */",
28
- "/* eslint-disable */",
29
- "/* prettier-ignore */"
30
- ],
31
- content: ""
32
- };
33
- }
34
20
  async function graphQLLoadSchemaSync(schemaPointers, data = {}) {
35
21
  const filteredPointers = [...Array.isArray(schemaPointers) ? schemaPointers : [schemaPointers], "!**/vfs/**"];
36
22
  let result;
@@ -185,19 +171,7 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
185
171
  pureMagicComment: true,
186
172
  dedupeOperationSuffix: true,
187
173
  rawRequest: true,
188
- scalars: {
189
- DateTime: DateTimeResolver.extensions.codegenScalarType,
190
- DateTimeISO: DateTimeISOResolver.extensions.codegenScalarType,
191
- UUID: UUIDResolver.extensions.codegenScalarType,
192
- JSON: JSONResolver.extensions.codegenScalarType,
193
- JSONObject: JSONObjectResolver.extensions.codegenScalarType,
194
- NonEmptyString: NonEmptyStringResolver.extensions.codegenScalarType,
195
- Currency: CurrencyResolver.extensions.codegenScalarType,
196
- File: {
197
- input: "File",
198
- output: "File"
199
- }
200
- }
174
+ scalars: DEFAULT_GRAPHQL_SCALARS
201
175
  }, config);
202
176
  const mergedSdkConfig = defu$1(mergedConfig, sdkConfig);
203
177
  try {
@@ -0,0 +1,20 @@
1
+ import { GraphQLSchema } from "graphql";
2
+ import { Source } from "@graphql-tools/utils";
3
+
4
+ //#region src/utils/codegen-plugin.d.ts
5
+
6
+ /**
7
+ * Plugin to add prepend comments to generated files
8
+ * Used by both server and client codegen
9
+ */
10
+ declare function pluginContent(_schema: GraphQLSchema, _documents: Source[], _config: Record<string, unknown> | undefined, _info: Record<string, unknown> | undefined): {
11
+ prepend: string[];
12
+ content: string;
13
+ };
14
+ /**
15
+ * Generate the prepend header for generated files
16
+ * Can be used when creating files manually without codegen
17
+ */
18
+ declare const GENERATED_FILE_HEADER = "// THIS FILE IS GENERATED, DO NOT EDIT!\n/* eslint-disable eslint-comments/no-unlimited-disable */\n/* tslint:disable */\n/* eslint-disable */\n/* prettier-ignore */\n";
19
+ //#endregion
20
+ export { GENERATED_FILE_HEADER, pluginContent };
@@ -0,0 +1,30 @@
1
+ //#region src/utils/codegen-plugin.ts
2
+ /**
3
+ * Plugin to add prepend comments to generated files
4
+ * Used by both server and client codegen
5
+ */
6
+ function pluginContent(_schema, _documents, _config, _info) {
7
+ return {
8
+ prepend: [
9
+ "// THIS FILE IS GENERATED, DO NOT EDIT!",
10
+ "/* eslint-disable eslint-comments/no-unlimited-disable */",
11
+ "/* tslint:disable */",
12
+ "/* eslint-disable */",
13
+ "/* prettier-ignore */"
14
+ ],
15
+ content: ""
16
+ };
17
+ }
18
+ /**
19
+ * Generate the prepend header for generated files
20
+ * Can be used when creating files manually without codegen
21
+ */
22
+ const GENERATED_FILE_HEADER = `// THIS FILE IS GENERATED, DO NOT EDIT!
23
+ /* eslint-disable eslint-comments/no-unlimited-disable */
24
+ /* tslint:disable */
25
+ /* eslint-disable */
26
+ /* prettier-ignore */
27
+ `;
28
+
29
+ //#endregion
30
+ export { GENERATED_FILE_HEADER, pluginContent };
@@ -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 };
@@ -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 { Nitro } from "nitro/types";
5
-
6
- //#region src/utils/index.d.ts
7
- declare const GLOB_SCAN_PATTERN = "**/*.{graphql,gql,js,mjs,cjs,ts,mts,cts,tsx,jsx}";
8
- /**
9
- * Get all Nuxt layer directories from Nitro config
10
- */
11
- declare function getLayerDirectories(nitro: Nitro): string[];
12
- /**
13
- * Get all Nuxt layer server directories from Nitro config
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 scanDocuments(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, scanDocuments, 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 };
@@ -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 { readFile } from "node:fs/promises";
4
- import { basename, join, relative } from "pathe";
5
- import { hash } from "ohash";
6
- import { parseSync } from "oxc-parser";
7
- import { glob } from "tinyglobby";
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
- //#region src/utils/index.ts
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 scanDocuments(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, scanDocuments, 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 };