@lark-apaas/devtool-kits 1.2.19 → 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.cjs CHANGED
@@ -31,16 +31,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ buildFullPath: () => buildFullPath,
35
+ calculateFileHash: () => calculateFileHash,
34
36
  createCollectLogsMiddleware: () => createCollectLogsMiddleware,
35
37
  createDevLogsMiddleware: () => createDevLogsMiddleware,
36
38
  createOpenapiMiddleware: () => createOpenapiMiddleware,
39
+ evaluateTemplateLiteral: () => evaluateTemplateLiteral,
40
+ extractPageRouteInfo: () => extractPageRouteInfo,
37
41
  getQuery: () => getQuery,
38
42
  getQueryParam: () => getQueryParam,
39
43
  handleDevProxyError: () => handleDevProxyError,
44
+ isRouteComponent: () => isRouteComponent,
40
45
  normalizeBasePath: () => normalizeBasePath,
41
46
  parseAndGenerateNestResourceTemplate: () => parseAndGenerateNestResourceTemplate,
47
+ parseApiRoutes: () => parseApiRoutes,
48
+ parseRoutesFromFile: () => parseRoutesFromFile,
42
49
  postprocessDrizzleSchema: () => postprocessDrizzleSchema,
43
50
  registerMiddlewares: () => registerMiddlewares,
51
+ routeParserLog: () => routeParserLog,
44
52
  sendError: () => sendError,
45
53
  sendJson: () => sendJson,
46
54
  sendSuccess: () => sendSuccess
@@ -1281,7 +1289,7 @@ function isConnectionError(err) {
1281
1289
  }
1282
1290
  __name(isConnectionError, "isConnectionError");
1283
1291
  function checkServiceAvailable(targetUrl, timeout = 2e3) {
1284
- return new Promise((resolve) => {
1292
+ return new Promise((resolve2) => {
1285
1293
  try {
1286
1294
  const url = new URL(targetUrl);
1287
1295
  const isHttps = url.protocol === "https:";
@@ -1293,18 +1301,18 @@ function checkServiceAvailable(targetUrl, timeout = 2e3) {
1293
1301
  method: "HEAD",
1294
1302
  timeout
1295
1303
  }, (res) => {
1296
- resolve(res.statusCode !== 502);
1304
+ resolve2(res.statusCode !== 502);
1297
1305
  });
1298
1306
  req.on("timeout", () => {
1299
1307
  req.destroy();
1300
- resolve(false);
1308
+ resolve2(false);
1301
1309
  });
1302
1310
  req.on("error", () => {
1303
- resolve(false);
1311
+ resolve2(false);
1304
1312
  });
1305
1313
  req.end();
1306
1314
  } catch {
1307
- resolve(false);
1315
+ resolve2(false);
1308
1316
  }
1309
1317
  });
1310
1318
  }
@@ -1316,7 +1324,7 @@ async function waitForServiceRecovery(targetUrl, timeout, interval) {
1316
1324
  if (isAvailable) {
1317
1325
  return true;
1318
1326
  }
1319
- await new Promise((resolve) => setTimeout(resolve, interval));
1327
+ await new Promise((resolve2) => setTimeout(resolve2, interval));
1320
1328
  }
1321
1329
  return false;
1322
1330
  }
@@ -1386,6 +1394,7 @@ var import_node_crypto = __toESM(require("crypto"), 1);
1386
1394
 
1387
1395
  // src/middlewares/openapi/services.ts
1388
1396
  var import_node_fs4 = require("fs");
1397
+ var fsSync = __toESM(require("fs"), 1);
1389
1398
  var import_node_path4 = __toESM(require("path"), 1);
1390
1399
  var import_typescript = __toESM(require("typescript"), 1);
1391
1400
 
@@ -1608,6 +1617,120 @@ function extractControllerMetadata(sourceFile, filePath) {
1608
1617
  return metadata;
1609
1618
  }
1610
1619
  __name(extractControllerMetadata, "extractControllerMetadata");
1620
+ var HTTP_DECORATOR_NAMES = [
1621
+ "Get",
1622
+ "Post",
1623
+ "Put",
1624
+ "Delete",
1625
+ "Patch",
1626
+ "Options",
1627
+ "Head",
1628
+ "All"
1629
+ ];
1630
+ function findControllerFilesSync(dir) {
1631
+ const files = [];
1632
+ function scan(currentDir) {
1633
+ let entries;
1634
+ try {
1635
+ entries = fsSync.readdirSync(currentDir, {
1636
+ withFileTypes: true
1637
+ });
1638
+ } catch {
1639
+ return;
1640
+ }
1641
+ for (const entry of entries) {
1642
+ const fullPath = import_node_path4.default.join(currentDir, entry.name);
1643
+ if (entry.isDirectory()) {
1644
+ scan(fullPath);
1645
+ } else if (entry.isFile() && entry.name.endsWith(".controller.ts")) {
1646
+ files.push(fullPath);
1647
+ }
1648
+ }
1649
+ }
1650
+ __name(scan, "scan");
1651
+ scan(dir);
1652
+ return files;
1653
+ }
1654
+ __name(findControllerFilesSync, "findControllerFilesSync");
1655
+ function normalizeApiPath(controllerPath, routePath) {
1656
+ const combined = routePath ? `${controllerPath}/${routePath}` : controllerPath;
1657
+ let normalized = combined.replace(/\/+/g, "/");
1658
+ if (!normalized.startsWith("/")) normalized = `/${normalized}`;
1659
+ if (normalized.length > 1 && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
1660
+ return normalized;
1661
+ }
1662
+ __name(normalizeApiPath, "normalizeApiPath");
1663
+ function parseControllerRoutes(filePath) {
1664
+ let content;
1665
+ try {
1666
+ content = fsSync.readFileSync(filePath, "utf-8");
1667
+ } catch {
1668
+ return [];
1669
+ }
1670
+ const sourceFile = import_typescript.default.createSourceFile(filePath, content, import_typescript.default.ScriptTarget.Latest, true);
1671
+ const routes = [];
1672
+ function getDecoratorsCompat(node) {
1673
+ if ("modifiers" in node && Array.isArray(node.modifiers)) {
1674
+ return node.modifiers.filter((mod) => mod.kind === import_typescript.default.SyntaxKind.Decorator);
1675
+ }
1676
+ if ("decorators" in node && Array.isArray(node.decorators)) {
1677
+ return node.decorators;
1678
+ }
1679
+ return [];
1680
+ }
1681
+ __name(getDecoratorsCompat, "getDecoratorsCompat");
1682
+ function getStringArg(expr) {
1683
+ if (expr.arguments.length > 0 && import_typescript.default.isStringLiteral(expr.arguments[0])) {
1684
+ return expr.arguments[0].text;
1685
+ }
1686
+ return "";
1687
+ }
1688
+ __name(getStringArg, "getStringArg");
1689
+ function visit(node) {
1690
+ if (import_typescript.default.isClassDeclaration(node)) {
1691
+ let controllerPath = "";
1692
+ for (const dec of getDecoratorsCompat(node)) {
1693
+ if (import_typescript.default.isCallExpression(dec.expression)) {
1694
+ const name = dec.expression.expression.getText(sourceFile);
1695
+ if (name === "Controller") {
1696
+ controllerPath = getStringArg(dec.expression);
1697
+ break;
1698
+ }
1699
+ }
1700
+ }
1701
+ for (const member of node.members) {
1702
+ if (!import_typescript.default.isMethodDeclaration(member)) continue;
1703
+ for (const dec of getDecoratorsCompat(member)) {
1704
+ if (!import_typescript.default.isCallExpression(dec.expression)) continue;
1705
+ const decoratorName = dec.expression.expression.getText(sourceFile);
1706
+ if (!HTTP_DECORATOR_NAMES.includes(decoratorName)) continue;
1707
+ const routePath = getStringArg(dec.expression);
1708
+ const fullPath = normalizeApiPath(controllerPath, routePath);
1709
+ const method = decoratorName === "All" ? "*" : decoratorName.toUpperCase();
1710
+ routes.push({
1711
+ method,
1712
+ path: fullPath
1713
+ });
1714
+ }
1715
+ }
1716
+ }
1717
+ import_typescript.default.forEachChild(node, visit);
1718
+ }
1719
+ __name(visit, "visit");
1720
+ visit(sourceFile);
1721
+ return routes;
1722
+ }
1723
+ __name(parseControllerRoutes, "parseControllerRoutes");
1724
+ function parseApiRoutes(serverDir) {
1725
+ const resolvedDir = import_node_path4.default.resolve(serverDir);
1726
+ const controllerFiles = findControllerFilesSync(resolvedDir);
1727
+ const routes = [];
1728
+ for (const filePath of controllerFiles) {
1729
+ routes.push(...parseControllerRoutes(filePath));
1730
+ }
1731
+ return routes;
1732
+ }
1733
+ __name(parseApiRoutes, "parseApiRoutes");
1611
1734
 
1612
1735
  // src/middlewares/openapi/controller.ts
1613
1736
  function createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir) {
@@ -1646,12 +1769,135 @@ function createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir) {
1646
1769
  }
1647
1770
  __name(createOpenapiHandler, "createOpenapiHandler");
1648
1771
 
1772
+ // src/middlewares/openapi/spec-controller.ts
1773
+ var import_promises3 = __toESM(require("fs/promises"), 1);
1774
+ var import_node_crypto2 = __toESM(require("crypto"), 1);
1775
+ var MAX_REF_DEPTH = 5;
1776
+ function createOpenapiSpecHandler(openapiSpecFilePath) {
1777
+ let cache = null;
1778
+ return async (_req, res, context) => {
1779
+ try {
1780
+ const fileBuffer = await import_promises3.default.readFile(openapiSpecFilePath, "utf-8");
1781
+ const currentHash = import_node_crypto2.default.createHash("md5").update(fileBuffer).digest("hex");
1782
+ if (cache && cache.fileHash === currentHash) {
1783
+ return res.json(cache.data);
1784
+ }
1785
+ let parsed;
1786
+ try {
1787
+ parsed = JSON.parse(fileBuffer);
1788
+ } catch (err) {
1789
+ const message = err instanceof Error ? err.message : "Invalid JSON";
1790
+ return res.status(500).json({
1791
+ error: "Failed to load OpenAPI spec",
1792
+ message: `${openapiSpecFilePath} invalid: ${message}`
1793
+ });
1794
+ }
1795
+ if (!parsed || typeof parsed !== "object" || !parsed.paths || typeof parsed.paths !== "object") {
1796
+ return res.status(500).json({
1797
+ error: "Failed to load OpenAPI spec",
1798
+ message: `${openapiSpecFilePath} missing "paths"`
1799
+ });
1800
+ }
1801
+ const result = buildFilteredSpec(parsed, context.basePath ?? "");
1802
+ cache = {
1803
+ data: result,
1804
+ fileHash: currentHash
1805
+ };
1806
+ res.json(result);
1807
+ } catch (error) {
1808
+ const message = error instanceof Error ? error.message : "Unknown error";
1809
+ res.status(500).json({
1810
+ error: "Failed to load OpenAPI spec",
1811
+ message
1812
+ });
1813
+ }
1814
+ };
1815
+ }
1816
+ __name(createOpenapiSpecHandler, "createOpenapiSpecHandler");
1817
+ function buildFilteredSpec(spec, globalPrefix) {
1818
+ const schemas = spec.components?.schemas ?? {};
1819
+ const paths = spec.paths ?? {};
1820
+ const filteredPaths = {};
1821
+ const cleanPrefix = globalPrefix.replace(/\/+$/, "");
1822
+ for (const [pathKey, methods] of Object.entries(paths)) {
1823
+ const cleanPath = stripPrefix(pathKey, cleanPrefix);
1824
+ if (!cleanPath.startsWith("/openapi")) continue;
1825
+ filteredPaths[cleanPath] = {};
1826
+ for (const [method, operation] of Object.entries(methods)) {
1827
+ if ([
1828
+ "parameters",
1829
+ "summary",
1830
+ "description",
1831
+ "servers"
1832
+ ].includes(method)) continue;
1833
+ filteredPaths[cleanPath][method] = resolveRefsDeep(structuredClone(operation), schemas);
1834
+ }
1835
+ }
1836
+ return {
1837
+ openapi: spec.openapi ?? "3.0.0",
1838
+ paths: filteredPaths,
1839
+ components: {
1840
+ schemas: resolveAllSchemaRefs(structuredClone(schemas))
1841
+ }
1842
+ };
1843
+ }
1844
+ __name(buildFilteredSpec, "buildFilteredSpec");
1845
+ function stripPrefix(pathStr, prefix) {
1846
+ if (prefix && pathStr.startsWith(prefix)) {
1847
+ return pathStr.slice(prefix.length);
1848
+ }
1849
+ return pathStr;
1850
+ }
1851
+ __name(stripPrefix, "stripPrefix");
1852
+ function resolveRefsDeep(obj, schemas, depth = 0) {
1853
+ if (depth > MAX_REF_DEPTH || obj === null || obj === void 0) return obj;
1854
+ if (typeof obj !== "object") return obj;
1855
+ if (Array.isArray(obj)) {
1856
+ return obj.map((item) => resolveRefsDeep(item, schemas, depth));
1857
+ }
1858
+ const record = obj;
1859
+ if (typeof record["$ref"] === "string") {
1860
+ const resolved = resolveRef(record["$ref"], schemas);
1861
+ if (resolved !== void 0) {
1862
+ return resolveRefsDeep(structuredClone(resolved), schemas, depth + 1);
1863
+ }
1864
+ return record;
1865
+ }
1866
+ const result = {};
1867
+ for (const [key, value] of Object.entries(record)) {
1868
+ result[key] = resolveRefsDeep(value, schemas, depth);
1869
+ }
1870
+ return result;
1871
+ }
1872
+ __name(resolveRefsDeep, "resolveRefsDeep");
1873
+ function resolveRef(ref, schemas) {
1874
+ const prefix = "#/components/schemas/";
1875
+ if (ref.startsWith(prefix)) {
1876
+ const name = ref.slice(prefix.length);
1877
+ return schemas[name];
1878
+ }
1879
+ return void 0;
1880
+ }
1881
+ __name(resolveRef, "resolveRef");
1882
+ function resolveAllSchemaRefs(schemas) {
1883
+ const result = {};
1884
+ for (const [name, schema] of Object.entries(schemas)) {
1885
+ result[name] = resolveRefsDeep(schema, schemas);
1886
+ }
1887
+ return result;
1888
+ }
1889
+ __name(resolveAllSchemaRefs, "resolveAllSchemaRefs");
1890
+
1649
1891
  // src/middlewares/openapi/router.ts
1650
1892
  function createOpenapiRouter(options, context) {
1651
- const { openapiFilePath, enableEnhancement, serverDir } = options;
1893
+ const { openapiFilePath, openapiSpecFilePath, enableEnhancement, serverDir } = options;
1652
1894
  const router = import_express.default.Router();
1653
1895
  const handler = createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir);
1654
1896
  router.get("/openapi.json", (req, res) => handler(req, res, context));
1897
+ if (openapiSpecFilePath) {
1898
+ const specHandler = createOpenapiSpecHandler(openapiSpecFilePath);
1899
+ router.get("/openapi/spec", (req, res) => specHandler(req, res, context));
1900
+ }
1655
1901
  return router;
1656
1902
  }
1657
1903
  __name(createOpenapiRouter, "createOpenapiRouter");
@@ -1662,18 +1908,25 @@ var OPENAPI_ROUTES = [
1662
1908
  method: "GET",
1663
1909
  path: "/openapi.json",
1664
1910
  description: "Serve enhanced OpenAPI specification with source code references"
1911
+ },
1912
+ {
1913
+ method: "GET",
1914
+ path: "/openapi/spec",
1915
+ description: "Serve OpenAPI specification for /openapi/*"
1665
1916
  }
1666
1917
  ];
1667
1918
  function createOpenapiMiddleware(options) {
1668
- const { openapiFilePath, enableEnhancement = true, serverDir } = options;
1919
+ const { openapiFilePath, openapiSpecFilePath, enableEnhancement = true, serverDir } = options;
1920
+ const routes = openapiSpecFilePath ? OPENAPI_ROUTES : OPENAPI_ROUTES.filter((route) => route.path !== "/openapi/spec");
1669
1921
  return {
1670
1922
  name: "openapi",
1671
1923
  mountPath: "/dev",
1672
- routes: OPENAPI_ROUTES,
1924
+ routes,
1673
1925
  enabled: /* @__PURE__ */ __name((context) => context.isDev, "enabled"),
1674
1926
  createRouter: /* @__PURE__ */ __name((context) => {
1675
1927
  return createOpenapiRouter({
1676
1928
  openapiFilePath,
1929
+ openapiSpecFilePath,
1677
1930
  enableEnhancement,
1678
1931
  serverDir
1679
1932
  }, context);
@@ -1719,8 +1972,8 @@ function hasSpecialPatterns(pattern) {
1719
1972
  return /[{*]/.test(pattern);
1720
1973
  }
1721
1974
  __name(hasSpecialPatterns, "hasSpecialPatterns");
1722
- function normalizePathForMatching(path7) {
1723
- return path7.replace(/\/+/g, "/").replace(/\/+$/, "");
1975
+ function normalizePathForMatching(path8) {
1976
+ return path8.replace(/\/+/g, "/").replace(/\/+$/, "");
1724
1977
  }
1725
1978
  __name(normalizePathForMatching, "normalizePathForMatching");
1726
1979
 
@@ -2068,8 +2321,8 @@ async function readRecentTraceCalls(filePath, page, pageSize, pathFilter, method
2068
2321
  const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
2069
2322
  builder.hasCompleted = true;
2070
2323
  builder.endTime = entry.time;
2071
- builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
2072
- builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
2324
+ builder.statusCode = typeof entry.status_code === "number" ? entry.status_code : extractNumber(message, /status_code:\s*(\d+)/);
2325
+ builder.durationMs = typeof entry.duration_ms === "number" ? entry.duration_ms : extractNumber(message, /duration_ms:\s*(\d+)/);
2073
2326
  if (!builder.path && entry.path) {
2074
2327
  builder.path = String(entry.path);
2075
2328
  }
@@ -2269,7 +2522,7 @@ __name(readLogsBySource, "readLogsBySource");
2269
2522
  // src/middlewares/dev-logs/services/trigger.service.ts
2270
2523
  var import_node_fs9 = require("fs");
2271
2524
  var import_node_readline3 = require("readline");
2272
- async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2525
+ async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2273
2526
  if (!await fileExists(filePath)) {
2274
2527
  return void 0;
2275
2528
  }
@@ -2295,7 +2548,7 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2295
2548
  if (alreadyAdded) {
2296
2549
  return false;
2297
2550
  }
2298
- const isAutomationTrigger = builder.path?.endsWith(path7);
2551
+ const isAutomationTrigger = builder.path?.endsWith(path8);
2299
2552
  if (!isAutomationTrigger) {
2300
2553
  return false;
2301
2554
  }
@@ -2378,7 +2631,7 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2378
2631
  };
2379
2632
  }
2380
2633
  __name(readTriggerList, "readTriggerList");
2381
- async function readTriggerDetail(filePath, path7, instanceID) {
2634
+ async function readTriggerDetail(filePath, path8, instanceID) {
2382
2635
  const exists = await fileExists(filePath);
2383
2636
  if (!exists) {
2384
2637
  return void 0;
@@ -2394,7 +2647,7 @@ async function readTriggerDetail(filePath, path7, instanceID) {
2394
2647
  for await (const line of rl) {
2395
2648
  const entry = parseLogLine(line);
2396
2649
  if (!entry) continue;
2397
- const isAutomationTrigger = entry.path?.endsWith(path7);
2650
+ const isAutomationTrigger = entry.path?.endsWith(path8);
2398
2651
  const hasInstanceID = entry.instance_id === instanceID && entry.trigger;
2399
2652
  if (!isAutomationTrigger || !hasInstanceID) continue;
2400
2653
  matches.push(entry);
@@ -2648,16 +2901,16 @@ function createGetTriggerListHandler(logDir) {
2648
2901
  });
2649
2902
  }
2650
2903
  const triggerID = typeof req.query.triggerID === "string" ? req.query.triggerID.trim() : void 0;
2651
- const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2904
+ const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2652
2905
  const limit = parseLimit(req.query.limit, 10, 200);
2653
2906
  try {
2654
- const result = await readTriggerList(traceLogPath, trigger, path7, limit, triggerID);
2907
+ const result = await readTriggerList(traceLogPath, trigger, path8, limit, triggerID);
2655
2908
  if (!result) {
2656
2909
  return handleNotFound(res, traceLogPath);
2657
2910
  }
2658
2911
  res.json({
2659
2912
  file: getRelativePath(traceLogPath),
2660
- path: path7,
2913
+ path: path8,
2661
2914
  ...result
2662
2915
  });
2663
2916
  } catch (error) {
@@ -2675,9 +2928,9 @@ function createGetTriggerDetailHandler(logDir) {
2675
2928
  message: "instanceID is required"
2676
2929
  });
2677
2930
  }
2678
- const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2931
+ const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2679
2932
  try {
2680
- const result = await readTriggerDetail(traceLogPath, path7, instanceID);
2933
+ const result = await readTriggerDetail(traceLogPath, path8, instanceID);
2681
2934
  if (!result) {
2682
2935
  return handleNotFound(res, traceLogPath);
2683
2936
  }
@@ -2720,7 +2973,7 @@ __name(createGetCapabilityTraceListHandler, "createGetCapabilityTraceListHandler
2720
2973
  // src/middlewares/dev-logs/health.controller.ts
2721
2974
  var import_node_http = __toESM(require("http"), 1);
2722
2975
  function checkServiceHealth(host, port, timeout) {
2723
- return new Promise((resolve) => {
2976
+ return new Promise((resolve2) => {
2724
2977
  const startTime = Date.now();
2725
2978
  const req = import_node_http.default.request({
2726
2979
  hostname: host,
@@ -2730,20 +2983,20 @@ function checkServiceHealth(host, port, timeout) {
2730
2983
  timeout
2731
2984
  }, (_res) => {
2732
2985
  const responseTime = Date.now() - startTime;
2733
- resolve({
2986
+ resolve2({
2734
2987
  available: true,
2735
2988
  responseTime
2736
2989
  });
2737
2990
  });
2738
2991
  req.on("timeout", () => {
2739
2992
  req.destroy();
2740
- resolve({
2993
+ resolve2({
2741
2994
  available: false,
2742
2995
  error: "Request timeout"
2743
2996
  });
2744
2997
  });
2745
2998
  req.on("error", (err) => {
2746
- resolve({
2999
+ resolve2({
2747
3000
  available: false,
2748
3001
  error: err.message
2749
3002
  });
@@ -2785,7 +3038,7 @@ function createHealthCheckHandler(options = {}) {
2785
3038
  __name(createHealthCheckHandler, "createHealthCheckHandler");
2786
3039
 
2787
3040
  // src/middlewares/dev-logs/sse/log-watcher.ts
2788
- var fs8 = __toESM(require("fs"), 1);
3041
+ var fs9 = __toESM(require("fs"), 1);
2789
3042
  var path5 = __toESM(require("path"), 1);
2790
3043
  function mapPinoLevelToServerLogLevel2(pinoLevel) {
2791
3044
  if (typeof pinoLevel === "string") {
@@ -3004,12 +3257,12 @@ var LogWatcher = class {
3004
3257
  */
3005
3258
  watchFile(config) {
3006
3259
  const filePath = path5.join(this.logDir, config.fileName);
3007
- if (!fs8.existsSync(filePath)) {
3260
+ if (!fs9.existsSync(filePath)) {
3008
3261
  this.log(`File not found, skipping: ${config.fileName}`);
3009
3262
  return;
3010
3263
  }
3011
3264
  try {
3012
- const stats = fs8.statSync(filePath);
3265
+ const stats = fs9.statSync(filePath);
3013
3266
  this.filePositions.set(config.fileName, stats.size);
3014
3267
  this.log(`Initialized position for ${config.fileName}: ${stats.size} bytes`);
3015
3268
  } catch (error) {
@@ -3017,7 +3270,7 @@ var LogWatcher = class {
3017
3270
  this.filePositions.set(config.fileName, 0);
3018
3271
  }
3019
3272
  try {
3020
- const watcher = fs8.watch(filePath, (eventType) => {
3273
+ const watcher = fs9.watch(filePath, (eventType) => {
3021
3274
  if (eventType === "change") {
3022
3275
  this.handleFileChange(config);
3023
3276
  }
@@ -3055,7 +3308,7 @@ var LogWatcher = class {
3055
3308
  const filePath = path5.join(this.logDir, config.fileName);
3056
3309
  const lastPosition = this.filePositions.get(config.fileName) || 0;
3057
3310
  try {
3058
- const stats = fs8.statSync(filePath);
3311
+ const stats = fs9.statSync(filePath);
3059
3312
  const currentSize = stats.size;
3060
3313
  if (currentSize < lastPosition) {
3061
3314
  this.log(`File ${config.fileName} was truncated, resetting position`);
@@ -3068,11 +3321,11 @@ var LogWatcher = class {
3068
3321
  }
3069
3322
  const readSize = currentSize - lastPosition;
3070
3323
  const buffer = Buffer.alloc(readSize);
3071
- const fd = fs8.openSync(filePath, "r");
3324
+ const fd = fs9.openSync(filePath, "r");
3072
3325
  try {
3073
- fs8.readSync(fd, buffer, 0, readSize, lastPosition);
3326
+ fs9.readSync(fd, buffer, 0, readSize, lastPosition);
3074
3327
  } finally {
3075
- fs8.closeSync(fd);
3328
+ fs9.closeSync(fd);
3076
3329
  }
3077
3330
  this.filePositions.set(config.fileName, currentSize);
3078
3331
  const content = buffer.toString("utf8");
@@ -3303,8 +3556,8 @@ __name(createSSEHandler, "createSSEHandler");
3303
3556
 
3304
3557
  // src/middlewares/dev-logs/api-list-handler.ts
3305
3558
  var SERVER_PORT = process.env.SERVER_PORT || "3000";
3306
- function extractModuleFromPath(path7) {
3307
- const segments = path7.split("/").filter(Boolean);
3559
+ function extractModuleFromPath(path8) {
3560
+ const segments = path8.split("/").filter(Boolean);
3308
3561
  let startIndex = 0;
3309
3562
  if (segments[0] === "api") {
3310
3563
  startIndex = 1;
@@ -3319,8 +3572,8 @@ function extractModuleFromPath(path7) {
3319
3572
  return moduleName;
3320
3573
  }
3321
3574
  __name(extractModuleFromPath, "extractModuleFromPath");
3322
- function generateRouteId(method, path7) {
3323
- const cleanPath = path7.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
3575
+ function generateRouteId(method, path8) {
3576
+ const cleanPath = path8.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
3324
3577
  return `${method.toLowerCase()}_${cleanPath}`;
3325
3578
  }
3326
3579
  __name(generateRouteId, "generateRouteId");
@@ -3571,7 +3824,7 @@ function handleError2(res, error, message = "Failed to collect logs") {
3571
3824
  __name(handleError2, "handleError");
3572
3825
 
3573
3826
  // src/middlewares/collect-logs/router.ts
3574
- var DEFAULT_BODY_SIZE_LIMIT = "1mb";
3827
+ var DEFAULT_BODY_SIZE_LIMIT = "20mb";
3575
3828
  function getBodySizeLimit() {
3576
3829
  return process.env.BODY_SIZE_LIMIT || DEFAULT_BODY_SIZE_LIMIT;
3577
3830
  }
@@ -3794,18 +4047,201 @@ async function registerMiddlewares(server, middlewares, options) {
3794
4047
  }
3795
4048
  }
3796
4049
  __name(registerMiddlewares, "registerMiddlewares");
4050
+
4051
+ // src/route-parser.ts
4052
+ var fs12 = __toESM(require("fs"), 1);
4053
+ var path7 = __toESM(require("path"), 1);
4054
+ var crypto3 = __toESM(require("crypto"), 1);
4055
+ var import_parser = require("@babel/parser");
4056
+ var import_traverse = __toESM(require("@babel/traverse"), 1);
4057
+ var t = __toESM(require("@babel/types"), 1);
4058
+ var traverse = typeof import_traverse.default === "function" ? import_traverse.default : import_traverse.default.default;
4059
+ function routeParserLog(level, message, ...args) {
4060
+ const prefix = "[route-parser]";
4061
+ const logMessage = `${prefix} ${message}`;
4062
+ switch (level) {
4063
+ case "warn":
4064
+ console.warn(logMessage, ...args);
4065
+ break;
4066
+ case "error":
4067
+ console.error(logMessage, ...args);
4068
+ break;
4069
+ case "info":
4070
+ console.info(logMessage, ...args);
4071
+ break;
4072
+ default:
4073
+ console.log(logMessage, ...args);
4074
+ }
4075
+ }
4076
+ __name(routeParserLog, "routeParserLog");
4077
+ function calculateFileHash(filePath) {
4078
+ try {
4079
+ const content = fs12.readFileSync(filePath, "utf-8");
4080
+ return crypto3.createHash("md5").update(content).digest("hex");
4081
+ } catch (error) {
4082
+ routeParserLog("warn", "Failed to calculate file hash:", error.message);
4083
+ return null;
4084
+ }
4085
+ }
4086
+ __name(calculateFileHash, "calculateFileHash");
4087
+ function isRouteComponent(openingElement) {
4088
+ return t.isJSXIdentifier(openingElement.name) && openingElement.name.name === "Route";
4089
+ }
4090
+ __name(isRouteComponent, "isRouteComponent");
4091
+ function evaluateTemplateLiteral(templateLiteral) {
4092
+ const quasis = templateLiteral.quasis;
4093
+ const expressions = templateLiteral.expressions;
4094
+ if (quasis.length === 1 && expressions.length === 0) {
4095
+ return quasis[0].value.raw;
4096
+ }
4097
+ return quasis.map((q) => q.value.raw).join("");
4098
+ }
4099
+ __name(evaluateTemplateLiteral, "evaluateTemplateLiteral");
4100
+ function extractPageRouteInfo(openingElement) {
4101
+ const routeInfo = {};
4102
+ openingElement.attributes.forEach((attr) => {
4103
+ if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
4104
+ const name = attr.name.name;
4105
+ let value;
4106
+ if (attr.value) {
4107
+ if (t.isStringLiteral(attr.value)) {
4108
+ value = attr.value.value;
4109
+ } else if (t.isJSXExpressionContainer(attr.value)) {
4110
+ const expression = attr.value.expression;
4111
+ if (t.isStringLiteral(expression)) {
4112
+ value = expression.value;
4113
+ } else if (t.isTemplateLiteral(expression)) {
4114
+ value = evaluateTemplateLiteral(expression);
4115
+ } else {
4116
+ value = true;
4117
+ }
4118
+ }
4119
+ } else {
4120
+ value = true;
4121
+ }
4122
+ routeInfo[name] = value;
4123
+ }
4124
+ });
4125
+ return routeInfo;
4126
+ }
4127
+ __name(extractPageRouteInfo, "extractPageRouteInfo");
4128
+ function buildFullPath(routeStack, currentRoute) {
4129
+ let fullPath = "";
4130
+ for (let i = 0; i < routeStack.length; i++) {
4131
+ if (routeStack[i].path) {
4132
+ let parentPath = routeStack[i].path;
4133
+ if (!parentPath.startsWith("/")) parentPath = `/${parentPath}`;
4134
+ if (parentPath.endsWith("/") && parentPath !== "/") {
4135
+ parentPath = parentPath.slice(0, -1);
4136
+ }
4137
+ fullPath += parentPath === "/" ? "" : parentPath;
4138
+ }
4139
+ }
4140
+ if (currentRoute.index) {
4141
+ return fullPath || "/";
4142
+ } else if (currentRoute.path) {
4143
+ const routePath = currentRoute.path;
4144
+ if (routePath === "*") {
4145
+ return null;
4146
+ }
4147
+ if (!routePath.startsWith("/")) {
4148
+ fullPath = `${fullPath}/${routePath}`;
4149
+ } else {
4150
+ fullPath = routePath;
4151
+ }
4152
+ if (fullPath === "") fullPath = "/";
4153
+ if (!fullPath.startsWith("/")) fullPath = `/${fullPath}`;
4154
+ return fullPath;
4155
+ }
4156
+ return null;
4157
+ }
4158
+ __name(buildFullPath, "buildFullPath");
4159
+ function parseRoutesFromFile(appPath, basePath, options = {}) {
4160
+ const { applyBasePath = true } = options;
4161
+ const defaultPath = applyBasePath && basePath ? `${basePath}/` : "/";
4162
+ try {
4163
+ const appFilePath = path7.resolve(process.cwd(), appPath);
4164
+ if (!fs12.existsSync(appFilePath)) {
4165
+ throw new Error(`App file does not exist: ${appFilePath}`);
4166
+ }
4167
+ const sourceCode = fs12.readFileSync(appFilePath, "utf-8");
4168
+ const ast = (0, import_parser.parse)(sourceCode, {
4169
+ sourceType: "module",
4170
+ plugins: [
4171
+ "jsx",
4172
+ "typescript",
4173
+ "decorators-legacy",
4174
+ "classProperties",
4175
+ "objectRestSpread",
4176
+ "functionBind",
4177
+ "exportDefaultFrom",
4178
+ "exportNamespaceFrom",
4179
+ "dynamicImport",
4180
+ "nullishCoalescingOperator",
4181
+ "optionalChaining"
4182
+ ]
4183
+ });
4184
+ const routeSet = /* @__PURE__ */ new Set();
4185
+ const routeStack = [];
4186
+ traverse(ast, {
4187
+ JSXElement: {
4188
+ enter(nodePath) {
4189
+ const { openingElement } = nodePath.node;
4190
+ if (isRouteComponent(openingElement)) {
4191
+ routeStack.push(extractPageRouteInfo(openingElement));
4192
+ }
4193
+ },
4194
+ exit(nodePath) {
4195
+ const { openingElement } = nodePath.node;
4196
+ if (isRouteComponent(openingElement)) {
4197
+ const currentRoute = routeStack.pop();
4198
+ if (currentRoute && currentRoute.path === "*") return;
4199
+ if (currentRoute && (currentRoute.path || currentRoute.index)) {
4200
+ const fullPath = buildFullPath(routeStack, currentRoute);
4201
+ if (fullPath) routeSet.add(fullPath);
4202
+ }
4203
+ }
4204
+ }
4205
+ }
4206
+ });
4207
+ const routes = Array.from(routeSet).map((routePath) => ({
4208
+ path: applyBasePath && basePath ? `${basePath}${routePath}` : routePath
4209
+ }));
4210
+ return routes.length > 0 ? routes : [
4211
+ {
4212
+ path: defaultPath
4213
+ }
4214
+ ];
4215
+ } catch (error) {
4216
+ routeParserLog("warn", "Route parsing failed, using default routes:", error.message);
4217
+ return [
4218
+ {
4219
+ path: defaultPath
4220
+ }
4221
+ ];
4222
+ }
4223
+ }
4224
+ __name(parseRoutesFromFile, "parseRoutesFromFile");
3797
4225
  // Annotate the CommonJS export names for ESM import in node:
3798
4226
  0 && (module.exports = {
4227
+ buildFullPath,
4228
+ calculateFileHash,
3799
4229
  createCollectLogsMiddleware,
3800
4230
  createDevLogsMiddleware,
3801
4231
  createOpenapiMiddleware,
4232
+ evaluateTemplateLiteral,
4233
+ extractPageRouteInfo,
3802
4234
  getQuery,
3803
4235
  getQueryParam,
3804
4236
  handleDevProxyError,
4237
+ isRouteComponent,
3805
4238
  normalizeBasePath,
3806
4239
  parseAndGenerateNestResourceTemplate,
4240
+ parseApiRoutes,
4241
+ parseRoutesFromFile,
3807
4242
  postprocessDrizzleSchema,
3808
4243
  registerMiddlewares,
4244
+ routeParserLog,
3809
4245
  sendError,
3810
4246
  sendJson,
3811
4247
  sendSuccess