@lark-apaas/devtool-kits 1.2.5-alpha.1 → 1.2.5-alpha.3

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
@@ -2136,229 +2136,147 @@ async function readLogFilePage(filePath, page, pageSize) {
2136
2136
  };
2137
2137
  }
2138
2138
  __name(readLogFilePage, "readLogFilePage");
2139
- async function readServerLogs(logDir, options = {}) {
2140
- const limit = options.limit || 100;
2141
- const offset = options.offset || 0;
2142
- const sources = options.sources || [
2143
- "server",
2144
- "trace",
2145
- "server-std",
2146
- "client-std"
2147
- ];
2148
- const allLogs = [];
2149
- const errors = [];
2150
- for (const source of sources) {
2151
- try {
2152
- const logs = await readLogsBySource(logDir, source);
2153
- allLogs.push(...logs);
2154
- } catch (error) {
2155
- const errorMsg = `Failed to read ${source}: ${error instanceof Error ? error.message : String(error)}`;
2156
- errors.push(errorMsg);
2157
- console.warn(`[readServerLogs] ${errorMsg}`);
2158
- }
2159
- }
2160
- if (allLogs.length === 0) {
2161
- if (errors.length > 0) {
2162
- console.warn(`[readServerLogs] No logs found. Errors: ${errors.join(", ")}`);
2163
- }
2139
+ async function readTriggerList(filePath, trigger, path7, limit) {
2140
+ if (!await fileExists(filePath)) {
2164
2141
  return void 0;
2165
2142
  }
2166
- let filteredLogs = allLogs;
2167
- if (options.levels && options.levels.length > 0) {
2168
- filteredLogs = allLogs.filter((log) => options.levels.includes(log.level));
2169
- }
2170
- filteredLogs.sort((a, b) => b.timestamp - a.timestamp);
2171
- const total = filteredLogs.length;
2172
- const paginatedLogs = filteredLogs.slice(offset, offset + limit);
2173
- return {
2174
- logs: paginatedLogs,
2175
- total,
2176
- hasMore: offset + limit < total
2143
+ const config = {
2144
+ maxEntriesPerTrace: 10,
2145
+ chunkSize: 64 * 1024
2177
2146
  };
2178
- }
2179
- __name(readServerLogs, "readServerLogs");
2180
- async function readLogsBySource(logDir, source) {
2181
- const { join: join6 } = await import("path");
2182
- let filePath;
2183
- let parser;
2184
- if (source === "server") {
2185
- filePath = join6(logDir, "server.log");
2186
- parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
2187
- } else if (source === "trace") {
2188
- filePath = join6(logDir, "trace.log");
2189
- parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
2190
- } else if (source === "server-std") {
2191
- filePath = join6(logDir, "server.std.log");
2192
- parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
2193
- } else if (source === "client-std") {
2194
- filePath = join6(logDir, "client.std.log");
2195
- parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
2196
- } else {
2197
- console.warn(`[readLogsBySource] Unknown source: ${source}`);
2198
- return [];
2199
- }
2200
- if (!await fileExists(filePath)) {
2201
- console.warn(`[readLogsBySource] File not found: ${filePath}`);
2202
- return [];
2203
- }
2204
- const logs = [];
2205
- let stream = null;
2206
- let rl = null;
2207
- try {
2208
- stream = (0, import_node_fs7.createReadStream)(filePath, {
2209
- encoding: "utf8"
2210
- });
2211
- rl = (0, import_node_readline.createInterface)({
2212
- input: stream,
2213
- crlfDelay: Infinity
2214
- });
2215
- for await (const line of rl) {
2216
- if (!line.trim()) continue;
2217
- try {
2218
- const log = parser(line);
2219
- if (log) {
2220
- logs.push(log);
2221
- }
2222
- } catch (parseError) {
2147
+ const builders = /* @__PURE__ */ new Map();
2148
+ const completedCalls = [];
2149
+ const createTraceBuilder = /* @__PURE__ */ __name((traceId) => ({
2150
+ traceId,
2151
+ entries: [],
2152
+ method: void 0,
2153
+ path: void 0,
2154
+ startTime: void 0,
2155
+ endTime: void 0,
2156
+ statusCode: void 0,
2157
+ durationMs: void 0,
2158
+ hasCompleted: false
2159
+ }), "createTraceBuilder");
2160
+ const shouldIncludeInCompletedCalls = /* @__PURE__ */ __name((builder) => {
2161
+ const alreadyAdded = completedCalls.some((call) => call.traceId === builder.traceId);
2162
+ if (alreadyAdded) {
2163
+ return false;
2164
+ }
2165
+ if (!builder.hasCompleted) {
2166
+ return false;
2167
+ }
2168
+ const isAutomationTrigger = builder.path?.endsWith(path7);
2169
+ if (!isAutomationTrigger) {
2170
+ return false;
2171
+ }
2172
+ if (trigger && builder.entries.length > 0) {
2173
+ const requestEntry = builder.entries.find((e) => e.request_body?.trigger);
2174
+ if (requestEntry?.request_body?.trigger) {
2175
+ return String(requestEntry.request_body.trigger) === trigger;
2223
2176
  }
2177
+ return false;
2224
2178
  }
2225
- } catch (error) {
2226
- console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
2227
- throw error;
2228
- } finally {
2229
- if (rl) {
2230
- rl.close();
2179
+ return true;
2180
+ }, "shouldIncludeInCompletedCalls");
2181
+ const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
2182
+ if (entry.method && !builder.method) builder.method = String(entry.method);
2183
+ if (entry.path && !builder.path) builder.path = String(entry.path);
2184
+ builder.entries.push(entry);
2185
+ if (builder.entries.length > config.maxEntriesPerTrace) {
2186
+ builder.entries.shift();
2231
2187
  }
2232
- if (stream) {
2233
- stream.close();
2188
+ if (shouldIncludeInCompletedCalls(builder)) {
2189
+ completedCalls.push(builder);
2190
+ if (limit && completedCalls.length > limit) {
2191
+ completedCalls.shift();
2192
+ }
2234
2193
  }
2235
- }
2236
- return logs;
2237
- }
2238
- __name(readLogsBySource, "readLogsBySource");
2239
- function parsePinoLog(line, source) {
2240
- try {
2241
- const pinoLog = JSON.parse(line);
2242
- const id = generateUUID();
2243
- return {
2244
- id,
2245
- level: mapPinoLevelToServerLogLevel(pinoLog.level),
2246
- timestamp: new Date(pinoLog.time).getTime(),
2247
- message: pinoLog.message || pinoLog.msg || "",
2248
- context: pinoLog.context || null,
2249
- traceId: pinoLog.trace_id || null,
2250
- userId: pinoLog.user_id || null,
2251
- appId: pinoLog.app_id || null,
2252
- tenantId: pinoLog.tenant_id || null,
2253
- stack: pinoLog.stack || null,
2254
- meta: {
2255
- pid: pinoLog.pid,
2256
- hostname: pinoLog.hostname,
2257
- path: pinoLog.path,
2258
- method: pinoLog.method,
2259
- statusCode: pinoLog.status_code,
2260
- durationMs: pinoLog.duration_ms,
2261
- ip: pinoLog.ip,
2262
- requestBody: pinoLog.request_body,
2263
- responseBody: pinoLog.response_body
2264
- },
2265
- tags: [
2266
- source
2267
- ]
2268
- };
2269
- } catch (error) {
2270
- return null;
2271
- }
2272
- }
2273
- __name(parsePinoLog, "parsePinoLog");
2274
- function parseStdLog(line, source) {
2275
- const id = generateUUID();
2276
- const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2277
- if (!match) {
2278
- return {
2279
- id,
2280
- level: "log",
2281
- timestamp: Date.now(),
2282
- message: line,
2283
- context: null,
2284
- traceId: null,
2285
- userId: null,
2286
- appId: null,
2287
- tenantId: null,
2288
- stack: null,
2289
- meta: null,
2290
- tags: [
2291
- source
2292
- ]
2293
- };
2294
- }
2295
- const [, timeStr, , content] = match;
2296
- let timestamp;
2297
- try {
2298
- const isoStr = timeStr.replace(" ", "T");
2299
- timestamp = new Date(isoStr).getTime();
2300
- if (isNaN(timestamp)) {
2301
- timestamp = Date.now();
2194
+ }, "updateBuilderMetadata");
2195
+ const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
2196
+ builder.hasCompleted = true;
2197
+ builder.endTime = entry.time;
2198
+ builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
2199
+ builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
2200
+ if (!builder.path && entry.path) {
2201
+ builder.path = String(entry.path);
2302
2202
  }
2303
- } catch (error) {
2304
- timestamp = Date.now();
2305
- }
2306
- const level = extractLogLevel(content);
2203
+ if (shouldIncludeInCompletedCalls(builder)) {
2204
+ completedCalls.push(builder);
2205
+ if (limit && completedCalls.length > limit) {
2206
+ completedCalls.shift();
2207
+ }
2208
+ }
2209
+ }, "handleRequestCompleted");
2210
+ const processLogEntry = /* @__PURE__ */ __name((entry) => {
2211
+ const { trace_id: traceId, message = "" } = entry;
2212
+ if (!traceId) return;
2213
+ let builder = builders.get(traceId);
2214
+ if (!builder) {
2215
+ builder = createTraceBuilder(traceId);
2216
+ builders.set(traceId, builder);
2217
+ }
2218
+ updateBuilderMetadata(builder, entry);
2219
+ if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
2220
+ handleRequestCompleted(builder, entry, message);
2221
+ }
2222
+ if (message.includes("HTTP request started") && !builder.startTime) {
2223
+ builder.startTime = entry.time;
2224
+ }
2225
+ }, "processLogEntry");
2226
+ const processLine = /* @__PURE__ */ __name((line) => {
2227
+ const entry = parseLogLine2(line);
2228
+ if (entry?.trace_id) {
2229
+ processLogEntry(entry);
2230
+ }
2231
+ }, "processLine");
2232
+ await readFileReverse(filePath, config.chunkSize, processLine);
2307
2233
  return {
2308
- id,
2309
- level,
2310
- timestamp,
2311
- message: content,
2312
- context: null,
2313
- traceId: null,
2314
- userId: null,
2315
- appId: null,
2316
- tenantId: null,
2317
- stack: null,
2318
- meta: null,
2319
- tags: [
2320
- source
2321
- ]
2234
+ page: 1,
2235
+ pageSize: completedCalls.length,
2236
+ totalCalls: completedCalls.length,
2237
+ totalPages: 1,
2238
+ calls: completedCalls.map((builder) => ({
2239
+ traceId: builder.traceId,
2240
+ method: builder.method,
2241
+ path: builder.path,
2242
+ startTime: builder.startTime,
2243
+ endTime: builder.endTime,
2244
+ statusCode: builder.statusCode,
2245
+ durationMs: builder.durationMs,
2246
+ entries: builder.entries.slice().reverse()
2247
+ }))
2322
2248
  };
2323
2249
  }
2324
- __name(parseStdLog, "parseStdLog");
2325
- function mapPinoLevelToServerLogLevel(pinoLevel) {
2326
- if (typeof pinoLevel === "string") {
2327
- const lower = pinoLevel.toLowerCase();
2328
- if (lower === "fatal") return "fatal";
2329
- if (lower === "error") return "error";
2330
- if (lower === "warn" || lower === "warning") return "warn";
2331
- if (lower === "info" || lower === "log") return "log";
2332
- if (lower === "debug") return "debug";
2333
- if (lower === "trace" || lower === "verbose") return "verbose";
2334
- return "log";
2335
- }
2336
- if (pinoLevel >= 60) return "fatal";
2337
- if (pinoLevel >= 50) return "error";
2338
- if (pinoLevel >= 40) return "warn";
2339
- if (pinoLevel >= 30) return "log";
2340
- if (pinoLevel >= 20) return "debug";
2341
- return "verbose";
2342
- }
2343
- __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2344
- function extractLogLevel(text) {
2345
- const lower = text.toLowerCase();
2346
- if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2347
- if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2348
- if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2349
- if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2350
- if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2351
- return "log";
2352
- }
2353
- __name(extractLogLevel, "extractLogLevel");
2354
- function generateUUID() {
2355
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2356
- const r = Math.random() * 16 | 0;
2357
- const v = c === "x" ? r : r & 3 | 8;
2358
- return v.toString(16);
2250
+ __name(readTriggerList, "readTriggerList");
2251
+ async function readTriggerDetail(filePath, path7, instanceID) {
2252
+ const exists = await fileExists(filePath);
2253
+ if (!exists) {
2254
+ return void 0;
2255
+ }
2256
+ const matches = [];
2257
+ const stream = (0, import_node_fs7.createReadStream)(filePath, {
2258
+ encoding: "utf8"
2359
2259
  });
2260
+ const rl = (0, import_node_readline.createInterface)({
2261
+ input: stream,
2262
+ crlfDelay: Infinity
2263
+ });
2264
+ for await (const line of rl) {
2265
+ const entry = parseLogLine2(line);
2266
+ if (!entry) continue;
2267
+ const isAutomationTrigger = entry.path?.endsWith(path7);
2268
+ const hasInstanceID = entry.message?.includes(`instanceID=${instanceID}`);
2269
+ if (!isAutomationTrigger || !hasInstanceID) continue;
2270
+ matches.push(entry);
2271
+ }
2272
+ rl.close();
2273
+ stream.close();
2274
+ return {
2275
+ instanceID,
2276
+ entries: matches
2277
+ };
2360
2278
  }
2361
- __name(generateUUID, "generateUUID");
2279
+ __name(readTriggerDetail, "readTriggerDetail");
2362
2280
 
2363
2281
  // src/middlewares/dev-logs/controller.ts
2364
2282
  function handleNotFound(res, filePath, message = "Log file not found") {
@@ -2452,32 +2370,58 @@ function createGetLogFileHandler(logDir) {
2452
2370
  };
2453
2371
  }
2454
2372
  __name(createGetLogFileHandler, "createGetLogFileHandler");
2455
- function createGetServerLogsHandler(logDir) {
2373
+ function createGetTriggerListHandler(logDir) {
2374
+ const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
2456
2375
  return async (req, res) => {
2457
- const limit = parseLimit(req.query.limit, 100, 1e3);
2458
- const offset = parsePositiveInt(req.query.offset, 0);
2459
- const levels = req.query.levels ? String(req.query.levels).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
2460
- const sources = req.query.sources ? String(req.query.sources).split(",").map((s) => s.trim()).filter(Boolean) : void 0;
2376
+ const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
2377
+ if (!trigger) {
2378
+ return res.status(400).json({
2379
+ message: "trigger is required"
2380
+ });
2381
+ }
2382
+ const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2383
+ const limit = parseLimit(req.query.limit, 10, 200);
2461
2384
  try {
2462
- const result = await readServerLogs(logDir, {
2463
- limit,
2464
- offset,
2465
- levels,
2466
- sources
2385
+ const result = await readTriggerList(traceLogPath, trigger, path7, limit);
2386
+ if (!result) {
2387
+ return handleNotFound(res, traceLogPath);
2388
+ }
2389
+ res.json({
2390
+ file: getRelativePath(traceLogPath),
2391
+ path: path7,
2392
+ ...result
2467
2393
  });
2394
+ } catch (error) {
2395
+ handleError(res, error, "Failed to read trace log");
2396
+ }
2397
+ };
2398
+ }
2399
+ __name(createGetTriggerListHandler, "createGetTriggerListHandler");
2400
+ function createGetTriggerDetailHandler(logDir) {
2401
+ const traceLogPath = (0, import_node_path7.join)(logDir, "server.log");
2402
+ return async (req, res) => {
2403
+ const instanceID = (req.params.instanceID || "").trim();
2404
+ if (!instanceID) {
2405
+ return res.status(400).json({
2406
+ message: "instanceID is required"
2407
+ });
2408
+ }
2409
+ const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2410
+ try {
2411
+ const result = await readTriggerDetail(traceLogPath, path7, instanceID);
2468
2412
  if (!result) {
2469
- return res.status(404).json({
2470
- message: "No server log files found",
2471
- hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
2472
- });
2413
+ return handleNotFound(res, traceLogPath);
2473
2414
  }
2474
- res.json(result);
2415
+ res.json({
2416
+ file: getRelativePath(traceLogPath),
2417
+ ...result
2418
+ });
2475
2419
  } catch (error) {
2476
- handleError(res, error, "Failed to read server logs");
2420
+ handleError(res, error, "Failed to read trace log");
2477
2421
  }
2478
2422
  };
2479
2423
  }
2480
- __name(createGetServerLogsHandler, "createGetServerLogsHandler");
2424
+ __name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
2481
2425
 
2482
2426
  // src/middlewares/dev-logs/health.controller.ts
2483
2427
  var import_node_http2 = __toESM(require("http"), 1);
@@ -2553,7 +2497,8 @@ function createDevLogRouter(options = {}) {
2553
2497
  router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
2554
2498
  router.get("/trace/recent", createGetRecentTracesHandler(logDir));
2555
2499
  router.get("/files/:fileName", createGetLogFileHandler(logDir));
2556
- router.get("/server-logs", createGetServerLogsHandler(logDir));
2500
+ router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
2501
+ router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
2557
2502
  router.get("/health", createHealthCheckHandler());
2558
2503
  return router;
2559
2504
  }
@@ -2578,8 +2523,13 @@ var DEV_LOGS_ROUTES = [
2578
2523
  },
2579
2524
  {
2580
2525
  method: "GET",
2581
- path: "/server-logs",
2582
- description: "Get server logs in ServerLog format (compatible with frontend)"
2526
+ path: "/trace/trigger/list",
2527
+ description: "Get trigger list (automation trigger) in trace.log"
2528
+ },
2529
+ {
2530
+ method: "GET",
2531
+ path: "/trace/trigger/:instanceID",
2532
+ description: "Get trigger detail (automation trigger) in trace.log by instanceID"
2583
2533
  }
2584
2534
  ];
2585
2535
  function createDevLogsMiddleware(options = {}) {