nitro-graphql 2.0.0-beta.31 → 2.0.0-beta.32
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 +176 -0
- package/dist/codegen/external-types.d.mts +12 -0
- package/dist/codegen/external-types.mjs +129 -0
- package/dist/codegen/index.d.mts +25 -0
- package/dist/codegen/index.mjs +38 -0
- package/dist/codegen/server-types.d.mts +13 -0
- package/dist/codegen/server-types.mjs +76 -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.mjs +91 -0
- package/dist/ecosystem/nuxt.mjs +3 -3
- package/dist/rollup.d.mts +7 -7
- package/dist/rollup.mjs +73 -73
- package/dist/routes/apollo-server.d.mts +2 -2
- package/dist/routes/debug.d.mts +2 -2
- package/dist/routes/health.d.mts +2 -2
- package/dist/setup/file-watcher.mjs +80 -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 +127 -274
- package/dist/types/index.d.mts +1 -1
- package/dist/utils/client-codegen.d.mts +1 -1
- package/dist/utils/client-codegen.mjs +5 -2
- package/dist/utils/directive-parser.d.mts +2 -1
- package/dist/utils/directive-parser.mjs +4 -2
- package/dist/utils/file-generator.mjs +1 -1
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +2 -2
- package/dist/utils/path-resolver.d.mts +2 -2
- package/dist/utils/path-resolver.mjs +2 -2
- package/dist/utils/server-codegen.mjs +4 -1
- package/dist/utils/type-generation.d.mts +6 -12
- package/dist/utils/type-generation.mjs +6 -419
- package/package.json +8 -2
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { FILE_CONFIG_TS, FILE_CONTEXT_DTS, FILE_CONTEXT_TS, FILE_GRAPHQL_CONFIG, FILE_SCHEMA_TS, LOG_TAG } from "../constants.mjs";
|
|
2
|
+
import { relativeWithDot } from "../utils/index.mjs";
|
|
3
|
+
import { writeFileIfNotExists } from "../utils/file-generator.mjs";
|
|
4
|
+
import { getDefaultPaths, getScaffoldConfig, resolveFilePath, shouldGenerateScaffold } from "../utils/path-resolver.mjs";
|
|
5
|
+
import consola from "consola";
|
|
6
|
+
import { join, resolve } from "pathe";
|
|
7
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
8
|
+
|
|
9
|
+
//#region src/setup/scaffold-generator.ts
|
|
10
|
+
const logger = consola.withTag(LOG_TAG);
|
|
11
|
+
/**
|
|
12
|
+
* Generate all scaffold files based on configuration
|
|
13
|
+
* Can be disabled via: scaffold: false or scaffold.enabled: false
|
|
14
|
+
*/
|
|
15
|
+
function generateScaffoldFiles(nitro) {
|
|
16
|
+
if (!shouldGenerateScaffold(nitro)) {
|
|
17
|
+
logger.info("Scaffold file generation is disabled (library mode)");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const placeholders = getDefaultPaths(nitro);
|
|
21
|
+
const scaffoldConfig = getScaffoldConfig(nitro);
|
|
22
|
+
generateGraphQLConfig(nitro, scaffoldConfig, placeholders);
|
|
23
|
+
generateServerScaffoldFiles(nitro, scaffoldConfig, placeholders);
|
|
24
|
+
checkOldContextFile(nitro);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate graphql.config.ts for IDE tooling support
|
|
28
|
+
*/
|
|
29
|
+
function generateGraphQLConfig(nitro, scaffoldConfig, placeholders) {
|
|
30
|
+
const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, FILE_GRAPHQL_CONFIG, placeholders);
|
|
31
|
+
if (!graphqlConfigPath) return;
|
|
32
|
+
writeFileIfNotExists(graphqlConfigPath, `import type { IGraphQLConfig } from 'graphql-config'
|
|
33
|
+
|
|
34
|
+
export default <IGraphQLConfig> {
|
|
35
|
+
projects: {
|
|
36
|
+
default: {
|
|
37
|
+
schema: [
|
|
38
|
+
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
|
|
39
|
+
],
|
|
40
|
+
documents: [
|
|
41
|
+
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}`, FILE_GRAPHQL_CONFIG);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate server-side scaffold files (schema.ts, config.ts, context.d.ts)
|
|
49
|
+
*/
|
|
50
|
+
function generateServerScaffoldFiles(nitro, scaffoldConfig, placeholders) {
|
|
51
|
+
const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
|
|
52
|
+
const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
|
|
53
|
+
const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.d.ts", placeholders);
|
|
54
|
+
if (serverSchemaPath || serverConfigPath || serverContextPath) {
|
|
55
|
+
if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
|
|
58
|
+
|
|
59
|
+
})
|
|
60
|
+
`, `server ${FILE_SCHEMA_TS}`);
|
|
61
|
+
if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
|
|
62
|
+
// import * as tables from '../drizzle/schema/index'
|
|
63
|
+
// import { useDatabase } from '../utils/useDb'
|
|
64
|
+
import { defineGraphQLConfig } from 'nitro-graphql/define'
|
|
65
|
+
|
|
66
|
+
export default defineGraphQLConfig({
|
|
67
|
+
// graphql-yoga example config
|
|
68
|
+
// context: () => {
|
|
69
|
+
// return {
|
|
70
|
+
// context: {
|
|
71
|
+
// useDatabase,
|
|
72
|
+
// tables,
|
|
73
|
+
// },
|
|
74
|
+
// }
|
|
75
|
+
// },
|
|
76
|
+
})
|
|
77
|
+
`, `server ${FILE_CONFIG_TS}`);
|
|
78
|
+
if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
|
|
79
|
+
// import type { Database } from '../utils/useDb'
|
|
80
|
+
|
|
81
|
+
declare module 'nitro/h3' {
|
|
82
|
+
interface H3EventContext {
|
|
83
|
+
// Add your custom context properties here
|
|
84
|
+
// useDatabase: () => Database
|
|
85
|
+
// tables: typeof import('../drizzle/schema')
|
|
86
|
+
// auth?: {
|
|
87
|
+
// user?: {
|
|
88
|
+
// id: string
|
|
89
|
+
// role: 'admin' | 'user'
|
|
90
|
+
// }
|
|
91
|
+
// }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {}
|
|
96
|
+
`, `server ${FILE_CONTEXT_DTS}`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check for old context.ts file and warn users to migrate to context.d.ts
|
|
100
|
+
*/
|
|
101
|
+
function checkOldContextFile(nitro) {
|
|
102
|
+
if (existsSync(join(nitro.graphql.serverDir, FILE_CONTEXT_TS))) {
|
|
103
|
+
logger.warn(`Found ${FILE_CONTEXT_TS} file. Please rename it to ${FILE_CONTEXT_DTS} for type-only definitions.`);
|
|
104
|
+
logger.info(`The context file should now be ${FILE_CONTEXT_DTS} instead of ${FILE_CONTEXT_TS}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
export { generateScaffoldFiles };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { relativeWithDot } from "../utils/index.mjs";
|
|
2
|
+
import { getDefaultPaths, getTypesConfig, resolveFilePath } from "../utils/path-resolver.mjs";
|
|
3
|
+
import { dirname, join, resolve } from "pathe";
|
|
4
|
+
|
|
5
|
+
//#region src/setup/ts-config.ts
|
|
6
|
+
/**
|
|
7
|
+
* Setup TypeScript path aliases for GraphQL types
|
|
8
|
+
* Called via nitro:config hook to extend tsconfig.json
|
|
9
|
+
*/
|
|
10
|
+
function setupTypeScriptPaths(nitro, types) {
|
|
11
|
+
const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
|
|
12
|
+
types.tsConfig ||= {};
|
|
13
|
+
types.tsConfig.compilerOptions ??= {};
|
|
14
|
+
types.tsConfig.compilerOptions.paths ??= {};
|
|
15
|
+
types.tsConfig.include = types.tsConfig.include || [];
|
|
16
|
+
const placeholders = getDefaultPaths(nitro);
|
|
17
|
+
const typesConfig = getTypesConfig(nitro);
|
|
18
|
+
setupServerTypesPath(nitro, types, tsconfigDir, placeholders, typesConfig);
|
|
19
|
+
setupClientTypesPath(nitro, types, tsconfigDir, placeholders, typesConfig);
|
|
20
|
+
setupSchemaPath(nitro, types, tsconfigDir);
|
|
21
|
+
setupExternalServicePaths(nitro, types, tsconfigDir, placeholders, typesConfig);
|
|
22
|
+
types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Setup #graphql/server path alias
|
|
26
|
+
*/
|
|
27
|
+
function setupServerTypesPath(nitro, types, tsconfigDir, placeholders, typesConfig) {
|
|
28
|
+
const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
|
|
29
|
+
if (serverTypesPath) {
|
|
30
|
+
types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
|
|
31
|
+
types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Setup #graphql/client path alias
|
|
36
|
+
*/
|
|
37
|
+
function setupClientTypesPath(nitro, types, tsconfigDir, placeholders, typesConfig) {
|
|
38
|
+
const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
|
|
39
|
+
if (clientTypesPath) {
|
|
40
|
+
types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
|
|
41
|
+
types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Setup #graphql/schema path alias
|
|
46
|
+
*/
|
|
47
|
+
function setupSchemaPath(nitro, types, tsconfigDir) {
|
|
48
|
+
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Setup #graphql/client/{serviceName} path aliases for external services
|
|
52
|
+
*/
|
|
53
|
+
function setupExternalServicePaths(nitro, types, tsconfigDir, placeholders, typesConfig) {
|
|
54
|
+
if (!nitro.options.graphql?.externalServices?.length) return;
|
|
55
|
+
for (const service of nitro.options.graphql.externalServices) {
|
|
56
|
+
const servicePlaceholders = {
|
|
57
|
+
...placeholders,
|
|
58
|
+
serviceName: service.name
|
|
59
|
+
};
|
|
60
|
+
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
61
|
+
if (externalTypesPath) {
|
|
62
|
+
types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
|
|
63
|
+
types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { setupTypeScriptPaths };
|
package/dist/setup.d.mts
CHANGED
|
@@ -3,8 +3,8 @@ import { Nitro } from "nitro/types";
|
|
|
3
3
|
//#region src/setup.d.ts
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Main setup function for nitro-graphql
|
|
7
|
+
* Coordinates all initialization steps for the module
|
|
8
8
|
*/
|
|
9
9
|
declare function setupNitroGraphQL(nitro: Nitro): Promise<void>;
|
|
10
10
|
//#endregion
|
package/dist/setup.mjs
CHANGED
|
@@ -1,40 +1,50 @@
|
|
|
1
|
+
import { ENDPOINT_DEBUG, FRAMEWORK_NITRO, FRAMEWORK_NUXT, GRAPHQL_HTTP_METHODS, LOG_TAG } from "./constants.mjs";
|
|
2
|
+
import { DEFAULT_RUNTIME_CONFIG, DEFAULT_TYPESCRIPT_STRICT, DEFAULT_TYPES_CONFIG } from "./config/defaults.mjs";
|
|
1
3
|
import { generateDirectiveSchemas } from "./utils/directive-parser.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.mjs";
|
|
4
|
+
import { scanDirectives, scanDocuments, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.mjs";
|
|
5
|
+
import { getDefaultPaths } from "./utils/path-resolver.mjs";
|
|
6
|
+
import { clientTypeGeneration, serverTypeGeneration } from "./codegen/index.mjs";
|
|
6
7
|
import { rollupConfig } from "./rollup.mjs";
|
|
8
|
+
import { getWatchDirectories, setupFileWatcher } from "./setup/file-watcher.mjs";
|
|
9
|
+
import { setupRollupChunking, setupRollupExternals } from "./setup/rollup-integration.mjs";
|
|
10
|
+
import { generateScaffoldFiles } from "./setup/scaffold-generator.mjs";
|
|
11
|
+
import { setupTypeScriptPaths } from "./setup/ts-config.mjs";
|
|
7
12
|
import defu from "defu";
|
|
8
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
9
13
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { watch } from "chokidar";
|
|
11
14
|
import consola from "consola";
|
|
12
|
-
import {
|
|
15
|
+
import { join, relative, resolve } from "pathe";
|
|
13
16
|
|
|
14
17
|
//#region src/setup.ts
|
|
15
|
-
const logger = consola.withTag(
|
|
18
|
+
const logger = consola.withTag(LOG_TAG);
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
20
|
+
* Main setup function for nitro-graphql
|
|
21
|
+
* Coordinates all initialization steps for the module
|
|
19
22
|
*/
|
|
20
23
|
async function setupNitroGraphQL(nitro) {
|
|
24
|
+
initializeConfiguration(nitro);
|
|
25
|
+
validateConfiguration(nitro);
|
|
26
|
+
setupBuildDirectories(nitro);
|
|
27
|
+
setupRollupExternals(nitro);
|
|
28
|
+
setupRollupChunking(nitro);
|
|
29
|
+
initializeRuntimeConfig(nitro);
|
|
30
|
+
setupFileWatching(nitro);
|
|
31
|
+
await scanGraphQLFiles(nitro);
|
|
32
|
+
setupDevHooks(nitro);
|
|
33
|
+
await rollupConfig(nitro);
|
|
34
|
+
await generateTypes(nitro);
|
|
35
|
+
setupCloseHooks(nitro);
|
|
36
|
+
registerRouteHandlers(nitro);
|
|
37
|
+
setupTypeScriptConfiguration(nitro);
|
|
38
|
+
setupNuxtIntegration(nitro);
|
|
39
|
+
generateScaffoldFiles(nitro);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Initialize default configuration values
|
|
43
|
+
*/
|
|
44
|
+
function initializeConfiguration(nitro) {
|
|
21
45
|
nitro.options.graphql ||= {};
|
|
22
|
-
nitro.options.graphql.types = defu(nitro.options.graphql.types,
|
|
23
|
-
server: ".graphql/nitro-graphql-server.d.ts",
|
|
24
|
-
client: ".graphql/nitro-graphql-client.d.ts",
|
|
25
|
-
enabled: true
|
|
26
|
-
});
|
|
46
|
+
nitro.options.graphql.types = defu(nitro.options.graphql.types, DEFAULT_TYPES_CONFIG);
|
|
27
47
|
if (!nitro.options.graphql?.framework) logger.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
|
|
28
|
-
if (nitro.options.graphql?.externalServices?.length) {
|
|
29
|
-
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
30
|
-
if (validationErrors.length > 0) {
|
|
31
|
-
logger.error("External services configuration errors:");
|
|
32
|
-
for (const error of validationErrors) logger.error(` - ${error}`);
|
|
33
|
-
throw new Error("Invalid external services configuration");
|
|
34
|
-
}
|
|
35
|
-
logger.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
|
|
36
|
-
}
|
|
37
|
-
const { getDefaultPaths } = await import("./utils/path-resolver.mjs");
|
|
38
48
|
const defaultPaths = getDefaultPaths(nitro);
|
|
39
49
|
nitro.graphql ||= {
|
|
40
50
|
buildDir: "",
|
|
@@ -47,100 +57,87 @@ async function setupNitroGraphQL(nitro) {
|
|
|
47
57
|
server: "server"
|
|
48
58
|
}
|
|
49
59
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
rollupConfig$1.external = (id, parent, isResolved) => {
|
|
62
|
-
if (allExternals.some((external) => id.includes(external))) return true;
|
|
63
|
-
return originalExternal(id, parent, isResolved);
|
|
64
|
-
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validate external services configuration
|
|
63
|
+
*/
|
|
64
|
+
function validateConfiguration(nitro) {
|
|
65
|
+
if (nitro.options.graphql?.externalServices?.length) {
|
|
66
|
+
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
67
|
+
if (validationErrors.length > 0) {
|
|
68
|
+
logger.error("External services configuration errors:");
|
|
69
|
+
for (const error of validationErrors) logger.error(` - ${error}`);
|
|
70
|
+
throw new Error("Invalid external services configuration");
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
endpoint: {
|
|
69
|
-
graphql: "/api/graphql",
|
|
70
|
-
healthCheck: "/api/graphql/health"
|
|
71
|
-
},
|
|
72
|
-
playground: true
|
|
73
|
-
});
|
|
72
|
+
logger.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
|
|
73
|
+
}
|
|
74
74
|
if (nitro.options.graphql?.federation?.enabled) logger.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Setup build directories
|
|
78
|
+
*/
|
|
79
|
+
function setupBuildDirectories(nitro) {
|
|
75
80
|
const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
|
|
76
81
|
nitro.graphql.buildDir = graphqlBuildDir;
|
|
77
|
-
const watchDirs = [];
|
|
78
82
|
switch (nitro.options.framework.name) {
|
|
79
|
-
case
|
|
83
|
+
case FRAMEWORK_NUXT:
|
|
80
84
|
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
81
85
|
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
82
|
-
watchDirs.push(nitro.graphql.clientDir);
|
|
83
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
84
|
-
const layerAppDirs = getLayerAppDirectories(nitro);
|
|
85
|
-
for (const layerServerDir of layerServerDirs) watchDirs.push(join(layerServerDir, "graphql"));
|
|
86
|
-
for (const layerAppDir of layerAppDirs) watchDirs.push(join(layerAppDir, "graphql"));
|
|
87
86
|
break;
|
|
88
|
-
|
|
89
|
-
case "nitro":
|
|
87
|
+
case FRAMEWORK_NITRO:
|
|
90
88
|
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
91
89
|
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
92
|
-
watchDirs.push(nitro.graphql.clientDir);
|
|
93
|
-
watchDirs.push(nitro.graphql.serverDir);
|
|
94
90
|
break;
|
|
95
|
-
default:
|
|
91
|
+
default: break;
|
|
96
92
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const isResolverFile = path.endsWith(".resolver.ts") || path.endsWith(".resolver.js");
|
|
112
|
-
const isDirectiveFile = path.endsWith(".directive.ts") || path.endsWith(".directive.js");
|
|
113
|
-
if (isGraphQLFile || isResolverFile || isDirectiveFile) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql") || isResolverFile || isDirectiveFile) {
|
|
114
|
-
await scanResolvers(nitro).then((r) => nitro.scanResolvers = r);
|
|
115
|
-
await scanDirectives(nitro).then((d) => nitro.scanDirectives = d);
|
|
116
|
-
logger.success("Types regenerated");
|
|
117
|
-
await serverTypeGeneration(nitro, { silent: true });
|
|
118
|
-
await clientTypeGeneration(nitro, { silent: true });
|
|
119
|
-
await nitro.hooks.callHook("dev:reload");
|
|
120
|
-
} else {
|
|
121
|
-
logger.success("Types regenerated");
|
|
122
|
-
await clientTypeGeneration(nitro, { silent: true });
|
|
123
|
-
}
|
|
124
|
-
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Initialize runtime configuration
|
|
96
|
+
*/
|
|
97
|
+
function initializeRuntimeConfig(nitro) {
|
|
98
|
+
nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, DEFAULT_RUNTIME_CONFIG);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Setup file watching for development mode
|
|
102
|
+
*/
|
|
103
|
+
function setupFileWatching(nitro) {
|
|
104
|
+
const watchDirs = getWatchDirectories(nitro);
|
|
105
|
+
nitro.graphql.watchDirs = watchDirs;
|
|
106
|
+
const watcher = setupFileWatcher(nitro, watchDirs);
|
|
125
107
|
nitro.hooks.hook("close", () => {
|
|
126
108
|
watcher.close();
|
|
127
109
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Scan all GraphQL files (schemas, resolvers, directives, documents)
|
|
113
|
+
*/
|
|
114
|
+
async function scanGraphQLFiles(nitro) {
|
|
132
115
|
const directives = await scanDirectives(nitro);
|
|
133
116
|
nitro.scanDirectives = directives;
|
|
134
|
-
|
|
117
|
+
nitro.scanSchemas = [];
|
|
118
|
+
const directivesPath = await generateDirectiveSchemas(nitro, directives);
|
|
119
|
+
const schemas = await scanSchemas(nitro);
|
|
120
|
+
if (directivesPath && !schemas.includes(directivesPath)) schemas.push(directivesPath);
|
|
121
|
+
nitro.scanSchemas = schemas;
|
|
122
|
+
nitro.scanDocuments = await scanDocuments(nitro);
|
|
123
|
+
nitro.scanResolvers = await scanResolvers(nitro);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Setup dev mode hooks for rescanning files
|
|
127
|
+
*/
|
|
128
|
+
function setupDevHooks(nitro) {
|
|
135
129
|
let hasShownInitialLogs = false;
|
|
136
130
|
nitro.hooks.hook("dev:start", async () => {
|
|
137
|
-
|
|
131
|
+
const directives = await scanDirectives(nitro);
|
|
132
|
+
nitro.scanDirectives = directives;
|
|
133
|
+
if (!nitro.scanSchemas) nitro.scanSchemas = [];
|
|
134
|
+
const directivesPath = await generateDirectiveSchemas(nitro, directives);
|
|
135
|
+
const schemas = await scanSchemas(nitro);
|
|
136
|
+
if (directivesPath && !schemas.includes(directivesPath)) schemas.push(directivesPath);
|
|
137
|
+
nitro.scanSchemas = schemas;
|
|
138
|
+
nitro.scanDocuments = await scanDocuments(nitro);
|
|
138
139
|
const resolvers = await scanResolvers(nitro);
|
|
139
140
|
nitro.scanResolvers = resolvers;
|
|
140
|
-
const directives$1 = await scanDirectives(nitro);
|
|
141
|
-
nitro.scanDirectives = directives$1;
|
|
142
|
-
await generateDirectiveSchemas(nitro, directives$1);
|
|
143
|
-
nitro.scanDocuments = await scanDocs(nitro);
|
|
144
141
|
if (nitro.options.dev && !hasShownInitialLogs) {
|
|
145
142
|
hasShownInitialLogs = true;
|
|
146
143
|
if (resolvers.length > 0) {
|
|
@@ -165,25 +162,35 @@ async function setupNitroGraphQL(nitro) {
|
|
|
165
162
|
} else logger.warn("No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
166
163
|
}
|
|
167
164
|
});
|
|
168
|
-
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Generate server and client types
|
|
168
|
+
*/
|
|
169
|
+
async function generateTypes(nitro) {
|
|
169
170
|
await serverTypeGeneration(nitro);
|
|
170
171
|
await clientTypeGeneration(nitro, { isInitial: true });
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Setup close hooks for final type generation
|
|
175
|
+
*/
|
|
176
|
+
function setupCloseHooks(nitro) {
|
|
171
177
|
nitro.hooks.hook("close", async () => {
|
|
172
178
|
await serverTypeGeneration(nitro, { silent: true });
|
|
173
179
|
await clientTypeGeneration(nitro, { silent: true });
|
|
174
180
|
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Register GraphQL route handlers
|
|
184
|
+
*/
|
|
185
|
+
function registerRouteHandlers(nitro) {
|
|
175
186
|
const runtime = fileURLToPath(new URL("routes", import.meta.url));
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
"POST",
|
|
179
|
-
"OPTIONS"
|
|
180
|
-
];
|
|
181
|
-
if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
|
|
187
|
+
const framework = nitro.options.graphql?.framework;
|
|
188
|
+
if (framework === "graphql-yoga") for (const method of GRAPHQL_HTTP_METHODS) nitro.options.handlers.push({
|
|
182
189
|
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
183
190
|
handler: join(runtime, "graphql-yoga"),
|
|
184
191
|
method
|
|
185
192
|
});
|
|
186
|
-
if (
|
|
193
|
+
if (framework === "apollo-server") for (const method of GRAPHQL_HTTP_METHODS) nitro.options.handlers.push({
|
|
187
194
|
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
188
195
|
handler: join(runtime, "apollo-server"),
|
|
189
196
|
method
|
|
@@ -194,182 +201,28 @@ async function setupNitroGraphQL(nitro) {
|
|
|
194
201
|
method: "GET"
|
|
195
202
|
});
|
|
196
203
|
if (nitro.options.dev) nitro.options.handlers.push({
|
|
197
|
-
route:
|
|
204
|
+
route: ENDPOINT_DEBUG,
|
|
198
205
|
handler: join(runtime, "debug"),
|
|
199
206
|
method: "GET"
|
|
200
207
|
});
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
let graphqlIndex = id.indexOf("server/graphql/");
|
|
208
|
-
let baseLength = 15;
|
|
209
|
-
if (graphqlIndex === -1) {
|
|
210
|
-
graphqlIndex = id.indexOf("routes/graphql/");
|
|
211
|
-
baseLength = 15;
|
|
212
|
-
}
|
|
213
|
-
if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
|
|
214
|
-
return "schemas";
|
|
215
|
-
}
|
|
216
|
-
if (id.endsWith(".resolver.ts")) {
|
|
217
|
-
let graphqlIndex = id.indexOf("server/graphql/");
|
|
218
|
-
let baseLength = 15;
|
|
219
|
-
if (graphqlIndex === -1) {
|
|
220
|
-
graphqlIndex = id.indexOf("routes/graphql/");
|
|
221
|
-
baseLength = 15;
|
|
222
|
-
}
|
|
223
|
-
if (graphqlIndex !== -1) return id.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
|
|
224
|
-
return "resolvers";
|
|
225
|
-
}
|
|
226
|
-
if (typeof manualChunks === "function") return manualChunks(id, meta);
|
|
227
|
-
};
|
|
228
|
-
rollupConfig$1.output.advancedChunks = {
|
|
229
|
-
groups: [{
|
|
230
|
-
name: (moduleId) => {
|
|
231
|
-
if (!moduleId.endsWith(".graphql") && !moduleId.endsWith(".gql")) return;
|
|
232
|
-
let graphqlIndex = moduleId.indexOf("server/graphql/");
|
|
233
|
-
let baseLength = 15;
|
|
234
|
-
if (graphqlIndex === -1) {
|
|
235
|
-
graphqlIndex = moduleId.indexOf("routes/graphql/");
|
|
236
|
-
baseLength = 15;
|
|
237
|
-
}
|
|
238
|
-
if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.(?:graphql|gql)$/, "-schema");
|
|
239
|
-
return "schemas";
|
|
240
|
-
},
|
|
241
|
-
test: /\.(?:graphql|gql)$/
|
|
242
|
-
}, {
|
|
243
|
-
name: (moduleId) => {
|
|
244
|
-
if (!moduleId.endsWith(".resolver.ts")) return;
|
|
245
|
-
let graphqlIndex = moduleId.indexOf("server/graphql/");
|
|
246
|
-
let baseLength = 15;
|
|
247
|
-
if (graphqlIndex === -1) {
|
|
248
|
-
graphqlIndex = moduleId.indexOf("routes/graphql/");
|
|
249
|
-
baseLength = 15;
|
|
250
|
-
}
|
|
251
|
-
if (graphqlIndex !== -1) return moduleId.slice(graphqlIndex + baseLength).replace(/\.resolver\.ts$/, "");
|
|
252
|
-
return "resolvers";
|
|
253
|
-
},
|
|
254
|
-
test: /\.resolver\.(?:ts|js)$/
|
|
255
|
-
}],
|
|
256
|
-
minSize: 0,
|
|
257
|
-
minShareCount: 1
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
|
|
261
|
-
if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;
|
|
262
|
-
if (typeof chunkFiles === "function") return chunkFiles(chunkInfo);
|
|
263
|
-
return `chunks/_/[name].mjs`;
|
|
264
|
-
};
|
|
265
|
-
});
|
|
266
|
-
nitro.options.typescript.strict = true;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Setup TypeScript configuration and path aliases
|
|
211
|
+
*/
|
|
212
|
+
function setupTypeScriptConfiguration(nitro) {
|
|
213
|
+
nitro.options.typescript.strict = DEFAULT_TYPESCRIPT_STRICT;
|
|
267
214
|
nitro.hooks.hook("types:extend", (types) => {
|
|
268
|
-
types
|
|
269
|
-
types.tsConfig.compilerOptions ??= {};
|
|
270
|
-
types.tsConfig.compilerOptions.paths ??= {};
|
|
271
|
-
const placeholders = getDefaultPaths(nitro);
|
|
272
|
-
const typesConfig = getTypesConfig(nitro);
|
|
273
|
-
const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
|
|
274
|
-
if (serverTypesPath) types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
|
|
275
|
-
const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
|
|
276
|
-
if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
|
|
277
|
-
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
278
|
-
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
|
|
279
|
-
const servicePlaceholders = {
|
|
280
|
-
...placeholders,
|
|
281
|
-
serviceName: service.name
|
|
282
|
-
};
|
|
283
|
-
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
284
|
-
if (externalTypesPath) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
|
|
285
|
-
}
|
|
286
|
-
types.tsConfig.include = types.tsConfig.include || [];
|
|
287
|
-
if (serverTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
|
|
288
|
-
if (clientTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
|
|
289
|
-
types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
|
|
290
|
-
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
|
|
291
|
-
const servicePlaceholders = {
|
|
292
|
-
...placeholders,
|
|
293
|
-
serviceName: service.name
|
|
294
|
-
};
|
|
295
|
-
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
296
|
-
if (externalTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
|
|
297
|
-
}
|
|
215
|
+
setupTypeScriptPaths(nitro, types);
|
|
298
216
|
});
|
|
299
|
-
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Setup Nuxt-specific integration
|
|
220
|
+
*/
|
|
221
|
+
function setupNuxtIntegration(nitro) {
|
|
222
|
+
if (nitro.options.framework?.name === FRAMEWORK_NUXT && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
|
|
300
223
|
const nuxtOptions = nitro._nuxt?.options;
|
|
301
224
|
if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
|
|
302
225
|
});
|
|
303
|
-
if (shouldGenerateScaffold(nitro)) {
|
|
304
|
-
const placeholders = getDefaultPaths(nitro);
|
|
305
|
-
const scaffoldConfig = getScaffoldConfig(nitro);
|
|
306
|
-
const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
|
|
307
|
-
if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
|
|
308
|
-
import type { IGraphQLConfig } from 'graphql-config'
|
|
309
|
-
|
|
310
|
-
export default <IGraphQLConfig> {
|
|
311
|
-
projects: {
|
|
312
|
-
default: {
|
|
313
|
-
schema: [
|
|
314
|
-
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
|
|
315
|
-
],
|
|
316
|
-
documents: [
|
|
317
|
-
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
|
|
318
|
-
],
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
|
-
}`, "graphql.config.ts");
|
|
322
|
-
const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
|
|
323
|
-
const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
|
|
324
|
-
const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.d.ts", placeholders);
|
|
325
|
-
if (serverSchemaPath || serverConfigPath || serverContextPath) {
|
|
326
|
-
if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
|
|
327
|
-
}
|
|
328
|
-
if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
|
|
329
|
-
|
|
330
|
-
})
|
|
331
|
-
`, "server schema.ts");
|
|
332
|
-
if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
|
|
333
|
-
// import * as tables from '../drizzle/schema/index'
|
|
334
|
-
// import { useDatabase } from '../utils/useDb'
|
|
335
|
-
import { defineGraphQLConfig } from 'nitro-graphql/define'
|
|
336
|
-
|
|
337
|
-
export default defineGraphQLConfig({
|
|
338
|
-
// graphql-yoga example config
|
|
339
|
-
// context: () => {
|
|
340
|
-
// return {
|
|
341
|
-
// context: {
|
|
342
|
-
// useDatabase,
|
|
343
|
-
// tables,
|
|
344
|
-
// },
|
|
345
|
-
// }
|
|
346
|
-
// },
|
|
347
|
-
})
|
|
348
|
-
`, "server config.ts");
|
|
349
|
-
if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
|
|
350
|
-
// import type { Database } from '../utils/useDb'
|
|
351
|
-
|
|
352
|
-
declare module 'nitro/h3' {
|
|
353
|
-
interface H3EventContext {
|
|
354
|
-
// Add your custom context properties here
|
|
355
|
-
// useDatabase: () => Database
|
|
356
|
-
// tables: typeof import('../drizzle/schema')
|
|
357
|
-
// auth?: {
|
|
358
|
-
// user?: {
|
|
359
|
-
// id: string
|
|
360
|
-
// role: 'admin' | 'user'
|
|
361
|
-
// }
|
|
362
|
-
// }
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export {}
|
|
367
|
-
`, "server context.d.ts");
|
|
368
|
-
if (existsSync(join(nitro.graphql.serverDir, "context.ts"))) {
|
|
369
|
-
logger.warn("Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
|
|
370
|
-
logger.info("The context file should now be context.d.ts instead of context.ts");
|
|
371
|
-
}
|
|
372
|
-
} else logger.info("Scaffold file generation is disabled (library mode)");
|
|
373
226
|
}
|
|
374
227
|
|
|
375
228
|
//#endregion
|