@elysiajs/openapi 1.4.10 → 1.4.12
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/bun.lock +79 -144
- package/dist/cjs/gen/index.js +1021 -344
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1308 -392
- package/dist/cjs/openapi.d.ts +1 -1
- package/dist/cjs/openapi.js +213 -9
- package/dist/cjs/scalar/index.js +9 -2
- package/dist/cjs/types.d.ts +8 -0
- package/dist/gen/index.mjs +1021 -344
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1308 -392
- package/dist/openapi.d.ts +1 -1
- package/dist/openapi.mjs +213 -9
- 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 +3 -3
package/dist/openapi.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ 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) => OpenAPIV3.SchemaObject | undefined;
|
|
13
|
+
export declare const unwrapSchema: (schema: InputSchema["body"], mapJsonSchema?: MapJsonSchema, io?: "input" | "output") => OpenAPIV3.SchemaObject | undefined;
|
|
14
14
|
export declare const enumToOpenApi: <T extends TAnySchema | OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined>(_schema: T) => T;
|
|
15
15
|
/**
|
|
16
16
|
* Converts Elysia routes to OpenAPI 3.0.3 paths schema
|
package/dist/openapi.mjs
CHANGED
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
import { t } from "elysia";
|
|
3
3
|
|
|
4
4
|
// node_modules/@sinclair/typebox/build/esm/type/symbols/symbols.mjs
|
|
5
|
-
var
|
|
6
|
-
var ReadonlyKind = Symbol.for("TypeBox.Readonly");
|
|
7
|
-
var OptionalKind = Symbol.for("TypeBox.Optional");
|
|
8
|
-
var Hint = Symbol.for("TypeBox.Hint");
|
|
9
|
-
var Kind = Symbol.for("TypeBox.Kind");
|
|
5
|
+
var Kind = /* @__PURE__ */ Symbol.for("TypeBox.Kind");
|
|
10
6
|
|
|
11
7
|
// src/openapi.ts
|
|
12
8
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
@@ -71,6 +67,212 @@ openapi({
|
|
|
71
67
|
})`
|
|
72
68
|
};
|
|
73
69
|
var warned = {};
|
|
70
|
+
var mergeObjectSchemas = (schemas) => {
|
|
71
|
+
if (schemas.length === 0)
|
|
72
|
+
return {
|
|
73
|
+
schema: void 0,
|
|
74
|
+
notObjects: []
|
|
75
|
+
};
|
|
76
|
+
if (schemas.length === 1)
|
|
77
|
+
return schemas[0].type === "object" ? {
|
|
78
|
+
schema: schemas[0],
|
|
79
|
+
notObjects: []
|
|
80
|
+
} : {
|
|
81
|
+
schema: void 0,
|
|
82
|
+
notObjects: schemas
|
|
83
|
+
};
|
|
84
|
+
let newSchema;
|
|
85
|
+
const notObjects = [];
|
|
86
|
+
let additionalPropertiesIsTrue = false;
|
|
87
|
+
let additionalPropertiesIsFalse = false;
|
|
88
|
+
for (const schema of schemas) {
|
|
89
|
+
if (!schema) continue;
|
|
90
|
+
if (schema.type !== "object") {
|
|
91
|
+
notObjects.push(schema);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if ("additionalProperties" in schema) {
|
|
95
|
+
if (schema.additionalProperties === true)
|
|
96
|
+
additionalPropertiesIsTrue = true;
|
|
97
|
+
else if (schema.additionalProperties === false)
|
|
98
|
+
additionalPropertiesIsFalse = true;
|
|
99
|
+
}
|
|
100
|
+
if (!newSchema) {
|
|
101
|
+
newSchema = schema;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
newSchema = {
|
|
105
|
+
...newSchema,
|
|
106
|
+
...schema,
|
|
107
|
+
properties: {
|
|
108
|
+
...newSchema.properties,
|
|
109
|
+
...schema.properties
|
|
110
|
+
},
|
|
111
|
+
required: [
|
|
112
|
+
...newSchema?.required ?? [],
|
|
113
|
+
...schema.required ?? []
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (newSchema) {
|
|
118
|
+
if (newSchema.required)
|
|
119
|
+
newSchema.required = [...new Set(newSchema.required)];
|
|
120
|
+
if (additionalPropertiesIsFalse) newSchema.additionalProperties = false;
|
|
121
|
+
else if (additionalPropertiesIsTrue)
|
|
122
|
+
newSchema.additionalProperties = true;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
schema: newSchema,
|
|
126
|
+
notObjects
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
var isTSchema = (value) => {
|
|
130
|
+
if (!value || typeof value !== "object") return false;
|
|
131
|
+
if (Kind in value) return true;
|
|
132
|
+
const keys = Object.keys(value);
|
|
133
|
+
if (keys.length > 0 && keys.every((k) => !isNaN(Number(k)))) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
};
|
|
138
|
+
var normalizeSchemaReference = (schema) => {
|
|
139
|
+
if (!schema) return void 0;
|
|
140
|
+
if (typeof schema !== "string") return schema;
|
|
141
|
+
return t.Ref(schema);
|
|
142
|
+
};
|
|
143
|
+
var mergeSchemaProperty = (existing, incoming, vendors) => {
|
|
144
|
+
if (!existing) return incoming;
|
|
145
|
+
if (!incoming) return existing;
|
|
146
|
+
const existingSchema = normalizeSchemaReference(existing);
|
|
147
|
+
let incomingSchema = normalizeSchemaReference(incoming);
|
|
148
|
+
if (!existingSchema) return incoming;
|
|
149
|
+
if (!incomingSchema) return existing;
|
|
150
|
+
if (!isTSchema(incomingSchema) && incomingSchema["~standard"])
|
|
151
|
+
incomingSchema = unwrapSchema(incomingSchema, vendors);
|
|
152
|
+
if (!incomingSchema) return existing;
|
|
153
|
+
const { schema: mergedSchema, notObjects } = mergeObjectSchemas([
|
|
154
|
+
existingSchema,
|
|
155
|
+
incomingSchema
|
|
156
|
+
]);
|
|
157
|
+
if (notObjects.length > 0) {
|
|
158
|
+
if (mergedSchema) return t.Intersect([mergedSchema, ...notObjects]);
|
|
159
|
+
return notObjects.length === 1 ? notObjects[0] : t.Intersect(notObjects);
|
|
160
|
+
}
|
|
161
|
+
return mergedSchema;
|
|
162
|
+
};
|
|
163
|
+
var unwrapResponseSchema = (schema, vendors) => typeof schema === "string" ? normalizeSchemaReference(schema) : !schema ? void 0 : isTSchema(schema) ? schema : (
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
schema["~standard"] ? unwrapSchema(schema, vendors, "output") : Object.fromEntries(
|
|
166
|
+
Object.entries(schema).map(([status, schema2]) => [
|
|
167
|
+
status,
|
|
168
|
+
typeof schema2 === "string" ? normalizeSchemaReference(schema2) : isTSchema(schema2) ? schema2 : unwrapSchema(schema2, vendors, "output")
|
|
169
|
+
])
|
|
170
|
+
)
|
|
171
|
+
);
|
|
172
|
+
var mergeResponseSchema = (_existing, _incoming, vendors) => {
|
|
173
|
+
if (!_existing) return _incoming;
|
|
174
|
+
if (!_incoming) return _existing;
|
|
175
|
+
let existing = unwrapResponseSchema(_existing, vendors);
|
|
176
|
+
let incoming = unwrapResponseSchema(_incoming, vendors);
|
|
177
|
+
if (!existing && !incoming) return void 0;
|
|
178
|
+
if (incoming && !existing) return incoming;
|
|
179
|
+
if (existing && !incoming) return existing;
|
|
180
|
+
if (isTSchema(existing) || existing?.["~standard"])
|
|
181
|
+
existing = {
|
|
182
|
+
200: existing
|
|
183
|
+
};
|
|
184
|
+
if (isTSchema(incoming) || incoming?.["~standard"])
|
|
185
|
+
incoming = {
|
|
186
|
+
200: incoming
|
|
187
|
+
};
|
|
188
|
+
const schema = {
|
|
189
|
+
...incoming
|
|
190
|
+
};
|
|
191
|
+
for (const status of Object.keys(existing ?? {})) {
|
|
192
|
+
const existingSchema = existing[status];
|
|
193
|
+
const incomingSchema = incoming[status];
|
|
194
|
+
if (existingSchema && incomingSchema)
|
|
195
|
+
schema[status] = mergeSchemaProperty(
|
|
196
|
+
existingSchema,
|
|
197
|
+
incomingSchema,
|
|
198
|
+
vendors
|
|
199
|
+
);
|
|
200
|
+
else if (existingSchema) schema[status] = existingSchema;
|
|
201
|
+
else if (incomingSchema) schema[status] = incomingSchema;
|
|
202
|
+
}
|
|
203
|
+
return schema;
|
|
204
|
+
};
|
|
205
|
+
var mergeStandaloneValidators = (hooks, vendors) => {
|
|
206
|
+
const merged = { ...hooks };
|
|
207
|
+
if (!hooks.standaloneValidator?.length) return merged;
|
|
208
|
+
for (const validator of hooks.standaloneValidator) {
|
|
209
|
+
if (validator.body)
|
|
210
|
+
merged.body = mergeSchemaProperty(
|
|
211
|
+
merged.body,
|
|
212
|
+
validator.body,
|
|
213
|
+
vendors
|
|
214
|
+
);
|
|
215
|
+
if (validator.headers)
|
|
216
|
+
merged.headers = mergeSchemaProperty(
|
|
217
|
+
merged.headers,
|
|
218
|
+
validator.headers,
|
|
219
|
+
vendors
|
|
220
|
+
);
|
|
221
|
+
if (validator.query)
|
|
222
|
+
merged.query = mergeSchemaProperty(
|
|
223
|
+
merged.query,
|
|
224
|
+
validator.query,
|
|
225
|
+
vendors
|
|
226
|
+
);
|
|
227
|
+
if (validator.params)
|
|
228
|
+
merged.params = mergeSchemaProperty(
|
|
229
|
+
merged.params,
|
|
230
|
+
validator.params,
|
|
231
|
+
vendors
|
|
232
|
+
);
|
|
233
|
+
if (validator.cookie)
|
|
234
|
+
merged.cookie = mergeSchemaProperty(
|
|
235
|
+
merged.cookie,
|
|
236
|
+
validator.cookie,
|
|
237
|
+
vendors
|
|
238
|
+
);
|
|
239
|
+
if (validator.response)
|
|
240
|
+
merged.response = mergeResponseSchema(
|
|
241
|
+
merged.response,
|
|
242
|
+
validator.response,
|
|
243
|
+
vendors
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (typeof merged.body === "string")
|
|
247
|
+
merged.body = normalizeSchemaReference(merged.body);
|
|
248
|
+
if (typeof merged.headers === "string")
|
|
249
|
+
merged.headers = normalizeSchemaReference(merged.headers);
|
|
250
|
+
if (typeof merged.query === "string")
|
|
251
|
+
merged.query = normalizeSchemaReference(merged.query);
|
|
252
|
+
if (typeof merged.params === "string")
|
|
253
|
+
merged.params = normalizeSchemaReference(merged.params);
|
|
254
|
+
if (typeof merged.cookie === "string")
|
|
255
|
+
merged.cookie = normalizeSchemaReference(merged.cookie);
|
|
256
|
+
if (merged.response && typeof merged.response !== "string") {
|
|
257
|
+
const response = merged.response;
|
|
258
|
+
if ("type" in response || "$ref" in response) {
|
|
259
|
+
if (typeof response === "string")
|
|
260
|
+
merged.response = normalizeSchemaReference(response);
|
|
261
|
+
} else {
|
|
262
|
+
for (const [status, schema] of Object.entries(response))
|
|
263
|
+
if (typeof schema === "string")
|
|
264
|
+
response[status] = normalizeSchemaReference(schema);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return merged;
|
|
268
|
+
};
|
|
269
|
+
var flattenRoutes = (routes, vendors) => routes.map((route) => {
|
|
270
|
+
if (!route.hooks?.standaloneValidator?.length) return route;
|
|
271
|
+
return {
|
|
272
|
+
...route,
|
|
273
|
+
hooks: mergeStandaloneValidators(route.hooks, vendors)
|
|
274
|
+
};
|
|
275
|
+
});
|
|
74
276
|
var unwrapReference = (schema, definitions) => {
|
|
75
277
|
const ref = schema?.$ref;
|
|
76
278
|
if (!ref) return schema;
|
|
@@ -78,13 +280,15 @@ var unwrapReference = (schema, definitions) => {
|
|
|
78
280
|
if (ref && definitions[name]) schema = definitions[name];
|
|
79
281
|
return enumToOpenApi(schema);
|
|
80
282
|
};
|
|
81
|
-
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
283
|
+
var unwrapSchema = (schema, mapJsonSchema, io = "input") => {
|
|
82
284
|
if (!schema) return;
|
|
83
285
|
if (typeof schema === "string") schema = toRef(schema);
|
|
84
286
|
if (Kind in schema) return enumToOpenApi(schema);
|
|
85
287
|
if (Kind in schema || !schema?.["~standard"]) return;
|
|
86
288
|
const vendor = schema["~standard"].vendor;
|
|
87
289
|
try {
|
|
290
|
+
if (schema["~standard"]?.jsonSchema?.[io])
|
|
291
|
+
return schema["~standard"]?.jsonSchema?.[io]?.();
|
|
88
292
|
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
89
293
|
return enumToOpenApi(mapJsonSchema[vendor](schema));
|
|
90
294
|
switch (vendor) {
|
|
@@ -179,7 +383,6 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
179
383
|
const excludePaths = Array.isArray(exclude?.paths) ? exclude.paths : typeof exclude?.paths !== "undefined" ? [exclude.paths] : [];
|
|
180
384
|
const paths = /* @__PURE__ */ Object.create(null);
|
|
181
385
|
const definitions = app.getGlobalDefinitions?.().type;
|
|
182
|
-
const routes = app.getGlobalRoutes();
|
|
183
386
|
if (references) {
|
|
184
387
|
if (!Array.isArray(references)) references = [references];
|
|
185
388
|
for (let i = 0; i < references.length; i++) {
|
|
@@ -187,6 +390,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
187
390
|
if (typeof reference === "function") references[i] = reference();
|
|
188
391
|
}
|
|
189
392
|
}
|
|
393
|
+
const routes = flattenRoutes(app.getGlobalRoutes(), vendors);
|
|
190
394
|
for (const route of routes) {
|
|
191
395
|
if (route.hooks?.detail?.hide) continue;
|
|
192
396
|
const method = route.method.toLowerCase();
|
|
@@ -376,7 +580,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
376
580
|
if (typeof hooks.response === "object" && // TypeBox
|
|
377
581
|
!hooks.response.type && !hooks.response.$ref && !hooks.response["~standard"]) {
|
|
378
582
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
379
|
-
const response = unwrapSchema(schema, vendors);
|
|
583
|
+
const response = unwrapSchema(schema, vendors, "output");
|
|
380
584
|
if (!response) continue;
|
|
381
585
|
const { type, description, $ref, ..._options } = unwrapReference(response, definitions);
|
|
382
586
|
operation.responses[status] = {
|
|
@@ -393,7 +597,7 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
393
597
|
};
|
|
394
598
|
}
|
|
395
599
|
} else {
|
|
396
|
-
const response = unwrapSchema(hooks.response, vendors);
|
|
600
|
+
const response = unwrapSchema(hooks.response, vendors, "output");
|
|
397
601
|
if (response) {
|
|
398
602
|
const {
|
|
399
603
|
type: _type,
|
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
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elysiajs/openapi",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.12",
|
|
4
4
|
"description": "Plugin for Elysia to auto-generate API documentation",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "saltyAom",
|
|
@@ -80,12 +80,12 @@
|
|
|
80
80
|
"@sinclair/typemap": "^0.10.1",
|
|
81
81
|
"@types/bun": "1.2.20",
|
|
82
82
|
"effect": "^3.17.13",
|
|
83
|
-
"elysia": "1.4.
|
|
83
|
+
"elysia": "1.4.19",
|
|
84
84
|
"eslint": "9.6.0",
|
|
85
85
|
"openapi-types": "^12.1.3",
|
|
86
86
|
"tsup": "^8.5.0",
|
|
87
87
|
"typescript": "^5.9.2",
|
|
88
|
-
"zod": "^4.1
|
|
88
|
+
"zod": "^4.2.1"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
91
|
"elysia": ">= 1.4.0"
|