@lark-apaas/devtool-kits 1.2.11-alpha.1 → 1.2.12-alpha.0
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 +772 -407
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +769 -404
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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(
|
|
1854
|
-
return
|
|
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
|
|
1952
|
+
var import_node_path7 = require("path");
|
|
1953
1953
|
|
|
1954
|
-
// src/middlewares/dev-logs/services
|
|
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,
|
|
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,
|
|
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 = (
|
|
2211
|
+
filePath = join7(logDir, "server.log");
|
|
2344
2212
|
parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
|
|
2345
2213
|
} else if (source === "trace") {
|
|
2346
|
-
filePath = (
|
|
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 = (
|
|
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 = (
|
|
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,
|
|
2234
|
+
stream = (0, import_node_fs7.createReadStream)(filePath, {
|
|
2367
2235
|
encoding: "utf8"
|
|
2368
2236
|
});
|
|
2369
|
-
rl = (0,
|
|
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
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
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(
|
|
2414
|
+
const isAutomationTrigger = builder.path?.endsWith(path8);
|
|
2428
2415
|
if (!isAutomationTrigger) {
|
|
2429
2416
|
return false;
|
|
2430
2417
|
}
|
|
@@ -2476,178 +2463,66 @@ async function readTriggerList(filePath, trigger, path7, limit, triggerID) {
|
|
|
2476
2463
|
}
|
|
2477
2464
|
updateBuilderMetadata(builder, entry);
|
|
2478
2465
|
if (!builder.hasCompleted && (message.includes("HTTP request completed") || message.includes("HTTP request failed"))) {
|
|
2479
|
-
handleRequestCompleted(builder, entry, message);
|
|
2480
|
-
}
|
|
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);
|
|
2466
|
+
handleRequestCompleted(builder, entry, message);
|
|
2467
|
+
}
|
|
2468
|
+
if (message.includes("HTTP request started") && !builder.startTime) {
|
|
2469
|
+
builder.startTime = entry.time;
|
|
2616
2470
|
}
|
|
2617
|
-
updateBuilderMetadata(builder, entry);
|
|
2618
2471
|
}, "processLogEntry");
|
|
2619
2472
|
const processLine = /* @__PURE__ */ __name((line) => {
|
|
2620
2473
|
const entry = parseLogLine2(line);
|
|
2621
|
-
if (entry?.
|
|
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
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
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
|
-
|
|
2638
|
-
|
|
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
|
-
|
|
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(
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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:
|
|
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,
|
|
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
|
|
2682
|
+
const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
|
|
2808
2683
|
try {
|
|
2809
|
-
const result = await readTriggerDetail(traceLogPath,
|
|
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,9 @@ 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));
|
|
2924
3290
|
router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
|
|
2925
3291
|
router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
|
|
2926
|
-
router.get("/trace/capability/list", createGetCapabilityTraceListHandler(logDir));
|
|
2927
3292
|
router.get("/health", createHealthCheckHandler());
|
|
2928
3293
|
return router;
|
|
2929
3294
|
}
|
|
@@ -2986,18 +3351,18 @@ var import_path2 = require("path");
|
|
|
2986
3351
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
2987
3352
|
|
|
2988
3353
|
// src/middlewares/collect-logs/utils.ts
|
|
2989
|
-
var
|
|
2990
|
-
var
|
|
3354
|
+
var import_node_path8 = require("path");
|
|
3355
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
2991
3356
|
function resolveLogDir2(provided) {
|
|
2992
3357
|
if (!provided) {
|
|
2993
|
-
return (0,
|
|
3358
|
+
return (0, import_node_path8.join)(process.cwd(), "logs");
|
|
2994
3359
|
}
|
|
2995
|
-
return (0,
|
|
3360
|
+
return (0, import_node_path8.isAbsolute)(provided) ? provided : (0, import_node_path8.join)(process.cwd(), provided);
|
|
2996
3361
|
}
|
|
2997
3362
|
__name(resolveLogDir2, "resolveLogDir");
|
|
2998
3363
|
function ensureDir(dir) {
|
|
2999
|
-
if (!
|
|
3000
|
-
|
|
3364
|
+
if (!import_node_fs8.default.existsSync(dir)) {
|
|
3365
|
+
import_node_fs8.default.mkdirSync(dir, {
|
|
3001
3366
|
recursive: true
|
|
3002
3367
|
});
|
|
3003
3368
|
}
|
|
@@ -3120,7 +3485,7 @@ function isGlobalMiddleware(middleware) {
|
|
|
3120
3485
|
}
|
|
3121
3486
|
__name(isGlobalMiddleware, "isGlobalMiddleware");
|
|
3122
3487
|
function computeMountPath(basePath, mountPath) {
|
|
3123
|
-
const routePath =
|
|
3488
|
+
const routePath = import_node_path9.default.posix.join(basePath, mountPath);
|
|
3124
3489
|
return routePath.startsWith("/") ? routePath : `/${routePath}`;
|
|
3125
3490
|
}
|
|
3126
3491
|
__name(computeMountPath, "computeMountPath");
|
|
@@ -3128,7 +3493,7 @@ function logMiddlewareRegistration(middleware, fullMountPath) {
|
|
|
3128
3493
|
if (middleware.routes && middleware.routes.length > 0) {
|
|
3129
3494
|
console.log(`[Middleware] Registered: ${middleware.name} at ${fullMountPath}`);
|
|
3130
3495
|
middleware.routes.forEach((route) => {
|
|
3131
|
-
const routePath = route.path === "/" ? fullMountPath :
|
|
3496
|
+
const routePath = route.path === "/" ? fullMountPath : import_node_path9.default.posix.join(fullMountPath, route.path);
|
|
3132
3497
|
console.log(` ${route.method} ${routePath} - ${route.description}`);
|
|
3133
3498
|
});
|
|
3134
3499
|
} else {
|