@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/bin/generate-api-routes.cjs +189 -0
- package/dist/bin/generate-api-routes.cjs.map +1 -0
- package/dist/bin/generate-api-routes.d.cts +1 -0
- package/dist/bin/generate-api-routes.d.ts +1 -0
- package/dist/bin/generate-api-routes.js +43 -0
- package/dist/bin/generate-api-routes.js.map +1 -0
- package/dist/bin/generate-page-routes.cjs +227 -0
- package/dist/bin/generate-page-routes.cjs.map +1 -0
- package/dist/bin/generate-page-routes.d.cts +1 -0
- package/dist/bin/generate-page-routes.d.ts +1 -0
- package/dist/bin/generate-page-routes.js +43 -0
- package/dist/bin/generate-page-routes.js.map +1 -0
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/chunk-LSHFHCDF.js +350 -0
- package/dist/chunk-LSHFHCDF.js.map +1 -0
- package/dist/chunk-YPNLFWHQ.js +189 -0
- package/dist/chunk-YPNLFWHQ.js.map +1 -0
- package/dist/index.cjs +475 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -3
- package/dist/index.d.ts +41 -3
- package/dist/index.js +202 -276
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
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((
|
|
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
|
-
|
|
1304
|
+
resolve2(res.statusCode !== 502);
|
|
1297
1305
|
});
|
|
1298
1306
|
req.on("timeout", () => {
|
|
1299
1307
|
req.destroy();
|
|
1300
|
-
|
|
1308
|
+
resolve2(false);
|
|
1301
1309
|
});
|
|
1302
1310
|
req.on("error", () => {
|
|
1303
|
-
|
|
1311
|
+
resolve2(false);
|
|
1304
1312
|
});
|
|
1305
1313
|
req.end();
|
|
1306
1314
|
} catch {
|
|
1307
|
-
|
|
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((
|
|
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
|
|
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(
|
|
1723
|
-
return
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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
|
|
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,
|
|
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:
|
|
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
|
|
2931
|
+
const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2679
2932
|
try {
|
|
2680
|
-
const result = await readTriggerDetail(traceLogPath,
|
|
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((
|
|
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
|
-
|
|
2986
|
+
resolve2({
|
|
2734
2987
|
available: true,
|
|
2735
2988
|
responseTime
|
|
2736
2989
|
});
|
|
2737
2990
|
});
|
|
2738
2991
|
req.on("timeout", () => {
|
|
2739
2992
|
req.destroy();
|
|
2740
|
-
|
|
2993
|
+
resolve2({
|
|
2741
2994
|
available: false,
|
|
2742
2995
|
error: "Request timeout"
|
|
2743
2996
|
});
|
|
2744
2997
|
});
|
|
2745
2998
|
req.on("error", (err) => {
|
|
2746
|
-
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
3324
|
+
const fd = fs9.openSync(filePath, "r");
|
|
3072
3325
|
try {
|
|
3073
|
-
|
|
3326
|
+
fs9.readSync(fd, buffer, 0, readSize, lastPosition);
|
|
3074
3327
|
} finally {
|
|
3075
|
-
|
|
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(
|
|
3307
|
-
const segments =
|
|
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,
|
|
3323
|
-
const cleanPath =
|
|
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 = "
|
|
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
|