nitro-graphql 2.0.0-beta.4 → 2.0.0-beta.40
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 +441 -27
- package/dist/cli/commands/generate.d.mts +26 -0
- package/dist/cli/commands/generate.mjs +196 -0
- package/dist/cli/commands/index.d.mts +4 -0
- package/dist/cli/commands/index.mjs +5 -0
- package/dist/cli/commands/init.d.mts +46 -0
- package/dist/cli/commands/init.mjs +195 -0
- package/dist/cli/commands/validate.d.mts +10 -0
- package/dist/cli/commands/validate.mjs +69 -0
- package/dist/cli/completions.d.mts +7 -0
- package/dist/cli/completions.mjs +34 -0
- package/dist/cli/config.d.mts +75 -0
- package/dist/cli/config.mjs +20 -0
- package/dist/cli/index.d.mts +24 -0
- package/dist/cli/index.mjs +253 -0
- package/dist/core/codegen/client.d.mts +23 -0
- package/dist/core/codegen/client.mjs +150 -0
- package/dist/core/codegen/document-loader.d.mts +10 -0
- package/dist/core/codegen/document-loader.mjs +18 -0
- package/dist/core/codegen/index.d.mts +8 -0
- package/dist/core/codegen/index.mjs +9 -0
- package/dist/core/codegen/plugin.d.mts +20 -0
- package/dist/core/codegen/plugin.mjs +30 -0
- package/dist/core/codegen/runtime.d.mts +20 -0
- package/dist/core/codegen/runtime.mjs +60 -0
- package/dist/core/codegen/schema-loader.d.mts +28 -0
- package/dist/core/codegen/schema-loader.mjs +128 -0
- package/dist/core/codegen/server.d.mts +28 -0
- package/dist/core/codegen/server.mjs +143 -0
- package/dist/core/codegen/validation.d.mts +13 -0
- package/dist/core/codegen/validation.mjs +96 -0
- package/dist/core/config.d.mts +50 -0
- package/dist/core/config.mjs +82 -0
- package/dist/core/constants.d.mts +188 -0
- package/dist/core/constants.mjs +210 -0
- package/dist/core/index.d.mts +32 -0
- package/dist/core/index.mjs +26 -0
- package/dist/core/scanning/ast-scanner.d.mts +23 -0
- package/dist/core/scanning/ast-scanner.mjs +103 -0
- package/dist/core/scanning/common.d.mts +37 -0
- package/dist/core/scanning/common.mjs +60 -0
- package/dist/core/scanning/directives.d.mts +10 -0
- package/dist/core/scanning/directives.mjs +29 -0
- package/dist/core/scanning/documents.d.mts +21 -0
- package/dist/core/scanning/documents.mjs +43 -0
- package/dist/core/scanning/index.d.mts +7 -0
- package/dist/core/scanning/index.mjs +8 -0
- package/dist/core/scanning/resolvers.d.mts +10 -0
- package/dist/core/scanning/resolvers.mjs +58 -0
- package/dist/core/scanning/schemas.d.mts +14 -0
- package/dist/core/scanning/schemas.mjs +64 -0
- package/dist/core/schema/builder.d.mts +53 -0
- package/dist/core/schema/builder.mjs +70 -0
- package/dist/core/schema/federation.d.mts +34 -0
- package/dist/core/schema/federation.mjs +40 -0
- package/dist/core/schema/index.d.mts +3 -0
- package/dist/core/schema/index.mjs +4 -0
- package/dist/core/types/adapter.d.mts +58 -0
- package/dist/core/types/codegen.d.mts +133 -0
- package/dist/core/types/config.d.mts +212 -0
- package/dist/core/types/config.mjs +1 -0
- package/dist/{utils/define.d.ts → core/types/define.d.mts} +3 -30
- package/dist/core/types/define.mjs +1 -0
- package/dist/core/types/index.d.mts +5 -0
- package/dist/core/types/index.mjs +1 -0
- package/dist/core/types/scanning.d.mts +69 -0
- package/dist/core/types/scanning.mjs +1 -0
- package/dist/{utils/directive-parser.d.ts → core/utils/directive-parser.d.mts} +21 -4
- package/dist/{utils/directive-parser.js → core/utils/directive-parser.mjs} +25 -34
- package/dist/core/utils/errors.d.mts +77 -0
- package/dist/core/utils/errors.mjs +93 -0
- package/dist/core/utils/file-io.d.mts +24 -0
- package/dist/core/utils/file-io.mjs +47 -0
- package/dist/core/utils/imports.d.mts +15 -0
- package/dist/core/utils/imports.mjs +25 -0
- package/dist/core/utils/index.d.mts +7 -0
- package/dist/core/utils/index.mjs +8 -0
- package/dist/core/utils/logger.d.mts +19 -0
- package/dist/core/utils/logger.mjs +38 -0
- package/dist/core/utils/ofetch-templates.d.mts +30 -0
- package/dist/core/utils/ofetch-templates.mjs +135 -0
- package/dist/core/validation/external-services.d.mts +11 -0
- package/dist/core/validation/external-services.mjs +34 -0
- package/dist/core/validation/index.d.mts +2 -0
- package/dist/core/validation/index.mjs +3 -0
- package/dist/define.d.mts +294 -0
- package/dist/define.mjs +323 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +6 -0
- package/dist/nitro/adapter.d.mts +30 -0
- package/dist/nitro/adapter.mjs +97 -0
- package/dist/{utils/apollo.d.ts → nitro/apollo.d.mts} +3 -3
- package/dist/nitro/apollo.mjs +59 -0
- package/dist/nitro/codegen.d.mts +19 -0
- package/dist/nitro/codegen.mjs +141 -0
- package/dist/nitro/config.d.mts +52 -0
- package/dist/nitro/config.mjs +58 -0
- package/dist/nitro/index.d.mts +46 -0
- package/dist/nitro/index.mjs +65 -0
- package/dist/nitro/paths.d.mts +54 -0
- package/dist/nitro/paths.mjs +93 -0
- package/dist/nitro/rollup.d.mts +6 -0
- package/dist/nitro/rollup.mjs +95 -0
- package/dist/nitro/routes/apollo-server.d.mts +6 -0
- package/dist/nitro/routes/apollo-server.mjs +71 -0
- package/dist/nitro/routes/debug-template.d.mts +15 -0
- package/dist/nitro/routes/debug-template.mjs +385 -0
- package/dist/nitro/routes/debug.d.mts +55 -0
- package/dist/nitro/routes/debug.mjs +102 -0
- package/dist/nitro/routes/graphql-yoga.d.mts +6 -0
- package/dist/nitro/routes/graphql-yoga.mjs +62 -0
- package/dist/nitro/routes/health.d.mts +10 -0
- package/dist/{routes/health.js → nitro/routes/health.mjs} +4 -3
- package/dist/nitro/setup/file-watcher.d.mts +16 -0
- package/dist/nitro/setup/file-watcher.mjs +80 -0
- package/dist/nitro/setup/logging.d.mts +17 -0
- package/dist/nitro/setup/logging.mjs +66 -0
- package/dist/nitro/setup/rollup-integration.d.mts +16 -0
- package/dist/nitro/setup/rollup-integration.mjs +90 -0
- package/dist/nitro/setup/routes.d.mts +10 -0
- package/dist/nitro/setup/routes.mjs +35 -0
- package/dist/nitro/setup/ts-config.d.mts +11 -0
- package/dist/nitro/setup/ts-config.mjs +69 -0
- package/dist/nitro/setup.d.mts +12 -0
- package/dist/nitro/setup.mjs +231 -0
- package/dist/nitro/types.d.mts +378 -0
- package/dist/nitro/types.mjs +1 -0
- package/dist/nitro/virtual/generators.d.mts +31 -0
- package/dist/nitro/virtual/generators.mjs +193 -0
- package/dist/nitro/virtual/stubs.d.mts +20 -0
- package/dist/nitro/virtual/stubs.mjs +31 -0
- package/dist/{ecosystem/nuxt.d.ts → nuxt.d.mts} +1 -1
- package/dist/nuxt.mjs +109 -0
- package/dist/{graphql/server.d.ts → stubs/index.d.mts} +5 -1
- package/dist/stubs/index.mjs +1 -0
- package/package.json +97 -78
- package/dist/ecosystem/nuxt.js +0 -67
- package/dist/graphql/index.d.ts +0 -5
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -264
- package/dist/rollup.js +0 -119
- package/dist/routes/apollo-server.d.ts +0 -6
- package/dist/routes/apollo-server.js +0 -89
- package/dist/routes/graphql-yoga.d.ts +0 -6
- package/dist/routes/graphql-yoga.js +0 -91
- package/dist/routes/health.d.ts +0 -6
- package/dist/types/index.d.ts +0 -128
- package/dist/types/standard-schema.d.ts +0 -59
- package/dist/utils/apollo.js +0 -61
- package/dist/utils/client-codegen.d.ts +0 -38
- package/dist/utils/client-codegen.js +0 -290
- package/dist/utils/define.js +0 -57
- package/dist/utils/index.d.ts +0 -39
- package/dist/utils/index.js +0 -250
- package/dist/utils/server-codegen.d.ts +0 -7
- package/dist/utils/server-codegen.js +0 -136
- package/dist/utils/type-generation.d.ts +0 -7
- package/dist/utils/type-generation.js +0 -287
- package/dist/vite.d.ts +0 -25
- package/dist/vite.js +0 -40
- /package/dist/{graphql/index.js → core/types/adapter.mjs} +0 -0
- /package/dist/{graphql/server.js → core/types/codegen.mjs} +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { writeFile } from "../utils/file-io.mjs";
|
|
2
|
+
import { resolve } from "pathe";
|
|
3
|
+
import { printSchemaWithDirectives } from "@graphql-tools/utils";
|
|
4
|
+
import { GraphQLFileLoader } from "@graphql-tools/graphql-file-loader";
|
|
5
|
+
import { loadSchemaSync } from "@graphql-tools/load";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
8
|
+
import { UrlLoader } from "@graphql-tools/url-loader";
|
|
9
|
+
|
|
10
|
+
//#region src/core/codegen/schema-loader.ts
|
|
11
|
+
/**
|
|
12
|
+
* Check if a path is a URL
|
|
13
|
+
*/
|
|
14
|
+
function isUrl(path) {
|
|
15
|
+
return path.startsWith("http://") || path.startsWith("https://");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load GraphQL schema synchronously
|
|
19
|
+
*/
|
|
20
|
+
function graphQLLoadSchemaSync(schemaPointers, data = {}) {
|
|
21
|
+
const filteredPointers = [...Array.isArray(schemaPointers) ? schemaPointers : [schemaPointers], "!**/vfs/**"];
|
|
22
|
+
try {
|
|
23
|
+
return loadSchemaSync(filteredPointers, {
|
|
24
|
+
...data,
|
|
25
|
+
loaders: [
|
|
26
|
+
new GraphQLFileLoader(),
|
|
27
|
+
new UrlLoader(),
|
|
28
|
+
...data.loaders || []
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
} catch (e) {
|
|
32
|
+
if ((e.message || "").includes("Unable to find any GraphQL type definitions for the following pointers:")) return;
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Load schema from external GraphQL service
|
|
38
|
+
*/
|
|
39
|
+
async function loadExternalSchema(service, buildDir) {
|
|
40
|
+
try {
|
|
41
|
+
const headers = typeof service.headers === "function" ? service.headers() : service.headers || {};
|
|
42
|
+
const schemaSource = service.schema ?? service.endpoint;
|
|
43
|
+
const schemas = Array.isArray(schemaSource) ? schemaSource : [schemaSource];
|
|
44
|
+
if (service.downloadSchema && buildDir) {
|
|
45
|
+
const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
|
|
46
|
+
const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
|
|
47
|
+
if (existsSync(schemaFilePath)) try {
|
|
48
|
+
return loadSchemaSync([schemaFilePath], { loaders: [new GraphQLFileLoader()] });
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
const hasUrls = schemas.some((schema) => isUrl(schema));
|
|
52
|
+
const hasLocalFiles = schemas.some((schema) => !isUrl(schema));
|
|
53
|
+
const loaders = [];
|
|
54
|
+
if (hasLocalFiles) loaders.push(new GraphQLFileLoader());
|
|
55
|
+
if (hasUrls) loaders.push(new UrlLoader());
|
|
56
|
+
if (loaders.length === 0) throw new Error("No appropriate loaders found for schema sources");
|
|
57
|
+
return loadSchemaSync(schemas, {
|
|
58
|
+
loaders,
|
|
59
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Download and save schema from external service
|
|
67
|
+
*/
|
|
68
|
+
async function downloadAndSaveSchema(service, buildDir) {
|
|
69
|
+
const downloadMode = service.downloadSchema;
|
|
70
|
+
if (!downloadMode || downloadMode === "manual") return;
|
|
71
|
+
const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
|
|
72
|
+
const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
|
|
73
|
+
try {
|
|
74
|
+
const headers = typeof service.headers === "function" ? service.headers() : service.headers || {};
|
|
75
|
+
const schemaSource = service.schema ?? service.endpoint;
|
|
76
|
+
const schemas = Array.isArray(schemaSource) ? schemaSource : [schemaSource];
|
|
77
|
+
const hasUrlSchemas = schemas.some((schema) => isUrl(schema));
|
|
78
|
+
const hasLocalSchemas = schemas.some((schema) => !isUrl(schema));
|
|
79
|
+
let shouldDownload = false;
|
|
80
|
+
const fileExists = existsSync(schemaFilePath);
|
|
81
|
+
if (downloadMode === "always") {
|
|
82
|
+
shouldDownload = true;
|
|
83
|
+
if (fileExists && hasUrlSchemas) try {
|
|
84
|
+
const remoteSchemaString = printSchemaWithDirectives(loadSchemaSync(schemas.filter(isUrl), {
|
|
85
|
+
loaders: [new UrlLoader()],
|
|
86
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
87
|
+
}));
|
|
88
|
+
const remoteHash = createHash("md5").update(remoteSchemaString).digest("hex");
|
|
89
|
+
const localSchemaString = readFileSync(schemaFilePath, "utf-8");
|
|
90
|
+
if (remoteHash === createHash("md5").update(localSchemaString).digest("hex")) shouldDownload = false;
|
|
91
|
+
} catch {
|
|
92
|
+
shouldDownload = true;
|
|
93
|
+
}
|
|
94
|
+
else if (fileExists && hasLocalSchemas) {
|
|
95
|
+
const localFiles = schemas.filter((schema) => !isUrl(schema));
|
|
96
|
+
let sourceIsNewer = false;
|
|
97
|
+
for (const localFile of localFiles) if (existsSync(localFile)) {
|
|
98
|
+
const sourceStats = statSync(localFile);
|
|
99
|
+
const cachedStats = statSync(schemaFilePath);
|
|
100
|
+
if (sourceStats.mtime > cachedStats.mtime) {
|
|
101
|
+
sourceIsNewer = true;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!sourceIsNewer) shouldDownload = false;
|
|
106
|
+
}
|
|
107
|
+
} else if (downloadMode === true || downloadMode === "once") shouldDownload = !fileExists;
|
|
108
|
+
if (shouldDownload) {
|
|
109
|
+
let schema;
|
|
110
|
+
if (hasUrlSchemas && hasLocalSchemas) schema = loadSchemaSync(schemas, {
|
|
111
|
+
loaders: [new GraphQLFileLoader(), new UrlLoader()],
|
|
112
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
113
|
+
});
|
|
114
|
+
else if (hasUrlSchemas) schema = loadSchemaSync(schemas, {
|
|
115
|
+
loaders: [new UrlLoader()],
|
|
116
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
117
|
+
});
|
|
118
|
+
else schema = loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] });
|
|
119
|
+
writeFile(schemaFilePath, printSchemaWithDirectives(schema));
|
|
120
|
+
}
|
|
121
|
+
return schemaFilePath;
|
|
122
|
+
} catch {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
export { downloadAndSaveSchema, graphQLLoadSchemaSync, loadExternalSchema };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ServerCodegenConfig, ServerCodegenInput, ServerCodegenResult } from "../types/codegen.mjs";
|
|
2
|
+
import { GraphQLSchema } from "graphql";
|
|
3
|
+
|
|
4
|
+
//#region src/core/codegen/server.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Default server codegen configuration
|
|
8
|
+
*/
|
|
9
|
+
declare const DEFAULT_SERVER_CODEGEN_CONFIG: ServerCodegenConfig;
|
|
10
|
+
/**
|
|
11
|
+
* Generate server-side GraphQL types
|
|
12
|
+
* Pure function that generates TypeScript types from a GraphQL schema
|
|
13
|
+
*/
|
|
14
|
+
declare function generateServerTypesCore(input: ServerCodegenInput): Promise<ServerCodegenResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Generate types from schema (simplified version for direct use)
|
|
17
|
+
* @deprecated Use generateServerTypesCore instead
|
|
18
|
+
*/
|
|
19
|
+
declare function generateTypes(framework: string, schema: GraphQLSchema, config?: {
|
|
20
|
+
codegen?: {
|
|
21
|
+
server?: ServerCodegenConfig;
|
|
22
|
+
};
|
|
23
|
+
federation?: {
|
|
24
|
+
enabled?: boolean;
|
|
25
|
+
};
|
|
26
|
+
}, outputPath?: string): Promise<string>;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore, generateTypes };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { DEFAULT_GRAPHQL_SCALARS } from "../constants.mjs";
|
|
2
|
+
import { pluginContent } from "./plugin.mjs";
|
|
3
|
+
import { defu as defu$1 } from "defu";
|
|
4
|
+
import { codegen } from "@graphql-codegen/core";
|
|
5
|
+
import * as typescriptPlugin from "@graphql-codegen/typescript";
|
|
6
|
+
import { printSchemaWithDirectives } from "@graphql-tools/utils";
|
|
7
|
+
import { parse } from "graphql";
|
|
8
|
+
import * as typescriptResolversPlugin from "@graphql-codegen/typescript-resolvers";
|
|
9
|
+
|
|
10
|
+
//#region src/core/codegen/server.ts
|
|
11
|
+
/**
|
|
12
|
+
* Default server codegen configuration
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_SERVER_CODEGEN_CONFIG = {
|
|
15
|
+
scalars: DEFAULT_GRAPHQL_SCALARS,
|
|
16
|
+
defaultScalarType: "unknown",
|
|
17
|
+
defaultMapper: `ResolverReturnType<{T}>`,
|
|
18
|
+
contextType: "nitro/h3#H3Event",
|
|
19
|
+
maybeValue: "T | null | undefined",
|
|
20
|
+
inputMaybeValue: "T | undefined",
|
|
21
|
+
declarationKind: "interface",
|
|
22
|
+
enumsAsTypes: true
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Generate server-side GraphQL types
|
|
26
|
+
* Pure function that generates TypeScript types from a GraphQL schema
|
|
27
|
+
*/
|
|
28
|
+
async function generateServerTypesCore(input) {
|
|
29
|
+
const { framework, schema, config = {}, federationEnabled = false, outputPath } = input;
|
|
30
|
+
const mergedConfig = defu$1({
|
|
31
|
+
...DEFAULT_SERVER_CODEGEN_CONFIG,
|
|
32
|
+
...federationEnabled && { federation: true }
|
|
33
|
+
}, config);
|
|
34
|
+
const schemaString = printSchemaWithDirectives(schema);
|
|
35
|
+
return {
|
|
36
|
+
types: await codegen({
|
|
37
|
+
filename: outputPath || "types.generated.ts",
|
|
38
|
+
schema: parse(schemaString),
|
|
39
|
+
documents: [],
|
|
40
|
+
config: mergedConfig,
|
|
41
|
+
plugins: [
|
|
42
|
+
{ imports: {} },
|
|
43
|
+
{ pluginContent: {} },
|
|
44
|
+
{ typescript: {} },
|
|
45
|
+
{ typescriptResolvers: {} }
|
|
46
|
+
],
|
|
47
|
+
pluginMap: {
|
|
48
|
+
pluginContent: { plugin: pluginContent },
|
|
49
|
+
imports: { plugin: () => {
|
|
50
|
+
return {
|
|
51
|
+
prepend: [
|
|
52
|
+
`import schemas from '#graphql/schema'`,
|
|
53
|
+
`import type { StandardSchemaV1 } from 'nitro-graphql/types'`,
|
|
54
|
+
generateServerTypeHelpers(framework),
|
|
55
|
+
""
|
|
56
|
+
],
|
|
57
|
+
content: ""
|
|
58
|
+
};
|
|
59
|
+
} },
|
|
60
|
+
typescript: typescriptPlugin,
|
|
61
|
+
typescriptResolvers: typescriptResolversPlugin
|
|
62
|
+
}
|
|
63
|
+
}),
|
|
64
|
+
schemaString
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate server type helper code
|
|
69
|
+
*/
|
|
70
|
+
function generateServerTypeHelpers(framework) {
|
|
71
|
+
return `
|
|
72
|
+
export interface NPMConfig {
|
|
73
|
+
framework: '${framework || "graphql-yoga"}';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type SchemaType = Partial<Record<Partial<keyof ResolversTypes>, StandardSchemaV1>>
|
|
77
|
+
|
|
78
|
+
// Check if schemas is empty object, return never if so
|
|
79
|
+
type SafeSchemaKeys<T> = T extends Record<PropertyKey, never>
|
|
80
|
+
? never
|
|
81
|
+
: keyof T extends string | number | symbol
|
|
82
|
+
? keyof T extends never
|
|
83
|
+
? never
|
|
84
|
+
: keyof T
|
|
85
|
+
: never;
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
type SchemaKeys = SafeSchemaKeys<typeof schemas>;
|
|
89
|
+
|
|
90
|
+
type InferInput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferInput<T> : unknown;
|
|
91
|
+
type InferOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T> : unknown;
|
|
92
|
+
|
|
93
|
+
type InferInputFromSchema<T extends SchemaKeys> = InferInput<(typeof schemas)[T]>;
|
|
94
|
+
type InferOutputFromSchema<T extends SchemaKeys> = InferOutput<(typeof schemas)[T]>;
|
|
95
|
+
|
|
96
|
+
type Primitive =
|
|
97
|
+
| null
|
|
98
|
+
| undefined
|
|
99
|
+
| string
|
|
100
|
+
| number
|
|
101
|
+
| boolean
|
|
102
|
+
| symbol
|
|
103
|
+
| bigint;
|
|
104
|
+
|
|
105
|
+
type BuiltIns = Primitive | void | Date | RegExp;
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
type ResolverReturnType<T> = T extends BuiltIns
|
|
109
|
+
? T
|
|
110
|
+
: T extends (...args: any[]) => unknown
|
|
111
|
+
? T | undefined
|
|
112
|
+
: T extends object
|
|
113
|
+
? T extends Array<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
114
|
+
? ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
115
|
+
? Array<ResolverReturnType<ItemType>>
|
|
116
|
+
: ResolverReturnTypeObject<T> // Tuples behave properly
|
|
117
|
+
: ResolverReturnTypeObject<T>
|
|
118
|
+
: unknown;
|
|
119
|
+
|
|
120
|
+
type ResolverReturnTypeObject<T extends object> =
|
|
121
|
+
T extends { __typename?: infer TTypename }
|
|
122
|
+
? TTypename extends SchemaKeys
|
|
123
|
+
? InferOutputFromSchema<TTypename>
|
|
124
|
+
: { [K in keyof T]: ResolverReturnType<T[K]> }
|
|
125
|
+
: { [K in keyof T]: ResolverReturnType<T[K]> };
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Generate types from schema (simplified version for direct use)
|
|
130
|
+
* @deprecated Use generateServerTypesCore instead
|
|
131
|
+
*/
|
|
132
|
+
async function generateTypes(framework, schema, config = {}, outputPath) {
|
|
133
|
+
return (await generateServerTypesCore({
|
|
134
|
+
framework,
|
|
135
|
+
schema,
|
|
136
|
+
config: config.codegen?.server,
|
|
137
|
+
federationEnabled: config.federation?.enabled,
|
|
138
|
+
outputPath
|
|
139
|
+
})).types;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { DEFAULT_SERVER_CODEGEN_CONFIG, generateServerTypesCore, generateTypes };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/core/codegen/validation.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* GraphQL schema validation utilities
|
|
4
|
+
* Validates schemas for duplicate type definitions and conflicts
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check for duplicate type definitions using a simpler approach
|
|
8
|
+
* Try to build each schema individually - if that succeeds but merging fails, we have duplicates
|
|
9
|
+
* @returns true if validation passes, false if duplicates found
|
|
10
|
+
*/
|
|
11
|
+
declare function validateNoDuplicateTypes(schemas: string[], schemaStrings: string[]): boolean;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { validateNoDuplicateTypes };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { BUILTIN_SCALARS } from "../constants.mjs";
|
|
2
|
+
import consola from "consola";
|
|
3
|
+
import { basename } from "pathe";
|
|
4
|
+
import { parse } from "graphql";
|
|
5
|
+
import { mergeTypeDefs } from "@graphql-tools/merge";
|
|
6
|
+
|
|
7
|
+
//#region src/core/codegen/validation.ts
|
|
8
|
+
/**
|
|
9
|
+
* GraphQL schema validation utilities
|
|
10
|
+
* Validates schemas for duplicate type definitions and conflicts
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Check for duplicate type definitions using a simpler approach
|
|
14
|
+
* Try to build each schema individually - if that succeeds but merging fails, we have duplicates
|
|
15
|
+
* @returns true if validation passes, false if duplicates found
|
|
16
|
+
*/
|
|
17
|
+
function validateNoDuplicateTypes(schemas, schemaStrings) {
|
|
18
|
+
const individualSchemasByFile = /* @__PURE__ */ new Map();
|
|
19
|
+
schemaStrings.forEach((schemaContent, index) => {
|
|
20
|
+
const schemaPath = schemas[index];
|
|
21
|
+
const fileName = basename(schemaPath);
|
|
22
|
+
try {
|
|
23
|
+
parse(schemaContent);
|
|
24
|
+
individualSchemasByFile.set(fileName, schemaContent);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
consola.warn(`Invalid GraphQL syntax in ${fileName}:`, error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
mergeTypeDefs([schemaStrings.join("\n\n")], {
|
|
32
|
+
throwOnConflict: false,
|
|
33
|
+
commentDescriptions: true,
|
|
34
|
+
sort: true
|
|
35
|
+
});
|
|
36
|
+
mergeTypeDefs([schemaStrings.join("\n\n")], {
|
|
37
|
+
throwOnConflict: true,
|
|
38
|
+
commentDescriptions: true,
|
|
39
|
+
sort: true
|
|
40
|
+
});
|
|
41
|
+
} catch (conflictError) {
|
|
42
|
+
if (conflictError?.message?.includes("already defined with a different type")) throw conflictError;
|
|
43
|
+
}
|
|
44
|
+
const typeNames = /* @__PURE__ */ new Set();
|
|
45
|
+
const duplicateTypes = [];
|
|
46
|
+
schemaStrings.forEach((schemaContent, index) => {
|
|
47
|
+
const fileName = basename(schemas[index]);
|
|
48
|
+
try {
|
|
49
|
+
parse(schemaContent).definitions.forEach((def) => {
|
|
50
|
+
if (def.kind === "ObjectTypeDefinition" || def.kind === "InterfaceTypeDefinition" || def.kind === "UnionTypeDefinition" || def.kind === "EnumTypeDefinition" || def.kind === "InputObjectTypeDefinition" || def.kind === "ScalarTypeDefinition") {
|
|
51
|
+
const typeName = def.name.value;
|
|
52
|
+
if (BUILTIN_SCALARS.includes(typeName)) return;
|
|
53
|
+
if (typeNames.has(typeName)) {
|
|
54
|
+
const existing = duplicateTypes.find((d) => d.type === typeName);
|
|
55
|
+
if (existing) existing.files.push(fileName);
|
|
56
|
+
else {
|
|
57
|
+
const firstFile = schemas.find((_, i) => {
|
|
58
|
+
const content = schemaStrings[i];
|
|
59
|
+
if (!content) return false;
|
|
60
|
+
try {
|
|
61
|
+
return parse(content).definitions.some((d) => (d.kind === "ObjectTypeDefinition" || d.kind === "InterfaceTypeDefinition" || d.kind === "UnionTypeDefinition" || d.kind === "EnumTypeDefinition" || d.kind === "InputObjectTypeDefinition" || d.kind === "ScalarTypeDefinition") && d.name.value === typeName);
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
duplicateTypes.push({
|
|
67
|
+
type: typeName,
|
|
68
|
+
files: [basename(firstFile || ""), fileName]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
} else typeNames.add(typeName);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
} catch {}
|
|
75
|
+
});
|
|
76
|
+
if (duplicateTypes.length > 0) {
|
|
77
|
+
let errorMessage = "⚠️ DUPLICATE TYPE DEFINITIONS DETECTED!\n\n";
|
|
78
|
+
duplicateTypes.forEach(({ type, files }) => {
|
|
79
|
+
errorMessage += `❌ Type "${type}" is defined in multiple files:\n`;
|
|
80
|
+
files.forEach((fileName) => {
|
|
81
|
+
const fullPath = schemas.find((path) => basename(path) === fileName) || fileName;
|
|
82
|
+
errorMessage += ` • ${fullPath}\n`;
|
|
83
|
+
});
|
|
84
|
+
errorMessage += "\n";
|
|
85
|
+
});
|
|
86
|
+
errorMessage += "💡 Each GraphQL type should only be defined once.\n";
|
|
87
|
+
errorMessage += " Consider using \"extend type\" syntax instead of duplicate definitions.\n";
|
|
88
|
+
errorMessage += `\n🔍 Found ${duplicateTypes.length} duplicate type(s): ${duplicateTypes.map((d) => d.type).join(", ")}`;
|
|
89
|
+
consola.error(errorMessage);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { validateNoDuplicateTypes };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CoreConfig, CoreContext, CoreGraphQLOptions, CoreLogger } from "./types/config.mjs";
|
|
2
|
+
import { ScanContext } from "./types/scanning.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/config.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Options for creating a CoreConfig
|
|
8
|
+
*/
|
|
9
|
+
interface CreateCoreConfigOptions {
|
|
10
|
+
/** Root directory of the project */
|
|
11
|
+
rootDir: string;
|
|
12
|
+
/** Build directory (optional, defaults based on framework) */
|
|
13
|
+
buildDir?: string;
|
|
14
|
+
/** Server GraphQL directory (optional) */
|
|
15
|
+
serverDir?: string;
|
|
16
|
+
/** Client GraphQL directory (optional) */
|
|
17
|
+
clientDir?: string;
|
|
18
|
+
/** Whether running in Nuxt context */
|
|
19
|
+
isNuxt?: boolean;
|
|
20
|
+
/** Whether running in development mode */
|
|
21
|
+
isDev?: boolean;
|
|
22
|
+
/** GraphQL options */
|
|
23
|
+
graphqlOptions?: CoreGraphQLOptions;
|
|
24
|
+
/** Custom logger */
|
|
25
|
+
logger?: CoreLogger;
|
|
26
|
+
/** Patterns to ignore */
|
|
27
|
+
ignorePatterns?: string[];
|
|
28
|
+
/** Layer server directories */
|
|
29
|
+
layerServerDirs?: string[];
|
|
30
|
+
/** Layer app directories */
|
|
31
|
+
layerAppDirs?: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a CoreConfig with sensible defaults
|
|
35
|
+
*/
|
|
36
|
+
declare function createCoreConfig(options: CreateCoreConfigOptions): CoreConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Create a CoreContext from CoreConfig
|
|
39
|
+
*/
|
|
40
|
+
declare function createCoreContext(config: CoreConfig): CoreContext;
|
|
41
|
+
/**
|
|
42
|
+
* Create a ScanContext from CoreConfig
|
|
43
|
+
*/
|
|
44
|
+
declare function createScanContext(config: CoreConfig): ScanContext;
|
|
45
|
+
/**
|
|
46
|
+
* Merge GraphQL options with defaults
|
|
47
|
+
*/
|
|
48
|
+
declare function mergeGraphQLOptions(options: Partial<CoreGraphQLOptions>, defaults?: Partial<CoreGraphQLOptions>): CoreGraphQLOptions;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CreateCoreConfigOptions, createCoreConfig, createCoreContext, createScanContext, mergeGraphQLOptions };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { DIR_APP_GRAPHQL, DIR_BUILD_NITRO, DIR_CLIENT_GRAPHQL, DIR_SERVER_GRAPHQL, GRAPHQL_FRAMEWORK_YOGA } from "./constants.mjs";
|
|
2
|
+
import { createLogger } from "./utils/logger.mjs";
|
|
3
|
+
import { relative, resolve } from "pathe";
|
|
4
|
+
|
|
5
|
+
//#region src/core/config.ts
|
|
6
|
+
/**
|
|
7
|
+
* Create a CoreConfig with sensible defaults
|
|
8
|
+
*/
|
|
9
|
+
function createCoreConfig(options) {
|
|
10
|
+
const { rootDir, isNuxt = false, isDev = process.env.NODE_ENV !== "production", graphqlOptions = {}, logger = createLogger(), ignorePatterns = [], layerServerDirs = [], layerAppDirs = [] } = options;
|
|
11
|
+
const framework = graphqlOptions.framework || GRAPHQL_FRAMEWORK_YOGA;
|
|
12
|
+
const buildDir = options.buildDir || resolve(rootDir, isNuxt ? ".nuxt" : DIR_BUILD_NITRO);
|
|
13
|
+
return {
|
|
14
|
+
rootDir,
|
|
15
|
+
buildDir,
|
|
16
|
+
serverDir: options.serverDir || resolve(rootDir, DIR_SERVER_GRAPHQL),
|
|
17
|
+
clientDir: options.clientDir || resolve(rootDir, isNuxt ? DIR_APP_GRAPHQL : DIR_CLIENT_GRAPHQL),
|
|
18
|
+
typesDir: resolve(buildDir, "types"),
|
|
19
|
+
framework,
|
|
20
|
+
isNuxt,
|
|
21
|
+
isDev,
|
|
22
|
+
graphqlOptions,
|
|
23
|
+
logger,
|
|
24
|
+
ignorePatterns,
|
|
25
|
+
layerServerDirs,
|
|
26
|
+
layerAppDirs
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a CoreContext from CoreConfig
|
|
31
|
+
*/
|
|
32
|
+
function createCoreContext(config) {
|
|
33
|
+
return {
|
|
34
|
+
config,
|
|
35
|
+
graphqlBuildDir: resolve(config.buildDir, "graphql"),
|
|
36
|
+
watchDirs: [],
|
|
37
|
+
dir: {
|
|
38
|
+
build: relative(config.rootDir, config.buildDir),
|
|
39
|
+
client: relative(config.rootDir, config.clientDir),
|
|
40
|
+
server: relative(config.rootDir, config.serverDir)
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a ScanContext from CoreConfig
|
|
46
|
+
*/
|
|
47
|
+
function createScanContext(config) {
|
|
48
|
+
return {
|
|
49
|
+
rootDir: config.rootDir,
|
|
50
|
+
serverDir: config.serverDir,
|
|
51
|
+
clientDir: config.clientDir,
|
|
52
|
+
ignorePatterns: config.ignorePatterns,
|
|
53
|
+
isDev: config.isDev,
|
|
54
|
+
logger: config.logger,
|
|
55
|
+
layerServerDirs: config.layerServerDirs,
|
|
56
|
+
layerAppDirs: config.layerAppDirs
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Merge GraphQL options with defaults
|
|
61
|
+
*/
|
|
62
|
+
function mergeGraphQLOptions(options, defaults = {}) {
|
|
63
|
+
return {
|
|
64
|
+
...defaults,
|
|
65
|
+
...options,
|
|
66
|
+
codegen: {
|
|
67
|
+
...defaults.codegen,
|
|
68
|
+
...options.codegen
|
|
69
|
+
},
|
|
70
|
+
security: {
|
|
71
|
+
...defaults.security,
|
|
72
|
+
...options.security
|
|
73
|
+
},
|
|
74
|
+
paths: {
|
|
75
|
+
...defaults.paths,
|
|
76
|
+
...options.paths
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
export { createCoreConfig, createCoreContext, createScanContext, mergeGraphQLOptions };
|