@elysiajs/openapi 1.4.14 → 1.4.16

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 { type AnyElysia, type TSchema, type InputSchema } from 'elysia';
1
+ import { type AnyElysia, type InputSchema } from 'elysia';
2
2
  import type { OpenAPIV3 } from 'openapi-types';
3
- import { TAnySchema, type TProperties } from '@sinclair/typebox';
4
- import type { AdditionalReferences, ElysiaOpenAPIConfig, MapJsonSchema } from './types';
3
+ import { TAnySchema } from '@sinclair/typebox';
4
+ import type { AdditionalReferences, ElysiaOpenAPIConfig, MapJsonSchema, OpenAPIVersion } from './types';
5
5
  export declare const capitalize: (word: string) => string;
6
6
  /**
7
7
  * Get all possible paths of a path with optional parameters
@@ -10,24 +10,27 @@ export declare const capitalize: (word: string) => string;
10
10
  */
11
11
  export declare const getPossiblePath: (path: string) => string[];
12
12
  export declare const getLoosePath: (path: string) => string;
13
- export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema, io?: "input" | "output") => OpenAPIV3.SchemaObject | undefined;
13
+ export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema, io?: "input" | "output", openapiVersion?: OpenAPIVersion) => OpenAPIV3.SchemaObject | undefined;
14
14
  /**
15
15
  * Convert TypeBox enum-like Union schemas to OpenAPI enum schemas
16
16
  *
17
17
  * Otherwise, return the schema as is
18
18
  */
19
19
  export declare const enumToOpenApi: <T extends TAnySchema | OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined>(_schema: T) => T;
20
+ export declare const nullToOpenApi: <T>(schema: T, openapiVersion: OpenAPIVersion) => T;
20
21
  /**
21
- * Converts Elysia routes to OpenAPI 3.0.3 paths schema
22
+ * Converts Elysia routes to OpenAPI paths schema
22
23
  * @param routes Array of Elysia route objects
23
24
  * @returns OpenAPI paths object
24
25
  */
25
- export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences, vendors?: MapJsonSchema): {
26
+ export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences, vendors?: MapJsonSchema, openapiVersion?: OpenAPIVersion): {
26
27
  components: {
27
28
  schemas: any;
28
29
  };
29
30
  paths: OpenAPIV3.PathsObject<{}, {}>;
30
31
  };
31
- export declare const withHeaders: (schema: TSchema, headers: TProperties) => TSchema & {
32
- headers: TProperties;
32
+ type ResponseHeaderSchemas = Record<string, Exclude<InputSchema['headers'], undefined>>;
33
+ export declare const withHeaders: <S extends Exclude<InputSchema["body"], string | undefined>, H extends ResponseHeaderSchemas>(schema: S, headers: H) => S & {
34
+ headers: H;
33
35
  };
36
+ export {};
@@ -24,21 +24,16 @@ __export(openapi_exports, {
24
24
  enumToOpenApi: () => enumToOpenApi,
25
25
  getLoosePath: () => getLoosePath,
26
26
  getPossiblePath: () => getPossiblePath,
27
+ nullToOpenApi: () => nullToOpenApi,
27
28
  toOpenAPISchema: () => toOpenAPISchema,
28
29
  unwrapSchema: () => unwrapSchema,
29
30
  withHeaders: () => withHeaders
30
31
  });
31
32
  module.exports = __toCommonJS(openapi_exports);
32
33
  var import_elysia = require("elysia");
33
-
34
- // node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
35
- var Kind = /* @__PURE__ */ Symbol.for("TypeBox.Kind");
36
-
37
- // src/openapi.ts
34
+ var import_typebox = require("@sinclair/typebox");
38
35
  var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
39
- var toRef = (name) => import_elysia.t.Ref(
40
- name.startsWith("#/") ? name : `#/components/schemas/${name}`
41
- );
36
+ var toRef = (name) => import_elysia.t.Ref(name.startsWith("#/") ? name : `#/components/schemas/${name}`);
42
37
  var toOperationId = (method, paths) => {
43
38
  let operationId = method.toLowerCase();
44
39
  if (!paths || paths === "/") return operationId + "Index";
@@ -59,7 +54,7 @@ var getPossiblePath = (path) => {
59
54
  }
60
55
  return paths;
61
56
  };
62
- var isValidSchema = (schema) => schema && typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
57
+ var isValidSchema = (schema) => schema && typeof schema === "object" && (import_typebox.Kind in schema && schema[import_typebox.Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
63
58
  var getLoosePath = (path) => {
64
59
  if (path.charCodeAt(path.length - 1) === 47)
65
60
  return path.slice(0, path.length - 1);
@@ -160,7 +155,7 @@ var mergeObjectSchemas = (schemas) => {
160
155
  };
161
156
  var isTSchema = (value) => {
162
157
  if (!value || typeof value !== "object") return false;
163
- if (Kind in value) return true;
158
+ if (import_typebox.Kind in value) return true;
164
159
  const keys = Object.keys(value);
165
160
  if (keys.length > 0 && keys.every((k) => !isNaN(Number(k)))) {
166
161
  return false;
@@ -172,7 +167,7 @@ var normalizeSchemaReference = (schema) => {
172
167
  if (typeof schema !== "string") return schema;
173
168
  return toRef(schema);
174
169
  };
175
- var mergeSchemaProperty = (existing, incoming, vendors) => {
170
+ var mergeSchemaProperty = (existing, incoming, vendors, openapiVersion = "3.1.2") => {
176
171
  if (!existing) return incoming;
177
172
  if (!incoming) return existing;
178
173
  let existingSchema = normalizeSchemaReference(existing);
@@ -180,9 +175,19 @@ var mergeSchemaProperty = (existing, incoming, vendors) => {
180
175
  if (!existingSchema) return incoming;
181
176
  if (!incomingSchema) return existing;
182
177
  if (!isTSchema(incomingSchema) && incomingSchema["~standard"])
183
- incomingSchema = unwrapSchema(incomingSchema, vendors);
178
+ incomingSchema = unwrapSchema(
179
+ incomingSchema,
180
+ vendors,
181
+ "input",
182
+ openapiVersion
183
+ );
184
184
  if (!isTSchema(existingSchema) && existingSchema["~standard"])
185
- existingSchema = unwrapSchema(existingSchema, vendors);
185
+ existingSchema = unwrapSchema(
186
+ existingSchema,
187
+ vendors,
188
+ "input",
189
+ openapiVersion
190
+ );
186
191
  if (!incomingSchema) return existingSchema;
187
192
  if (!existingSchema) return incomingSchema;
188
193
  const { schema: mergedSchema, notObjects } = mergeObjectSchemas([
@@ -195,24 +200,30 @@ var mergeSchemaProperty = (existing, incoming, vendors) => {
195
200
  }
196
201
  return mergedSchema;
197
202
  };
198
- var unwrapResponseSchema = (schema, vendors) => typeof schema === "string" ? normalizeSchemaReference(schema) : !schema ? void 0 : isTSchema(schema) ? schema : (
203
+ var unwrapResponseSchema = (schema, vendors, openapiVersion = "3.1.2") => typeof schema === "string" ? normalizeSchemaReference(schema) : !schema ? void 0 : isTSchema(schema) ? schema : (
199
204
  // @ts-ignore
200
- schema["~standard"] ? unwrapSchema(schema, vendors, "output") : Object.fromEntries(
205
+ schema["~standard"] ? unwrapSchema(
206
+ schema,
207
+ vendors,
208
+ "output",
209
+ openapiVersion
210
+ ) : Object.fromEntries(
201
211
  Object.entries(schema).map(([status, schema2]) => [
202
212
  status,
203
213
  typeof schema2 === "string" ? normalizeSchemaReference(schema2) : isTSchema(schema2) ? schema2 : unwrapSchema(
204
214
  schema2,
205
215
  vendors,
206
- "output"
216
+ "output",
217
+ openapiVersion
207
218
  )
208
219
  ])
209
220
  )
210
221
  );
211
- var mergeResponseSchema = (_existing, _incoming, vendors) => {
222
+ var mergeResponseSchema = (_existing, _incoming, vendors, openapiVersion = "3.1.2") => {
212
223
  if (!_existing) return _incoming;
213
224
  if (!_incoming) return _existing;
214
- let existing = unwrapResponseSchema(_existing, vendors);
215
- let incoming = unwrapResponseSchema(_incoming, vendors);
225
+ let existing = unwrapResponseSchema(_existing, vendors, openapiVersion);
226
+ let incoming = unwrapResponseSchema(_incoming, vendors, openapiVersion);
216
227
  if (!existing && !incoming) return void 0;
217
228
  if (incoming && !existing) return incoming;
218
229
  if (existing && !incoming) return existing;
@@ -234,14 +245,15 @@ var mergeResponseSchema = (_existing, _incoming, vendors) => {
234
245
  schema[status] = mergeSchemaProperty(
235
246
  existingSchema,
236
247
  incomingSchema,
237
- vendors
248
+ vendors,
249
+ openapiVersion
238
250
  );
239
251
  else if (existingSchema) schema[status] = existingSchema;
240
252
  else if (incomingSchema) schema[status] = incomingSchema;
241
253
  }
242
254
  return schema;
243
255
  };
244
- var mergeStandaloneValidators = (hooks, vendors) => {
256
+ var mergeStandaloneValidators = (hooks, vendors, openapiVersion = "3.1.2") => {
245
257
  const merged = { ...hooks };
246
258
  if (!hooks.standaloneValidator?.length) return merged;
247
259
  for (const validator of hooks.standaloneValidator) {
@@ -249,37 +261,43 @@ var mergeStandaloneValidators = (hooks, vendors) => {
249
261
  merged.body = mergeSchemaProperty(
250
262
  merged.body,
251
263
  validator.body,
252
- vendors
264
+ vendors,
265
+ openapiVersion
253
266
  );
254
267
  if (validator.headers)
255
268
  merged.headers = mergeSchemaProperty(
256
269
  merged.headers,
257
270
  validator.headers,
258
- vendors
271
+ vendors,
272
+ openapiVersion
259
273
  );
260
274
  if (validator.query)
261
275
  merged.query = mergeSchemaProperty(
262
276
  merged.query,
263
277
  validator.query,
264
- vendors
278
+ vendors,
279
+ openapiVersion
265
280
  );
266
281
  if (validator.params)
267
282
  merged.params = mergeSchemaProperty(
268
283
  merged.params,
269
284
  validator.params,
270
- vendors
285
+ vendors,
286
+ openapiVersion
271
287
  );
272
288
  if (validator.cookie)
273
289
  merged.cookie = mergeSchemaProperty(
274
290
  merged.cookie,
275
291
  validator.cookie,
276
- vendors
292
+ vendors,
293
+ openapiVersion
277
294
  );
278
295
  if (validator.response)
279
296
  merged.response = mergeResponseSchema(
280
297
  merged.response,
281
298
  validator.response,
282
- vendors
299
+ vendors,
300
+ openapiVersion
283
301
  );
284
302
  }
285
303
  if (typeof merged.body === "string")
@@ -305,36 +323,51 @@ var mergeStandaloneValidators = (hooks, vendors) => {
305
323
  }
306
324
  return merged;
307
325
  };
308
- var flattenRoutes = (routes, vendors) => routes.map((route) => {
326
+ var flattenRoutes = (routes, vendors, openapiVersion = "3.1.2") => routes.map((route) => {
309
327
  if (!route.hooks?.standaloneValidator?.length) return route;
310
328
  return {
311
329
  ...route,
312
- hooks: mergeStandaloneValidators(route.hooks, vendors)
330
+ hooks: mergeStandaloneValidators(
331
+ route.hooks,
332
+ vendors,
333
+ openapiVersion
334
+ )
313
335
  };
314
336
  });
315
- var unwrapReference = (schema, definitions) => {
337
+ var unwrapReference = (schema, definitions, openapiVersion = "3.1.2") => {
316
338
  const ref = schema?.$ref;
317
339
  if (!ref) return schema;
318
340
  const name = ref.slice(ref.lastIndexOf("/") + 1);
319
341
  if (ref && definitions[name]) schema = definitions[name];
320
- return enumToOpenApi(schema);
342
+ return nullToOpenApi(enumToOpenApi(schema), openapiVersion);
321
343
  };
322
- var unwrapSchema = (schema, mapJsonSchema, io = "input") => {
344
+ var unwrapSchema = (schema, mapJsonSchema, io = "input", openapiVersion = "3.1.2") => {
323
345
  if (!schema) return;
324
346
  if (typeof schema === "string") schema = toRef(schema);
325
- if (Kind in schema) return enumToOpenApi(schema);
347
+ if (import_typebox.Kind in schema)
348
+ return nullToOpenApi(enumToOpenApi(schema), openapiVersion);
326
349
  if (!schema?.["~standard"] && // @ts-ignore
327
350
  (schema.$schema || schema.type || schema.properties || schema.items))
328
- return schema;
351
+ return nullToOpenApi(schema, openapiVersion);
329
352
  if (!schema?.["~standard"]) return;
330
- const vendor = schema["~standard"].vendor;
353
+ const standard = schema["~standard"];
354
+ const vendor = standard.vendor;
331
355
  try {
356
+ const jsonSchemaTarget = openapiVersion.startsWith("3.0.") ? "draft-07" : "draft-2020-12";
332
357
  if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
333
- return enumToOpenApi(mapJsonSchema[vendor](schema));
334
- if (schema["~standard"]?.jsonSchema?.[io])
335
- return enumToOpenApi(schema["~standard"].jsonSchema[io]({
336
- target: "draft-2020-12"
337
- }));
358
+ return nullToOpenApi(
359
+ enumToOpenApi(mapJsonSchema[vendor](schema)),
360
+ openapiVersion
361
+ );
362
+ if (standard.jsonSchema?.[io])
363
+ return nullToOpenApi(
364
+ enumToOpenApi(
365
+ standard.jsonSchema[io]({
366
+ target: jsonSchemaTarget
367
+ })
368
+ ),
369
+ openapiVersion
370
+ );
338
371
  switch (vendor) {
339
372
  case "zod":
340
373
  if (warned.zod4 || warned.zod3) break;
@@ -379,10 +412,16 @@ var unwrapSchema = (schema, mapJsonSchema, io = "input") => {
379
412
  break;
380
413
  }
381
414
  if (vendor === "arktype")
382
- return enumToOpenApi(schema?.toJsonSchema?.());
383
- return enumToOpenApi(
384
- // @ts-ignore
385
- schema.toJSONSchema?.() ?? schema?.toJsonSchema?.()
415
+ return nullToOpenApi(
416
+ enumToOpenApi(schema.toJsonSchema?.()),
417
+ openapiVersion
418
+ );
419
+ return nullToOpenApi(
420
+ enumToOpenApi(
421
+ // @ts-ignore
422
+ schema.toJSONSchema?.() ?? schema?.toJsonSchema?.()
423
+ ),
424
+ openapiVersion
386
425
  );
387
426
  } catch (error) {
388
427
  console.warn(error);
@@ -390,9 +429,9 @@ var unwrapSchema = (schema, mapJsonSchema, io = "input") => {
390
429
  };
391
430
  var enumToOpenApi = (_schema) => {
392
431
  if (!_schema || typeof _schema !== "object") return _schema;
393
- if (Kind in _schema) {
432
+ if (import_typebox.Kind in _schema) {
394
433
  const schema2 = _schema;
395
- if (schema2[Kind] === "Union" && schema2.anyOf && Array.isArray(schema2.anyOf) && schema2.anyOf.length > 0 && schema2.anyOf.every(
434
+ if (schema2[import_typebox.Kind] === "Union" && schema2.anyOf && Array.isArray(schema2.anyOf) && schema2.anyOf.length > 0 && schema2.anyOf.every(
396
435
  (item) => item && typeof item === "object" && item.const !== void 0
397
436
  ))
398
437
  return {
@@ -415,9 +454,154 @@ var enumToOpenApi = (_schema) => {
415
454
  ...schema,
416
455
  items: enumToOpenApi(schema.items)
417
456
  };
457
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
458
+ const mapped = schema.anyOf.map(
459
+ (item) => item && typeof item === "object" && item.type === "Date" ? { type: "string", format: "date-time" } : enumToOpenApi(item)
460
+ );
461
+ const seen = /* @__PURE__ */ new Set();
462
+ const deduped = mapped.filter((item) => {
463
+ if (!item || typeof item !== "object") return true;
464
+ const key = JSON.stringify(
465
+ Object.fromEntries(
466
+ Object.entries(item).sort(
467
+ ([a], [b]) => a < b ? -1 : a > b ? 1 : 0
468
+ )
469
+ )
470
+ );
471
+ if (seen.has(key)) return false;
472
+ seen.add(key);
473
+ return true;
474
+ });
475
+ if (deduped.length === 1) return deduped[0];
476
+ return { ...schema, anyOf: deduped };
477
+ }
418
478
  return schema;
419
479
  };
420
- function toOpenAPISchema(app, exclude, references, vendors) {
480
+ var SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
481
+ "properties",
482
+ "patternProperties",
483
+ "$defs",
484
+ "definitions",
485
+ "dependentSchemas"
486
+ ]);
487
+ var SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf", "prefixItems"]);
488
+ var SCHEMA_VALUE_KEYS = /* @__PURE__ */ new Set([
489
+ "items",
490
+ "additionalProperties",
491
+ "unevaluatedProperties",
492
+ "contains",
493
+ "not",
494
+ "if",
495
+ "then",
496
+ "else",
497
+ "propertyNames"
498
+ ]);
499
+ var isSchemaObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
500
+ var nullToOpenApi = (schema, openapiVersion) => {
501
+ const normalize = (value) => {
502
+ if (Array.isArray(value)) return value.map(normalize);
503
+ if (!isSchemaObject(value)) return value;
504
+ const normalized = { ...value };
505
+ const isOpenAPI30 = openapiVersion.startsWith("3.0.");
506
+ for (const unionKey of ["anyOf", "oneOf"]) {
507
+ const union = normalized[unionKey];
508
+ if (!Array.isArray(union)) continue;
509
+ const nonNull = union.filter(
510
+ (item) => !isSchemaObject(item) || item.type !== "null"
511
+ );
512
+ if (nonNull.length === union.length) continue;
513
+ const normalizedNonNull = nonNull.map(normalize);
514
+ if (isOpenAPI30) {
515
+ delete normalized[unionKey];
516
+ if (normalizedNonNull.length === 1 && isSchemaObject(normalizedNonNull[0]))
517
+ Object.assign(normalized, normalizedNonNull[0]);
518
+ else if (normalizedNonNull.length)
519
+ normalized[unionKey] = normalizedNonNull;
520
+ normalized.nullable = true;
521
+ } else if (normalizedNonNull.length === 1 && isSchemaObject(normalizedNonNull[0]) && typeof normalizedNonNull[0].type === "string") {
522
+ delete normalized[unionKey];
523
+ Object.assign(normalized, normalizedNonNull[0]);
524
+ normalized.type = [normalizedNonNull[0].type, "null"];
525
+ } else normalized[unionKey] = union.map(normalize);
526
+ }
527
+ if (isOpenAPI30 && normalized.type === "null") {
528
+ delete normalized.type;
529
+ normalized.nullable = true;
530
+ } else if (isOpenAPI30 && Array.isArray(normalized.type) && normalized.type.includes("null")) {
531
+ const types = normalized.type.filter((type) => type !== "null");
532
+ normalized.nullable = true;
533
+ if (types.length === 1) normalized.type = types[0];
534
+ else if (types.length) normalized.type = types;
535
+ else delete normalized.type;
536
+ }
537
+ for (const [key, nested] of Object.entries(normalized)) {
538
+ if (SCHEMA_MAP_KEYS.has(key) && isSchemaObject(nested))
539
+ normalized[key] = Object.fromEntries(
540
+ Object.entries(nested).map(([name, child]) => [
541
+ name,
542
+ normalize(child)
543
+ ])
544
+ );
545
+ else if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(nested))
546
+ normalized[key] = nested.map(normalize);
547
+ else if (SCHEMA_VALUE_KEYS.has(key) && isSchemaObject(nested))
548
+ normalized[key] = normalize(nested);
549
+ else if (key === "dependencies" && isSchemaObject(nested))
550
+ normalized[key] = Object.fromEntries(
551
+ Object.entries(nested).map(([name, child]) => [
552
+ name,
553
+ isSchemaObject(child) ? normalize(child) : child
554
+ ])
555
+ );
556
+ }
557
+ return normalized;
558
+ };
559
+ return normalize(schema);
560
+ };
561
+ var toResponseHeaders = (schema, vendors, openapiVersion = "3.1.2") => {
562
+ if (!schema || typeof schema === "string" || !("headers" in schema) || !schema.headers)
563
+ return;
564
+ const entries = Object.entries(
565
+ schema.headers
566
+ ).map(
567
+ ([name, hs]) => [
568
+ name,
569
+ {
570
+ schema: unwrapSchema(
571
+ hs,
572
+ vendors,
573
+ "output",
574
+ openapiVersion
575
+ )
576
+ }
577
+ ]
578
+ ).filter(([, v]) => v.schema);
579
+ return entries.length ? Object.fromEntries(entries) : void 0;
580
+ };
581
+ var stripHeaders = (schema) => {
582
+ const { headers, ...rest } = schema;
583
+ return rest;
584
+ };
585
+ var VOID_TYPES = /* @__PURE__ */ new Set(["void", "null", "undefined"]);
586
+ var PLAIN_TYPES = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean"]);
587
+ var toResponseContent = (schema, type, description) => VOID_TYPES.has(type) ? { type, description } : PLAIN_TYPES.has(type) ? { "text/plain": { schema } } : { "application/json": { schema } };
588
+ var toResponseObject = (schema, status, definitions, vendors, openapiVersion = "3.1.2") => {
589
+ const response = unwrapSchema(schema, vendors, "output", openapiVersion);
590
+ if (!response) return;
591
+ const responseSchema = stripHeaders(response);
592
+ const { type, description } = unwrapReference(
593
+ responseSchema,
594
+ definitions,
595
+ openapiVersion
596
+ );
597
+ const headers = toResponseHeaders(schema, vendors, openapiVersion);
598
+ return {
599
+ description: description ?? `Response for status ${status}`,
600
+ ...headers ? { headers } : {},
601
+ content: toResponseContent(responseSchema, type, description)
602
+ };
603
+ };
604
+ function toOpenAPISchema(app, exclude, references, vendors, openapiVersion = "3.1.2") {
421
605
  let {
422
606
  methods: excludeMethods = ["options"],
423
607
  staticFile: excludeStaticFile = true,
@@ -434,11 +618,19 @@ function toOpenAPISchema(app, exclude, references, vendors) {
434
618
  if (typeof reference === "function") references[i] = reference();
435
619
  }
436
620
  }
437
- const routes = flattenRoutes(app.getGlobalRoutes(), vendors);
621
+ const routes = flattenRoutes(app.getGlobalRoutes(), vendors, openapiVersion);
438
622
  for (const route of routes) {
439
623
  if (route.hooks?.detail?.hide) continue;
440
624
  const method = route.method.toLowerCase();
441
- if (excludeStaticFile && route.path.includes(".") || excludePaths.includes(route.path) || excludeMethods.includes(method))
625
+ if (excludeStaticFile && route.path.includes(".") || excludePaths.some((exclusion) => {
626
+ if (exclusion instanceof RegExp) {
627
+ exclusion.lastIndex = 0;
628
+ return exclusion.test(route.path);
629
+ }
630
+ if (typeof exclusion === "string")
631
+ return exclusion === route.path;
632
+ return false;
633
+ }) || excludeMethods.includes(method))
442
634
  continue;
443
635
  const hooks = route.hooks ?? {};
444
636
  if (references?.length)
@@ -484,8 +676,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
484
676
  const parameters = [];
485
677
  if (hooks.params) {
486
678
  const params = unwrapReference(
487
- unwrapSchema(hooks.params, vendors),
488
- definitions
679
+ unwrapSchema(hooks.params, vendors, "input", openapiVersion),
680
+ definitions,
681
+ openapiVersion
489
682
  );
490
683
  if (params && params.type === "object" && params.properties)
491
684
  for (const [name, schema] of Object.entries(params.properties))
@@ -509,8 +702,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
509
702
  }
510
703
  if (hooks.query) {
511
704
  const query = unwrapReference(
512
- unwrapSchema(hooks.query, vendors),
513
- definitions
705
+ unwrapSchema(hooks.query, vendors, "input", openapiVersion),
706
+ definitions,
707
+ openapiVersion
514
708
  );
515
709
  if (query && query.type === "object" && query.properties) {
516
710
  const required = query.required || [];
@@ -525,8 +719,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
525
719
  }
526
720
  if (hooks.headers) {
527
721
  const headers = unwrapReference(
528
- unwrapSchema(hooks.headers, vendors),
529
- definitions
722
+ unwrapSchema(hooks.headers, vendors, "input", openapiVersion),
723
+ definitions,
724
+ openapiVersion
530
725
  );
531
726
  if (headers && headers.type === "object" && headers.properties) {
532
727
  const required = headers.required || [];
@@ -541,8 +736,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
541
736
  }
542
737
  if (hooks.cookie) {
543
738
  const cookie = unwrapReference(
544
- unwrapSchema(hooks.cookie, vendors),
545
- definitions
739
+ unwrapSchema(hooks.cookie, vendors, "input", openapiVersion),
740
+ definitions,
741
+ openapiVersion
546
742
  );
547
743
  if (cookie && cookie.type === "object" && cookie.properties) {
548
744
  const required = cookie.required || [];
@@ -557,11 +753,17 @@ function toOpenAPISchema(app, exclude, references, vendors) {
557
753
  }
558
754
  if (parameters.length > 0) operation.parameters = parameters;
559
755
  if (hooks.body && method !== "get" && method !== "head") {
560
- const body = unwrapSchema(hooks.body, vendors);
756
+ const body = unwrapSchema(
757
+ hooks.body,
758
+ vendors,
759
+ "input",
760
+ openapiVersion
761
+ );
561
762
  if (body) {
562
763
  const { type, description, $ref, ...options } = unwrapReference(
563
764
  body,
564
- definitions
765
+ definitions,
766
+ openapiVersion
565
767
  );
566
768
  if (hooks.parse) {
567
769
  const content = {};
@@ -589,6 +791,12 @@ function toOpenAPISchema(app, exclude, references, vendors) {
589
791
  schema: body
590
792
  };
591
793
  continue;
794
+ case "arrayBuffer":
795
+ case "application/octet-stream":
796
+ content["application/octet-stream"] = {
797
+ schema: body
798
+ };
799
+ continue;
592
800
  }
593
801
  }
594
802
  operation.requestBody = {
@@ -622,50 +830,26 @@ function toOpenAPISchema(app, exclude, references, vendors) {
622
830
  if (hooks.response) {
623
831
  operation.responses = {};
624
832
  if (typeof hooks.response === "object" && // TypeBox
625
- !hooks.response.type && !hooks.response.$ref && !hooks.response["~standard"]) {
833
+ !(import_typebox.Kind in hooks.response) && !hooks.response.type && !hooks.response.$ref && !hooks.response["~standard"]) {
626
834
  for (let [status, schema] of Object.entries(hooks.response)) {
627
- const response = unwrapSchema(schema, vendors, "output");
628
- if (!response) continue;
629
- const { type, description, $ref, ..._options } = unwrapReference(response, definitions);
630
- operation.responses[status] = {
631
- description: description ?? `Response for status ${status}`,
632
- content: type === "void" || type === "null" || type === "undefined" ? { type, description } : type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
633
- "text/plain": {
634
- schema: response
635
- }
636
- } : {
637
- "application/json": {
638
- schema: response
639
- }
640
- }
641
- };
835
+ const response = toResponseObject(
836
+ schema,
837
+ status,
838
+ definitions,
839
+ vendors,
840
+ openapiVersion
841
+ );
842
+ if (response) operation.responses[status] = response;
642
843
  }
643
844
  } else {
644
- const response = unwrapSchema(
845
+ const response = toResponseObject(
645
846
  hooks.response,
847
+ "200",
848
+ definitions,
646
849
  vendors,
647
- "output"
850
+ openapiVersion
648
851
  );
649
- if (response) {
650
- const {
651
- type: _type,
652
- description,
653
- ...options
654
- } = unwrapReference(response, definitions);
655
- const type = _type;
656
- operation.responses["200"] = {
657
- description: description ?? `Response for status 200`,
658
- content: type === "void" || type === "null" || type === "undefined" ? { type, description } : type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
659
- "text/plain": {
660
- schema: response
661
- }
662
- } : {
663
- "application/json": {
664
- schema: response
665
- }
666
- }
667
- };
668
- }
852
+ if (response) operation.responses["200"] = response;
669
853
  }
670
854
  }
671
855
  for (let path of getPossiblePath(route.path)) {
@@ -699,7 +883,12 @@ function toOpenAPISchema(app, exclude, references, vendors) {
699
883
  const schemas = /* @__PURE__ */ Object.create(null);
700
884
  if (definitions)
701
885
  for (const [name, schema] of Object.entries(definitions)) {
702
- const jsonSchema = unwrapSchema(schema, vendors);
886
+ const jsonSchema = unwrapSchema(
887
+ schema,
888
+ vendors,
889
+ "input",
890
+ openapiVersion
891
+ );
703
892
  if (jsonSchema) schemas[name] = jsonSchema;
704
893
  }
705
894
  return {
@@ -709,15 +898,26 @@ function toOpenAPISchema(app, exclude, references, vendors) {
709
898
  paths
710
899
  };
711
900
  }
712
- var withHeaders = (schema, headers) => Object.assign(schema, {
713
- headers
714
- });
901
+ var withHeaders = (schema, headers) => {
902
+ const clone = Object.create(
903
+ Object.getPrototypeOf(schema),
904
+ Object.getOwnPropertyDescriptors(schema)
905
+ );
906
+ Object.defineProperty(clone, "headers", {
907
+ value: headers,
908
+ enumerable: true,
909
+ configurable: true,
910
+ writable: true
911
+ });
912
+ return clone;
913
+ };
715
914
  // Annotate the CommonJS export names for ESM import in node:
716
915
  0 && (module.exports = {
717
916
  capitalize,
718
917
  enumToOpenApi,
719
918
  getLoosePath,
720
919
  getPossiblePath,
920
+ nullToOpenApi,
721
921
  toOpenAPISchema,
722
922
  unwrapSchema,
723
923
  withHeaders