@lark-apaas/devtool-kits 1.2.17-alpha.4 → 1.2.17-alpha.41
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 +191 -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 +170 -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/index.cjs +241 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +170 -270
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
enhanceOpenApiWithSourceInfo,
|
|
3
|
+
parseApiRoutes,
|
|
4
|
+
transformOpenapiPaths
|
|
5
|
+
} from "./chunk-LSHFHCDF.js";
|
|
6
|
+
import {
|
|
7
|
+
__name
|
|
8
|
+
} from "./chunk-7QVYU63E.js";
|
|
3
9
|
|
|
4
10
|
// src/utils/index.ts
|
|
5
11
|
function normalizeBasePath(basePath) {
|
|
@@ -1329,246 +1335,19 @@ function handleDevProxyError(err, req, res, options) {
|
|
|
1329
1335
|
__name(handleDevProxyError, "handleDevProxyError");
|
|
1330
1336
|
|
|
1331
1337
|
// src/middlewares/index.ts
|
|
1332
|
-
import
|
|
1338
|
+
import path4 from "path";
|
|
1333
1339
|
|
|
1334
1340
|
// src/middlewares/openapi/router.ts
|
|
1335
1341
|
import express from "express";
|
|
1336
1342
|
|
|
1337
1343
|
// src/middlewares/openapi/controller.ts
|
|
1338
|
-
import
|
|
1344
|
+
import fs3 from "fs/promises";
|
|
1339
1345
|
import crypto from "crypto";
|
|
1340
|
-
|
|
1341
|
-
// src/middlewares/openapi/services.ts
|
|
1342
|
-
import { promises as fs4 } from "fs";
|
|
1343
|
-
import path4 from "path";
|
|
1344
|
-
import ts from "typescript";
|
|
1345
|
-
|
|
1346
|
-
// src/middlewares/openapi/utils.ts
|
|
1347
|
-
import path3 from "path";
|
|
1348
|
-
import { promises as fs3 } from "fs";
|
|
1349
|
-
async function findControllerFiles(dir) {
|
|
1350
|
-
const files = [];
|
|
1351
|
-
async function scan(currentDir) {
|
|
1352
|
-
const entries = await fs3.readdir(currentDir, {
|
|
1353
|
-
withFileTypes: true
|
|
1354
|
-
});
|
|
1355
|
-
for (const entry of entries) {
|
|
1356
|
-
const fullPath = path3.join(currentDir, entry.name);
|
|
1357
|
-
if (entry.isDirectory()) {
|
|
1358
|
-
await scan(fullPath);
|
|
1359
|
-
} else if (entry.isFile() && entry.name.endsWith(".controller.ts")) {
|
|
1360
|
-
files.push(fullPath);
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
__name(scan, "scan");
|
|
1365
|
-
await scan(dir);
|
|
1366
|
-
return files;
|
|
1367
|
-
}
|
|
1368
|
-
__name(findControllerFiles, "findControllerFiles");
|
|
1369
|
-
async function buildSourceMap(controllerFiles, processFile) {
|
|
1370
|
-
const sourceMap = /* @__PURE__ */ new Map();
|
|
1371
|
-
const concurrency = 10;
|
|
1372
|
-
const results = [];
|
|
1373
|
-
for (let i = 0; i < controllerFiles.length; i += concurrency) {
|
|
1374
|
-
const batch = controllerFiles.slice(i, i + concurrency);
|
|
1375
|
-
const batchResults = await Promise.all(batch.map((filePath) => processFile(filePath)));
|
|
1376
|
-
results.push(...batchResults);
|
|
1377
|
-
}
|
|
1378
|
-
for (const metadata of results) {
|
|
1379
|
-
for (const [operationId, info] of metadata.entries()) {
|
|
1380
|
-
sourceMap.set(operationId, info);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
return sourceMap;
|
|
1384
|
-
}
|
|
1385
|
-
__name(buildSourceMap, "buildSourceMap");
|
|
1386
|
-
function findSourceInfo(operationId, sourceMap) {
|
|
1387
|
-
const directMatch = sourceMap.get(operationId);
|
|
1388
|
-
if (directMatch) {
|
|
1389
|
-
return directMatch;
|
|
1390
|
-
}
|
|
1391
|
-
for (const [key, value] of sourceMap.entries()) {
|
|
1392
|
-
const [className, methodName] = key.split("_");
|
|
1393
|
-
if (!className || !methodName) continue;
|
|
1394
|
-
const camelCaseId = className.charAt(0).toLowerCase() + className.slice(1) + methodName.charAt(0).toUpperCase() + methodName.slice(1);
|
|
1395
|
-
if (operationId === camelCaseId) {
|
|
1396
|
-
return value;
|
|
1397
|
-
}
|
|
1398
|
-
if (operationId === methodName) {
|
|
1399
|
-
return value;
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
return void 0;
|
|
1403
|
-
}
|
|
1404
|
-
__name(findSourceInfo, "findSourceInfo");
|
|
1405
|
-
function enhanceOpenApiPaths(openapi, sourceMap) {
|
|
1406
|
-
let enhancedCount = 0;
|
|
1407
|
-
if (!openapi.paths) {
|
|
1408
|
-
return enhancedCount;
|
|
1409
|
-
}
|
|
1410
|
-
for (const pathItem of Object.values(openapi.paths)) {
|
|
1411
|
-
if (!pathItem || typeof pathItem !== "object") continue;
|
|
1412
|
-
for (const operation of Object.values(pathItem)) {
|
|
1413
|
-
if (operation && typeof operation === "object" && "operationId" in operation) {
|
|
1414
|
-
const sourceInfo = findSourceInfo(operation.operationId, sourceMap);
|
|
1415
|
-
if (sourceInfo) {
|
|
1416
|
-
operation["x-source"] = {
|
|
1417
|
-
file: sourceInfo.file,
|
|
1418
|
-
line: sourceInfo.line
|
|
1419
|
-
};
|
|
1420
|
-
enhancedCount++;
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
return enhancedCount;
|
|
1426
|
-
}
|
|
1427
|
-
__name(enhanceOpenApiPaths, "enhanceOpenApiPaths");
|
|
1428
|
-
function transformOpenapiPaths(openapi, basePath) {
|
|
1429
|
-
if (basePath === "/" || !openapi.paths) {
|
|
1430
|
-
return openapi;
|
|
1431
|
-
}
|
|
1432
|
-
const newPaths = {};
|
|
1433
|
-
Object.keys(openapi.paths).forEach((key) => {
|
|
1434
|
-
const staticApiKey = key.startsWith(basePath) ? key.slice(basePath.length) : key;
|
|
1435
|
-
newPaths[staticApiKey] = openapi.paths[key];
|
|
1436
|
-
});
|
|
1437
|
-
return {
|
|
1438
|
-
...openapi,
|
|
1439
|
-
paths: newPaths,
|
|
1440
|
-
basePath
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1443
|
-
__name(transformOpenapiPaths, "transformOpenapiPaths");
|
|
1444
|
-
|
|
1445
|
-
// src/middlewares/openapi/services.ts
|
|
1446
|
-
async function enhanceOpenApiWithSourceInfo(options = {}) {
|
|
1447
|
-
const startTime = Date.now();
|
|
1448
|
-
const openapiPath = options.openapiPath || path4.resolve(__dirname, "../client/src/api/gen/openapi.json");
|
|
1449
|
-
const serverDir = options.serverDir || path4.resolve(__dirname, "../server");
|
|
1450
|
-
const writeFile2 = options.writeFile !== false;
|
|
1451
|
-
let openapi;
|
|
1452
|
-
if (options.openapiData) {
|
|
1453
|
-
openapi = JSON.parse(JSON.stringify(options.openapiData));
|
|
1454
|
-
} else {
|
|
1455
|
-
const openapiContent = await fs4.readFile(openapiPath, "utf-8");
|
|
1456
|
-
openapi = JSON.parse(openapiContent);
|
|
1457
|
-
}
|
|
1458
|
-
const controllerFiles = await findControllerFiles(serverDir);
|
|
1459
|
-
const sourceMap = await buildSourceMap(controllerFiles, processControllerFile);
|
|
1460
|
-
const enhanced = enhanceOpenApiPaths(openapi, sourceMap);
|
|
1461
|
-
if (writeFile2) {
|
|
1462
|
-
await fs4.writeFile(openapiPath, JSON.stringify(openapi, null, 2) + "\n", "utf-8");
|
|
1463
|
-
}
|
|
1464
|
-
const duration = Date.now() - startTime;
|
|
1465
|
-
return {
|
|
1466
|
-
openapi,
|
|
1467
|
-
stats: {
|
|
1468
|
-
duration,
|
|
1469
|
-
controllersFound: controllerFiles.length,
|
|
1470
|
-
endpointsExtracted: sourceMap.size,
|
|
1471
|
-
endpointsEnhanced: enhanced
|
|
1472
|
-
}
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
|
-
__name(enhanceOpenApiWithSourceInfo, "enhanceOpenApiWithSourceInfo");
|
|
1476
|
-
async function processControllerFile(filePath) {
|
|
1477
|
-
const relativePath = path4.relative(process.cwd(), filePath);
|
|
1478
|
-
const content = await fs4.readFile(filePath, "utf-8");
|
|
1479
|
-
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
1480
|
-
return extractControllerMetadata(sourceFile, relativePath);
|
|
1481
|
-
}
|
|
1482
|
-
__name(processControllerFile, "processControllerFile");
|
|
1483
|
-
function extractControllerMetadata(sourceFile, filePath) {
|
|
1484
|
-
const metadata = /* @__PURE__ */ new Map();
|
|
1485
|
-
let controllerPath = "";
|
|
1486
|
-
let className = "";
|
|
1487
|
-
function getDecorators(node) {
|
|
1488
|
-
if ("modifiers" in node && Array.isArray(node.modifiers)) {
|
|
1489
|
-
return node.modifiers.filter((mod) => mod.kind === ts.SyntaxKind.Decorator);
|
|
1490
|
-
}
|
|
1491
|
-
if ("decorators" in node && Array.isArray(node.decorators)) {
|
|
1492
|
-
return node.decorators;
|
|
1493
|
-
}
|
|
1494
|
-
return [];
|
|
1495
|
-
}
|
|
1496
|
-
__name(getDecorators, "getDecorators");
|
|
1497
|
-
function visit(node) {
|
|
1498
|
-
if (ts.isClassDeclaration(node)) {
|
|
1499
|
-
const decorators = getDecorators(node);
|
|
1500
|
-
if (node.name) {
|
|
1501
|
-
className = node.name.getText(sourceFile);
|
|
1502
|
-
}
|
|
1503
|
-
for (const decorator of decorators) {
|
|
1504
|
-
if (ts.isCallExpression(decorator.expression)) {
|
|
1505
|
-
const expression = decorator.expression;
|
|
1506
|
-
const decoratorName = expression.expression.getText(sourceFile);
|
|
1507
|
-
if (decoratorName === "Controller") {
|
|
1508
|
-
if (expression.arguments.length > 0) {
|
|
1509
|
-
const arg = expression.arguments[0];
|
|
1510
|
-
if (ts.isStringLiteral(arg)) {
|
|
1511
|
-
controllerPath = arg.text;
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
if (ts.isMethodDeclaration(node) && node.name) {
|
|
1519
|
-
const methodName = node.name.getText(sourceFile);
|
|
1520
|
-
let httpMethod = "";
|
|
1521
|
-
let routePath = "";
|
|
1522
|
-
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
1523
|
-
const decorators = getDecorators(node);
|
|
1524
|
-
for (const decorator of decorators) {
|
|
1525
|
-
if (ts.isCallExpression(decorator.expression)) {
|
|
1526
|
-
const decoratorName = decorator.expression.expression.getText(sourceFile);
|
|
1527
|
-
if ([
|
|
1528
|
-
"Get",
|
|
1529
|
-
"Post",
|
|
1530
|
-
"Put",
|
|
1531
|
-
"Delete",
|
|
1532
|
-
"Patch",
|
|
1533
|
-
"Options",
|
|
1534
|
-
"Head",
|
|
1535
|
-
"All"
|
|
1536
|
-
].includes(decoratorName)) {
|
|
1537
|
-
httpMethod = decoratorName.toLowerCase();
|
|
1538
|
-
if (decorator.expression.arguments.length > 0) {
|
|
1539
|
-
const arg = decorator.expression.arguments[0];
|
|
1540
|
-
if (ts.isStringLiteral(arg)) {
|
|
1541
|
-
routePath = arg.text;
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
if (httpMethod && methodName && className) {
|
|
1548
|
-
const operationId = `${className}_${methodName}`;
|
|
1549
|
-
metadata.set(operationId, {
|
|
1550
|
-
file: filePath,
|
|
1551
|
-
line: line + 1,
|
|
1552
|
-
method: httpMethod,
|
|
1553
|
-
controllerPath,
|
|
1554
|
-
routePath
|
|
1555
|
-
});
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
ts.forEachChild(node, visit);
|
|
1559
|
-
}
|
|
1560
|
-
__name(visit, "visit");
|
|
1561
|
-
visit(sourceFile);
|
|
1562
|
-
return metadata;
|
|
1563
|
-
}
|
|
1564
|
-
__name(extractControllerMetadata, "extractControllerMetadata");
|
|
1565
|
-
|
|
1566
|
-
// src/middlewares/openapi/controller.ts
|
|
1567
1346
|
function createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir) {
|
|
1568
1347
|
let cache = null;
|
|
1569
1348
|
return async (_req, res, context) => {
|
|
1570
1349
|
try {
|
|
1571
|
-
const fileBuffer = await
|
|
1350
|
+
const fileBuffer = await fs3.readFile(openapiFilePath, "utf-8");
|
|
1572
1351
|
const currentHash = crypto.createHash("md5").update(fileBuffer).digest("hex");
|
|
1573
1352
|
if (cache && cache.fileHash === currentHash) {
|
|
1574
1353
|
return res.json(cache.data);
|
|
@@ -1640,7 +1419,7 @@ __name(createOpenapiMiddleware, "createOpenapiMiddleware");
|
|
|
1640
1419
|
import express2 from "express";
|
|
1641
1420
|
|
|
1642
1421
|
// src/middlewares/dev-logs/utils.ts
|
|
1643
|
-
import { promises as
|
|
1422
|
+
import { promises as fs4 } from "fs";
|
|
1644
1423
|
import { isAbsolute, join as join2, relative } from "path";
|
|
1645
1424
|
|
|
1646
1425
|
// src/middlewares/dev-logs/helper/path-matcher.ts
|
|
@@ -1673,8 +1452,8 @@ function hasSpecialPatterns(pattern) {
|
|
|
1673
1452
|
return /[{*]/.test(pattern);
|
|
1674
1453
|
}
|
|
1675
1454
|
__name(hasSpecialPatterns, "hasSpecialPatterns");
|
|
1676
|
-
function normalizePathForMatching(
|
|
1677
|
-
return
|
|
1455
|
+
function normalizePathForMatching(path5) {
|
|
1456
|
+
return path5.replace(/\/+/g, "/").replace(/\/+$/, "");
|
|
1678
1457
|
}
|
|
1679
1458
|
__name(normalizePathForMatching, "normalizePathForMatching");
|
|
1680
1459
|
|
|
@@ -1692,7 +1471,7 @@ function getRelativePath(filePath) {
|
|
|
1692
1471
|
__name(getRelativePath, "getRelativePath");
|
|
1693
1472
|
async function fileExists(filePath) {
|
|
1694
1473
|
try {
|
|
1695
|
-
await
|
|
1474
|
+
await fs4.access(filePath);
|
|
1696
1475
|
return true;
|
|
1697
1476
|
} catch {
|
|
1698
1477
|
return false;
|
|
@@ -1775,9 +1554,9 @@ __name(serializeError, "serializeError");
|
|
|
1775
1554
|
import { join as join4 } from "path";
|
|
1776
1555
|
|
|
1777
1556
|
// src/middlewares/dev-logs/services/file-reader.ts
|
|
1778
|
-
import { promises as
|
|
1557
|
+
import { promises as fs5 } from "fs";
|
|
1779
1558
|
async function readFileReverse(filePath, chunkSize, processLine) {
|
|
1780
|
-
const handle = await
|
|
1559
|
+
const handle = await fs5.open(filePath, "r");
|
|
1781
1560
|
try {
|
|
1782
1561
|
const stats = await handle.stat();
|
|
1783
1562
|
let position = stats.size;
|
|
@@ -1894,8 +1673,10 @@ function parsePinoLog(line, source) {
|
|
|
1894
1673
|
statusCode: pinoLog.status_code,
|
|
1895
1674
|
durationMs: pinoLog.duration_ms,
|
|
1896
1675
|
ip: pinoLog.ip,
|
|
1676
|
+
pageRoute: pinoLog.page_route,
|
|
1897
1677
|
requestBody: pinoLog.request_body,
|
|
1898
|
-
responseBody: pinoLog.response_body
|
|
1678
|
+
responseBody: pinoLog.response_body,
|
|
1679
|
+
queryParams: pinoLog.query_params
|
|
1899
1680
|
},
|
|
1900
1681
|
tags: [
|
|
1901
1682
|
source
|
|
@@ -2221,7 +2002,7 @@ __name(readLogsBySource, "readLogsBySource");
|
|
|
2221
2002
|
// src/middlewares/dev-logs/services/trigger.service.ts
|
|
2222
2003
|
import { createReadStream as createReadStream3 } from "fs";
|
|
2223
2004
|
import { createInterface as createInterface3 } from "readline";
|
|
2224
|
-
async function readTriggerList(filePath, trigger,
|
|
2005
|
+
async function readTriggerList(filePath, trigger, path5, limit, triggerID) {
|
|
2225
2006
|
if (!await fileExists(filePath)) {
|
|
2226
2007
|
return void 0;
|
|
2227
2008
|
}
|
|
@@ -2247,7 +2028,7 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
|
|
|
2247
2028
|
if (alreadyAdded) {
|
|
2248
2029
|
return false;
|
|
2249
2030
|
}
|
|
2250
|
-
const isAutomationTrigger = builder.path?.endsWith(
|
|
2031
|
+
const isAutomationTrigger = builder.path?.endsWith(path5);
|
|
2251
2032
|
if (!isAutomationTrigger) {
|
|
2252
2033
|
return false;
|
|
2253
2034
|
}
|
|
@@ -2330,7 +2111,7 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
|
|
|
2330
2111
|
};
|
|
2331
2112
|
}
|
|
2332
2113
|
__name(readTriggerList, "readTriggerList");
|
|
2333
|
-
async function readTriggerDetail(filePath,
|
|
2114
|
+
async function readTriggerDetail(filePath, path5, instanceID) {
|
|
2334
2115
|
const exists = await fileExists(filePath);
|
|
2335
2116
|
if (!exists) {
|
|
2336
2117
|
return void 0;
|
|
@@ -2346,7 +2127,7 @@ async function readTriggerDetail(filePath, path7, instanceID) {
|
|
|
2346
2127
|
for await (const line of rl) {
|
|
2347
2128
|
const entry = parseLogLine(line);
|
|
2348
2129
|
if (!entry) continue;
|
|
2349
|
-
const isAutomationTrigger = entry.path?.endsWith(
|
|
2130
|
+
const isAutomationTrigger = entry.path?.endsWith(path5);
|
|
2350
2131
|
const hasInstanceID = entry.instance_id === instanceID && entry.trigger;
|
|
2351
2132
|
if (!isAutomationTrigger || !hasInstanceID) continue;
|
|
2352
2133
|
matches.push(entry);
|
|
@@ -2600,16 +2381,16 @@ function createGetTriggerListHandler(logDir) {
|
|
|
2600
2381
|
});
|
|
2601
2382
|
}
|
|
2602
2383
|
const triggerID = typeof req.query.triggerID === "string" ? req.query.triggerID.trim() : void 0;
|
|
2603
|
-
const
|
|
2384
|
+
const path5 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2604
2385
|
const limit = parseLimit(req.query.limit, 10, 200);
|
|
2605
2386
|
try {
|
|
2606
|
-
const result = await readTriggerList(traceLogPath, trigger,
|
|
2387
|
+
const result = await readTriggerList(traceLogPath, trigger, path5, limit, triggerID);
|
|
2607
2388
|
if (!result) {
|
|
2608
2389
|
return handleNotFound(res, traceLogPath);
|
|
2609
2390
|
}
|
|
2610
2391
|
res.json({
|
|
2611
2392
|
file: getRelativePath(traceLogPath),
|
|
2612
|
-
path:
|
|
2393
|
+
path: path5,
|
|
2613
2394
|
...result
|
|
2614
2395
|
});
|
|
2615
2396
|
} catch (error) {
|
|
@@ -2627,9 +2408,9 @@ function createGetTriggerDetailHandler(logDir) {
|
|
|
2627
2408
|
message: "instanceID is required"
|
|
2628
2409
|
});
|
|
2629
2410
|
}
|
|
2630
|
-
const
|
|
2411
|
+
const path5 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2631
2412
|
try {
|
|
2632
|
-
const result = await readTriggerDetail(traceLogPath,
|
|
2413
|
+
const result = await readTriggerDetail(traceLogPath, path5, instanceID);
|
|
2633
2414
|
if (!result) {
|
|
2634
2415
|
return handleNotFound(res, traceLogPath);
|
|
2635
2416
|
}
|
|
@@ -2737,8 +2518,8 @@ function createHealthCheckHandler(options = {}) {
|
|
|
2737
2518
|
__name(createHealthCheckHandler, "createHealthCheckHandler");
|
|
2738
2519
|
|
|
2739
2520
|
// src/middlewares/dev-logs/sse/log-watcher.ts
|
|
2740
|
-
import * as
|
|
2741
|
-
import * as
|
|
2521
|
+
import * as fs6 from "fs";
|
|
2522
|
+
import * as path3 from "path";
|
|
2742
2523
|
function mapPinoLevelToServerLogLevel2(pinoLevel) {
|
|
2743
2524
|
if (typeof pinoLevel === "string") {
|
|
2744
2525
|
const lower = pinoLevel.toLowerCase();
|
|
@@ -2799,8 +2580,10 @@ function parsePinoLog2(line, source) {
|
|
|
2799
2580
|
statusCode: pinoLog.status_code,
|
|
2800
2581
|
durationMs: pinoLog.duration_ms,
|
|
2801
2582
|
ip: pinoLog.ip,
|
|
2583
|
+
pageRoute: pinoLog.page_route,
|
|
2802
2584
|
requestBody: pinoLog.request_body,
|
|
2803
|
-
responseBody: pinoLog.response_body
|
|
2585
|
+
responseBody: pinoLog.response_body,
|
|
2586
|
+
queryParams: pinoLog.query_params
|
|
2804
2587
|
},
|
|
2805
2588
|
tags: [
|
|
2806
2589
|
source
|
|
@@ -2953,13 +2736,13 @@ var LogWatcher = class {
|
|
|
2953
2736
|
* Watch a single log file
|
|
2954
2737
|
*/
|
|
2955
2738
|
watchFile(config) {
|
|
2956
|
-
const filePath =
|
|
2957
|
-
if (!
|
|
2739
|
+
const filePath = path3.join(this.logDir, config.fileName);
|
|
2740
|
+
if (!fs6.existsSync(filePath)) {
|
|
2958
2741
|
this.log(`File not found, skipping: ${config.fileName}`);
|
|
2959
2742
|
return;
|
|
2960
2743
|
}
|
|
2961
2744
|
try {
|
|
2962
|
-
const stats =
|
|
2745
|
+
const stats = fs6.statSync(filePath);
|
|
2963
2746
|
this.filePositions.set(config.fileName, stats.size);
|
|
2964
2747
|
this.log(`Initialized position for ${config.fileName}: ${stats.size} bytes`);
|
|
2965
2748
|
} catch (error) {
|
|
@@ -2967,7 +2750,7 @@ var LogWatcher = class {
|
|
|
2967
2750
|
this.filePositions.set(config.fileName, 0);
|
|
2968
2751
|
}
|
|
2969
2752
|
try {
|
|
2970
|
-
const watcher =
|
|
2753
|
+
const watcher = fs6.watch(filePath, (eventType) => {
|
|
2971
2754
|
if (eventType === "change") {
|
|
2972
2755
|
this.handleFileChange(config);
|
|
2973
2756
|
}
|
|
@@ -3002,10 +2785,10 @@ var LogWatcher = class {
|
|
|
3002
2785
|
* Handle file change event - read new content
|
|
3003
2786
|
*/
|
|
3004
2787
|
handleFileChange(config) {
|
|
3005
|
-
const filePath =
|
|
2788
|
+
const filePath = path3.join(this.logDir, config.fileName);
|
|
3006
2789
|
const lastPosition = this.filePositions.get(config.fileName) || 0;
|
|
3007
2790
|
try {
|
|
3008
|
-
const stats =
|
|
2791
|
+
const stats = fs6.statSync(filePath);
|
|
3009
2792
|
const currentSize = stats.size;
|
|
3010
2793
|
if (currentSize < lastPosition) {
|
|
3011
2794
|
this.log(`File ${config.fileName} was truncated, resetting position`);
|
|
@@ -3018,11 +2801,11 @@ var LogWatcher = class {
|
|
|
3018
2801
|
}
|
|
3019
2802
|
const readSize = currentSize - lastPosition;
|
|
3020
2803
|
const buffer = Buffer.alloc(readSize);
|
|
3021
|
-
const fd =
|
|
2804
|
+
const fd = fs6.openSync(filePath, "r");
|
|
3022
2805
|
try {
|
|
3023
|
-
|
|
2806
|
+
fs6.readSync(fd, buffer, 0, readSize, lastPosition);
|
|
3024
2807
|
} finally {
|
|
3025
|
-
|
|
2808
|
+
fs6.closeSync(fd);
|
|
3026
2809
|
}
|
|
3027
2810
|
this.filePositions.set(config.fileName, currentSize);
|
|
3028
2811
|
const content = buffer.toString("utf8");
|
|
@@ -3251,6 +3034,106 @@ function createSSEHandler(logDir, options = {}) {
|
|
|
3251
3034
|
}
|
|
3252
3035
|
__name(createSSEHandler, "createSSEHandler");
|
|
3253
3036
|
|
|
3037
|
+
// src/middlewares/dev-logs/api-list-handler.ts
|
|
3038
|
+
var SERVER_PORT = process.env.SERVER_PORT || "3000";
|
|
3039
|
+
function extractModuleFromPath(path5) {
|
|
3040
|
+
const segments = path5.split("/").filter(Boolean);
|
|
3041
|
+
let startIndex = 0;
|
|
3042
|
+
if (segments[0] === "api") {
|
|
3043
|
+
startIndex = 1;
|
|
3044
|
+
}
|
|
3045
|
+
if (segments[startIndex]?.match(/^v\d+$/)) {
|
|
3046
|
+
startIndex++;
|
|
3047
|
+
}
|
|
3048
|
+
const moduleName = segments[startIndex];
|
|
3049
|
+
if (!moduleName || moduleName.startsWith(":")) {
|
|
3050
|
+
return "default";
|
|
3051
|
+
}
|
|
3052
|
+
return moduleName;
|
|
3053
|
+
}
|
|
3054
|
+
__name(extractModuleFromPath, "extractModuleFromPath");
|
|
3055
|
+
function generateRouteId(method, path5) {
|
|
3056
|
+
const cleanPath = path5.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
|
|
3057
|
+
return `${method.toLowerCase()}_${cleanPath}`;
|
|
3058
|
+
}
|
|
3059
|
+
__name(generateRouteId, "generateRouteId");
|
|
3060
|
+
function capitalize(str) {
|
|
3061
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3062
|
+
}
|
|
3063
|
+
__name(capitalize, "capitalize");
|
|
3064
|
+
function groupRoutesByModule(routes) {
|
|
3065
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
3066
|
+
routes.forEach((route) => {
|
|
3067
|
+
const existing = groupMap.get(route.module) || [];
|
|
3068
|
+
existing.push(route);
|
|
3069
|
+
groupMap.set(route.module, existing);
|
|
3070
|
+
});
|
|
3071
|
+
const groups = [];
|
|
3072
|
+
groupMap.forEach((apis, moduleName) => {
|
|
3073
|
+
groups.push({
|
|
3074
|
+
id: moduleName,
|
|
3075
|
+
name: capitalize(moduleName),
|
|
3076
|
+
apis: apis.sort((a, b) => a.path.localeCompare(b.path))
|
|
3077
|
+
});
|
|
3078
|
+
});
|
|
3079
|
+
return groups.sort((a, b) => a.name.localeCompare(b.name));
|
|
3080
|
+
}
|
|
3081
|
+
__name(groupRoutesByModule, "groupRoutesByModule");
|
|
3082
|
+
async function fetchRoutesFromBackend(basePath) {
|
|
3083
|
+
const normalizedBasePath = basePath.replace(/\/+$/, "");
|
|
3084
|
+
const url = `http://localhost:${SERVER_PORT}${normalizedBasePath}/api/__framework__/debug`;
|
|
3085
|
+
const response = await fetch(url, {
|
|
3086
|
+
method: "GET",
|
|
3087
|
+
headers: {
|
|
3088
|
+
"Accept": "application/json"
|
|
3089
|
+
}
|
|
3090
|
+
});
|
|
3091
|
+
if (!response.ok) {
|
|
3092
|
+
throw new Error(`Failed to fetch routes: ${response.status}`);
|
|
3093
|
+
}
|
|
3094
|
+
const data = await response.json();
|
|
3095
|
+
const routeConfig = data["\u8DEF\u7531\u914D\u7F6E"];
|
|
3096
|
+
if (!routeConfig || !routeConfig.routes || !Array.isArray(routeConfig.routes)) {
|
|
3097
|
+
console.warn("[api-list] Invalid routes data:", routeConfig);
|
|
3098
|
+
return [];
|
|
3099
|
+
}
|
|
3100
|
+
const debugRoutes = routeConfig.routes;
|
|
3101
|
+
return debugRoutes.filter((route) => {
|
|
3102
|
+
return route.path.includes("/api/") && !route.path.includes("__framework__") && !route.path.includes("__innerapi__") && !route.path.includes("/api/capability");
|
|
3103
|
+
}).map((route) => {
|
|
3104
|
+
const apiPathMatch = route.path.match(/\/api\/.*/);
|
|
3105
|
+
const apiPath = apiPathMatch ? apiPathMatch[0] : route.path;
|
|
3106
|
+
const method = route.method || "ALL";
|
|
3107
|
+
return {
|
|
3108
|
+
id: generateRouteId(method, apiPath),
|
|
3109
|
+
path: apiPath,
|
|
3110
|
+
method,
|
|
3111
|
+
module: extractModuleFromPath(apiPath)
|
|
3112
|
+
};
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
__name(fetchRoutesFromBackend, "fetchRoutesFromBackend");
|
|
3116
|
+
function createApiListHandler() {
|
|
3117
|
+
return async (_req, res) => {
|
|
3118
|
+
try {
|
|
3119
|
+
const basePath = process.env.CLIENT_BASE_PATH || "";
|
|
3120
|
+
const routes = await fetchRoutesFromBackend(basePath);
|
|
3121
|
+
const groups = groupRoutesByModule(routes);
|
|
3122
|
+
res.json({
|
|
3123
|
+
groups,
|
|
3124
|
+
total: routes.length
|
|
3125
|
+
});
|
|
3126
|
+
} catch (error) {
|
|
3127
|
+
console.error("[api-list] Failed to fetch routes:", error);
|
|
3128
|
+
res.status(500).json({
|
|
3129
|
+
error: "Failed to fetch routes",
|
|
3130
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
};
|
|
3134
|
+
}
|
|
3135
|
+
__name(createApiListHandler, "createApiListHandler");
|
|
3136
|
+
|
|
3254
3137
|
// src/middlewares/dev-logs/router.ts
|
|
3255
3138
|
function createDevLogRouter(options = {}) {
|
|
3256
3139
|
const logDir = resolveLogDir(options.logDir);
|
|
@@ -3264,6 +3147,7 @@ function createDevLogRouter(options = {}) {
|
|
|
3264
3147
|
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
3265
3148
|
router.get("/trace/capability/list", createGetCapabilityTraceListHandler(logDir));
|
|
3266
3149
|
router.get("/health", createHealthCheckHandler());
|
|
3150
|
+
router.get("/api-list", createApiListHandler());
|
|
3267
3151
|
return router;
|
|
3268
3152
|
}
|
|
3269
3153
|
__name(createDevLogRouter, "createDevLogRouter");
|
|
@@ -3299,6 +3183,11 @@ var DEV_LOGS_ROUTES = [
|
|
|
3299
3183
|
method: "GET",
|
|
3300
3184
|
path: "/trace/trigger/:instanceID",
|
|
3301
3185
|
description: "Get trigger detail (automation trigger) in trace.log by instanceID"
|
|
3186
|
+
},
|
|
3187
|
+
{
|
|
3188
|
+
method: "GET",
|
|
3189
|
+
path: "/api-list",
|
|
3190
|
+
description: "Get all API routes grouped by module"
|
|
3302
3191
|
}
|
|
3303
3192
|
];
|
|
3304
3193
|
function createDevLogsMiddleware(options = {}) {
|
|
@@ -3322,11 +3211,11 @@ import express3 from "express";
|
|
|
3322
3211
|
|
|
3323
3212
|
// src/middlewares/collect-logs/controller.ts
|
|
3324
3213
|
import { join as join7 } from "path";
|
|
3325
|
-
import
|
|
3214
|
+
import fs8 from "fs";
|
|
3326
3215
|
|
|
3327
3216
|
// src/middlewares/collect-logs/utils.ts
|
|
3328
3217
|
import { isAbsolute as isAbsolute2, join as join6 } from "path";
|
|
3329
|
-
import
|
|
3218
|
+
import fs7 from "fs";
|
|
3330
3219
|
function resolveLogDir2(provided) {
|
|
3331
3220
|
if (!provided) {
|
|
3332
3221
|
return join6(process.cwd(), "logs");
|
|
@@ -3335,8 +3224,8 @@ function resolveLogDir2(provided) {
|
|
|
3335
3224
|
}
|
|
3336
3225
|
__name(resolveLogDir2, "resolveLogDir");
|
|
3337
3226
|
function ensureDir(dir) {
|
|
3338
|
-
if (!
|
|
3339
|
-
|
|
3227
|
+
if (!fs7.existsSync(dir)) {
|
|
3228
|
+
fs7.mkdirSync(dir, {
|
|
3340
3229
|
recursive: true
|
|
3341
3230
|
});
|
|
3342
3231
|
}
|
|
@@ -3368,7 +3257,7 @@ function collectLogsHandler(logDir, fileName) {
|
|
|
3368
3257
|
...logContent,
|
|
3369
3258
|
server_time: (/* @__PURE__ */ new Date()).toISOString()
|
|
3370
3259
|
}) + "\n";
|
|
3371
|
-
await
|
|
3260
|
+
await fs8.promises.appendFile(filePath, logLine);
|
|
3372
3261
|
res.json({
|
|
3373
3262
|
success: true
|
|
3374
3263
|
});
|
|
@@ -3396,7 +3285,7 @@ function collectLogsBatchHandler(logDir, fileName) {
|
|
|
3396
3285
|
server_time: (/* @__PURE__ */ new Date()).toISOString()
|
|
3397
3286
|
}) + "\n");
|
|
3398
3287
|
}
|
|
3399
|
-
await
|
|
3288
|
+
await fs8.promises.appendFile(filePath, logLines.join(""));
|
|
3400
3289
|
res.json({
|
|
3401
3290
|
success: true
|
|
3402
3291
|
});
|
|
@@ -3415,11 +3304,21 @@ function handleError2(res, error, message = "Failed to collect logs") {
|
|
|
3415
3304
|
__name(handleError2, "handleError");
|
|
3416
3305
|
|
|
3417
3306
|
// src/middlewares/collect-logs/router.ts
|
|
3307
|
+
var DEFAULT_BODY_SIZE_LIMIT = "1mb";
|
|
3308
|
+
function getBodySizeLimit() {
|
|
3309
|
+
return process.env.BODY_SIZE_LIMIT || DEFAULT_BODY_SIZE_LIMIT;
|
|
3310
|
+
}
|
|
3311
|
+
__name(getBodySizeLimit, "getBodySizeLimit");
|
|
3418
3312
|
function createDevLogRouter2(options = {}) {
|
|
3419
3313
|
const logDir = resolveLogDir2(options.logDir);
|
|
3420
3314
|
const router = express3.Router();
|
|
3421
|
-
|
|
3422
|
-
router.post("/collect
|
|
3315
|
+
const bodyLimit = getBodySizeLimit();
|
|
3316
|
+
router.post("/collect", express3.json({
|
|
3317
|
+
limit: bodyLimit
|
|
3318
|
+
}), collectLogsHandler(logDir, options.fileName || "client.log"));
|
|
3319
|
+
router.post("/collect-batch", express3.json({
|
|
3320
|
+
limit: bodyLimit
|
|
3321
|
+
}), collectLogsBatchHandler(logDir, options.fileName || "client.log"));
|
|
3423
3322
|
return router;
|
|
3424
3323
|
}
|
|
3425
3324
|
__name(createDevLogRouter2, "createDevLogRouter");
|
|
@@ -3552,7 +3451,7 @@ function isGlobalMiddleware(middleware) {
|
|
|
3552
3451
|
}
|
|
3553
3452
|
__name(isGlobalMiddleware, "isGlobalMiddleware");
|
|
3554
3453
|
function computeMountPath(basePath, mountPath) {
|
|
3555
|
-
const routePath =
|
|
3454
|
+
const routePath = path4.posix.join(basePath, mountPath);
|
|
3556
3455
|
return routePath.startsWith("/") ? routePath : `/${routePath}`;
|
|
3557
3456
|
}
|
|
3558
3457
|
__name(computeMountPath, "computeMountPath");
|
|
@@ -3560,7 +3459,7 @@ function logMiddlewareRegistration(middleware, fullMountPath) {
|
|
|
3560
3459
|
if (middleware.routes && middleware.routes.length > 0) {
|
|
3561
3460
|
console.log(`[Middleware] Registered: ${middleware.name} at ${fullMountPath}`);
|
|
3562
3461
|
middleware.routes.forEach((route) => {
|
|
3563
|
-
const routePath = route.path === "/" ? fullMountPath :
|
|
3462
|
+
const routePath = route.path === "/" ? fullMountPath : path4.posix.join(fullMountPath, route.path);
|
|
3564
3463
|
console.log(` ${route.method} ${routePath} - ${route.description}`);
|
|
3565
3464
|
});
|
|
3566
3465
|
} else {
|
|
@@ -3637,6 +3536,7 @@ export {
|
|
|
3637
3536
|
handleDevProxyError,
|
|
3638
3537
|
normalizeBasePath,
|
|
3639
3538
|
parseAndGenerateNestResourceTemplate,
|
|
3539
|
+
parseApiRoutes,
|
|
3640
3540
|
postprocessDrizzleSchema,
|
|
3641
3541
|
registerMiddlewares,
|
|
3642
3542
|
sendError,
|