nitro-graphql 2.0.0-beta.11 โ 2.0.0-beta.13
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 +27 -1
- package/dist/ecosystem/nuxt.js +55 -13
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -315
- package/dist/routes/apollo-server.d.ts +2 -2
- package/dist/routes/debug.d.ts +2 -2
- package/dist/routes/debug.js +3 -7
- package/dist/routes/graphql-yoga.d.ts +2 -2
- package/dist/routes/health.d.ts +2 -2
- package/dist/setup.js +345 -0
- package/dist/utils/client-codegen.d.ts +2 -2
- package/dist/utils/client-codegen.js +4 -4
- package/dist/utils/path-resolver.js +2 -2
- package/dist/vite.d.ts +5 -3
- package/dist/vite.js +11 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# Nitro GraphQL
|
|
6
6
|
|
|
7
7
|
[![npm version][npm-version-src]][npm-version-href]
|
|
8
|
+
[![Beta Status][beta-src]][beta-href]
|
|
8
9
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
9
10
|
[![bundle][bundle-src]][bundle-href]
|
|
10
11
|
[![License][license-src]][license-href]
|
|
@@ -18,6 +19,13 @@
|
|
|
18
19
|
|
|
19
20
|
</div>
|
|
20
21
|
|
|
22
|
+
> [!IMPORTANT]
|
|
23
|
+
> **v2.0 Beta (Current - Main Branch)**
|
|
24
|
+
> This is the **v2.0** beta branch with Nitro v3 and H3 v2 support. Includes Rolldown optimization, improved chunking, and enhanced Vite integration.
|
|
25
|
+
>
|
|
26
|
+
> **Looking for v1.x?**
|
|
27
|
+
> For the stable v1 version (Nitro v2), see the [`v1` branch](https://github.com/productdevbook/nitro-graphql/tree/v1).
|
|
28
|
+
|
|
21
29
|
---
|
|
22
30
|
|
|
23
31
|
## ๐ฅ Watch & Learn
|
|
@@ -34,6 +42,14 @@
|
|
|
34
42
|
- ๐ฎ **Developer-friendly** - Built-in Apollo Sandbox for testing
|
|
35
43
|
- ๐ง **Zero config** - Sensible defaults, customize when needed
|
|
36
44
|
|
|
45
|
+
### ๐ What's New in v2.0 Beta
|
|
46
|
+
|
|
47
|
+
- ๐ **Nitro v3 & H3 v2** - Full compatibility with the latest Nitro and H3
|
|
48
|
+
- โ๏ธ **Rolldown Support** - Optimized for both Rolldown (Vite 7+) and Rollup
|
|
49
|
+
- ๐ฆ **Smart Chunking** - GraphQL code split into separate chunks (~98% size reduction)
|
|
50
|
+
- ๐ **Debug Dashboard** - Built-in diagnostics at `/_nitro/graphql/debug` (dev only)
|
|
51
|
+
- ๐จ **Enhanced Vite Integration** - Better custom path support and virtual module resolution
|
|
52
|
+
|
|
37
53
|
## ๐ Quick Start
|
|
38
54
|
|
|
39
55
|
### 1. Install
|
|
@@ -147,6 +163,7 @@ pnpm dev
|
|
|
147
163
|
- **Endpoint**: `http://localhost:3000/api/graphql`
|
|
148
164
|
- **Playground**: `http://localhost:3000/api/graphql` (browser)
|
|
149
165
|
- **Health**: `http://localhost:3000/api/graphql/health`
|
|
166
|
+
- **Debug Dashboard**: `http://localhost:3000/_nitro/graphql/debug` (dev mode only)
|
|
150
167
|
|
|
151
168
|
## ๐ฎ Examples
|
|
152
169
|
|
|
@@ -159,6 +176,13 @@ Try these working examples:
|
|
|
159
176
|
| [**Nuxt Integration**](./playgrounds/nuxt/) | Full Nuxt app with client types | `pnpm playground:nuxt` |
|
|
160
177
|
| [**Apollo Federation**](./playgrounds/federation/) | Federated GraphQL services | `pnpm playground:federation` |
|
|
161
178
|
|
|
179
|
+
### ๐งช Test Projects
|
|
180
|
+
|
|
181
|
+
Real-world test projects using nitro-graphql v2:
|
|
182
|
+
|
|
183
|
+
- [**Vite + Nitro + Rolldown**](https://github.com/productdevbook/vite-nitro-graphql/tree/rolldown) - Testing with Rolldown bundler (Vite 7+)
|
|
184
|
+
- [**Vite + Nitro (Main)**](https://github.com/productdevbook/vite-nitro-graphql) - Standard Vite integration tests
|
|
185
|
+
|
|
162
186
|
## ๐๏ธ Building Your First Feature
|
|
163
187
|
|
|
164
188
|
Let's create a complete user management system:
|
|
@@ -1248,4 +1272,6 @@ pnpm lint
|
|
|
1248
1272
|
[license-src]: https://img.shields.io/github/license/productdevbook/nitro-graphql.svg?style=flat&colorA=080f12&colorB=1fa669
|
|
1249
1273
|
[license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
|
|
1250
1274
|
[docs-src]: https://img.shields.io/badge/docs-read-blue?style=flat&colorA=080f12&colorB=1fa669
|
|
1251
|
-
[docs-href]: https://nitro-graphql.pages.dev
|
|
1275
|
+
[docs-href]: https://nitro-graphql.pages.dev
|
|
1276
|
+
[beta-src]: https://img.shields.io/npm/v/nitro-graphql/beta?style=flat&logo=rocket&logoColor=white&label=beta&color=7c3aed&colorA=080f12
|
|
1277
|
+
[beta-href]: https://github.com/productdevbook/nitro-graphql/releases
|
package/dist/ecosystem/nuxt.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { getDefaultPaths, getTypesConfig, resolveFilePath } from "../utils/path-resolver.js";
|
|
1
2
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join, resolve } from "pathe";
|
|
3
|
+
import { dirname, join, relative, resolve } from "pathe";
|
|
3
4
|
import { defineNuxtModule, getLayerDirectories } from "@nuxt/kit";
|
|
4
5
|
|
|
5
6
|
//#region src/ecosystem/nuxt.ts
|
|
@@ -11,24 +12,65 @@ var nuxt_default = defineNuxtModule({
|
|
|
11
12
|
},
|
|
12
13
|
setup: async (_options, nuxt) => {
|
|
13
14
|
nuxt.hooks.hook("prepare:types", (options) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const mockNitro$1 = { options: {
|
|
16
|
+
rootDir: nuxt.options.rootDir,
|
|
17
|
+
buildDir: nuxt.options.buildDir,
|
|
18
|
+
framework: { name: "nuxt" },
|
|
19
|
+
graphql: nuxt.options.nitro?.graphql
|
|
20
|
+
} };
|
|
21
|
+
const placeholders$1 = getDefaultPaths(mockNitro$1);
|
|
22
|
+
const typesConfig$1 = getTypesConfig(mockNitro$1);
|
|
23
|
+
const tsconfigDir = dirname(join(nuxt.options.buildDir, "tsconfig.json"));
|
|
24
|
+
const relativeWithDot = (from, to) => {
|
|
25
|
+
const rel = relative(from, to);
|
|
26
|
+
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
27
|
+
};
|
|
28
|
+
const clientTypesPath$1 = resolveFilePath(typesConfig$1.client, typesConfig$1.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders$1);
|
|
29
|
+
if (clientTypesPath$1) {
|
|
30
|
+
const relativePath = relativeWithDot(tsconfigDir, clientTypesPath$1);
|
|
31
|
+
options.references.push({ path: relativePath });
|
|
32
|
+
options.tsConfig ??= {};
|
|
33
|
+
options.tsConfig.compilerOptions ??= {};
|
|
34
|
+
options.tsConfig.compilerOptions.paths ??= {};
|
|
35
|
+
options.tsConfig.compilerOptions.paths["#graphql/client"] = [relativePath];
|
|
36
|
+
options.tsConfig.include = options.tsConfig.include || [];
|
|
37
|
+
options.tsConfig.include.push(relativePath);
|
|
38
|
+
}
|
|
19
39
|
const externalServices$1 = nuxt.options.nitro?.graphql?.externalServices || [];
|
|
20
40
|
for (const service of externalServices$1) {
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
const servicePlaceholders = {
|
|
42
|
+
...placeholders$1,
|
|
43
|
+
serviceName: service.name
|
|
44
|
+
};
|
|
45
|
+
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig$1.external, typesConfig$1.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
46
|
+
if (externalTypesPath) {
|
|
47
|
+
const relativePath = relativeWithDot(tsconfigDir, externalTypesPath);
|
|
48
|
+
options.references.push({ path: relativePath });
|
|
49
|
+
options.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativePath];
|
|
50
|
+
options.tsConfig.include.push(relativePath);
|
|
51
|
+
}
|
|
23
52
|
}
|
|
24
|
-
options.tsConfig.include = options.tsConfig.include || [];
|
|
25
|
-
options.tsConfig.include.push("./types/nitro-graphql-client.d.ts");
|
|
26
|
-
for (const service of externalServices$1) options.tsConfig.include.push(`./types/nitro-graphql-client-${service.name}.d.ts`);
|
|
27
53
|
});
|
|
28
54
|
nuxt.options.alias = nuxt.options.alias || {};
|
|
29
|
-
|
|
55
|
+
const mockNitro = { options: {
|
|
56
|
+
rootDir: nuxt.options.rootDir,
|
|
57
|
+
buildDir: nuxt.options.buildDir,
|
|
58
|
+
framework: { name: "nuxt" },
|
|
59
|
+
graphql: nuxt.options.nitro?.graphql
|
|
60
|
+
} };
|
|
61
|
+
const placeholders = getDefaultPaths(mockNitro);
|
|
62
|
+
const typesConfig = getTypesConfig(mockNitro);
|
|
63
|
+
const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
|
|
64
|
+
if (clientTypesPath) nuxt.options.alias["#graphql/client"] = clientTypesPath;
|
|
30
65
|
const externalServices = nuxt.options.nitro?.graphql?.externalServices || [];
|
|
31
|
-
for (const service of externalServices)
|
|
66
|
+
for (const service of externalServices) {
|
|
67
|
+
const servicePlaceholders = {
|
|
68
|
+
...placeholders,
|
|
69
|
+
serviceName: service.name
|
|
70
|
+
};
|
|
71
|
+
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
72
|
+
if (externalTypesPath) nuxt.options.alias[`#graphql/client/${service.name}`] = externalTypesPath;
|
|
73
|
+
}
|
|
32
74
|
nuxt.hook("imports:dirs", (dirs) => {
|
|
33
75
|
const graphqlServerPath = nuxt.options.nitro?.graphql?.serverDir || resolve(nuxt.options.srcDir, "graphql");
|
|
34
76
|
dirs.push(graphqlServerPath);
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGr
|
|
|
3
3
|
import * as nitro_types0 from "nitro/types";
|
|
4
4
|
|
|
5
5
|
//#region src/index.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Nitro GraphQL module
|
|
8
|
+
* Can be used via modules array in nitro.config.ts
|
|
9
|
+
*/
|
|
6
10
|
declare const _default: nitro_types0.NitroModule;
|
|
7
11
|
//#endregion
|
|
8
12
|
export { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, ExternalServicePaths, FederationConfig, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, PathsConfig, ScaffoldConfig, SdkConfig, StandardSchemaV1, TypesConfig, _default as default };
|
package/dist/index.js
CHANGED
|
@@ -1,323 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.js";
|
|
3
|
-
import { writeFileIfNotExists } from "./utils/file-generator.js";
|
|
4
|
-
import { getScaffoldConfig, resolveFilePath, shouldGenerateScaffold } from "./utils/path-resolver.js";
|
|
5
|
-
import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.js";
|
|
6
|
-
import { rollupConfig } from "./rollup.js";
|
|
7
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { watch } from "chokidar";
|
|
10
|
-
import consola from "consola";
|
|
11
|
-
import defu from "defu";
|
|
12
|
-
import { dirname, join, relative, resolve } from "pathe";
|
|
1
|
+
import { setupNitroGraphQL } from "./setup.js";
|
|
13
2
|
|
|
14
3
|
//#region src/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* Nitro GraphQL module
|
|
6
|
+
* Can be used via modules array in nitro.config.ts
|
|
7
|
+
*/
|
|
15
8
|
var src_default = defineNitroModule({
|
|
16
9
|
name: "nitro-graphql",
|
|
17
10
|
async setup(nitro) {
|
|
18
|
-
|
|
19
|
-
if (nitro.options.graphql?.externalServices?.length) {
|
|
20
|
-
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
21
|
-
if (validationErrors.length > 0) {
|
|
22
|
-
consola.error("External services configuration errors:");
|
|
23
|
-
for (const error of validationErrors) consola.error(` - ${error}`);
|
|
24
|
-
throw new Error("Invalid external services configuration");
|
|
25
|
-
}
|
|
26
|
-
consola.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
|
|
27
|
-
}
|
|
28
|
-
const { getDefaultPaths: getDefaultPaths$1 } = await import("./utils/path-resolver.js");
|
|
29
|
-
const defaultPaths = getDefaultPaths$1(nitro);
|
|
30
|
-
nitro.graphql ||= {
|
|
31
|
-
buildDir: "",
|
|
32
|
-
watchDirs: [],
|
|
33
|
-
clientDir: defaultPaths.clientGraphql,
|
|
34
|
-
serverDir: defaultPaths.serverGraphql,
|
|
35
|
-
dir: {
|
|
36
|
-
build: relative(nitro.options.rootDir, nitro.options.buildDir),
|
|
37
|
-
client: "graphql",
|
|
38
|
-
server: "server"
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
42
|
-
rollupConfig$1.external = rollupConfig$1.external || [];
|
|
43
|
-
const codegenExternals = ["oxc-parser", "@oxc-parser"];
|
|
44
|
-
if (Array.isArray(rollupConfig$1.external)) rollupConfig$1.external.push(...codegenExternals);
|
|
45
|
-
else if (typeof rollupConfig$1.external === "function") {
|
|
46
|
-
const originalExternal = rollupConfig$1.external;
|
|
47
|
-
rollupConfig$1.external = (id, parent, isResolved) => {
|
|
48
|
-
if (codegenExternals.some((external) => id.includes(external))) return true;
|
|
49
|
-
return originalExternal(id, parent, isResolved);
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, {
|
|
54
|
-
endpoint: {
|
|
55
|
-
graphql: "/api/graphql",
|
|
56
|
-
healthCheck: "/api/graphql/health"
|
|
57
|
-
},
|
|
58
|
-
playground: true
|
|
59
|
-
});
|
|
60
|
-
if (nitro.options.graphql?.federation?.enabled) consola.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
|
|
61
|
-
const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
|
|
62
|
-
nitro.graphql.buildDir = graphqlBuildDir;
|
|
63
|
-
const watchDirs = [];
|
|
64
|
-
switch (nitro.options.framework.name) {
|
|
65
|
-
case "nuxt": {
|
|
66
|
-
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
67
|
-
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
68
|
-
watchDirs.push(nitro.graphql.clientDir);
|
|
69
|
-
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
70
|
-
const layerAppDirs = getLayerAppDirectories(nitro);
|
|
71
|
-
for (const layerServerDir of layerServerDirs) watchDirs.push(join(layerServerDir, "graphql"));
|
|
72
|
-
for (const layerAppDir of layerAppDirs) watchDirs.push(join(layerAppDir, "graphql"));
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case "nitro":
|
|
76
|
-
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
77
|
-
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
78
|
-
watchDirs.push(nitro.graphql.clientDir);
|
|
79
|
-
watchDirs.push(nitro.graphql.serverDir);
|
|
80
|
-
break;
|
|
81
|
-
default:
|
|
82
|
-
}
|
|
83
|
-
if (nitro.options.graphql?.externalServices?.length) {
|
|
84
|
-
for (const service of nitro.options.graphql.externalServices) if (service.documents?.length) for (const pattern of service.documents) {
|
|
85
|
-
if (!pattern) continue;
|
|
86
|
-
const baseDir = pattern.split("**")[0]?.replace(/\/$/, "") || ".";
|
|
87
|
-
const resolvedDir = resolve(nitro.options.rootDir, baseDir);
|
|
88
|
-
if (!watchDirs.includes(resolvedDir)) watchDirs.push(resolvedDir);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const watcher = watch(watchDirs, {
|
|
92
|
-
persistent: true,
|
|
93
|
-
ignoreInitial: true,
|
|
94
|
-
ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns(nitro)]
|
|
95
|
-
}).on("all", async (_, path) => {
|
|
96
|
-
if (path.endsWith(".graphql") || path.endsWith(".gql")) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql")) {
|
|
97
|
-
await serverTypeGeneration(nitro);
|
|
98
|
-
await clientTypeGeneration(nitro);
|
|
99
|
-
await nitro.hooks.callHook("dev:reload");
|
|
100
|
-
} else await clientTypeGeneration(nitro);
|
|
101
|
-
});
|
|
102
|
-
nitro.hooks.hook("close", () => {
|
|
103
|
-
watcher.close();
|
|
104
|
-
});
|
|
105
|
-
const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
|
|
106
|
-
const typesDir = resolve(nitro.options.buildDir, "types");
|
|
107
|
-
nitro.scanSchemas = await scanSchemas(nitro);
|
|
108
|
-
nitro.scanDocuments = await scanDocs(nitro);
|
|
109
|
-
nitro.scanResolvers = await scanResolvers(nitro);
|
|
110
|
-
const directives = await scanDirectives(nitro);
|
|
111
|
-
nitro.scanDirectives = directives;
|
|
112
|
-
await generateDirectiveSchemas(nitro, directives);
|
|
113
|
-
nitro.hooks.hook("dev:start", async () => {
|
|
114
|
-
const schemas = await scanSchemas(nitro);
|
|
115
|
-
nitro.scanSchemas = schemas;
|
|
116
|
-
const resolvers = await scanResolvers(nitro);
|
|
117
|
-
nitro.scanResolvers = resolvers;
|
|
118
|
-
const directives$1 = await scanDirectives(nitro);
|
|
119
|
-
nitro.scanDirectives = directives$1;
|
|
120
|
-
await generateDirectiveSchemas(nitro, directives$1);
|
|
121
|
-
const docs = await scanDocs(nitro);
|
|
122
|
-
nitro.scanDocuments = docs;
|
|
123
|
-
if (nitro.options.dev) {
|
|
124
|
-
consola.box({
|
|
125
|
-
title: "Nitro GraphQL",
|
|
126
|
-
message: [
|
|
127
|
-
`Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
|
|
128
|
-
`Schemas: ${schemas.length}`,
|
|
129
|
-
`Resolvers: ${resolvers.length}`,
|
|
130
|
-
`Directives: ${directives$1.length}`,
|
|
131
|
-
`Documents: ${docs.length}`,
|
|
132
|
-
"",
|
|
133
|
-
"Debug Dashboard: /_nitro/graphql/debug"
|
|
134
|
-
].join("\n"),
|
|
135
|
-
style: {
|
|
136
|
-
borderColor: "cyan",
|
|
137
|
-
borderStyle: "rounded"
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
if (resolvers.length > 0) {
|
|
141
|
-
const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
|
|
142
|
-
const typeCount = {
|
|
143
|
-
query: 0,
|
|
144
|
-
mutation: 0,
|
|
145
|
-
resolver: 0,
|
|
146
|
-
type: 0,
|
|
147
|
-
subscription: 0,
|
|
148
|
-
directive: 0
|
|
149
|
-
};
|
|
150
|
-
for (const resolver of resolvers) for (const imp of resolver.imports) if (imp.type in typeCount) typeCount[imp.type]++;
|
|
151
|
-
const breakdown = [];
|
|
152
|
-
if (typeCount.query > 0) breakdown.push(`${typeCount.query} query`);
|
|
153
|
-
if (typeCount.mutation > 0) breakdown.push(`${typeCount.mutation} mutation`);
|
|
154
|
-
if (typeCount.resolver > 0) breakdown.push(`${typeCount.resolver} resolver`);
|
|
155
|
-
if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
|
|
156
|
-
if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
|
|
157
|
-
if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
|
|
158
|
-
if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
|
|
159
|
-
} else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
await rollupConfig(nitro);
|
|
163
|
-
await serverTypeGeneration(nitro);
|
|
164
|
-
await clientTypeGeneration(nitro);
|
|
165
|
-
nitro.hooks.hook("close", async () => {
|
|
166
|
-
await serverTypeGeneration(nitro);
|
|
167
|
-
await clientTypeGeneration(nitro);
|
|
168
|
-
});
|
|
169
|
-
const runtime = fileURLToPath(new URL("routes", import.meta.url));
|
|
170
|
-
const methods = [
|
|
171
|
-
"GET",
|
|
172
|
-
"POST",
|
|
173
|
-
"OPTIONS"
|
|
174
|
-
];
|
|
175
|
-
if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
|
|
176
|
-
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
177
|
-
handler: join(runtime, "graphql-yoga"),
|
|
178
|
-
method
|
|
179
|
-
});
|
|
180
|
-
if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
|
|
181
|
-
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
182
|
-
handler: join(runtime, "apollo-server"),
|
|
183
|
-
method
|
|
184
|
-
});
|
|
185
|
-
nitro.options.handlers.push({
|
|
186
|
-
route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
|
|
187
|
-
handler: join(runtime, "health"),
|
|
188
|
-
method: "GET"
|
|
189
|
-
});
|
|
190
|
-
if (nitro.options.dev) {
|
|
191
|
-
nitro.options.handlers.push({
|
|
192
|
-
route: "/_nitro/graphql/debug",
|
|
193
|
-
handler: join(runtime, "debug"),
|
|
194
|
-
method: "GET"
|
|
195
|
-
});
|
|
196
|
-
consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
|
|
197
|
-
}
|
|
198
|
-
if (nitro.options.imports) {
|
|
199
|
-
nitro.options.imports.presets ??= [];
|
|
200
|
-
nitro.options.imports.presets.push({
|
|
201
|
-
from: fileURLToPath(new URL("utils/define", import.meta.url)),
|
|
202
|
-
imports: [
|
|
203
|
-
"defineResolver",
|
|
204
|
-
"defineMutation",
|
|
205
|
-
"defineQuery",
|
|
206
|
-
"defineSubscription",
|
|
207
|
-
"defineType",
|
|
208
|
-
"defineGraphQLConfig",
|
|
209
|
-
"defineSchema",
|
|
210
|
-
"defineDirective"
|
|
211
|
-
]
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
215
|
-
const manualChunks = rollupConfig$1.output?.manualChunks;
|
|
216
|
-
const chunkFiles = rollupConfig$1.output?.chunkFileNames;
|
|
217
|
-
if (!rollupConfig$1.output.inlineDynamicImports) {
|
|
218
|
-
rollupConfig$1.output.manualChunks = (id, meta) => {
|
|
219
|
-
if (id.endsWith(".graphql") || id.endsWith(".gql")) return "schemas";
|
|
220
|
-
if (id.endsWith(".resolver.ts")) return "resolvers";
|
|
221
|
-
if (typeof manualChunks === "function") return manualChunks(id, meta);
|
|
222
|
-
};
|
|
223
|
-
rollupConfig$1.output.advancedChunks = { groups: [{
|
|
224
|
-
name: "schemas",
|
|
225
|
-
test: /\.(?:graphql|gql)$/
|
|
226
|
-
}, {
|
|
227
|
-
name: "resolvers",
|
|
228
|
-
test: /\.resolver\.ts$/
|
|
229
|
-
}] };
|
|
230
|
-
}
|
|
231
|
-
rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
|
|
232
|
-
if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;
|
|
233
|
-
if (typeof chunkFiles === "function") return chunkFiles(chunkInfo);
|
|
234
|
-
return `chunks/_/[name].mjs`;
|
|
235
|
-
};
|
|
236
|
-
});
|
|
237
|
-
nitro.options.typescript.strict = true;
|
|
238
|
-
nitro.hooks.hook("types:extend", (types) => {
|
|
239
|
-
types.tsConfig ||= {};
|
|
240
|
-
types.tsConfig.compilerOptions ??= {};
|
|
241
|
-
types.tsConfig.compilerOptions.paths ??= {};
|
|
242
|
-
types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-server.d.ts"))];
|
|
243
|
-
types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-client.d.ts"))];
|
|
244
|
-
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
245
|
-
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, join(typesDir, `nitro-graphql-client-${service.name}.d.ts`))];
|
|
246
|
-
types.tsConfig.include = types.tsConfig.include || [];
|
|
247
|
-
types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-server.d.ts")), relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-client.d.ts")), relativeWithDot(tsconfigDir, join(typesDir, "graphql.d.ts")));
|
|
248
|
-
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(typesDir, `nitro-graphql-client-${service.name}.d.ts`)));
|
|
249
|
-
});
|
|
250
|
-
if (nitro.options.framework?.name === "nuxt" && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
|
|
251
|
-
const nuxtOptions = nitro._nuxt?.options;
|
|
252
|
-
if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
|
|
253
|
-
});
|
|
254
|
-
if (shouldGenerateScaffold(nitro)) {
|
|
255
|
-
const placeholders = getDefaultPaths$1(nitro);
|
|
256
|
-
const scaffoldConfig = getScaffoldConfig(nitro);
|
|
257
|
-
const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
|
|
258
|
-
if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
|
|
259
|
-
import type { IGraphQLConfig } from 'graphql-config'
|
|
260
|
-
|
|
261
|
-
export default <IGraphQLConfig> {
|
|
262
|
-
projects: {
|
|
263
|
-
default: {
|
|
264
|
-
schema: [
|
|
265
|
-
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
|
|
266
|
-
],
|
|
267
|
-
documents: [
|
|
268
|
-
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
|
|
269
|
-
],
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
}`, "graphql.config.ts");
|
|
273
|
-
const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
|
|
274
|
-
const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
|
|
275
|
-
const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.ts", placeholders);
|
|
276
|
-
if (serverSchemaPath || serverConfigPath || serverContextPath) {
|
|
277
|
-
if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
|
|
278
|
-
}
|
|
279
|
-
if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
|
|
280
|
-
|
|
281
|
-
})
|
|
282
|
-
`, "server schema.ts");
|
|
283
|
-
if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
|
|
284
|
-
// import * as tables from '../drizzle/schema/index'
|
|
285
|
-
// import { useDatabase } from '../utils/useDb'
|
|
286
|
-
import { defineGraphQLConfig } from 'nitro-graphql/utils/define'
|
|
287
|
-
|
|
288
|
-
export default defineGraphQLConfig({
|
|
289
|
-
// graphql-yoga example config
|
|
290
|
-
// context: () => {
|
|
291
|
-
// return {
|
|
292
|
-
// context: {
|
|
293
|
-
// useDatabase,
|
|
294
|
-
// tables,
|
|
295
|
-
// },
|
|
296
|
-
// }
|
|
297
|
-
// },
|
|
298
|
-
})
|
|
299
|
-
`, "server config.ts");
|
|
300
|
-
if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
|
|
301
|
-
// import type { Database } from '../utils/useDb'
|
|
302
|
-
|
|
303
|
-
declare module 'h3' {
|
|
304
|
-
interface H3EventContext {
|
|
305
|
-
// Add your custom context properties here
|
|
306
|
-
// useDatabase: () => Database
|
|
307
|
-
// tables: typeof import('../drizzle/schema')
|
|
308
|
-
// auth?: {
|
|
309
|
-
// user?: {
|
|
310
|
-
// id: string
|
|
311
|
-
// role: 'admin' | 'user'
|
|
312
|
-
// }
|
|
313
|
-
// }
|
|
314
|
-
}
|
|
315
|
-
}`, "server context.ts");
|
|
316
|
-
if (existsSync(join(nitro.graphql.serverDir, "context.d.ts"))) {
|
|
317
|
-
consola.warn("nitro-graphql: Found context.d.ts file. Please rename it to context.ts for the new structure.");
|
|
318
|
-
consola.info("The context file should now be context.ts instead of context.d.ts");
|
|
319
|
-
}
|
|
320
|
-
} else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
|
|
11
|
+
await setupNitroGraphQL(nitro);
|
|
321
12
|
}
|
|
322
13
|
});
|
|
323
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h30 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/apollo-server.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h30.EventHandlerWithFetch<h30.EventHandlerRequest, Promise<any>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/routes/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h33 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/debug.d.ts
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ import * as h35 from "h3";
|
|
|
10
10
|
* - /_nitro/graphql/debug - HTML dashboard
|
|
11
11
|
* - /_nitro/graphql/debug?format=json - JSON API
|
|
12
12
|
*/
|
|
13
|
-
declare const _default:
|
|
13
|
+
declare const _default: h33.EventHandlerWithFetch<h33.EventHandlerRequest, Promise<string | {
|
|
14
14
|
timestamp: string;
|
|
15
15
|
environment: {
|
|
16
16
|
dev: any;
|
package/dist/routes/debug.js
CHANGED
|
@@ -2,7 +2,7 @@ import { moduleConfig } from "#nitro-graphql/module-config";
|
|
|
2
2
|
import { directives } from "#nitro-graphql/server-directives";
|
|
3
3
|
import { resolvers } from "#nitro-graphql/server-resolvers";
|
|
4
4
|
import { schemas } from "#nitro-graphql/server-schemas";
|
|
5
|
-
import { defineEventHandler, getQuery
|
|
5
|
+
import { defineEventHandler, getQuery } from "h3";
|
|
6
6
|
import { debugInfo } from "#nitro-graphql/debug-info";
|
|
7
7
|
|
|
8
8
|
//#region src/routes/debug.ts
|
|
@@ -15,10 +15,6 @@ import { debugInfo } from "#nitro-graphql/debug-info";
|
|
|
15
15
|
* - /_nitro/graphql/debug?format=json - JSON API
|
|
16
16
|
*/
|
|
17
17
|
var debug_default = defineEventHandler(async (event) => {
|
|
18
|
-
if (!debugInfo.isDev) {
|
|
19
|
-
setResponseHeader(event, "Content-Type", "text/plain");
|
|
20
|
-
return "Debug endpoint is only available in development mode";
|
|
21
|
-
}
|
|
22
18
|
const format = getQuery(event).format || "html";
|
|
23
19
|
const processedResolverFiles = debugInfo.scanned.resolverFiles.map((r) => {
|
|
24
20
|
const parts = r.specifier.split("/");
|
|
@@ -94,10 +90,10 @@ var debug_default = defineEventHandler(async (event) => {
|
|
|
94
90
|
}
|
|
95
91
|
};
|
|
96
92
|
if (format === "json") {
|
|
97
|
-
|
|
93
|
+
event.res.headers.set("Content-Type", "application/json");
|
|
98
94
|
return fullDebugInfo;
|
|
99
95
|
}
|
|
100
|
-
|
|
96
|
+
event.res.headers.set("Content-Type", "text/html");
|
|
101
97
|
return generateHtmlDashboard(fullDebugInfo);
|
|
102
98
|
});
|
|
103
99
|
function generateHtmlDashboard(debugInfo$1) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h35 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/graphql-yoga.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h35.EventHandlerWithFetch<h35.EventHandlerRequest, Promise<Response>>;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { _default as default };
|
package/dist/routes/health.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as h31 from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/routes/health.d.ts
|
|
4
|
-
declare const _default:
|
|
4
|
+
declare const _default: h31.EventHandlerWithFetch<h31.EventHandlerRequest, Promise<{
|
|
5
5
|
status: string;
|
|
6
6
|
message: string;
|
|
7
7
|
timestamp: string;
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { generateDirectiveSchemas } from "./utils/directive-parser.js";
|
|
2
|
+
import { generateLayerIgnorePatterns, getLayerAppDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanResolvers, scanSchemas, validateExternalServices } from "./utils/index.js";
|
|
3
|
+
import { writeFileIfNotExists } from "./utils/file-generator.js";
|
|
4
|
+
import { getScaffoldConfig, getTypesConfig, resolveFilePath, shouldGenerateScaffold } from "./utils/path-resolver.js";
|
|
5
|
+
import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.js";
|
|
6
|
+
import { rollupConfig } from "./rollup.js";
|
|
7
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { watch } from "chokidar";
|
|
10
|
+
import consola from "consola";
|
|
11
|
+
import defu from "defu";
|
|
12
|
+
import { dirname, join, relative, resolve } from "pathe";
|
|
13
|
+
|
|
14
|
+
//#region src/setup.ts
|
|
15
|
+
/**
|
|
16
|
+
* Shared setup logic for nitro-graphql module
|
|
17
|
+
* Used by both the direct Nitro module export and the Vite plugin's nitro: hook
|
|
18
|
+
*/
|
|
19
|
+
async function setupNitroGraphQL(nitro) {
|
|
20
|
+
if (!nitro.options.graphql?.framework) consola.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
|
|
21
|
+
if (nitro.options.graphql?.externalServices?.length) {
|
|
22
|
+
const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
|
|
23
|
+
if (validationErrors.length > 0) {
|
|
24
|
+
consola.error("External services configuration errors:");
|
|
25
|
+
for (const error of validationErrors) consola.error(` - ${error}`);
|
|
26
|
+
throw new Error("Invalid external services configuration");
|
|
27
|
+
}
|
|
28
|
+
consola.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
|
|
29
|
+
}
|
|
30
|
+
const { getDefaultPaths } = await import("./utils/path-resolver.js");
|
|
31
|
+
const defaultPaths = getDefaultPaths(nitro);
|
|
32
|
+
nitro.graphql ||= {
|
|
33
|
+
buildDir: "",
|
|
34
|
+
watchDirs: [],
|
|
35
|
+
clientDir: defaultPaths.clientGraphql,
|
|
36
|
+
serverDir: defaultPaths.serverGraphql,
|
|
37
|
+
dir: {
|
|
38
|
+
build: relative(nitro.options.rootDir, nitro.options.buildDir),
|
|
39
|
+
client: "graphql",
|
|
40
|
+
server: "server"
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
44
|
+
rollupConfig$1.external = rollupConfig$1.external || [];
|
|
45
|
+
const codegenExternals = ["oxc-parser", "@oxc-parser"];
|
|
46
|
+
if (Array.isArray(rollupConfig$1.external)) rollupConfig$1.external.push(...codegenExternals);
|
|
47
|
+
else if (typeof rollupConfig$1.external === "function") {
|
|
48
|
+
const originalExternal = rollupConfig$1.external;
|
|
49
|
+
rollupConfig$1.external = (id, parent, isResolved) => {
|
|
50
|
+
if (codegenExternals.some((external) => id.includes(external))) return true;
|
|
51
|
+
return originalExternal(id, parent, isResolved);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
nitro.options.runtimeConfig.graphql = defu(nitro.options.runtimeConfig.graphql || {}, {
|
|
56
|
+
endpoint: {
|
|
57
|
+
graphql: "/api/graphql",
|
|
58
|
+
healthCheck: "/api/graphql/health"
|
|
59
|
+
},
|
|
60
|
+
playground: true
|
|
61
|
+
});
|
|
62
|
+
if (nitro.options.graphql?.federation?.enabled) consola.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
|
|
63
|
+
const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
|
|
64
|
+
nitro.graphql.buildDir = graphqlBuildDir;
|
|
65
|
+
const watchDirs = [];
|
|
66
|
+
switch (nitro.options.framework.name) {
|
|
67
|
+
case "nuxt": {
|
|
68
|
+
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
69
|
+
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
70
|
+
watchDirs.push(nitro.graphql.clientDir);
|
|
71
|
+
const layerServerDirs = getLayerServerDirectories(nitro);
|
|
72
|
+
const layerAppDirs = getLayerAppDirectories(nitro);
|
|
73
|
+
for (const layerServerDir of layerServerDirs) watchDirs.push(join(layerServerDir, "graphql"));
|
|
74
|
+
for (const layerAppDir of layerAppDirs) watchDirs.push(join(layerAppDir, "graphql"));
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "nitro":
|
|
78
|
+
nitro.graphql.dir.client = relative(nitro.options.rootDir, nitro.graphql.clientDir);
|
|
79
|
+
nitro.graphql.dir.server = relative(nitro.options.rootDir, nitro.graphql.serverDir);
|
|
80
|
+
watchDirs.push(nitro.graphql.clientDir);
|
|
81
|
+
watchDirs.push(nitro.graphql.serverDir);
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
}
|
|
85
|
+
if (nitro.options.graphql?.externalServices?.length) {
|
|
86
|
+
for (const service of nitro.options.graphql.externalServices) if (service.documents?.length) for (const pattern of service.documents) {
|
|
87
|
+
if (!pattern) continue;
|
|
88
|
+
const baseDir = pattern.split("**")[0]?.replace(/\/$/, "") || ".";
|
|
89
|
+
const resolvedDir = resolve(nitro.options.rootDir, baseDir);
|
|
90
|
+
if (!watchDirs.includes(resolvedDir)) watchDirs.push(resolvedDir);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const watcher = watch(watchDirs, {
|
|
94
|
+
persistent: true,
|
|
95
|
+
ignoreInitial: true,
|
|
96
|
+
ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns(nitro)]
|
|
97
|
+
}).on("all", async (_, path) => {
|
|
98
|
+
if (path.endsWith(".graphql") || path.endsWith(".gql")) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql")) {
|
|
99
|
+
await serverTypeGeneration(nitro);
|
|
100
|
+
await clientTypeGeneration(nitro);
|
|
101
|
+
await nitro.hooks.callHook("dev:reload");
|
|
102
|
+
} else await clientTypeGeneration(nitro);
|
|
103
|
+
});
|
|
104
|
+
nitro.hooks.hook("close", () => {
|
|
105
|
+
watcher.close();
|
|
106
|
+
});
|
|
107
|
+
const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
|
|
108
|
+
nitro.scanSchemas = await scanSchemas(nitro);
|
|
109
|
+
nitro.scanDocuments = await scanDocs(nitro);
|
|
110
|
+
nitro.scanResolvers = await scanResolvers(nitro);
|
|
111
|
+
const directives = await scanDirectives(nitro);
|
|
112
|
+
nitro.scanDirectives = directives;
|
|
113
|
+
await generateDirectiveSchemas(nitro, directives);
|
|
114
|
+
nitro.hooks.hook("dev:start", async () => {
|
|
115
|
+
const schemas = await scanSchemas(nitro);
|
|
116
|
+
nitro.scanSchemas = schemas;
|
|
117
|
+
const resolvers = await scanResolvers(nitro);
|
|
118
|
+
nitro.scanResolvers = resolvers;
|
|
119
|
+
const directives$1 = await scanDirectives(nitro);
|
|
120
|
+
nitro.scanDirectives = directives$1;
|
|
121
|
+
await generateDirectiveSchemas(nitro, directives$1);
|
|
122
|
+
const docs = await scanDocs(nitro);
|
|
123
|
+
nitro.scanDocuments = docs;
|
|
124
|
+
if (nitro.options.dev) {
|
|
125
|
+
consola.box({
|
|
126
|
+
title: "Nitro GraphQL",
|
|
127
|
+
message: [
|
|
128
|
+
`Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
|
|
129
|
+
`Schemas: ${schemas.length}`,
|
|
130
|
+
`Resolvers: ${resolvers.length}`,
|
|
131
|
+
`Directives: ${directives$1.length}`,
|
|
132
|
+
`Documents: ${docs.length}`,
|
|
133
|
+
"",
|
|
134
|
+
"Debug Dashboard: /_nitro/graphql/debug"
|
|
135
|
+
].join("\n"),
|
|
136
|
+
style: {
|
|
137
|
+
borderColor: "cyan",
|
|
138
|
+
borderStyle: "rounded"
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
if (resolvers.length > 0) {
|
|
142
|
+
const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
|
|
143
|
+
const typeCount = {
|
|
144
|
+
query: 0,
|
|
145
|
+
mutation: 0,
|
|
146
|
+
resolver: 0,
|
|
147
|
+
type: 0,
|
|
148
|
+
subscription: 0,
|
|
149
|
+
directive: 0
|
|
150
|
+
};
|
|
151
|
+
for (const resolver of resolvers) for (const imp of resolver.imports) if (imp.type in typeCount) typeCount[imp.type]++;
|
|
152
|
+
const breakdown = [];
|
|
153
|
+
if (typeCount.query > 0) breakdown.push(`${typeCount.query} query`);
|
|
154
|
+
if (typeCount.mutation > 0) breakdown.push(`${typeCount.mutation} mutation`);
|
|
155
|
+
if (typeCount.resolver > 0) breakdown.push(`${typeCount.resolver} resolver`);
|
|
156
|
+
if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
|
|
157
|
+
if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
|
|
158
|
+
if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
|
|
159
|
+
if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
|
|
160
|
+
} else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
await rollupConfig(nitro);
|
|
164
|
+
await serverTypeGeneration(nitro);
|
|
165
|
+
await clientTypeGeneration(nitro);
|
|
166
|
+
nitro.hooks.hook("close", async () => {
|
|
167
|
+
await serverTypeGeneration(nitro);
|
|
168
|
+
await clientTypeGeneration(nitro);
|
|
169
|
+
});
|
|
170
|
+
const runtime = fileURLToPath(new URL("routes", import.meta.url));
|
|
171
|
+
const methods = [
|
|
172
|
+
"GET",
|
|
173
|
+
"POST",
|
|
174
|
+
"OPTIONS"
|
|
175
|
+
];
|
|
176
|
+
if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
|
|
177
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
178
|
+
handler: join(runtime, "graphql-yoga"),
|
|
179
|
+
method
|
|
180
|
+
});
|
|
181
|
+
if (nitro.options.graphql?.framework === "apollo-server") for (const method of methods) nitro.options.handlers.push({
|
|
182
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
|
|
183
|
+
handler: join(runtime, "apollo-server"),
|
|
184
|
+
method
|
|
185
|
+
});
|
|
186
|
+
nitro.options.handlers.push({
|
|
187
|
+
route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
|
|
188
|
+
handler: join(runtime, "health"),
|
|
189
|
+
method: "GET"
|
|
190
|
+
});
|
|
191
|
+
if (nitro.options.dev) {
|
|
192
|
+
nitro.options.handlers.push({
|
|
193
|
+
route: "/_nitro/graphql/debug",
|
|
194
|
+
handler: join(runtime, "debug"),
|
|
195
|
+
method: "GET"
|
|
196
|
+
});
|
|
197
|
+
consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
|
|
198
|
+
}
|
|
199
|
+
if (nitro.options.imports) {
|
|
200
|
+
nitro.options.imports.presets ??= [];
|
|
201
|
+
nitro.options.imports.presets.push({
|
|
202
|
+
from: fileURLToPath(new URL("utils/define", import.meta.url)),
|
|
203
|
+
imports: [
|
|
204
|
+
"defineResolver",
|
|
205
|
+
"defineMutation",
|
|
206
|
+
"defineQuery",
|
|
207
|
+
"defineSubscription",
|
|
208
|
+
"defineType",
|
|
209
|
+
"defineGraphQLConfig",
|
|
210
|
+
"defineSchema",
|
|
211
|
+
"defineDirective"
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
nitro.hooks.hook("rollup:before", (_, rollupConfig$1) => {
|
|
216
|
+
const manualChunks = rollupConfig$1.output?.manualChunks;
|
|
217
|
+
const chunkFiles = rollupConfig$1.output?.chunkFileNames;
|
|
218
|
+
if (!rollupConfig$1.output.inlineDynamicImports) {
|
|
219
|
+
rollupConfig$1.output.manualChunks = (id, meta) => {
|
|
220
|
+
if (id.endsWith(".graphql") || id.endsWith(".gql")) return "schemas";
|
|
221
|
+
if (id.endsWith(".resolver.ts")) return "resolvers";
|
|
222
|
+
if (typeof manualChunks === "function") return manualChunks(id, meta);
|
|
223
|
+
};
|
|
224
|
+
rollupConfig$1.output.advancedChunks = { groups: [{
|
|
225
|
+
name: "schemas",
|
|
226
|
+
test: /\.(?:graphql|gql)$/
|
|
227
|
+
}, {
|
|
228
|
+
name: "resolvers",
|
|
229
|
+
test: /\.resolver\.ts$/
|
|
230
|
+
}] };
|
|
231
|
+
}
|
|
232
|
+
rollupConfig$1.output.chunkFileNames = (chunkInfo) => {
|
|
233
|
+
if (chunkInfo.moduleIds && chunkInfo.moduleIds.some((id) => id.endsWith(".graphql") || id.endsWith(".resolver.ts") || id.endsWith(".gql"))) return `chunks/graphql/[name].mjs`;
|
|
234
|
+
if (typeof chunkFiles === "function") return chunkFiles(chunkInfo);
|
|
235
|
+
return `chunks/_/[name].mjs`;
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
nitro.options.typescript.strict = true;
|
|
239
|
+
nitro.hooks.hook("types:extend", (types) => {
|
|
240
|
+
types.tsConfig ||= {};
|
|
241
|
+
types.tsConfig.compilerOptions ??= {};
|
|
242
|
+
types.tsConfig.compilerOptions.paths ??= {};
|
|
243
|
+
const placeholders = getDefaultPaths(nitro);
|
|
244
|
+
const typesConfig = getTypesConfig(nitro);
|
|
245
|
+
const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
|
|
246
|
+
if (serverTypesPath) types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
|
|
247
|
+
const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
|
|
248
|
+
if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
|
|
249
|
+
types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
|
|
250
|
+
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
|
|
251
|
+
const servicePlaceholders = {
|
|
252
|
+
...placeholders,
|
|
253
|
+
serviceName: service.name
|
|
254
|
+
};
|
|
255
|
+
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
256
|
+
if (externalTypesPath) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
|
|
257
|
+
}
|
|
258
|
+
types.tsConfig.include = types.tsConfig.include || [];
|
|
259
|
+
if (serverTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
|
|
260
|
+
if (clientTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
|
|
261
|
+
types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
|
|
262
|
+
if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
|
|
263
|
+
const servicePlaceholders = {
|
|
264
|
+
...placeholders,
|
|
265
|
+
serviceName: service.name
|
|
266
|
+
};
|
|
267
|
+
const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
|
|
268
|
+
if (externalTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
if (nitro.options.framework?.name === "nuxt" && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
|
|
272
|
+
const nuxtOptions = nitro._nuxt?.options;
|
|
273
|
+
if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
|
|
274
|
+
});
|
|
275
|
+
if (shouldGenerateScaffold(nitro)) {
|
|
276
|
+
const placeholders = getDefaultPaths(nitro);
|
|
277
|
+
const scaffoldConfig = getScaffoldConfig(nitro);
|
|
278
|
+
const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
|
|
279
|
+
if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
|
|
280
|
+
import type { IGraphQLConfig } from 'graphql-config'
|
|
281
|
+
|
|
282
|
+
export default <IGraphQLConfig> {
|
|
283
|
+
projects: {
|
|
284
|
+
default: {
|
|
285
|
+
schema: [
|
|
286
|
+
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
|
|
287
|
+
],
|
|
288
|
+
documents: [
|
|
289
|
+
'${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
}`, "graphql.config.ts");
|
|
294
|
+
const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
|
|
295
|
+
const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
|
|
296
|
+
const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.ts", placeholders);
|
|
297
|
+
if (serverSchemaPath || serverConfigPath || serverContextPath) {
|
|
298
|
+
if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
|
|
299
|
+
}
|
|
300
|
+
if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
|
|
301
|
+
|
|
302
|
+
})
|
|
303
|
+
`, "server schema.ts");
|
|
304
|
+
if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
|
|
305
|
+
// import * as tables from '../drizzle/schema/index'
|
|
306
|
+
// import { useDatabase } from '../utils/useDb'
|
|
307
|
+
import { defineGraphQLConfig } from 'nitro-graphql/utils/define'
|
|
308
|
+
|
|
309
|
+
export default defineGraphQLConfig({
|
|
310
|
+
// graphql-yoga example config
|
|
311
|
+
// context: () => {
|
|
312
|
+
// return {
|
|
313
|
+
// context: {
|
|
314
|
+
// useDatabase,
|
|
315
|
+
// tables,
|
|
316
|
+
// },
|
|
317
|
+
// }
|
|
318
|
+
// },
|
|
319
|
+
})
|
|
320
|
+
`, "server config.ts");
|
|
321
|
+
if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
|
|
322
|
+
// import type { Database } from '../utils/useDb'
|
|
323
|
+
|
|
324
|
+
declare module 'h3' {
|
|
325
|
+
interface H3EventContext {
|
|
326
|
+
// Add your custom context properties here
|
|
327
|
+
// useDatabase: () => Database
|
|
328
|
+
// tables: typeof import('../drizzle/schema')
|
|
329
|
+
// auth?: {
|
|
330
|
+
// user?: {
|
|
331
|
+
// id: string
|
|
332
|
+
// role: 'admin' | 'user'
|
|
333
|
+
// }
|
|
334
|
+
// }
|
|
335
|
+
}
|
|
336
|
+
}`, "server context.ts");
|
|
337
|
+
if (existsSync(join(nitro.graphql.serverDir, "context.d.ts"))) {
|
|
338
|
+
consola.warn("nitro-graphql: Found context.d.ts file. Please rename it to context.ts for the new structure.");
|
|
339
|
+
consola.info("The context file should now be context.ts instead of context.d.ts");
|
|
340
|
+
}
|
|
341
|
+
} else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//#endregion
|
|
345
|
+
export { setupNitroGraphQL };
|
|
@@ -23,14 +23,14 @@ declare function loadExternalSchema(service: ExternalGraphQLService, buildDir?:
|
|
|
23
23
|
*/
|
|
24
24
|
declare function downloadAndSaveSchema(service: ExternalGraphQLService, buildDir: string): Promise<string | undefined>;
|
|
25
25
|
declare function loadGraphQLDocuments(patterns: string | string[]): Promise<Source[]>;
|
|
26
|
-
declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string): Promise<false | {
|
|
26
|
+
declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string, virtualTypesPath?: string): Promise<false | {
|
|
27
27
|
types: string;
|
|
28
28
|
sdk: string;
|
|
29
29
|
}>;
|
|
30
30
|
/**
|
|
31
31
|
* Generate client types for external GraphQL service
|
|
32
32
|
*/
|
|
33
|
-
declare function generateExternalClientTypes(service: ExternalGraphQLService, schema: GraphQLSchema, docs: Source[]): Promise<{
|
|
33
|
+
declare function generateExternalClientTypes(service: ExternalGraphQLService, schema: GraphQLSchema, docs: Source[], virtualTypesPath?: string): Promise<{
|
|
34
34
|
types: string;
|
|
35
35
|
sdk: string;
|
|
36
36
|
} | false>;
|
|
@@ -165,7 +165,7 @@ async function loadGraphQLDocuments(patterns) {
|
|
|
165
165
|
else throw e;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName) {
|
|
168
|
+
async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath) {
|
|
169
169
|
if (docs.length === 0 && !serviceName) {
|
|
170
170
|
consola$1.info("No client GraphQL files found. Skipping client type generation.");
|
|
171
171
|
return false;
|
|
@@ -252,7 +252,7 @@ export function getSdk(requester: Requester): Sdk {
|
|
|
252
252
|
typescriptOperations: { plugin: plugin$2 }
|
|
253
253
|
}
|
|
254
254
|
});
|
|
255
|
-
const typesPath = serviceName ? `#graphql/client/${serviceName}` : "#graphql/client";
|
|
255
|
+
const typesPath = virtualTypesPath || (serviceName ? `#graphql/client/${serviceName}` : "#graphql/client");
|
|
256
256
|
const sdkOutput = await preset.buildGeneratesSection({
|
|
257
257
|
baseOutputDir: outputPath || "client-types.generated.ts",
|
|
258
258
|
schema: parse(printSchemaWithDirectives(schema)),
|
|
@@ -282,8 +282,8 @@ export function getSdk(requester: Requester): Sdk {
|
|
|
282
282
|
/**
|
|
283
283
|
* Generate client types for external GraphQL service
|
|
284
284
|
*/
|
|
285
|
-
async function generateExternalClientTypes(service, schema, docs) {
|
|
286
|
-
return generateClientTypes(schema, docs, service.codegen?.client || {}, service.codegen?.clientSDK || {}, void 0, service.name);
|
|
285
|
+
async function generateExternalClientTypes(service, schema, docs, virtualTypesPath) {
|
|
286
|
+
return generateClientTypes(schema, docs, service.codegen?.client || {}, service.codegen?.clientSDK || {}, void 0, service.name, virtualTypesPath);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolve } from "pathe";
|
|
1
|
+
import { isAbsolute, resolve } from "pathe";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/path-resolver.ts
|
|
4
4
|
/**
|
|
@@ -49,7 +49,7 @@ function resolveFilePath(config, categoryEnabled, topLevelEnabled, defaultPath,
|
|
|
49
49
|
if (!shouldGenerateFile(config, categoryEnabled, topLevelEnabled)) return null;
|
|
50
50
|
if (typeof config === "string") {
|
|
51
51
|
const customPath = replacePlaceholders(config, placeholders);
|
|
52
|
-
return resolve(placeholders.rootDir, customPath);
|
|
52
|
+
return isAbsolute(customPath) ? customPath : resolve(placeholders.rootDir, customPath);
|
|
53
53
|
}
|
|
54
54
|
const resolvedDefault = replacePlaceholders(defaultPath, placeholders);
|
|
55
55
|
return resolve(placeholders.rootDir, resolvedDefault);
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { NitroGraphQLOptions } from "./types/index.js";
|
|
1
2
|
import { Plugin } from "vite";
|
|
2
3
|
|
|
3
4
|
//#region src/vite.d.ts
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Vite plugin to load GraphQL files as strings
|
|
7
|
+
* Vite plugin to load GraphQL files as strings AND auto-register Nitro module
|
|
7
8
|
* This prevents Vite from trying to parse .graphql/.gql files as JavaScript
|
|
9
|
+
* and automatically sets up the nitro-graphql module via the nitro: hook
|
|
8
10
|
*
|
|
9
11
|
* @example
|
|
10
12
|
* ```ts
|
|
@@ -14,12 +16,12 @@ import { Plugin } from "vite";
|
|
|
14
16
|
*
|
|
15
17
|
* export default defineConfig({
|
|
16
18
|
* plugins: [
|
|
17
|
-
* graphql(), //
|
|
19
|
+
* graphql({ framework: 'graphql-yoga' }), // Auto-registers Nitro module
|
|
18
20
|
* nitro()
|
|
19
21
|
* ]
|
|
20
22
|
* })
|
|
21
23
|
* ```
|
|
22
24
|
*/
|
|
23
|
-
declare function graphql(): Plugin;
|
|
25
|
+
declare function graphql(options?: NitroGraphQLOptions): Plugin;
|
|
24
26
|
//#endregion
|
|
25
27
|
export { graphql };
|
package/dist/vite.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { setupNitroGraphQL } from "./setup.js";
|
|
2
|
+
import defu from "defu";
|
|
1
3
|
import { readFile } from "node:fs/promises";
|
|
2
4
|
|
|
3
5
|
//#region src/vite.ts
|
|
4
6
|
/**
|
|
5
|
-
* Vite plugin to load GraphQL files as strings
|
|
7
|
+
* Vite plugin to load GraphQL files as strings AND auto-register Nitro module
|
|
6
8
|
* This prevents Vite from trying to parse .graphql/.gql files as JavaScript
|
|
9
|
+
* and automatically sets up the nitro-graphql module via the nitro: hook
|
|
7
10
|
*
|
|
8
11
|
* @example
|
|
9
12
|
* ```ts
|
|
@@ -13,13 +16,13 @@ import { readFile } from "node:fs/promises";
|
|
|
13
16
|
*
|
|
14
17
|
* export default defineConfig({
|
|
15
18
|
* plugins: [
|
|
16
|
-
* graphql(), //
|
|
19
|
+
* graphql({ framework: 'graphql-yoga' }), // Auto-registers Nitro module
|
|
17
20
|
* nitro()
|
|
18
21
|
* ]
|
|
19
22
|
* })
|
|
20
23
|
* ```
|
|
21
24
|
*/
|
|
22
|
-
function graphql() {
|
|
25
|
+
function graphql(options) {
|
|
23
26
|
return {
|
|
24
27
|
name: "nitro-graphql:vite",
|
|
25
28
|
enforce: "pre",
|
|
@@ -32,7 +35,11 @@ function graphql() {
|
|
|
32
35
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") return null;
|
|
33
36
|
throw error;
|
|
34
37
|
}
|
|
35
|
-
}
|
|
38
|
+
},
|
|
39
|
+
nitro: { async setup(nitro) {
|
|
40
|
+
if (options) nitro.options.graphql = defu(nitro.options.graphql || {}, options);
|
|
41
|
+
await setupNitroGraphQL(nitro);
|
|
42
|
+
} }
|
|
36
43
|
};
|
|
37
44
|
}
|
|
38
45
|
|