hono-openapi 1.2.0 → 1.3.0
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 +70 -21
- package/dist/index.d.cts +33 -12
- package/dist/index.d.ts +33 -12
- package/dist/index.js +70 -21
- package/package.json +1 -1
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
|
-
|
|
339
|
-
|
|
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,12 +457,55 @@ 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
|
|
470
|
+
vendor,
|
|
457
471
|
validate: schema["~standard"].validate,
|
|
458
472
|
toJSONSchema: (customOptions) => standardJson.toJsonSchema(schema, { ...userDefinedOptions, ...customOptions }),
|
|
459
|
-
toOpenAPISchema: (customOptions) => standardOpenapi.toOpenAPISchema(schema, {
|
|
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) {
|
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,7 @@ 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';
|
|
9
10
|
import { JSONSchema7 } from 'json-schema';
|
|
10
11
|
|
|
11
12
|
/** The Standard Schema interface. */
|
|
@@ -122,7 +123,7 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
|
|
|
122
123
|
};
|
|
123
124
|
type Num<T> = T extends `${infer N extends number}` ? N : T;
|
|
124
125
|
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]
|
|
126
|
+
[K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<JSONParsed<StandardSchemaV1.InferOutput<T[K]>>, Num<K> extends StatusCode ? Num<K> : never> : never;
|
|
126
127
|
}[keyof T]>;
|
|
127
128
|
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
129
|
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 +152,41 @@ type HandlerUniqueProperty = (ResolverReturnType & {
|
|
|
151
152
|
}) | {
|
|
152
153
|
spec: DescribeRouteOptions;
|
|
153
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* A media type object that accepts resolver() output in addition to standard schema types.
|
|
157
|
+
*/
|
|
158
|
+
type MediaTypeObjectWithResolver = Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
|
|
159
|
+
schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* A response object that accepts resolver() output in schema positions.
|
|
163
|
+
*/
|
|
164
|
+
type ResponseObjectWithResolver = (Omit<OpenAPIV3_1.ResponseObject, "content"> & {
|
|
165
|
+
content?: {
|
|
166
|
+
[media: string]: MediaTypeObjectWithResolver;
|
|
167
|
+
};
|
|
168
|
+
}) | OpenAPIV3_1.ReferenceObject;
|
|
169
|
+
/**
|
|
170
|
+
* A responses map that accepts resolver() output in schema positions.
|
|
171
|
+
*/
|
|
172
|
+
type ResponsesWithResolver = {
|
|
173
|
+
[key: string]: ResponseObjectWithResolver;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Extended document type that allows resolver() in documentation.components.responses
|
|
177
|
+
*/
|
|
178
|
+
type DocumentWithResolver = Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict" | "components"> & {
|
|
179
|
+
components?: Omit<OpenAPIV3_1.ComponentsObject, "responses"> & {
|
|
180
|
+
responses?: ResponsesWithResolver;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
154
183
|
type GenerateSpecOptions = {
|
|
155
184
|
/**
|
|
156
185
|
* Customize OpenAPI config, refers to Swagger 2.0 config
|
|
157
186
|
*
|
|
158
187
|
* @see https://swagger.io/specification/v2/
|
|
159
188
|
*/
|
|
160
|
-
documentation:
|
|
189
|
+
documentation: DocumentWithResolver;
|
|
161
190
|
/**
|
|
162
191
|
* Include paths which don't have the handlers.
|
|
163
192
|
* This is useful when you want to document the
|
|
@@ -203,15 +232,7 @@ type DescribeRouteOptions = Omit<OpenAPIV3_1.OperationObject, "responses" | "ope
|
|
|
203
232
|
/**
|
|
204
233
|
* Responses of the request
|
|
205
234
|
*/
|
|
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
|
-
};
|
|
235
|
+
responses?: ResponsesWithResolver;
|
|
215
236
|
};
|
|
216
237
|
type RegisterSchemaPathOptions = {
|
|
217
238
|
route: RouterRoute;
|
|
@@ -277,4 +298,4 @@ declare function generateSpecs<E extends Env = BlankEnv, P extends string = stri
|
|
|
277
298
|
jsonSchemaDialect?: string;
|
|
278
299
|
}>;
|
|
279
300
|
|
|
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 };
|
|
301
|
+
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,7 @@ 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';
|
|
9
10
|
import { JSONSchema7 } from 'json-schema';
|
|
10
11
|
|
|
11
12
|
/** The Standard Schema interface. */
|
|
@@ -122,7 +123,7 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
|
|
|
122
123
|
};
|
|
123
124
|
type Num<T> = T extends `${infer N extends number}` ? N : T;
|
|
124
125
|
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]
|
|
126
|
+
[K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<JSONParsed<StandardSchemaV1.InferOutput<T[K]>>, Num<K> extends StatusCode ? Num<K> : never> : never;
|
|
126
127
|
}[keyof T]>;
|
|
127
128
|
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
129
|
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 +152,41 @@ type HandlerUniqueProperty = (ResolverReturnType & {
|
|
|
151
152
|
}) | {
|
|
152
153
|
spec: DescribeRouteOptions;
|
|
153
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* A media type object that accepts resolver() output in addition to standard schema types.
|
|
157
|
+
*/
|
|
158
|
+
type MediaTypeObjectWithResolver = Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
|
|
159
|
+
schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* A response object that accepts resolver() output in schema positions.
|
|
163
|
+
*/
|
|
164
|
+
type ResponseObjectWithResolver = (Omit<OpenAPIV3_1.ResponseObject, "content"> & {
|
|
165
|
+
content?: {
|
|
166
|
+
[media: string]: MediaTypeObjectWithResolver;
|
|
167
|
+
};
|
|
168
|
+
}) | OpenAPIV3_1.ReferenceObject;
|
|
169
|
+
/**
|
|
170
|
+
* A responses map that accepts resolver() output in schema positions.
|
|
171
|
+
*/
|
|
172
|
+
type ResponsesWithResolver = {
|
|
173
|
+
[key: string]: ResponseObjectWithResolver;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Extended document type that allows resolver() in documentation.components.responses
|
|
177
|
+
*/
|
|
178
|
+
type DocumentWithResolver = Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict" | "components"> & {
|
|
179
|
+
components?: Omit<OpenAPIV3_1.ComponentsObject, "responses"> & {
|
|
180
|
+
responses?: ResponsesWithResolver;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
154
183
|
type GenerateSpecOptions = {
|
|
155
184
|
/**
|
|
156
185
|
* Customize OpenAPI config, refers to Swagger 2.0 config
|
|
157
186
|
*
|
|
158
187
|
* @see https://swagger.io/specification/v2/
|
|
159
188
|
*/
|
|
160
|
-
documentation:
|
|
189
|
+
documentation: DocumentWithResolver;
|
|
161
190
|
/**
|
|
162
191
|
* Include paths which don't have the handlers.
|
|
163
192
|
* This is useful when you want to document the
|
|
@@ -203,15 +232,7 @@ type DescribeRouteOptions = Omit<OpenAPIV3_1.OperationObject, "responses" | "ope
|
|
|
203
232
|
/**
|
|
204
233
|
* Responses of the request
|
|
205
234
|
*/
|
|
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
|
-
};
|
|
235
|
+
responses?: ResponsesWithResolver;
|
|
215
236
|
};
|
|
216
237
|
type RegisterSchemaPathOptions = {
|
|
217
238
|
route: RouterRoute;
|
|
@@ -277,4 +298,4 @@ declare function generateSpecs<E extends Env = BlankEnv, P extends string = stri
|
|
|
277
298
|
jsonSchemaDialect?: string;
|
|
278
299
|
}>;
|
|
279
300
|
|
|
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 };
|
|
301
|
+
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
|
-
|
|
337
|
-
|
|
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,12 +455,55 @@ 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
|
|
468
|
+
vendor,
|
|
455
469
|
validate: schema["~standard"].validate,
|
|
456
470
|
toJSONSchema: (customOptions) => toJsonSchema(schema, { ...userDefinedOptions, ...customOptions }),
|
|
457
|
-
toOpenAPISchema: (customOptions) => toOpenAPISchema(schema, {
|
|
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) {
|