@lark-apaas/devtool-kits 1.2.11-alpha.1 → 1.2.11

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
@@ -1506,7 +1506,7 @@ function sendSimpleRedirect(req, res) {
1506
1506
  __name(sendSimpleRedirect, "sendSimpleRedirect");
1507
1507
 
1508
1508
  // src/middlewares/index.ts
1509
- var import_node_path10 = __toESM(require("path"), 1);
1509
+ var import_node_path9 = __toESM(require("path"), 1);
1510
1510
 
1511
1511
  // src/middlewares/openapi/router.ts
1512
1512
  var import_express = __toESM(require("express"), 1);
@@ -1850,8 +1850,8 @@ function hasSpecialPatterns(pattern) {
1850
1850
  return /[{*]/.test(pattern);
1851
1851
  }
1852
1852
  __name(hasSpecialPatterns, "hasSpecialPatterns");
1853
- function normalizePathForMatching(path7) {
1854
- return path7.replace(/\/+/g, "/").replace(/\/+$/, "");
1853
+ function normalizePathForMatching(path8) {
1854
+ return path8.replace(/\/+/g, "/").replace(/\/+$/, "");
1855
1855
  }
1856
1856
  __name(normalizePathForMatching, "normalizePathForMatching");
1857
1857
 
@@ -1949,194 +1949,10 @@ function serializeError(error) {
1949
1949
  __name(serializeError, "serializeError");
1950
1950
 
1951
1951
  // src/middlewares/dev-logs/controller.ts
1952
- var import_node_path8 = require("path");
1952
+ var import_node_path7 = require("path");
1953
1953
 
1954
- // src/middlewares/dev-logs/services/file-reader.ts
1954
+ // src/middlewares/dev-logs/services.ts
1955
1955
  var import_node_fs7 = require("fs");
1956
- async function readFileReverse(filePath, chunkSize, processLine) {
1957
- const handle = await import_node_fs7.promises.open(filePath, "r");
1958
- try {
1959
- const stats = await handle.stat();
1960
- let position = stats.size;
1961
- let remainder = "";
1962
- while (position > 0) {
1963
- const length = Math.min(chunkSize, position);
1964
- position -= length;
1965
- const buffer = Buffer.alloc(length);
1966
- await handle.read(buffer, 0, length, position);
1967
- let chunk = buffer.toString("utf8");
1968
- if (remainder) {
1969
- chunk += remainder;
1970
- remainder = "";
1971
- }
1972
- const lines = chunk.split("\n");
1973
- remainder = lines.shift() ?? "";
1974
- for (let i = lines.length - 1; i >= 0; i -= 1) {
1975
- if (lines[i]) {
1976
- processLine(lines[i]);
1977
- }
1978
- }
1979
- }
1980
- if (remainder) {
1981
- processLine(remainder);
1982
- }
1983
- } finally {
1984
- await handle.close();
1985
- }
1986
- }
1987
- __name(readFileReverse, "readFileReverse");
1988
- function buildPaginatedResponse(items, page, pageSize) {
1989
- const totalItems = items.length;
1990
- const totalPages = totalItems === 0 ? 0 : Math.ceil(totalItems / pageSize);
1991
- const startIndex = (page - 1) * pageSize;
1992
- const endIndex = Math.min(startIndex + pageSize, totalItems);
1993
- const pagedItems = items.slice(startIndex, endIndex).map((builder) => ({
1994
- traceId: builder.traceId,
1995
- method: builder.method,
1996
- path: builder.path,
1997
- startTime: builder.startTime,
1998
- endTime: builder.endTime,
1999
- statusCode: builder.statusCode,
2000
- durationMs: builder.durationMs,
2001
- entries: builder.entries.slice().reverse()
2002
- }));
2003
- return {
2004
- page,
2005
- pageSize,
2006
- totalCalls: totalItems,
2007
- totalPages,
2008
- calls: pagedItems
2009
- };
2010
- }
2011
- __name(buildPaginatedResponse, "buildPaginatedResponse");
2012
-
2013
- // src/middlewares/dev-logs/services/parsers.ts
2014
- function generateUUID() {
2015
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2016
- const r = Math.random() * 16 | 0;
2017
- const v = c === "x" ? r : r & 3 | 8;
2018
- return v.toString(16);
2019
- });
2020
- }
2021
- __name(generateUUID, "generateUUID");
2022
- function mapPinoLevelToServerLogLevel(pinoLevel) {
2023
- if (typeof pinoLevel === "string") {
2024
- const lower = pinoLevel.toLowerCase();
2025
- if (lower === "fatal") return "fatal";
2026
- if (lower === "error") return "error";
2027
- if (lower === "warn" || lower === "warning") return "warn";
2028
- if (lower === "info" || lower === "log") return "log";
2029
- if (lower === "debug") return "debug";
2030
- if (lower === "trace" || lower === "verbose") return "verbose";
2031
- return "log";
2032
- }
2033
- if (pinoLevel >= 60) return "fatal";
2034
- if (pinoLevel >= 50) return "error";
2035
- if (pinoLevel >= 40) return "warn";
2036
- if (pinoLevel >= 30) return "log";
2037
- if (pinoLevel >= 20) return "debug";
2038
- return "verbose";
2039
- }
2040
- __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2041
- function extractLogLevel(text) {
2042
- const lower = text.toLowerCase();
2043
- if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2044
- if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2045
- if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2046
- if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2047
- if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2048
- return "log";
2049
- }
2050
- __name(extractLogLevel, "extractLogLevel");
2051
- function parsePinoLog(line, source) {
2052
- try {
2053
- const pinoLog = JSON.parse(line);
2054
- const id = generateUUID();
2055
- return {
2056
- id,
2057
- level: mapPinoLevelToServerLogLevel(pinoLog.level),
2058
- timestamp: new Date(pinoLog.time).getTime(),
2059
- message: pinoLog.message || pinoLog.msg || "",
2060
- context: pinoLog.context || null,
2061
- traceId: pinoLog.trace_id || null,
2062
- userId: pinoLog.user_id || null,
2063
- appId: pinoLog.app_id || null,
2064
- tenantId: pinoLog.tenant_id || null,
2065
- stack: pinoLog.stack || null,
2066
- meta: {
2067
- pid: pinoLog.pid,
2068
- hostname: pinoLog.hostname,
2069
- path: pinoLog.path,
2070
- method: pinoLog.method,
2071
- statusCode: pinoLog.status_code,
2072
- durationMs: pinoLog.duration_ms,
2073
- ip: pinoLog.ip,
2074
- requestBody: pinoLog.request_body,
2075
- responseBody: pinoLog.response_body
2076
- },
2077
- tags: [
2078
- source
2079
- ]
2080
- };
2081
- } catch (error) {
2082
- return null;
2083
- }
2084
- }
2085
- __name(parsePinoLog, "parsePinoLog");
2086
- function parseStdLog(line, source) {
2087
- const id = generateUUID();
2088
- const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2089
- if (!match) {
2090
- return {
2091
- id,
2092
- level: "log",
2093
- timestamp: Date.now(),
2094
- message: line,
2095
- context: null,
2096
- traceId: null,
2097
- userId: null,
2098
- appId: null,
2099
- tenantId: null,
2100
- stack: null,
2101
- meta: null,
2102
- tags: [
2103
- source
2104
- ]
2105
- };
2106
- }
2107
- const [, timeStr, , content] = match;
2108
- let timestamp;
2109
- try {
2110
- const isoStr = timeStr.replace(" ", "T");
2111
- timestamp = new Date(isoStr).getTime();
2112
- if (isNaN(timestamp)) {
2113
- timestamp = Date.now();
2114
- }
2115
- } catch (error) {
2116
- timestamp = Date.now();
2117
- }
2118
- const level = extractLogLevel(content);
2119
- return {
2120
- id,
2121
- level,
2122
- timestamp,
2123
- message: content,
2124
- context: null,
2125
- traceId: null,
2126
- userId: null,
2127
- appId: null,
2128
- tenantId: null,
2129
- stack: null,
2130
- meta: null,
2131
- tags: [
2132
- source
2133
- ]
2134
- };
2135
- }
2136
- __name(parseStdLog, "parseStdLog");
2137
-
2138
- // src/middlewares/dev-logs/services/trace.service.ts
2139
- var import_node_fs8 = require("fs");
2140
1956
  var import_node_readline = require("readline");
2141
1957
  async function readLogEntriesByTrace(filePath, traceId, limit) {
2142
1958
  const exists = await fileExists(filePath);
@@ -2144,7 +1960,7 @@ async function readLogEntriesByTrace(filePath, traceId, limit) {
2144
1960
  return void 0;
2145
1961
  }
2146
1962
  const matches = [];
2147
- const stream = (0, import_node_fs8.createReadStream)(filePath, {
1963
+ const stream = (0, import_node_fs7.createReadStream)(filePath, {
2148
1964
  encoding: "utf8"
2149
1965
  });
2150
1966
  const rl = (0, import_node_readline.createInterface)({
@@ -2235,6 +2051,62 @@ async function readRecentTraceCalls(filePath, page, pageSize, pathFilter, method
2235
2051
  return buildPaginatedResponse(completedCalls, page, pageSize);
2236
2052
  }
2237
2053
  __name(readRecentTraceCalls, "readRecentTraceCalls");
2054
+ async function readFileReverse(filePath, chunkSize, processLine) {
2055
+ const handle = await import_node_fs7.promises.open(filePath, "r");
2056
+ try {
2057
+ const stats = await handle.stat();
2058
+ let position = stats.size;
2059
+ let remainder = "";
2060
+ while (position > 0) {
2061
+ const length = Math.min(chunkSize, position);
2062
+ position -= length;
2063
+ const buffer = Buffer.alloc(length);
2064
+ await handle.read(buffer, 0, length, position);
2065
+ let chunk = buffer.toString("utf8");
2066
+ if (remainder) {
2067
+ chunk += remainder;
2068
+ remainder = "";
2069
+ }
2070
+ const lines = chunk.split("\n");
2071
+ remainder = lines.shift() ?? "";
2072
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
2073
+ if (lines[i]) {
2074
+ processLine(lines[i]);
2075
+ }
2076
+ }
2077
+ }
2078
+ if (remainder) {
2079
+ processLine(remainder);
2080
+ }
2081
+ } finally {
2082
+ await handle.close();
2083
+ }
2084
+ }
2085
+ __name(readFileReverse, "readFileReverse");
2086
+ function buildPaginatedResponse(items, page, pageSize) {
2087
+ const totalItems = items.length;
2088
+ const totalPages = totalItems === 0 ? 0 : Math.ceil(totalItems / pageSize);
2089
+ const startIndex = (page - 1) * pageSize;
2090
+ const endIndex = Math.min(startIndex + pageSize, totalItems);
2091
+ const pagedItems = items.slice(startIndex, endIndex).map((builder) => ({
2092
+ traceId: builder.traceId,
2093
+ method: builder.method,
2094
+ path: builder.path,
2095
+ startTime: builder.startTime,
2096
+ endTime: builder.endTime,
2097
+ statusCode: builder.statusCode,
2098
+ durationMs: builder.durationMs,
2099
+ entries: builder.entries.slice().reverse()
2100
+ }));
2101
+ return {
2102
+ page,
2103
+ pageSize,
2104
+ totalCalls: totalItems,
2105
+ totalPages,
2106
+ calls: pagedItems
2107
+ };
2108
+ }
2109
+ __name(buildPaginatedResponse, "buildPaginatedResponse");
2238
2110
  async function readLogFilePage(filePath, page, pageSize) {
2239
2111
  if (!await fileExists(filePath)) {
2240
2112
  return void 0;
@@ -2242,7 +2114,7 @@ async function readLogFilePage(filePath, page, pageSize) {
2242
2114
  const capacity = page * pageSize;
2243
2115
  const buffer = [];
2244
2116
  let totalLines = 0;
2245
- const stream = (0, import_node_fs8.createReadStream)(filePath, {
2117
+ const stream = (0, import_node_fs7.createReadStream)(filePath, {
2246
2118
  encoding: "utf8"
2247
2119
  });
2248
2120
  const rl = (0, import_node_readline.createInterface)({
@@ -2290,11 +2162,6 @@ async function readLogFilePage(filePath, page, pageSize) {
2290
2162
  };
2291
2163
  }
2292
2164
  __name(readLogFilePage, "readLogFilePage");
2293
-
2294
- // src/middlewares/dev-logs/services/server-log.service.ts
2295
- var import_node_fs9 = require("fs");
2296
- var import_node_readline2 = require("readline");
2297
- var import_node_path7 = require("path");
2298
2165
  async function readServerLogs(logDir, options = {}) {
2299
2166
  const limit = options.limit || 100;
2300
2167
  const offset = options.offset || 0;
@@ -2337,19 +2204,20 @@ async function readServerLogs(logDir, options = {}) {
2337
2204
  }
2338
2205
  __name(readServerLogs, "readServerLogs");
2339
2206
  async function readLogsBySource(logDir, source) {
2207
+ const { join: join7 } = await import("path");
2340
2208
  let filePath;
2341
2209
  let parser;
2342
2210
  if (source === "server") {
2343
- filePath = (0, import_node_path7.join)(logDir, "server.log");
2211
+ filePath = join7(logDir, "server.log");
2344
2212
  parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
2345
2213
  } else if (source === "trace") {
2346
- filePath = (0, import_node_path7.join)(logDir, "trace.log");
2214
+ filePath = join7(logDir, "trace.log");
2347
2215
  parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
2348
2216
  } else if (source === "server-std") {
2349
- filePath = (0, import_node_path7.join)(logDir, "server.std.log");
2217
+ filePath = join7(logDir, "server.std.log");
2350
2218
  parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
2351
2219
  } else if (source === "client-std") {
2352
- filePath = (0, import_node_path7.join)(logDir, "client.std.log");
2220
+ filePath = join7(logDir, "client.std.log");
2353
2221
  parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
2354
2222
  } else {
2355
2223
  console.warn(`[readLogsBySource] Unknown source: ${source}`);
@@ -2363,10 +2231,10 @@ async function readLogsBySource(logDir, source) {
2363
2231
  let stream = null;
2364
2232
  let rl = null;
2365
2233
  try {
2366
- stream = (0, import_node_fs9.createReadStream)(filePath, {
2234
+ stream = (0, import_node_fs7.createReadStream)(filePath, {
2367
2235
  encoding: "utf8"
2368
2236
  });
2369
- rl = (0, import_node_readline2.createInterface)({
2237
+ rl = (0, import_node_readline.createInterface)({
2370
2238
  input: stream,
2371
2239
  crlfDelay: Infinity
2372
2240
  });
@@ -2394,11 +2262,130 @@ async function readLogsBySource(logDir, source) {
2394
2262
  return logs;
2395
2263
  }
2396
2264
  __name(readLogsBySource, "readLogsBySource");
2397
-
2398
- // src/middlewares/dev-logs/services/trigger.service.ts
2399
- var import_node_fs10 = require("fs");
2400
- var import_node_readline3 = require("readline");
2401
- async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2265
+ function parsePinoLog(line, source) {
2266
+ try {
2267
+ const pinoLog = JSON.parse(line);
2268
+ const id = generateUUID();
2269
+ return {
2270
+ id,
2271
+ level: mapPinoLevelToServerLogLevel(pinoLog.level),
2272
+ timestamp: new Date(pinoLog.time).getTime(),
2273
+ message: pinoLog.message || pinoLog.msg || "",
2274
+ context: pinoLog.context || null,
2275
+ traceId: pinoLog.trace_id || null,
2276
+ userId: pinoLog.user_id || null,
2277
+ appId: pinoLog.app_id || null,
2278
+ tenantId: pinoLog.tenant_id || null,
2279
+ stack: pinoLog.stack || null,
2280
+ meta: {
2281
+ pid: pinoLog.pid,
2282
+ hostname: pinoLog.hostname,
2283
+ path: pinoLog.path,
2284
+ method: pinoLog.method,
2285
+ statusCode: pinoLog.status_code,
2286
+ durationMs: pinoLog.duration_ms,
2287
+ ip: pinoLog.ip,
2288
+ requestBody: pinoLog.request_body,
2289
+ responseBody: pinoLog.response_body
2290
+ },
2291
+ tags: [
2292
+ source
2293
+ ]
2294
+ };
2295
+ } catch (error) {
2296
+ return null;
2297
+ }
2298
+ }
2299
+ __name(parsePinoLog, "parsePinoLog");
2300
+ function parseStdLog(line, source) {
2301
+ const id = generateUUID();
2302
+ const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2303
+ if (!match) {
2304
+ return {
2305
+ id,
2306
+ level: "log",
2307
+ timestamp: Date.now(),
2308
+ message: line,
2309
+ context: null,
2310
+ traceId: null,
2311
+ userId: null,
2312
+ appId: null,
2313
+ tenantId: null,
2314
+ stack: null,
2315
+ meta: null,
2316
+ tags: [
2317
+ source
2318
+ ]
2319
+ };
2320
+ }
2321
+ const [, timeStr, , content] = match;
2322
+ let timestamp;
2323
+ try {
2324
+ const isoStr = timeStr.replace(" ", "T");
2325
+ timestamp = new Date(isoStr).getTime();
2326
+ if (isNaN(timestamp)) {
2327
+ timestamp = Date.now();
2328
+ }
2329
+ } catch (error) {
2330
+ timestamp = Date.now();
2331
+ }
2332
+ const level = extractLogLevel(content);
2333
+ return {
2334
+ id,
2335
+ level,
2336
+ timestamp,
2337
+ message: content,
2338
+ context: null,
2339
+ traceId: null,
2340
+ userId: null,
2341
+ appId: null,
2342
+ tenantId: null,
2343
+ stack: null,
2344
+ meta: null,
2345
+ tags: [
2346
+ source
2347
+ ]
2348
+ };
2349
+ }
2350
+ __name(parseStdLog, "parseStdLog");
2351
+ function mapPinoLevelToServerLogLevel(pinoLevel) {
2352
+ if (typeof pinoLevel === "string") {
2353
+ const lower = pinoLevel.toLowerCase();
2354
+ if (lower === "fatal") return "fatal";
2355
+ if (lower === "error") return "error";
2356
+ if (lower === "warn" || lower === "warning") return "warn";
2357
+ if (lower === "info" || lower === "log") return "log";
2358
+ if (lower === "debug") return "debug";
2359
+ if (lower === "trace" || lower === "verbose") return "verbose";
2360
+ return "log";
2361
+ }
2362
+ if (pinoLevel >= 60) return "fatal";
2363
+ if (pinoLevel >= 50) return "error";
2364
+ if (pinoLevel >= 40) return "warn";
2365
+ if (pinoLevel >= 30) return "log";
2366
+ if (pinoLevel >= 20) return "debug";
2367
+ return "verbose";
2368
+ }
2369
+ __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2370
+ function extractLogLevel(text) {
2371
+ const lower = text.toLowerCase();
2372
+ if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2373
+ if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2374
+ if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2375
+ if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2376
+ if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2377
+ return "log";
2378
+ }
2379
+ __name(extractLogLevel, "extractLogLevel");
2380
+ function generateUUID() {
2381
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2382
+ const r = Math.random() * 16 | 0;
2383
+ const v = c === "x" ? r : r & 3 | 8;
2384
+ return v.toString(16);
2385
+ });
2386
+ }
2387
+ __name(generateUUID, "generateUUID");
2388
+ async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2402
2389
  if (!await fileExists(filePath)) {
2403
2390
  return void 0;
2404
2391
  }
@@ -2424,7 +2411,7 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2424
2411
  if (alreadyAdded) {
2425
2412
  return false;
2426
2413
  }
2427
- const isAutomationTrigger = builder.path?.endsWith(path7);
2414
+ const isAutomationTrigger = builder.path?.endsWith(path8);
2428
2415
  if (!isAutomationTrigger) {
2429
2416
  return false;
2430
2417
  }
@@ -2478,176 +2465,64 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
2478
2465
  if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
2479
2466
  handleRequestCompleted(builder, entry, message);
2480
2467
  }
2481
- if (message.includes("HTTP request started") && !builder.startTime) {
2482
- builder.startTime = entry.time;
2483
- }
2484
- }, "processLogEntry");
2485
- const processLine = /* @__PURE__ */ __name((line) => {
2486
- const entry = parseLogLine2(line);
2487
- if (entry?.trace_id) {
2488
- processLogEntry(entry);
2489
- }
2490
- }, "processLine");
2491
- await readFileReverse(filePath, config.chunkSize, processLine);
2492
- return {
2493
- page: 1,
2494
- pageSize: completedCalls.length,
2495
- totalCalls: completedCalls.length,
2496
- totalPages: 1,
2497
- calls: completedCalls.map((builder) => ({
2498
- traceId: builder.traceId,
2499
- method: builder.method,
2500
- path: builder.path,
2501
- startTime: builder.startTime,
2502
- endTime: builder.endTime,
2503
- statusCode: builder.statusCode,
2504
- durationMs: builder.durationMs,
2505
- entries: builder.entries.slice().reverse()
2506
- }))
2507
- };
2508
- }
2509
- __name(readTriggerList, "readTriggerList");
2510
- async function readTriggerDetail(filePath, path7, instanceID) {
2511
- const exists = await fileExists(filePath);
2512
- if (!exists) {
2513
- return void 0;
2514
- }
2515
- const matches = [];
2516
- const stream = (0, import_node_fs10.createReadStream)(filePath, {
2517
- encoding: "utf8"
2518
- });
2519
- const rl = (0, import_node_readline3.createInterface)({
2520
- input: stream,
2521
- crlfDelay: Infinity
2522
- });
2523
- for await (const line of rl) {
2524
- const entry = parseLogLine2(line);
2525
- if (!entry) continue;
2526
- const isAutomationTrigger = entry.path?.endsWith(path7);
2527
- const hasInstanceID = entry.instance_id === instanceID && entry.trigger;
2528
- if (!isAutomationTrigger || !hasInstanceID) continue;
2529
- matches.push(entry);
2530
- }
2531
- rl.close();
2532
- stream.close();
2533
- return {
2534
- instanceID,
2535
- entries: matches
2536
- };
2537
- }
2538
- __name(readTriggerDetail, "readTriggerDetail");
2539
-
2540
- // src/middlewares/dev-logs/services/capability.service.ts
2541
- async function readCapabilityTraceList(filePath, capabilityId, limit) {
2542
- if (!await fileExists(filePath)) {
2543
- return void 0;
2544
- }
2545
- const config = {
2546
- chunkSize: 64 * 1024
2547
- };
2548
- const builders = /* @__PURE__ */ new Map();
2549
- const completedTraces = [];
2550
- const createCapabilityTraceBuilder = /* @__PURE__ */ __name((traceId, capId) => ({
2551
- traceId,
2552
- capabilityId: capId,
2553
- hasCompleted: false,
2554
- hasStartEntry: false
2555
- }), "createCapabilityTraceBuilder");
2556
- const shouldIncludeInCompletedTraces = /* @__PURE__ */ __name((builder) => {
2557
- const alreadyAdded = completedTraces.some((trace) => trace.traceId === builder.traceId);
2558
- if (alreadyAdded) {
2559
- return false;
2560
- }
2561
- return builder.capabilityId === capabilityId;
2562
- }, "shouldIncludeInCompletedTraces");
2563
- const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
2564
- if (entry.plugin_key && !builder.pluginKey) {
2565
- builder.pluginKey = String(entry.plugin_key);
2566
- }
2567
- if (entry.action && !builder.action) {
2568
- builder.action = String(entry.action);
2569
- }
2570
- const message = entry.message || "";
2571
- if (message.includes("Executing capability") && !builder.hasStartEntry) {
2572
- builder.hasStartEntry = true;
2573
- builder.startTime = entry.time;
2574
- if (entry.input) {
2575
- builder.input = String(entry.input);
2576
- }
2577
- }
2578
- if (message.includes("executed successfully")) {
2579
- builder.hasCompleted = true;
2580
- builder.endTime = entry.time;
2581
- builder.status = "success";
2582
- if (entry.output) {
2583
- builder.output = String(entry.output);
2584
- }
2585
- if (entry.duration_ms) {
2586
- builder.durationMs = Number(entry.duration_ms);
2587
- }
2588
- if (shouldIncludeInCompletedTraces(builder)) {
2589
- completedTraces.push(builder);
2590
- }
2591
- }
2592
- if (message.includes("execution failed")) {
2593
- builder.hasCompleted = true;
2594
- builder.endTime = entry.time;
2595
- builder.status = "failed";
2596
- if (entry.error) {
2597
- builder.error = {
2598
- message: String(entry.error)
2599
- };
2600
- }
2601
- if (entry.duration_ms) {
2602
- builder.durationMs = Number(entry.duration_ms);
2603
- }
2604
- if (shouldIncludeInCompletedTraces(builder)) {
2605
- completedTraces.push(builder);
2606
- }
2607
- }
2608
- }, "updateBuilderMetadata");
2609
- const processLogEntry = /* @__PURE__ */ __name((entry) => {
2610
- const { trace_id: traceId, capability_id: capId } = entry;
2611
- if (!traceId || !capId || capId !== capabilityId) return;
2612
- let builder = builders.get(traceId);
2613
- if (!builder) {
2614
- builder = createCapabilityTraceBuilder(traceId, capId);
2615
- builders.set(traceId, builder);
2616
- }
2617
- updateBuilderMetadata(builder, entry);
2468
+ if (message.includes("HTTP request started") && !builder.startTime) {
2469
+ builder.startTime = entry.time;
2470
+ }
2618
2471
  }, "processLogEntry");
2619
2472
  const processLine = /* @__PURE__ */ __name((line) => {
2620
2473
  const entry = parseLogLine2(line);
2621
- if (entry?.capability_id) {
2474
+ if (entry?.trace_id) {
2622
2475
  processLogEntry(entry);
2623
2476
  }
2624
2477
  }, "processLine");
2625
2478
  await readFileReverse(filePath, config.chunkSize, processLine);
2626
- completedTraces.sort((a, b) => {
2627
- const timeA = a.endTime ? new Date(a.endTime).getTime() : 0;
2628
- const timeB = b.endTime ? new Date(b.endTime).getTime() : 0;
2629
- return timeB - timeA;
2630
- });
2631
- const limitedTraces = limit ? completedTraces.slice(0, limit) : completedTraces;
2632
2479
  return {
2633
- capabilityId,
2634
- totalTraces: limitedTraces.length,
2635
- traces: limitedTraces.map((builder) => ({
2480
+ page: 1,
2481
+ pageSize: completedCalls.length,
2482
+ totalCalls: completedCalls.length,
2483
+ totalPages: 1,
2484
+ calls: completedCalls.map((builder) => ({
2636
2485
  traceId: builder.traceId,
2637
- capabilityId: builder.capabilityId,
2638
- pluginKey: builder.pluginKey,
2639
- action: builder.action,
2486
+ method: builder.method,
2487
+ path: builder.path,
2640
2488
  startTime: builder.startTime,
2641
2489
  endTime: builder.endTime,
2490
+ statusCode: builder.statusCode,
2642
2491
  durationMs: builder.durationMs,
2643
- status: builder.status || "failed",
2644
- input: builder.input,
2645
- output: builder.output,
2646
- error: builder.error
2492
+ entries: builder.entries.slice().reverse()
2647
2493
  }))
2648
2494
  };
2649
2495
  }
2650
- __name(readCapabilityTraceList, "readCapabilityTraceList");
2496
+ __name(readTriggerList, "readTriggerList");
2497
+ async function readTriggerDetail(filePath, path8, instanceID) {
2498
+ const exists = await fileExists(filePath);
2499
+ if (!exists) {
2500
+ return void 0;
2501
+ }
2502
+ const matches = [];
2503
+ const stream = (0, import_node_fs7.createReadStream)(filePath, {
2504
+ encoding: "utf8"
2505
+ });
2506
+ const rl = (0, import_node_readline.createInterface)({
2507
+ input: stream,
2508
+ crlfDelay: Infinity
2509
+ });
2510
+ for await (const line of rl) {
2511
+ const entry = parseLogLine2(line);
2512
+ if (!entry) continue;
2513
+ const isAutomationTrigger = entry.path?.endsWith(path8);
2514
+ const hasInstanceID = entry.instance_id === instanceID && entry.trigger;
2515
+ if (!isAutomationTrigger || !hasInstanceID) continue;
2516
+ matches.push(entry);
2517
+ }
2518
+ rl.close();
2519
+ stream.close();
2520
+ return {
2521
+ instanceID,
2522
+ entries: matches
2523
+ };
2524
+ }
2525
+ __name(readTriggerDetail, "readTriggerDetail");
2651
2526
 
2652
2527
  // src/middlewares/dev-logs/controller.ts
2653
2528
  function handleNotFound(res, filePath, message = "Log file not found") {
@@ -2664,7 +2539,7 @@ function handleError(res, error, message = "Failed to read log file") {
2664
2539
  }
2665
2540
  __name(handleError, "handleError");
2666
2541
  function createGetTraceEntriesHandler(logDir) {
2667
- const appLogPath = (0, import_node_path8.join)(logDir, "server.log");
2542
+ const appLogPath = (0, import_node_path7.join)(logDir, "server.log");
2668
2543
  return async (req, res) => {
2669
2544
  const traceId = (req.params.traceId || "").trim();
2670
2545
  if (!traceId) {
@@ -2691,7 +2566,7 @@ function createGetTraceEntriesHandler(logDir) {
2691
2566
  }
2692
2567
  __name(createGetTraceEntriesHandler, "createGetTraceEntriesHandler");
2693
2568
  function createGetRecentTracesHandler(logDir) {
2694
- const traceLogPath = (0, import_node_path8.join)(logDir, "trace.log");
2569
+ const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
2695
2570
  return async (req, res) => {
2696
2571
  const page = parsePositiveInt(req.query.page, 1);
2697
2572
  const pageSize = parseLimit(req.query.pageSize, 10, 100);
@@ -2768,7 +2643,7 @@ function createGetServerLogsHandler(logDir) {
2768
2643
  }
2769
2644
  __name(createGetServerLogsHandler, "createGetServerLogsHandler");
2770
2645
  function createGetTriggerListHandler(logDir) {
2771
- const traceLogPath = (0, import_node_path8.join)(logDir, "trace.log");
2646
+ const traceLogPath = (0, import_node_path7.join)(logDir, "trace.log");
2772
2647
  return async (req, res) => {
2773
2648
  const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
2774
2649
  if (!trigger) {
@@ -2777,16 +2652,16 @@ function createGetTriggerListHandler(logDir) {
2777
2652
  });
2778
2653
  }
2779
2654
  const triggerID = typeof req.query.triggerID === "string" ? req.query.triggerID.trim() : void 0;
2780
- const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2655
+ const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2781
2656
  const limit = parseLimit(req.query.limit, 10, 200);
2782
2657
  try {
2783
- const result = await readTriggerList(traceLogPath, trigger, path7, limit, triggerID);
2658
+ const result = await readTriggerList(traceLogPath, trigger, path8, limit, triggerID);
2784
2659
  if (!result) {
2785
2660
  return handleNotFound(res, traceLogPath);
2786
2661
  }
2787
2662
  res.json({
2788
2663
  file: getRelativePath(traceLogPath),
2789
- path: path7,
2664
+ path: path8,
2790
2665
  ...result
2791
2666
  });
2792
2667
  } catch (error) {
@@ -2796,7 +2671,7 @@ function createGetTriggerListHandler(logDir) {
2796
2671
  }
2797
2672
  __name(createGetTriggerListHandler, "createGetTriggerListHandler");
2798
2673
  function createGetTriggerDetailHandler(logDir) {
2799
- const traceLogPath = (0, import_node_path8.join)(logDir, "server.log");
2674
+ const traceLogPath = (0, import_node_path7.join)(logDir, "server.log");
2800
2675
  return async (req, res) => {
2801
2676
  const instanceID = (req.params.instanceID || "").trim();
2802
2677
  if (!instanceID) {
@@ -2804,9 +2679,9 @@ function createGetTriggerDetailHandler(logDir) {
2804
2679
  message: "instanceID is required"
2805
2680
  });
2806
2681
  }
2807
- const path7 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2682
+ const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2808
2683
  try {
2809
- const result = await readTriggerDetail(traceLogPath, path7, instanceID);
2684
+ const result = await readTriggerDetail(traceLogPath, path8, instanceID);
2810
2685
  if (!result) {
2811
2686
  return handleNotFound(res, traceLogPath);
2812
2687
  }
@@ -2820,31 +2695,6 @@ function createGetTriggerDetailHandler(logDir) {
2820
2695
  };
2821
2696
  }
2822
2697
  __name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
2823
- function createGetCapabilityTraceListHandler(logDir) {
2824
- const serverLogPath = (0, import_node_path8.join)(logDir, "server.log");
2825
- return async (req, res) => {
2826
- const capabilityId = typeof req.query.capability_id === "string" ? req.query.capability_id.trim() : void 0;
2827
- if (!capabilityId) {
2828
- return res.status(400).json({
2829
- message: "capability_id is required"
2830
- });
2831
- }
2832
- const limit = parseLimit(req.query.limit, 10, 200);
2833
- try {
2834
- const result = await readCapabilityTraceList(serverLogPath, capabilityId, limit);
2835
- if (!result) {
2836
- return handleNotFound(res, serverLogPath);
2837
- }
2838
- res.json({
2839
- file: getRelativePath(serverLogPath),
2840
- ...result
2841
- });
2842
- } catch (error) {
2843
- handleError(res, error, "Failed to read server log");
2844
- }
2845
- };
2846
- }
2847
- __name(createGetCapabilityTraceListHandler, "createGetCapabilityTraceListHandler");
2848
2698
 
2849
2699
  // src/middlewares/dev-logs/health.controller.ts
2850
2700
  var import_node_http2 = __toESM(require("http"), 1);
@@ -2913,6 +2763,521 @@ function createHealthCheckHandler(options = {}) {
2913
2763
  }
2914
2764
  __name(createHealthCheckHandler, "createHealthCheckHandler");
2915
2765
 
2766
+ // src/middlewares/dev-logs/sse/log-watcher.ts
2767
+ var fs9 = __toESM(require("fs"), 1);
2768
+ var path6 = __toESM(require("path"), 1);
2769
+ function mapPinoLevelToServerLogLevel2(pinoLevel) {
2770
+ if (typeof pinoLevel === "string") {
2771
+ const lower = pinoLevel.toLowerCase();
2772
+ if (lower === "fatal") return "fatal";
2773
+ if (lower === "error") return "error";
2774
+ if (lower === "warn" || lower === "warning") return "warn";
2775
+ if (lower === "info" || lower === "log") return "log";
2776
+ if (lower === "debug") return "debug";
2777
+ if (lower === "trace" || lower === "verbose") return "verbose";
2778
+ return "log";
2779
+ }
2780
+ if (pinoLevel >= 60) return "fatal";
2781
+ if (pinoLevel >= 50) return "error";
2782
+ if (pinoLevel >= 40) return "warn";
2783
+ if (pinoLevel >= 30) return "log";
2784
+ if (pinoLevel >= 20) return "debug";
2785
+ return "verbose";
2786
+ }
2787
+ __name(mapPinoLevelToServerLogLevel2, "mapPinoLevelToServerLogLevel");
2788
+ function extractLogLevel2(text) {
2789
+ const lower = text.toLowerCase();
2790
+ if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2791
+ if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2792
+ if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2793
+ if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2794
+ if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2795
+ return "log";
2796
+ }
2797
+ __name(extractLogLevel2, "extractLogLevel");
2798
+ function generateUUID2() {
2799
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2800
+ const r = Math.random() * 16 | 0;
2801
+ const v = c === "x" ? r : r & 3 | 8;
2802
+ return v.toString(16);
2803
+ });
2804
+ }
2805
+ __name(generateUUID2, "generateUUID");
2806
+ function parsePinoLog2(line, source) {
2807
+ try {
2808
+ const pinoLog = JSON.parse(line);
2809
+ const id = generateUUID2();
2810
+ return {
2811
+ id,
2812
+ level: mapPinoLevelToServerLogLevel2(pinoLog.level),
2813
+ timestamp: new Date(pinoLog.time).getTime(),
2814
+ message: pinoLog.message || pinoLog.msg || "",
2815
+ context: pinoLog.context || null,
2816
+ traceId: pinoLog.trace_id || null,
2817
+ userId: pinoLog.user_id || null,
2818
+ appId: pinoLog.app_id || null,
2819
+ tenantId: pinoLog.tenant_id || null,
2820
+ stack: pinoLog.stack || null,
2821
+ meta: {
2822
+ pid: pinoLog.pid,
2823
+ hostname: pinoLog.hostname,
2824
+ path: pinoLog.path,
2825
+ method: pinoLog.method,
2826
+ statusCode: pinoLog.status_code,
2827
+ durationMs: pinoLog.duration_ms,
2828
+ ip: pinoLog.ip,
2829
+ requestBody: pinoLog.request_body,
2830
+ responseBody: pinoLog.response_body
2831
+ },
2832
+ tags: [
2833
+ source
2834
+ ]
2835
+ };
2836
+ } catch {
2837
+ return null;
2838
+ }
2839
+ }
2840
+ __name(parsePinoLog2, "parsePinoLog");
2841
+ function parseStdLog2(line, source) {
2842
+ const id = generateUUID2();
2843
+ const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2844
+ if (!match) {
2845
+ return {
2846
+ id,
2847
+ level: extractLogLevel2(line),
2848
+ timestamp: Date.now(),
2849
+ message: line,
2850
+ context: null,
2851
+ traceId: null,
2852
+ userId: null,
2853
+ appId: null,
2854
+ tenantId: null,
2855
+ stack: null,
2856
+ meta: null,
2857
+ tags: [
2858
+ source
2859
+ ]
2860
+ };
2861
+ }
2862
+ const [, timeStr, , content] = match;
2863
+ let timestamp;
2864
+ try {
2865
+ const isoStr = timeStr.replace(" ", "T");
2866
+ timestamp = new Date(isoStr).getTime();
2867
+ if (isNaN(timestamp)) {
2868
+ timestamp = Date.now();
2869
+ }
2870
+ } catch {
2871
+ timestamp = Date.now();
2872
+ }
2873
+ return {
2874
+ id,
2875
+ level: extractLogLevel2(content),
2876
+ timestamp,
2877
+ message: content,
2878
+ context: null,
2879
+ traceId: null,
2880
+ userId: null,
2881
+ appId: null,
2882
+ tenantId: null,
2883
+ stack: null,
2884
+ meta: null,
2885
+ tags: [
2886
+ source
2887
+ ]
2888
+ };
2889
+ }
2890
+ __name(parseStdLog2, "parseStdLog");
2891
+ var LogWatcher = class {
2892
+ static {
2893
+ __name(this, "LogWatcher");
2894
+ }
2895
+ logDir = "";
2896
+ watchers = /* @__PURE__ */ new Map();
2897
+ filePositions = /* @__PURE__ */ new Map();
2898
+ subscribers = /* @__PURE__ */ new Set();
2899
+ isRunning = false;
2900
+ debug = false;
2901
+ logFiles = [
2902
+ {
2903
+ fileName: "server.log",
2904
+ source: "server",
2905
+ parser: parsePinoLog2
2906
+ },
2907
+ {
2908
+ fileName: "trace.log",
2909
+ source: "trace",
2910
+ parser: parsePinoLog2
2911
+ },
2912
+ {
2913
+ fileName: "server.std.log",
2914
+ source: "server-std",
2915
+ parser: parseStdLog2
2916
+ },
2917
+ {
2918
+ fileName: "client.std.log",
2919
+ source: "client-std",
2920
+ parser: parseStdLog2
2921
+ }
2922
+ ];
2923
+ constructor(options = {}) {
2924
+ this.debug = options.debug ?? false;
2925
+ }
2926
+ log(...args) {
2927
+ if (this.debug) {
2928
+ console.log("[LogWatcher]", ...args);
2929
+ }
2930
+ }
2931
+ /**
2932
+ * Start watching log files
2933
+ */
2934
+ start(logDir) {
2935
+ if (this.isRunning) {
2936
+ this.log("Already running, ignoring start call");
2937
+ return;
2938
+ }
2939
+ this.logDir = logDir;
2940
+ this.isRunning = true;
2941
+ this.log(`Starting to watch log files in: ${logDir}`);
2942
+ for (const config of this.logFiles) {
2943
+ this.watchFile(config);
2944
+ }
2945
+ }
2946
+ /**
2947
+ * Stop watching all files
2948
+ */
2949
+ stop() {
2950
+ if (!this.isRunning) {
2951
+ return;
2952
+ }
2953
+ this.log("Stopping file watchers");
2954
+ this.isRunning = false;
2955
+ Array.from(this.watchers.entries()).forEach(([fileName, watcher]) => {
2956
+ watcher.close();
2957
+ this.log(`Closed watcher for: ${fileName}`);
2958
+ });
2959
+ this.watchers.clear();
2960
+ this.filePositions.clear();
2961
+ }
2962
+ /**
2963
+ * Subscribe to new log events
2964
+ */
2965
+ onLog(callback) {
2966
+ this.subscribers.add(callback);
2967
+ this.log(`Subscriber added, total: ${this.subscribers.size}`);
2968
+ return () => {
2969
+ this.subscribers.delete(callback);
2970
+ this.log(`Subscriber removed, total: ${this.subscribers.size}`);
2971
+ };
2972
+ }
2973
+ /**
2974
+ * Get subscriber count
2975
+ */
2976
+ getSubscriberCount() {
2977
+ return this.subscribers.size;
2978
+ }
2979
+ /**
2980
+ * Watch a single log file
2981
+ */
2982
+ watchFile(config) {
2983
+ const filePath = path6.join(this.logDir, config.fileName);
2984
+ if (!fs9.existsSync(filePath)) {
2985
+ this.log(`File not found, skipping: ${config.fileName}`);
2986
+ return;
2987
+ }
2988
+ try {
2989
+ const stats = fs9.statSync(filePath);
2990
+ this.filePositions.set(config.fileName, stats.size);
2991
+ this.log(`Initialized position for ${config.fileName}: ${stats.size} bytes`);
2992
+ } catch (error) {
2993
+ this.log(`Failed to get initial position for ${config.fileName}:`, error);
2994
+ this.filePositions.set(config.fileName, 0);
2995
+ }
2996
+ try {
2997
+ const watcher = fs9.watch(filePath, (eventType) => {
2998
+ if (eventType === "change") {
2999
+ this.handleFileChange(config);
3000
+ }
3001
+ });
3002
+ watcher.on("error", (error) => {
3003
+ this.log(`Watcher error for ${config.fileName}:`, error);
3004
+ this.restartWatcher(config);
3005
+ });
3006
+ this.watchers.set(config.fileName, watcher);
3007
+ this.log(`Started watching: ${config.fileName}`);
3008
+ } catch (error) {
3009
+ this.log(`Failed to start watcher for ${config.fileName}:`, error);
3010
+ }
3011
+ }
3012
+ /**
3013
+ * Restart a file watcher after error
3014
+ */
3015
+ restartWatcher(config) {
3016
+ const existingWatcher = this.watchers.get(config.fileName);
3017
+ if (existingWatcher) {
3018
+ existingWatcher.close();
3019
+ this.watchers.delete(config.fileName);
3020
+ }
3021
+ setTimeout(() => {
3022
+ if (this.isRunning) {
3023
+ this.log(`Restarting watcher for: ${config.fileName}`);
3024
+ this.watchFile(config);
3025
+ }
3026
+ }, 1e3);
3027
+ }
3028
+ /**
3029
+ * Handle file change event - read new content
3030
+ */
3031
+ handleFileChange(config) {
3032
+ const filePath = path6.join(this.logDir, config.fileName);
3033
+ const lastPosition = this.filePositions.get(config.fileName) || 0;
3034
+ try {
3035
+ const stats = fs9.statSync(filePath);
3036
+ const currentSize = stats.size;
3037
+ if (currentSize < lastPosition) {
3038
+ this.log(`File ${config.fileName} was truncated, resetting position`);
3039
+ this.filePositions.set(config.fileName, 0);
3040
+ this.handleFileChange(config);
3041
+ return;
3042
+ }
3043
+ if (currentSize === lastPosition) {
3044
+ return;
3045
+ }
3046
+ const readSize = currentSize - lastPosition;
3047
+ const buffer = Buffer.alloc(readSize);
3048
+ const fd = fs9.openSync(filePath, "r");
3049
+ try {
3050
+ fs9.readSync(fd, buffer, 0, readSize, lastPosition);
3051
+ } finally {
3052
+ fs9.closeSync(fd);
3053
+ }
3054
+ this.filePositions.set(config.fileName, currentSize);
3055
+ const content = buffer.toString("utf8");
3056
+ const lines = content.split("\n");
3057
+ for (const line of lines) {
3058
+ if (!line.trim()) continue;
3059
+ try {
3060
+ const log = config.parser(line, config.source);
3061
+ if (log) {
3062
+ this.notifySubscribers(log);
3063
+ }
3064
+ } catch {
3065
+ }
3066
+ }
3067
+ } catch (error) {
3068
+ this.log(`Error reading file ${config.fileName}:`, error);
3069
+ }
3070
+ }
3071
+ /**
3072
+ * Notify all subscribers of new log
3073
+ */
3074
+ notifySubscribers(log) {
3075
+ Array.from(this.subscribers).forEach((subscriber) => {
3076
+ try {
3077
+ subscriber(log);
3078
+ } catch (error) {
3079
+ this.log("Subscriber error:", error);
3080
+ }
3081
+ });
3082
+ }
3083
+ };
3084
+
3085
+ // src/middlewares/dev-logs/sse/client-manager.ts
3086
+ var ClientManager = class {
3087
+ static {
3088
+ __name(this, "ClientManager");
3089
+ }
3090
+ clients = /* @__PURE__ */ new Map();
3091
+ debug = false;
3092
+ constructor(options = {}) {
3093
+ this.debug = options.debug ?? false;
3094
+ }
3095
+ log(...args) {
3096
+ if (this.debug) {
3097
+ console.log("[ClientManager]", ...args);
3098
+ }
3099
+ }
3100
+ /**
3101
+ * Generate a unique client ID
3102
+ */
3103
+ generateClientId() {
3104
+ return `client_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
3105
+ }
3106
+ /**
3107
+ * Add a new client connection
3108
+ */
3109
+ addClient(id, res) {
3110
+ this.clients.set(id, {
3111
+ id,
3112
+ res,
3113
+ connectedAt: Date.now()
3114
+ });
3115
+ this.log(`Client connected: ${id}, total clients: ${this.clients.size}`);
3116
+ }
3117
+ /**
3118
+ * Remove a client connection
3119
+ */
3120
+ removeClient(id) {
3121
+ if (this.clients.has(id)) {
3122
+ this.clients.delete(id);
3123
+ this.log(`Client disconnected: ${id}, total clients: ${this.clients.size}`);
3124
+ }
3125
+ }
3126
+ /**
3127
+ * Get current client count
3128
+ */
3129
+ getClientCount() {
3130
+ return this.clients.size;
3131
+ }
3132
+ /**
3133
+ * Check if a client exists
3134
+ */
3135
+ hasClient(id) {
3136
+ return this.clients.has(id);
3137
+ }
3138
+ /**
3139
+ * Send SSE event to a specific client
3140
+ */
3141
+ sendToClient(clientId, event, data) {
3142
+ const client = this.clients.get(clientId);
3143
+ if (!client) {
3144
+ return false;
3145
+ }
3146
+ try {
3147
+ const message = this.formatSSEMessage(event, data);
3148
+ client.res.write(message);
3149
+ return true;
3150
+ } catch (error) {
3151
+ this.log(`Failed to send to client ${clientId}:`, error);
3152
+ this.removeClient(clientId);
3153
+ return false;
3154
+ }
3155
+ }
3156
+ /**
3157
+ * Broadcast SSE event to all clients
3158
+ */
3159
+ broadcast(event, data) {
3160
+ const message = this.formatSSEMessage(event, data);
3161
+ const failedClients = [];
3162
+ Array.from(this.clients.entries()).forEach(([id, client]) => {
3163
+ try {
3164
+ client.res.write(message);
3165
+ } catch (error) {
3166
+ this.log(`Broadcast failed for client ${id}:`, error);
3167
+ failedClients.push(id);
3168
+ }
3169
+ });
3170
+ failedClients.forEach((id) => {
3171
+ this.removeClient(id);
3172
+ });
3173
+ }
3174
+ /**
3175
+ * Format SSE message
3176
+ * SSE format: event: <event>\ndata: <json>\n\n
3177
+ */
3178
+ formatSSEMessage(event, data) {
3179
+ const jsonData = JSON.stringify(data);
3180
+ return `event: ${event}
3181
+ data: ${jsonData}
3182
+
3183
+ `;
3184
+ }
3185
+ /**
3186
+ * Get all client IDs
3187
+ */
3188
+ getClientIds() {
3189
+ return Array.from(this.clients.keys());
3190
+ }
3191
+ /**
3192
+ * Get client info
3193
+ */
3194
+ getClientInfo(id) {
3195
+ const client = this.clients.get(id);
3196
+ if (!client) {
3197
+ return null;
3198
+ }
3199
+ return {
3200
+ id: client.id,
3201
+ connectedAt: client.connectedAt
3202
+ };
3203
+ }
3204
+ /**
3205
+ * Close all client connections
3206
+ */
3207
+ closeAll() {
3208
+ this.log(`Closing all ${this.clients.size} clients`);
3209
+ Array.from(this.clients.entries()).forEach(([id, client]) => {
3210
+ try {
3211
+ client.res.end();
3212
+ } catch (error) {
3213
+ this.log(`Error closing client ${id}:`, error);
3214
+ }
3215
+ });
3216
+ this.clients.clear();
3217
+ }
3218
+ };
3219
+
3220
+ // src/middlewares/dev-logs/sse/sse.controller.ts
3221
+ function createSSEHandler(logDir, options = {}) {
3222
+ const { debug = false, heartbeatInterval = 3e4 } = options;
3223
+ const logWatcher = new LogWatcher({
3224
+ debug
3225
+ });
3226
+ const clientManager = new ClientManager({
3227
+ debug
3228
+ });
3229
+ const log = /* @__PURE__ */ __name((...args) => {
3230
+ if (debug) {
3231
+ console.log("[SSEHandler]", ...args);
3232
+ }
3233
+ }, "log");
3234
+ return (req, res) => {
3235
+ res.setHeader("Content-Type", "text/event-stream");
3236
+ res.setHeader("Cache-Control", "no-cache");
3237
+ res.setHeader("Connection", "keep-alive");
3238
+ res.setHeader("X-Accel-Buffering", "no");
3239
+ res.setTimeout(0);
3240
+ const clientId = clientManager.generateClientId();
3241
+ clientManager.addClient(clientId, res);
3242
+ log(`New SSE connection: ${clientId}`);
3243
+ if (clientManager.getClientCount() === 1) {
3244
+ log("First client connected, starting log watcher");
3245
+ logWatcher.start(logDir);
3246
+ }
3247
+ const unsubscribe = logWatcher.onLog((logEntry) => {
3248
+ clientManager.sendToClient(clientId, "log", logEntry);
3249
+ });
3250
+ clientManager.sendToClient(clientId, "connected", {
3251
+ clientId,
3252
+ timestamp: Date.now()
3253
+ });
3254
+ const heartbeat = setInterval(() => {
3255
+ const success = clientManager.sendToClient(clientId, "heartbeat", {
3256
+ timestamp: Date.now()
3257
+ });
3258
+ if (!success) {
3259
+ clearInterval(heartbeat);
3260
+ }
3261
+ }, heartbeatInterval);
3262
+ const cleanup = /* @__PURE__ */ __name(() => {
3263
+ log(`Client disconnected: ${clientId}`);
3264
+ clearInterval(heartbeat);
3265
+ unsubscribe();
3266
+ clientManager.removeClient(clientId);
3267
+ if (clientManager.getClientCount() === 0) {
3268
+ log("No more clients, stopping log watcher");
3269
+ logWatcher.stop();
3270
+ }
3271
+ }, "cleanup");
3272
+ req.on("close", cleanup);
3273
+ req.on("error", (error) => {
3274
+ log(`Client error ${clientId}:`, error);
3275
+ cleanup();
3276
+ });
3277
+ };
3278
+ }
3279
+ __name(createSSEHandler, "createSSEHandler");
3280
+
2916
3281
  // src/middlewares/dev-logs/router.ts
2917
3282
  function createDevLogRouter(options = {}) {
2918
3283
  const logDir = resolveLogDir(options.logDir);
@@ -2921,9 +3286,11 @@ function createDevLogRouter(options = {}) {
2921
3286
  router.get("/trace/recent", createGetRecentTracesHandler(logDir));
2922
3287
  router.get("/files/:fileName", createGetLogFileHandler(logDir));
2923
3288
  router.get("/server-logs", createGetServerLogsHandler(logDir));
3289
+ router.get("/server-logs/stream", createSSEHandler(logDir, {
3290
+ debug: true
3291
+ }));
2924
3292
  router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
2925
3293
  router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
2926
- router.get("/trace/capability/list", createGetCapabilityTraceListHandler(logDir));
2927
3294
  router.get("/health", createHealthCheckHandler());
2928
3295
  return router;
2929
3296
  }
@@ -2986,18 +3353,18 @@ var import_path2 = require("path");
2986
3353
  var import_fs2 = __toESM(require("fs"), 1);
2987
3354
 
2988
3355
  // src/middlewares/collect-logs/utils.ts
2989
- var import_node_path9 = require("path");
2990
- var import_node_fs11 = __toESM(require("fs"), 1);
3356
+ var import_node_path8 = require("path");
3357
+ var import_node_fs8 = __toESM(require("fs"), 1);
2991
3358
  function resolveLogDir2(provided) {
2992
3359
  if (!provided) {
2993
- return (0, import_node_path9.join)(process.cwd(), "logs");
3360
+ return (0, import_node_path8.join)(process.cwd(), "logs");
2994
3361
  }
2995
- return (0, import_node_path9.isAbsolute)(provided) ? provided : (0, import_node_path9.join)(process.cwd(), provided);
3362
+ return (0, import_node_path8.isAbsolute)(provided) ? provided : (0, import_node_path8.join)(process.cwd(), provided);
2996
3363
  }
2997
3364
  __name(resolveLogDir2, "resolveLogDir");
2998
3365
  function ensureDir(dir) {
2999
- if (!import_node_fs11.default.existsSync(dir)) {
3000
- import_node_fs11.default.mkdirSync(dir, {
3366
+ if (!import_node_fs8.default.existsSync(dir)) {
3367
+ import_node_fs8.default.mkdirSync(dir, {
3001
3368
  recursive: true
3002
3369
  });
3003
3370
  }
@@ -3120,7 +3487,7 @@ function isGlobalMiddleware(middleware) {
3120
3487
  }
3121
3488
  __name(isGlobalMiddleware, "isGlobalMiddleware");
3122
3489
  function computeMountPath(basePath, mountPath) {
3123
- const routePath = import_node_path10.default.posix.join(basePath, mountPath);
3490
+ const routePath = import_node_path9.default.posix.join(basePath, mountPath);
3124
3491
  return routePath.startsWith("/") ? routePath : `/${routePath}`;
3125
3492
  }
3126
3493
  __name(computeMountPath, "computeMountPath");
@@ -3128,7 +3495,7 @@ function logMiddlewareRegistration(middleware, fullMountPath) {
3128
3495
  if (middleware.routes && middleware.routes.length > 0) {
3129
3496
  console.log(`[Middleware] Registered: ${middleware.name} at ${fullMountPath}`);
3130
3497
  middleware.routes.forEach((route) => {
3131
- const routePath = route.path === "/" ? fullMountPath : import_node_path10.default.posix.join(fullMountPath, route.path);
3498
+ const routePath = route.path === "/" ? fullMountPath : import_node_path9.default.posix.join(fullMountPath, route.path);
3132
3499
  console.log(` ${route.method} ${routePath} - ${route.description}`);
3133
3500
  });
3134
3501
  } else {