@elysiajs/openapi 1.4.9 → 1.4.11
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/README.md +1 -1
- package/dist/cjs/gen/index.js +91 -59
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +9027 -446
- package/dist/cjs/openapi.d.ts +2 -1
- package/dist/cjs/openapi.js +113 -73
- package/dist/cjs/scalar/index.js +9 -2
- package/dist/cjs/types.d.ts +8 -0
- package/dist/gen/index.d.ts +6 -4
- package/dist/gen/index.mjs +81 -60
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +9032 -446
- package/dist/openapi.d.ts +2 -1
- package/dist/openapi.mjs +112 -73
- package/dist/scalar/index.d.ts +1 -1
- package/dist/scalar/index.mjs +9 -2
- package/dist/types.d.ts +8 -0
- package/package.json +1 -1
package/dist/openapi.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AnyElysia, type TSchema, type InputSchema } from 'elysia';
|
|
2
2
|
import type { OpenAPIV3 } from 'openapi-types';
|
|
3
|
-
import { type TProperties } from '@sinclair/typebox';
|
|
3
|
+
import { TAnySchema, type TProperties } from '@sinclair/typebox';
|
|
4
4
|
import type { AdditionalReferences, ElysiaOpenAPIConfig, MapJsonSchema } from './types';
|
|
5
5
|
export declare const capitalize: (word: string) => string;
|
|
6
6
|
/**
|
|
@@ -11,6 +11,7 @@ export declare const capitalize: (word: string) => string;
|
|
|
11
11
|
export declare const getPossiblePath: (path: string) => string[];
|
|
12
12
|
export declare const getLoosePath: (path: string) => string;
|
|
13
13
|
export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema) => OpenAPIV3.SchemaObject | undefined;
|
|
14
|
+
export declare const enumToOpenApi: <T extends TAnySchema | OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined>(_schema: T) => T;
|
|
14
15
|
/**
|
|
15
16
|
* Converts Elysia routes to OpenAPI 3.0.3 paths schema
|
|
16
17
|
* @param routes Array of Elysia route objects
|
package/dist/openapi.mjs
CHANGED
|
@@ -76,62 +76,98 @@ var unwrapReference = (schema, definitions) => {
|
|
|
76
76
|
if (!ref) return schema;
|
|
77
77
|
const name = ref.slice(ref.lastIndexOf("/") + 1);
|
|
78
78
|
if (ref && definitions[name]) schema = definitions[name];
|
|
79
|
-
return schema;
|
|
79
|
+
return enumToOpenApi(schema);
|
|
80
80
|
};
|
|
81
81
|
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
82
82
|
if (!schema) return;
|
|
83
83
|
if (typeof schema === "string") schema = toRef(schema);
|
|
84
|
-
if (Kind in schema) return schema;
|
|
84
|
+
if (Kind in schema) return enumToOpenApi(schema);
|
|
85
85
|
if (Kind in schema || !schema?.["~standard"]) return;
|
|
86
86
|
const vendor = schema["~standard"].vendor;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
94
|
-
);
|
|
95
|
-
if ("_zod" in schema) {
|
|
96
|
-
warned.zod4 = true;
|
|
87
|
+
try {
|
|
88
|
+
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
89
|
+
return enumToOpenApi(mapJsonSchema[vendor](schema));
|
|
90
|
+
switch (vendor) {
|
|
91
|
+
case "zod":
|
|
92
|
+
if (warned.zod4 || warned.zod3) break;
|
|
97
93
|
console.warn(
|
|
98
|
-
"
|
|
94
|
+
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
99
95
|
);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
if ("_zod" in schema) {
|
|
97
|
+
warned.zod4 = true;
|
|
98
|
+
console.warn(
|
|
99
|
+
"For Zod v4, please provide z.toJSONSchema as follows:\n"
|
|
100
|
+
);
|
|
101
|
+
console.warn(warnings.zod4);
|
|
102
|
+
} else {
|
|
103
|
+
warned.zod3 = true;
|
|
104
|
+
console.warn(
|
|
105
|
+
"For Zod v3, please install zod-to-json-schema package and use it like this:\n"
|
|
106
|
+
);
|
|
107
|
+
console.warn(warnings.zod3);
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
case "valibot":
|
|
111
|
+
if (warned.valibot) break;
|
|
112
|
+
warned.valibot = true;
|
|
103
113
|
console.warn(
|
|
104
|
-
"
|
|
114
|
+
"[@elysiajs/openapi] Valibot require a separate package for JSON Schema conversion"
|
|
105
115
|
);
|
|
106
|
-
console.warn(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
116
|
+
console.warn(
|
|
117
|
+
"Please install @valibot/to-json-schema package and use it like this:\n"
|
|
118
|
+
);
|
|
119
|
+
console.warn(warnings.valibot);
|
|
120
|
+
break;
|
|
121
|
+
case "effect":
|
|
122
|
+
if (warned.effect) break;
|
|
123
|
+
warned.effect = true;
|
|
124
|
+
console.warn(
|
|
125
|
+
"[@elysiajs/openapi] Effect Schema doesn't provide JSON Schema method on the schema"
|
|
126
|
+
);
|
|
127
|
+
console.warn(
|
|
128
|
+
"please provide JSONSchema from 'effect' package as follows:\n"
|
|
129
|
+
);
|
|
130
|
+
console.warn(warnings.effect);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
if (vendor === "arktype")
|
|
134
|
+
return enumToOpenApi(schema?.toJsonSchema?.());
|
|
135
|
+
return enumToOpenApi(
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
schema.toJSONSchema?.() ?? schema?.toJsonSchema?.()
|
|
138
|
+
);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.warn(error);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
var enumToOpenApi = (_schema) => {
|
|
144
|
+
if (!_schema || typeof _schema !== "object") return _schema;
|
|
145
|
+
if (Kind in _schema) {
|
|
146
|
+
const schema2 = _schema;
|
|
147
|
+
if (schema2[Kind] === "Union" && schema2.anyOf && Array.isArray(schema2.anyOf) && schema2.anyOf.length > 0 && schema2.anyOf.every(
|
|
148
|
+
(item) => item && typeof item === "object" && item.const !== void 0
|
|
149
|
+
))
|
|
150
|
+
return {
|
|
151
|
+
type: "string",
|
|
152
|
+
enum: schema2.anyOf.map((item) => item.const)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const schema = _schema;
|
|
156
|
+
if (schema.type === "object" && schema.properties) {
|
|
157
|
+
const properties = {};
|
|
158
|
+
for (const [key, value] of Object.entries(schema.properties))
|
|
159
|
+
properties[key] = enumToOpenApi(value);
|
|
160
|
+
return {
|
|
161
|
+
...schema,
|
|
162
|
+
properties
|
|
163
|
+
};
|
|
131
164
|
}
|
|
132
|
-
if (
|
|
133
|
-
return
|
|
134
|
-
|
|
165
|
+
if (schema.type === "array" && schema.items)
|
|
166
|
+
return {
|
|
167
|
+
...schema,
|
|
168
|
+
items: enumToOpenApi(schema.items)
|
|
169
|
+
};
|
|
170
|
+
return schema;
|
|
135
171
|
};
|
|
136
172
|
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
137
173
|
let {
|
|
@@ -204,16 +240,24 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
204
240
|
definitions
|
|
205
241
|
);
|
|
206
242
|
if (params && params.type === "object" && params.properties)
|
|
207
|
-
for (const [
|
|
208
|
-
params.properties
|
|
209
|
-
))
|
|
243
|
+
for (const [name, schema] of Object.entries(params.properties))
|
|
210
244
|
parameters.push({
|
|
211
|
-
name
|
|
245
|
+
name,
|
|
212
246
|
in: "path",
|
|
213
247
|
required: true,
|
|
214
248
|
// Path parameters are always required
|
|
215
|
-
schema
|
|
249
|
+
schema
|
|
216
250
|
});
|
|
251
|
+
} else {
|
|
252
|
+
for (const match of route.path.matchAll(/:([^/]+)/g)) {
|
|
253
|
+
const name = match[1].replace("?", "");
|
|
254
|
+
parameters.push({
|
|
255
|
+
name,
|
|
256
|
+
in: "path",
|
|
257
|
+
required: true,
|
|
258
|
+
schema: { type: "string" }
|
|
259
|
+
});
|
|
260
|
+
}
|
|
217
261
|
}
|
|
218
262
|
if (hooks.query) {
|
|
219
263
|
const query = unwrapReference(
|
|
@@ -222,32 +266,28 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
222
266
|
);
|
|
223
267
|
if (query && query.type === "object" && query.properties) {
|
|
224
268
|
const required = query.required || [];
|
|
225
|
-
for (const [
|
|
226
|
-
query.properties
|
|
227
|
-
))
|
|
269
|
+
for (const [name, schema] of Object.entries(query.properties))
|
|
228
270
|
parameters.push({
|
|
229
|
-
name
|
|
271
|
+
name,
|
|
230
272
|
in: "query",
|
|
231
|
-
required: required.includes(
|
|
232
|
-
schema
|
|
273
|
+
required: required.includes(name),
|
|
274
|
+
schema
|
|
233
275
|
});
|
|
234
276
|
}
|
|
235
277
|
}
|
|
236
278
|
if (hooks.headers) {
|
|
237
279
|
const headers = unwrapReference(
|
|
238
|
-
unwrapSchema(hooks.
|
|
280
|
+
unwrapSchema(hooks.headers, vendors),
|
|
239
281
|
definitions
|
|
240
282
|
);
|
|
241
283
|
if (headers && headers.type === "object" && headers.properties) {
|
|
242
284
|
const required = headers.required || [];
|
|
243
|
-
for (const [
|
|
244
|
-
headers.properties
|
|
245
|
-
))
|
|
285
|
+
for (const [name, schema] of Object.entries(headers.properties))
|
|
246
286
|
parameters.push({
|
|
247
|
-
name
|
|
287
|
+
name,
|
|
248
288
|
in: "header",
|
|
249
|
-
required: required.includes(
|
|
250
|
-
schema
|
|
289
|
+
required: required.includes(name),
|
|
290
|
+
schema
|
|
251
291
|
});
|
|
252
292
|
}
|
|
253
293
|
}
|
|
@@ -258,14 +298,12 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
258
298
|
);
|
|
259
299
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
260
300
|
const required = cookie.required || [];
|
|
261
|
-
for (const [
|
|
262
|
-
cookie.properties
|
|
263
|
-
))
|
|
301
|
+
for (const [name, schema] of Object.entries(cookie.properties))
|
|
264
302
|
parameters.push({
|
|
265
|
-
name
|
|
303
|
+
name,
|
|
266
304
|
in: "cookie",
|
|
267
|
-
required: required.includes(
|
|
268
|
-
schema
|
|
305
|
+
required: required.includes(name),
|
|
306
|
+
schema
|
|
269
307
|
});
|
|
270
308
|
}
|
|
271
309
|
}
|
|
@@ -313,6 +351,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
313
351
|
} else {
|
|
314
352
|
operation.requestBody = {
|
|
315
353
|
description,
|
|
354
|
+
required: true,
|
|
316
355
|
content: type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
|
|
317
356
|
"text/plain": {
|
|
318
357
|
schema: body
|
|
@@ -327,8 +366,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
327
366
|
"multipart/form-data": {
|
|
328
367
|
schema: body
|
|
329
368
|
}
|
|
330
|
-
}
|
|
331
|
-
required: true
|
|
369
|
+
}
|
|
332
370
|
};
|
|
333
371
|
}
|
|
334
372
|
}
|
|
@@ -340,7 +378,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
340
378
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
341
379
|
const response = unwrapSchema(schema, vendors);
|
|
342
380
|
if (!response) continue;
|
|
343
|
-
const { type, description, $ref, ...
|
|
381
|
+
const { type, description, $ref, ..._options } = unwrapReference(response, definitions);
|
|
344
382
|
operation.responses[status] = {
|
|
345
383
|
description: description ?? `Response for status ${status}`,
|
|
346
384
|
content: type === "void" || type === "null" || type === "undefined" ? { type, description } : type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
|
|
@@ -379,7 +417,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
379
417
|
}
|
|
380
418
|
}
|
|
381
419
|
for (let path of getPossiblePath(route.path)) {
|
|
382
|
-
const operationId = toOperationId(route.method, path);
|
|
420
|
+
const operationId = hooks.detail?.operationId ?? toOperationId(route.method, path);
|
|
383
421
|
path = path.replace(/:([^/]+)/g, "{$1}");
|
|
384
422
|
if (!paths[path]) paths[path] = {};
|
|
385
423
|
const current = paths[path];
|
|
@@ -424,6 +462,7 @@ var withHeaders = (schema, headers) => Object.assign(schema, {
|
|
|
424
462
|
});
|
|
425
463
|
export {
|
|
426
464
|
capitalize,
|
|
465
|
+
enumToOpenApi,
|
|
427
466
|
getLoosePath,
|
|
428
467
|
getPossiblePath,
|
|
429
468
|
toOpenAPISchema,
|
package/dist/scalar/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from 'openapi-types';
|
|
2
2
|
import { ElysiaOpenAPIConfig } from '../types';
|
|
3
|
-
export declare const ScalarRender: (info: OpenAPIV3.InfoObject, config: NonNullable<ElysiaOpenAPIConfig["scalar"]
|
|
3
|
+
export declare const ScalarRender: (info: OpenAPIV3.InfoObject, config: NonNullable<ElysiaOpenAPIConfig["scalar"]>, embedSpec?: string) => string;
|
package/dist/scalar/index.mjs
CHANGED
|
@@ -119,7 +119,7 @@ var elysiaCSS = `.light-mode {
|
|
|
119
119
|
background-image: var(--stripes), var(--rainbow);
|
|
120
120
|
filter: opacity(4%) saturate(200%);
|
|
121
121
|
}`;
|
|
122
|
-
var ScalarRender = (info, config) => `<!doctype html>
|
|
122
|
+
var ScalarRender = (info, config, embedSpec) => `<!doctype html>
|
|
123
123
|
<html>
|
|
124
124
|
<head>
|
|
125
125
|
<title>${info.title}</title>
|
|
@@ -147,7 +147,14 @@ var ScalarRender = (info, config) => `<!doctype html>
|
|
|
147
147
|
<body>
|
|
148
148
|
<script
|
|
149
149
|
id="api-reference"
|
|
150
|
-
data-
|
|
150
|
+
data-configuration='${JSON.stringify(
|
|
151
|
+
Object.assign(
|
|
152
|
+
config,
|
|
153
|
+
{
|
|
154
|
+
content: embedSpec
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
)}'
|
|
151
158
|
>
|
|
152
159
|
</script>
|
|
153
160
|
<script src="${config.cdn}" crossorigin></script>
|
package/dist/types.d.ts
CHANGED
|
@@ -74,6 +74,14 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
74
74
|
* Additional reference for each endpoint
|
|
75
75
|
*/
|
|
76
76
|
references?: AdditionalReferences;
|
|
77
|
+
/**
|
|
78
|
+
* Embed OpenAPI schema to provider body if possible
|
|
79
|
+
*
|
|
80
|
+
* This is highly discouraged, unless you really have to inline OpenAPI schema
|
|
81
|
+
*
|
|
82
|
+
* @default false
|
|
83
|
+
*/
|
|
84
|
+
embedSpec?: boolean;
|
|
77
85
|
/**
|
|
78
86
|
* Mapping function from Standard schema to OpenAPI schema
|
|
79
87
|
*
|