@elysiajs/openapi 1.4.0 → 1.4.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/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +23 -24
- package/dist/cjs/openapi.d.ts +4 -6
- package/dist/cjs/openapi.js +19 -21
- package/dist/cjs/types.d.ts +18 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +23 -24
- package/dist/openapi.d.ts +4 -6
- package/dist/openapi.mjs +19 -21
- package/dist/types.d.ts +18 -0
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ElysiaOpenAPIConfig, OpenAPIProvider } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* @see https://github.com/elysiajs/elysia-swagger
|
|
7
7
|
*/
|
|
8
|
-
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi", const Provider extends OpenAPIProvider = "scalar">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references }?: ElysiaOpenAPIConfig<Enabled, Path, Provider>) => Elysia<"", {
|
|
8
|
+
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi", const Provider extends OpenAPIProvider = "scalar">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references, mapJsonSchema }?: ElysiaOpenAPIConfig<Enabled, Path, Provider>) => Elysia<"", {
|
|
9
9
|
decorator: {};
|
|
10
10
|
store: {};
|
|
11
11
|
derive: {};
|
package/dist/cjs/index.js
CHANGED
|
@@ -295,7 +295,6 @@ var Hint = Symbol.for("TypeBox.Hint");
|
|
|
295
295
|
var Kind = Symbol.for("TypeBox.Kind");
|
|
296
296
|
|
|
297
297
|
// src/openapi.ts
|
|
298
|
-
var import_xsschema = require("xsschema");
|
|
299
298
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
300
299
|
var toRef = (name) => import_elysia.t.Ref(`#/components/schemas/${name}`);
|
|
301
300
|
var toOperationId = (method, paths) => {
|
|
@@ -324,14 +323,21 @@ var getLoosePath = (path) => {
|
|
|
324
323
|
return path.slice(0, path.length - 1);
|
|
325
324
|
return path + "/";
|
|
326
325
|
};
|
|
327
|
-
var unwrapSchema = (schema) => {
|
|
326
|
+
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
328
327
|
if (!schema) return;
|
|
329
328
|
if (typeof schema === "string") schema = toRef(schema);
|
|
330
329
|
if (Kind in schema) return schema;
|
|
331
|
-
if (Kind in schema
|
|
332
|
-
|
|
330
|
+
if (Kind in schema || !schema?.["~standard"]) return;
|
|
331
|
+
const vendor = schema["~standard"].vendor;
|
|
332
|
+
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
333
|
+
return mapJsonSchema[vendor](schema);
|
|
334
|
+
if (vendor === "zod" || vendor === "sury")
|
|
335
|
+
return schema.toJSONSchema?.();
|
|
336
|
+
if (vendor === "arktype")
|
|
337
|
+
return schema?.toJsonSchema?.();
|
|
338
|
+
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
333
339
|
};
|
|
334
|
-
|
|
340
|
+
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
335
341
|
const {
|
|
336
342
|
methods: excludeMethods = ["OPTIONS"],
|
|
337
343
|
staticFile: excludeStaticFile = true,
|
|
@@ -384,8 +390,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
384
390
|
};
|
|
385
391
|
const parameters = [];
|
|
386
392
|
if (hooks.params) {
|
|
387
|
-
|
|
388
|
-
if (params) params = await params;
|
|
393
|
+
const params = unwrapSchema(hooks.params, vendors);
|
|
389
394
|
if (params && params.type === "object" && params.properties)
|
|
390
395
|
for (const [paramName, paramSchema] of Object.entries(
|
|
391
396
|
params.properties
|
|
@@ -399,8 +404,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
399
404
|
});
|
|
400
405
|
}
|
|
401
406
|
if (hooks.query) {
|
|
402
|
-
let query = unwrapSchema(hooks.query);
|
|
403
|
-
if (query) query = await query;
|
|
407
|
+
let query = unwrapSchema(hooks.query, vendors);
|
|
404
408
|
if (query && query.type === "object" && query.properties) {
|
|
405
409
|
const required = query.required || [];
|
|
406
410
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -415,8 +419,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
415
419
|
}
|
|
416
420
|
}
|
|
417
421
|
if (hooks.headers) {
|
|
418
|
-
|
|
419
|
-
if (headers) headers = await headers;
|
|
422
|
+
const headers = unwrapSchema(hooks.query, vendors);
|
|
420
423
|
if (headers && headers.type === "object" && headers.properties) {
|
|
421
424
|
const required = headers.required || [];
|
|
422
425
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -431,8 +434,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
431
434
|
}
|
|
432
435
|
}
|
|
433
436
|
if (hooks.cookie) {
|
|
434
|
-
|
|
435
|
-
if (cookie) cookie = await cookie;
|
|
437
|
+
const cookie = unwrapSchema(hooks.cookie, vendors);
|
|
436
438
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
437
439
|
const required = cookie.required || [];
|
|
438
440
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -448,8 +450,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
448
450
|
}
|
|
449
451
|
if (parameters.length > 0) operation.parameters = parameters;
|
|
450
452
|
if (hooks.body && method !== "get" && method !== "head") {
|
|
451
|
-
|
|
452
|
-
if (body) body = await body;
|
|
453
|
+
const body = unwrapSchema(hooks.body, vendors);
|
|
453
454
|
if (body) {
|
|
454
455
|
const { type: _type, description, ...options } = body;
|
|
455
456
|
const type = _type;
|
|
@@ -511,8 +512,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
511
512
|
operation.responses = {};
|
|
512
513
|
if (typeof hooks.response === "object" && !hooks.response.type && !hooks.response.$ref) {
|
|
513
514
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
514
|
-
|
|
515
|
-
if (response) response = await response;
|
|
515
|
+
const response = unwrapSchema(schema, vendors);
|
|
516
516
|
if (!response) continue;
|
|
517
517
|
const { type: _type, description, ...options } = response;
|
|
518
518
|
const type = _type;
|
|
@@ -531,8 +531,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
531
531
|
};
|
|
532
532
|
}
|
|
533
533
|
} else {
|
|
534
|
-
|
|
535
|
-
if (response) response = await response;
|
|
534
|
+
const response = unwrapSchema(hooks.response, vendors);
|
|
536
535
|
if (response) {
|
|
537
536
|
const { type: _type, description, ...options } = response;
|
|
538
537
|
const type = _type;
|
|
@@ -583,8 +582,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
583
582
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
584
583
|
if (_schemas)
|
|
585
584
|
for (const [name, schema] of Object.entries(_schemas)) {
|
|
586
|
-
|
|
587
|
-
if (jsonSchema instanceof Promise) jsonSchema = await jsonSchema;
|
|
585
|
+
const jsonSchema = unwrapSchema(schema, vendors);
|
|
588
586
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
589
587
|
}
|
|
590
588
|
return {
|
|
@@ -608,7 +606,8 @@ var openapi = ({
|
|
|
608
606
|
exclude,
|
|
609
607
|
swagger,
|
|
610
608
|
scalar,
|
|
611
|
-
references
|
|
609
|
+
references,
|
|
610
|
+
mapJsonSchema
|
|
612
611
|
} = {}) => {
|
|
613
612
|
if (!enabled) return new import_elysia2.Elysia({ name: "@elysiajs/openapi" });
|
|
614
613
|
const info = {
|
|
@@ -652,13 +651,13 @@ var openapi = ({
|
|
|
652
651
|
);
|
|
653
652
|
}).get(
|
|
654
653
|
specPath,
|
|
655
|
-
|
|
654
|
+
function openAPISchema() {
|
|
656
655
|
if (totalRoutes === app.routes.length) return cachedSchema;
|
|
657
656
|
totalRoutes = app.routes.length;
|
|
658
657
|
const {
|
|
659
658
|
paths,
|
|
660
659
|
components: { schemas }
|
|
661
|
-
} =
|
|
660
|
+
} = toOpenAPISchema(app, exclude, references, mapJsonSchema);
|
|
662
661
|
return cachedSchema = {
|
|
663
662
|
openapi: "3.0.3",
|
|
664
663
|
...documentation,
|
package/dist/cjs/openapi.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AnyElysia, type TSchema, type InputSchema } from 'elysia';
|
|
2
2
|
import type { OpenAPIV3 } from 'openapi-types';
|
|
3
3
|
import { type TProperties } from '@sinclair/typebox';
|
|
4
|
-
import type { AdditionalReferences, ElysiaOpenAPIConfig } from './types';
|
|
4
|
+
import type { AdditionalReferences, ElysiaOpenAPIConfig, MapJsonSchema } 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,20 +10,18 @@ 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
|
-
|
|
14
|
-
export declare const unwrapSchema: (schema: InputSchema["body"]) => MaybePromise<OpenAPIV3.SchemaObject | undefined>;
|
|
13
|
+
export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema) => OpenAPIV3.SchemaObject | undefined;
|
|
15
14
|
/**
|
|
16
15
|
* Converts Elysia routes to OpenAPI 3.0.3 paths schema
|
|
17
16
|
* @param routes Array of Elysia route objects
|
|
18
17
|
* @returns OpenAPI paths object
|
|
19
18
|
*/
|
|
20
|
-
export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences):
|
|
19
|
+
export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences, vendors?: MapJsonSchema): {
|
|
21
20
|
components: {
|
|
22
21
|
schemas: any;
|
|
23
22
|
};
|
|
24
23
|
paths: OpenAPIV3.PathsObject<{}, {}>;
|
|
25
|
-
}
|
|
24
|
+
};
|
|
26
25
|
export declare const withHeaders: (schema: TSchema, headers: TProperties) => TSchema & {
|
|
27
26
|
headers: TProperties;
|
|
28
27
|
};
|
|
29
|
-
export {};
|
package/dist/cjs/openapi.js
CHANGED
|
@@ -38,7 +38,6 @@ var Hint = Symbol.for("TypeBox.Hint");
|
|
|
38
38
|
var Kind = Symbol.for("TypeBox.Kind");
|
|
39
39
|
|
|
40
40
|
// src/openapi.ts
|
|
41
|
-
var import_xsschema = require("xsschema");
|
|
42
41
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
43
42
|
var toRef = (name) => import_elysia.t.Ref(`#/components/schemas/${name}`);
|
|
44
43
|
var toOperationId = (method, paths) => {
|
|
@@ -67,14 +66,21 @@ var getLoosePath = (path) => {
|
|
|
67
66
|
return path.slice(0, path.length - 1);
|
|
68
67
|
return path + "/";
|
|
69
68
|
};
|
|
70
|
-
var unwrapSchema = (schema) => {
|
|
69
|
+
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
71
70
|
if (!schema) return;
|
|
72
71
|
if (typeof schema === "string") schema = toRef(schema);
|
|
73
72
|
if (Kind in schema) return schema;
|
|
74
|
-
if (Kind in schema
|
|
75
|
-
|
|
73
|
+
if (Kind in schema || !schema?.["~standard"]) return;
|
|
74
|
+
const vendor = schema["~standard"].vendor;
|
|
75
|
+
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
76
|
+
return mapJsonSchema[vendor](schema);
|
|
77
|
+
if (vendor === "zod" || vendor === "sury")
|
|
78
|
+
return schema.toJSONSchema?.();
|
|
79
|
+
if (vendor === "arktype")
|
|
80
|
+
return schema?.toJsonSchema?.();
|
|
81
|
+
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
76
82
|
};
|
|
77
|
-
|
|
83
|
+
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
78
84
|
const {
|
|
79
85
|
methods: excludeMethods = ["OPTIONS"],
|
|
80
86
|
staticFile: excludeStaticFile = true,
|
|
@@ -127,8 +133,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
127
133
|
};
|
|
128
134
|
const parameters = [];
|
|
129
135
|
if (hooks.params) {
|
|
130
|
-
|
|
131
|
-
if (params) params = await params;
|
|
136
|
+
const params = unwrapSchema(hooks.params, vendors);
|
|
132
137
|
if (params && params.type === "object" && params.properties)
|
|
133
138
|
for (const [paramName, paramSchema] of Object.entries(
|
|
134
139
|
params.properties
|
|
@@ -142,8 +147,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
142
147
|
});
|
|
143
148
|
}
|
|
144
149
|
if (hooks.query) {
|
|
145
|
-
let query = unwrapSchema(hooks.query);
|
|
146
|
-
if (query) query = await query;
|
|
150
|
+
let query = unwrapSchema(hooks.query, vendors);
|
|
147
151
|
if (query && query.type === "object" && query.properties) {
|
|
148
152
|
const required = query.required || [];
|
|
149
153
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -158,8 +162,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
158
162
|
}
|
|
159
163
|
}
|
|
160
164
|
if (hooks.headers) {
|
|
161
|
-
|
|
162
|
-
if (headers) headers = await headers;
|
|
165
|
+
const headers = unwrapSchema(hooks.query, vendors);
|
|
163
166
|
if (headers && headers.type === "object" && headers.properties) {
|
|
164
167
|
const required = headers.required || [];
|
|
165
168
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -174,8 +177,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
if (hooks.cookie) {
|
|
177
|
-
|
|
178
|
-
if (cookie) cookie = await cookie;
|
|
180
|
+
const cookie = unwrapSchema(hooks.cookie, vendors);
|
|
179
181
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
180
182
|
const required = cookie.required || [];
|
|
181
183
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -191,8 +193,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
191
193
|
}
|
|
192
194
|
if (parameters.length > 0) operation.parameters = parameters;
|
|
193
195
|
if (hooks.body && method !== "get" && method !== "head") {
|
|
194
|
-
|
|
195
|
-
if (body) body = await body;
|
|
196
|
+
const body = unwrapSchema(hooks.body, vendors);
|
|
196
197
|
if (body) {
|
|
197
198
|
const { type: _type, description, ...options } = body;
|
|
198
199
|
const type = _type;
|
|
@@ -254,8 +255,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
254
255
|
operation.responses = {};
|
|
255
256
|
if (typeof hooks.response === "object" && !hooks.response.type && !hooks.response.$ref) {
|
|
256
257
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
257
|
-
|
|
258
|
-
if (response) response = await response;
|
|
258
|
+
const response = unwrapSchema(schema, vendors);
|
|
259
259
|
if (!response) continue;
|
|
260
260
|
const { type: _type, description, ...options } = response;
|
|
261
261
|
const type = _type;
|
|
@@ -274,8 +274,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
276
|
} else {
|
|
277
|
-
|
|
278
|
-
if (response) response = await response;
|
|
277
|
+
const response = unwrapSchema(hooks.response, vendors);
|
|
279
278
|
if (response) {
|
|
280
279
|
const { type: _type, description, ...options } = response;
|
|
281
280
|
const type = _type;
|
|
@@ -326,8 +325,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
326
325
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
327
326
|
if (_schemas)
|
|
328
327
|
for (const [name, schema] of Object.entries(_schemas)) {
|
|
329
|
-
|
|
330
|
-
if (jsonSchema instanceof Promise) jsonSchema = await jsonSchema;
|
|
328
|
+
const jsonSchema = unwrapSchema(schema, vendors);
|
|
331
329
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
332
330
|
}
|
|
333
331
|
return {
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import type { ApiReferenceConfiguration } from '@scalar/types';
|
|
|
4
4
|
import type { SwaggerUIOptions } from './swagger/types';
|
|
5
5
|
export type OpenAPIProvider = 'scalar' | 'swagger-ui' | null;
|
|
6
6
|
type MaybeArray<T> = T | T[];
|
|
7
|
+
export type MapJsonSchema = {
|
|
8
|
+
[vendor: string]: Function;
|
|
9
|
+
};
|
|
7
10
|
export type AdditionalReference = {
|
|
8
11
|
[path in string]: {
|
|
9
12
|
[method in string]: {
|
|
@@ -69,6 +72,21 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
69
72
|
* Additional reference for each endpoint
|
|
70
73
|
*/
|
|
71
74
|
references?: AdditionalReferences;
|
|
75
|
+
/**
|
|
76
|
+
* Mapping function from Standard schema to OpenAPI schema
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { openapi } from '@elysiajs/openapi'
|
|
81
|
+
* import { toJsonSchema } from '@valibot/to-json-schema'
|
|
82
|
+
*
|
|
83
|
+
* openapi({
|
|
84
|
+
* vendors: {
|
|
85
|
+
* valibot: toJsonSchema
|
|
86
|
+
* }
|
|
87
|
+
* })
|
|
88
|
+
*/
|
|
89
|
+
mapJsonSchema?: MapJsonSchema;
|
|
72
90
|
/**
|
|
73
91
|
* Scalar configuration to customize scalar
|
|
74
92
|
*'
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ElysiaOpenAPIConfig, OpenAPIProvider } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* @see https://github.com/elysiajs/elysia-swagger
|
|
7
7
|
*/
|
|
8
|
-
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi", const Provider extends OpenAPIProvider = "scalar">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references }?: ElysiaOpenAPIConfig<Enabled, Path, Provider>) => Elysia<"", {
|
|
8
|
+
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi", const Provider extends OpenAPIProvider = "scalar">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references, mapJsonSchema }?: ElysiaOpenAPIConfig<Enabled, Path, Provider>) => Elysia<"", {
|
|
9
9
|
decorator: {};
|
|
10
10
|
store: {};
|
|
11
11
|
derive: {};
|
package/dist/index.mjs
CHANGED
|
@@ -268,7 +268,6 @@ var Hint = Symbol.for("TypeBox.Hint");
|
|
|
268
268
|
var Kind = Symbol.for("TypeBox.Kind");
|
|
269
269
|
|
|
270
270
|
// src/openapi.ts
|
|
271
|
-
import { toJsonSchema } from "xsschema";
|
|
272
271
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
273
272
|
var toRef = (name) => t.Ref(`#/components/schemas/${name}`);
|
|
274
273
|
var toOperationId = (method, paths) => {
|
|
@@ -297,14 +296,21 @@ var getLoosePath = (path) => {
|
|
|
297
296
|
return path.slice(0, path.length - 1);
|
|
298
297
|
return path + "/";
|
|
299
298
|
};
|
|
300
|
-
var unwrapSchema = (schema) => {
|
|
299
|
+
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
301
300
|
if (!schema) return;
|
|
302
301
|
if (typeof schema === "string") schema = toRef(schema);
|
|
303
302
|
if (Kind in schema) return schema;
|
|
304
|
-
if (Kind in schema
|
|
305
|
-
|
|
303
|
+
if (Kind in schema || !schema?.["~standard"]) return;
|
|
304
|
+
const vendor = schema["~standard"].vendor;
|
|
305
|
+
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
306
|
+
return mapJsonSchema[vendor](schema);
|
|
307
|
+
if (vendor === "zod" || vendor === "sury")
|
|
308
|
+
return schema.toJSONSchema?.();
|
|
309
|
+
if (vendor === "arktype")
|
|
310
|
+
return schema?.toJsonSchema?.();
|
|
311
|
+
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
306
312
|
};
|
|
307
|
-
|
|
313
|
+
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
308
314
|
const {
|
|
309
315
|
methods: excludeMethods = ["OPTIONS"],
|
|
310
316
|
staticFile: excludeStaticFile = true,
|
|
@@ -357,8 +363,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
357
363
|
};
|
|
358
364
|
const parameters = [];
|
|
359
365
|
if (hooks.params) {
|
|
360
|
-
|
|
361
|
-
if (params) params = await params;
|
|
366
|
+
const params = unwrapSchema(hooks.params, vendors);
|
|
362
367
|
if (params && params.type === "object" && params.properties)
|
|
363
368
|
for (const [paramName, paramSchema] of Object.entries(
|
|
364
369
|
params.properties
|
|
@@ -372,8 +377,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
372
377
|
});
|
|
373
378
|
}
|
|
374
379
|
if (hooks.query) {
|
|
375
|
-
let query = unwrapSchema(hooks.query);
|
|
376
|
-
if (query) query = await query;
|
|
380
|
+
let query = unwrapSchema(hooks.query, vendors);
|
|
377
381
|
if (query && query.type === "object" && query.properties) {
|
|
378
382
|
const required = query.required || [];
|
|
379
383
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -388,8 +392,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
388
392
|
}
|
|
389
393
|
}
|
|
390
394
|
if (hooks.headers) {
|
|
391
|
-
|
|
392
|
-
if (headers) headers = await headers;
|
|
395
|
+
const headers = unwrapSchema(hooks.query, vendors);
|
|
393
396
|
if (headers && headers.type === "object" && headers.properties) {
|
|
394
397
|
const required = headers.required || [];
|
|
395
398
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -404,8 +407,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
404
407
|
}
|
|
405
408
|
}
|
|
406
409
|
if (hooks.cookie) {
|
|
407
|
-
|
|
408
|
-
if (cookie) cookie = await cookie;
|
|
410
|
+
const cookie = unwrapSchema(hooks.cookie, vendors);
|
|
409
411
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
410
412
|
const required = cookie.required || [];
|
|
411
413
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -421,8 +423,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
421
423
|
}
|
|
422
424
|
if (parameters.length > 0) operation.parameters = parameters;
|
|
423
425
|
if (hooks.body && method !== "get" && method !== "head") {
|
|
424
|
-
|
|
425
|
-
if (body) body = await body;
|
|
426
|
+
const body = unwrapSchema(hooks.body, vendors);
|
|
426
427
|
if (body) {
|
|
427
428
|
const { type: _type, description, ...options } = body;
|
|
428
429
|
const type = _type;
|
|
@@ -484,8 +485,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
484
485
|
operation.responses = {};
|
|
485
486
|
if (typeof hooks.response === "object" && !hooks.response.type && !hooks.response.$ref) {
|
|
486
487
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
487
|
-
|
|
488
|
-
if (response) response = await response;
|
|
488
|
+
const response = unwrapSchema(schema, vendors);
|
|
489
489
|
if (!response) continue;
|
|
490
490
|
const { type: _type, description, ...options } = response;
|
|
491
491
|
const type = _type;
|
|
@@ -504,8 +504,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
504
504
|
};
|
|
505
505
|
}
|
|
506
506
|
} else {
|
|
507
|
-
|
|
508
|
-
if (response) response = await response;
|
|
507
|
+
const response = unwrapSchema(hooks.response, vendors);
|
|
509
508
|
if (response) {
|
|
510
509
|
const { type: _type, description, ...options } = response;
|
|
511
510
|
const type = _type;
|
|
@@ -556,8 +555,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
556
555
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
557
556
|
if (_schemas)
|
|
558
557
|
for (const [name, schema] of Object.entries(_schemas)) {
|
|
559
|
-
|
|
560
|
-
if (jsonSchema instanceof Promise) jsonSchema = await jsonSchema;
|
|
558
|
+
const jsonSchema = unwrapSchema(schema, vendors);
|
|
561
559
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
562
560
|
}
|
|
563
561
|
return {
|
|
@@ -581,7 +579,8 @@ var openapi = ({
|
|
|
581
579
|
exclude,
|
|
582
580
|
swagger,
|
|
583
581
|
scalar,
|
|
584
|
-
references
|
|
582
|
+
references,
|
|
583
|
+
mapJsonSchema
|
|
585
584
|
} = {}) => {
|
|
586
585
|
if (!enabled) return new Elysia({ name: "@elysiajs/openapi" });
|
|
587
586
|
const info = {
|
|
@@ -625,13 +624,13 @@ var openapi = ({
|
|
|
625
624
|
);
|
|
626
625
|
}).get(
|
|
627
626
|
specPath,
|
|
628
|
-
|
|
627
|
+
function openAPISchema() {
|
|
629
628
|
if (totalRoutes === app.routes.length) return cachedSchema;
|
|
630
629
|
totalRoutes = app.routes.length;
|
|
631
630
|
const {
|
|
632
631
|
paths,
|
|
633
632
|
components: { schemas }
|
|
634
|
-
} =
|
|
633
|
+
} = toOpenAPISchema(app, exclude, references, mapJsonSchema);
|
|
635
634
|
return cachedSchema = {
|
|
636
635
|
openapi: "3.0.3",
|
|
637
636
|
...documentation,
|
package/dist/openapi.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AnyElysia, type TSchema, type InputSchema } from 'elysia';
|
|
2
2
|
import type { OpenAPIV3 } from 'openapi-types';
|
|
3
3
|
import { type TProperties } from '@sinclair/typebox';
|
|
4
|
-
import type { AdditionalReferences, ElysiaOpenAPIConfig } from './types';
|
|
4
|
+
import type { AdditionalReferences, ElysiaOpenAPIConfig, MapJsonSchema } 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,20 +10,18 @@ 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
|
-
|
|
14
|
-
export declare const unwrapSchema: (schema: InputSchema["body"]) => MaybePromise<OpenAPIV3.SchemaObject | undefined>;
|
|
13
|
+
export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema) => OpenAPIV3.SchemaObject | undefined;
|
|
15
14
|
/**
|
|
16
15
|
* Converts Elysia routes to OpenAPI 3.0.3 paths schema
|
|
17
16
|
* @param routes Array of Elysia route objects
|
|
18
17
|
* @returns OpenAPI paths object
|
|
19
18
|
*/
|
|
20
|
-
export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences):
|
|
19
|
+
export declare function toOpenAPISchema(app: AnyElysia, exclude?: ElysiaOpenAPIConfig['exclude'], references?: AdditionalReferences, vendors?: MapJsonSchema): {
|
|
21
20
|
components: {
|
|
22
21
|
schemas: any;
|
|
23
22
|
};
|
|
24
23
|
paths: OpenAPIV3.PathsObject<{}, {}>;
|
|
25
|
-
}
|
|
24
|
+
};
|
|
26
25
|
export declare const withHeaders: (schema: TSchema, headers: TProperties) => TSchema & {
|
|
27
26
|
headers: TProperties;
|
|
28
27
|
};
|
|
29
|
-
export {};
|
package/dist/openapi.mjs
CHANGED
|
@@ -9,7 +9,6 @@ var Hint = Symbol.for("TypeBox.Hint");
|
|
|
9
9
|
var Kind = Symbol.for("TypeBox.Kind");
|
|
10
10
|
|
|
11
11
|
// src/openapi.ts
|
|
12
|
-
import { toJsonSchema } from "xsschema";
|
|
13
12
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
14
13
|
var toRef = (name) => t.Ref(`#/components/schemas/${name}`);
|
|
15
14
|
var toOperationId = (method, paths) => {
|
|
@@ -38,14 +37,21 @@ var getLoosePath = (path) => {
|
|
|
38
37
|
return path.slice(0, path.length - 1);
|
|
39
38
|
return path + "/";
|
|
40
39
|
};
|
|
41
|
-
var unwrapSchema = (schema) => {
|
|
40
|
+
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
42
41
|
if (!schema) return;
|
|
43
42
|
if (typeof schema === "string") schema = toRef(schema);
|
|
44
43
|
if (Kind in schema) return schema;
|
|
45
|
-
if (Kind in schema
|
|
46
|
-
|
|
44
|
+
if (Kind in schema || !schema?.["~standard"]) return;
|
|
45
|
+
const vendor = schema["~standard"].vendor;
|
|
46
|
+
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
47
|
+
return mapJsonSchema[vendor](schema);
|
|
48
|
+
if (vendor === "zod" || vendor === "sury")
|
|
49
|
+
return schema.toJSONSchema?.();
|
|
50
|
+
if (vendor === "arktype")
|
|
51
|
+
return schema?.toJsonSchema?.();
|
|
52
|
+
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
47
53
|
};
|
|
48
|
-
|
|
54
|
+
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
49
55
|
const {
|
|
50
56
|
methods: excludeMethods = ["OPTIONS"],
|
|
51
57
|
staticFile: excludeStaticFile = true,
|
|
@@ -98,8 +104,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
98
104
|
};
|
|
99
105
|
const parameters = [];
|
|
100
106
|
if (hooks.params) {
|
|
101
|
-
|
|
102
|
-
if (params) params = await params;
|
|
107
|
+
const params = unwrapSchema(hooks.params, vendors);
|
|
103
108
|
if (params && params.type === "object" && params.properties)
|
|
104
109
|
for (const [paramName, paramSchema] of Object.entries(
|
|
105
110
|
params.properties
|
|
@@ -113,8 +118,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
113
118
|
});
|
|
114
119
|
}
|
|
115
120
|
if (hooks.query) {
|
|
116
|
-
let query = unwrapSchema(hooks.query);
|
|
117
|
-
if (query) query = await query;
|
|
121
|
+
let query = unwrapSchema(hooks.query, vendors);
|
|
118
122
|
if (query && query.type === "object" && query.properties) {
|
|
119
123
|
const required = query.required || [];
|
|
120
124
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -129,8 +133,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
if (hooks.headers) {
|
|
132
|
-
|
|
133
|
-
if (headers) headers = await headers;
|
|
136
|
+
const headers = unwrapSchema(hooks.query, vendors);
|
|
134
137
|
if (headers && headers.type === "object" && headers.properties) {
|
|
135
138
|
const required = headers.required || [];
|
|
136
139
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -145,8 +148,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
if (hooks.cookie) {
|
|
148
|
-
|
|
149
|
-
if (cookie) cookie = await cookie;
|
|
151
|
+
const cookie = unwrapSchema(hooks.cookie, vendors);
|
|
150
152
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
151
153
|
const required = cookie.required || [];
|
|
152
154
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -162,8 +164,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
162
164
|
}
|
|
163
165
|
if (parameters.length > 0) operation.parameters = parameters;
|
|
164
166
|
if (hooks.body && method !== "get" && method !== "head") {
|
|
165
|
-
|
|
166
|
-
if (body) body = await body;
|
|
167
|
+
const body = unwrapSchema(hooks.body, vendors);
|
|
167
168
|
if (body) {
|
|
168
169
|
const { type: _type, description, ...options } = body;
|
|
169
170
|
const type = _type;
|
|
@@ -225,8 +226,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
225
226
|
operation.responses = {};
|
|
226
227
|
if (typeof hooks.response === "object" && !hooks.response.type && !hooks.response.$ref) {
|
|
227
228
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
228
|
-
|
|
229
|
-
if (response) response = await response;
|
|
229
|
+
const response = unwrapSchema(schema, vendors);
|
|
230
230
|
if (!response) continue;
|
|
231
231
|
const { type: _type, description, ...options } = response;
|
|
232
232
|
const type = _type;
|
|
@@ -245,8 +245,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
247
|
} else {
|
|
248
|
-
|
|
249
|
-
if (response) response = await response;
|
|
248
|
+
const response = unwrapSchema(hooks.response, vendors);
|
|
250
249
|
if (response) {
|
|
251
250
|
const { type: _type, description, ...options } = response;
|
|
252
251
|
const type = _type;
|
|
@@ -297,8 +296,7 @@ async function toOpenAPISchema(app, exclude, references) {
|
|
|
297
296
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
298
297
|
if (_schemas)
|
|
299
298
|
for (const [name, schema] of Object.entries(_schemas)) {
|
|
300
|
-
|
|
301
|
-
if (jsonSchema instanceof Promise) jsonSchema = await jsonSchema;
|
|
299
|
+
const jsonSchema = unwrapSchema(schema, vendors);
|
|
302
300
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
303
301
|
}
|
|
304
302
|
return {
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import type { ApiReferenceConfiguration } from '@scalar/types';
|
|
|
4
4
|
import type { SwaggerUIOptions } from './swagger/types';
|
|
5
5
|
export type OpenAPIProvider = 'scalar' | 'swagger-ui' | null;
|
|
6
6
|
type MaybeArray<T> = T | T[];
|
|
7
|
+
export type MapJsonSchema = {
|
|
8
|
+
[vendor: string]: Function;
|
|
9
|
+
};
|
|
7
10
|
export type AdditionalReference = {
|
|
8
11
|
[path in string]: {
|
|
9
12
|
[method in string]: {
|
|
@@ -69,6 +72,21 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
69
72
|
* Additional reference for each endpoint
|
|
70
73
|
*/
|
|
71
74
|
references?: AdditionalReferences;
|
|
75
|
+
/**
|
|
76
|
+
* Mapping function from Standard schema to OpenAPI schema
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { openapi } from '@elysiajs/openapi'
|
|
81
|
+
* import { toJsonSchema } from '@valibot/to-json-schema'
|
|
82
|
+
*
|
|
83
|
+
* openapi({
|
|
84
|
+
* vendors: {
|
|
85
|
+
* valibot: toJsonSchema
|
|
86
|
+
* }
|
|
87
|
+
* })
|
|
88
|
+
*/
|
|
89
|
+
mapJsonSchema?: MapJsonSchema;
|
|
72
90
|
/**
|
|
73
91
|
* Scalar configuration to customize scalar
|
|
74
92
|
*'
|