@elysiajs/openapi 1.4.2 → 1.4.4
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 +11 -2
- package/dist/cjs/gen/index.js +37 -6
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +114 -13
- package/dist/cjs/openapi.js +110 -13
- package/dist/cjs/types.d.ts +5 -3
- package/dist/gen/index.d.ts +6 -1
- package/dist/gen/index.mjs +37 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +114 -13
- package/dist/openapi.mjs +110 -13
- package/dist/types.d.ts +5 -3
- package/package.json +3 -2
package/bun.lock
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"@scalar/types": "^0.2.13",
|
|
9
9
|
"@sinclair/typemap": "^0.10.1",
|
|
10
10
|
"@types/bun": "1.2.20",
|
|
11
|
-
"
|
|
11
|
+
"effect": "^3.17.13",
|
|
12
|
+
"elysia": "1.4.6",
|
|
12
13
|
"eslint": "9.6.0",
|
|
13
14
|
"openapi-types": "^12.1.3",
|
|
14
15
|
"tsup": "^8.5.0",
|
|
@@ -167,6 +168,8 @@
|
|
|
167
168
|
|
|
168
169
|
"@sinclair/typemap": ["@sinclair/typemap@0.10.1", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.30", "valibot": "^1.0.0", "zod": "^3.24.1" } }, "sha512-UXR0fhu/n3c9B6lB+SLI5t1eVpt9i9CdDrp2TajRe3LbKiUhCTZN2kSfJhjPnpc3I59jMRIhgew7+0HlMi08mg=="],
|
|
169
170
|
|
|
171
|
+
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
|
|
172
|
+
|
|
170
173
|
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
|
|
171
174
|
|
|
172
175
|
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
|
@@ -239,7 +242,9 @@
|
|
|
239
242
|
|
|
240
243
|
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
|
|
241
244
|
|
|
242
|
-
"
|
|
245
|
+
"effect": ["effect@3.17.13", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-JMz5oBxs/6mu4FP9Csjub4jYMUwMLrp+IzUmSDVIzn2NoeoyOXMl7x1lghfr3dLKWffWrdnv/d8nFFdgrHXPqw=="],
|
|
246
|
+
|
|
247
|
+
"elysia": ["elysia@1.4.6", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-u2CorXLPs5ZXyWP+tQR+bgka/lJA4vNpB8lDE2w/sTmdaIwoPQmHEL4J3ai6OAlluWR1kfG7T9gO3EYT9D8viQ=="],
|
|
243
248
|
|
|
244
249
|
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
|
245
250
|
|
|
@@ -265,6 +270,8 @@
|
|
|
265
270
|
|
|
266
271
|
"exact-mirror": ["exact-mirror@0.2.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-CrGe+4QzHZlnrXZVlo/WbUZ4qQZq8C0uATQVGVgXIrNXgHDBBNFD1VRfssRA2C9t3RYvh3MadZSdg2Wy7HBoQA=="],
|
|
267
272
|
|
|
273
|
+
"fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
|
|
274
|
+
|
|
268
275
|
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
|
269
276
|
|
|
270
277
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
|
@@ -405,6 +412,8 @@
|
|
|
405
412
|
|
|
406
413
|
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
|
407
414
|
|
|
415
|
+
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
|
416
|
+
|
|
408
417
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
|
409
418
|
|
|
410
419
|
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
package/dist/cjs/gen/index.js
CHANGED
|
@@ -8315,6 +8315,35 @@ var import_child_process = require("child_process");
|
|
|
8315
8315
|
var matchRoute = /: Elysia<(.*)>/gs;
|
|
8316
8316
|
var matchStatus = /(\d{3}):/g;
|
|
8317
8317
|
var wrapStatusInQuote = (value) => value.replace(matchStatus, '"$1":');
|
|
8318
|
+
function extractRootObjects(code) {
|
|
8319
|
+
const results = [];
|
|
8320
|
+
let i = 0;
|
|
8321
|
+
while (i < code.length) {
|
|
8322
|
+
const colonIdx = code.indexOf(":", i);
|
|
8323
|
+
if (colonIdx === -1) break;
|
|
8324
|
+
let keyEnd = colonIdx - 1;
|
|
8325
|
+
while (keyEnd >= 0 && /\s/.test(code[keyEnd])) keyEnd--;
|
|
8326
|
+
let keyStart = keyEnd;
|
|
8327
|
+
while (keyStart >= 0 && /\w/.test(code[keyStart])) keyStart--;
|
|
8328
|
+
const braceIdx = code.indexOf("{", colonIdx);
|
|
8329
|
+
if (braceIdx === -1) break;
|
|
8330
|
+
let depth = 0;
|
|
8331
|
+
let end = braceIdx;
|
|
8332
|
+
for (; end < code.length; end++) {
|
|
8333
|
+
if (code[end] === "{") depth++;
|
|
8334
|
+
else if (code[end] === "}") {
|
|
8335
|
+
depth--;
|
|
8336
|
+
if (depth === 0) {
|
|
8337
|
+
end++;
|
|
8338
|
+
break;
|
|
8339
|
+
}
|
|
8340
|
+
}
|
|
8341
|
+
}
|
|
8342
|
+
results.push(`{${code.slice(keyStart + 1, end)};}`);
|
|
8343
|
+
i = end;
|
|
8344
|
+
}
|
|
8345
|
+
return results;
|
|
8346
|
+
}
|
|
8318
8347
|
var fromTypes = (targetFilePath, {
|
|
8319
8348
|
tsconfigPath = "tsconfig.json",
|
|
8320
8349
|
instanceName,
|
|
@@ -8322,7 +8351,8 @@ var fromTypes = (targetFilePath, {
|
|
|
8322
8351
|
overrideOutputPath,
|
|
8323
8352
|
debug = false,
|
|
8324
8353
|
compilerOptions,
|
|
8325
|
-
tmpRoot = (0, import_path2.join)((0, import_os.tmpdir)(), ".ElysiaAutoOpenAPI")
|
|
8354
|
+
tmpRoot = (0, import_path2.join)((0, import_os.tmpdir)(), ".ElysiaAutoOpenAPI"),
|
|
8355
|
+
silent = false
|
|
8326
8356
|
} = {}) => () => {
|
|
8327
8357
|
try {
|
|
8328
8358
|
if (!targetFilePath.endsWith(".ts") && !targetFilePath.endsWith(".tsx"))
|
|
@@ -8369,7 +8399,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8369
8399
|
(0, import_child_process.spawnSync)(`tsc`, {
|
|
8370
8400
|
shell: true,
|
|
8371
8401
|
cwd: tmpRoot,
|
|
8372
|
-
stdio:
|
|
8402
|
+
stdio: silent ? void 0 : "inherit"
|
|
8373
8403
|
});
|
|
8374
8404
|
const fileName = targetFilePath.replace(/.tsx$/, ".ts").replace(/.ts$/, ".d.ts");
|
|
8375
8405
|
targetFile = (overrideOutputPath ? typeof overrideOutputPath === "string" ? overrideOutputPath.startsWith("/") ? overrideOutputPath : (0, import_path2.join)(tmpRoot, "dist", overrideOutputPath) : overrideOutputPath(tmpRoot) : void 0) ?? (0, import_path2.join)(
|
|
@@ -8405,7 +8435,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8405
8435
|
console.warn(tempFiles);
|
|
8406
8436
|
}
|
|
8407
8437
|
} else {
|
|
8408
|
-
console.
|
|
8438
|
+
console.warn(
|
|
8409
8439
|
"reason: root folder doesn't exists",
|
|
8410
8440
|
(0, import_path2.join)(tmpRoot, "dist")
|
|
8411
8441
|
);
|
|
@@ -8414,7 +8444,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8414
8444
|
}
|
|
8415
8445
|
}
|
|
8416
8446
|
const declaration = (0, import_fs.readFileSync)(targetFile, "utf8");
|
|
8417
|
-
if ((0, import_fs.existsSync)(tmpRoot))
|
|
8447
|
+
if (!debug && (0, import_fs.existsSync)(tmpRoot))
|
|
8418
8448
|
(0, import_fs.rmSync)(tmpRoot, { recursive: true, force: true });
|
|
8419
8449
|
let instance = declaration.match(
|
|
8420
8450
|
instanceName ? new RegExp(`${instanceName}: Elysia<(.*)`, "gs") : matchRoute
|
|
@@ -8434,8 +8464,8 @@ var fromTypes = (targetFilePath, {
|
|
|
8434
8464
|
instance.slice(3, instance.indexOf("}, {", 4))
|
|
8435
8465
|
);
|
|
8436
8466
|
const routes = {};
|
|
8437
|
-
for (const route of routesString
|
|
8438
|
-
let schema = TypeBox(
|
|
8467
|
+
for (const route of extractRootObjects(routesString)) {
|
|
8468
|
+
let schema = TypeBox(route);
|
|
8439
8469
|
if (schema.type !== "object") continue;
|
|
8440
8470
|
const paths = [];
|
|
8441
8471
|
while (true) {
|
|
@@ -8446,6 +8476,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8446
8476
|
if (!schema?.properties) break;
|
|
8447
8477
|
}
|
|
8448
8478
|
const method = paths.pop();
|
|
8479
|
+
if (!method) continue;
|
|
8449
8480
|
const path = "/" + paths.join("/");
|
|
8450
8481
|
schema = schema.properties;
|
|
8451
8482
|
if (schema?.response?.type === "object") {
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
|
-
import type { ElysiaOpenAPIConfig
|
|
2
|
+
import type { ElysiaOpenAPIConfig } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Plugin for [elysia](https://github.com/elysiajs/elysia) that auto-generate OpenAPI documentation page.
|
|
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"
|
|
8
|
+
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references, mapJsonSchema }?: ElysiaOpenAPIConfig<Enabled, Path>) => Elysia<"", {
|
|
9
9
|
decorator: {};
|
|
10
10
|
store: {};
|
|
11
11
|
derive: {};
|
package/dist/cjs/index.js
CHANGED
|
@@ -317,12 +317,52 @@ var getPossiblePath = (path) => {
|
|
|
317
317
|
}
|
|
318
318
|
return paths;
|
|
319
319
|
};
|
|
320
|
-
var isValidSchema = (schema) => typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
320
|
+
var isValidSchema = (schema) => schema && typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
321
321
|
var getLoosePath = (path) => {
|
|
322
322
|
if (path.charCodeAt(path.length - 1) === 47)
|
|
323
323
|
return path.slice(0, path.length - 1);
|
|
324
324
|
return path + "/";
|
|
325
325
|
};
|
|
326
|
+
var warnings = {
|
|
327
|
+
zod4: `import openapi from '@elysiajs/openapi'
|
|
328
|
+
import * as z from 'zod'
|
|
329
|
+
|
|
330
|
+
openapi({
|
|
331
|
+
mapJsonSchema: {
|
|
332
|
+
zod: z.toJSONSchema
|
|
333
|
+
}
|
|
334
|
+
})`,
|
|
335
|
+
zod3: `import openapi from '@elysiajs/openapi'
|
|
336
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
337
|
+
|
|
338
|
+
openapi({
|
|
339
|
+
mapJsonSchema: {
|
|
340
|
+
zod: zodToJsonSchema
|
|
341
|
+
}
|
|
342
|
+
})`,
|
|
343
|
+
valibot: `import openapi from '@elysiajs/openapi'
|
|
344
|
+
import { toJsonSchema } from '@valibot/to-json-schema'
|
|
345
|
+
|
|
346
|
+
openapi({
|
|
347
|
+
mapJsonSchema: {
|
|
348
|
+
valibot: toJsonSchema
|
|
349
|
+
}
|
|
350
|
+
})`,
|
|
351
|
+
effect: `import { JSONSchema } from 'effect'
|
|
352
|
+
|
|
353
|
+
openapi({
|
|
354
|
+
mapJsonSchema: {
|
|
355
|
+
effect: JSONSchema.make
|
|
356
|
+
}
|
|
357
|
+
})`
|
|
358
|
+
};
|
|
359
|
+
var warned = {};
|
|
360
|
+
var unwrapReference = (schema, definitions) => {
|
|
361
|
+
if (!schema?.$ref) return schema;
|
|
362
|
+
const name = schema.$ref.slice(schema.$ref.lastIndexOf("/") + 1);
|
|
363
|
+
if (schema.$ref && definitions[name]) schema = definitions[name];
|
|
364
|
+
return schema;
|
|
365
|
+
};
|
|
326
366
|
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
327
367
|
if (!schema) return;
|
|
328
368
|
if (typeof schema === "string") schema = toRef(schema);
|
|
@@ -331,20 +371,63 @@ var unwrapSchema = (schema, mapJsonSchema) => {
|
|
|
331
371
|
const vendor = schema["~standard"].vendor;
|
|
332
372
|
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
333
373
|
return mapJsonSchema[vendor](schema);
|
|
334
|
-
|
|
335
|
-
|
|
374
|
+
switch (vendor) {
|
|
375
|
+
case "zod":
|
|
376
|
+
if (warned.zod4 || warned.zod3) break;
|
|
377
|
+
console.warn(
|
|
378
|
+
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
379
|
+
);
|
|
380
|
+
if ("_zod" in schema) {
|
|
381
|
+
warned.zod4 = true;
|
|
382
|
+
console.warn(
|
|
383
|
+
"For Zod v4, please provide z.toJSONSchema as follows:\n"
|
|
384
|
+
);
|
|
385
|
+
console.warn(warnings.zod4);
|
|
386
|
+
} else {
|
|
387
|
+
warned.zod3 = true;
|
|
388
|
+
console.warn(
|
|
389
|
+
"For Zod v3, please install zod-to-json-schema package and use it like this:\n"
|
|
390
|
+
);
|
|
391
|
+
console.warn(warnings.zod3);
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
case "valibot":
|
|
395
|
+
if (warned.valibot) break;
|
|
396
|
+
warned.valibot = true;
|
|
397
|
+
console.warn(
|
|
398
|
+
"[@elysiajs/openapi] Valibot require a separate package for JSON Schema conversion"
|
|
399
|
+
);
|
|
400
|
+
console.warn(
|
|
401
|
+
"Please install @valibot/to-json-schema package and use it like this:\n"
|
|
402
|
+
);
|
|
403
|
+
console.warn(warnings.valibot);
|
|
404
|
+
break;
|
|
405
|
+
case "effect":
|
|
406
|
+
if (warned.effect) break;
|
|
407
|
+
warned.effect = true;
|
|
408
|
+
console.warn(
|
|
409
|
+
"[@elysiajs/openapi] Effect Schema doesn't provide JSON Schema method on the schema"
|
|
410
|
+
);
|
|
411
|
+
console.warn(
|
|
412
|
+
"please provide JSONSchema from 'effect' package as follows:\n"
|
|
413
|
+
);
|
|
414
|
+
console.warn(warnings.effect);
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
336
417
|
if (vendor === "arktype")
|
|
337
418
|
return schema?.toJsonSchema?.();
|
|
338
419
|
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
339
420
|
};
|
|
340
421
|
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
341
|
-
|
|
342
|
-
methods: excludeMethods = ["
|
|
422
|
+
let {
|
|
423
|
+
methods: excludeMethods = ["options"],
|
|
343
424
|
staticFile: excludeStaticFile = true,
|
|
344
425
|
tags: excludeTags
|
|
345
426
|
} = exclude ?? {};
|
|
427
|
+
excludeMethods = excludeMethods.map((method) => method.toLowerCase());
|
|
346
428
|
const excludePaths = Array.isArray(exclude?.paths) ? exclude.paths : typeof exclude?.paths !== "undefined" ? [exclude.paths] : [];
|
|
347
429
|
const paths = /* @__PURE__ */ Object.create(null);
|
|
430
|
+
const definitions = app.getGlobalDefinitions?.().type;
|
|
348
431
|
const routes = app.getGlobalRoutes();
|
|
349
432
|
if (references) {
|
|
350
433
|
if (!Array.isArray(references)) references = [references];
|
|
@@ -359,7 +442,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
359
442
|
if (excludeStaticFile && route.path.includes(".") || excludePaths.includes(route.path) || excludeMethods.includes(method))
|
|
360
443
|
continue;
|
|
361
444
|
const hooks = route.hooks ?? {};
|
|
362
|
-
if (
|
|
445
|
+
if (route.path === "/a") {
|
|
446
|
+
console.log("H");
|
|
447
|
+
}
|
|
448
|
+
if (references?.length)
|
|
363
449
|
for (const reference of references) {
|
|
364
450
|
if (!reference) continue;
|
|
365
451
|
const refer = reference[route.path]?.[method] ?? reference[getLoosePath(route.path)]?.[method];
|
|
@@ -390,7 +476,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
390
476
|
};
|
|
391
477
|
const parameters = [];
|
|
392
478
|
if (hooks.params) {
|
|
393
|
-
const params =
|
|
479
|
+
const params = unwrapReference(
|
|
480
|
+
unwrapSchema(hooks.params, vendors),
|
|
481
|
+
definitions
|
|
482
|
+
);
|
|
394
483
|
if (params && params.type === "object" && params.properties)
|
|
395
484
|
for (const [paramName, paramSchema] of Object.entries(
|
|
396
485
|
params.properties
|
|
@@ -404,7 +493,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
404
493
|
});
|
|
405
494
|
}
|
|
406
495
|
if (hooks.query) {
|
|
407
|
-
|
|
496
|
+
const query = unwrapReference(
|
|
497
|
+
unwrapSchema(hooks.query, vendors),
|
|
498
|
+
definitions
|
|
499
|
+
);
|
|
408
500
|
if (query && query.type === "object" && query.properties) {
|
|
409
501
|
const required = query.required || [];
|
|
410
502
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -419,7 +511,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
419
511
|
}
|
|
420
512
|
}
|
|
421
513
|
if (hooks.headers) {
|
|
422
|
-
const headers =
|
|
514
|
+
const headers = unwrapReference(
|
|
515
|
+
unwrapSchema(hooks.query, vendors),
|
|
516
|
+
definitions
|
|
517
|
+
);
|
|
423
518
|
if (headers && headers.type === "object" && headers.properties) {
|
|
424
519
|
const required = headers.required || [];
|
|
425
520
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -434,7 +529,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
434
529
|
}
|
|
435
530
|
}
|
|
436
531
|
if (hooks.cookie) {
|
|
437
|
-
const cookie =
|
|
532
|
+
const cookie = unwrapReference(
|
|
533
|
+
unwrapSchema(hooks.cookie, vendors),
|
|
534
|
+
definitions
|
|
535
|
+
);
|
|
438
536
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
439
537
|
const required = cookie.required || [];
|
|
440
538
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -578,10 +676,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
578
676
|
};
|
|
579
677
|
}
|
|
580
678
|
}
|
|
581
|
-
const _schemas = app.getGlobalDefinitions?.().type;
|
|
582
679
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
583
|
-
if (
|
|
584
|
-
for (const [name, schema] of Object.entries(
|
|
680
|
+
if (definitions)
|
|
681
|
+
for (const [name, schema] of Object.entries(definitions)) {
|
|
585
682
|
const jsonSchema = unwrapSchema(schema, vendors);
|
|
586
683
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
587
684
|
}
|
|
@@ -684,6 +781,10 @@ var openapi = ({
|
|
|
684
781
|
};
|
|
685
782
|
},
|
|
686
783
|
{
|
|
784
|
+
error({ error }) {
|
|
785
|
+
console.log("[@elysiajs/openapi] error at specPath");
|
|
786
|
+
console.warn(error);
|
|
787
|
+
},
|
|
687
788
|
detail: {
|
|
688
789
|
hide: true
|
|
689
790
|
}
|
package/dist/cjs/openapi.js
CHANGED
|
@@ -60,12 +60,52 @@ var getPossiblePath = (path) => {
|
|
|
60
60
|
}
|
|
61
61
|
return paths;
|
|
62
62
|
};
|
|
63
|
-
var isValidSchema = (schema) => typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
63
|
+
var isValidSchema = (schema) => schema && typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
64
64
|
var getLoosePath = (path) => {
|
|
65
65
|
if (path.charCodeAt(path.length - 1) === 47)
|
|
66
66
|
return path.slice(0, path.length - 1);
|
|
67
67
|
return path + "/";
|
|
68
68
|
};
|
|
69
|
+
var warnings = {
|
|
70
|
+
zod4: `import openapi from '@elysiajs/openapi'
|
|
71
|
+
import * as z from 'zod'
|
|
72
|
+
|
|
73
|
+
openapi({
|
|
74
|
+
mapJsonSchema: {
|
|
75
|
+
zod: z.toJSONSchema
|
|
76
|
+
}
|
|
77
|
+
})`,
|
|
78
|
+
zod3: `import openapi from '@elysiajs/openapi'
|
|
79
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
80
|
+
|
|
81
|
+
openapi({
|
|
82
|
+
mapJsonSchema: {
|
|
83
|
+
zod: zodToJsonSchema
|
|
84
|
+
}
|
|
85
|
+
})`,
|
|
86
|
+
valibot: `import openapi from '@elysiajs/openapi'
|
|
87
|
+
import { toJsonSchema } from '@valibot/to-json-schema'
|
|
88
|
+
|
|
89
|
+
openapi({
|
|
90
|
+
mapJsonSchema: {
|
|
91
|
+
valibot: toJsonSchema
|
|
92
|
+
}
|
|
93
|
+
})`,
|
|
94
|
+
effect: `import { JSONSchema } from 'effect'
|
|
95
|
+
|
|
96
|
+
openapi({
|
|
97
|
+
mapJsonSchema: {
|
|
98
|
+
effect: JSONSchema.make
|
|
99
|
+
}
|
|
100
|
+
})`
|
|
101
|
+
};
|
|
102
|
+
var warned = {};
|
|
103
|
+
var unwrapReference = (schema, definitions) => {
|
|
104
|
+
if (!schema?.$ref) return schema;
|
|
105
|
+
const name = schema.$ref.slice(schema.$ref.lastIndexOf("/") + 1);
|
|
106
|
+
if (schema.$ref && definitions[name]) schema = definitions[name];
|
|
107
|
+
return schema;
|
|
108
|
+
};
|
|
69
109
|
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
70
110
|
if (!schema) return;
|
|
71
111
|
if (typeof schema === "string") schema = toRef(schema);
|
|
@@ -74,20 +114,63 @@ var unwrapSchema = (schema, mapJsonSchema) => {
|
|
|
74
114
|
const vendor = schema["~standard"].vendor;
|
|
75
115
|
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
76
116
|
return mapJsonSchema[vendor](schema);
|
|
77
|
-
|
|
78
|
-
|
|
117
|
+
switch (vendor) {
|
|
118
|
+
case "zod":
|
|
119
|
+
if (warned.zod4 || warned.zod3) break;
|
|
120
|
+
console.warn(
|
|
121
|
+
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
122
|
+
);
|
|
123
|
+
if ("_zod" in schema) {
|
|
124
|
+
warned.zod4 = true;
|
|
125
|
+
console.warn(
|
|
126
|
+
"For Zod v4, please provide z.toJSONSchema as follows:\n"
|
|
127
|
+
);
|
|
128
|
+
console.warn(warnings.zod4);
|
|
129
|
+
} else {
|
|
130
|
+
warned.zod3 = true;
|
|
131
|
+
console.warn(
|
|
132
|
+
"For Zod v3, please install zod-to-json-schema package and use it like this:\n"
|
|
133
|
+
);
|
|
134
|
+
console.warn(warnings.zod3);
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
case "valibot":
|
|
138
|
+
if (warned.valibot) break;
|
|
139
|
+
warned.valibot = true;
|
|
140
|
+
console.warn(
|
|
141
|
+
"[@elysiajs/openapi] Valibot require a separate package for JSON Schema conversion"
|
|
142
|
+
);
|
|
143
|
+
console.warn(
|
|
144
|
+
"Please install @valibot/to-json-schema package and use it like this:\n"
|
|
145
|
+
);
|
|
146
|
+
console.warn(warnings.valibot);
|
|
147
|
+
break;
|
|
148
|
+
case "effect":
|
|
149
|
+
if (warned.effect) break;
|
|
150
|
+
warned.effect = true;
|
|
151
|
+
console.warn(
|
|
152
|
+
"[@elysiajs/openapi] Effect Schema doesn't provide JSON Schema method on the schema"
|
|
153
|
+
);
|
|
154
|
+
console.warn(
|
|
155
|
+
"please provide JSONSchema from 'effect' package as follows:\n"
|
|
156
|
+
);
|
|
157
|
+
console.warn(warnings.effect);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
79
160
|
if (vendor === "arktype")
|
|
80
161
|
return schema?.toJsonSchema?.();
|
|
81
162
|
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
82
163
|
};
|
|
83
164
|
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
84
|
-
|
|
85
|
-
methods: excludeMethods = ["
|
|
165
|
+
let {
|
|
166
|
+
methods: excludeMethods = ["options"],
|
|
86
167
|
staticFile: excludeStaticFile = true,
|
|
87
168
|
tags: excludeTags
|
|
88
169
|
} = exclude ?? {};
|
|
170
|
+
excludeMethods = excludeMethods.map((method) => method.toLowerCase());
|
|
89
171
|
const excludePaths = Array.isArray(exclude?.paths) ? exclude.paths : typeof exclude?.paths !== "undefined" ? [exclude.paths] : [];
|
|
90
172
|
const paths = /* @__PURE__ */ Object.create(null);
|
|
173
|
+
const definitions = app.getGlobalDefinitions?.().type;
|
|
91
174
|
const routes = app.getGlobalRoutes();
|
|
92
175
|
if (references) {
|
|
93
176
|
if (!Array.isArray(references)) references = [references];
|
|
@@ -102,7 +185,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
102
185
|
if (excludeStaticFile && route.path.includes(".") || excludePaths.includes(route.path) || excludeMethods.includes(method))
|
|
103
186
|
continue;
|
|
104
187
|
const hooks = route.hooks ?? {};
|
|
105
|
-
if (
|
|
188
|
+
if (route.path === "/a") {
|
|
189
|
+
console.log("H");
|
|
190
|
+
}
|
|
191
|
+
if (references?.length)
|
|
106
192
|
for (const reference of references) {
|
|
107
193
|
if (!reference) continue;
|
|
108
194
|
const refer = reference[route.path]?.[method] ?? reference[getLoosePath(route.path)]?.[method];
|
|
@@ -133,7 +219,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
133
219
|
};
|
|
134
220
|
const parameters = [];
|
|
135
221
|
if (hooks.params) {
|
|
136
|
-
const params =
|
|
222
|
+
const params = unwrapReference(
|
|
223
|
+
unwrapSchema(hooks.params, vendors),
|
|
224
|
+
definitions
|
|
225
|
+
);
|
|
137
226
|
if (params && params.type === "object" && params.properties)
|
|
138
227
|
for (const [paramName, paramSchema] of Object.entries(
|
|
139
228
|
params.properties
|
|
@@ -147,7 +236,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
147
236
|
});
|
|
148
237
|
}
|
|
149
238
|
if (hooks.query) {
|
|
150
|
-
|
|
239
|
+
const query = unwrapReference(
|
|
240
|
+
unwrapSchema(hooks.query, vendors),
|
|
241
|
+
definitions
|
|
242
|
+
);
|
|
151
243
|
if (query && query.type === "object" && query.properties) {
|
|
152
244
|
const required = query.required || [];
|
|
153
245
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -162,7 +254,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
162
254
|
}
|
|
163
255
|
}
|
|
164
256
|
if (hooks.headers) {
|
|
165
|
-
const headers =
|
|
257
|
+
const headers = unwrapReference(
|
|
258
|
+
unwrapSchema(hooks.query, vendors),
|
|
259
|
+
definitions
|
|
260
|
+
);
|
|
166
261
|
if (headers && headers.type === "object" && headers.properties) {
|
|
167
262
|
const required = headers.required || [];
|
|
168
263
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -177,7 +272,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
177
272
|
}
|
|
178
273
|
}
|
|
179
274
|
if (hooks.cookie) {
|
|
180
|
-
const cookie =
|
|
275
|
+
const cookie = unwrapReference(
|
|
276
|
+
unwrapSchema(hooks.cookie, vendors),
|
|
277
|
+
definitions
|
|
278
|
+
);
|
|
181
279
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
182
280
|
const required = cookie.required || [];
|
|
183
281
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -321,10 +419,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
321
419
|
};
|
|
322
420
|
}
|
|
323
421
|
}
|
|
324
|
-
const _schemas = app.getGlobalDefinitions?.().type;
|
|
325
422
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
326
|
-
if (
|
|
327
|
-
for (const [name, schema] of Object.entries(
|
|
423
|
+
if (definitions)
|
|
424
|
+
for (const [name, schema] of Object.entries(definitions)) {
|
|
328
425
|
const jsonSchema = unwrapSchema(schema, vendors);
|
|
329
426
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
330
427
|
}
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type OpenAPIProvider = 'scalar' | 'swagger-ui' | null;
|
|
|
6
6
|
type MaybeArray<T> = T | T[];
|
|
7
7
|
export type MapJsonSchema = {
|
|
8
8
|
[vendor: string]: Function;
|
|
9
|
+
} & {
|
|
10
|
+
[vendor in 'zod' | 'effect' | 'valibot' | 'arktype' | 'typemap' | 'yup' | 'joi']?: Function;
|
|
9
11
|
};
|
|
10
12
|
export type AdditionalReference = {
|
|
11
13
|
[path in string]: {
|
|
@@ -21,7 +23,7 @@ export type AdditionalReference = {
|
|
|
21
23
|
};
|
|
22
24
|
};
|
|
23
25
|
export type AdditionalReferences = MaybeArray<AdditionalReference | undefined | (() => AdditionalReference | undefined)>;
|
|
24
|
-
export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extends string = '/swagger'
|
|
26
|
+
export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extends string = '/swagger'> {
|
|
25
27
|
/**
|
|
26
28
|
* @default true
|
|
27
29
|
*/
|
|
@@ -67,7 +69,7 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
67
69
|
* @see https://github.com/scalar/scalar
|
|
68
70
|
* @see https://github.com/swagger-api/swagger-ui
|
|
69
71
|
*/
|
|
70
|
-
provider?:
|
|
72
|
+
provider?: OpenAPIProvider;
|
|
71
73
|
/**
|
|
72
74
|
* Additional reference for each endpoint
|
|
73
75
|
*/
|
|
@@ -81,7 +83,7 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
81
83
|
* import { toJsonSchema } from '@valibot/to-json-schema'
|
|
82
84
|
*
|
|
83
85
|
* openapi({
|
|
84
|
-
*
|
|
86
|
+
* mapJsonSchema: {
|
|
85
87
|
* valibot: toJsonSchema
|
|
86
88
|
* }
|
|
87
89
|
* })
|
package/dist/gen/index.d.ts
CHANGED
|
@@ -46,6 +46,11 @@ interface OpenAPIGeneratorOptions {
|
|
|
46
46
|
* ! be careful that the folder will be removed after the process ends
|
|
47
47
|
*/
|
|
48
48
|
tmpRoot?: string;
|
|
49
|
+
/**
|
|
50
|
+
* disable log
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
silent?: boolean;
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* Auto generate OpenAPI schema from Elysia instance
|
|
@@ -60,5 +65,5 @@ export declare const fromTypes: (
|
|
|
60
65
|
*
|
|
61
66
|
* The path must export an Elysia instance
|
|
62
67
|
*/
|
|
63
|
-
targetFilePath: string, { tsconfigPath, instanceName, projectRoot, overrideOutputPath, debug, compilerOptions, tmpRoot }?: OpenAPIGeneratorOptions) => () => AdditionalReference | undefined;
|
|
68
|
+
targetFilePath: string, { tsconfigPath, instanceName, projectRoot, overrideOutputPath, debug, compilerOptions, tmpRoot, silent }?: OpenAPIGeneratorOptions) => () => AdditionalReference | undefined;
|
|
64
69
|
export {};
|
package/dist/gen/index.mjs
CHANGED
|
@@ -8304,6 +8304,35 @@ import { spawnSync } from "child_process";
|
|
|
8304
8304
|
var matchRoute = /: Elysia<(.*)>/gs;
|
|
8305
8305
|
var matchStatus = /(\d{3}):/g;
|
|
8306
8306
|
var wrapStatusInQuote = (value) => value.replace(matchStatus, '"$1":');
|
|
8307
|
+
function extractRootObjects(code) {
|
|
8308
|
+
const results = [];
|
|
8309
|
+
let i = 0;
|
|
8310
|
+
while (i < code.length) {
|
|
8311
|
+
const colonIdx = code.indexOf(":", i);
|
|
8312
|
+
if (colonIdx === -1) break;
|
|
8313
|
+
let keyEnd = colonIdx - 1;
|
|
8314
|
+
while (keyEnd >= 0 && /\s/.test(code[keyEnd])) keyEnd--;
|
|
8315
|
+
let keyStart = keyEnd;
|
|
8316
|
+
while (keyStart >= 0 && /\w/.test(code[keyStart])) keyStart--;
|
|
8317
|
+
const braceIdx = code.indexOf("{", colonIdx);
|
|
8318
|
+
if (braceIdx === -1) break;
|
|
8319
|
+
let depth = 0;
|
|
8320
|
+
let end = braceIdx;
|
|
8321
|
+
for (; end < code.length; end++) {
|
|
8322
|
+
if (code[end] === "{") depth++;
|
|
8323
|
+
else if (code[end] === "}") {
|
|
8324
|
+
depth--;
|
|
8325
|
+
if (depth === 0) {
|
|
8326
|
+
end++;
|
|
8327
|
+
break;
|
|
8328
|
+
}
|
|
8329
|
+
}
|
|
8330
|
+
}
|
|
8331
|
+
results.push(`{${code.slice(keyStart + 1, end)};}`);
|
|
8332
|
+
i = end;
|
|
8333
|
+
}
|
|
8334
|
+
return results;
|
|
8335
|
+
}
|
|
8307
8336
|
var fromTypes = (targetFilePath, {
|
|
8308
8337
|
tsconfigPath = "tsconfig.json",
|
|
8309
8338
|
instanceName,
|
|
@@ -8311,7 +8340,8 @@ var fromTypes = (targetFilePath, {
|
|
|
8311
8340
|
overrideOutputPath,
|
|
8312
8341
|
debug = false,
|
|
8313
8342
|
compilerOptions,
|
|
8314
|
-
tmpRoot = join(tmpdir(), ".ElysiaAutoOpenAPI")
|
|
8343
|
+
tmpRoot = join(tmpdir(), ".ElysiaAutoOpenAPI"),
|
|
8344
|
+
silent = false
|
|
8315
8345
|
} = {}) => () => {
|
|
8316
8346
|
try {
|
|
8317
8347
|
if (!targetFilePath.endsWith(".ts") && !targetFilePath.endsWith(".tsx"))
|
|
@@ -8358,7 +8388,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8358
8388
|
spawnSync(`tsc`, {
|
|
8359
8389
|
shell: true,
|
|
8360
8390
|
cwd: tmpRoot,
|
|
8361
|
-
stdio:
|
|
8391
|
+
stdio: silent ? void 0 : "inherit"
|
|
8362
8392
|
});
|
|
8363
8393
|
const fileName = targetFilePath.replace(/.tsx$/, ".ts").replace(/.ts$/, ".d.ts");
|
|
8364
8394
|
targetFile = (overrideOutputPath ? typeof overrideOutputPath === "string" ? overrideOutputPath.startsWith("/") ? overrideOutputPath : join(tmpRoot, "dist", overrideOutputPath) : overrideOutputPath(tmpRoot) : void 0) ?? join(
|
|
@@ -8394,7 +8424,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8394
8424
|
console.warn(tempFiles);
|
|
8395
8425
|
}
|
|
8396
8426
|
} else {
|
|
8397
|
-
console.
|
|
8427
|
+
console.warn(
|
|
8398
8428
|
"reason: root folder doesn't exists",
|
|
8399
8429
|
join(tmpRoot, "dist")
|
|
8400
8430
|
);
|
|
@@ -8403,7 +8433,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8403
8433
|
}
|
|
8404
8434
|
}
|
|
8405
8435
|
const declaration = readFileSync(targetFile, "utf8");
|
|
8406
|
-
if (existsSync(tmpRoot))
|
|
8436
|
+
if (!debug && existsSync(tmpRoot))
|
|
8407
8437
|
rmSync(tmpRoot, { recursive: true, force: true });
|
|
8408
8438
|
let instance = declaration.match(
|
|
8409
8439
|
instanceName ? new RegExp(`${instanceName}: Elysia<(.*)`, "gs") : matchRoute
|
|
@@ -8423,8 +8453,8 @@ var fromTypes = (targetFilePath, {
|
|
|
8423
8453
|
instance.slice(3, instance.indexOf("}, {", 4))
|
|
8424
8454
|
);
|
|
8425
8455
|
const routes = {};
|
|
8426
|
-
for (const route of routesString
|
|
8427
|
-
let schema = TypeBox(
|
|
8456
|
+
for (const route of extractRootObjects(routesString)) {
|
|
8457
|
+
let schema = TypeBox(route);
|
|
8428
8458
|
if (schema.type !== "object") continue;
|
|
8429
8459
|
const paths = [];
|
|
8430
8460
|
while (true) {
|
|
@@ -8435,6 +8465,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8435
8465
|
if (!schema?.properties) break;
|
|
8436
8466
|
}
|
|
8437
8467
|
const method = paths.pop();
|
|
8468
|
+
if (!method) continue;
|
|
8438
8469
|
const path = "/" + paths.join("/");
|
|
8439
8470
|
schema = schema.properties;
|
|
8440
8471
|
if (schema?.response?.type === "object") {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
|
-
import type { ElysiaOpenAPIConfig
|
|
2
|
+
import type { ElysiaOpenAPIConfig } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Plugin for [elysia](https://github.com/elysiajs/elysia) that auto-generate OpenAPI documentation page.
|
|
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"
|
|
8
|
+
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references, mapJsonSchema }?: ElysiaOpenAPIConfig<Enabled, Path>) => Elysia<"", {
|
|
9
9
|
decorator: {};
|
|
10
10
|
store: {};
|
|
11
11
|
derive: {};
|
package/dist/index.mjs
CHANGED
|
@@ -290,12 +290,52 @@ var getPossiblePath = (path) => {
|
|
|
290
290
|
}
|
|
291
291
|
return paths;
|
|
292
292
|
};
|
|
293
|
-
var isValidSchema = (schema) => typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
293
|
+
var isValidSchema = (schema) => schema && typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
294
294
|
var getLoosePath = (path) => {
|
|
295
295
|
if (path.charCodeAt(path.length - 1) === 47)
|
|
296
296
|
return path.slice(0, path.length - 1);
|
|
297
297
|
return path + "/";
|
|
298
298
|
};
|
|
299
|
+
var warnings = {
|
|
300
|
+
zod4: `import openapi from '@elysiajs/openapi'
|
|
301
|
+
import * as z from 'zod'
|
|
302
|
+
|
|
303
|
+
openapi({
|
|
304
|
+
mapJsonSchema: {
|
|
305
|
+
zod: z.toJSONSchema
|
|
306
|
+
}
|
|
307
|
+
})`,
|
|
308
|
+
zod3: `import openapi from '@elysiajs/openapi'
|
|
309
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
310
|
+
|
|
311
|
+
openapi({
|
|
312
|
+
mapJsonSchema: {
|
|
313
|
+
zod: zodToJsonSchema
|
|
314
|
+
}
|
|
315
|
+
})`,
|
|
316
|
+
valibot: `import openapi from '@elysiajs/openapi'
|
|
317
|
+
import { toJsonSchema } from '@valibot/to-json-schema'
|
|
318
|
+
|
|
319
|
+
openapi({
|
|
320
|
+
mapJsonSchema: {
|
|
321
|
+
valibot: toJsonSchema
|
|
322
|
+
}
|
|
323
|
+
})`,
|
|
324
|
+
effect: `import { JSONSchema } from 'effect'
|
|
325
|
+
|
|
326
|
+
openapi({
|
|
327
|
+
mapJsonSchema: {
|
|
328
|
+
effect: JSONSchema.make
|
|
329
|
+
}
|
|
330
|
+
})`
|
|
331
|
+
};
|
|
332
|
+
var warned = {};
|
|
333
|
+
var unwrapReference = (schema, definitions) => {
|
|
334
|
+
if (!schema?.$ref) return schema;
|
|
335
|
+
const name = schema.$ref.slice(schema.$ref.lastIndexOf("/") + 1);
|
|
336
|
+
if (schema.$ref && definitions[name]) schema = definitions[name];
|
|
337
|
+
return schema;
|
|
338
|
+
};
|
|
299
339
|
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
300
340
|
if (!schema) return;
|
|
301
341
|
if (typeof schema === "string") schema = toRef(schema);
|
|
@@ -304,20 +344,63 @@ var unwrapSchema = (schema, mapJsonSchema) => {
|
|
|
304
344
|
const vendor = schema["~standard"].vendor;
|
|
305
345
|
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
306
346
|
return mapJsonSchema[vendor](schema);
|
|
307
|
-
|
|
308
|
-
|
|
347
|
+
switch (vendor) {
|
|
348
|
+
case "zod":
|
|
349
|
+
if (warned.zod4 || warned.zod3) break;
|
|
350
|
+
console.warn(
|
|
351
|
+
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
352
|
+
);
|
|
353
|
+
if ("_zod" in schema) {
|
|
354
|
+
warned.zod4 = true;
|
|
355
|
+
console.warn(
|
|
356
|
+
"For Zod v4, please provide z.toJSONSchema as follows:\n"
|
|
357
|
+
);
|
|
358
|
+
console.warn(warnings.zod4);
|
|
359
|
+
} else {
|
|
360
|
+
warned.zod3 = true;
|
|
361
|
+
console.warn(
|
|
362
|
+
"For Zod v3, please install zod-to-json-schema package and use it like this:\n"
|
|
363
|
+
);
|
|
364
|
+
console.warn(warnings.zod3);
|
|
365
|
+
}
|
|
366
|
+
break;
|
|
367
|
+
case "valibot":
|
|
368
|
+
if (warned.valibot) break;
|
|
369
|
+
warned.valibot = true;
|
|
370
|
+
console.warn(
|
|
371
|
+
"[@elysiajs/openapi] Valibot require a separate package for JSON Schema conversion"
|
|
372
|
+
);
|
|
373
|
+
console.warn(
|
|
374
|
+
"Please install @valibot/to-json-schema package and use it like this:\n"
|
|
375
|
+
);
|
|
376
|
+
console.warn(warnings.valibot);
|
|
377
|
+
break;
|
|
378
|
+
case "effect":
|
|
379
|
+
if (warned.effect) break;
|
|
380
|
+
warned.effect = true;
|
|
381
|
+
console.warn(
|
|
382
|
+
"[@elysiajs/openapi] Effect Schema doesn't provide JSON Schema method on the schema"
|
|
383
|
+
);
|
|
384
|
+
console.warn(
|
|
385
|
+
"please provide JSONSchema from 'effect' package as follows:\n"
|
|
386
|
+
);
|
|
387
|
+
console.warn(warnings.effect);
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
309
390
|
if (vendor === "arktype")
|
|
310
391
|
return schema?.toJsonSchema?.();
|
|
311
392
|
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
312
393
|
};
|
|
313
394
|
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
314
|
-
|
|
315
|
-
methods: excludeMethods = ["
|
|
395
|
+
let {
|
|
396
|
+
methods: excludeMethods = ["options"],
|
|
316
397
|
staticFile: excludeStaticFile = true,
|
|
317
398
|
tags: excludeTags
|
|
318
399
|
} = exclude ?? {};
|
|
400
|
+
excludeMethods = excludeMethods.map((method) => method.toLowerCase());
|
|
319
401
|
const excludePaths = Array.isArray(exclude?.paths) ? exclude.paths : typeof exclude?.paths !== "undefined" ? [exclude.paths] : [];
|
|
320
402
|
const paths = /* @__PURE__ */ Object.create(null);
|
|
403
|
+
const definitions = app.getGlobalDefinitions?.().type;
|
|
321
404
|
const routes = app.getGlobalRoutes();
|
|
322
405
|
if (references) {
|
|
323
406
|
if (!Array.isArray(references)) references = [references];
|
|
@@ -332,7 +415,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
332
415
|
if (excludeStaticFile && route.path.includes(".") || excludePaths.includes(route.path) || excludeMethods.includes(method))
|
|
333
416
|
continue;
|
|
334
417
|
const hooks = route.hooks ?? {};
|
|
335
|
-
if (
|
|
418
|
+
if (route.path === "/a") {
|
|
419
|
+
console.log("H");
|
|
420
|
+
}
|
|
421
|
+
if (references?.length)
|
|
336
422
|
for (const reference of references) {
|
|
337
423
|
if (!reference) continue;
|
|
338
424
|
const refer = reference[route.path]?.[method] ?? reference[getLoosePath(route.path)]?.[method];
|
|
@@ -363,7 +449,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
363
449
|
};
|
|
364
450
|
const parameters = [];
|
|
365
451
|
if (hooks.params) {
|
|
366
|
-
const params =
|
|
452
|
+
const params = unwrapReference(
|
|
453
|
+
unwrapSchema(hooks.params, vendors),
|
|
454
|
+
definitions
|
|
455
|
+
);
|
|
367
456
|
if (params && params.type === "object" && params.properties)
|
|
368
457
|
for (const [paramName, paramSchema] of Object.entries(
|
|
369
458
|
params.properties
|
|
@@ -377,7 +466,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
377
466
|
});
|
|
378
467
|
}
|
|
379
468
|
if (hooks.query) {
|
|
380
|
-
|
|
469
|
+
const query = unwrapReference(
|
|
470
|
+
unwrapSchema(hooks.query, vendors),
|
|
471
|
+
definitions
|
|
472
|
+
);
|
|
381
473
|
if (query && query.type === "object" && query.properties) {
|
|
382
474
|
const required = query.required || [];
|
|
383
475
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -392,7 +484,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
392
484
|
}
|
|
393
485
|
}
|
|
394
486
|
if (hooks.headers) {
|
|
395
|
-
const headers =
|
|
487
|
+
const headers = unwrapReference(
|
|
488
|
+
unwrapSchema(hooks.query, vendors),
|
|
489
|
+
definitions
|
|
490
|
+
);
|
|
396
491
|
if (headers && headers.type === "object" && headers.properties) {
|
|
397
492
|
const required = headers.required || [];
|
|
398
493
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -407,7 +502,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
407
502
|
}
|
|
408
503
|
}
|
|
409
504
|
if (hooks.cookie) {
|
|
410
|
-
const cookie =
|
|
505
|
+
const cookie = unwrapReference(
|
|
506
|
+
unwrapSchema(hooks.cookie, vendors),
|
|
507
|
+
definitions
|
|
508
|
+
);
|
|
411
509
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
412
510
|
const required = cookie.required || [];
|
|
413
511
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -551,10 +649,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
551
649
|
};
|
|
552
650
|
}
|
|
553
651
|
}
|
|
554
|
-
const _schemas = app.getGlobalDefinitions?.().type;
|
|
555
652
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
556
|
-
if (
|
|
557
|
-
for (const [name, schema] of Object.entries(
|
|
653
|
+
if (definitions)
|
|
654
|
+
for (const [name, schema] of Object.entries(definitions)) {
|
|
558
655
|
const jsonSchema = unwrapSchema(schema, vendors);
|
|
559
656
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
560
657
|
}
|
|
@@ -657,6 +754,10 @@ var openapi = ({
|
|
|
657
754
|
};
|
|
658
755
|
},
|
|
659
756
|
{
|
|
757
|
+
error({ error }) {
|
|
758
|
+
console.log("[@elysiajs/openapi] error at specPath");
|
|
759
|
+
console.warn(error);
|
|
760
|
+
},
|
|
660
761
|
detail: {
|
|
661
762
|
hide: true
|
|
662
763
|
}
|
package/dist/openapi.mjs
CHANGED
|
@@ -31,12 +31,52 @@ var getPossiblePath = (path) => {
|
|
|
31
31
|
}
|
|
32
32
|
return paths;
|
|
33
33
|
};
|
|
34
|
-
var isValidSchema = (schema) => typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
34
|
+
var isValidSchema = (schema) => schema && typeof schema === "object" && (Kind in schema && schema[Kind] !== "Unknown" || schema.type || schema.properties || schema.items);
|
|
35
35
|
var getLoosePath = (path) => {
|
|
36
36
|
if (path.charCodeAt(path.length - 1) === 47)
|
|
37
37
|
return path.slice(0, path.length - 1);
|
|
38
38
|
return path + "/";
|
|
39
39
|
};
|
|
40
|
+
var warnings = {
|
|
41
|
+
zod4: `import openapi from '@elysiajs/openapi'
|
|
42
|
+
import * as z from 'zod'
|
|
43
|
+
|
|
44
|
+
openapi({
|
|
45
|
+
mapJsonSchema: {
|
|
46
|
+
zod: z.toJSONSchema
|
|
47
|
+
}
|
|
48
|
+
})`,
|
|
49
|
+
zod3: `import openapi from '@elysiajs/openapi'
|
|
50
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
51
|
+
|
|
52
|
+
openapi({
|
|
53
|
+
mapJsonSchema: {
|
|
54
|
+
zod: zodToJsonSchema
|
|
55
|
+
}
|
|
56
|
+
})`,
|
|
57
|
+
valibot: `import openapi from '@elysiajs/openapi'
|
|
58
|
+
import { toJsonSchema } from '@valibot/to-json-schema'
|
|
59
|
+
|
|
60
|
+
openapi({
|
|
61
|
+
mapJsonSchema: {
|
|
62
|
+
valibot: toJsonSchema
|
|
63
|
+
}
|
|
64
|
+
})`,
|
|
65
|
+
effect: `import { JSONSchema } from 'effect'
|
|
66
|
+
|
|
67
|
+
openapi({
|
|
68
|
+
mapJsonSchema: {
|
|
69
|
+
effect: JSONSchema.make
|
|
70
|
+
}
|
|
71
|
+
})`
|
|
72
|
+
};
|
|
73
|
+
var warned = {};
|
|
74
|
+
var unwrapReference = (schema, definitions) => {
|
|
75
|
+
if (!schema?.$ref) return schema;
|
|
76
|
+
const name = schema.$ref.slice(schema.$ref.lastIndexOf("/") + 1);
|
|
77
|
+
if (schema.$ref && definitions[name]) schema = definitions[name];
|
|
78
|
+
return schema;
|
|
79
|
+
};
|
|
40
80
|
var unwrapSchema = (schema, mapJsonSchema) => {
|
|
41
81
|
if (!schema) return;
|
|
42
82
|
if (typeof schema === "string") schema = toRef(schema);
|
|
@@ -45,20 +85,63 @@ var unwrapSchema = (schema, mapJsonSchema) => {
|
|
|
45
85
|
const vendor = schema["~standard"].vendor;
|
|
46
86
|
if (mapJsonSchema?.[vendor] && typeof mapJsonSchema[vendor] === "function")
|
|
47
87
|
return mapJsonSchema[vendor](schema);
|
|
48
|
-
|
|
49
|
-
|
|
88
|
+
switch (vendor) {
|
|
89
|
+
case "zod":
|
|
90
|
+
if (warned.zod4 || warned.zod3) break;
|
|
91
|
+
console.warn(
|
|
92
|
+
"[@elysiajs/openapi] Zod doesn't provide JSON Schema method on the schema"
|
|
93
|
+
);
|
|
94
|
+
if ("_zod" in schema) {
|
|
95
|
+
warned.zod4 = true;
|
|
96
|
+
console.warn(
|
|
97
|
+
"For Zod v4, please provide z.toJSONSchema as follows:\n"
|
|
98
|
+
);
|
|
99
|
+
console.warn(warnings.zod4);
|
|
100
|
+
} else {
|
|
101
|
+
warned.zod3 = true;
|
|
102
|
+
console.warn(
|
|
103
|
+
"For Zod v3, please install zod-to-json-schema package and use it like this:\n"
|
|
104
|
+
);
|
|
105
|
+
console.warn(warnings.zod3);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case "valibot":
|
|
109
|
+
if (warned.valibot) break;
|
|
110
|
+
warned.valibot = true;
|
|
111
|
+
console.warn(
|
|
112
|
+
"[@elysiajs/openapi] Valibot require a separate package for JSON Schema conversion"
|
|
113
|
+
);
|
|
114
|
+
console.warn(
|
|
115
|
+
"Please install @valibot/to-json-schema package and use it like this:\n"
|
|
116
|
+
);
|
|
117
|
+
console.warn(warnings.valibot);
|
|
118
|
+
break;
|
|
119
|
+
case "effect":
|
|
120
|
+
if (warned.effect) break;
|
|
121
|
+
warned.effect = true;
|
|
122
|
+
console.warn(
|
|
123
|
+
"[@elysiajs/openapi] Effect Schema doesn't provide JSON Schema method on the schema"
|
|
124
|
+
);
|
|
125
|
+
console.warn(
|
|
126
|
+
"please provide JSONSchema from 'effect' package as follows:\n"
|
|
127
|
+
);
|
|
128
|
+
console.warn(warnings.effect);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
50
131
|
if (vendor === "arktype")
|
|
51
132
|
return schema?.toJsonSchema?.();
|
|
52
133
|
return schema.toJSONSchema?.() ?? schema?.toJsonSchema?.();
|
|
53
134
|
};
|
|
54
135
|
function toOpenAPISchema(app, exclude, references, vendors) {
|
|
55
|
-
|
|
56
|
-
methods: excludeMethods = ["
|
|
136
|
+
let {
|
|
137
|
+
methods: excludeMethods = ["options"],
|
|
57
138
|
staticFile: excludeStaticFile = true,
|
|
58
139
|
tags: excludeTags
|
|
59
140
|
} = exclude ?? {};
|
|
141
|
+
excludeMethods = excludeMethods.map((method) => method.toLowerCase());
|
|
60
142
|
const excludePaths = Array.isArray(exclude?.paths) ? exclude.paths : typeof exclude?.paths !== "undefined" ? [exclude.paths] : [];
|
|
61
143
|
const paths = /* @__PURE__ */ Object.create(null);
|
|
144
|
+
const definitions = app.getGlobalDefinitions?.().type;
|
|
62
145
|
const routes = app.getGlobalRoutes();
|
|
63
146
|
if (references) {
|
|
64
147
|
if (!Array.isArray(references)) references = [references];
|
|
@@ -73,7 +156,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
73
156
|
if (excludeStaticFile && route.path.includes(".") || excludePaths.includes(route.path) || excludeMethods.includes(method))
|
|
74
157
|
continue;
|
|
75
158
|
const hooks = route.hooks ?? {};
|
|
76
|
-
if (
|
|
159
|
+
if (route.path === "/a") {
|
|
160
|
+
console.log("H");
|
|
161
|
+
}
|
|
162
|
+
if (references?.length)
|
|
77
163
|
for (const reference of references) {
|
|
78
164
|
if (!reference) continue;
|
|
79
165
|
const refer = reference[route.path]?.[method] ?? reference[getLoosePath(route.path)]?.[method];
|
|
@@ -104,7 +190,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
104
190
|
};
|
|
105
191
|
const parameters = [];
|
|
106
192
|
if (hooks.params) {
|
|
107
|
-
const params =
|
|
193
|
+
const params = unwrapReference(
|
|
194
|
+
unwrapSchema(hooks.params, vendors),
|
|
195
|
+
definitions
|
|
196
|
+
);
|
|
108
197
|
if (params && params.type === "object" && params.properties)
|
|
109
198
|
for (const [paramName, paramSchema] of Object.entries(
|
|
110
199
|
params.properties
|
|
@@ -118,7 +207,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
118
207
|
});
|
|
119
208
|
}
|
|
120
209
|
if (hooks.query) {
|
|
121
|
-
|
|
210
|
+
const query = unwrapReference(
|
|
211
|
+
unwrapSchema(hooks.query, vendors),
|
|
212
|
+
definitions
|
|
213
|
+
);
|
|
122
214
|
if (query && query.type === "object" && query.properties) {
|
|
123
215
|
const required = query.required || [];
|
|
124
216
|
for (const [queryName, querySchema] of Object.entries(
|
|
@@ -133,7 +225,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
133
225
|
}
|
|
134
226
|
}
|
|
135
227
|
if (hooks.headers) {
|
|
136
|
-
const headers =
|
|
228
|
+
const headers = unwrapReference(
|
|
229
|
+
unwrapSchema(hooks.query, vendors),
|
|
230
|
+
definitions
|
|
231
|
+
);
|
|
137
232
|
if (headers && headers.type === "object" && headers.properties) {
|
|
138
233
|
const required = headers.required || [];
|
|
139
234
|
for (const [headerName, headerSchema] of Object.entries(
|
|
@@ -148,7 +243,10 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
148
243
|
}
|
|
149
244
|
}
|
|
150
245
|
if (hooks.cookie) {
|
|
151
|
-
const cookie =
|
|
246
|
+
const cookie = unwrapReference(
|
|
247
|
+
unwrapSchema(hooks.cookie, vendors),
|
|
248
|
+
definitions
|
|
249
|
+
);
|
|
152
250
|
if (cookie && cookie.type === "object" && cookie.properties) {
|
|
153
251
|
const required = cookie.required || [];
|
|
154
252
|
for (const [cookieName, cookieSchema] of Object.entries(
|
|
@@ -292,10 +390,9 @@ function toOpenAPISchema(app, exclude, references, vendors) {
|
|
|
292
390
|
};
|
|
293
391
|
}
|
|
294
392
|
}
|
|
295
|
-
const _schemas = app.getGlobalDefinitions?.().type;
|
|
296
393
|
const schemas = /* @__PURE__ */ Object.create(null);
|
|
297
|
-
if (
|
|
298
|
-
for (const [name, schema] of Object.entries(
|
|
394
|
+
if (definitions)
|
|
395
|
+
for (const [name, schema] of Object.entries(definitions)) {
|
|
299
396
|
const jsonSchema = unwrapSchema(schema, vendors);
|
|
300
397
|
if (jsonSchema) schemas[name] = jsonSchema;
|
|
301
398
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type OpenAPIProvider = 'scalar' | 'swagger-ui' | null;
|
|
|
6
6
|
type MaybeArray<T> = T | T[];
|
|
7
7
|
export type MapJsonSchema = {
|
|
8
8
|
[vendor: string]: Function;
|
|
9
|
+
} & {
|
|
10
|
+
[vendor in 'zod' | 'effect' | 'valibot' | 'arktype' | 'typemap' | 'yup' | 'joi']?: Function;
|
|
9
11
|
};
|
|
10
12
|
export type AdditionalReference = {
|
|
11
13
|
[path in string]: {
|
|
@@ -21,7 +23,7 @@ export type AdditionalReference = {
|
|
|
21
23
|
};
|
|
22
24
|
};
|
|
23
25
|
export type AdditionalReferences = MaybeArray<AdditionalReference | undefined | (() => AdditionalReference | undefined)>;
|
|
24
|
-
export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extends string = '/swagger'
|
|
26
|
+
export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extends string = '/swagger'> {
|
|
25
27
|
/**
|
|
26
28
|
* @default true
|
|
27
29
|
*/
|
|
@@ -67,7 +69,7 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
67
69
|
* @see https://github.com/scalar/scalar
|
|
68
70
|
* @see https://github.com/swagger-api/swagger-ui
|
|
69
71
|
*/
|
|
70
|
-
provider?:
|
|
72
|
+
provider?: OpenAPIProvider;
|
|
71
73
|
/**
|
|
72
74
|
* Additional reference for each endpoint
|
|
73
75
|
*/
|
|
@@ -81,7 +83,7 @@ export interface ElysiaOpenAPIConfig<Enabled extends boolean = true, Path extend
|
|
|
81
83
|
* import { toJsonSchema } from '@valibot/to-json-schema'
|
|
82
84
|
*
|
|
83
85
|
* openapi({
|
|
84
|
-
*
|
|
86
|
+
* mapJsonSchema: {
|
|
85
87
|
* valibot: toJsonSchema
|
|
86
88
|
* }
|
|
87
89
|
* })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elysiajs/openapi",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "Plugin for Elysia to auto-generate API documentation",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "saltyAom",
|
|
@@ -79,7 +79,8 @@
|
|
|
79
79
|
"@scalar/types": "^0.2.13",
|
|
80
80
|
"@sinclair/typemap": "^0.10.1",
|
|
81
81
|
"@types/bun": "1.2.20",
|
|
82
|
-
"
|
|
82
|
+
"effect": "^3.17.13",
|
|
83
|
+
"elysia": "1.4.6",
|
|
83
84
|
"eslint": "9.6.0",
|
|
84
85
|
"openapi-types": "^12.1.3",
|
|
85
86
|
"tsup": "^8.5.0",
|