nitro-graphql 2.0.0-beta.24 → 2.0.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/define.d.mts CHANGED
@@ -43,19 +43,19 @@ declare function defineSchema<T extends Partial<Record<keyof ResolversTypes, Sta
43
43
  * ```typescript
44
44
  * export const userResolvers = defineResolver({
45
45
  * Query: {
46
- * user: async (_, { id }, context) => {
46
+ * user: async (parent, { id }, context) => {
47
47
  * return await context.storage.getItem(`user:${id}`)
48
48
  * }
49
49
  * },
50
50
  * Mutation: {
51
- * createUser: async (_, { input }, context) => {
51
+ * createUser: async (parent, { input }, context) => {
52
52
  * const user = { id: generateId(), ...input }
53
53
  * await context.storage.setItem(`user:${user.id}`, user)
54
54
  * return user
55
55
  * }
56
56
  * },
57
57
  * User: {
58
- * fullName: (parent) => `${parent.firstName} ${parent.lastName}`
58
+ * fullName: (parent, args, context) => `${parent.firstName} ${parent.lastName}`
59
59
  * }
60
60
  * })
61
61
  * ```
@@ -74,10 +74,10 @@ declare function defineResolver(resolvers: Resolvers): Resolvers;
74
74
  * @example
75
75
  * ```typescript
76
76
  * export const userQueries = defineQuery({
77
- * user: async (_, { id }, context) => {
77
+ * user: async (parent, { id }, context) => {
78
78
  * return await fetchUser(id)
79
79
  * },
80
- * users: async (_, __, context) => {
80
+ * users: async (parent, args, context) => {
81
81
  * return await fetchAllUsers()
82
82
  * }
83
83
  * })
@@ -100,14 +100,14 @@ declare function defineQuery(resolvers?: Resolvers['Query']): Resolvers;
100
100
  * @example
101
101
  * ```typescript
102
102
  * export const userMutations = defineMutation({
103
- * createUser: async (_, { input }, context) => {
103
+ * createUser: async (parent, { input }, context) => {
104
104
  * const user = await context.db.users.create(input)
105
105
  * return user
106
106
  * },
107
- * updateUser: async (_, { id, input }, context) => {
107
+ * updateUser: async (parent, { id, input }, context) => {
108
108
  * return await context.db.users.update(id, input)
109
109
  * },
110
- * deleteUser: async (_, { id }, context) => {
110
+ * deleteUser: async (parent, { id }, context) => {
111
111
  * return await context.db.users.delete(id)
112
112
  * }
113
113
  * })
@@ -133,13 +133,13 @@ declare function defineMutation(resolvers?: Resolvers['Mutation']): Resolvers;
133
133
  *
134
134
  * export const messageSubscriptions = defineSubscription({
135
135
  * messageAdded: {
136
- * subscribe: async function* (_, { channelId }, context) {
136
+ * subscribe: async function* (parent, { channelId }, context) {
137
137
  * const pubsub = context.pubsub
138
138
  * yield* pubsub.subscribe(`channel:${channelId}`)
139
139
  * }
140
140
  * },
141
141
  * userStatusChanged: {
142
- * subscribe: async (_, __, context) => {
142
+ * subscribe: async (parent, args, context) => {
143
143
  * return new Repeater(async (push, stop) => {
144
144
  * // Real-time subscription logic
145
145
  * })
@@ -197,6 +197,8 @@ declare function defineType(resolvers: Resolvers): Resolvers;
197
197
  *
198
198
  * @example
199
199
  * ```typescript
200
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
201
+ *
200
202
  * // GraphQL Yoga configuration
201
203
  * export default defineGraphQLConfig({
202
204
  * schema: {
@@ -208,10 +210,10 @@ declare function defineType(resolvers: Resolvers): Resolvers;
208
210
  * db: getDatabase()
209
211
  * }
210
212
  * },
211
- * yoga: {
212
- * graphiql: true,
213
- * maskedErrors: false
214
- * }
213
+ * maskedErrors: {
214
+ * maskError: createDefaultMaskError()
215
+ * },
216
+ * graphiql: true
215
217
  * })
216
218
  * ```
217
219
  *
package/dist/define.mjs CHANGED
@@ -39,19 +39,19 @@ function defineSchema(config) {
39
39
  * ```typescript
40
40
  * export const userResolvers = defineResolver({
41
41
  * Query: {
42
- * user: async (_, { id }, context) => {
42
+ * user: async (parent, { id }, context) => {
43
43
  * return await context.storage.getItem(`user:${id}`)
44
44
  * }
45
45
  * },
46
46
  * Mutation: {
47
- * createUser: async (_, { input }, context) => {
47
+ * createUser: async (parent, { input }, context) => {
48
48
  * const user = { id: generateId(), ...input }
49
49
  * await context.storage.setItem(`user:${user.id}`, user)
50
50
  * return user
51
51
  * }
52
52
  * },
53
53
  * User: {
54
- * fullName: (parent) => `${parent.firstName} ${parent.lastName}`
54
+ * fullName: (parent, args, context) => `${parent.firstName} ${parent.lastName}`
55
55
  * }
56
56
  * })
57
57
  * ```
@@ -72,10 +72,10 @@ function defineResolver(resolvers) {
72
72
  * @example
73
73
  * ```typescript
74
74
  * export const userQueries = defineQuery({
75
- * user: async (_, { id }, context) => {
75
+ * user: async (parent, { id }, context) => {
76
76
  * return await fetchUser(id)
77
77
  * },
78
- * users: async (_, __, context) => {
78
+ * users: async (parent, args, context) => {
79
79
  * return await fetchAllUsers()
80
80
  * }
81
81
  * })
@@ -100,14 +100,14 @@ function defineQuery(resolvers = {}) {
100
100
  * @example
101
101
  * ```typescript
102
102
  * export const userMutations = defineMutation({
103
- * createUser: async (_, { input }, context) => {
103
+ * createUser: async (parent, { input }, context) => {
104
104
  * const user = await context.db.users.create(input)
105
105
  * return user
106
106
  * },
107
- * updateUser: async (_, { id, input }, context) => {
107
+ * updateUser: async (parent, { id, input }, context) => {
108
108
  * return await context.db.users.update(id, input)
109
109
  * },
110
- * deleteUser: async (_, { id }, context) => {
110
+ * deleteUser: async (parent, { id }, context) => {
111
111
  * return await context.db.users.delete(id)
112
112
  * }
113
113
  * })
@@ -135,13 +135,13 @@ function defineMutation(resolvers = {}) {
135
135
  *
136
136
  * export const messageSubscriptions = defineSubscription({
137
137
  * messageAdded: {
138
- * subscribe: async function* (_, { channelId }, context) {
138
+ * subscribe: async function* (parent, { channelId }, context) {
139
139
  * const pubsub = context.pubsub
140
140
  * yield* pubsub.subscribe(`channel:${channelId}`)
141
141
  * }
142
142
  * },
143
143
  * userStatusChanged: {
144
- * subscribe: async (_, __, context) => {
144
+ * subscribe: async (parent, args, context) => {
145
145
  * return new Repeater(async (push, stop) => {
146
146
  * // Real-time subscription logic
147
147
  * })
@@ -203,6 +203,8 @@ function defineType(resolvers) {
203
203
  *
204
204
  * @example
205
205
  * ```typescript
206
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
207
+ *
206
208
  * // GraphQL Yoga configuration
207
209
  * export default defineGraphQLConfig({
208
210
  * schema: {
@@ -214,10 +216,10 @@ function defineType(resolvers) {
214
216
  * db: getDatabase()
215
217
  * }
216
218
  * },
217
- * yoga: {
218
- * graphiql: true,
219
- * maskedErrors: false
220
- * }
219
+ * maskedErrors: {
220
+ * maskError: createDefaultMaskError()
221
+ * },
222
+ * graphiql: true
221
223
  * })
222
224
  * ```
223
225
  *
package/dist/rollup.mjs CHANGED
@@ -94,8 +94,8 @@ async function rollupConfig(app) {
94
94
  }
95
95
  });
96
96
  app.hooks.hook("dev:reload", async () => {
97
- await serverTypeGeneration(app);
98
- await clientTypeGeneration(app);
97
+ await serverTypeGeneration(app, { silent: true });
98
+ await clientTypeGeneration(app, { silent: true });
99
99
  });
100
100
  }
101
101
  function virtualSchemas(app) {
@@ -1,6 +1,6 @@
1
- import * as h33 from "h3";
1
+ import * as h30 from "h3";
2
2
 
3
3
  //#region src/routes/apollo-server.d.ts
4
- declare const _default: h33.EventHandlerWithFetch<h33.EventHandlerRequest, Promise<any>>;
4
+ declare const _default: h30.EventHandlerWithFetch<h30.EventHandlerRequest, Promise<any>>;
5
5
  //#endregion
6
6
  export { _default as default };
@@ -84,6 +84,10 @@ var graphql_yoga_default = defineEventHandler(async (event) => {
84
84
  renderGraphiQL: () => apolloSandboxHtml
85
85
  }, importedConfig));
86
86
  const response = await yoga.handleRequest(event.req, event);
87
+ if (event.res.statusCode && event.res.statusCode !== 200) return new Response(response.body, {
88
+ ...response,
89
+ status: event.res.statusCode
90
+ });
87
91
  return new Response(response.body, response);
88
92
  });
89
93
 
@@ -1,7 +1,7 @@
1
- import * as h30 from "h3";
1
+ import * as h33 from "h3";
2
2
 
3
3
  //#region src/routes/health.d.ts
4
- declare const _default: h30.EventHandlerWithFetch<h30.EventHandlerRequest, Promise<{
4
+ declare const _default: h33.EventHandlerWithFetch<h33.EventHandlerRequest, Promise<{
5
5
  status: string;
6
6
  message: string;
7
7
  timestamp: string;
package/dist/setup.mjs CHANGED
@@ -12,20 +12,21 @@ import consola from "consola";
12
12
  import { dirname, join, relative, resolve } from "pathe";
13
13
 
14
14
  //#region src/setup.ts
15
+ const logger = consola.withTag("nitro-graphql");
15
16
  /**
16
17
  * Shared setup logic for nitro-graphql module
17
18
  * Used by both the direct Nitro module export and the Vite plugin's nitro: hook
18
19
  */
19
20
  async function setupNitroGraphQL(nitro) {
20
- if (!nitro.options.graphql?.framework) consola.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
21
+ if (!nitro.options.graphql?.framework) logger.warn("No GraphQL framework specified. Please set graphql.framework to \"graphql-yoga\" or \"apollo-server\".");
21
22
  if (nitro.options.graphql?.externalServices?.length) {
22
23
  const validationErrors = validateExternalServices(nitro.options.graphql.externalServices);
23
24
  if (validationErrors.length > 0) {
24
- consola.error("External services configuration errors:");
25
- for (const error of validationErrors) consola.error(` - ${error}`);
25
+ logger.error("External services configuration errors:");
26
+ for (const error of validationErrors) logger.error(` - ${error}`);
26
27
  throw new Error("Invalid external services configuration");
27
28
  }
28
- consola.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
29
+ logger.info(`Configured ${nitro.options.graphql.externalServices.length} external GraphQL services`);
29
30
  }
30
31
  const { getDefaultPaths } = await import("./utils/path-resolver.mjs");
31
32
  const defaultPaths = getDefaultPaths(nitro);
@@ -59,7 +60,7 @@ async function setupNitroGraphQL(nitro) {
59
60
  },
60
61
  playground: true
61
62
  });
62
- if (nitro.options.graphql?.federation?.enabled) consola.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
63
+ if (nitro.options.graphql?.federation?.enabled) logger.info(`Apollo Federation enabled for service: ${nitro.options.graphql.federation.serviceName || "unnamed"}`);
63
64
  const graphqlBuildDir = resolve(nitro.options.buildDir, "graphql");
64
65
  nitro.graphql.buildDir = graphqlBuildDir;
65
66
  const watchDirs = [];
@@ -95,11 +96,20 @@ async function setupNitroGraphQL(nitro) {
95
96
  ignoreInitial: true,
96
97
  ignored: [...nitro.options.ignore, ...generateLayerIgnorePatterns()]
97
98
  }).on("all", async (_, path) => {
98
- if (path.endsWith(".graphql") || path.endsWith(".gql")) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql")) {
99
- await serverTypeGeneration(nitro);
100
- await clientTypeGeneration(nitro);
99
+ const isGraphQLFile = path.endsWith(".graphql") || path.endsWith(".gql");
100
+ const isResolverFile = path.endsWith(".resolver.ts") || path.endsWith(".resolver.js");
101
+ const isDirectiveFile = path.endsWith(".directive.ts") || path.endsWith(".directive.js");
102
+ if (isGraphQLFile || isResolverFile || isDirectiveFile) if (path.includes(nitro.graphql.serverDir) || path.includes("server/graphql") || path.includes("server\\graphql") || isResolverFile || isDirectiveFile) {
103
+ await scanResolvers(nitro).then((r) => nitro.scanResolvers = r);
104
+ await scanDirectives(nitro).then((d) => nitro.scanDirectives = d);
105
+ logger.success("Types regenerated");
106
+ await serverTypeGeneration(nitro, { silent: true });
107
+ await clientTypeGeneration(nitro, { silent: true });
101
108
  await nitro.hooks.callHook("dev:reload");
102
- } else await clientTypeGeneration(nitro);
109
+ } else {
110
+ logger.success("Types regenerated");
111
+ await clientTypeGeneration(nitro, { silent: true });
112
+ }
103
113
  });
104
114
  nitro.hooks.hook("close", () => {
105
115
  watcher.close();
@@ -111,33 +121,17 @@ async function setupNitroGraphQL(nitro) {
111
121
  const directives = await scanDirectives(nitro);
112
122
  nitro.scanDirectives = directives;
113
123
  await generateDirectiveSchemas(nitro, directives);
124
+ let hasShownInitialLogs = false;
114
125
  nitro.hooks.hook("dev:start", async () => {
115
- const schemas = await scanSchemas(nitro);
116
- nitro.scanSchemas = schemas;
126
+ nitro.scanSchemas = await scanSchemas(nitro);
117
127
  const resolvers = await scanResolvers(nitro);
118
128
  nitro.scanResolvers = resolvers;
119
129
  const directives$1 = await scanDirectives(nitro);
120
130
  nitro.scanDirectives = directives$1;
121
131
  await generateDirectiveSchemas(nitro, directives$1);
122
- const docs = await scanDocs(nitro);
123
- nitro.scanDocuments = docs;
124
- if (nitro.options.dev) {
125
- consola.box({
126
- title: "Nitro GraphQL",
127
- message: [
128
- `Framework: ${nitro.options.graphql?.framework || "Not configured"}`,
129
- `Schemas: ${schemas.length}`,
130
- `Resolvers: ${resolvers.length}`,
131
- `Directives: ${directives$1.length}`,
132
- `Documents: ${docs.length}`,
133
- "",
134
- "Debug Dashboard: /_nitro/graphql/debug"
135
- ].join("\n"),
136
- style: {
137
- borderColor: "cyan",
138
- borderStyle: "rounded"
139
- }
140
- });
132
+ nitro.scanDocuments = await scanDocs(nitro);
133
+ if (nitro.options.dev && !hasShownInitialLogs) {
134
+ hasShownInitialLogs = true;
141
135
  if (resolvers.length > 0) {
142
136
  const totalExports = resolvers.reduce((sum, r) => sum + r.imports.length, 0);
143
137
  const typeCount = {
@@ -156,16 +150,16 @@ async function setupNitroGraphQL(nitro) {
156
150
  if (typeCount.type > 0) breakdown.push(`${typeCount.type} type`);
157
151
  if (typeCount.subscription > 0) breakdown.push(`${typeCount.subscription} subscription`);
158
152
  if (typeCount.directive > 0) breakdown.push(`${typeCount.directive} directive`);
159
- if (breakdown.length > 0) consola.success(`[nitro-graphql] ${totalExports} resolver export(s): ${breakdown.join(", ")}`);
160
- } else consola.warn("[nitro-graphql] No resolvers found. Check /_nitro/graphql/debug for details.");
153
+ if (breakdown.length > 0) logger.success(`${totalExports} resolver export(s): ${breakdown.join(", ")}`);
154
+ } else logger.warn("No resolvers found. Check /_nitro/graphql/debug for details.");
161
155
  }
162
156
  });
163
157
  await rollupConfig(nitro);
164
158
  await serverTypeGeneration(nitro);
165
- await clientTypeGeneration(nitro);
159
+ await clientTypeGeneration(nitro, { isInitial: true });
166
160
  nitro.hooks.hook("close", async () => {
167
- await serverTypeGeneration(nitro);
168
- await clientTypeGeneration(nitro);
161
+ await serverTypeGeneration(nitro, { silent: true });
162
+ await clientTypeGeneration(nitro, { silent: true });
169
163
  });
170
164
  const runtime = fileURLToPath(new URL("routes", import.meta.url));
171
165
  const methods = [
@@ -188,14 +182,11 @@ async function setupNitroGraphQL(nitro) {
188
182
  handler: join(runtime, "health"),
189
183
  method: "GET"
190
184
  });
191
- if (nitro.options.dev) {
192
- nitro.options.handlers.push({
193
- route: "/_nitro/graphql/debug",
194
- handler: join(runtime, "debug"),
195
- method: "GET"
196
- });
197
- consola.info("[nitro-graphql] Debug dashboard available at: /_nitro/graphql/debug");
198
- }
185
+ if (nitro.options.dev) nitro.options.handlers.push({
186
+ route: "/_nitro/graphql/debug",
187
+ handler: join(runtime, "debug"),
188
+ method: "GET"
189
+ });
199
190
  if (nitro.options.imports) {
200
191
  nitro.options.imports.presets ??= [];
201
192
  nitro.options.imports.presets.push({
@@ -380,10 +371,10 @@ declare module 'nitro/h3' {
380
371
  export {}
381
372
  `, "server context.d.ts");
382
373
  if (existsSync(join(nitro.graphql.serverDir, "context.ts"))) {
383
- consola.warn("nitro-graphql: Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
384
- consola.info("The context file should now be context.d.ts instead of context.ts");
374
+ logger.warn("Found context.ts file. Please rename it to context.d.ts for type-only definitions.");
375
+ logger.info("The context file should now be context.d.ts instead of context.ts");
385
376
  }
386
- } else consola.info("[nitro-graphql] Scaffold file generation is disabled (library mode)");
377
+ } else logger.info("Scaffold file generation is disabled (library mode)");
387
378
  }
388
379
 
389
380
  //#endregion
@@ -8,7 +8,18 @@ import { NPMConfig } from "#graphql/server";
8
8
  type Flatten<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
9
9
  type DefineServerConfig<T extends NPMConfig = NPMConfig> = T['framework'] extends 'graphql-yoga' ? Partial<YogaServerOptions<H3Event, Partial<H3Event>>> : T['framework'] extends 'apollo-server' ? Partial<ApolloServerOptions<H3Event>> : Partial<YogaServerOptions<H3Event, Partial<H3Event>>> | Partial<ApolloServerOptions<H3Event>>;
10
10
  type DirectiveLocationName = 'QUERY' | 'MUTATION' | 'SUBSCRIPTION' | 'FIELD' | 'FRAGMENT_DEFINITION' | 'FRAGMENT_SPREAD' | 'INLINE_FRAGMENT' | 'VARIABLE_DEFINITION' | 'SCHEMA' | 'SCALAR' | 'OBJECT' | 'FIELD_DEFINITION' | 'ARGUMENT_DEFINITION' | 'INTERFACE' | 'UNION' | 'ENUM' | 'ENUM_VALUE' | 'INPUT_OBJECT' | 'INPUT_FIELD_DEFINITION';
11
+ type GraphQLScalarType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID' | 'JSON' | 'DateTime';
12
+ type GraphQLBaseType = GraphQLScalarType | (string & {});
11
13
  type GraphQLArgumentType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID' | 'JSON' | 'DateTime' | 'String!' | 'Int!' | 'Float!' | 'Boolean!' | 'ID!' | 'JSON!' | 'DateTime!' | '[String]' | '[String!]' | '[String]!' | '[String!]!' | '[Int]' | '[Int!]' | '[Int]!' | '[Int!]!' | '[Float]' | '[Float!]' | '[Float]!' | '[Float!]!' | '[Boolean]' | '[Boolean!]' | '[Boolean]!' | '[Boolean!]!' | '[ID]' | '[ID!]' | '[ID]!' | '[ID!]!' | '[JSON]' | '[JSON!]' | '[JSON]!' | '[JSON!]!' | '[DateTime]' | '[DateTime!]' | '[DateTime]!' | '[DateTime!]!' | (string & {});
14
+ interface DirectiveArgument<T extends GraphQLArgumentType = GraphQLArgumentType> {
15
+ /**
16
+ * GraphQL type for the argument
17
+ * @example 'String', 'Int!', '[String!]!', 'DateTime', 'JSON'
18
+ */
19
+ type: T;
20
+ defaultValue?: any;
21
+ description?: string;
22
+ }
12
23
  interface DirectiveArg {
13
24
  type: GraphQLArgumentType;
14
25
  defaultValue?: any;
@@ -35,4 +46,4 @@ interface DefineDirectiveConfig {
35
46
  transformer?: (schema: GraphQLSchema) => GraphQLSchema;
36
47
  }
37
48
  //#endregion
38
- export { DefineDirectiveConfig, DefineServerConfig, DirectiveDefinition, Flatten };
49
+ export { DefineDirectiveConfig, DefineServerConfig, DirectiveArgument, DirectiveDefinition, Flatten, GraphQLArgumentType, GraphQLBaseType, GraphQLScalarType };
@@ -0,0 +1 @@
1
+ export { };
@@ -243,4 +243,4 @@ interface NitroGraphQLOptions {
243
243
  paths?: PathsConfig;
244
244
  }
245
245
  //#endregion
246
- export { ClientUtilsConfig, CodegenClientConfig, ExternalGraphQLService, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, ScaffoldConfig, SdkConfig, TypesConfig };
246
+ export { ClientUtilsConfig, CodegenClientConfig, CodegenServerConfig, ExternalGraphQLService, ExternalServicePaths, FederationConfig, FileGenerationConfig, GenImport, GenericSdkConfig, NitroGraphQLOptions, PathsConfig, ScaffoldConfig, SdkConfig, StandardSchemaV1, TypesConfig };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -23,7 +23,10 @@ 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, virtualTypesPath?: string): Promise<false | {
26
+ declare function generateClientTypes(schema: GraphQLSchema, docs: Source[], config?: CodegenClientConfig, sdkConfig?: GenericSdkConfig, outputPath?: string, serviceName?: string, virtualTypesPath?: string, options?: {
27
+ silent?: boolean;
28
+ isInitial?: boolean;
29
+ }): Promise<false | {
27
30
  types: string;
28
31
  sdk: string;
29
32
  }>;
@@ -165,9 +165,9 @@ async function loadGraphQLDocuments(patterns) {
165
165
  else throw e;
166
166
  }
167
167
  }
168
- async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath) {
168
+ async function generateClientTypes(schema, docs, config = {}, sdkConfig = {}, outputPath, serviceName, virtualTypesPath, options = {}) {
169
169
  if (docs.length === 0 && !serviceName) {
170
- consola$1.info("No client GraphQL files found. Skipping client type generation.");
170
+ if (!options.silent && options.isInitial) consola$1.info("No client GraphQL files found. Skipping client type generation.");
171
171
  return false;
172
172
  }
173
173
  const serviceLabel = serviceName ? `:${serviceName}` : "";
@@ -0,0 +1,73 @@
1
+ //#region src/utils/errors.d.ts
2
+ interface MaskErrorOptions {
3
+ /**
4
+ * Default HTTP status code for validation errors (ZodError)
5
+ * @default 400
6
+ */
7
+ validationStatusCode?: number;
8
+ /**
9
+ * Default HTTP status code for HTTP errors when status is not provided
10
+ * @default 500
11
+ */
12
+ defaultHttpStatusCode?: number;
13
+ }
14
+ /**
15
+ * Default error masking function for GraphQL Yoga
16
+ * Handles common error types like ZodError and HTTPError
17
+ *
18
+ * @param options - Configuration options for error handling
19
+ *
20
+ * @example Basic usage
21
+ * ```ts
22
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
23
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
24
+ *
25
+ * export default defineGraphQLConfig({
26
+ * maskedErrors: {
27
+ * maskError: createDefaultMaskError()
28
+ * }
29
+ * })
30
+ * ```
31
+ *
32
+ * @example Custom status codes
33
+ * ```ts
34
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
35
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
36
+ *
37
+ * export default defineGraphQLConfig({
38
+ * maskedErrors: {
39
+ * maskError: createDefaultMaskError({
40
+ * validationStatusCode: 422, // Use 422 for validation errors
41
+ * defaultHttpStatusCode: 500 // Use 500 for unknown HTTP errors
42
+ * })
43
+ * }
44
+ * })
45
+ * ```
46
+ *
47
+ * @example Custom error handling with fallback to default
48
+ * ```ts
49
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
50
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
51
+ *
52
+ * const defaultMaskError = createDefaultMaskError()
53
+ *
54
+ * export default defineGraphQLConfig({
55
+ * maskedErrors: {
56
+ * maskError: (error: unknown) => {
57
+ * // Handle custom errors first
58
+ * if (error instanceof MyCustomError) {
59
+ * return new GraphQLError(error.message, {
60
+ * extensions: { code: 'CUSTOM_ERROR' }
61
+ * })
62
+ * }
63
+ *
64
+ * // Fall back to default handling
65
+ * return defaultMaskError(error)
66
+ * }
67
+ * }
68
+ * })
69
+ * ```
70
+ */
71
+ declare function createDefaultMaskError(options?: MaskErrorOptions): (error: unknown) => Error;
72
+ //#endregion
73
+ export { MaskErrorOptions, createDefaultMaskError };
@@ -0,0 +1,89 @@
1
+ import { GraphQLError } from "graphql";
2
+
3
+ //#region src/utils/errors.ts
4
+ /**
5
+ * Default error masking function for GraphQL Yoga
6
+ * Handles common error types like ZodError and HTTPError
7
+ *
8
+ * @param options - Configuration options for error handling
9
+ *
10
+ * @example Basic usage
11
+ * ```ts
12
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
13
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
14
+ *
15
+ * export default defineGraphQLConfig({
16
+ * maskedErrors: {
17
+ * maskError: createDefaultMaskError()
18
+ * }
19
+ * })
20
+ * ```
21
+ *
22
+ * @example Custom status codes
23
+ * ```ts
24
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
25
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
26
+ *
27
+ * export default defineGraphQLConfig({
28
+ * maskedErrors: {
29
+ * maskError: createDefaultMaskError({
30
+ * validationStatusCode: 422, // Use 422 for validation errors
31
+ * defaultHttpStatusCode: 500 // Use 500 for unknown HTTP errors
32
+ * })
33
+ * }
34
+ * })
35
+ * ```
36
+ *
37
+ * @example Custom error handling with fallback to default
38
+ * ```ts
39
+ * import { defineGraphQLConfig } from 'nitro-graphql/define'
40
+ * import { createDefaultMaskError } from 'nitro-graphql/utils'
41
+ *
42
+ * const defaultMaskError = createDefaultMaskError()
43
+ *
44
+ * export default defineGraphQLConfig({
45
+ * maskedErrors: {
46
+ * maskError: (error: unknown) => {
47
+ * // Handle custom errors first
48
+ * if (error instanceof MyCustomError) {
49
+ * return new GraphQLError(error.message, {
50
+ * extensions: { code: 'CUSTOM_ERROR' }
51
+ * })
52
+ * }
53
+ *
54
+ * // Fall back to default handling
55
+ * return defaultMaskError(error)
56
+ * }
57
+ * }
58
+ * })
59
+ * ```
60
+ */
61
+ function createDefaultMaskError(options) {
62
+ const validationStatusCode = options?.validationStatusCode ?? 400;
63
+ const defaultHttpStatusCode = options?.defaultHttpStatusCode ?? 500;
64
+ return (error) => {
65
+ if (error && typeof error === "object" && "originalError" in error) {
66
+ const graphqlError = error;
67
+ if (graphqlError.originalError && typeof graphqlError.originalError === "object" && "issues" in graphqlError.originalError && Array.isArray(graphqlError.originalError.issues)) return new GraphQLError("Validation failed", { extensions: {
68
+ code: "BAD_USER_INPUT",
69
+ validationErrors: graphqlError.originalError.issues.map((issue) => ({
70
+ field: issue.path.join("."),
71
+ message: issue.message
72
+ })),
73
+ http: { status: validationStatusCode }
74
+ } });
75
+ if (graphqlError.originalError && typeof graphqlError.originalError === "object" && "statusCode" in graphqlError.originalError && "statusMessage" in graphqlError.originalError) {
76
+ const httpError = graphqlError.originalError;
77
+ const statusCode = httpError.statusCode ?? defaultHttpStatusCode;
78
+ return new GraphQLError(httpError.statusMessage || httpError.message || "Internal Server Error", { extensions: {
79
+ code: statusCode,
80
+ http: { status: statusCode }
81
+ } });
82
+ }
83
+ }
84
+ return error instanceof Error ? error : new Error(String(error));
85
+ };
86
+ }
87
+
88
+ //#endregion
89
+ export { createDefaultMaskError };
@@ -1,5 +1,6 @@
1
1
  import { GenImport } from "../types/index.mjs";
2
2
  import { directiveParser, generateDirectiveSchema, generateDirectiveSchemas } from "./directive-parser.mjs";
3
+ import { createDefaultMaskError } from "./errors.mjs";
3
4
  import { Nitro } from "nitro/types";
4
5
 
5
6
  //#region src/utils/index.d.ts
@@ -36,4 +37,4 @@ declare function scanExternalServiceDocs(nitro: Nitro, serviceName: string, patt
36
37
  */
37
38
  declare function validateExternalServices(services: unknown[]): string[];
38
39
  //#endregion
39
- export { GLOB_SCAN_PATTERN, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };
40
+ export { GLOB_SCAN_PATTERN, createDefaultMaskError, directiveParser, generateDirectiveSchema, generateDirectiveSchemas, generateLayerIgnorePatterns, getImportId, getLayerAppDirectories, getLayerDirectories, getLayerServerDirectories, relativeWithDot, scanDirectives, scanDocs, scanExternalServiceDocs, scanGraphql, scanResolvers, scanSchemas, validateExternalServices };