nitro-graphql 1.4.4 → 2.0.0-beta.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.
@@ -43,8 +43,7 @@ var nuxt_default = defineNuxtModule({
43
43
  nitroConfig.graphql.layerDirectories = layerDirectories;
44
44
  nitroConfig.graphql.layerServerDirs = layerServerDirs;
45
45
  nitroConfig.graphql.layerAppDirs = layerAppDirs;
46
- const appGraphqlDir = resolve(nuxt.options.rootDir, "app/graphql");
47
- if (!existsSync(appGraphqlDir)) {
46
+ if (!existsSync(resolve(nuxt.options.rootDir, "app/graphql"))) {
48
47
  const defaultDir = join(clientDir, "default");
49
48
  if (!existsSync(defaultDir)) mkdirSync(defaultDir, { recursive: true });
50
49
  const sampleQueryFile = join(defaultDir, "queries.graphql");
package/dist/index.js CHANGED
@@ -7,7 +7,6 @@ import { fileURLToPath } from "node:url";
7
7
  import { watch } from "chokidar";
8
8
  import consola from "consola";
9
9
  import defu from "defu";
10
- import { defineNitroModule } from "nitropack/kit";
11
10
  import { dirname, join, relative, resolve } from "pathe";
12
11
 
13
12
  //#region src/index.ts
@@ -28,7 +27,7 @@ var src_default = defineNitroModule({
28
27
  buildDir: "",
29
28
  watchDirs: [],
30
29
  clientDir: "",
31
- serverDir: resolve(nitro.options.srcDir, "graphql"),
30
+ serverDir: resolve(nitro.options.rootDir, "server", "graphql"),
32
31
  dir: {
33
32
  build: relative(nitro.options.rootDir, nitro.options.buildDir),
34
33
  client: "graphql",
@@ -73,8 +72,11 @@ var src_default = defineNitroModule({
73
72
  break;
74
73
  }
75
74
  case "nitro":
75
+ if (!nitro.options.graphql?.serverDir) nitro.graphql.serverDir = resolve(nitro.options.rootDir, "server", "graphql");
76
76
  nitro.graphql.clientDir = resolve(nitro.options.rootDir, "graphql");
77
77
  nitro.graphql.dir.client = "graphql";
78
+ watchDirs.push(nitro.graphql.clientDir);
79
+ watchDirs.push(nitro.graphql.serverDir);
78
80
  break;
79
81
  default:
80
82
  }
@@ -91,13 +93,16 @@ var src_default = defineNitroModule({
91
93
  ignoreInitial: true,
92
94
  ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns(nitro)]
93
95
  }).on("all", async (_, path) => {
94
- if (path.endsWith(".graphql") || path.endsWith(".gql")) await clientTypeGeneration(nitro);
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);
95
101
  });
96
102
  nitro.hooks.hook("close", () => {
97
103
  watcher.close();
98
104
  });
99
- const tsConfigPath = resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath);
100
- const tsconfigDir = dirname(tsConfigPath);
105
+ const tsconfigDir = dirname(resolve(nitro.options.buildDir, nitro.options.typescript.tsconfigPath));
101
106
  const typesDir = resolve(nitro.options.buildDir, "types");
102
107
  nitro.scanSchemas = await scanSchemas(nitro);
103
108
  nitro.scanDocuments = await scanDocs(nitro);
@@ -122,9 +127,9 @@ var src_default = defineNitroModule({
122
127
  });
123
128
  const runtime = fileURLToPath(new URL("routes", import.meta.url));
124
129
  const methods = [
125
- "get",
126
- "post",
127
- "options"
130
+ "GET",
131
+ "POST",
132
+ "OPTIONS"
128
133
  ];
129
134
  if (nitro.options.graphql?.framework === "graphql-yoga") for (const method of methods) nitro.options.handlers.push({
130
135
  route: nitro.options.runtimeConfig.graphql?.endpoint?.graphql || "/api/graphql",
@@ -139,7 +144,7 @@ var src_default = defineNitroModule({
139
144
  nitro.options.handlers.push({
140
145
  route: nitro.options.runtimeConfig.graphql?.endpoint?.healthCheck || "/api/graphql/health",
141
146
  handler: join(runtime, "health"),
142
- method: "get"
147
+ method: "GET"
143
148
  });
144
149
  if (nitro.options.imports) {
145
150
  nitro.options.imports.presets ??= [];
@@ -208,13 +213,17 @@ export default <IGraphQLConfig> {
208
213
  }`, "utf-8");
209
214
  }
210
215
  if (!existsSync(nitro.graphql.serverDir)) mkdirSync(nitro.graphql.serverDir, { recursive: true });
211
- if (!existsSync(join(nitro.graphql.serverDir, "schema.ts"))) writeFileSync(join(nitro.graphql.serverDir, "schema.ts"), `export default defineSchema({
216
+ if (!existsSync(join(nitro.graphql.serverDir, "schema.ts"))) writeFileSync(join(nitro.graphql.serverDir, "schema.ts"), `
217
+ import { defineSchema } from 'nitro-graphql/utils/define'
218
+
219
+ export default defineSchema({
212
220
 
213
221
  })
214
222
  `, "utf-8");
215
223
  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
216
224
  // import * as tables from '../drizzle/schema/index'
217
225
  // import { useDatabase } from '../utils/useDb'
226
+ import { defineGraphQLConfig } from 'nitro-graphql/utils/define'
218
227
 
219
228
  export default defineGraphQLConfig({
220
229
  // graphql-yoga example config
package/dist/rollup.js CHANGED
@@ -37,7 +37,6 @@ async function rollupConfig(app) {
37
37
  async buildStart() {
38
38
  const graphqlFiles = await scanGraphql(nitro);
39
39
  for (const file of graphqlFiles) this.addWatchFile(file);
40
- this.addWatchFile(app.graphql.serverDir);
41
40
  }
42
41
  });
43
42
  }
@@ -48,9 +47,7 @@ async function rollupConfig(app) {
48
47
  });
49
48
  }
50
49
  function virtualSchemas(app) {
51
- const getSchemas = () => {
52
- return [...app.scanSchemas, ...app.options.graphql?.typedefs ?? []];
53
- };
50
+ const getSchemas = () => [...app.scanSchemas, ...app.options.graphql?.typedefs ?? []];
54
51
  app.options.virtual ??= {};
55
52
  app.options.virtual["#nitro-internal-virtual/server-schemas"] = () => {
56
53
  const imports = getSchemas();
@@ -64,43 +61,35 @@ ${imports.map((h) => `{ def: ${getImportId(h)} }`).join(",\n")}
64
61
  };
65
62
  }
66
63
  function virtualResolvers(app) {
67
- const getResolvers = () => {
68
- return [...app.scanResolvers];
69
- };
64
+ const getResolvers = () => [...app.scanResolvers];
70
65
  app.options.virtual ??= {};
71
66
  app.options.virtual["#nitro-internal-virtual/server-resolvers"] = () => {
72
67
  const imports = getResolvers();
73
- const importsContent = [...imports.map(({ specifier, imports: imports$1, options }) => {
74
- return genImport(specifier, imports$1, options);
75
- })];
76
- const content = [
68
+ const importsContent = imports.map(({ specifier, imports: imports$1, options }) => genImport(specifier, imports$1, options));
69
+ const data = imports.map(({ imports: imports$1 }) => imports$1.map((i) => `{ resolver: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n");
70
+ return [
71
+ ...importsContent,
77
72
  "export const resolvers = [",
78
- imports.map(({ imports: imports$1 }) => imports$1.map((i) => `{ resolver: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n"),
73
+ data,
79
74
  "]",
80
75
  ""
81
- ];
82
- content.unshift(...importsContent);
83
- return content.join("\n");
76
+ ].join("\n");
84
77
  };
85
78
  }
86
79
  function virtualDirectives(app) {
87
- const getDirectives = () => {
88
- return [...app.scanDirectives || []];
89
- };
80
+ const getDirectives = () => app.scanDirectives || [];
90
81
  app.options.virtual ??= {};
91
82
  app.options.virtual["#nitro-internal-virtual/server-directives"] = () => {
92
83
  const imports = getDirectives();
93
- const importsContent = [...imports.map(({ specifier, imports: imports$1, options }) => {
94
- return genImport(specifier, imports$1, options);
95
- })];
96
- const content = [
84
+ const importsContent = imports.map(({ specifier, imports: imports$1, options }) => genImport(specifier, imports$1, options));
85
+ const data = imports.map(({ imports: imports$1 }) => imports$1.map((i) => `{ directive: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n");
86
+ return [
87
+ ...importsContent,
97
88
  "export const directives = [",
98
- imports.map(({ imports: imports$1 }) => imports$1.map((i) => `{ directive: ${i.as} }`).join(",\n")).filter(Boolean).join(",\n"),
89
+ data,
99
90
  "]",
100
91
  ""
101
- ];
102
- content.unshift(...importsContent);
103
- return content.join("\n");
92
+ ].join("\n");
104
93
  };
105
94
  }
106
95
  function getGraphQLConfig(app) {
@@ -1,6 +1,6 @@
1
1
  import * as h31 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: h31.EventHandler<h31.EventHandlerRequest, unknown>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -26,8 +26,7 @@ async function loadFederationSupport() {
26
26
  }
27
27
  async function createMergedSchema() {
28
28
  try {
29
- const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
30
- const typeDefs = mergeTypeDefs([mergedSchemas], {
29
+ const typeDefs = mergeTypeDefs([schemas.map((schema$1) => schema$1.def).join("\n\n")], {
31
30
  throwOnConflict: true,
32
31
  commentDescriptions: true,
33
32
  sort: true
@@ -37,13 +36,11 @@ async function createMergedSchema() {
37
36
  let schema;
38
37
  if (federationEnabled) {
39
38
  const buildSubgraph = await loadFederationSupport();
40
- if (buildSubgraph) {
41
- const typeDefsDoc = typeof typeDefs === "string" ? parse(typeDefs) : typeDefs;
42
- schema = buildSubgraph({
43
- typeDefs: typeDefsDoc,
44
- resolvers: mergedResolvers
45
- });
46
- } else {
39
+ if (buildSubgraph) schema = buildSubgraph({
40
+ typeDefs: typeof typeDefs === "string" ? parse(typeDefs) : typeDefs,
41
+ resolvers: mergedResolvers
42
+ });
43
+ else {
47
44
  console.warn("Federation enabled but @apollo/subgraph not available, falling back to regular schema");
48
45
  schema = makeExecutableSchema({
49
46
  typeDefs,
@@ -67,9 +64,8 @@ let apolloServer = null;
67
64
  let serverStarted = false;
68
65
  async function createApolloServer() {
69
66
  if (!apolloServer) {
70
- const schema = await createMergedSchema();
71
67
  apolloServer = new ApolloServer(defu({
72
- schema,
68
+ schema: await createMergedSchema(),
73
69
  introspection: true,
74
70
  plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })]
75
71
  }, importedConfig));
@@ -83,8 +79,7 @@ async function createApolloServer() {
83
79
  let serverPromise = null;
84
80
  var apollo_server_default = defineEventHandler(async (event) => {
85
81
  if (!serverPromise) serverPromise = createApolloServer();
86
- const server = await serverPromise;
87
- return startServerAndCreateH3Handler(server, {
82
+ return startServerAndCreateH3Handler(await serverPromise, {
88
83
  context: async () => ({ event }),
89
84
  serverAlreadyStarted: true
90
85
  })(event);
@@ -1,6 +1,6 @@
1
1
  import * as h30 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: h30.EventHandler<h30.EventHandlerRequest, unknown>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -8,7 +8,7 @@ import { directives } from "#nitro-internal-virtual/server-directives";
8
8
  import { resolvers } from "#nitro-internal-virtual/server-resolvers";
9
9
  import { schemas } from "#nitro-internal-virtual/server-schemas";
10
10
  import { makeExecutableSchema } from "@graphql-tools/schema";
11
- import { defineEventHandler, toWebRequest } from "h3";
11
+ import { defineEventHandler } from "h3";
12
12
  import { createYoga } from "graphql-yoga";
13
13
 
14
14
  //#region src/routes/graphql-yoga.ts
@@ -41,8 +41,7 @@ new window.EmbeddedSandbox({
41
41
  </html>`;
42
42
  async function createMergedSchema() {
43
43
  try {
44
- const mergedSchemas = schemas.map((schema$1) => schema$1.def).join("\n\n");
45
- const typeDefs = mergeTypeDefs([mergedSchemas], {
44
+ const typeDefs = mergeTypeDefs([schemas.map((schema$1) => schema$1.def).join("\n\n")], {
46
45
  throwOnConflict: true,
47
46
  commentDescriptions: true,
48
47
  sort: true
@@ -52,13 +51,11 @@ async function createMergedSchema() {
52
51
  let schema;
53
52
  if (federationEnabled) {
54
53
  const buildSubgraph = await loadFederationSupport();
55
- if (buildSubgraph) {
56
- const typeDefsDoc = typeof typeDefs === "string" ? parse(typeDefs) : typeDefs;
57
- schema = buildSubgraph({
58
- typeDefs: typeDefsDoc,
59
- resolvers: mergedResolvers
60
- });
61
- } else {
54
+ if (buildSubgraph) schema = buildSubgraph({
55
+ typeDefs: typeof typeDefs === "string" ? parse(typeDefs) : typeDefs,
56
+ resolvers: mergedResolvers
57
+ });
58
+ else {
62
59
  console.warn("Federation enabled but @apollo/subgraph not available, falling back to regular schema");
63
60
  schema = makeExecutableSchema({
64
61
  typeDefs,
@@ -80,17 +77,13 @@ async function createMergedSchema() {
80
77
  }
81
78
  let yoga;
82
79
  var graphql_yoga_default = defineEventHandler(async (event) => {
83
- if (!yoga) {
84
- const schema = await createMergedSchema();
85
- yoga = createYoga(defu({
86
- schema,
87
- graphqlEndpoint: "/api/graphql",
88
- landingPage: false,
89
- renderGraphiQL: () => apolloSandboxHtml
90
- }, importedConfig));
91
- }
92
- const request = toWebRequest(event);
93
- const response = await yoga.handleRequest(request, event);
80
+ if (!yoga) yoga = createYoga(defu({
81
+ schema: await createMergedSchema(),
82
+ graphqlEndpoint: "/api/graphql",
83
+ landingPage: false,
84
+ renderGraphiQL: () => apolloSandboxHtml
85
+ }, importedConfig));
86
+ const response = await yoga.handleRequest(event.req, event);
94
87
  return new Response(response.body, response);
95
88
  });
96
89
 
@@ -1,10 +1,6 @@
1
1
  import * as h33 from "h3";
2
2
 
3
3
  //#region src/routes/health.d.ts
4
- declare const _default: h33.EventHandler<h33.EventHandlerRequest, Promise<{
5
- status: string;
6
- message: string;
7
- timestamp: string;
8
- }>>;
4
+ declare const _default: h33.EventHandler<h33.EventHandlerRequest, unknown>;
9
5
  //#endregion
10
6
  export { _default as default };
@@ -1,11 +1,12 @@
1
- import { defineEventHandler, setResponseStatus } from "h3";
2
- import { useRuntimeConfig } from "nitropack/runtime";
1
+ import { defineEventHandler } from "h3";
2
+ import { useRuntimeConfig } from "nitro/runtime";
3
3
 
4
4
  //#region src/routes/health.ts
5
5
  var health_default = defineEventHandler(async (event) => {
6
6
  const runtime = useRuntimeConfig();
7
7
  if (!runtime.graphql || !runtime.graphql.endpoint?.graphql) {
8
- setResponseStatus(event, 404);
8
+ event.res.status = 404;
9
+ event.res.statusText = "Not Found";
9
10
  return {
10
11
  status: "error",
11
12
  message: "GraphQL health check endpoint is not configured",
@@ -31,7 +32,8 @@ var health_default = defineEventHandler(async (event) => {
31
32
  };
32
33
  throw new Error("Invalid response from GraphQL server");
33
34
  } catch (error) {
34
- setResponseStatus(event, 503);
35
+ event.res.status = 503;
36
+ event.res.statusText = "Service Unavailable";
35
37
  return {
36
38
  status: "unhealthy",
37
39
  message: error instanceof Error ? error.message : "GraphQL server is not responding",
@@ -27,7 +27,7 @@ interface GenImport {
27
27
  imports: IESMImport[];
28
28
  options?: ESMCodeGenOptions;
29
29
  }
30
- declare module 'nitropack/types' {
30
+ declare module 'nitro/types' {
31
31
  interface Nitro {
32
32
  scanSchemas: string[];
33
33
  scanDocuments: string[];
@@ -46,7 +46,7 @@ declare module 'nitropack/types' {
46
46
  };
47
47
  }
48
48
  }
49
- declare module 'nitropack' {
49
+ declare module 'nitro/types' {
50
50
  interface NitroOptions {
51
51
  graphql?: NitroGraphQLOptions;
52
52
  }
@@ -101,15 +101,13 @@ async function downloadAndSaveSchema(service, buildDir) {
101
101
  if (downloadMode === "always") {
102
102
  shouldDownload = true;
103
103
  if (fileExists && hasUrlSchemas) try {
104
- const remoteSchema = loadSchemaSync(schemas.filter(isUrl), {
104
+ const remoteSchemaString = printSchemaWithDirectives(loadSchemaSync(schemas.filter(isUrl), {
105
105
  loaders: [new UrlLoader()],
106
106
  ...Object.keys(headers).length > 0 && { headers }
107
- });
108
- const remoteSchemaString = printSchemaWithDirectives(remoteSchema);
107
+ }));
109
108
  const remoteHash = createHash("md5").update(remoteSchemaString).digest("hex");
110
109
  const localSchemaString = readFileSync(schemaFilePath, "utf-8");
111
- const localHash = createHash("md5").update(localSchemaString).digest("hex");
112
- if (remoteHash === localHash) {
110
+ if (remoteHash === createHash("md5").update(localSchemaString).digest("hex")) {
113
111
  shouldDownload = false;
114
112
  consola$1.info(`[graphql:${service.name}] Schema is up-to-date, using cached version`);
115
113
  }
@@ -134,24 +132,21 @@ async function downloadAndSaveSchema(service, buildDir) {
134
132
  } else if (downloadMode === true || downloadMode === "once") shouldDownload = !fileExists;
135
133
  if (shouldDownload) {
136
134
  if (hasUrlSchemas && hasLocalSchemas) {
137
- const schema = loadSchemaSync(schemas, {
135
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, {
138
136
  loaders: [new GraphQLFileLoader(), new UrlLoader()],
139
137
  ...Object.keys(headers).length > 0 && { headers }
140
- });
141
- const schemaString = printSchemaWithDirectives(schema);
138
+ }));
142
139
  mkdirSync(dirname(schemaFilePath), { recursive: true });
143
140
  writeFileSync(schemaFilePath, schemaString, "utf-8");
144
141
  } else if (hasUrlSchemas) {
145
- const schema = loadSchemaSync(schemas, {
142
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, {
146
143
  loaders: [new UrlLoader()],
147
144
  ...Object.keys(headers).length > 0 && { headers }
148
- });
149
- const schemaString = printSchemaWithDirectives(schema);
145
+ }));
150
146
  mkdirSync(dirname(schemaFilePath), { recursive: true });
151
147
  writeFileSync(schemaFilePath, schemaString, "utf-8");
152
148
  } else if (hasLocalSchemas) {
153
- const schema = loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] });
154
- const schemaString = printSchemaWithDirectives(schema);
149
+ const schemaString = printSchemaWithDirectives(loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] }));
155
150
  mkdirSync(dirname(schemaFilePath), { recursive: true });
156
151
  writeFileSync(schemaFilePath, schemaString, "utf-8");
157
152
  }
@@ -176,7 +171,7 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
176
171
  return false;
177
172
  }
178
173
  const serviceLabel = serviceName ? `:${serviceName}` : "";
179
- const defaultConfig = {
174
+ const mergedConfig = defu$1({
180
175
  emitLegacyCommonJSImports: false,
181
176
  useTypeImports: true,
182
177
  enumsAsTypes: true,
@@ -200,8 +195,7 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
200
195
  output: "File"
201
196
  }
202
197
  }
203
- };
204
- const mergedConfig = defu$1(defaultConfig, config);
198
+ }, config);
205
199
  const mergedSdkConfig = defu$1(mergedConfig, sdkConfig);
206
200
  try {
207
201
  if (docs.length === 0) return {
@@ -271,15 +265,14 @@ export function getSdk(requester: Requester): Sdk {
271
265
  typescriptGenericSdk: { plugin: plugin$1 }
272
266
  }
273
267
  });
274
- const sdkContent = (await Promise.all(sdkOutput.map(async (config$1) => {
275
- return {
276
- file: config$1.filename,
277
- content: await codegen(config$1)
278
- };
279
- })))[0]?.content || "";
280
268
  return {
281
269
  types: output,
282
- sdk: sdkContent
270
+ sdk: (await Promise.all(sdkOutput.map(async (config$1) => {
271
+ return {
272
+ file: config$1.filename,
273
+ content: await codegen(config$1)
274
+ };
275
+ })))[0]?.content || ""
283
276
  };
284
277
  } catch (error) {
285
278
  consola$1.warn(`[graphql${serviceLabel}] Client type generation failed:`, error);
@@ -290,9 +283,7 @@ export function getSdk(requester: Requester): Sdk {
290
283
  * Generate client types for external GraphQL service
291
284
  */
292
285
  async function generateExternalClientTypes(service, schema, docs) {
293
- const config = service.codegen?.client || {};
294
- const sdkConfig = service.codegen?.clientSDK || {};
295
- return generateClientTypes(schema, docs, config, sdkConfig, void 0, service.name);
286
+ return generateClientTypes(schema, docs, service.codegen?.client || {}, service.codegen?.clientSDK || {}, void 0, service.name);
296
287
  }
297
288
 
298
289
  //#endregion
@@ -18,13 +18,9 @@ var DirectiveParser = class {
18
18
  sourceType: "module",
19
19
  astType: "ts"
20
20
  });
21
- if (result.errors.length > 0) {
22
- console.warn(`Parse errors in ${filePath}:`, result.errors.map((e) => e.message));
23
- return [];
24
- }
21
+ if (result.errors.length > 0) return [];
25
22
  return this.extractDirectiveDefinitions(result.program);
26
- } catch (error) {
27
- console.warn(`Failed to parse ${filePath} with oxc:`, error);
23
+ } catch {
28
24
  return [];
29
25
  }
30
26
  }
@@ -205,7 +201,7 @@ async function generateDirectiveSchemas(nitro, directives) {
205
201
  }
206
202
  }
207
203
  if (directiveSchemas.length > 0) {
208
- const directivesPath = resolve(nitro.graphql.serverDir, "_directives.graphql");
204
+ const directivesPath = resolve(nitro.graphql.buildDir, "_directives.graphql");
209
205
  const content = `# WARNING: This file is auto-generated by nitro-graphql
210
206
  # Do not modify this file directly. It will be overwritten.
211
207
  # To define custom directives, create .directive.ts files using defineDirective()
@@ -1,6 +1,6 @@
1
1
  import { GenImport } from "../types/index.js";
2
2
  import { directiveParser, generateDirectiveSchema, generateDirectiveSchemas } from "./directive-parser.js";
3
- import { Nitro } from "nitropack";
3
+ import { Nitro } from "nitro/types";
4
4
 
5
5
  //#region src/utils/index.d.ts
6
6
  declare const GLOB_SCAN_PATTERN = "**/*.{graphql,gql,js,mjs,cjs,ts,mts,cts,tsx,jsx}";
@@ -19,13 +19,12 @@ declare function getLayerAppDirectories(nitro: Nitro): string[];
19
19
  /**
20
20
  * Generate layer-aware ignore patterns for auto-generated files
21
21
  */
22
- declare function generateLayerIgnorePatterns(nitro: Nitro): string[];
22
+ declare function generateLayerIgnorePatterns(): string[];
23
23
  declare function getImportId(p: string, lazy?: boolean): string;
24
24
  declare function relativeWithDot(from: string, to: string): string;
25
25
  declare function scanGraphql(nitro: Nitro): Promise<string[]>;
26
26
  declare function scanResolvers(nitro: Nitro): Promise<GenImport[]>;
27
27
  declare function scanDirectives(nitro: Nitro): Promise<GenImport[]>;
28
- declare function scanTypeDefs(nitro: Nitro): Promise<string[]>;
29
28
  declare function scanSchemas(nitro: Nitro): Promise<string[]>;
30
29
  declare function scanDocs(nitro: Nitro): Promise<string[]>;
31
30
  /**
@@ -37,4 +36,4 @@ declare function scanExternalServiceDocs(nitro: Nitro, serviceName: string, patt
37
36
  */
38
37
  declare function validateExternalServices(services: unknown[]): string[];
39
38
  //#endregion
40
- export { GLOB_SCAN_PATTERN, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, scanTypeDefs, validateExternalServices };
39
+ export { GLOB_SCAN_PATTERN, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };
@@ -28,12 +28,8 @@ function getLayerAppDirectories(nitro) {
28
28
  /**
29
29
  * Generate layer-aware ignore patterns for auto-generated files
30
30
  */
31
- function generateLayerIgnorePatterns(nitro) {
32
- const patterns = [];
33
- patterns.push(`${nitro.graphql.serverDir}/_directives.graphql`);
34
- const layerServerDirs = nitro.options.graphql?.layerServerDirs || [];
35
- for (const layerServerDir of layerServerDirs) patterns.push(`${layerServerDir}/graphql/_directives.graphql`);
36
- return patterns;
31
+ function generateLayerIgnorePatterns() {
32
+ return [];
37
33
  }
38
34
  function getImportId(p, lazy) {
39
35
  return (lazy ? "_lazy_" : "_") + hash(p).replace(/-/g, "").slice(0, 6);
@@ -44,10 +40,30 @@ function relativeWithDot(from, to) {
44
40
  return RELATIVE_RE.test(rel) ? rel : `./${rel}`;
45
41
  }
46
42
  async function scanGraphql(nitro) {
47
- return (await scanFiles(nitro, "graphql")).map((f) => f.fullPath);
43
+ const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
44
+ const files = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.{graphql,gql}");
45
+ const layerServerDirs = getLayerServerDirectories(nitro);
46
+ const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.{graphql,gql}"))).then((r) => r.flat());
47
+ const allFiles = [...files, ...layerFiles];
48
+ const seenPaths = /* @__PURE__ */ new Set();
49
+ return allFiles.filter((file) => {
50
+ if (seenPaths.has(file.fullPath)) return false;
51
+ seenPaths.add(file.fullPath);
52
+ return true;
53
+ }).map((f) => f.fullPath);
48
54
  }
49
55
  async function scanResolvers(nitro) {
50
- const files = await scanFiles(nitro, "graphql", "**/*.resolver.{ts,js}");
56
+ const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
57
+ const regularFiles = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.resolver.{ts,js}");
58
+ const layerServerDirs = getLayerServerDirectories(nitro);
59
+ const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.resolver.{ts,js}"))).then((r) => r.flat());
60
+ const allFiles = [...regularFiles, ...layerFiles];
61
+ const seenPaths = /* @__PURE__ */ new Set();
62
+ const files = allFiles.filter((file) => {
63
+ if (seenPaths.has(file.fullPath)) return false;
64
+ seenPaths.add(file.fullPath);
65
+ return true;
66
+ });
51
67
  const exportName = [];
52
68
  for (const file of files) {
53
69
  const fileContent = await readFile(file.fullPath, "utf-8");
@@ -97,7 +113,17 @@ async function scanResolvers(nitro) {
97
113
  return exportName;
98
114
  }
99
115
  async function scanDirectives(nitro) {
100
- const files = await scanFiles(nitro, "graphql", "**/*.directive.{ts,js}");
116
+ const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
117
+ const regularFiles = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.directive.{ts,js}");
118
+ const layerServerDirs = getLayerServerDirectories(nitro);
119
+ const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.directive.{ts,js}"))).then((r) => r.flat());
120
+ const allFiles = [...regularFiles, ...layerFiles];
121
+ const seenPaths = /* @__PURE__ */ new Set();
122
+ const files = allFiles.filter((file) => {
123
+ if (seenPaths.has(file.fullPath)) return false;
124
+ seenPaths.add(file.fullPath);
125
+ return true;
126
+ });
101
127
  const exportName = [];
102
128
  for (const file of files) {
103
129
  const fileContent = await readFile(file.fullPath, "utf-8");
@@ -121,11 +147,18 @@ async function scanDirectives(nitro) {
121
147
  }
122
148
  return exportName;
123
149
  }
124
- async function scanTypeDefs(nitro) {
125
- return (await scanFiles(nitro, "graphql", "**/*.typedef.{ts,js}")).map((f) => f.fullPath);
126
- }
127
150
  async function scanSchemas(nitro) {
128
- return (await scanFiles(nitro, "graphql", "**/*.graphql")).map((f) => f.fullPath);
151
+ const serverDirRelative = relative(nitro.options.rootDir, nitro.graphql.serverDir);
152
+ const files = await scanDir(nitro, nitro.options.rootDir, serverDirRelative, "**/*.graphql");
153
+ const layerServerDirs = getLayerServerDirectories(nitro);
154
+ const layerFiles = await Promise.all(layerServerDirs.map((layerServerDir) => scanDir(nitro, layerServerDir, "graphql", "**/*.graphql"))).then((r) => r.flat());
155
+ const allFiles = [...files, ...layerFiles];
156
+ const seenPaths = /* @__PURE__ */ new Set();
157
+ return allFiles.filter((file) => {
158
+ if (seenPaths.has(file.fullPath)) return false;
159
+ seenPaths.add(file.fullPath);
160
+ return true;
161
+ }).map((f) => f.fullPath);
129
162
  }
130
163
  async function scanDocs(nitro) {
131
164
  const files = await scanDir(nitro, nitro.options.rootDir, nitro.graphql.dir.client, "**/*.graphql");
@@ -143,9 +176,7 @@ async function scanDocs(nitro) {
143
176
  const relativePath = f.path;
144
177
  for (const pattern of externalPatterns) {
145
178
  const clientDirPattern = `${nitro.graphql.dir.client}/`;
146
- const patternDir = pattern.replace(/* @__PURE__ */ new RegExp(`^${clientDirPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "").split("/")[0];
147
- const fileDir = relativePath.split("/")[0];
148
- if (patternDir === fileDir) return false;
179
+ if (pattern.replace(/* @__PURE__ */ new RegExp(`^${clientDirPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`), "").split("/")[0] === relativePath.split("/")[0]) return false;
149
180
  }
150
181
  return true;
151
182
  }).map((f) => f.fullPath);
@@ -195,18 +226,6 @@ function validateExternalServices(services) {
195
226
  }
196
227
  return errors;
197
228
  }
198
- async function scanFiles(nitro, name, globPattern = GLOB_SCAN_PATTERN) {
199
- const regularFiles = await Promise.all(nitro.options.scanDirs.map((dir) => scanDir(nitro, dir, name, globPattern))).then((r) => r.flat());
200
- const layerDirectories = getLayerDirectories(nitro);
201
- const layerFiles = await Promise.all(layerDirectories.map((layerDir) => scanDir(nitro, layerDir, `server/${name}`, globPattern))).then((r) => r.flat());
202
- const allFiles = [...regularFiles, ...layerFiles];
203
- const seenPaths = /* @__PURE__ */ new Set();
204
- return allFiles.filter((file) => {
205
- if (seenPaths.has(file.fullPath)) return false;
206
- seenPaths.add(file.fullPath);
207
- return true;
208
- });
209
- }
210
229
  async function scanDir(nitro, dir, name, globPattern = GLOB_SCAN_PATTERN) {
211
230
  return (await glob(join(name, globPattern), {
212
231
  cwd: dir,
@@ -228,4 +247,4 @@ async function scanDir(nitro, dir, name, globPattern = GLOB_SCAN_PATTERN) {
228
247
  }
229
248
 
230
249
  //#endregion
231
- export { GLOB_SCAN_PATTERN, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, scanTypeDefs, validateExternalServices };
250
+ export { GLOB_SCAN_PATTERN, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };
@@ -21,7 +21,7 @@ function pluginContent(_schema, _documents, _config, _info) {
21
21
  };
22
22
  }
23
23
  async function generateTypes(selectFremework, schema, config = {}, outputPath) {
24
- const defaultConfig = {
24
+ const mergedConfig = defu$1({
25
25
  scalars: {
26
26
  DateTime: DateTimeResolver.extensions.codegenScalarType,
27
27
  DateTimeISO: DateTimeISOResolver.extensions.codegenScalarType,
@@ -43,8 +43,7 @@ async function generateTypes(selectFremework, schema, config = {}, outputPath) {
43
43
  declarationKind: "interface",
44
44
  enumsAsTypes: true,
45
45
  ...config.federation?.enabled && { federation: true }
46
- };
47
- const mergedConfig = defu$1(defaultConfig, config.codegen?.server);
46
+ }, config.codegen?.server);
48
47
  return await codegen({
49
48
  filename: outputPath || "types.generated.ts",
50
49
  schema: parse(printSchemaWithDirectives(schema)),
@@ -1,4 +1,4 @@
1
- import { Nitro } from "nitropack";
1
+ import { Nitro } from "nitro/types";
2
2
 
3
3
  //#region src/utils/type-generation.d.ts
4
4
  declare function serverTypeGeneration(app: Nitro): Promise<void>;
@@ -27,16 +27,20 @@ export * from './default/ofetch'
27
27
  writeFileSync(indexPath, indexContent, "utf-8");
28
28
  }
29
29
  }
30
- function generateNuxtOfetchClient(clientDir, serviceName = "default") {
30
+ function generateOfetchClient(clientDir, serviceName, endpoint, isDefault = false) {
31
31
  const serviceDir = resolve(clientDir, serviceName);
32
32
  const ofetchPath = resolve(serviceDir, "ofetch.ts");
33
33
  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
34
+ if (existsSync(ofetchPath)) return;
35
+ const capitalizedServiceName = serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
36
+ const functionName = isDefault ? "createGraphQLClient" : `create${capitalizedServiceName}GraphQLClient`;
37
+ const exportName = isDefault ? "$sdk" : `$${serviceName}Sdk`;
38
+ writeFileSync(ofetchPath, `// This file is auto-generated once by nitro-graphql for quick start
35
39
  // You can modify this file according to your needs
36
- import type { Requester } from './sdk'
40
+ import type { ${isDefault ? "Requester" : "Sdk, Requester"} } from './sdk'
37
41
  import { getSdk } from './sdk'
38
42
 
39
- export function createGraphQLClient(endpoint: string): Requester {
43
+ export function ${functionName}(endpoint: string${isDefault ? "" : ` = '${endpoint}'`}): Requester {
40
44
  return async <R>(doc: string, vars?: any): Promise<R> => {
41
45
  const headers = import.meta.server ? useRequestHeaders() : undefined
42
46
 
@@ -53,39 +57,7 @@ export function createGraphQLClient(endpoint: string): Requester {
53
57
  }
54
58
  }
55
59
 
56
- export const $sdk = getSdk(createGraphQLClient('/api/graphql'))`, "utf-8");
57
- }
58
- function generateExternalOfetchClient(clientDir, serviceName, endpoint) {
59
- const serviceDir = resolve(clientDir, serviceName);
60
- const ofetchPath = resolve(serviceDir, "ofetch.ts");
61
- if (!existsSync(serviceDir)) mkdirSync(serviceDir, { recursive: true });
62
- if (!existsSync(ofetchPath)) {
63
- const capitalizedServiceName = serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
64
- const ofetchContent = `// This file is auto-generated once by nitro-graphql for quick start
65
- // You can modify this file according to your needs
66
- import type { Sdk, Requester } from './sdk'
67
- import { getSdk } from './sdk'
68
-
69
- export function create${capitalizedServiceName}GraphQLClient(endpoint: string = '${endpoint}'): Requester {
70
- return async <R>(doc: string, vars?: any): Promise<R> => {
71
- const headers = import.meta.server ? useRequestHeaders() : undefined
72
-
73
- const result = await $fetch(endpoint, {
74
- method: 'POST',
75
- body: { query: doc, variables: vars },
76
- headers: {
77
- 'Content-Type': 'application/json',
78
- ...headers,
79
- },
80
- })
81
-
82
- return result as R
83
- }
84
- }
85
-
86
- export const $${serviceName}Sdk: Sdk = getSdk(create${capitalizedServiceName}GraphQLClient())`;
87
- writeFileSync(ofetchPath, ofetchContent, "utf-8");
88
- }
60
+ export const ${exportName}${isDefault ? "" : ": Sdk"} = getSdk(${functionName}(${isDefault ? "'/api/graphql'" : ""}))`, "utf-8");
89
61
  }
90
62
  /**
91
63
  * Check for duplicate type definitions using a simpler approach
@@ -251,8 +223,7 @@ async function generateMainClientTypes(nitro) {
251
223
  return;
252
224
  }
253
225
  const graphqlString = readFileSync(schemaFilePath, "utf-8");
254
- const schema = nitro.options.graphql?.federation?.enabled === true ? buildSubgraphSchema([{ typeDefs: parse(graphqlString) }]) : buildSchema(graphqlString);
255
- const types = await generateClientTypes(schema, loadDocs, nitro.options.graphql?.codegen?.client ?? {}, nitro.options.graphql?.codegen?.clientSDK ?? {});
226
+ 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 ?? {});
256
227
  if (types === false) return;
257
228
  const clientTypesPath = resolve(nitro.options.buildDir, "types", "nitro-graphql-client.d.ts");
258
229
  const defaultServiceDir = resolve(nitro.graphql.clientDir, "default");
@@ -260,9 +231,11 @@ async function generateMainClientTypes(nitro) {
260
231
  mkdirSync(dirname(clientTypesPath), { recursive: true });
261
232
  writeFileSync(clientTypesPath, types.types, "utf-8");
262
233
  mkdirSync(defaultServiceDir, { recursive: true });
263
- writeFileSync(sdkTypesPath, types.sdk, "utf-8");
234
+ let shouldWriteSdk = true;
235
+ if (existsSync(sdkTypesPath)) shouldWriteSdk = readFileSync(sdkTypesPath, "utf-8") !== types.sdk;
236
+ if (shouldWriteSdk) writeFileSync(sdkTypesPath, types.sdk, "utf-8");
264
237
  if (nitro.options.framework?.name === "nuxt") {
265
- generateNuxtOfetchClient(nitro.graphql.clientDir, "default");
238
+ generateOfetchClient(nitro.graphql.clientDir, "default", "/api/graphql", true);
266
239
  const externalServices = nitro.options.graphql?.externalServices || [];
267
240
  generateGraphQLIndexFile(nitro.graphql.clientDir, externalServices);
268
241
  }
@@ -300,8 +273,10 @@ async function generateExternalServicesTypes(nitro) {
300
273
  mkdirSync(dirname(serviceTypesPath), { recursive: true });
301
274
  writeFileSync(serviceTypesPath, types.types, "utf-8");
302
275
  mkdirSync(serviceDir, { recursive: true });
303
- writeFileSync(serviceSdkPath, types.sdk, "utf-8");
304
- if (nitro.options.framework?.name === "nuxt") generateExternalOfetchClient(nitro.graphql.clientDir, service.name, service.endpoint);
276
+ let shouldWriteServiceSdk = true;
277
+ if (existsSync(serviceSdkPath)) shouldWriteServiceSdk = readFileSync(serviceSdkPath, "utf-8") !== types.sdk;
278
+ if (shouldWriteServiceSdk) writeFileSync(serviceSdkPath, types.sdk, "utf-8");
279
+ if (nitro.options.framework?.name === "nuxt") generateOfetchClient(nitro.graphql.clientDir, service.name, service.endpoint, false);
305
280
  consola.success(`[graphql:${service.name}] External service types generated successfully`);
306
281
  } catch (error) {
307
282
  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.4.4",
4
+ "version": "2.0.0-beta.2",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
@@ -63,8 +63,8 @@
63
63
  "@apollo/utils.withrequired": "^3.0.0",
64
64
  "@as-integrations/h3": "^2.0.0",
65
65
  "graphql": "^16.11.0",
66
- "h3": "^1.15.3",
67
- "nitropack": "^2.11.13"
66
+ "h3": "^2.0.1-rc.2",
67
+ "nitro": "^3.0.1-alpha.0"
68
68
  },
69
69
  "peerDependenciesMeta": {
70
70
  "@apollo/server": {
@@ -114,8 +114,8 @@
114
114
  "eslint": "^9.37.0",
115
115
  "graphql": "16.11.0",
116
116
  "graphql-yoga": "^5.16.0",
117
- "h3": "1.15.3",
118
- "nitropack": "^2.12.6",
117
+ "h3": "^2.0.1-rc.2",
118
+ "nitro": "^3.0.1-alpha.0",
119
119
  "tsdown": "^0.15.6",
120
120
  "typescript": "^5.9.3"
121
121
  },