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

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.js CHANGED
@@ -2095,229 +2095,146 @@ async function readLogFilePage(filePath, page, pageSize) {
2095
2095
  };
2096
2096
  }
2097
2097
  __name(readLogFilePage, "readLogFilePage");
2098
- async function readServerLogs(logDir, options = {}) {
2099
- const limit = options.limit || 100;
2100
- const offset = options.offset || 0;
2101
- const sources = options.sources || [
2102
- "server",
2103
- "trace",
2104
- "server-std",
2105
- "client-std"
2106
- ];
2107
- const allLogs = [];
2108
- const errors = [];
2109
- for (const source of sources) {
2110
- try {
2111
- const logs = await readLogsBySource(logDir, source);
2112
- allLogs.push(...logs);
2113
- } catch (error) {
2114
- const errorMsg = `Failed to read ${source}: ${error instanceof Error ? error.message : String(error)}`;
2115
- errors.push(errorMsg);
2116
- console.warn(`[readServerLogs] ${errorMsg}`);
2117
- }
2118
- }
2119
- if (allLogs.length === 0) {
2120
- if (errors.length > 0) {
2121
- console.warn(`[readServerLogs] No logs found. Errors: ${errors.join(", ")}`);
2122
- }
2098
+ async function readTriggerList(filePath, trigger, path7, limit) {
2099
+ if (!await fileExists(filePath)) {
2123
2100
  return void 0;
2124
2101
  }
2125
- let filteredLogs = allLogs;
2126
- if (options.levels && options.levels.length > 0) {
2127
- filteredLogs = allLogs.filter((log) => options.levels.includes(log.level));
2128
- }
2129
- filteredLogs.sort((a, b) => b.timestamp - a.timestamp);
2130
- const total = filteredLogs.length;
2131
- const paginatedLogs = filteredLogs.slice(offset, offset + limit);
2132
- return {
2133
- logs: paginatedLogs,
2134
- total,
2135
- hasMore: offset + limit < total
2102
+ const config = {
2103
+ maxEntriesPerTrace: 10,
2104
+ chunkSize: 64 * 1024
2136
2105
  };
2137
- }
2138
- __name(readServerLogs, "readServerLogs");
2139
- async function readLogsBySource(logDir, source) {
2140
- const { join: join6 } = await import("path");
2141
- let filePath;
2142
- let parser;
2143
- if (source === "server") {
2144
- filePath = join6(logDir, "server.log");
2145
- parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
2146
- } else if (source === "trace") {
2147
- filePath = join6(logDir, "trace.log");
2148
- parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
2149
- } else if (source === "server-std") {
2150
- filePath = join6(logDir, "server.std.log");
2151
- parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
2152
- } else if (source === "client-std") {
2153
- filePath = join6(logDir, "client.std.log");
2154
- parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
2155
- } else {
2156
- console.warn(`[readLogsBySource] Unknown source: ${source}`);
2157
- return [];
2158
- }
2159
- if (!await fileExists(filePath)) {
2160
- console.warn(`[readLogsBySource] File not found: ${filePath}`);
2161
- return [];
2162
- }
2163
- const logs = [];
2164
- let stream = null;
2165
- let rl = null;
2166
- try {
2167
- stream = createReadStream(filePath, {
2168
- encoding: "utf8"
2169
- });
2170
- rl = createInterface({
2171
- input: stream,
2172
- crlfDelay: Infinity
2173
- });
2174
- for await (const line of rl) {
2175
- if (!line.trim()) continue;
2176
- try {
2177
- const log = parser(line);
2178
- if (log) {
2179
- logs.push(log);
2180
- }
2181
- } catch (parseError) {
2106
+ const builders = /* @__PURE__ */ new Map();
2107
+ const completedCalls = [];
2108
+ const createTraceBuilder = /* @__PURE__ */ __name((traceId) => ({
2109
+ traceId,
2110
+ entries: [],
2111
+ method: void 0,
2112
+ path: void 0,
2113
+ startTime: void 0,
2114
+ endTime: void 0,
2115
+ statusCode: void 0,
2116
+ durationMs: void 0,
2117
+ hasCompleted: false
2118
+ }), "createTraceBuilder");
2119
+ const shouldIncludeInCompletedCalls = /* @__PURE__ */ __name((builder) => {
2120
+ const alreadyAdded = completedCalls.some((call) => call.traceId === builder.traceId);
2121
+ if (alreadyAdded) {
2122
+ return false;
2123
+ }
2124
+ if (!builder.hasCompleted) {
2125
+ return false;
2126
+ }
2127
+ const isAutomationTrigger = builder.path === path7;
2128
+ if (!isAutomationTrigger) {
2129
+ return false;
2130
+ }
2131
+ if (trigger && builder.entries.length > 0) {
2132
+ const requestEntry = builder.entries.find((e) => e.request_body?.trigger);
2133
+ if (requestEntry?.request_body?.trigger) {
2134
+ return String(requestEntry.request_body.trigger) === trigger;
2182
2135
  }
2136
+ return false;
2183
2137
  }
2184
- } catch (error) {
2185
- console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
2186
- throw error;
2187
- } finally {
2188
- if (rl) {
2189
- rl.close();
2138
+ return true;
2139
+ }, "shouldIncludeInCompletedCalls");
2140
+ const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
2141
+ if (entry.method && !builder.method) builder.method = String(entry.method);
2142
+ if (entry.path && !builder.path) builder.path = String(entry.path);
2143
+ builder.entries.push(entry);
2144
+ if (builder.entries.length > config.maxEntriesPerTrace) {
2145
+ builder.entries.shift();
2190
2146
  }
2191
- if (stream) {
2192
- stream.close();
2147
+ if (shouldIncludeInCompletedCalls(builder)) {
2148
+ completedCalls.push(builder);
2149
+ if (limit && completedCalls.length > limit) {
2150
+ completedCalls.shift();
2151
+ }
2193
2152
  }
2194
- }
2195
- return logs;
2196
- }
2197
- __name(readLogsBySource, "readLogsBySource");
2198
- function parsePinoLog(line, source) {
2199
- try {
2200
- const pinoLog = JSON.parse(line);
2201
- const id = generateUUID();
2202
- return {
2203
- id,
2204
- level: mapPinoLevelToServerLogLevel(pinoLog.level),
2205
- timestamp: new Date(pinoLog.time).getTime(),
2206
- message: pinoLog.message || pinoLog.msg || "",
2207
- context: pinoLog.context || null,
2208
- traceId: pinoLog.trace_id || null,
2209
- userId: pinoLog.user_id || null,
2210
- appId: pinoLog.app_id || null,
2211
- tenantId: pinoLog.tenant_id || null,
2212
- stack: pinoLog.stack || null,
2213
- meta: {
2214
- pid: pinoLog.pid,
2215
- hostname: pinoLog.hostname,
2216
- path: pinoLog.path,
2217
- method: pinoLog.method,
2218
- statusCode: pinoLog.status_code,
2219
- durationMs: pinoLog.duration_ms,
2220
- ip: pinoLog.ip,
2221
- requestBody: pinoLog.request_body,
2222
- responseBody: pinoLog.response_body
2223
- },
2224
- tags: [
2225
- source
2226
- ]
2227
- };
2228
- } catch (error) {
2229
- return null;
2230
- }
2231
- }
2232
- __name(parsePinoLog, "parsePinoLog");
2233
- function parseStdLog(line, source) {
2234
- const id = generateUUID();
2235
- const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2236
- if (!match) {
2237
- return {
2238
- id,
2239
- level: "log",
2240
- timestamp: Date.now(),
2241
- message: line,
2242
- context: null,
2243
- traceId: null,
2244
- userId: null,
2245
- appId: null,
2246
- tenantId: null,
2247
- stack: null,
2248
- meta: null,
2249
- tags: [
2250
- source
2251
- ]
2252
- };
2253
- }
2254
- const [, timeStr, , content] = match;
2255
- let timestamp;
2256
- try {
2257
- const isoStr = timeStr.replace(" ", "T");
2258
- timestamp = new Date(isoStr).getTime();
2259
- if (isNaN(timestamp)) {
2260
- timestamp = Date.now();
2153
+ }, "updateBuilderMetadata");
2154
+ const handleRequestCompleted = /* @__PURE__ */ __name((builder, entry, message) => {
2155
+ builder.hasCompleted = true;
2156
+ builder.endTime = entry.time;
2157
+ builder.statusCode = extractNumber(message, /status_code:\s*(\d+)/);
2158
+ builder.durationMs = extractNumber(message, /duration_ms:\s*(\d+)/);
2159
+ if (!builder.path && entry.path) {
2160
+ builder.path = String(entry.path);
2261
2161
  }
2262
- } catch (error) {
2263
- timestamp = Date.now();
2264
- }
2265
- const level = extractLogLevel(content);
2162
+ if (shouldIncludeInCompletedCalls(builder)) {
2163
+ completedCalls.push(builder);
2164
+ if (limit && completedCalls.length > limit) {
2165
+ completedCalls.shift();
2166
+ }
2167
+ }
2168
+ }, "handleRequestCompleted");
2169
+ const processLogEntry = /* @__PURE__ */ __name((entry) => {
2170
+ const { trace_id: traceId, message = "" } = entry;
2171
+ if (!traceId) return;
2172
+ let builder = builders.get(traceId);
2173
+ if (!builder) {
2174
+ builder = createTraceBuilder(traceId);
2175
+ builders.set(traceId, builder);
2176
+ }
2177
+ updateBuilderMetadata(builder, entry);
2178
+ if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
2179
+ handleRequestCompleted(builder, entry, message);
2180
+ }
2181
+ if (message.includes("HTTP request started") && !builder.startTime) {
2182
+ builder.startTime = entry.time;
2183
+ }
2184
+ }, "processLogEntry");
2185
+ const processLine = /* @__PURE__ */ __name((line) => {
2186
+ const entry = parseLogLine2(line);
2187
+ if (entry?.trace_id) {
2188
+ processLogEntry(entry);
2189
+ }
2190
+ }, "processLine");
2191
+ await readFileReverse(filePath, config.chunkSize, processLine);
2266
2192
  return {
2267
- id,
2268
- level,
2269
- timestamp,
2270
- message: content,
2271
- context: null,
2272
- traceId: null,
2273
- userId: null,
2274
- appId: null,
2275
- tenantId: null,
2276
- stack: null,
2277
- meta: null,
2278
- tags: [
2279
- source
2280
- ]
2193
+ page: 1,
2194
+ pageSize: completedCalls.length,
2195
+ totalCalls: completedCalls.length,
2196
+ totalPages: 1,
2197
+ calls: completedCalls.map((builder) => ({
2198
+ traceId: builder.traceId,
2199
+ method: builder.method,
2200
+ path: builder.path,
2201
+ startTime: builder.startTime,
2202
+ endTime: builder.endTime,
2203
+ statusCode: builder.statusCode,
2204
+ durationMs: builder.durationMs,
2205
+ entries: builder.entries.slice().reverse()
2206
+ }))
2281
2207
  };
2282
2208
  }
2283
- __name(parseStdLog, "parseStdLog");
2284
- function mapPinoLevelToServerLogLevel(pinoLevel) {
2285
- if (typeof pinoLevel === "string") {
2286
- const lower = pinoLevel.toLowerCase();
2287
- if (lower === "fatal") return "fatal";
2288
- if (lower === "error") return "error";
2289
- if (lower === "warn" || lower === "warning") return "warn";
2290
- if (lower === "info" || lower === "log") return "log";
2291
- if (lower === "debug") return "debug";
2292
- if (lower === "trace" || lower === "verbose") return "verbose";
2293
- return "log";
2294
- }
2295
- if (pinoLevel >= 60) return "fatal";
2296
- if (pinoLevel >= 50) return "error";
2297
- if (pinoLevel >= 40) return "warn";
2298
- if (pinoLevel >= 30) return "log";
2299
- if (pinoLevel >= 20) return "debug";
2300
- return "verbose";
2301
- }
2302
- __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2303
- function extractLogLevel(text) {
2304
- const lower = text.toLowerCase();
2305
- if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2306
- if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2307
- if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2308
- if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2309
- if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2310
- return "log";
2311
- }
2312
- __name(extractLogLevel, "extractLogLevel");
2313
- function generateUUID() {
2314
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2315
- const r = Math.random() * 16 | 0;
2316
- const v = c === "x" ? r : r & 3 | 8;
2317
- return v.toString(16);
2209
+ __name(readTriggerList, "readTriggerList");
2210
+ async function readTriggerDetail(filePath, instanceID) {
2211
+ const exists = await fileExists(filePath);
2212
+ if (!exists) {
2213
+ return void 0;
2214
+ }
2215
+ const matches = [];
2216
+ const stream = createReadStream(filePath, {
2217
+ encoding: "utf8"
2318
2218
  });
2219
+ const rl = createInterface({
2220
+ input: stream,
2221
+ crlfDelay: Infinity
2222
+ });
2223
+ for await (const line of rl) {
2224
+ const entry = parseLogLine2(line);
2225
+ if (!entry) continue;
2226
+ const hasInstanceID = entry.message?.includes(`instanceID=${instanceID}`);
2227
+ if (!hasInstanceID) continue;
2228
+ matches.push(entry);
2229
+ }
2230
+ rl.close();
2231
+ stream.close();
2232
+ return {
2233
+ instanceID,
2234
+ entries: matches
2235
+ };
2319
2236
  }
2320
- __name(generateUUID, "generateUUID");
2237
+ __name(readTriggerDetail, "readTriggerDetail");
2321
2238
 
2322
2239
  // src/middlewares/dev-logs/controller.ts
2323
2240
  function handleNotFound(res, filePath, message = "Log file not found") {
@@ -2411,32 +2328,57 @@ function createGetLogFileHandler(logDir) {
2411
2328
  };
2412
2329
  }
2413
2330
  __name(createGetLogFileHandler, "createGetLogFileHandler");
2414
- function createGetServerLogsHandler(logDir) {
2331
+ function createGetTriggerListHandler(logDir) {
2332
+ const traceLogPath = join3(logDir, "trace.log");
2415
2333
  return async (req, res) => {
2416
- const limit = parseLimit(req.query.limit, 100, 1e3);
2417
- const offset = parsePositiveInt(req.query.offset, 0);
2418
- const levels = req.query.levels ? String(req.query.levels).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
2419
- const sources = req.query.sources ? String(req.query.sources).split(",").map((s) => s.trim()).filter(Boolean) : void 0;
2334
+ const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
2335
+ if (!trigger) {
2336
+ return res.status(400).json({
2337
+ message: "trigger is required"
2338
+ });
2339
+ }
2340
+ const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2341
+ const limit = parseLimit(req.query.limit, 10, 200);
2420
2342
  try {
2421
- const result = await readServerLogs(logDir, {
2422
- limit,
2423
- offset,
2424
- levels,
2425
- sources
2343
+ const result = await readTriggerList(traceLogPath, trigger, path7, limit);
2344
+ if (!result) {
2345
+ return handleNotFound(res, traceLogPath);
2346
+ }
2347
+ res.json({
2348
+ file: getRelativePath(traceLogPath),
2349
+ path: path7,
2350
+ ...result
2426
2351
  });
2352
+ } catch (error) {
2353
+ handleError(res, error, "Failed to read trace log");
2354
+ }
2355
+ };
2356
+ }
2357
+ __name(createGetTriggerListHandler, "createGetTriggerListHandler");
2358
+ function createGetTriggerDetailHandler(logDir) {
2359
+ const traceLogPath = join3(logDir, "server.log");
2360
+ return async (req, res) => {
2361
+ const instanceID = (req.params.instanceID || "").trim();
2362
+ if (!instanceID) {
2363
+ return res.status(400).json({
2364
+ message: "instanceID is required"
2365
+ });
2366
+ }
2367
+ try {
2368
+ const result = await readTriggerDetail(traceLogPath, instanceID);
2427
2369
  if (!result) {
2428
- return res.status(404).json({
2429
- message: "No server log files found",
2430
- hint: "Expected files: server.log, trace.log, server.std.log, client.std.log"
2431
- });
2370
+ return handleNotFound(res, traceLogPath);
2432
2371
  }
2433
- res.json(result);
2372
+ res.json({
2373
+ file: getRelativePath(traceLogPath),
2374
+ ...result
2375
+ });
2434
2376
  } catch (error) {
2435
- handleError(res, error, "Failed to read server logs");
2377
+ handleError(res, error, "Failed to read trace log");
2436
2378
  }
2437
2379
  };
2438
2380
  }
2439
- __name(createGetServerLogsHandler, "createGetServerLogsHandler");
2381
+ __name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
2440
2382
 
2441
2383
  // src/middlewares/dev-logs/health.controller.ts
2442
2384
  import http2 from "http";
@@ -2512,7 +2454,8 @@ function createDevLogRouter(options = {}) {
2512
2454
  router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
2513
2455
  router.get("/trace/recent", createGetRecentTracesHandler(logDir));
2514
2456
  router.get("/files/:fileName", createGetLogFileHandler(logDir));
2515
- router.get("/server-logs", createGetServerLogsHandler(logDir));
2457
+ router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
2458
+ router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
2516
2459
  router.get("/health", createHealthCheckHandler());
2517
2460
  return router;
2518
2461
  }
@@ -2537,8 +2480,13 @@ var DEV_LOGS_ROUTES = [
2537
2480
  },
2538
2481
  {
2539
2482
  method: "GET",
2540
- path: "/server-logs",
2541
- description: "Get server logs in ServerLog format (compatible with frontend)"
2483
+ path: "/trace/trigger/list",
2484
+ description: "Get trigger list (automation trigger) in trace.log"
2485
+ },
2486
+ {
2487
+ method: "GET",
2488
+ path: "/trace/trigger/:instanceID",
2489
+ description: "Get trigger detail (automation trigger) in trace.log by instanceID"
2542
2490
  }
2543
2491
  ];
2544
2492
  function createDevLogsMiddleware(options = {}) {