@lark-apaas/devtool-kits 1.2.20 → 1.2.21

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/dist/index.d.cts CHANGED
@@ -166,6 +166,8 @@ type Middleware = RouteMiddleware | GlobalMiddleware;
166
166
  interface OpenapiMiddlewareOptions {
167
167
  /** Path to the openapi.json file */
168
168
  openapiFilePath: string;
169
+ /** Path to the OpenAPI spec source file (when set, serves /openapi/spec with /openapi/* filtered and $refs resolved) */
170
+ openapiSpecFilePath?: string;
169
171
  /** Enable source code enhancement */
170
172
  enableEnhancement?: boolean;
171
173
  /** Server directory for source code scanning (defaults to context.rootDir) */
package/dist/index.d.ts CHANGED
@@ -166,6 +166,8 @@ type Middleware = RouteMiddleware | GlobalMiddleware;
166
166
  interface OpenapiMiddlewareOptions {
167
167
  /** Path to the openapi.json file */
168
168
  openapiFilePath: string;
169
+ /** Path to the OpenAPI spec source file (when set, serves /openapi/spec with /openapi/* filtered and $refs resolved) */
170
+ openapiSpecFilePath?: string;
169
171
  /** Enable source code enhancement */
170
172
  enableEnhancement?: boolean;
171
173
  /** Server directory for source code scanning (defaults to context.rootDir) */
package/dist/index.js CHANGED
@@ -1388,12 +1388,135 @@ function createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir) {
1388
1388
  }
1389
1389
  __name(createOpenapiHandler, "createOpenapiHandler");
1390
1390
 
1391
+ // src/middlewares/openapi/spec-controller.ts
1392
+ import fs4 from "fs/promises";
1393
+ import crypto2 from "crypto";
1394
+ var MAX_REF_DEPTH = 5;
1395
+ function createOpenapiSpecHandler(openapiSpecFilePath) {
1396
+ let cache = null;
1397
+ return async (_req, res, context) => {
1398
+ try {
1399
+ const fileBuffer = await fs4.readFile(openapiSpecFilePath, "utf-8");
1400
+ const currentHash = crypto2.createHash("md5").update(fileBuffer).digest("hex");
1401
+ if (cache && cache.fileHash === currentHash) {
1402
+ return res.json(cache.data);
1403
+ }
1404
+ let parsed;
1405
+ try {
1406
+ parsed = JSON.parse(fileBuffer);
1407
+ } catch (err) {
1408
+ const message = err instanceof Error ? err.message : "Invalid JSON";
1409
+ return res.status(500).json({
1410
+ error: "Failed to load OpenAPI spec",
1411
+ message: `${openapiSpecFilePath} invalid: ${message}`
1412
+ });
1413
+ }
1414
+ if (!parsed || typeof parsed !== "object" || !parsed.paths || typeof parsed.paths !== "object") {
1415
+ return res.status(500).json({
1416
+ error: "Failed to load OpenAPI spec",
1417
+ message: `${openapiSpecFilePath} missing "paths"`
1418
+ });
1419
+ }
1420
+ const result = buildFilteredSpec(parsed, context.basePath ?? "");
1421
+ cache = {
1422
+ data: result,
1423
+ fileHash: currentHash
1424
+ };
1425
+ res.json(result);
1426
+ } catch (error) {
1427
+ const message = error instanceof Error ? error.message : "Unknown error";
1428
+ res.status(500).json({
1429
+ error: "Failed to load OpenAPI spec",
1430
+ message
1431
+ });
1432
+ }
1433
+ };
1434
+ }
1435
+ __name(createOpenapiSpecHandler, "createOpenapiSpecHandler");
1436
+ function buildFilteredSpec(spec, globalPrefix) {
1437
+ const schemas = spec.components?.schemas ?? {};
1438
+ const paths = spec.paths ?? {};
1439
+ const filteredPaths = {};
1440
+ const cleanPrefix = globalPrefix.replace(/\/+$/, "");
1441
+ for (const [pathKey, methods] of Object.entries(paths)) {
1442
+ const cleanPath = stripPrefix(pathKey, cleanPrefix);
1443
+ if (!cleanPath.startsWith("/openapi")) continue;
1444
+ filteredPaths[cleanPath] = {};
1445
+ for (const [method, operation] of Object.entries(methods)) {
1446
+ if ([
1447
+ "parameters",
1448
+ "summary",
1449
+ "description",
1450
+ "servers"
1451
+ ].includes(method)) continue;
1452
+ filteredPaths[cleanPath][method] = resolveRefsDeep(structuredClone(operation), schemas);
1453
+ }
1454
+ }
1455
+ return {
1456
+ openapi: spec.openapi ?? "3.0.0",
1457
+ paths: filteredPaths,
1458
+ components: {
1459
+ schemas: resolveAllSchemaRefs(structuredClone(schemas))
1460
+ }
1461
+ };
1462
+ }
1463
+ __name(buildFilteredSpec, "buildFilteredSpec");
1464
+ function stripPrefix(pathStr, prefix) {
1465
+ if (prefix && pathStr.startsWith(prefix)) {
1466
+ return pathStr.slice(prefix.length);
1467
+ }
1468
+ return pathStr;
1469
+ }
1470
+ __name(stripPrefix, "stripPrefix");
1471
+ function resolveRefsDeep(obj, schemas, depth = 0) {
1472
+ if (depth > MAX_REF_DEPTH || obj === null || obj === void 0) return obj;
1473
+ if (typeof obj !== "object") return obj;
1474
+ if (Array.isArray(obj)) {
1475
+ return obj.map((item) => resolveRefsDeep(item, schemas, depth));
1476
+ }
1477
+ const record = obj;
1478
+ if (typeof record["$ref"] === "string") {
1479
+ const resolved = resolveRef(record["$ref"], schemas);
1480
+ if (resolved !== void 0) {
1481
+ return resolveRefsDeep(structuredClone(resolved), schemas, depth + 1);
1482
+ }
1483
+ return record;
1484
+ }
1485
+ const result = {};
1486
+ for (const [key, value] of Object.entries(record)) {
1487
+ result[key] = resolveRefsDeep(value, schemas, depth);
1488
+ }
1489
+ return result;
1490
+ }
1491
+ __name(resolveRefsDeep, "resolveRefsDeep");
1492
+ function resolveRef(ref, schemas) {
1493
+ const prefix = "#/components/schemas/";
1494
+ if (ref.startsWith(prefix)) {
1495
+ const name = ref.slice(prefix.length);
1496
+ return schemas[name];
1497
+ }
1498
+ return void 0;
1499
+ }
1500
+ __name(resolveRef, "resolveRef");
1501
+ function resolveAllSchemaRefs(schemas) {
1502
+ const result = {};
1503
+ for (const [name, schema] of Object.entries(schemas)) {
1504
+ result[name] = resolveRefsDeep(schema, schemas);
1505
+ }
1506
+ return result;
1507
+ }
1508
+ __name(resolveAllSchemaRefs, "resolveAllSchemaRefs");
1509
+
1391
1510
  // src/middlewares/openapi/router.ts
1392
1511
  function createOpenapiRouter(options, context) {
1393
- const { openapiFilePath, enableEnhancement, serverDir } = options;
1512
+ const { openapiFilePath, openapiSpecFilePath, enableEnhancement, serverDir } = options;
1394
1513
  const router = express.Router();
1395
1514
  const handler = createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir);
1396
1515
  router.get("/openapi.json", (req, res) => handler(req, res, context));
1516
+ if (openapiSpecFilePath) {
1517
+ const specHandler = createOpenapiSpecHandler(openapiSpecFilePath);
1518
+ router.get("/openapi/spec", (req, res) => specHandler(req, res, context));
1519
+ }
1397
1520
  return router;
1398
1521
  }
1399
1522
  __name(createOpenapiRouter, "createOpenapiRouter");
@@ -1404,18 +1527,25 @@ var OPENAPI_ROUTES = [
1404
1527
  method: "GET",
1405
1528
  path: "/openapi.json",
1406
1529
  description: "Serve enhanced OpenAPI specification with source code references"
1530
+ },
1531
+ {
1532
+ method: "GET",
1533
+ path: "/openapi/spec",
1534
+ description: "Serve OpenAPI specification for /openapi/*"
1407
1535
  }
1408
1536
  ];
1409
1537
  function createOpenapiMiddleware(options) {
1410
- const { openapiFilePath, enableEnhancement = true, serverDir } = options;
1538
+ const { openapiFilePath, openapiSpecFilePath, enableEnhancement = true, serverDir } = options;
1539
+ const routes = openapiSpecFilePath ? OPENAPI_ROUTES : OPENAPI_ROUTES.filter((route) => route.path !== "/openapi/spec");
1411
1540
  return {
1412
1541
  name: "openapi",
1413
1542
  mountPath: "/dev",
1414
- routes: OPENAPI_ROUTES,
1543
+ routes,
1415
1544
  enabled: /* @__PURE__ */ __name((context) => context.isDev, "enabled"),
1416
1545
  createRouter: /* @__PURE__ */ __name((context) => {
1417
1546
  return createOpenapiRouter({
1418
1547
  openapiFilePath,
1548
+ openapiSpecFilePath,
1419
1549
  enableEnhancement,
1420
1550
  serverDir
1421
1551
  }, context);
@@ -1428,7 +1558,7 @@ __name(createOpenapiMiddleware, "createOpenapiMiddleware");
1428
1558
  import express2 from "express";
1429
1559
 
1430
1560
  // src/middlewares/dev-logs/utils.ts
1431
- import { promises as fs4 } from "fs";
1561
+ import { promises as fs5 } from "fs";
1432
1562
  import { isAbsolute, join as join2, relative } from "path";
1433
1563
 
1434
1564
  // src/middlewares/dev-logs/helper/path-matcher.ts
@@ -1480,7 +1610,7 @@ function getRelativePath(filePath) {
1480
1610
  __name(getRelativePath, "getRelativePath");
1481
1611
  async function fileExists(filePath) {
1482
1612
  try {
1483
- await fs4.access(filePath);
1613
+ await fs5.access(filePath);
1484
1614
  return true;
1485
1615
  } catch {
1486
1616
  return false;
@@ -1563,9 +1693,9 @@ __name(serializeError, "serializeError");
1563
1693
  import { join as join4 } from "path";
1564
1694
 
1565
1695
  // src/middlewares/dev-logs/services/file-reader.ts
1566
- import { promises as fs5 } from "fs";
1696
+ import { promises as fs6 } from "fs";
1567
1697
  async function readFileReverse(filePath, chunkSize, processLine) {
1568
- const handle = await fs5.open(filePath, "r");
1698
+ const handle = await fs6.open(filePath, "r");
1569
1699
  try {
1570
1700
  const stats = await handle.stat();
1571
1701
  let position = stats.size;
@@ -1810,8 +1940,8 @@ async function readRecentTraceCalls(filePath, page, pageSize, pathFilter, method
1810
1940
  const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
1811
1941
  builder.hasCompleted = true;
1812
1942
  builder.endTime = entry.time;
1813
- builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
1814
- builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
1943
+ builder.statusCode = typeof entry.status_code === "number" ? entry.status_code : extractNumber(message, /status_code:\s*(\d+)/);
1944
+ builder.durationMs = typeof entry.duration_ms === "number" ? entry.duration_ms : extractNumber(message, /duration_ms:\s*(\d+)/);
1815
1945
  if (!builder.path && entry.path) {
1816
1946
  builder.path = String(entry.path);
1817
1947
  }
@@ -2527,7 +2657,7 @@ function createHealthCheckHandler(options = {}) {
2527
2657
  __name(createHealthCheckHandler, "createHealthCheckHandler");
2528
2658
 
2529
2659
  // src/middlewares/dev-logs/sse/log-watcher.ts
2530
- import * as fs6 from "fs";
2660
+ import * as fs7 from "fs";
2531
2661
  import * as path3 from "path";
2532
2662
  function mapPinoLevelToServerLogLevel2(pinoLevel) {
2533
2663
  if (typeof pinoLevel === "string") {
@@ -2746,12 +2876,12 @@ var LogWatcher = class {
2746
2876
  */
2747
2877
  watchFile(config) {
2748
2878
  const filePath = path3.join(this.logDir, config.fileName);
2749
- if (!fs6.existsSync(filePath)) {
2879
+ if (!fs7.existsSync(filePath)) {
2750
2880
  this.log(`File not found, skipping: ${config.fileName}`);
2751
2881
  return;
2752
2882
  }
2753
2883
  try {
2754
- const stats = fs6.statSync(filePath);
2884
+ const stats = fs7.statSync(filePath);
2755
2885
  this.filePositions.set(config.fileName, stats.size);
2756
2886
  this.log(`Initialized position for ${config.fileName}: ${stats.size} bytes`);
2757
2887
  } catch (error) {
@@ -2759,7 +2889,7 @@ var LogWatcher = class {
2759
2889
  this.filePositions.set(config.fileName, 0);
2760
2890
  }
2761
2891
  try {
2762
- const watcher = fs6.watch(filePath, (eventType) => {
2892
+ const watcher = fs7.watch(filePath, (eventType) => {
2763
2893
  if (eventType === "change") {
2764
2894
  this.handleFileChange(config);
2765
2895
  }
@@ -2797,7 +2927,7 @@ var LogWatcher = class {
2797
2927
  const filePath = path3.join(this.logDir, config.fileName);
2798
2928
  const lastPosition = this.filePositions.get(config.fileName) || 0;
2799
2929
  try {
2800
- const stats = fs6.statSync(filePath);
2930
+ const stats = fs7.statSync(filePath);
2801
2931
  const currentSize = stats.size;
2802
2932
  if (currentSize < lastPosition) {
2803
2933
  this.log(`File ${config.fileName} was truncated, resetting position`);
@@ -2810,11 +2940,11 @@ var LogWatcher = class {
2810
2940
  }
2811
2941
  const readSize = currentSize - lastPosition;
2812
2942
  const buffer = Buffer.alloc(readSize);
2813
- const fd = fs6.openSync(filePath, "r");
2943
+ const fd = fs7.openSync(filePath, "r");
2814
2944
  try {
2815
- fs6.readSync(fd, buffer, 0, readSize, lastPosition);
2945
+ fs7.readSync(fd, buffer, 0, readSize, lastPosition);
2816
2946
  } finally {
2817
- fs6.closeSync(fd);
2947
+ fs7.closeSync(fd);
2818
2948
  }
2819
2949
  this.filePositions.set(config.fileName, currentSize);
2820
2950
  const content = buffer.toString("utf8");
@@ -3220,11 +3350,11 @@ import express3 from "express";
3220
3350
 
3221
3351
  // src/middlewares/collect-logs/controller.ts
3222
3352
  import { join as join7 } from "path";
3223
- import fs8 from "fs";
3353
+ import fs9 from "fs";
3224
3354
 
3225
3355
  // src/middlewares/collect-logs/utils.ts
3226
3356
  import { isAbsolute as isAbsolute2, join as join6 } from "path";
3227
- import fs7 from "fs";
3357
+ import fs8 from "fs";
3228
3358
  function resolveLogDir2(provided) {
3229
3359
  if (!provided) {
3230
3360
  return join6(process.cwd(), "logs");
@@ -3233,8 +3363,8 @@ function resolveLogDir2(provided) {
3233
3363
  }
3234
3364
  __name(resolveLogDir2, "resolveLogDir");
3235
3365
  function ensureDir(dir) {
3236
- if (!fs7.existsSync(dir)) {
3237
- fs7.mkdirSync(dir, {
3366
+ if (!fs8.existsSync(dir)) {
3367
+ fs8.mkdirSync(dir, {
3238
3368
  recursive: true
3239
3369
  });
3240
3370
  }
@@ -3266,7 +3396,7 @@ function collectLogsHandler(logDir, fileName) {
3266
3396
  ...logContent,
3267
3397
  server_time: (/* @__PURE__ */ new Date()).toISOString()
3268
3398
  }) + "\n";
3269
- await fs8.promises.appendFile(filePath, logLine);
3399
+ await fs9.promises.appendFile(filePath, logLine);
3270
3400
  res.json({
3271
3401
  success: true
3272
3402
  });
@@ -3294,7 +3424,7 @@ function collectLogsBatchHandler(logDir, fileName) {
3294
3424
  server_time: (/* @__PURE__ */ new Date()).toISOString()
3295
3425
  }) + "\n");
3296
3426
  }
3297
- await fs8.promises.appendFile(filePath, logLines.join(""));
3427
+ await fs9.promises.appendFile(filePath, logLines.join(""));
3298
3428
  res.json({
3299
3429
  success: true
3300
3430
  });