@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/README.md
CHANGED
|
@@ -83,7 +83,7 @@ The endpoint to expose OpenAPI documentation frontend
|
|
|
83
83
|
|
|
84
84
|
OpenAPI documentation frontend between:
|
|
85
85
|
- [Scalar](https://github.com/scalar/scalar)
|
|
86
|
-
- [SwaggerUI](https://github.com/
|
|
86
|
+
- [SwaggerUI](https://github.com/swagger-api/swagger-ui)
|
|
87
87
|
- null: disable frontend
|
|
88
88
|
|
|
89
89
|
## references
|
package/dist/cjs/gen/index.js
CHANGED
|
@@ -20,10 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/gen/index.ts
|
|
21
21
|
var gen_exports = {};
|
|
22
22
|
__export(gen_exports, {
|
|
23
|
+
declarationToJSONSchema: () => declarationToJSONSchema,
|
|
24
|
+
extractRootObjects: () => extractRootObjects,
|
|
23
25
|
fromTypes: () => fromTypes
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(gen_exports);
|
|
26
|
-
var import_fs = require("fs");
|
|
27
28
|
|
|
28
29
|
// node_modules/@sinclair/typebox/build/esm/value/guard/guard.mjs
|
|
29
30
|
function IsObject(value) {
|
|
@@ -8309,11 +8310,9 @@ function TypeBox(...args) {
|
|
|
8309
8310
|
}
|
|
8310
8311
|
|
|
8311
8312
|
// src/gen/index.ts
|
|
8312
|
-
var import_os = require("os");
|
|
8313
|
-
var import_path2 = require("path");
|
|
8314
|
-
var import_child_process = require("child_process");
|
|
8315
8313
|
var matchRoute = /: Elysia<(.*)>/gs;
|
|
8316
|
-
var
|
|
8314
|
+
var numberKey = /(\d+):/g;
|
|
8315
|
+
var join = (...parts) => parts.join("/").replace(/\/{1,}/g, "/");
|
|
8317
8316
|
function extractRootObjects(code) {
|
|
8318
8317
|
const results = [];
|
|
8319
8318
|
let i = 0;
|
|
@@ -8345,42 +8344,90 @@ function extractRootObjects(code) {
|
|
|
8345
8344
|
}
|
|
8346
8345
|
return results;
|
|
8347
8346
|
}
|
|
8348
|
-
|
|
8347
|
+
function declarationToJSONSchema(declaration) {
|
|
8348
|
+
const routes = {};
|
|
8349
|
+
for (const route of extractRootObjects(
|
|
8350
|
+
declaration.replace(numberKey, '"$1":')
|
|
8351
|
+
)) {
|
|
8352
|
+
let schema = TypeBox(route.replaceAll(/readonly/g, ""));
|
|
8353
|
+
if (schema.type !== "object") continue;
|
|
8354
|
+
const paths = [];
|
|
8355
|
+
while (true) {
|
|
8356
|
+
const keys = Object.keys(schema.properties);
|
|
8357
|
+
if (keys.length !== 1) break;
|
|
8358
|
+
paths.push(keys[0]);
|
|
8359
|
+
schema = schema.properties[keys[0]];
|
|
8360
|
+
if (!schema?.properties) break;
|
|
8361
|
+
}
|
|
8362
|
+
const method = paths.pop();
|
|
8363
|
+
if (!method) continue;
|
|
8364
|
+
const path = "/" + paths.join("/");
|
|
8365
|
+
schema = schema.properties;
|
|
8366
|
+
if (schema?.response?.type === "object") {
|
|
8367
|
+
const responseSchema = {};
|
|
8368
|
+
for (const key in schema.response.properties)
|
|
8369
|
+
responseSchema[key] = schema.response.properties[key];
|
|
8370
|
+
schema.response = responseSchema;
|
|
8371
|
+
}
|
|
8372
|
+
if (!routes[path]) routes[path] = {};
|
|
8373
|
+
routes[path][method.toLowerCase()] = schema;
|
|
8374
|
+
}
|
|
8375
|
+
return routes;
|
|
8376
|
+
}
|
|
8377
|
+
var fromTypes = (targetFilePath = "src/index.ts", {
|
|
8349
8378
|
tsconfigPath = "tsconfig.json",
|
|
8350
8379
|
instanceName,
|
|
8351
8380
|
projectRoot = process.cwd(),
|
|
8352
8381
|
overrideOutputPath,
|
|
8353
8382
|
debug = false,
|
|
8354
8383
|
compilerOptions,
|
|
8355
|
-
tmpRoot
|
|
8384
|
+
tmpRoot,
|
|
8356
8385
|
silent = false
|
|
8357
8386
|
} = {}) => () => {
|
|
8387
|
+
if (targetFilePath.trimStart().startsWith("{") && targetFilePath.trimEnd().endsWith("}"))
|
|
8388
|
+
return declarationToJSONSchema(targetFilePath);
|
|
8389
|
+
if (typeof process === "undefined" || typeof process.getBuiltinModule !== "function")
|
|
8390
|
+
throw new Error(
|
|
8391
|
+
"[@elysiajs/openapi/gen] `fromTypes` from file path is only available in Node.js/Bun environment or environments"
|
|
8392
|
+
);
|
|
8393
|
+
const fs = process.getBuiltinModule("fs");
|
|
8394
|
+
if (!fs)
|
|
8395
|
+
throw new Error(
|
|
8396
|
+
"[@elysiajs/openapi/gen] `fromTypes` require `fs` module which is not available in this environment"
|
|
8397
|
+
);
|
|
8358
8398
|
try {
|
|
8359
8399
|
if (!targetFilePath.endsWith(".ts") && !targetFilePath.endsWith(".tsx"))
|
|
8360
8400
|
throw new Error("Only .ts files are supported");
|
|
8361
8401
|
if (targetFilePath.startsWith("./"))
|
|
8362
8402
|
targetFilePath = targetFilePath.slice(2);
|
|
8363
|
-
let src = targetFilePath.startsWith("/") ? targetFilePath :
|
|
8364
|
-
if (!
|
|
8403
|
+
let src = targetFilePath.startsWith("/") ? targetFilePath : join(projectRoot, targetFilePath);
|
|
8404
|
+
if (!fs.existsSync(src))
|
|
8365
8405
|
throw new Error(
|
|
8366
8406
|
`Couldn't find "${targetFilePath}" from ${projectRoot}`
|
|
8367
8407
|
);
|
|
8368
8408
|
let targetFile;
|
|
8409
|
+
if (!tmpRoot) {
|
|
8410
|
+
const os = process.getBuiltinModule("os");
|
|
8411
|
+
tmpRoot = join(
|
|
8412
|
+
os && typeof os.tmpdir === "function" ? os.tmpdir() : projectRoot,
|
|
8413
|
+
".ElysiaAutoOpenAPI"
|
|
8414
|
+
);
|
|
8415
|
+
}
|
|
8369
8416
|
if (targetFilePath.endsWith(".d.ts")) targetFile = targetFilePath;
|
|
8370
8417
|
else {
|
|
8371
|
-
if (
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
const tsconfig = tsconfigPath.startsWith("/") ? tsconfigPath :
|
|
8375
|
-
let extendsRef =
|
|
8376
|
-
let distDir =
|
|
8418
|
+
if (fs.existsSync(tmpRoot))
|
|
8419
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
8420
|
+
fs.mkdirSync(tmpRoot, { recursive: true });
|
|
8421
|
+
const tsconfig = tsconfigPath.startsWith("/") ? tsconfigPath : join(projectRoot, tsconfigPath);
|
|
8422
|
+
let extendsRef = fs.existsSync(tsconfig) ? `"extends": "${join(projectRoot, "tsconfig.json")}",` : "";
|
|
8423
|
+
let distDir = join(tmpRoot, "dist");
|
|
8377
8424
|
if (typeof process !== "undefined" && process.platform === "win32") {
|
|
8378
8425
|
extendsRef = extendsRef.replace(/\\/g, "/");
|
|
8379
8426
|
src = src.replace(/\\/g, "/");
|
|
8380
8427
|
distDir = distDir.replace(/\\/g, "/");
|
|
8381
8428
|
}
|
|
8382
|
-
|
|
8383
|
-
|
|
8429
|
+
fs.writeFileSync(
|
|
8430
|
+
join(tmpRoot, "tsconfig.json"),
|
|
8384
8431
|
`{
|
|
8385
8432
|
${extendsRef}
|
|
8386
8433
|
"compilerOptions": ${compilerOptions ? JSON.stringify(compilerOptions) : `{
|
|
@@ -8397,36 +8444,46 @@ var fromTypes = (targetFilePath, {
|
|
|
8397
8444
|
"include": ["${src}"]
|
|
8398
8445
|
}`
|
|
8399
8446
|
);
|
|
8400
|
-
|
|
8447
|
+
const child_process = process.getBuiltinModule("child_process");
|
|
8448
|
+
if (!child_process)
|
|
8449
|
+
throw new Error(
|
|
8450
|
+
"[@elysiajs/openapi/gen] `fromTypes` declaration generation require `child_process` module which is not available in this environment"
|
|
8451
|
+
);
|
|
8452
|
+
const { spawnSync } = child_process;
|
|
8453
|
+
if (typeof spawnSync !== "function")
|
|
8454
|
+
throw new Error(
|
|
8455
|
+
"[@elysiajs/openapi/gen] `fromTypes` declaration generation require child_process.spawnSync which is not available in this environment"
|
|
8456
|
+
);
|
|
8457
|
+
spawnSync(`tsc`, {
|
|
8401
8458
|
shell: true,
|
|
8402
8459
|
cwd: tmpRoot,
|
|
8403
8460
|
stdio: silent ? void 0 : "inherit"
|
|
8404
8461
|
});
|
|
8405
8462
|
const fileName = targetFilePath.replace(/.tsx$/, ".ts").replace(/.ts$/, ".d.ts");
|
|
8406
|
-
targetFile = (overrideOutputPath ? typeof overrideOutputPath === "string" ? overrideOutputPath.startsWith("/") ? overrideOutputPath :
|
|
8463
|
+
targetFile = (overrideOutputPath ? typeof overrideOutputPath === "string" ? overrideOutputPath.startsWith("/") ? overrideOutputPath : join(tmpRoot, "dist", overrideOutputPath) : overrideOutputPath(tmpRoot) : void 0) ?? join(
|
|
8407
8464
|
tmpRoot,
|
|
8408
8465
|
"dist",
|
|
8409
8466
|
// remove leading like src or something similar
|
|
8410
8467
|
fileName.slice(fileName.indexOf("/") + 1)
|
|
8411
8468
|
);
|
|
8412
|
-
let existed =
|
|
8469
|
+
let existed = fs.existsSync(targetFile);
|
|
8413
8470
|
if (!existed && !overrideOutputPath) {
|
|
8414
|
-
targetFile =
|
|
8471
|
+
targetFile = join(
|
|
8415
8472
|
tmpRoot,
|
|
8416
8473
|
"dist",
|
|
8417
8474
|
// use original file name as-is eg. in monorepo
|
|
8418
8475
|
fileName
|
|
8419
8476
|
);
|
|
8420
|
-
existed =
|
|
8477
|
+
existed = fs.existsSync(targetFile);
|
|
8421
8478
|
}
|
|
8422
8479
|
if (!existed) {
|
|
8423
|
-
|
|
8480
|
+
fs.rmSync(join(tmpRoot, "tsconfig.json"));
|
|
8424
8481
|
console.warn(
|
|
8425
8482
|
"[@elysiajs/openapi/gen] Failed to generate OpenAPI schema"
|
|
8426
8483
|
);
|
|
8427
8484
|
console.warn("Couldn't find generated declaration file");
|
|
8428
|
-
if (
|
|
8429
|
-
const tempFiles =
|
|
8485
|
+
if (fs.existsSync(join(tmpRoot, "dist"))) {
|
|
8486
|
+
const tempFiles = fs.readdirSync(join(tmpRoot, "dist"), {
|
|
8430
8487
|
recursive: true
|
|
8431
8488
|
}).filter((x) => x.toString().endsWith(".d.ts")).map((x) => `- ${x}`).join("\n");
|
|
8432
8489
|
if (tempFiles) {
|
|
@@ -8438,15 +8495,15 @@ var fromTypes = (targetFilePath, {
|
|
|
8438
8495
|
} else {
|
|
8439
8496
|
console.warn(
|
|
8440
8497
|
"reason: root folder doesn't exists",
|
|
8441
|
-
|
|
8498
|
+
join(tmpRoot, "dist")
|
|
8442
8499
|
);
|
|
8443
8500
|
}
|
|
8444
8501
|
return;
|
|
8445
8502
|
}
|
|
8446
8503
|
}
|
|
8447
|
-
const declaration =
|
|
8448
|
-
if (!debug &&
|
|
8449
|
-
|
|
8504
|
+
const declaration = fs.readFileSync(targetFile, "utf8");
|
|
8505
|
+
if (!debug && fs.existsSync(tmpRoot))
|
|
8506
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
8450
8507
|
let instance = declaration.match(
|
|
8451
8508
|
instanceName ? new RegExp(`${instanceName}: Elysia<(.*)`, "gs") : matchRoute
|
|
8452
8509
|
)?.[0];
|
|
@@ -8459,34 +8516,7 @@ var fromTypes = (targetFilePath, {
|
|
|
8459
8516
|
3
|
|
8460
8517
|
)
|
|
8461
8518
|
);
|
|
8462
|
-
|
|
8463
|
-
for (const route of extractRootObjects(
|
|
8464
|
-
instance.slice(2).replace(matchStatus, '"$1":')
|
|
8465
|
-
)) {
|
|
8466
|
-
let schema = TypeBox(route.replaceAll(/readonly/g, ""));
|
|
8467
|
-
if (schema.type !== "object") continue;
|
|
8468
|
-
const paths = [];
|
|
8469
|
-
while (true) {
|
|
8470
|
-
const keys = Object.keys(schema.properties);
|
|
8471
|
-
if (keys.length !== 1) break;
|
|
8472
|
-
paths.push(keys[0]);
|
|
8473
|
-
schema = schema.properties[keys[0]];
|
|
8474
|
-
if (!schema?.properties) break;
|
|
8475
|
-
}
|
|
8476
|
-
const method = paths.pop();
|
|
8477
|
-
if (!method) continue;
|
|
8478
|
-
const path = "/" + paths.join("/");
|
|
8479
|
-
schema = schema.properties;
|
|
8480
|
-
if (schema?.response?.type === "object") {
|
|
8481
|
-
const responseSchema = {};
|
|
8482
|
-
for (const key in schema.response.properties)
|
|
8483
|
-
responseSchema[key] = schema.response.properties[key];
|
|
8484
|
-
schema.response = responseSchema;
|
|
8485
|
-
}
|
|
8486
|
-
if (!routes[path]) routes[path] = {};
|
|
8487
|
-
routes[path][method.toLowerCase()] = schema;
|
|
8488
|
-
}
|
|
8489
|
-
return routes;
|
|
8519
|
+
return declarationToJSONSchema(instance.slice(2));
|
|
8490
8520
|
} catch (error) {
|
|
8491
8521
|
console.warn(
|
|
8492
8522
|
"[@elysiajs/openapi/gen] Failed to generate OpenAPI schema"
|
|
@@ -8494,11 +8524,13 @@ var fromTypes = (targetFilePath, {
|
|
|
8494
8524
|
console.warn(error);
|
|
8495
8525
|
return;
|
|
8496
8526
|
} finally {
|
|
8497
|
-
if (!debug &&
|
|
8498
|
-
|
|
8527
|
+
if (!debug && tmpRoot && fs.existsSync(tmpRoot))
|
|
8528
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
8499
8529
|
}
|
|
8500
8530
|
};
|
|
8501
8531
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8502
8532
|
0 && (module.exports = {
|
|
8533
|
+
declarationToJSONSchema,
|
|
8534
|
+
extractRootObjects,
|
|
8503
8535
|
fromTypes
|
|
8504
8536
|
});
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ElysiaOpenAPIConfig } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* @see https://github.com/elysiajs/elysia-swagger
|
|
7
7
|
*/
|
|
8
|
-
export declare const openapi: <const Enabled extends boolean = true, const Path extends string = "/openapi">({ enabled, path, provider, specPath, documentation, exclude, swagger, scalar, references, mapJsonSchema }?: ElysiaOpenAPIConfig<Enabled, Path>) => Elysia<"", {
|
|
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, embedSpec }?: ElysiaOpenAPIConfig<Enabled, Path>) => Elysia<"", {
|
|
9
9
|
decorator: {};
|
|
10
10
|
store: {};
|
|
11
11
|
derive: {};
|
|
@@ -33,6 +33,7 @@ export declare const openapi: <const Enabled extends boolean = true, const Path
|
|
|
33
33
|
standaloneSchema: {};
|
|
34
34
|
response: {};
|
|
35
35
|
}>;
|
|
36
|
+
export { fromTypes } from './gen';
|
|
36
37
|
export { toOpenAPISchema, withHeaders } from './openapi';
|
|
37
38
|
export type { ElysiaOpenAPIConfig };
|
|
38
39
|
export default openapi;
|