@elysiajs/openapi 1.3.11 → 1.4.0-exp.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/bun.lock +545 -537
- package/dist/cjs/gen/index.js +21 -13
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +122 -81
- package/dist/cjs/openapi.d.ts +7 -4
- package/dist/cjs/openapi.js +122 -79
- package/dist/gen/index.d.ts +16 -1
- package/dist/gen/index.mjs +21 -13
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +122 -81
- package/dist/openapi.d.ts +7 -4
- package/dist/openapi.mjs +121 -79
- package/package.json +96 -92
- package/bunfig.toml +0 -2
package/dist/cjs/openapi.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(openapi_exports, {
|
|
|
24
24
|
getLoosePath: () => getLoosePath,
|
|
25
25
|
getPossiblePath: () => getPossiblePath,
|
|
26
26
|
toOpenAPISchema: () => toOpenAPISchema,
|
|
27
|
+
unwrapSchema: () => unwrapSchema,
|
|
27
28
|
withHeaders: () => withHeaders
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(openapi_exports);
|
|
@@ -37,6 +38,7 @@ var Hint = Symbol.for("TypeBox.Hint");
|
|
|
37
38
|
var Kind = Symbol.for("TypeBox.Kind");
|
|
38
39
|
|
|
39
40
|
// src/openapi.ts
|
|
41
|
+
var import_xsschema = require("xsschema");
|
|
40
42
|
var capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
41
43
|
var toRef = (name) => import_elysia.t.Ref(`#/components/schemas/${name}`);
|
|
42
44
|
var toOperationId = (method, paths) => {
|
|
@@ -65,7 +67,14 @@ var getLoosePath = (path) => {
|
|
|
65
67
|
return path.slice(0, path.length - 1);
|
|
66
68
|
return path + "/";
|
|
67
69
|
};
|
|
68
|
-
|
|
70
|
+
var unwrapSchema = (schema) => {
|
|
71
|
+
if (!schema) return;
|
|
72
|
+
if (typeof schema === "string") schema = toRef(schema);
|
|
73
|
+
if (Kind in schema) return schema;
|
|
74
|
+
if (Kind in schema === false && schema["~standard"])
|
|
75
|
+
return (0, import_xsschema.toJsonSchema)(schema);
|
|
76
|
+
};
|
|
77
|
+
async function toOpenAPISchema(app, exclude, references) {
|
|
69
78
|
const {
|
|
70
79
|
methods: excludeMethods = ["OPTIONS"],
|
|
71
80
|
staticFile: excludeStaticFile = true,
|
|
@@ -118,11 +127,11 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
118
127
|
};
|
|
119
128
|
const parameters = [];
|
|
120
129
|
if (hooks.params) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (
|
|
130
|
+
let params = unwrapSchema(hooks.params);
|
|
131
|
+
if (params) params = await params;
|
|
132
|
+
if (params && params.type === "object" && params.properties)
|
|
124
133
|
for (const [paramName, paramSchema] of Object.entries(
|
|
125
|
-
|
|
134
|
+
params.properties
|
|
126
135
|
))
|
|
127
136
|
parameters.push({
|
|
128
137
|
name: paramName,
|
|
@@ -131,15 +140,14 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
131
140
|
// Path parameters are always required
|
|
132
141
|
schema: paramSchema
|
|
133
142
|
});
|
|
134
|
-
}
|
|
135
143
|
}
|
|
136
144
|
if (hooks.query) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
const required =
|
|
145
|
+
let query = unwrapSchema(hooks.query);
|
|
146
|
+
if (query) query = await query;
|
|
147
|
+
if (query && query.type === "object" && query.properties) {
|
|
148
|
+
const required = query.required || [];
|
|
141
149
|
for (const [queryName, querySchema] of Object.entries(
|
|
142
|
-
|
|
150
|
+
query.properties
|
|
143
151
|
))
|
|
144
152
|
parameters.push({
|
|
145
153
|
name: queryName,
|
|
@@ -150,12 +158,12 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
150
158
|
}
|
|
151
159
|
}
|
|
152
160
|
if (hooks.headers) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (
|
|
156
|
-
const required =
|
|
161
|
+
let headers = unwrapSchema(hooks.query);
|
|
162
|
+
if (headers) headers = await headers;
|
|
163
|
+
if (headers && headers.type === "object" && headers.properties) {
|
|
164
|
+
const required = headers.required || [];
|
|
157
165
|
for (const [headerName, headerSchema] of Object.entries(
|
|
158
|
-
|
|
166
|
+
headers.properties
|
|
159
167
|
))
|
|
160
168
|
parameters.push({
|
|
161
169
|
name: headerName,
|
|
@@ -166,12 +174,12 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
166
174
|
}
|
|
167
175
|
}
|
|
168
176
|
if (hooks.cookie) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
const required =
|
|
177
|
+
let cookie = unwrapSchema(hooks.cookie);
|
|
178
|
+
if (cookie) cookie = await cookie;
|
|
179
|
+
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
180
|
+
const required = cookie.required || [];
|
|
173
181
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
174
|
-
|
|
182
|
+
cookie.properties
|
|
175
183
|
))
|
|
176
184
|
parameters.push({
|
|
177
185
|
name: cookieName,
|
|
@@ -183,80 +191,107 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
183
191
|
}
|
|
184
192
|
if (parameters.length > 0) operation.parameters = parameters;
|
|
185
193
|
if (hooks.body && method !== "get" && method !== "head") {
|
|
186
|
-
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
194
|
+
let body = unwrapSchema(hooks.body);
|
|
195
|
+
if (body) body = await body;
|
|
196
|
+
if (body) {
|
|
197
|
+
const { type: _type, description, ...options } = body;
|
|
198
|
+
const type = _type;
|
|
199
|
+
if (hooks.parse) {
|
|
200
|
+
const content = {};
|
|
201
|
+
const parsers = hooks.parse;
|
|
202
|
+
for (const parser of parsers) {
|
|
203
|
+
if (typeof parser.fn === "function") continue;
|
|
204
|
+
switch (parser.fn) {
|
|
205
|
+
case "text":
|
|
206
|
+
case "text/plain":
|
|
207
|
+
content["text/plain"] = { schema: body };
|
|
208
|
+
continue;
|
|
209
|
+
case "urlencoded":
|
|
210
|
+
case "application/x-www-form-urlencoded":
|
|
211
|
+
content["application/x-www-form-urlencoded"] = {
|
|
212
|
+
schema: body
|
|
213
|
+
};
|
|
214
|
+
continue;
|
|
215
|
+
case "json":
|
|
216
|
+
case "application/json":
|
|
217
|
+
content["application/json"] = { schema: body };
|
|
218
|
+
continue;
|
|
219
|
+
case "formdata":
|
|
220
|
+
case "multipart/form-data":
|
|
221
|
+
content["multipart/form-data"] = {
|
|
222
|
+
schema: body
|
|
223
|
+
};
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
213
226
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
|
|
227
|
+
operation.requestBody = {
|
|
228
|
+
description,
|
|
229
|
+
content,
|
|
230
|
+
required: true
|
|
231
|
+
};
|
|
232
|
+
} else {
|
|
233
|
+
operation.requestBody = {
|
|
234
|
+
description,
|
|
235
|
+
content: type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
|
|
236
|
+
"text/plain": body
|
|
237
|
+
} : {
|
|
238
|
+
"application/json": {
|
|
239
|
+
schema: body
|
|
240
|
+
},
|
|
241
|
+
"application/x-www-form-urlencoded": {
|
|
242
|
+
schema: body
|
|
243
|
+
},
|
|
244
|
+
"multipart/form-data": {
|
|
245
|
+
schema: body
|
|
246
|
+
}
|
|
224
247
|
},
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
},
|
|
229
|
-
required: true
|
|
230
|
-
};
|
|
248
|
+
required: true
|
|
249
|
+
};
|
|
250
|
+
}
|
|
231
251
|
}
|
|
232
252
|
}
|
|
233
253
|
if (hooks.response) {
|
|
234
254
|
operation.responses = {};
|
|
235
255
|
if (typeof hooks.response === "object" && !hooks.response.type && !hooks.response.$ref) {
|
|
236
256
|
for (let [status, schema] of Object.entries(hooks.response)) {
|
|
237
|
-
|
|
238
|
-
|
|
257
|
+
let response = unwrapSchema(schema);
|
|
258
|
+
if (response) response = await response;
|
|
259
|
+
if (!response) continue;
|
|
260
|
+
const { type: _type, description, ...options } = response;
|
|
261
|
+
const type = _type;
|
|
239
262
|
operation.responses[status] = {
|
|
240
|
-
description: `Response for status ${status}`,
|
|
263
|
+
description: description ?? `Response for status ${status}`,
|
|
241
264
|
...options,
|
|
242
|
-
content: type === "void" || type === "null" || type === "undefined" ?
|
|
265
|
+
content: type === "void" || type === "null" || type === "undefined" ? response : type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
|
|
266
|
+
"text/plain": {
|
|
267
|
+
schema: response
|
|
268
|
+
}
|
|
269
|
+
} : {
|
|
243
270
|
"application/json": {
|
|
244
|
-
schema
|
|
271
|
+
schema: response
|
|
245
272
|
}
|
|
246
273
|
}
|
|
247
274
|
};
|
|
248
275
|
}
|
|
249
276
|
} else {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
277
|
+
let response = unwrapSchema(hooks.response);
|
|
278
|
+
if (response) response = await response;
|
|
279
|
+
if (response) {
|
|
280
|
+
const { type: _type, description, ...options } = response;
|
|
281
|
+
const type = _type;
|
|
282
|
+
operation.responses["200"] = {
|
|
283
|
+
description: description ?? `Response for status 200`,
|
|
284
|
+
content: type === "void" || type === "null" || type === "undefined" ? response : type === "string" || type === "number" || type === "integer" || type === "boolean" ? {
|
|
285
|
+
"text/plain": {
|
|
286
|
+
schema: response
|
|
287
|
+
}
|
|
288
|
+
} : {
|
|
289
|
+
"application/json": {
|
|
290
|
+
schema: response
|
|
291
|
+
}
|
|
257
292
|
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
260
295
|
}
|
|
261
296
|
}
|
|
262
297
|
for (let path of getPossiblePath(route.path)) {
|
|
@@ -287,7 +322,14 @@ function toOpenAPISchema(app, exclude, references) {
|
|
|
287
322
|
};
|
|
288
323
|
}
|
|
289
324
|
}
|
|
290
|
-
const
|
|
325
|
+
const _schemas = app.getGlobalDefinitions?.().type;
|
|
326
|
+
const schemas = /* @__PURE__ */ Object.create(null);
|
|
327
|
+
if (_schemas)
|
|
328
|
+
for (const [name, schema] of Object.entries(_schemas)) {
|
|
329
|
+
let jsonSchema = unwrapSchema(schema);
|
|
330
|
+
if (jsonSchema instanceof Promise) jsonSchema = await jsonSchema;
|
|
331
|
+
if (jsonSchema) schemas[name] = jsonSchema;
|
|
332
|
+
}
|
|
291
333
|
return {
|
|
292
334
|
components: {
|
|
293
335
|
schemas
|
|
@@ -304,5 +346,6 @@ var withHeaders = (schema, headers) => Object.assign(schema, {
|
|
|
304
346
|
getLoosePath,
|
|
305
347
|
getPossiblePath,
|
|
306
348
|
toOpenAPISchema,
|
|
349
|
+
unwrapSchema,
|
|
307
350
|
withHeaders
|
|
308
351
|
});
|
package/dist/gen/index.d.ts
CHANGED
|
@@ -31,6 +31,21 @@ interface OpenAPIGeneratorOptions {
|
|
|
31
31
|
* @default false
|
|
32
32
|
*/
|
|
33
33
|
debug?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* compilerOptions
|
|
36
|
+
*
|
|
37
|
+
* Override tsconfig.json compilerOptions
|
|
38
|
+
*/
|
|
39
|
+
compilerOptions?: Record<string, any>;
|
|
40
|
+
/**
|
|
41
|
+
* Temporary root
|
|
42
|
+
*
|
|
43
|
+
* a folder where temporary files are stored
|
|
44
|
+
* @default os.tmpdir()/.ElysiaAutoOpenAPI
|
|
45
|
+
*
|
|
46
|
+
* ! be careful that the folder will be removed after the process ends
|
|
47
|
+
*/
|
|
48
|
+
tmpRoot?: string;
|
|
34
49
|
}
|
|
35
50
|
/**
|
|
36
51
|
* Auto generate OpenAPI schema from Elysia instance
|
|
@@ -45,5 +60,5 @@ export declare const fromTypes: (
|
|
|
45
60
|
*
|
|
46
61
|
* The path must export an Elysia instance
|
|
47
62
|
*/
|
|
48
|
-
targetFilePath: string, { tsconfigPath, instanceName, projectRoot, overrideOutputPath, debug }?: OpenAPIGeneratorOptions) => () => AdditionalReference | undefined;
|
|
63
|
+
targetFilePath: string, { tsconfigPath, instanceName, projectRoot, overrideOutputPath, debug, compilerOptions, tmpRoot }?: OpenAPIGeneratorOptions) => () => AdditionalReference | undefined;
|
|
49
64
|
export {};
|
package/dist/gen/index.mjs
CHANGED
|
@@ -19,9 +19,10 @@ var fromTypes = (targetFilePath, {
|
|
|
19
19
|
instanceName,
|
|
20
20
|
projectRoot = process.cwd(),
|
|
21
21
|
overrideOutputPath,
|
|
22
|
-
debug = false
|
|
22
|
+
debug = false,
|
|
23
|
+
compilerOptions,
|
|
24
|
+
tmpRoot = join(tmpdir(), ".ElysiaAutoOpenAPI")
|
|
23
25
|
} = {}) => () => {
|
|
24
|
-
const tmpRoot = join(tmpdir(), ".ElysiaAutoOpenAPI");
|
|
25
26
|
try {
|
|
26
27
|
if (!targetFilePath.endsWith(".ts") && !targetFilePath.endsWith(".tsx"))
|
|
27
28
|
throw new Error("Only .ts files are supported");
|
|
@@ -40,25 +41,27 @@ var fromTypes = (targetFilePath, {
|
|
|
40
41
|
mkdirSync(tmpRoot, { recursive: true });
|
|
41
42
|
const tsconfig = tsconfigPath.startsWith("/") ? tsconfigPath : join(projectRoot, tsconfigPath);
|
|
42
43
|
let extendsRef = existsSync(tsconfig) ? `"extends": "${join(projectRoot, "tsconfig.json")}",` : "";
|
|
44
|
+
let distDir = join(tmpRoot, "dist");
|
|
43
45
|
if (typeof process !== "undefined" && process.platform === "win32") {
|
|
44
46
|
extendsRef = extendsRef.replace(/\\/g, "/");
|
|
45
47
|
src = src.replace(/\\/g, "/");
|
|
48
|
+
distDir = distDir.replace(/\\/g, "/");
|
|
46
49
|
}
|
|
47
50
|
writeFileSync(
|
|
48
51
|
join(tmpRoot, "tsconfig.json"),
|
|
49
52
|
`{
|
|
50
53
|
${extendsRef}
|
|
51
|
-
"compilerOptions": {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
"compilerOptions": ${compilerOptions ? JSON.stringify(compilerOptions) : `{
|
|
55
|
+
"lib": ["ESNext"],
|
|
56
|
+
"module": "ESNext",
|
|
57
|
+
"noEmit": false,
|
|
58
|
+
"declaration": true,
|
|
59
|
+
"emitDeclarationOnly": true,
|
|
60
|
+
"moduleResolution": "bundler",
|
|
61
|
+
"skipLibCheck": true,
|
|
62
|
+
"skipDefaultLibCheck": true,
|
|
63
|
+
"outDir": "${distDir}"
|
|
64
|
+
}`},
|
|
62
65
|
"include": ["${src}"]
|
|
63
66
|
}`
|
|
64
67
|
);
|
|
@@ -100,6 +103,11 @@ var fromTypes = (targetFilePath, {
|
|
|
100
103
|
);
|
|
101
104
|
console.warn(tempFiles);
|
|
102
105
|
}
|
|
106
|
+
} else {
|
|
107
|
+
console.log(
|
|
108
|
+
"reason: root folder doesn't exists",
|
|
109
|
+
join(tmpRoot, "dist")
|
|
110
|
+
);
|
|
103
111
|
}
|
|
104
112
|
return;
|
|
105
113
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,16 +19,19 @@ export declare const openapi: <const Enabled extends boolean = true, const Path
|
|
|
19
19
|
macro: {};
|
|
20
20
|
macroFn: {};
|
|
21
21
|
parser: {};
|
|
22
|
+
response: {};
|
|
22
23
|
}, {}, {
|
|
23
24
|
derive: {};
|
|
24
25
|
resolve: {};
|
|
25
26
|
schema: {};
|
|
26
27
|
standaloneSchema: {};
|
|
28
|
+
response: {};
|
|
27
29
|
}, {
|
|
28
30
|
derive: {};
|
|
29
31
|
resolve: {};
|
|
30
32
|
schema: {};
|
|
31
33
|
standaloneSchema: {};
|
|
34
|
+
response: {};
|
|
32
35
|
}>;
|
|
33
36
|
export { toOpenAPISchema, withHeaders } from './openapi';
|
|
34
37
|
export type { ElysiaOpenAPIConfig };
|