hono-openapi 1.2.0 → 1.3.1

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/index.cjs CHANGED
@@ -252,8 +252,10 @@ async function generateSpecs(hono, options = DEFAULT_OPTIONS, c) {
252
252
  }
253
253
  }
254
254
  }
255
+ const { components: resolvedDocComponents } = _documentation.components?.responses ? await resolveResponseSchemas(_documentation.components.responses) : { components: {} };
255
256
  const components = mergeComponentsObjects(
256
257
  _documentation.components,
258
+ resolvedDocComponents,
257
259
  ctx.components
258
260
  );
259
261
  return {
@@ -325,7 +327,6 @@ function getHiddenValue(options) {
325
327
  }
326
328
  async function getSpec(middlewareHandler, defaultOptions) {
327
329
  if ("spec" in middlewareHandler) {
328
- let components = {};
329
330
  const tmp = {
330
331
  ...defaultOptions,
331
332
  ...middlewareHandler.spec,
@@ -334,25 +335,10 @@ async function getSpec(middlewareHandler, defaultOptions) {
334
335
  ...middlewareHandler.spec.responses
335
336
  }
336
337
  };
338
+ let components = {};
337
339
  if (tmp.responses) {
338
- for (const key of Object.keys(tmp.responses)) {
339
- const response = tmp.responses[key];
340
- if (!response || !("content" in response)) continue;
341
- for (const contentKey of Object.keys(response.content ?? {})) {
342
- const raw = response.content?.[contentKey];
343
- if (!raw) continue;
344
- if (raw.schema && "toOpenAPISchema" in raw.schema) {
345
- const result2 = await raw.schema.toOpenAPISchema();
346
- raw.schema = result2.schema;
347
- if (result2.components) {
348
- components = mergeComponentsObjects(
349
- components,
350
- result2.components
351
- );
352
- }
353
- }
354
- }
355
- }
340
+ const resolved = await resolveResponseSchemas(tmp.responses);
341
+ components = resolved.components;
356
342
  }
357
343
  return { schema: tmp, components };
358
344
  }
@@ -362,6 +348,7 @@ async function getSpec(middlewareHandler, defaultOptions) {
362
348
  const media = middlewareHandler.options?.media ?? middlewareHandler.target === "json" ? "application/json" : "multipart/form-data";
363
349
  if (!docs.requestBody || !("content" in docs.requestBody) || !docs.requestBody.content) {
364
350
  docs.requestBody = {
351
+ required: true,
365
352
  content: {
366
353
  [media]: {
367
354
  schema: result.schema
@@ -421,6 +408,25 @@ function generateParameters(target, schema) {
421
408
  }
422
409
  return parameters;
423
410
  }
411
+ async function resolveResponseSchemas(responses) {
412
+ let components = {};
413
+ for (const key of Object.keys(responses)) {
414
+ const response = responses[key];
415
+ if (!response || !("content" in response)) continue;
416
+ for (const contentKey of Object.keys(response.content ?? {})) {
417
+ const raw = response.content?.[contentKey];
418
+ if (!raw) continue;
419
+ if (raw.schema && "toOpenAPISchema" in raw.schema) {
420
+ const result = await raw.schema.toOpenAPISchema();
421
+ raw.schema = result.schema;
422
+ if (result.components) {
423
+ components = mergeComponentsObjects(components, result.components);
424
+ }
425
+ }
426
+ }
427
+ }
428
+ return { responses, components };
429
+ }
424
430
  function mergeComponentsObjects(...components) {
425
431
  return components.reduce(
426
432
  (prev, component, index) => {
@@ -451,16 +457,63 @@ function loadVendor(vendor, fn) {
451
457
  standardOpenapi.loadVendor(vendor, fn.toOpenAPISchema);
452
458
  }
453
459
  }
460
+ const arktypeMorphFallback = (ctx) => ctx.base;
461
+ const zodV4DateOverride = (ctx) => {
462
+ if (ctx.zodSchema._zod.def.type === "date") {
463
+ ctx.jsonSchema.type = "string";
464
+ ctx.jsonSchema.format = "date-time";
465
+ }
466
+ };
454
467
  function resolver(schema, userDefinedOptions) {
468
+ const vendor = schema["~standard"].vendor;
455
469
  return {
456
- vendor: schema["~standard"].vendor,
470
+ vendor,
457
471
  validate: schema["~standard"].validate,
458
472
  toJSONSchema: (customOptions) => standardJson.toJsonSchema(schema, { ...userDefinedOptions, ...customOptions }),
459
- toOpenAPISchema: (customOptions) => standardOpenapi.toOpenAPISchema(schema, { ...userDefinedOptions, ...customOptions })
473
+ toOpenAPISchema: (customOptions) => standardOpenapi.toOpenAPISchema(schema, {
474
+ ...userDefinedOptions,
475
+ ...customOptions,
476
+ ...vendor === "arktype" ? injectArktypeFallback(userDefinedOptions, customOptions) : void 0,
477
+ ...vendor === "zod" ? injectZodV4DateOverride(schema, userDefinedOptions, customOptions) : void 0
478
+ })
479
+ };
480
+ }
481
+ function injectArktypeFallback(userDefined, custom) {
482
+ const userNested = userDefined?.options;
483
+ const customNested = custom?.options;
484
+ if (userDefined?.fallback || userNested?.fallback || custom?.fallback || customNested?.fallback) {
485
+ return void 0;
486
+ }
487
+ return {
488
+ options: {
489
+ fallback: arktypeMorphFallback,
490
+ ...userNested,
491
+ ...customNested
492
+ }
493
+ };
494
+ }
495
+ function injectZodV4DateOverride(schema, userDefined, custom) {
496
+ if (!("_zod" in schema)) return void 0;
497
+ const userNested = userDefined?.options;
498
+ const customNested = custom?.options;
499
+ if (userDefined?.override || userNested?.override || custom?.override || customNested?.override) {
500
+ return void 0;
501
+ }
502
+ return {
503
+ options: {
504
+ unrepresentable: "any",
505
+ override: zodV4DateOverride,
506
+ ...userNested,
507
+ ...customNested
508
+ }
460
509
  };
461
510
  }
462
511
  function validator(target, schema, hook, options) {
463
512
  const middleware = standardValidator.sValidator(target, schema, hook);
513
+ Object.defineProperty(middleware, "name", {
514
+ value: "validator",
515
+ configurable: true
516
+ });
464
517
  return Object.assign(middleware, {
465
518
  [uniqueSymbol]: {
466
519
  target,
@@ -473,6 +526,10 @@ function describeRoute(spec) {
473
526
  const middleware = async (_c, next) => {
474
527
  await next();
475
528
  };
529
+ Object.defineProperty(middleware, "name", {
530
+ value: "describeRoute",
531
+ configurable: true
532
+ });
476
533
  return Object.assign(middleware, {
477
534
  [uniqueSymbol]: {
478
535
  spec
package/dist/index.d.cts CHANGED
@@ -6,6 +6,8 @@ import { loadVendor as loadVendor$2, ToOpenAPISchemaContext } from '@standard-co
6
6
  import { Hook } from '@hono/standard-validator';
7
7
  import { loadVendor as loadVendor$1 } from '@standard-community/standard-json';
8
8
  import { StatusCode } from 'hono/utils/http-status';
9
+ import { JSONParsed } from 'hono/utils/types';
10
+ import { InferInput } from 'hono/validator';
9
11
  import { JSONSchema7 } from 'json-schema';
10
12
 
11
13
  /** The Standard Schema interface. */
@@ -93,13 +95,9 @@ type HasUndefined<T> = undefined extends T ? true : false;
93
95
  */
94
96
  declare function validator<Schema extends StandardSchemaV1, Target extends keyof ValidationTargets, E extends Env, P extends string, In = StandardSchemaV1.InferInput<Schema>, Out = StandardSchemaV1.InferOutput<Schema>, I extends Input = {
95
97
  in: HasUndefined<In> extends true ? {
96
- [K in Target]?: In extends ValidationTargets[K] ? In : {
97
- [K2 in keyof In]?: ValidationTargets[K][K2];
98
- };
98
+ [K in Target]?: [In] extends [ValidationTargets[K]] ? In : InferInput<In, K>;
99
99
  } : {
100
- [K in Target]: In extends ValidationTargets[K] ? In : {
101
- [K2 in keyof In]: ValidationTargets[K][K2];
102
- };
100
+ [K in Target]: [In] extends [ValidationTargets[K]] ? In : InferInput<In, K>;
103
101
  };
104
102
  out: {
105
103
  [K in Target]: Out;
@@ -122,7 +120,7 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
122
120
  };
123
121
  type Num<T> = T extends `${infer N extends number}` ? N : T;
124
122
  type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = PromiseOr<{
125
- [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never> : never;
123
+ [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<JSONParsed<StandardSchemaV1.InferOutput<T[K]>>, Num<K> extends StatusCode ? Num<K> : never> : never;
126
124
  }[keyof T]>;
127
125
  type Handler<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = (c: Context<E, P, I>, next: Next) => HandlerResponse<T>;
128
126
  declare function describeResponse<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>>(handler: Handler<E, P, I, T>, responses: ResponseObject<T>, options?: Record<string, unknown>): Handler<E, P, I, T>;
@@ -151,13 +149,41 @@ type HandlerUniqueProperty = (ResolverReturnType & {
151
149
  }) | {
152
150
  spec: DescribeRouteOptions;
153
151
  };
152
+ /**
153
+ * A media type object that accepts resolver() output in addition to standard schema types.
154
+ */
155
+ type MediaTypeObjectWithResolver = Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
156
+ schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
157
+ };
158
+ /**
159
+ * A response object that accepts resolver() output in schema positions.
160
+ */
161
+ type ResponseObjectWithResolver = (Omit<OpenAPIV3_1.ResponseObject, "content"> & {
162
+ content?: {
163
+ [media: string]: MediaTypeObjectWithResolver;
164
+ };
165
+ }) | OpenAPIV3_1.ReferenceObject;
166
+ /**
167
+ * A responses map that accepts resolver() output in schema positions.
168
+ */
169
+ type ResponsesWithResolver = {
170
+ [key: string]: ResponseObjectWithResolver;
171
+ };
172
+ /**
173
+ * Extended document type that allows resolver() in documentation.components.responses
174
+ */
175
+ type DocumentWithResolver = Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict" | "components"> & {
176
+ components?: Omit<OpenAPIV3_1.ComponentsObject, "responses"> & {
177
+ responses?: ResponsesWithResolver;
178
+ };
179
+ };
154
180
  type GenerateSpecOptions = {
155
181
  /**
156
182
  * Customize OpenAPI config, refers to Swagger 2.0 config
157
183
  *
158
184
  * @see https://swagger.io/specification/v2/
159
185
  */
160
- documentation: Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict">;
186
+ documentation: DocumentWithResolver;
161
187
  /**
162
188
  * Include paths which don't have the handlers.
163
189
  * This is useful when you want to document the
@@ -203,15 +229,7 @@ type DescribeRouteOptions = Omit<OpenAPIV3_1.OperationObject, "responses" | "ope
203
229
  /**
204
230
  * Responses of the request
205
231
  */
206
- responses?: {
207
- [key: string]: (OpenAPIV3_1.ResponseObject & {
208
- content?: {
209
- [key: string]: Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
210
- schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
211
- };
212
- };
213
- }) | OpenAPIV3_1.ReferenceObject;
214
- };
232
+ responses?: ResponsesWithResolver;
215
233
  };
216
234
  type RegisterSchemaPathOptions = {
217
235
  route: RouterRoute;
@@ -277,4 +295,4 @@ declare function generateSpecs<E extends Env = BlankEnv, P extends string = stri
277
295
  jsonSchemaDialect?: string;
278
296
  }>;
279
297
 
280
- export { ALLOWED_METHODS, type AllowedMethods, type DescribeRouteOptions, type GenerateSpecOptions, type HandlerUniqueProperty, type PromiseOr, type RegisterSchemaPathOptions, type ResolverReturnType, type SpecContext, clearSpecsContext, describeResponse, describeRoute, generateSpecs, loadVendor, openAPIRouteHandler, registerSchemaPath, removeExcludedPaths, resolver, uniqueSymbol, validator };
298
+ export { ALLOWED_METHODS, type AllowedMethods, type DescribeRouteOptions, type GenerateSpecOptions, type HandlerUniqueProperty, type PromiseOr, type RegisterSchemaPathOptions, type ResolverReturnType, type ResponsesWithResolver, type SpecContext, clearSpecsContext, describeResponse, describeRoute, generateSpecs, loadVendor, openAPIRouteHandler, registerSchemaPath, removeExcludedPaths, resolver, uniqueSymbol, validator };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ import { loadVendor as loadVendor$2, ToOpenAPISchemaContext } from '@standard-co
6
6
  import { Hook } from '@hono/standard-validator';
7
7
  import { loadVendor as loadVendor$1 } from '@standard-community/standard-json';
8
8
  import { StatusCode } from 'hono/utils/http-status';
9
+ import { JSONParsed } from 'hono/utils/types';
10
+ import { InferInput } from 'hono/validator';
9
11
  import { JSONSchema7 } from 'json-schema';
10
12
 
11
13
  /** The Standard Schema interface. */
@@ -93,13 +95,9 @@ type HasUndefined<T> = undefined extends T ? true : false;
93
95
  */
94
96
  declare function validator<Schema extends StandardSchemaV1, Target extends keyof ValidationTargets, E extends Env, P extends string, In = StandardSchemaV1.InferInput<Schema>, Out = StandardSchemaV1.InferOutput<Schema>, I extends Input = {
95
97
  in: HasUndefined<In> extends true ? {
96
- [K in Target]?: In extends ValidationTargets[K] ? In : {
97
- [K2 in keyof In]?: ValidationTargets[K][K2];
98
- };
98
+ [K in Target]?: [In] extends [ValidationTargets[K]] ? In : InferInput<In, K>;
99
99
  } : {
100
- [K in Target]: In extends ValidationTargets[K] ? In : {
101
- [K2 in keyof In]: ValidationTargets[K][K2];
102
- };
100
+ [K in Target]: [In] extends [ValidationTargets[K]] ? In : InferInput<In, K>;
103
101
  };
104
102
  out: {
105
103
  [K in Target]: Out;
@@ -122,7 +120,7 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
122
120
  };
123
121
  type Num<T> = T extends `${infer N extends number}` ? N : T;
124
122
  type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = PromiseOr<{
125
- [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never> : never;
123
+ [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<JSONParsed<StandardSchemaV1.InferOutput<T[K]>>, Num<K> extends StatusCode ? Num<K> : never> : never;
126
124
  }[keyof T]>;
127
125
  type Handler<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = (c: Context<E, P, I>, next: Next) => HandlerResponse<T>;
128
126
  declare function describeResponse<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>>(handler: Handler<E, P, I, T>, responses: ResponseObject<T>, options?: Record<string, unknown>): Handler<E, P, I, T>;
@@ -151,13 +149,41 @@ type HandlerUniqueProperty = (ResolverReturnType & {
151
149
  }) | {
152
150
  spec: DescribeRouteOptions;
153
151
  };
152
+ /**
153
+ * A media type object that accepts resolver() output in addition to standard schema types.
154
+ */
155
+ type MediaTypeObjectWithResolver = Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
156
+ schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
157
+ };
158
+ /**
159
+ * A response object that accepts resolver() output in schema positions.
160
+ */
161
+ type ResponseObjectWithResolver = (Omit<OpenAPIV3_1.ResponseObject, "content"> & {
162
+ content?: {
163
+ [media: string]: MediaTypeObjectWithResolver;
164
+ };
165
+ }) | OpenAPIV3_1.ReferenceObject;
166
+ /**
167
+ * A responses map that accepts resolver() output in schema positions.
168
+ */
169
+ type ResponsesWithResolver = {
170
+ [key: string]: ResponseObjectWithResolver;
171
+ };
172
+ /**
173
+ * Extended document type that allows resolver() in documentation.components.responses
174
+ */
175
+ type DocumentWithResolver = Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict" | "components"> & {
176
+ components?: Omit<OpenAPIV3_1.ComponentsObject, "responses"> & {
177
+ responses?: ResponsesWithResolver;
178
+ };
179
+ };
154
180
  type GenerateSpecOptions = {
155
181
  /**
156
182
  * Customize OpenAPI config, refers to Swagger 2.0 config
157
183
  *
158
184
  * @see https://swagger.io/specification/v2/
159
185
  */
160
- documentation: Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict">;
186
+ documentation: DocumentWithResolver;
161
187
  /**
162
188
  * Include paths which don't have the handlers.
163
189
  * This is useful when you want to document the
@@ -203,15 +229,7 @@ type DescribeRouteOptions = Omit<OpenAPIV3_1.OperationObject, "responses" | "ope
203
229
  /**
204
230
  * Responses of the request
205
231
  */
206
- responses?: {
207
- [key: string]: (OpenAPIV3_1.ResponseObject & {
208
- content?: {
209
- [key: string]: Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
210
- schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
211
- };
212
- };
213
- }) | OpenAPIV3_1.ReferenceObject;
214
- };
232
+ responses?: ResponsesWithResolver;
215
233
  };
216
234
  type RegisterSchemaPathOptions = {
217
235
  route: RouterRoute;
@@ -277,4 +295,4 @@ declare function generateSpecs<E extends Env = BlankEnv, P extends string = stri
277
295
  jsonSchemaDialect?: string;
278
296
  }>;
279
297
 
280
- export { ALLOWED_METHODS, type AllowedMethods, type DescribeRouteOptions, type GenerateSpecOptions, type HandlerUniqueProperty, type PromiseOr, type RegisterSchemaPathOptions, type ResolverReturnType, type SpecContext, clearSpecsContext, describeResponse, describeRoute, generateSpecs, loadVendor, openAPIRouteHandler, registerSchemaPath, removeExcludedPaths, resolver, uniqueSymbol, validator };
298
+ export { ALLOWED_METHODS, type AllowedMethods, type DescribeRouteOptions, type GenerateSpecOptions, type HandlerUniqueProperty, type PromiseOr, type RegisterSchemaPathOptions, type ResolverReturnType, type ResponsesWithResolver, type SpecContext, clearSpecsContext, describeResponse, describeRoute, generateSpecs, loadVendor, openAPIRouteHandler, registerSchemaPath, removeExcludedPaths, resolver, uniqueSymbol, validator };
package/dist/index.js CHANGED
@@ -250,8 +250,10 @@ async function generateSpecs(hono, options = DEFAULT_OPTIONS, c) {
250
250
  }
251
251
  }
252
252
  }
253
+ const { components: resolvedDocComponents } = _documentation.components?.responses ? await resolveResponseSchemas(_documentation.components.responses) : { components: {} };
253
254
  const components = mergeComponentsObjects(
254
255
  _documentation.components,
256
+ resolvedDocComponents,
255
257
  ctx.components
256
258
  );
257
259
  return {
@@ -323,7 +325,6 @@ function getHiddenValue(options) {
323
325
  }
324
326
  async function getSpec(middlewareHandler, defaultOptions) {
325
327
  if ("spec" in middlewareHandler) {
326
- let components = {};
327
328
  const tmp = {
328
329
  ...defaultOptions,
329
330
  ...middlewareHandler.spec,
@@ -332,25 +333,10 @@ async function getSpec(middlewareHandler, defaultOptions) {
332
333
  ...middlewareHandler.spec.responses
333
334
  }
334
335
  };
336
+ let components = {};
335
337
  if (tmp.responses) {
336
- for (const key of Object.keys(tmp.responses)) {
337
- const response = tmp.responses[key];
338
- if (!response || !("content" in response)) continue;
339
- for (const contentKey of Object.keys(response.content ?? {})) {
340
- const raw = response.content?.[contentKey];
341
- if (!raw) continue;
342
- if (raw.schema && "toOpenAPISchema" in raw.schema) {
343
- const result2 = await raw.schema.toOpenAPISchema();
344
- raw.schema = result2.schema;
345
- if (result2.components) {
346
- components = mergeComponentsObjects(
347
- components,
348
- result2.components
349
- );
350
- }
351
- }
352
- }
353
- }
338
+ const resolved = await resolveResponseSchemas(tmp.responses);
339
+ components = resolved.components;
354
340
  }
355
341
  return { schema: tmp, components };
356
342
  }
@@ -360,6 +346,7 @@ async function getSpec(middlewareHandler, defaultOptions) {
360
346
  const media = middlewareHandler.options?.media ?? middlewareHandler.target === "json" ? "application/json" : "multipart/form-data";
361
347
  if (!docs.requestBody || !("content" in docs.requestBody) || !docs.requestBody.content) {
362
348
  docs.requestBody = {
349
+ required: true,
363
350
  content: {
364
351
  [media]: {
365
352
  schema: result.schema
@@ -419,6 +406,25 @@ function generateParameters(target, schema) {
419
406
  }
420
407
  return parameters;
421
408
  }
409
+ async function resolveResponseSchemas(responses) {
410
+ let components = {};
411
+ for (const key of Object.keys(responses)) {
412
+ const response = responses[key];
413
+ if (!response || !("content" in response)) continue;
414
+ for (const contentKey of Object.keys(response.content ?? {})) {
415
+ const raw = response.content?.[contentKey];
416
+ if (!raw) continue;
417
+ if (raw.schema && "toOpenAPISchema" in raw.schema) {
418
+ const result = await raw.schema.toOpenAPISchema();
419
+ raw.schema = result.schema;
420
+ if (result.components) {
421
+ components = mergeComponentsObjects(components, result.components);
422
+ }
423
+ }
424
+ }
425
+ }
426
+ return { responses, components };
427
+ }
422
428
  function mergeComponentsObjects(...components) {
423
429
  return components.reduce(
424
430
  (prev, component, index) => {
@@ -449,16 +455,63 @@ function loadVendor(vendor, fn) {
449
455
  loadVendor$2(vendor, fn.toOpenAPISchema);
450
456
  }
451
457
  }
458
+ const arktypeMorphFallback = (ctx) => ctx.base;
459
+ const zodV4DateOverride = (ctx) => {
460
+ if (ctx.zodSchema._zod.def.type === "date") {
461
+ ctx.jsonSchema.type = "string";
462
+ ctx.jsonSchema.format = "date-time";
463
+ }
464
+ };
452
465
  function resolver(schema, userDefinedOptions) {
466
+ const vendor = schema["~standard"].vendor;
453
467
  return {
454
- vendor: schema["~standard"].vendor,
468
+ vendor,
455
469
  validate: schema["~standard"].validate,
456
470
  toJSONSchema: (customOptions) => toJsonSchema(schema, { ...userDefinedOptions, ...customOptions }),
457
- toOpenAPISchema: (customOptions) => toOpenAPISchema(schema, { ...userDefinedOptions, ...customOptions })
471
+ toOpenAPISchema: (customOptions) => toOpenAPISchema(schema, {
472
+ ...userDefinedOptions,
473
+ ...customOptions,
474
+ ...vendor === "arktype" ? injectArktypeFallback(userDefinedOptions, customOptions) : void 0,
475
+ ...vendor === "zod" ? injectZodV4DateOverride(schema, userDefinedOptions, customOptions) : void 0
476
+ })
477
+ };
478
+ }
479
+ function injectArktypeFallback(userDefined, custom) {
480
+ const userNested = userDefined?.options;
481
+ const customNested = custom?.options;
482
+ if (userDefined?.fallback || userNested?.fallback || custom?.fallback || customNested?.fallback) {
483
+ return void 0;
484
+ }
485
+ return {
486
+ options: {
487
+ fallback: arktypeMorphFallback,
488
+ ...userNested,
489
+ ...customNested
490
+ }
491
+ };
492
+ }
493
+ function injectZodV4DateOverride(schema, userDefined, custom) {
494
+ if (!("_zod" in schema)) return void 0;
495
+ const userNested = userDefined?.options;
496
+ const customNested = custom?.options;
497
+ if (userDefined?.override || userNested?.override || custom?.override || customNested?.override) {
498
+ return void 0;
499
+ }
500
+ return {
501
+ options: {
502
+ unrepresentable: "any",
503
+ override: zodV4DateOverride,
504
+ ...userNested,
505
+ ...customNested
506
+ }
458
507
  };
459
508
  }
460
509
  function validator(target, schema, hook, options) {
461
510
  const middleware = sValidator(target, schema, hook);
511
+ Object.defineProperty(middleware, "name", {
512
+ value: "validator",
513
+ configurable: true
514
+ });
462
515
  return Object.assign(middleware, {
463
516
  [uniqueSymbol]: {
464
517
  target,
@@ -471,6 +524,10 @@ function describeRoute(spec) {
471
524
  const middleware = async (_c, next) => {
472
525
  await next();
473
526
  };
527
+ Object.defineProperty(middleware, "name", {
528
+ value: "describeRoute",
529
+ configurable: true
530
+ });
474
531
  return Object.assign(middleware, {
475
532
  [uniqueSymbol]: {
476
533
  spec
package/package.json CHANGED
@@ -1,86 +1,84 @@
1
- {
2
- "name": "hono-openapi",
3
- "description": "OpenAPI schema generator for Hono",
4
- "version": "1.2.0",
5
- "type": "module",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
- "files": [
10
- "dist"
11
- ],
12
- "license": "MIT",
13
- "scripts": {
14
- "build": "pkgroll --clean-dist",
15
- "lint": "biome check .",
16
- "format": "biome check --write .",
17
- "prepare": "is-ci || husky",
18
- "test": "vitest"
19
- },
20
- "keywords": [
21
- "hono",
22
- "openapi",
23
- "zod",
24
- "valibot",
25
- "typebox",
26
- "arktype",
27
- "effect"
28
- ],
29
- "homepage": "https://github.com/rhinobase/hono-openapi",
30
- "publishConfig": {
31
- "access": "public"
32
- },
33
- "repository": {
34
- "type": "git",
35
- "url": "git+https://github.com/rhinobase/hono-openapi.git"
36
- },
37
- "bugs": {
38
- "url": "https://github.com/rhinobase/hono-openapi/issues"
39
- },
40
- "exports": {
41
- "import": {
42
- "types": "./dist/index.d.ts",
43
- "default": "./dist/index.js"
44
- },
45
- "require": {
46
- "types": "./dist/index.d.cts",
47
- "default": "./dist/index.cjs"
48
- }
49
- },
50
- "peerDependencies": {
51
- "@hono/standard-validator": "^0.2.0",
52
- "@standard-community/standard-json": "^0.3.5",
53
- "@standard-community/standard-openapi": "^0.2.9",
54
- "@types/json-schema": "^7.0.15",
55
- "hono": "^4.8.3",
56
- "openapi-types": "^12.1.3"
57
- },
58
- "peerDependenciesMeta": {
59
- "@hono/standard-validator": {
60
- "optional": true
61
- },
62
- "hono": {
63
- "optional": true
64
- }
65
- },
66
- "devDependencies": {
67
- "@biomejs/biome": "^2.0.6",
68
- "@standard-schema/spec": "^1.0.0",
69
- "@valibot/to-json-schema": "^1.3.0",
70
- "arktype": "^2.1.22",
71
- "effect": "^3.17.13",
72
- "husky": "^9.1.7",
73
- "is-ci": "^4.1.0",
74
- "nano-staged": "^0.8.0",
75
- "pkg-pr-new": "^0.0.60",
76
- "pkgroll": "^2.13.1",
77
- "typebox": "^1.0.17",
78
- "typescript": "^5.8.3",
79
- "sury": "^10.0.0",
80
- "valibot": "^1.1.0",
81
- "vitest": "^3.2.4",
82
- "zod": "^3.23.8",
83
- "zod-openapi": "^4"
84
- },
85
- "packageManager": "pnpm@10.0.0"
86
- }
1
+ {
2
+ "name": "hono-openapi",
3
+ "description": "OpenAPI schema generator for Hono",
4
+ "version": "1.3.1",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "hono",
15
+ "openapi",
16
+ "zod",
17
+ "valibot",
18
+ "typebox",
19
+ "arktype",
20
+ "effect"
21
+ ],
22
+ "homepage": "https://github.com/rhinobase/hono-openapi",
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/rhinobase/hono-openapi.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/rhinobase/hono-openapi/issues"
32
+ },
33
+ "exports": {
34
+ "import": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "require": {
39
+ "types": "./dist/index.d.cts",
40
+ "default": "./dist/index.cjs"
41
+ }
42
+ },
43
+ "peerDependencies": {
44
+ "@hono/standard-validator": "^0.2.0",
45
+ "@standard-community/standard-json": "^0.3.5",
46
+ "@standard-community/standard-openapi": "^0.2.9",
47
+ "@types/json-schema": "^7.0.15",
48
+ "hono": "^4.11.2",
49
+ "openapi-types": "^12.1.3"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@hono/standard-validator": {
53
+ "optional": true
54
+ },
55
+ "hono": {
56
+ "optional": true
57
+ }
58
+ },
59
+ "devDependencies": {
60
+ "@biomejs/biome": "^2.0.6",
61
+ "@standard-schema/spec": "^1.0.0",
62
+ "@valibot/to-json-schema": "^1.3.0",
63
+ "arktype": "^2.1.22",
64
+ "effect": "^3.17.13",
65
+ "husky": "^9.1.7",
66
+ "is-ci": "^4.1.0",
67
+ "nano-staged": "^0.8.0",
68
+ "pkg-pr-new": "^0.0.60",
69
+ "pkgroll": "^2.13.1",
70
+ "typebox": "^1.0.17",
71
+ "typescript": "^5.8.3",
72
+ "sury": "^10.0.0",
73
+ "valibot": "^1.1.0",
74
+ "vitest": "^3.2.4",
75
+ "zod": "^3.23.8",
76
+ "zod-openapi": "^4"
77
+ },
78
+ "scripts": {
79
+ "build": "pkgroll --clean-dist",
80
+ "lint": "biome check .",
81
+ "format": "biome check --write .",
82
+ "test": "vitest"
83
+ }
84
+ }