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

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,146 +2136,229 @@ async function readLogFilePage(filePath, page, pageSize) {
2136
2136
  };
2137
2137
  }
2138
2138
  __name(readLogFilePage, "readLogFilePage");
2139
- async function readTriggerList(filePath, trigger, path7, limit) {
2140
- if (!await fileExists(filePath)) {
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
+ }
2141
2164
  return void 0;
2142
2165
  }
2143
- const config = {
2144
- maxEntriesPerTrace: 10,
2145
- chunkSize: 64 * 1024
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
2146
2177
  };
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 === 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;
2176
- }
2177
- return false;
2178
- }
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();
2187
- }
2188
- if (shouldIncludeInCompletedCalls(builder)) {
2189
- completedCalls.push(builder);
2190
- if (limit && completedCalls.length > limit) {
2191
- completedCalls.shift();
2192
- }
2193
- }
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);
2202
- }
2203
- if (shouldIncludeInCompletedCalls(builder)) {
2204
- completedCalls.push(builder);
2205
- if (limit && completedCalls.length > limit) {
2206
- completedCalls.shift();
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) {
2207
2223
  }
2208
2224
  }
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;
2225
+ } catch (error) {
2226
+ console.error(`[readLogsBySource] Error reading ${filePath}:`, error);
2227
+ throw error;
2228
+ } finally {
2229
+ if (rl) {
2230
+ rl.close();
2224
2231
  }
2225
- }, "processLogEntry");
2226
- const processLine = /* @__PURE__ */ __name((line) => {
2227
- const entry = parseLogLine2(line);
2228
- if (entry?.trace_id) {
2229
- processLogEntry(entry);
2232
+ if (stream) {
2233
+ stream.close();
2230
2234
  }
2231
- }, "processLine");
2232
- await readFileReverse(filePath, config.chunkSize, processLine);
2233
- return {
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
- }))
2248
- };
2235
+ }
2236
+ return logs;
2249
2237
  }
2250
- __name(readTriggerList, "readTriggerList");
2251
- async function readTriggerDetail(filePath, instanceID) {
2252
- const exists = await fileExists(filePath);
2253
- if (!exists) {
2254
- return void 0;
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;
2255
2271
  }
2256
- const matches = [];
2257
- const stream = (0, import_node_fs7.createReadStream)(filePath, {
2258
- encoding: "utf8"
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 hasInstanceID = entry.message?.includes(`instanceID=${instanceID}`);
2268
- if (!hasInstanceID) continue;
2269
- matches.push(entry);
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
+ };
2270
2294
  }
2271
- rl.close();
2272
- stream.close();
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();
2302
+ }
2303
+ } catch (error) {
2304
+ timestamp = Date.now();
2305
+ }
2306
+ const level = extractLogLevel(content);
2273
2307
  return {
2274
- instanceID,
2275
- entries: matches
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
+ ]
2276
2322
  };
2277
2323
  }
2278
- __name(readTriggerDetail, "readTriggerDetail");
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);
2359
+ });
2360
+ }
2361
+ __name(generateUUID, "generateUUID");
2279
2362
 
2280
2363
  // src/middlewares/dev-logs/controller.ts
2281
2364
  function handleNotFound(res, filePath, message = "Log file not found") {
@@ -2369,57 +2452,32 @@ function createGetLogFileHandler(logDir) {
2369
2452
  };
2370
2453
  }
2371
2454
  __name(createGetLogFileHandler, "createGetLogFileHandler");
2372
- function createGetTriggerListHandler(logDir) {
2373
- const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
2455
+ function createGetServerLogsHandler(logDir) {
2374
2456
  return async (req, res) => {
2375
- const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
2376
- if (!trigger) {
2377
- return res.status(400).json({
2378
- message: "trigger is required"
2379
- });
2380
- }
2381
- const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2382
- const limit = parseLimit(req.query.limit, 10, 200);
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;
2383
2461
  try {
2384
- const result = await readTriggerList(traceLogPath, trigger, path7, limit);
2385
- if (!result) {
2386
- return handleNotFound(res, traceLogPath);
2387
- }
2388
- res.json({
2389
- file: getRelativePath(traceLogPath),
2390
- path: path7,
2391
- ...result
2462
+ const result = await readServerLogs(logDir, {
2463
+ limit,
2464
+ offset,
2465
+ levels,
2466
+ sources
2392
2467
  });
2393
- } catch (error) {
2394
- handleError(res, error, "Failed to read trace log");
2395
- }
2396
- };
2397
- }
2398
- __name(createGetTriggerListHandler, "createGetTriggerListHandler");
2399
- function createGetTriggerDetailHandler(logDir) {
2400
- const traceLogPath = (0, import_node_path7.join)(logDir, "server.log");
2401
- return async (req, res) => {
2402
- const instanceID = (req.params.instanceID || "").trim();
2403
- if (!instanceID) {
2404
- return res.status(400).json({
2405
- message: "instanceID is required"
2406
- });
2407
- }
2408
- try {
2409
- const result = await readTriggerDetail(traceLogPath, instanceID);
2410
2468
  if (!result) {
2411
- return handleNotFound(res, traceLogPath);
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
+ });
2412
2473
  }
2413
- res.json({
2414
- file: getRelativePath(traceLogPath),
2415
- ...result
2416
- });
2474
+ res.json(result);
2417
2475
  } catch (error) {
2418
- handleError(res, error, "Failed to read trace log");
2476
+ handleError(res, error, "Failed to read server logs");
2419
2477
  }
2420
2478
  };
2421
2479
  }
2422
- __name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
2480
+ __name(createGetServerLogsHandler, "createGetServerLogsHandler");
2423
2481
 
2424
2482
  // src/middlewares/dev-logs/health.controller.ts
2425
2483
  var import_node_http2 = __toESM(require("http"), 1);
@@ -2495,8 +2553,7 @@ function createDevLogRouter(options = {}) {
2495
2553
  router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
2496
2554
  router.get("/trace/recent", createGetRecentTracesHandler(logDir));
2497
2555
  router.get("/files/:fileName", createGetLogFileHandler(logDir));
2498
- router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
2499
- router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
2556
+ router.get("/server-logs", createGetServerLogsHandler(logDir));
2500
2557
  router.get("/health", createHealthCheckHandler());
2501
2558
  return router;
2502
2559
  }
@@ -2521,13 +2578,8 @@ var DEV_LOGS_ROUTES = [
2521
2578
  },
2522
2579
  {
2523
2580
  method: "GET",
2524
- path: "/trace/trigger/list",
2525
- description: "Get trigger list (automation trigger) in trace.log"
2526
- },
2527
- {
2528
- method: "GET",
2529
- path: "/trace/trigger/:instanceID",
2530
- description: "Get trigger detail (automation trigger) in trace.log by instanceID"
2581
+ path: "/server-logs",
2582
+ description: "Get server logs in ServerLog format (compatible with frontend)"
2531
2583
  }
2532
2584
  ];
2533
2585
  function createDevLogsMiddleware(options = {}) {