@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 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/openapi-api/openapi-ui)
86
+ - [SwaggerUI](https://github.com/swagger-api/swagger-ui)
87
87
  - null: disable frontend
88
88
 
89
89
  ## references
@@ -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 matchStatus = /(\d{3}):/g;
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
- var fromTypes = (targetFilePath, {
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 = (0, import_path2.join)((0, import_os.tmpdir)(), ".ElysiaAutoOpenAPI"),
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 : (0, import_path2.join)(projectRoot, targetFilePath);
8364
- if (!(0, import_fs.existsSync)(src))
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 ((0, import_fs.existsSync)(tmpRoot))
8372
- (0, import_fs.rmSync)(tmpRoot, { recursive: true, force: true });
8373
- (0, import_fs.mkdirSync)(tmpRoot, { recursive: true });
8374
- const tsconfig = tsconfigPath.startsWith("/") ? tsconfigPath : (0, import_path2.join)(projectRoot, tsconfigPath);
8375
- let extendsRef = (0, import_fs.existsSync)(tsconfig) ? `"extends": "${(0, import_path2.join)(projectRoot, "tsconfig.json")}",` : "";
8376
- let distDir = (0, import_path2.join)(tmpRoot, "dist");
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
- (0, import_fs.writeFileSync)(
8383
- (0, import_path2.join)(tmpRoot, "tsconfig.json"),
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
- (0, import_child_process.spawnSync)(`tsc`, {
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 : (0, import_path2.join)(tmpRoot, "dist", overrideOutputPath) : overrideOutputPath(tmpRoot) : void 0) ?? (0, import_path2.join)(
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 = (0, import_fs.existsSync)(targetFile);
8469
+ let existed = fs.existsSync(targetFile);
8413
8470
  if (!existed && !overrideOutputPath) {
8414
- targetFile = (0, import_path2.join)(
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 = (0, import_fs.existsSync)(targetFile);
8477
+ existed = fs.existsSync(targetFile);
8421
8478
  }
8422
8479
  if (!existed) {
8423
- (0, import_fs.rmSync)((0, import_path2.join)(tmpRoot, "tsconfig.json"));
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 ((0, import_fs.existsSync)((0, import_path2.join)(tmpRoot, "dist"))) {
8429
- const tempFiles = (0, import_fs.readdirSync)((0, import_path2.join)(tmpRoot, "dist"), {
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
- (0, import_path2.join)(tmpRoot, "dist")
8498
+ join(tmpRoot, "dist")
8442
8499
  );
8443
8500
  }
8444
8501
  return;
8445
8502
  }
8446
8503
  }
8447
- const declaration = (0, import_fs.readFileSync)(targetFile, "utf8");
8448
- if (!debug && (0, import_fs.existsSync)(tmpRoot))
8449
- (0, import_fs.rmSync)(tmpRoot, { recursive: true, force: true });
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
- const routes = {};
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 && (0, import_fs.existsSync)(tmpRoot))
8498
- (0, import_fs.rmSync)(tmpRoot, { recursive: true, force: true });
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
  });
@@ -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;