nitro-graphql 1.2.0 → 1.2.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.
@@ -1,7 +1,7 @@
1
- import * as _nuxt_schema3 from "@nuxt/schema";
1
+ import * as _nuxt_schema0 from "@nuxt/schema";
2
2
 
3
3
  //#region src/ecosystem/nuxt.d.ts
4
4
  interface ModuleOptions {}
5
- declare const _default: _nuxt_schema3.NuxtModule<ModuleOptions, ModuleOptions, false>;
5
+ declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
6
  //#endregion
7
7
  export { ModuleOptions, _default as default };
@@ -1,3 +1,4 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
1
2
  import { join, resolve } from "pathe";
2
3
  import { defineNuxtModule } from "@nuxt/kit";
3
4
 
@@ -31,6 +32,27 @@ var nuxt_default = defineNuxtModule({
31
32
  nuxt.hook("imports:dirs", (dirs) => {
32
33
  dirs.push(resolve(nuxt.options.srcDir, "graphql"));
33
34
  });
35
+ nuxt.hook("nitro:config", () => {
36
+ const clientDir = join(nuxt.options.buildDir, "graphql");
37
+ const appGraphqlDir = resolve(nuxt.options.rootDir, "app/graphql");
38
+ const hasAppGraphqlDir = existsSync(appGraphqlDir);
39
+ if (!hasAppGraphqlDir) {
40
+ const defaultDir = join(clientDir, "default");
41
+ if (!existsSync(defaultDir)) mkdirSync(defaultDir, { recursive: true });
42
+ const sampleQueryFile = join(defaultDir, "queries.graphql");
43
+ if (!existsSync(sampleQueryFile)) writeFileSync(sampleQueryFile, `# Example GraphQL queries
44
+ # Add your GraphQL queries here
45
+
46
+ # query GetUser($id: ID!) {
47
+ # user(id: $id) {
48
+ # id
49
+ # name
50
+ # email
51
+ # }
52
+ # }
53
+ `, "utf-8");
54
+ }
55
+ });
34
56
  }
35
57
  });
36
58
 
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { StandardSchemaV1 } from "./types/standard-schema.js";
2
2
  import { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions } from "./types/index.js";
3
- import * as nitropack2 from "nitropack";
3
+ import * as nitropack1 from "nitropack";
4
4
 
5
5
  //#region src/index.d.ts
6
- declare const _default: nitropack2.NitroModule;
6
+ declare const _default: nitropack1.NitroModule;
7
7
  //#endregion
8
8
  export { CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, GenImport, GenericSdkConfig, NitroGraphQLOptions, StandardSchemaV1, _default as default };
package/dist/index.js CHANGED
@@ -71,7 +71,8 @@ var src_default = defineNitroModule({
71
71
  }
72
72
  if (nitro.options.graphql?.externalServices?.length) {
73
73
  for (const service of nitro.options.graphql.externalServices) if (service.documents?.length) for (const pattern of service.documents) {
74
- const baseDir = pattern.split("**")[0].replace(/\/$/, "") || ".";
74
+ if (!pattern) continue;
75
+ const baseDir = pattern.split("**")[0]?.replace(/\/$/, "") || ".";
75
76
  const resolvedDir = resolve(nitro.options.rootDir, baseDir);
76
77
  if (!watchDirs.includes(resolvedDir)) watchDirs.push(resolvedDir);
77
78
  }
@@ -1,6 +1,6 @@
1
- import * as h36 from "h3";
1
+ import * as h32 from "h3";
2
2
 
3
3
  //#region src/routes/apollo-server.d.ts
4
- declare const _default: h36.EventHandler<h36.EventHandlerRequest, any>;
4
+ declare const _default: h32.EventHandler<h32.EventHandlerRequest, any>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -1,6 +1,6 @@
1
- import * as h30 from "h3";
1
+ import * as h36 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: h36.EventHandler<h36.EventHandlerRequest, Promise<Response>>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -57,23 +57,23 @@ async function loadExternalSchema(service, buildDir) {
57
57
  if (service.downloadSchema && buildDir) {
58
58
  const defaultPath = resolve(buildDir, "graphql", "schemas", `${service.name}.graphql`);
59
59
  const schemaFilePath = service.downloadPath ? resolve(service.downloadPath) : defaultPath;
60
- if (existsSync(schemaFilePath)) {
61
- consola$1.info(`[graphql:${service.name}] Loading schema from local file: ${schemaFilePath}`);
62
- try {
63
- const result$1 = loadSchemaSync([schemaFilePath], { loaders: [new GraphQLFileLoader()] });
64
- consola$1.info(`[graphql:${service.name}] External schema loaded successfully from local file`);
65
- return result$1;
66
- } catch (localError) {
67
- consola$1.warn(`[graphql:${service.name}] Failed to load local schema, falling back to remote:`, localError);
68
- }
60
+ if (existsSync(schemaFilePath)) try {
61
+ const result$1 = loadSchemaSync([schemaFilePath], { loaders: [new GraphQLFileLoader()] });
62
+ return result$1;
63
+ } catch {
64
+ consola$1.warn(`[graphql:${service.name}] Cached schema invalid, loading from source`);
69
65
  }
70
66
  }
71
- consola$1.info(`[graphql:${service.name}] Loading external schema from: ${schemas.join(", ")}`);
67
+ const hasUrls = schemas.some((schema) => isUrl(schema));
68
+ const hasLocalFiles = schemas.some((schema) => !isUrl(schema));
69
+ const loaders = [];
70
+ if (hasLocalFiles) loaders.push(new GraphQLFileLoader());
71
+ if (hasUrls) loaders.push(new UrlLoader());
72
+ if (loaders.length === 0) throw new Error("No appropriate loaders found for schema sources");
72
73
  const result = loadSchemaSync(schemas, {
73
- loaders: [new GraphQLFileLoader(), new UrlLoader()],
74
+ loaders,
74
75
  ...Object.keys(headers).length > 0 && { headers }
75
76
  });
76
- consola$1.info(`[graphql:${service.name}] External schema loaded successfully`);
77
77
  return result;
78
78
  } catch (error) {
79
79
  consola$1.error(`[graphql:${service.name}] Failed to load external schema:`, error);
@@ -81,6 +81,12 @@ async function loadExternalSchema(service, buildDir) {
81
81
  }
82
82
  }
83
83
  /**
84
+ * Check if a path is a URL (http/https)
85
+ */
86
+ function isUrl(path) {
87
+ return path.startsWith("http://") || path.startsWith("https://");
88
+ }
89
+ /**
84
90
  * Download and save schema from external service
85
91
  */
86
92
  async function downloadAndSaveSchema(service, buildDir) {
@@ -91,12 +97,14 @@ async function downloadAndSaveSchema(service, buildDir) {
91
97
  try {
92
98
  const headers = typeof service.headers === "function" ? service.headers() : service.headers || {};
93
99
  const schemas = Array.isArray(service.schema) ? service.schema : [service.schema];
100
+ const hasUrlSchemas = schemas.some((schema) => isUrl(schema));
101
+ const hasLocalSchemas = schemas.some((schema) => !isUrl(schema));
94
102
  let shouldDownload = false;
95
103
  const fileExists = existsSync(schemaFilePath);
96
104
  if (downloadMode === "always") {
97
105
  shouldDownload = true;
98
- if (fileExists) try {
99
- const remoteSchema = loadSchemaSync(schemas, {
106
+ if (fileExists && hasUrlSchemas) try {
107
+ const remoteSchema = loadSchemaSync(schemas.filter(isUrl), {
100
108
  loaders: [new UrlLoader()],
101
109
  ...Object.keys(headers).length > 0 && { headers }
102
110
  });
@@ -112,24 +120,48 @@ async function downloadAndSaveSchema(service, buildDir) {
112
120
  consola$1.warn(`[graphql:${service.name}] Unable to compare with remote schema, updating local cache`);
113
121
  shouldDownload = true;
114
122
  }
115
- } else if (downloadMode === true || downloadMode === "once") {
116
- shouldDownload = !fileExists;
117
- if (fileExists) consola$1.info(`[graphql:${service.name}] Using cached schema from: ${schemaFilePath}`);
118
- }
123
+ else if (fileExists && hasLocalSchemas) {
124
+ const localFiles = schemas.filter((schema) => !isUrl(schema));
125
+ let sourceIsNewer = false;
126
+ for (const localFile of localFiles) if (existsSync(localFile)) {
127
+ const { statSync } = await import("node:fs");
128
+ const sourceStats = statSync(localFile);
129
+ const cachedStats = statSync(schemaFilePath);
130
+ if (sourceStats.mtime > cachedStats.mtime) {
131
+ sourceIsNewer = true;
132
+ break;
133
+ }
134
+ }
135
+ if (!sourceIsNewer) shouldDownload = false;
136
+ }
137
+ } else if (downloadMode === true || downloadMode === "once") shouldDownload = !fileExists;
119
138
  if (shouldDownload) {
120
- consola$1.info(`[graphql:${service.name}] Downloading schema to: ${schemaFilePath}`);
121
- const schema = loadSchemaSync(schemas, {
122
- loaders: [new UrlLoader()],
123
- ...Object.keys(headers).length > 0 && { headers }
124
- });
125
- const schemaString = printSchemaWithDirectives(schema);
126
- mkdirSync(dirname(schemaFilePath), { recursive: true });
127
- writeFileSync(schemaFilePath, schemaString, "utf-8");
128
- consola$1.success(`[graphql:${service.name}] Schema downloaded and saved successfully`);
139
+ if (hasUrlSchemas && hasLocalSchemas) {
140
+ const schema = loadSchemaSync(schemas, {
141
+ loaders: [new GraphQLFileLoader(), new UrlLoader()],
142
+ ...Object.keys(headers).length > 0 && { headers }
143
+ });
144
+ const schemaString = printSchemaWithDirectives(schema);
145
+ mkdirSync(dirname(schemaFilePath), { recursive: true });
146
+ writeFileSync(schemaFilePath, schemaString, "utf-8");
147
+ } else if (hasUrlSchemas) {
148
+ const schema = loadSchemaSync(schemas, {
149
+ loaders: [new UrlLoader()],
150
+ ...Object.keys(headers).length > 0 && { headers }
151
+ });
152
+ const schemaString = printSchemaWithDirectives(schema);
153
+ mkdirSync(dirname(schemaFilePath), { recursive: true });
154
+ writeFileSync(schemaFilePath, schemaString, "utf-8");
155
+ } else if (hasLocalSchemas) {
156
+ const schema = loadSchemaSync(schemas, { loaders: [new GraphQLFileLoader()] });
157
+ const schemaString = printSchemaWithDirectives(schema);
158
+ mkdirSync(dirname(schemaFilePath), { recursive: true });
159
+ writeFileSync(schemaFilePath, schemaString, "utf-8");
160
+ }
129
161
  }
130
162
  return schemaFilePath;
131
163
  } catch (error) {
132
- consola$1.error(`[graphql:${service.name}] Failed to download schema:`, error);
164
+ consola$1.error(`[graphql:${service.name}] Failed to download/copy schema:`, error);
133
165
  return void 0;
134
166
  }
135
167
  }
@@ -143,13 +175,11 @@ async function loadGraphQLDocuments(patterns) {
143
175
  }
144
176
  }
145
177
  async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName) {
146
- if (docs.length === 0) {
147
- const serviceLabel$1 = serviceName ? `:${serviceName}` : "";
148
- consola$1.info(`[graphql${serviceLabel$1}] No client GraphQL files found. Skipping client type generation.`);
178
+ if (docs.length === 0 && !serviceName) {
179
+ consola$1.info("No client GraphQL files found. Skipping client type generation.");
149
180
  return false;
150
181
  }
151
182
  const serviceLabel = serviceName ? `:${serviceName}` : "";
152
- consola$1.info(`[graphql${serviceLabel}] Found ${docs.length} client GraphQL documents`);
153
183
  const defaultConfig = {
154
184
  emitLegacyCommonJSImports: false,
155
185
  useTypeImports: true,
@@ -178,6 +208,48 @@ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, ou
178
208
  const mergedConfig = defu$1(defaultConfig, config);
179
209
  const mergedSdkConfig = defu$1(mergedConfig, sdkConfig);
180
210
  try {
211
+ if (docs.length === 0) {
212
+ const output$1 = await codegen({
213
+ filename: outputPath || "client-types.generated.ts",
214
+ schema: parse(printSchemaWithDirectives(schema)),
215
+ documents: [],
216
+ config: mergedConfig,
217
+ plugins: [{ pluginContent: {} }, { typescript: {} }],
218
+ pluginMap: {
219
+ pluginContent: { plugin: pluginContent },
220
+ typescript: { plugin }
221
+ }
222
+ });
223
+ const sdkContent$1 = `// THIS FILE IS GENERATED, DO NOT EDIT!
224
+ /* eslint-disable eslint-comments/no-unlimited-disable */
225
+ /* tslint:disable */
226
+ /* eslint-disable */
227
+ /* prettier-ignore */
228
+
229
+ import type { GraphQLResolveInfo } from 'graphql'
230
+ export type RequireFields<T, K extends keyof T> = Omit<T, K> & { [P in K]-?: NonNullable<T[P]> }
231
+
232
+ export interface Requester<C = {}, E = unknown> {
233
+ <R, V>(doc: string, vars?: V, options?: C): Promise<R> | AsyncIterable<R>
234
+ }
235
+
236
+ export type Sdk = {
237
+ request: <R, V = Record<string, any>>(document: string, variables?: V) => Promise<R>
238
+ }
239
+
240
+ export function getSdk(requester: Requester): Sdk {
241
+ return {
242
+ request: <R, V = Record<string, any>>(document: string, variables?: V): Promise<R> => {
243
+ return requester<R, V>(document, variables)
244
+ }
245
+ }
246
+ }
247
+ `;
248
+ return {
249
+ types: output$1,
250
+ sdk: sdkContent$1
251
+ };
252
+ }
181
253
  const output = await codegen({
182
254
  filename: outputPath || "client-types.generated.ts",
183
255
  schema: parse(printSchemaWithDirectives(schema)),
@@ -116,7 +116,8 @@ async function serverTypeGeneration(app) {
116
116
  }
117
117
  async function clientTypeGeneration(nitro) {
118
118
  try {
119
- await generateMainClientTypes(nitro);
119
+ const hasServerSchema = nitro.scanSchemas && nitro.scanSchemas.length > 0;
120
+ if (hasServerSchema) await generateMainClientTypes(nitro);
120
121
  if (nitro.options.graphql?.externalServices?.length) await generateExternalServicesTypes(nitro);
121
122
  } catch (error) {
122
123
  consola.error("Client schema generation error:", error);
@@ -171,7 +172,9 @@ async function generateMainClientTypes(nitro) {
171
172
  mkdirSync(defaultServiceDir, { recursive: true });
172
173
  writeFileSync(sdkTypesPath, types.sdk, "utf-8");
173
174
  if (nitro.options.framework?.name === "nuxt") {
174
- generateNuxtOfetchClient(nitro.graphql.clientDir, "default");
175
+ const appGraphqlDir = resolve(nitro.options.rootDir, "app/graphql");
176
+ const hasUserGraphqlSetup = existsSync(appGraphqlDir);
177
+ if (!hasUserGraphqlSetup) generateNuxtOfetchClient(nitro.graphql.clientDir, "default");
175
178
  const externalServices = nitro.options.graphql?.externalServices || [];
176
179
  generateGraphQLIndexFile(nitro.graphql.clientDir, externalServices);
177
180
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nitro-graphql",
3
3
  "type": "module",
4
- "version": "1.2.0",
4
+ "version": "1.2.2",
5
5
  "description": "GraphQL integration for Nitro",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,