nitro-graphql 1.5.0 → 1.5.2

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 CHANGED
@@ -1,17 +1,20 @@
1
- # Nitro GraphQL
2
-
3
1
  <div align="center">
4
2
 
3
+ <img src="./.docs/public/logo.svg" alt="Nitro GraphQL Logo" width="120" height="120">
4
+
5
+ # Nitro GraphQL
6
+
5
7
  [![npm version][npm-version-src]][npm-version-href]
6
8
  [![npm downloads][npm-downloads-src]][npm-downloads-href]
7
9
  [![bundle][bundle-src]][bundle-href]
8
10
  [![License][license-src]][license-href]
11
+ [![Documentation][docs-src]][docs-href]
9
12
 
10
13
  **The easiest way to add GraphQL to any Nitro application**
11
14
 
12
15
  🚀 **Auto-discovery** • 📝 **Type Generation** • 🎮 **Apollo Sandbox** • 🔧 **Zero Config**
13
16
 
14
- [Quick Start](#-quick-start) • [Examples](#-examples) • [Documentation](#-documentation) • [Community](#-community)
17
+ [📚 Documentation](https://nitro-graphql.pages.dev) • [Quick Start](#-quick-start) • [Examples](#-examples) • [Community](#-community)
15
18
 
16
19
  </div>
17
20
 
@@ -210,6 +213,246 @@ query {
210
213
 
211
214
  ## 🚀 Advanced Features
212
215
 
216
+ <details>
217
+ <summary><strong>🎛️ Custom File Generation & Paths</strong></summary>
218
+
219
+ Control which files are auto-generated and customize their output paths. Perfect for library development, monorepos, or custom project structures.
220
+
221
+ ### Library Mode
222
+
223
+ Disable all scaffold files for library/module development:
224
+
225
+ ```ts
226
+ // nitro.config.ts
227
+ export default defineNitroConfig({
228
+ graphql: {
229
+ framework: 'graphql-yoga',
230
+ scaffold: false, // Disable all scaffold files
231
+ clientUtils: false, // Disable client utilities
232
+ }
233
+ })
234
+ ```
235
+
236
+ ### Fine-Grained Control
237
+
238
+ Control each file individually:
239
+
240
+ ```ts
241
+ export default defineNitroConfig({
242
+ graphql: {
243
+ framework: 'graphql-yoga',
244
+
245
+ // Scaffold files
246
+ scaffold: {
247
+ graphqlConfig: false, // Don't generate graphql.config.ts
248
+ serverSchema: true, // Generate server/graphql/schema.ts
249
+ serverConfig: true, // Generate server/graphql/config.ts
250
+ serverContext: false, // Don't generate server/graphql/context.ts
251
+ },
252
+
253
+ // Client utilities (Nuxt only)
254
+ clientUtils: {
255
+ index: true, // Generate app/graphql/index.ts
256
+ ofetch: false, // Don't generate ofetch wrappers
257
+ },
258
+
259
+ // SDK files
260
+ sdk: {
261
+ main: true, // Generate default SDK
262
+ external: true, // Generate external service SDKs
263
+ },
264
+
265
+ // Type files
266
+ types: {
267
+ server: true, // Generate server types
268
+ client: true, // Generate client types
269
+ external: true, // Generate external service types
270
+ }
271
+ }
272
+ })
273
+ ```
274
+
275
+ ### Custom Paths
276
+
277
+ Customize where files are generated:
278
+
279
+ ```ts
280
+ export default defineNitroConfig({
281
+ graphql: {
282
+ framework: 'graphql-yoga',
283
+
284
+ // Method 1: Global paths (affects all files)
285
+ paths: {
286
+ serverGraphql: 'src/server/graphql',
287
+ clientGraphql: 'src/client/graphql',
288
+ buildDir: '.build',
289
+ typesDir: '.build/types',
290
+ },
291
+
292
+ // Method 2: Specific file paths
293
+ scaffold: {
294
+ serverSchema: 'lib/graphql/schema.ts',
295
+ serverConfig: 'lib/graphql/config.ts',
296
+ },
297
+
298
+ sdk: {
299
+ main: 'app/graphql/organization/sdk.ts',
300
+ external: 'app/graphql/{serviceName}/client-sdk.ts',
301
+ },
302
+
303
+ types: {
304
+ server: 'types/graphql-server.d.ts',
305
+ client: 'types/graphql-client.d.ts',
306
+ }
307
+ }
308
+ })
309
+ ```
310
+
311
+ ### Path Placeholders
312
+
313
+ Use placeholders in custom paths:
314
+
315
+ | Placeholder | Description | Example |
316
+ |------------|-------------|---------|
317
+ | `{serviceName}` | External service name | `github`, `stripe` |
318
+ | `{buildDir}` | Build directory | `.nitro` or `.nuxt` |
319
+ | `{rootDir}` | Root directory | `/Users/you/project` |
320
+ | `{framework}` | Framework name | `nuxt` or `nitro` |
321
+ | `{typesDir}` | Types directory | `.nitro/types` |
322
+ | `{serverGraphql}` | Server GraphQL dir | `server/graphql` |
323
+ | `{clientGraphql}` | Client GraphQL dir | `app/graphql` |
324
+
325
+ Example:
326
+ ```ts
327
+ sdk: {
328
+ external: '{clientGraphql}/{serviceName}/sdk.ts'
329
+ }
330
+ // → app/graphql/github/sdk.ts
331
+ // → app/graphql/stripe/sdk.ts
332
+ ```
333
+
334
+ ### Service-Specific Paths
335
+
336
+ Customize paths for individual external services:
337
+
338
+ ```ts
339
+ export default defineNuxtConfig({
340
+ nitro: {
341
+ graphql: {
342
+ framework: 'graphql-yoga',
343
+
344
+ // Global default for all external services
345
+ sdk: {
346
+ external: 'app/graphql/{serviceName}/sdk.ts'
347
+ },
348
+
349
+ externalServices: [
350
+ {
351
+ name: 'github',
352
+ endpoint: 'https://api.github.com/graphql',
353
+ schema: 'https://api.github.com/graphql',
354
+
355
+ // GitHub-specific paths (override global config)
356
+ paths: {
357
+ sdk: 'app/graphql/organization/github-sdk.ts',
358
+ types: 'types/github.d.ts',
359
+ ofetch: 'app/graphql/organization/github-client.ts'
360
+ }
361
+ },
362
+ {
363
+ name: 'stripe',
364
+ endpoint: 'https://api.stripe.com/graphql',
365
+ schema: 'https://api.stripe.com/graphql',
366
+
367
+ // Stripe-specific paths
368
+ paths: {
369
+ sdk: 'app/graphql/payments/stripe-sdk.ts',
370
+ types: 'types/payments/stripe.d.ts',
371
+ // ofetch uses global config
372
+ }
373
+ },
374
+ {
375
+ name: 'shopify',
376
+ endpoint: 'https://api.shopify.com/graphql',
377
+ // No paths → uses global config
378
+ // → app/graphql/shopify/sdk.ts
379
+ }
380
+ ]
381
+ }
382
+ }
383
+ })
384
+ ```
385
+
386
+ ### Path Resolution Priority
387
+
388
+ When resolving file paths, the system follows this priority order:
389
+
390
+ 1. **Service-specific path** (for external services): `service.paths.sdk`
391
+ 2. **Category config**: `sdk.external` or `sdk.main`
392
+ 3. **Global paths**: `paths.clientGraphql`
393
+ 4. **Framework defaults**: Nuxt vs Nitro defaults
394
+
395
+ Example:
396
+ ```ts
397
+ // Given this config:
398
+ {
399
+ paths: { clientGraphql: 'custom/graphql' },
400
+ sdk: { external: '{clientGraphql}/{serviceName}/sdk.ts' },
401
+ externalServices: [
402
+ {
403
+ name: 'github',
404
+ paths: { sdk: 'app/org/github-sdk.ts' } // ← Wins (priority 1)
405
+ },
406
+ {
407
+ name: 'stripe',
408
+ // Uses sdk.external (priority 2)
409
+ // → custom/graphql/stripe/sdk.ts
410
+ }
411
+ ]
412
+ }
413
+ ```
414
+
415
+ ### Use Cases
416
+
417
+ **Monorepo structure:**
418
+ ```ts
419
+ paths: {
420
+ serverGraphql: 'packages/api/src/graphql',
421
+ clientGraphql: 'packages/web/src/graphql',
422
+ typesDir: 'packages/types/src/generated',
423
+ }
424
+ ```
425
+
426
+ **Multiple external service organizations:**
427
+ ```ts
428
+ externalServices: [
429
+ {
430
+ name: 'github',
431
+ paths: { sdk: 'app/graphql/vcs/github-sdk.ts' }
432
+ },
433
+ {
434
+ name: 'gitlab',
435
+ paths: { sdk: 'app/graphql/vcs/gitlab-sdk.ts' }
436
+ },
437
+ {
438
+ name: 'stripe',
439
+ paths: { sdk: 'app/graphql/billing/stripe-sdk.ts' }
440
+ }
441
+ ]
442
+ ```
443
+
444
+ **Library development (no scaffolding):**
445
+ ```ts
446
+ {
447
+ scaffold: false,
448
+ clientUtils: false,
449
+ sdk: { enabled: true }, // Only generate SDKs
450
+ types: { enabled: true }, // Only generate types
451
+ }
452
+ ```
453
+
454
+ </details>
455
+
213
456
  <details>
214
457
  <summary><strong>🎭 Custom Directives</strong></summary>
215
458
 
@@ -975,4 +1218,6 @@ pnpm lint
975
1218
  [bundle-src]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
976
1219
  [bundle-href]: https://deno.bundlejs.com/badge?q=nitro-graphql@0.0.4
977
1220
  [license-src]: https://img.shields.io/github/license/productdevbook/nitro-graphql.svg?style=flat&colorA=080f12&colorB=1fa669
978
- [license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
1221
+ [license-href]: https://github.com/productdevbook/nitro-graphql/blob/main/LICENSE
1222
+ [docs-src]: https://img.shields.io/badge/docs-read-blue?style=flat&colorA=080f12&colorB=1fa669
1223
+ [docs-href]: https://nitro-graphql.pages.dev
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { StandardSchemaV1 } from "./types/standard-schema.js";
2
- import { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions } from "./types/index.js";
2
+ import { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, ExternalServicePaths, FederationConfig, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, PathsConfig, ScaffoldConfig, SdkConfig, TypesConfig } from "./types/index.js";
3
3
  import * as nitropack0 from "nitropack";
4
4
 
5
5
  //#region src/index.d.ts
6
6
  declare const _default: nitropack0.NitroModule;
7
7
  //#endregion
8
- export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, StandardSchemaV1, _default as default };
8
+ 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,8 +1,10 @@
1
1
  import { generateDirectiveSchemas } from "./utils/directive-parser.js";
2
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 { getDefaultPaths, getScaffoldConfig, getTypesConfig, resolveFilePath, shouldGenerateScaffold } from "./utils/path-resolver.js";
3
5
  import { clientTypeGeneration, serverTypeGeneration } from "./utils/type-generation.js";
4
6
  import { rollupConfig } from "./rollup.js";
5
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
7
+ import { existsSync, mkdirSync } from "node:fs";
6
8
  import { fileURLToPath } from "node:url";
7
9
  import { watch } from "chokidar";
8
10
  import consola from "consola";
@@ -97,7 +99,6 @@ var src_default = defineNitroModule({
97
99
  watcher.close();
98
100
  });
99
101
  const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
100
- const typesDir = resolve(nitro.options.buildDir, "types");
101
102
  nitro.scanSchemas = await scanSchemas(nitro);
102
103
  nitro.scanDocuments = await scanDocs(nitro);
103
104
  nitro.scanResolvers = await scanResolvers(nitro);
@@ -224,43 +225,68 @@ var src_default = defineNitroModule({
224
225
  types.tsConfig ||= {};
225
226
  types.tsConfig.compilerOptions ??= {};
226
227
  types.tsConfig.compilerOptions.paths ??= {};
227
- types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-server.d.ts"))];
228
- types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, join(typesDir, "nitro-graphql-client.d.ts"))];
228
+ const placeholders = getDefaultPaths(nitro);
229
+ const typesConfig = getTypesConfig(nitro);
230
+ const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
231
+ if (serverTypesPath) types.tsConfig.compilerOptions.paths["#graphql/server"] = [relativeWithDot(tsconfigDir, serverTypesPath)];
232
+ const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
233
+ if (clientTypesPath) types.tsConfig.compilerOptions.paths["#graphql/client"] = [relativeWithDot(tsconfigDir, clientTypesPath)];
229
234
  types.tsConfig.compilerOptions.paths["#graphql/schema"] = [relativeWithDot(tsconfigDir, join(nitro.graphql.serverDir, "schema.ts"))];
230
- 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`))];
235
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
236
+ const servicePlaceholders = {
237
+ ...placeholders,
238
+ serviceName: service.name
239
+ };
240
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
241
+ if (externalTypesPath) types.tsConfig.compilerOptions.paths[`#graphql/client/${service.name}`] = [relativeWithDot(tsconfigDir, externalTypesPath)];
242
+ }
231
243
  types.tsConfig.include = types.tsConfig.include || [];
232
- 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")));
233
- 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`)));
244
+ if (serverTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, serverTypesPath));
245
+ if (clientTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, clientTypesPath));
246
+ types.tsConfig.include.push(relativeWithDot(tsconfigDir, join(placeholders.typesDir, "graphql.d.ts")));
247
+ if (nitro.options.graphql?.externalServices?.length) for (const service of nitro.options.graphql.externalServices) {
248
+ const servicePlaceholders = {
249
+ ...placeholders,
250
+ serviceName: service.name
251
+ };
252
+ const externalTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", servicePlaceholders);
253
+ if (externalTypesPath) types.tsConfig.include.push(relativeWithDot(tsconfigDir, externalTypesPath));
254
+ }
234
255
  });
235
256
  if (nitro.options.framework?.name === "nuxt" && nitro.options.graphql?.externalServices?.length) nitro.hooks.hook("build:before", () => {
236
257
  const nuxtOptions = nitro._nuxt?.options;
237
258
  if (nuxtOptions) nuxtOptions.nitroGraphqlExternalServices = nitro.options.graphql?.externalServices || [];
238
259
  });
239
- if (!existsSync(join(nitro.options.rootDir, "graphql.config.ts"))) {
240
- const schemaPath = relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"));
241
- const documentsPath = relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"));
242
- writeFileSync(join(nitro.options.rootDir, "graphql.config.ts"), `
260
+ if (shouldGenerateScaffold(nitro)) {
261
+ const placeholders = getDefaultPaths(nitro);
262
+ const scaffoldConfig = getScaffoldConfig(nitro);
263
+ const graphqlConfigPath = resolveFilePath(scaffoldConfig.graphqlConfig, scaffoldConfig.enabled, true, "graphql.config.ts", placeholders);
264
+ if (graphqlConfigPath) writeFileIfNotExists(graphqlConfigPath, `
243
265
  import type { IGraphQLConfig } from 'graphql-config'
244
266
 
245
267
  export default <IGraphQLConfig> {
246
268
  projects: {
247
269
  default: {
248
270
  schema: [
249
- '${schemaPath}',
271
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.buildDir, "schema.graphql"))}',
250
272
  ],
251
273
  documents: [
252
- '${documentsPath}',
274
+ '${relativeWithDot(nitro.options.rootDir, resolve(nitro.graphql.clientDir, "**/*.{graphql,js,ts,jsx,tsx}"))}',
253
275
  ],
254
276
  },
255
277
  },
256
- }`, "utf-8");
257
- }
258
- if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
259
- if (!existsSync(join(nitro.graphql.serverDir, "schema.ts"))) writeFileSync(join(nitro.graphql.serverDir, "schema.ts"), `export default defineSchema({
278
+ }`, "graphql.config.ts");
279
+ const serverSchemaPath = resolveFilePath(scaffoldConfig.serverSchema, scaffoldConfig.enabled, true, "{serverGraphql}/schema.ts", placeholders);
280
+ const serverConfigPath = resolveFilePath(scaffoldConfig.serverConfig, scaffoldConfig.enabled, true, "{serverGraphql}/config.ts", placeholders);
281
+ const serverContextPath = resolveFilePath(scaffoldConfig.serverContext, scaffoldConfig.enabled, true, "{serverGraphql}/context.ts", placeholders);
282
+ if (serverSchemaPath || serverConfigPath || serverContextPath) {
283
+ if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
284
+ }
285
+ if (serverSchemaPath) writeFileIfNotExists(serverSchemaPath, `export default defineSchema({
260
286
 
261
287
  })
262
- `, "utf-8");
263
- if (!existsSync(join(nitro.graphql.serverDir, "config.ts"))) writeFileSync(join(nitro.graphql.serverDir, "config.ts"), `// Example GraphQL config file please change it to your needs
288
+ `, "server schema.ts");
289
+ if (serverConfigPath) writeFileIfNotExists(serverConfigPath, `// Example GraphQL config file please change it to your needs
264
290
  // import * as tables from '../drizzle/schema/index'
265
291
  // import { useDatabase } from '../utils/useDb'
266
292
 
@@ -275,8 +301,8 @@ export default defineGraphQLConfig({
275
301
  // }
276
302
  // },
277
303
  })
278
- `, "utf-8");
279
- if (!existsSync(join(nitro.graphql.serverDir, "context.ts"))) writeFileSync(join(nitro.graphql.serverDir, "context.ts"), `// Example context definition - please change it to your needs
304
+ `, "server config.ts");
305
+ if (serverContextPath) writeFileIfNotExists(serverContextPath, `// Example context definition - please change it to your needs
280
306
  // import type { Database } from '../utils/useDb'
281
307
 
282
308
  declare module 'h3' {
@@ -291,11 +317,12 @@ declare module 'h3' {
291
317
  // }
292
318
  // }
293
319
  }
294
- }`, "utf-8");
295
- if (existsSync(join(nitro.graphql.serverDir, "context.d.ts"))) {
296
- consola.warn("nitro-graphql: Found context.d.ts file. Please rename it to context.ts for the new structure.");
297
- consola.info("The context file should now be context.ts instead of context.d.ts");
298
- }
320
+ }`, "server context.ts");
321
+ if (existsSync(join(nitro.graphql.serverDir, "context.d.ts"))) {
322
+ consola.warn("nitro-graphql: Found context.d.ts file. Please rename it to context.ts for the new structure.");
323
+ consola.info("The context file should now be context.ts instead of context.d.ts");
324
+ }
325
+ } else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
299
326
  }
300
327
  });
301
328
 
@@ -1,6 +1,6 @@
1
- import * as h31 from "h3";
1
+ import * as h33 from "h3";
2
2
 
3
3
  //#region src/routes/apollo-server.d.ts
4
- declare const _default: h31.EventHandler<h31.EventHandlerRequest, Promise<any>>;
4
+ declare const _default: h33.EventHandler<h33.EventHandlerRequest, Promise<any>>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -1,4 +1,4 @@
1
- import * as h33 from "h3";
1
+ import * as h30 from "h3";
2
2
 
3
3
  //#region src/routes/debug.d.ts
4
4
 
@@ -10,7 +10,7 @@ import * as h33 from "h3";
10
10
  * - /_nitro/graphql/debug - HTML dashboard
11
11
  * - /_nitro/graphql/debug?format=json - JSON API
12
12
  */
13
- declare const _default: h33.EventHandler<h33.EventHandlerRequest, Promise<string | {
13
+ declare const _default: h30.EventHandler<h30.EventHandlerRequest, Promise<string | {
14
14
  timestamp: string;
15
15
  environment: {
16
16
  dev: any;
@@ -1,6 +1,6 @@
1
- import * as h30 from "h3";
1
+ import * as h35 from "h3";
2
2
 
3
3
  //#region src/routes/graphql-yoga.d.ts
4
- declare const _default: h30.EventHandler<h30.EventHandlerRequest, Promise<Response>>;
4
+ declare const _default: h35.EventHandler<h35.EventHandlerRequest, Promise<Response>>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -1,7 +1,7 @@
1
- import * as h35 from "h3";
1
+ import * as h31 from "h3";
2
2
 
3
3
  //#region src/routes/health.d.ts
4
- declare const _default: h35.EventHandler<h35.EventHandlerRequest, Promise<{
4
+ declare const _default: h31.EventHandler<h31.EventHandlerRequest, Promise<{
5
5
  status: string;
6
6
  message: string;
7
7
  timestamp: string;
@@ -57,6 +57,18 @@ declare module 'nitropack' {
57
57
  graphql?: NitroGraphQLOptions;
58
58
  }
59
59
  }
60
+ /**
61
+ * Service-specific path overrides for external GraphQL services
62
+ * These paths override global config for this specific service
63
+ */
64
+ interface ExternalServicePaths {
65
+ /** SDK file path (overrides global sdk.external config) */
66
+ sdk?: FileGenerationConfig;
67
+ /** Type definitions file path (overrides global types.external config) */
68
+ types?: FileGenerationConfig;
69
+ /** ofetch client wrapper path (overrides global clientUtils.ofetch config) */
70
+ ofetch?: FileGenerationConfig;
71
+ }
60
72
  interface ExternalGraphQLService {
61
73
  /** Unique name for this service (used for file naming and type generation) */
62
74
  name: string;
@@ -83,6 +95,12 @@ interface ExternalGraphQLService {
83
95
  client?: CodegenClientConfig;
84
96
  clientSDK?: GenericSdkConfig;
85
97
  };
98
+ /**
99
+ * Optional: Service-specific path overrides
100
+ * These paths take precedence over global config (sdk, types, clientUtils)
101
+ * Supports placeholders: {serviceName}, {buildDir}, {rootDir}, {framework}, {typesDir}, {clientGraphql}
102
+ */
103
+ paths?: ExternalServicePaths;
86
104
  }
87
105
  interface FederationConfig {
88
106
  /** Enable Apollo Federation subgraph support */
@@ -94,6 +112,81 @@ interface FederationConfig {
94
112
  /** Service URL for federation gateway */
95
113
  serviceUrl?: string;
96
114
  }
115
+ /**
116
+ * File generation control:
117
+ * - false: Do not generate this file
118
+ * - true: Generate at default location
119
+ * - string: Generate at custom path (supports placeholders: {serviceName}, {buildDir}, {rootDir}, {framework})
120
+ */
121
+ type FileGenerationConfig = boolean | string;
122
+ /**
123
+ * Scaffold files configuration
124
+ * Control auto-generation of scaffold/boilerplate files
125
+ */
126
+ interface ScaffoldConfig {
127
+ /** Enable/disable all scaffold files */
128
+ enabled?: boolean;
129
+ /** graphql.config.ts - GraphQL Config file for IDE tooling */
130
+ graphqlConfig?: FileGenerationConfig;
131
+ /** server/graphql/schema.ts - Schema definition file */
132
+ serverSchema?: FileGenerationConfig;
133
+ /** server/graphql/config.ts - GraphQL server configuration */
134
+ serverConfig?: FileGenerationConfig;
135
+ /** server/graphql/context.ts - H3 context augmentation */
136
+ serverContext?: FileGenerationConfig;
137
+ }
138
+ /**
139
+ * Client utilities configuration
140
+ * Control auto-generation of client-side utility files (Nuxt only)
141
+ */
142
+ interface ClientUtilsConfig {
143
+ /** Enable/disable all client utilities */
144
+ enabled?: boolean;
145
+ /** app/graphql/index.ts - Main exports file */
146
+ index?: FileGenerationConfig;
147
+ /** app/graphql/{serviceName}/ofetch.ts - ofetch client wrapper */
148
+ ofetch?: FileGenerationConfig;
149
+ }
150
+ /**
151
+ * SDK files configuration
152
+ * Control auto-generation of GraphQL SDK files
153
+ */
154
+ interface SdkConfig {
155
+ /** Enable/disable all SDK files */
156
+ enabled?: boolean;
157
+ /** app/graphql/default/sdk.ts - Main service SDK */
158
+ main?: FileGenerationConfig;
159
+ /** app/graphql/{serviceName}/sdk.ts - External service SDKs */
160
+ external?: FileGenerationConfig;
161
+ }
162
+ /**
163
+ * Type files configuration
164
+ * Control auto-generation of TypeScript type definition files
165
+ */
166
+ interface TypesConfig {
167
+ /** Enable/disable all type files */
168
+ enabled?: boolean;
169
+ /** .nitro/types/nitro-graphql-server.d.ts - Server-side types */
170
+ server?: FileGenerationConfig;
171
+ /** .nitro/types/nitro-graphql-client.d.ts - Client-side types */
172
+ client?: FileGenerationConfig;
173
+ /** .nitro/types/nitro-graphql-client-{serviceName}.d.ts - External service types */
174
+ external?: FileGenerationConfig;
175
+ }
176
+ /**
177
+ * Global path overrides
178
+ * Set base directories for file generation
179
+ */
180
+ interface PathsConfig {
181
+ /** Server GraphQL directory (default: 'server/graphql') */
182
+ serverGraphql?: string;
183
+ /** Client GraphQL directory (default: 'app/graphql' for Nuxt, 'graphql' for Nitro) */
184
+ clientGraphql?: string;
185
+ /** Build directory (default: '.nitro' or '.nuxt') */
186
+ buildDir?: string;
187
+ /** Types directory (default: '{buildDir}/types') */
188
+ typesDir?: string;
189
+ }
97
190
  interface NitroGraphQLOptions {
98
191
  framework: 'graphql-yoga' | 'apollo-server';
99
192
  endpoint?: {
@@ -123,6 +216,31 @@ interface NitroGraphQLOptions {
123
216
  layerDirectories?: string[];
124
217
  layerServerDirs?: string[];
125
218
  layerAppDirs?: string[];
219
+ /**
220
+ * Scaffold files configuration
221
+ * Set to false to disable all scaffold file generation (library mode)
222
+ */
223
+ scaffold?: false | ScaffoldConfig;
224
+ /**
225
+ * Client utilities configuration
226
+ * Set to false to disable all client utility generation
227
+ */
228
+ clientUtils?: false | ClientUtilsConfig;
229
+ /**
230
+ * SDK files configuration
231
+ * Set to false to disable all SDK generation
232
+ */
233
+ sdk?: false | SdkConfig;
234
+ /**
235
+ * Type files configuration
236
+ * Set to false to disable all type generation
237
+ */
238
+ types?: false | TypesConfig;
239
+ /**
240
+ * Global path overrides
241
+ * Customize base directories for file generation
242
+ */
243
+ paths?: PathsConfig;
126
244
  }
127
245
  //#endregion
128
- export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, FederationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions };
246
+ export { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, ExternalServicePaths, FederationConfig, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, PathsConfig, ScaffoldConfig, SdkConfig, TypesConfig };
@@ -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
@@ -0,0 +1,37 @@
1
+ import { Nitro } from "nitropack/types";
2
+
3
+ //#region src/utils/file-generator.d.ts
4
+
5
+ /**
6
+ * Safely write a file to disk, creating parent directories if needed
7
+ */
8
+ declare function writeFile(filePath: string, content: string, description?: string): void;
9
+ /**
10
+ * Write a file only if it doesn't already exist
11
+ * Returns true if file was created, false if it already existed
12
+ */
13
+ declare function writeFileIfNotExists(filePath: string, content: string, description?: string): boolean;
14
+ /**
15
+ * Write a file and always overwrite (used for generated files like SDK)
16
+ * This is for files that are auto-generated and should be updated on every build
17
+ */
18
+ declare function writeGeneratedFile(filePath: string, content: string, description?: string): void;
19
+ /**
20
+ * Check if a path is configured and should be generated
21
+ * Returns the resolved path if should generate, null otherwise
22
+ */
23
+ declare function getGenerationPath(resolvedPath: string | null, description?: string): string | null;
24
+ /**
25
+ * Log skipped file generation (helpful for debugging library mode)
26
+ */
27
+ declare function logSkipped(fileName: string, reason?: string): void;
28
+ /**
29
+ * Log generated file path
30
+ */
31
+ declare function logGenerated(fileName: string, path: string): void;
32
+ /**
33
+ * Validate that a Nitro instance has the required GraphQL configuration
34
+ */
35
+ declare function validateGraphQLConfig(nitro: Nitro): boolean;
36
+ //#endregion
37
+ export { getGenerationPath, logGenerated, logSkipped, validateGraphQLConfig, writeFile, writeFileIfNotExists, writeGeneratedFile };
@@ -0,0 +1,72 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import consola from "consola";
3
+ import { dirname } from "pathe";
4
+
5
+ //#region src/utils/file-generator.ts
6
+ /**
7
+ * Safely write a file to disk, creating parent directories if needed
8
+ */
9
+ function writeFile(filePath, content, description) {
10
+ try {
11
+ const dir = dirname(filePath);
12
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
13
+ writeFileSync(filePath, content, "utf-8");
14
+ if (description) consola.success(`[nitro-graphql] Generated: ${description}`);
15
+ } catch (error) {
16
+ consola.error(`[nitro-graphql] Failed to write file: ${filePath}`, error);
17
+ throw error;
18
+ }
19
+ }
20
+ /**
21
+ * Write a file only if it doesn't already exist
22
+ * Returns true if file was created, false if it already existed
23
+ */
24
+ function writeFileIfNotExists(filePath, content, description) {
25
+ if (existsSync(filePath)) return false;
26
+ writeFile(filePath, content, description);
27
+ return true;
28
+ }
29
+ /**
30
+ * Write a file and always overwrite (used for generated files like SDK)
31
+ * This is for files that are auto-generated and should be updated on every build
32
+ */
33
+ function writeGeneratedFile(filePath, content, description) {
34
+ writeFile(filePath, content, description);
35
+ }
36
+ /**
37
+ * Check if a path is configured and should be generated
38
+ * Returns the resolved path if should generate, null otherwise
39
+ */
40
+ function getGenerationPath(resolvedPath, description) {
41
+ if (!resolvedPath) {
42
+ if (description) consola.debug(`[nitro-graphql] Skipping generation: ${description} (disabled in config)`);
43
+ return null;
44
+ }
45
+ return resolvedPath;
46
+ }
47
+ /**
48
+ * Log skipped file generation (helpful for debugging library mode)
49
+ */
50
+ function logSkipped(fileName, reason) {
51
+ const message = reason ? `Skipped ${fileName}: ${reason}` : `Skipped ${fileName}`;
52
+ consola.debug(`[nitro-graphql] ${message}`);
53
+ }
54
+ /**
55
+ * Log generated file path
56
+ */
57
+ function logGenerated(fileName, path) {
58
+ consola.info(`[nitro-graphql] Generated ${fileName} at: ${path}`);
59
+ }
60
+ /**
61
+ * Validate that a Nitro instance has the required GraphQL configuration
62
+ */
63
+ function validateGraphQLConfig(nitro) {
64
+ if (!nitro.options.graphql?.framework) {
65
+ consola.warn("[nitro-graphql] No GraphQL framework specified. Some features may not work correctly.");
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+
71
+ //#endregion
72
+ export { getGenerationPath, logGenerated, logSkipped, validateGraphQLConfig, writeFile, writeFileIfNotExists, writeGeneratedFile };
@@ -0,0 +1,70 @@
1
+ import { ClientUtilsConfig, FileGenerationConfig, ScaffoldConfig, SdkConfig, TypesConfig } from "../types/index.js";
2
+ import { Nitro } from "nitropack/types";
3
+
4
+ //#region src/utils/path-resolver.d.ts
5
+
6
+ /**
7
+ * Placeholder values for path resolution
8
+ */
9
+ interface PathPlaceholders {
10
+ serviceName?: string;
11
+ buildDir: string;
12
+ rootDir: string;
13
+ framework: 'nuxt' | 'nitro';
14
+ typesDir: string;
15
+ serverGraphql: string;
16
+ clientGraphql: string;
17
+ }
18
+ /**
19
+ * Replace placeholders in a path string
20
+ * Supports: {serviceName}, {buildDir}, {rootDir}, {framework}, {typesDir}, {serverGraphql}, {clientGraphql}
21
+ */
22
+ declare function replacePlaceholders(path: string, placeholders: PathPlaceholders): string;
23
+ /**
24
+ * Get default paths based on framework and user configuration
25
+ */
26
+ declare function getDefaultPaths(nitro: Nitro): Required<PathPlaceholders>;
27
+ /**
28
+ * Check if a file should be generated based on config
29
+ * Returns: true if should generate, false if should skip
30
+ */
31
+ declare function shouldGenerateFile(config: FileGenerationConfig | undefined, categoryEnabled: boolean | undefined, topLevelEnabled: boolean): boolean;
32
+ /**
33
+ * Resolve the file path based on configuration
34
+ * Returns: resolved absolute path or null if file should not be generated
35
+ */
36
+ declare function resolveFilePath(config: FileGenerationConfig | undefined, categoryEnabled: boolean | undefined, topLevelEnabled: boolean, defaultPath: string, placeholders: PathPlaceholders): string | null;
37
+ /**
38
+ * Check if scaffold files should be generated (category-level check)
39
+ */
40
+ declare function shouldGenerateScaffold(nitro: Nitro): boolean;
41
+ /**
42
+ * Get scaffold configuration (handles false case)
43
+ */
44
+ declare function getScaffoldConfig(nitro: Nitro): ScaffoldConfig;
45
+ /**
46
+ * Check if client utilities should be generated (category-level check)
47
+ */
48
+ declare function shouldGenerateClientUtils(nitro: Nitro): boolean;
49
+ /**
50
+ * Get client utilities configuration (handles false case)
51
+ */
52
+ declare function getClientUtilsConfig(nitro: Nitro): ClientUtilsConfig;
53
+ /**
54
+ * Check if SDK files should be generated (category-level check)
55
+ */
56
+ declare function shouldGenerateSDK(nitro: Nitro): boolean;
57
+ /**
58
+ * Get SDK configuration (handles false case)
59
+ */
60
+ declare function getSdkConfig(nitro: Nitro): SdkConfig;
61
+ /**
62
+ * Check if type files should be generated (category-level check)
63
+ */
64
+ declare function shouldGenerateTypes(nitro: Nitro): boolean;
65
+ /**
66
+ * Get types configuration (handles false case)
67
+ */
68
+ declare function getTypesConfig(nitro: Nitro): TypesConfig;
69
+ //#endregion
70
+ export { PathPlaceholders, getClientUtilsConfig, getDefaultPaths, getScaffoldConfig, getSdkConfig, getTypesConfig, replacePlaceholders, resolveFilePath, shouldGenerateClientUtils, shouldGenerateFile, shouldGenerateSDK, shouldGenerateScaffold, shouldGenerateTypes };
@@ -0,0 +1,127 @@
1
+ import { resolve } from "pathe";
2
+
3
+ //#region src/utils/path-resolver.ts
4
+ /**
5
+ * Replace placeholders in a path string
6
+ * Supports: {serviceName}, {buildDir}, {rootDir}, {framework}, {typesDir}, {serverGraphql}, {clientGraphql}
7
+ */
8
+ function replacePlaceholders(path, placeholders) {
9
+ return path.replace(/\{serviceName\}/g, placeholders.serviceName || "default").replace(/\{buildDir\}/g, placeholders.buildDir).replace(/\{rootDir\}/g, placeholders.rootDir).replace(/\{framework\}/g, placeholders.framework).replace(/\{typesDir\}/g, placeholders.typesDir).replace(/\{serverGraphql\}/g, placeholders.serverGraphql).replace(/\{clientGraphql\}/g, placeholders.clientGraphql);
10
+ }
11
+ /**
12
+ * Get default paths based on framework and user configuration
13
+ */
14
+ function getDefaultPaths(nitro) {
15
+ const isNuxt = nitro.options.framework?.name === "nuxt";
16
+ const rootDir = nitro.options.rootDir;
17
+ const buildDir = nitro.options.buildDir;
18
+ const pathsConfig = nitro.options.graphql?.paths || {};
19
+ const defaultServerGraphql = pathsConfig.serverGraphql || resolve(rootDir, "server", "graphql");
20
+ const defaultClientGraphql = pathsConfig.clientGraphql || resolve(rootDir, isNuxt ? "app/graphql" : "graphql");
21
+ const defaultBuildDir = pathsConfig.buildDir || buildDir;
22
+ const defaultTypesDir = pathsConfig.typesDir || resolve(defaultBuildDir, "types");
23
+ return {
24
+ serviceName: "default",
25
+ buildDir: defaultBuildDir,
26
+ rootDir,
27
+ framework: isNuxt ? "nuxt" : "nitro",
28
+ typesDir: defaultTypesDir,
29
+ serverGraphql: defaultServerGraphql,
30
+ clientGraphql: defaultClientGraphql
31
+ };
32
+ }
33
+ /**
34
+ * Check if a file should be generated based on config
35
+ * Returns: true if should generate, false if should skip
36
+ */
37
+ function shouldGenerateFile(config, categoryEnabled, topLevelEnabled) {
38
+ if (config === false) return false;
39
+ if (config === true || typeof config === "string") return true;
40
+ if (categoryEnabled === false) return false;
41
+ if (categoryEnabled === true) return true;
42
+ return topLevelEnabled;
43
+ }
44
+ /**
45
+ * Resolve the file path based on configuration
46
+ * Returns: resolved absolute path or null if file should not be generated
47
+ */
48
+ function resolveFilePath(config, categoryEnabled, topLevelEnabled, defaultPath, placeholders) {
49
+ if (!shouldGenerateFile(config, categoryEnabled, topLevelEnabled)) return null;
50
+ if (typeof config === "string") {
51
+ const customPath = replacePlaceholders(config, placeholders);
52
+ return resolve(placeholders.rootDir, customPath);
53
+ }
54
+ const resolvedDefault = replacePlaceholders(defaultPath, placeholders);
55
+ return resolve(placeholders.rootDir, resolvedDefault);
56
+ }
57
+ /**
58
+ * Check if scaffold files should be generated (category-level check)
59
+ */
60
+ function shouldGenerateScaffold(nitro) {
61
+ const scaffoldConfig = nitro.options.graphql?.scaffold;
62
+ if (scaffoldConfig === false) return false;
63
+ if (scaffoldConfig && scaffoldConfig.enabled === false) return false;
64
+ return true;
65
+ }
66
+ /**
67
+ * Get scaffold configuration (handles false case)
68
+ */
69
+ function getScaffoldConfig(nitro) {
70
+ const scaffoldConfig = nitro.options.graphql?.scaffold;
71
+ if (scaffoldConfig === false) return { enabled: false };
72
+ return scaffoldConfig || {};
73
+ }
74
+ /**
75
+ * Check if client utilities should be generated (category-level check)
76
+ */
77
+ function shouldGenerateClientUtils(nitro) {
78
+ const clientUtilsConfig = nitro.options.graphql?.clientUtils;
79
+ if (clientUtilsConfig === false) return false;
80
+ if (clientUtilsConfig && clientUtilsConfig.enabled === false) return false;
81
+ return nitro.options.framework?.name === "nuxt";
82
+ }
83
+ /**
84
+ * Get client utilities configuration (handles false case)
85
+ */
86
+ function getClientUtilsConfig(nitro) {
87
+ const clientUtilsConfig = nitro.options.graphql?.clientUtils;
88
+ if (clientUtilsConfig === false) return { enabled: false };
89
+ return clientUtilsConfig || {};
90
+ }
91
+ /**
92
+ * Check if SDK files should be generated (category-level check)
93
+ */
94
+ function shouldGenerateSDK(nitro) {
95
+ const sdkConfig = nitro.options.graphql?.sdk;
96
+ if (sdkConfig === false) return false;
97
+ if (sdkConfig && sdkConfig.enabled === false) return false;
98
+ return true;
99
+ }
100
+ /**
101
+ * Get SDK configuration (handles false case)
102
+ */
103
+ function getSdkConfig(nitro) {
104
+ const sdkConfig = nitro.options.graphql?.sdk;
105
+ if (sdkConfig === false) return { enabled: false };
106
+ return sdkConfig || {};
107
+ }
108
+ /**
109
+ * Check if type files should be generated (category-level check)
110
+ */
111
+ function shouldGenerateTypes(nitro) {
112
+ const typesConfig = nitro.options.graphql?.types;
113
+ if (typesConfig === false) return false;
114
+ if (typesConfig && typesConfig.enabled === false) return false;
115
+ return true;
116
+ }
117
+ /**
118
+ * Get types configuration (handles false case)
119
+ */
120
+ function getTypesConfig(nitro) {
121
+ const typesConfig = nitro.options.graphql?.types;
122
+ if (typesConfig === false) return { enabled: false };
123
+ return typesConfig || {};
124
+ }
125
+
126
+ //#endregion
127
+ export { getClientUtilsConfig, getDefaultPaths, getScaffoldConfig, getSdkConfig, getTypesConfig, replacePlaceholders, resolveFilePath, shouldGenerateClientUtils, shouldGenerateFile, shouldGenerateSDK, shouldGenerateScaffold, shouldGenerateTypes };
@@ -1,4 +1,6 @@
1
1
  import { downloadAndSaveSchema, generateClientTypes, generateExternalClientTypes, loadExternalSchema, loadGraphQLDocuments } from "./client-codegen.js";
2
+ import { writeFileIfNotExists } from "./file-generator.js";
3
+ import { getClientUtilsConfig, getDefaultPaths, getSdkConfig, getTypesConfig, resolveFilePath, shouldGenerateClientUtils, shouldGenerateTypes } from "./path-resolver.js";
2
4
  import { generateTypes } from "./server-codegen.js";
3
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
6
  import consola from "consola";
@@ -10,12 +12,16 @@ import { mergeTypeDefs } from "@graphql-tools/merge";
10
12
  import { printSchemaWithDirectives } from "@graphql-tools/utils";
11
13
 
12
14
  //#region src/utils/type-generation.ts
13
- function generateGraphQLIndexFile(clientDir, externalServices = []) {
14
- const indexPath = resolve(clientDir, "index.ts");
15
+ function generateGraphQLIndexFile(nitro, clientDir, externalServices = []) {
16
+ if (!shouldGenerateClientUtils(nitro)) return;
17
+ const placeholders = getDefaultPaths(nitro);
18
+ const clientUtilsConfig = getClientUtilsConfig(nitro);
19
+ const indexPath = resolveFilePath(clientUtilsConfig.index, clientUtilsConfig.enabled, true, "{clientGraphql}/index.ts", placeholders);
20
+ if (!indexPath) return;
15
21
  if (!existsSync(indexPath)) {
16
22
  let indexContent = `// This file is auto-generated once by nitro-graphql for quick start
17
23
  // You can modify this file according to your needs
18
- //
24
+ //
19
25
  // Export your main GraphQL service (auto-generated)
20
26
  export * from './default/ofetch'
21
27
 
@@ -24,14 +30,21 @@ export * from './default/ofetch'
24
30
  // export * from './yourServiceName/ofetch'
25
31
  `;
26
32
  for (const service of externalServices) indexContent += `export * from './${service.name}/ofetch'\n`;
27
- writeFileSync(indexPath, indexContent, "utf-8");
33
+ writeFileIfNotExists(indexPath, indexContent, "client index.ts");
28
34
  }
29
35
  }
30
- function generateNuxtOfetchClient(clientDir, serviceName = "default") {
31
- const serviceDir = resolve(clientDir, serviceName);
32
- const ofetchPath = resolve(serviceDir, "ofetch.ts");
36
+ function generateNuxtOfetchClient(nitro, clientDir, serviceName = "default") {
37
+ if (!shouldGenerateClientUtils(nitro)) return;
38
+ const placeholders = {
39
+ ...getDefaultPaths(nitro),
40
+ serviceName
41
+ };
42
+ const clientUtilsConfig = getClientUtilsConfig(nitro);
43
+ const ofetchPath = resolveFilePath(clientUtilsConfig.ofetch, clientUtilsConfig.enabled, true, "{clientGraphql}/{serviceName}/ofetch.ts", placeholders);
44
+ if (!ofetchPath) return;
45
+ const serviceDir = dirname(ofetchPath);
33
46
  if (!existsSync(serviceDir)) mkdirSync(serviceDir, { recursive: true });
34
- if (!existsSync(ofetchPath)) writeFileSync(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
47
+ if (!existsSync(ofetchPath)) writeFileIfNotExists(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
35
48
  // You can modify this file according to your needs
36
49
  import type { Requester } from './sdk'
37
50
  import { getSdk } from './sdk'
@@ -53,15 +66,23 @@ export function createGraphQLClient(endpoint: string): Requester {
53
66
  }
54
67
  }
55
68
 
56
- export const $sdk = getSdk(createGraphQLClient('/api/graphql'))`, "utf-8");
69
+ export const $sdk = getSdk(createGraphQLClient('/api/graphql'))`, `${serviceName} ofetch.ts`);
57
70
  }
58
- function generateExternalOfetchClient(clientDir, serviceName, endpoint) {
59
- const serviceDir = resolve(clientDir, serviceName);
60
- const ofetchPath = resolve(serviceDir, "ofetch.ts");
71
+ function generateExternalOfetchClient(nitro, service, endpoint) {
72
+ if (!shouldGenerateClientUtils(nitro)) return;
73
+ const serviceName = service.name;
74
+ const placeholders = {
75
+ ...getDefaultPaths(nitro),
76
+ serviceName
77
+ };
78
+ const clientUtilsConfig = getClientUtilsConfig(nitro);
79
+ const ofetchPath = resolveFilePath(service.paths?.ofetch ?? clientUtilsConfig.ofetch, clientUtilsConfig.enabled, true, "{clientGraphql}/{serviceName}/ofetch.ts", placeholders);
80
+ if (!ofetchPath) return;
81
+ const serviceDir = dirname(ofetchPath);
61
82
  if (!existsSync(serviceDir)) mkdirSync(serviceDir, { recursive: true });
62
83
  if (!existsSync(ofetchPath)) {
63
84
  const capitalizedServiceName = serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
64
- writeFileSync(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
85
+ writeFileIfNotExists(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
65
86
  // You can modify this file according to your needs
66
87
  import type { Sdk, Requester } from './sdk'
67
88
  import { getSdk } from './sdk'
@@ -83,7 +104,7 @@ export function create${capitalizedServiceName}GraphQLClient(endpoint: string =
83
104
  }
84
105
  }
85
106
 
86
- export const $${serviceName}Sdk: Sdk = getSdk(create${capitalizedServiceName}GraphQLClient())`, "utf-8");
107
+ export const $${serviceName}Sdk: Sdk = getSdk(create${capitalizedServiceName}GraphQLClient())`, `${serviceName} external ofetch.ts`);
87
108
  }
88
109
  }
89
110
  /**
@@ -178,6 +199,10 @@ function validateNoDuplicateTypes(schemas, schemaStrings) {
178
199
  }
179
200
  async function serverTypeGeneration(app) {
180
201
  try {
202
+ if (!shouldGenerateTypes(app)) {
203
+ consola.debug("[nitro-graphql] Server type generation is disabled");
204
+ return;
205
+ }
181
206
  const schemas = app.scanSchemas || [];
182
207
  if (!schemas.length) {
183
208
  consola.info("No GraphQL definitions found for server type generation.");
@@ -197,9 +222,14 @@ async function serverTypeGeneration(app) {
197
222
  const schemaPath = resolve(app.graphql.buildDir, "schema.graphql");
198
223
  mkdirSync(dirname(schemaPath), { recursive: true });
199
224
  writeFileSync(schemaPath, printSchema, "utf-8");
200
- const serverTypesPath = resolve(app.options.buildDir, "types", "nitro-graphql-server.d.ts");
201
- mkdirSync(dirname(serverTypesPath), { recursive: true });
202
- writeFileSync(serverTypesPath, data, "utf-8");
225
+ const placeholders = getDefaultPaths(app);
226
+ const typesConfig = getTypesConfig(app);
227
+ const serverTypesPath = resolveFilePath(typesConfig.server, typesConfig.enabled, true, "{typesDir}/nitro-graphql-server.d.ts", placeholders);
228
+ if (serverTypesPath) {
229
+ mkdirSync(dirname(serverTypesPath), { recursive: true });
230
+ writeFileSync(serverTypesPath, data, "utf-8");
231
+ consola.success(`[nitro-graphql] Generated server types at: ${serverTypesPath}`);
232
+ }
203
233
  } catch (error) {
204
234
  consola.error("Server schema generation error:", error);
205
235
  }
@@ -252,17 +282,25 @@ async function generateMainClientTypes(nitro) {
252
282
  const graphqlString = readFileSync(schemaFilePath, "utf-8");
253
283
  const types = await generateClientTypes(nitro.options.graphql?.federation?.enabled === true ? buildSubgraphSchema([{ typeDefs: parse(graphqlString) }]) : buildSchema(graphqlString), loadDocs, nitro.options.graphql?.codegen?.client ?? {}, nitro.options.graphql?.codegen?.clientSDK ?? {});
254
284
  if (types === false) return;
255
- const clientTypesPath = resolve(nitro.options.buildDir, "types", "nitro-graphql-client.d.ts");
256
- const defaultServiceDir = resolve(nitro.graphql.clientDir, "default");
257
- const sdkTypesPath = resolve(defaultServiceDir, "sdk.ts");
258
- mkdirSync(dirname(clientTypesPath), { recursive: true });
259
- writeFileSync(clientTypesPath, types.types, "utf-8");
260
- mkdirSync(defaultServiceDir, { recursive: true });
261
- writeFileSync(sdkTypesPath, types.sdk, "utf-8");
285
+ const placeholders = getDefaultPaths(nitro);
286
+ const typesConfig = getTypesConfig(nitro);
287
+ const sdkConfig = getSdkConfig(nitro);
288
+ const clientTypesPath = resolveFilePath(typesConfig.client, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client.d.ts", placeholders);
289
+ if (clientTypesPath) {
290
+ mkdirSync(dirname(clientTypesPath), { recursive: true });
291
+ writeFileSync(clientTypesPath, types.types, "utf-8");
292
+ consola.success(`[nitro-graphql] Generated client types at: ${clientTypesPath}`);
293
+ }
294
+ const sdkPath = resolveFilePath(sdkConfig.main, sdkConfig.enabled, true, "{clientGraphql}/default/sdk.ts", placeholders);
295
+ if (sdkPath) {
296
+ mkdirSync(dirname(sdkPath), { recursive: true });
297
+ writeFileSync(sdkPath, types.sdk, "utf-8");
298
+ consola.success(`[nitro-graphql] Generated SDK at: ${sdkPath}`);
299
+ }
262
300
  if (nitro.options.framework?.name === "nuxt") {
263
- generateNuxtOfetchClient(nitro.graphql.clientDir, "default");
301
+ generateNuxtOfetchClient(nitro, nitro.graphql.clientDir, "default");
264
302
  const externalServices = nitro.options.graphql?.externalServices || [];
265
- generateGraphQLIndexFile(nitro.graphql.clientDir, externalServices);
303
+ generateGraphQLIndexFile(nitro, nitro.graphql.clientDir, externalServices);
266
304
  }
267
305
  }
268
306
  async function generateExternalServicesTypes(nitro) {
@@ -292,14 +330,25 @@ async function generateExternalServicesTypes(nitro) {
292
330
  consola.warn(`[graphql:${service.name}] Type generation failed`);
293
331
  continue;
294
332
  }
295
- const serviceTypesPath = resolve(nitro.options.buildDir, "types", `nitro-graphql-client-${service.name}.d.ts`);
296
- const serviceDir = resolve(nitro.graphql.clientDir, service.name);
297
- const serviceSdkPath = resolve(serviceDir, "sdk.ts");
298
- mkdirSync(dirname(serviceTypesPath), { recursive: true });
299
- writeFileSync(serviceTypesPath, types.types, "utf-8");
300
- mkdirSync(serviceDir, { recursive: true });
301
- writeFileSync(serviceSdkPath, types.sdk, "utf-8");
302
- if (nitro.options.framework?.name === "nuxt") generateExternalOfetchClient(nitro.graphql.clientDir, service.name, service.endpoint);
333
+ const placeholders = {
334
+ ...getDefaultPaths(nitro),
335
+ serviceName: service.name
336
+ };
337
+ const typesConfig = getTypesConfig(nitro);
338
+ const sdkConfig = getSdkConfig(nitro);
339
+ const serviceTypesPath = resolveFilePath(service.paths?.types ?? typesConfig.external, typesConfig.enabled, true, "{typesDir}/nitro-graphql-client-{serviceName}.d.ts", placeholders);
340
+ if (serviceTypesPath) {
341
+ mkdirSync(dirname(serviceTypesPath), { recursive: true });
342
+ writeFileSync(serviceTypesPath, types.types, "utf-8");
343
+ consola.success(`[graphql:${service.name}] Generated types at: ${serviceTypesPath}`);
344
+ }
345
+ const serviceSdkPath = resolveFilePath(service.paths?.sdk ?? sdkConfig.external, sdkConfig.enabled, true, "{clientGraphql}/{serviceName}/sdk.ts", placeholders);
346
+ if (serviceSdkPath) {
347
+ mkdirSync(dirname(serviceSdkPath), { recursive: true });
348
+ writeFileSync(serviceSdkPath, types.sdk, "utf-8");
349
+ consola.success(`[graphql:${service.name}] Generated SDK at: ${serviceSdkPath}`);
350
+ }
351
+ if (nitro.options.framework?.name === "nuxt") generateExternalOfetchClient(nitro, service, service.endpoint);
303
352
  consola.success(`[graphql:${service.name}] External service types generated successfully`);
304
353
  } catch (error) {
305
354
  consola.error(`[graphql:${service.name}] External service generation failed:`, error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "1.5.0",
4
+ "version": "1.5.2",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
@@ -117,7 +117,8 @@
117
117
  "h3": "1.15.3",
118
118
  "nitropack": "^2.12.7",
119
119
  "tsdown": "^0.15.9",
120
- "typescript": "^5.9.3"
120
+ "typescript": "^5.9.3",
121
+ "vitepress-plugin-llms": "^1.8.1"
121
122
  },
122
123
  "resolutions": {
123
124
  "nitro-graphql": "link:."
@@ -130,6 +131,9 @@
130
131
  "playground:nitro": "cd playgrounds/nitro && pnpm install && pnpm dev",
131
132
  "playground:nuxt": "cd playgrounds/nuxt && pnpm install && pnpm dev",
132
133
  "playground:federation": "cd playgrounds/federation && pnpm install && pnpm dev",
134
+ "docs:dev": "cd .docs && pnpm install && pnpm dev",
135
+ "docs:build": "cd .docs && pnpm install && pnpm build",
136
+ "docs:preview": "cd .docs && pnpm preview",
133
137
  "lint": "eslint .",
134
138
  "lint:fix": "eslint . --fix"
135
139
  }