@lark-apaas/fullstack-cli 1.1.68-alpha.20261019123412 → 1.1.68-alpha.20261020063206
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +184 -42
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7786,8 +7786,140 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
|
|
|
7786
7786
|
return { lines: collected.reverse(), totalLinesCount };
|
|
7787
7787
|
}
|
|
7788
7788
|
|
|
7789
|
+
// src/commands/read-logs/std-level.ts
|
|
7790
|
+
var STD_LEVEL_SCAN_LINES = 2e3;
|
|
7791
|
+
var ANSI_PATTERN = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
7792
|
+
var TRANSIENT_CONNECTION_ERROR_PATTERN = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENETUNREACH|socket hang up|proxy error(?!.*ENOTFOUND)|\[Proxy\] (?:Error:\s*$|Error during|Connection error|Non-connection error|Headers already sent|Service (?:recovered|did not recover))/i;
|
|
7793
|
+
var ERROR_PATTERNS = [
|
|
7794
|
+
/compiled with errors/i,
|
|
7795
|
+
/failed to compile/i,
|
|
7796
|
+
/\[vite\].*(?:internal server error|pre-transform error)/i,
|
|
7797
|
+
/\berror:\s*\S+/i,
|
|
7798
|
+
/\b(?:uncaught|unhandled|fatal|exception)\b/i,
|
|
7799
|
+
/\beaddrinuse\b/i,
|
|
7800
|
+
/\b(?:cannot find module|module not found)\b/i,
|
|
7801
|
+
/\bts\d{3,5}:/i,
|
|
7802
|
+
/\b(?:syntax|type|reference|range)error\b/i,
|
|
7803
|
+
/\bENOTFOUND\b/i,
|
|
7804
|
+
/\berror\b/i
|
|
7805
|
+
];
|
|
7806
|
+
var WARN_PATTERNS = [
|
|
7807
|
+
/compiled with warnings/i,
|
|
7808
|
+
/(?:^|[\s)])[\w$.-]*Warning\s*:/i,
|
|
7809
|
+
/\bWARN(?:ING)?S?\b(?:\s|:|\])/,
|
|
7810
|
+
/\[vite\].*\bwarn(?:ing)?s?\b/i,
|
|
7811
|
+
/\bdeprecated\b/i,
|
|
7812
|
+
/\bdeprecation\b/i
|
|
7813
|
+
];
|
|
7814
|
+
var IGNORE_PATTERNS = [/\b0\s+errors?\b/i, /Server Error \d{3}/i];
|
|
7815
|
+
function comparableText(line) {
|
|
7816
|
+
return line.replace(ANSI_PATTERN, "");
|
|
7817
|
+
}
|
|
7818
|
+
function contentWithoutTimestamp(line) {
|
|
7819
|
+
return comparableText(line).replace(/^\[[^\]]+\]\s?/, "");
|
|
7820
|
+
}
|
|
7821
|
+
function isTransientStdLine(line) {
|
|
7822
|
+
return TRANSIENT_CONNECTION_ERROR_PATTERN.test(comparableText(line));
|
|
7823
|
+
}
|
|
7824
|
+
function classifyStdLine(line) {
|
|
7825
|
+
const text = contentWithoutTimestamp(line).trim();
|
|
7826
|
+
if (!text || isTransientStdLine(text) || IGNORE_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
7827
|
+
return void 0;
|
|
7828
|
+
}
|
|
7829
|
+
if (WARN_PATTERNS.some((pattern) => pattern.test(text))) return "warn";
|
|
7830
|
+
if (ERROR_PATTERNS.some((pattern) => pattern.test(text))) return "error";
|
|
7831
|
+
return void 0;
|
|
7832
|
+
}
|
|
7833
|
+
function isDiagnosticContinuation(line) {
|
|
7834
|
+
const content = contentWithoutTimestamp(line);
|
|
7835
|
+
if (!content.trim()) return true;
|
|
7836
|
+
return /^\s+/.test(content) || /^\s*(?:Plugin|File|Location|Caused by):/i.test(content) || /^\s*(?:at\s+|\.\.\.\s+\d+\s+more)/.test(content) || /^\s*(?:>?\s*\d+\s*\||\||\^|~)/.test(content) || /^\s*(?:Error|AggregateError)\s*\{?$/i.test(content);
|
|
7837
|
+
}
|
|
7838
|
+
function summarizeStack(lines) {
|
|
7839
|
+
const result = [];
|
|
7840
|
+
let stackLines = 0;
|
|
7841
|
+
for (const line of lines) {
|
|
7842
|
+
const content = contentWithoutTimestamp(line);
|
|
7843
|
+
const isStack = /^\s*at\s+/.test(content);
|
|
7844
|
+
if (isStack) {
|
|
7845
|
+
if (stackLines >= 3) continue;
|
|
7846
|
+
stackLines += 1;
|
|
7847
|
+
}
|
|
7848
|
+
result.push(line);
|
|
7849
|
+
}
|
|
7850
|
+
return result;
|
|
7851
|
+
}
|
|
7852
|
+
function normalizeRequestedStdLevels(levels) {
|
|
7853
|
+
if (!levels?.length) return void 0;
|
|
7854
|
+
const normalized = new Set(
|
|
7855
|
+
levels.map((level) => level.trim().toLowerCase()).filter(Boolean)
|
|
7856
|
+
);
|
|
7857
|
+
if (normalized.has("info")) return void 0;
|
|
7858
|
+
const supported = /* @__PURE__ */ new Set();
|
|
7859
|
+
if (normalized.has("error")) supported.add("error");
|
|
7860
|
+
if (normalized.has("warn") || normalized.has("warning"))
|
|
7861
|
+
supported.add("warn");
|
|
7862
|
+
return supported;
|
|
7863
|
+
}
|
|
7864
|
+
function extractStdDiagnosticBlocks(lines, requestedLevels) {
|
|
7865
|
+
const blocks = [];
|
|
7866
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
7867
|
+
const line = lines[index] ?? "";
|
|
7868
|
+
const level = classifyStdLine(line);
|
|
7869
|
+
if (!level || !requestedLevels.has(level)) continue;
|
|
7870
|
+
const blockLines = [line];
|
|
7871
|
+
let next = index + 1;
|
|
7872
|
+
while (next < lines.length) {
|
|
7873
|
+
const candidate = lines[next] ?? "";
|
|
7874
|
+
if (isDiagnosticContinuation(candidate)) {
|
|
7875
|
+
blockLines.push(candidate);
|
|
7876
|
+
next += 1;
|
|
7877
|
+
continue;
|
|
7878
|
+
}
|
|
7879
|
+
const candidateLevel = classifyStdLine(candidate);
|
|
7880
|
+
if (candidateLevel) break;
|
|
7881
|
+
break;
|
|
7882
|
+
}
|
|
7883
|
+
while (blockLines.length > 1 && !contentWithoutTimestamp(blockLines[blockLines.length - 1] ?? "").trim()) {
|
|
7884
|
+
blockLines.pop();
|
|
7885
|
+
}
|
|
7886
|
+
blocks.push({ level, lines: summarizeStack(blockLines) });
|
|
7887
|
+
index = next - 1;
|
|
7888
|
+
}
|
|
7889
|
+
return blocks;
|
|
7890
|
+
}
|
|
7891
|
+
function paginateStdDiagnosticBlocks(blocks, maxLines, offset) {
|
|
7892
|
+
let skippedLines = 0;
|
|
7893
|
+
let selectedLines = 0;
|
|
7894
|
+
const selected = [];
|
|
7895
|
+
for (let index = blocks.length - 1; index >= 0; index -= 1) {
|
|
7896
|
+
const block = blocks[index];
|
|
7897
|
+
if (!block) continue;
|
|
7898
|
+
if (skippedLines < offset) {
|
|
7899
|
+
skippedLines += block.lines.length;
|
|
7900
|
+
continue;
|
|
7901
|
+
}
|
|
7902
|
+
if (selectedLines >= maxLines) break;
|
|
7903
|
+
selected.unshift(block);
|
|
7904
|
+
selectedLines += block.lines.length;
|
|
7905
|
+
}
|
|
7906
|
+
return selected.flatMap((block) => block.lines);
|
|
7907
|
+
}
|
|
7908
|
+
function hasErrorInStdLines(lines) {
|
|
7909
|
+
return lines.some((line) => classifyStdLine(line) === "error");
|
|
7910
|
+
}
|
|
7911
|
+
|
|
7789
7912
|
// src/commands/read-logs/index.ts
|
|
7790
|
-
var LOG_TYPES = [
|
|
7913
|
+
var LOG_TYPES = [
|
|
7914
|
+
"server",
|
|
7915
|
+
"trace",
|
|
7916
|
+
"server-std",
|
|
7917
|
+
"client-std",
|
|
7918
|
+
"dev",
|
|
7919
|
+
"dev-std",
|
|
7920
|
+
"install-dep-std",
|
|
7921
|
+
"browser"
|
|
7922
|
+
];
|
|
7791
7923
|
function normalizeObjectKey(key) {
|
|
7792
7924
|
return key.toLowerCase().replace(/_/g, "");
|
|
7793
7925
|
}
|
|
@@ -7810,7 +7942,9 @@ function formatIsoWithLocalOffset(date, includeMilliseconds) {
|
|
|
7810
7942
|
return `${year}-${month}-${day}T${hour}:${minute}:${second}${msPart}${sign}${offsetHH}:${offsetMM}`;
|
|
7811
7943
|
}
|
|
7812
7944
|
function formatLocalDateTimeStringWithOffset(input) {
|
|
7813
|
-
const match = input.match(
|
|
7945
|
+
const match = input.match(
|
|
7946
|
+
/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/
|
|
7947
|
+
);
|
|
7814
7948
|
if (!match) return input;
|
|
7815
7949
|
const year = Number(match[1]);
|
|
7816
7950
|
const month = Number(match[2]);
|
|
@@ -7886,35 +8020,6 @@ function sanitizeStructuredLog(value) {
|
|
|
7886
8020
|
}
|
|
7887
8021
|
return sanitized;
|
|
7888
8022
|
}
|
|
7889
|
-
var TRANSIENT_CONNECTION_ERROR_PATTERN = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENETUNREACH|socket hang up|proxy error|\[Proxy\] (?:Error:\s*$|Error during|Connection error|Non-connection error|Headers already sent|Service (?:recovered|did not recover))/i;
|
|
7890
|
-
function hasErrorInStdLines(lines) {
|
|
7891
|
-
const filtered = lines.filter((line) => !TRANSIENT_CONNECTION_ERROR_PATTERN.test(line));
|
|
7892
|
-
const combined = filtered.join("\n");
|
|
7893
|
-
if (!combined) return false;
|
|
7894
|
-
const strong = [
|
|
7895
|
-
/compiled with errors/i,
|
|
7896
|
-
/failed to compile/i,
|
|
7897
|
-
/error: \w+/i,
|
|
7898
|
-
/uncaught/i,
|
|
7899
|
-
/unhandled/i,
|
|
7900
|
-
/eaddrinuse/i,
|
|
7901
|
-
/cannot find module/i,
|
|
7902
|
-
/module not found/i,
|
|
7903
|
-
/ts\d{3,5}:/i
|
|
7904
|
-
];
|
|
7905
|
-
if (strong.some((re) => re.test(combined))) return true;
|
|
7906
|
-
const weakLine = /\b(error|fatal|exception)\b/i;
|
|
7907
|
-
const ignorePatterns = [
|
|
7908
|
-
/\b0\s+errors?\b/i,
|
|
7909
|
-
/Server Error \d{3}/i
|
|
7910
|
-
];
|
|
7911
|
-
return filtered.some((line) => {
|
|
7912
|
-
const text = line.trim();
|
|
7913
|
-
if (!text) return false;
|
|
7914
|
-
if (ignorePatterns.some((re) => re.test(text))) return false;
|
|
7915
|
-
return weakLine.test(text);
|
|
7916
|
-
});
|
|
7917
|
-
}
|
|
7918
8023
|
function hasErrorInLogObject(value) {
|
|
7919
8024
|
if (!value || typeof value !== "object") return false;
|
|
7920
8025
|
const obj = value;
|
|
@@ -7924,8 +8029,10 @@ function hasErrorInLogObject(value) {
|
|
|
7924
8029
|
const level = typeof rawLevel === "string" ? rawLevel.toLowerCase() : "";
|
|
7925
8030
|
if (level === "error" || level === "fatal") return true;
|
|
7926
8031
|
if (level === "err") return true;
|
|
7927
|
-
if (typeof rawLevel === "number" && Number.isFinite(rawLevel) && rawLevel >= 50)
|
|
7928
|
-
|
|
8032
|
+
if (typeof rawLevel === "number" && Number.isFinite(rawLevel) && rawLevel >= 50)
|
|
8033
|
+
return true;
|
|
8034
|
+
if (level === "warn" && typeof obj.stack === "string" && obj.stack.length > 0)
|
|
8035
|
+
return true;
|
|
7929
8036
|
if (typeof obj.stack === "string" && obj.stack.length > 0) return true;
|
|
7930
8037
|
const statusCode = obj.statusCode;
|
|
7931
8038
|
const status_code = obj.status_code;
|
|
@@ -7952,10 +8059,35 @@ async function readLatestLogLinesMeta(options) {
|
|
|
7952
8059
|
throw new Error(`Log file not found: ${filePath}`);
|
|
7953
8060
|
}
|
|
7954
8061
|
if (options.type === "server-std") {
|
|
7955
|
-
|
|
8062
|
+
const requestedLevels = normalizeRequestedStdLevels(levels);
|
|
8063
|
+
if (!requestedLevels)
|
|
8064
|
+
return readServerStdSegment(filePath, maxLines, offset);
|
|
8065
|
+
const segment = readServerStdSegment(filePath, STD_LEVEL_SCAN_LINES, 0);
|
|
8066
|
+
const blocks = extractStdDiagnosticBlocks(segment.lines, requestedLevels);
|
|
8067
|
+
return {
|
|
8068
|
+
lines: paginateStdDiagnosticBlocks(blocks, maxLines, offset),
|
|
8069
|
+
totalLinesCount: blocks.reduce(
|
|
8070
|
+
(sum, block) => sum + block.lines.length,
|
|
8071
|
+
0
|
|
8072
|
+
),
|
|
8073
|
+
allLines: blocks.flatMap((block) => block.lines)
|
|
8074
|
+
};
|
|
7956
8075
|
}
|
|
7957
8076
|
if (options.type === "client-std") {
|
|
7958
|
-
|
|
8077
|
+
const requestedLevels = normalizeRequestedStdLevels(levels);
|
|
8078
|
+
if (!requestedLevels)
|
|
8079
|
+
return readClientStdSegment(filePath, maxLines, offset);
|
|
8080
|
+
const segment = readClientStdSegment(filePath, STD_LEVEL_SCAN_LINES, 0);
|
|
8081
|
+
const scanLines = segment.allLines.slice(-STD_LEVEL_SCAN_LINES);
|
|
8082
|
+
const blocks = extractStdDiagnosticBlocks(scanLines, requestedLevels);
|
|
8083
|
+
return {
|
|
8084
|
+
lines: paginateStdDiagnosticBlocks(blocks, maxLines, offset),
|
|
8085
|
+
totalLinesCount: blocks.reduce(
|
|
8086
|
+
(sum, block) => sum + block.lines.length,
|
|
8087
|
+
0
|
|
8088
|
+
),
|
|
8089
|
+
allLines: blocks.flatMap((block) => block.lines)
|
|
8090
|
+
};
|
|
7959
8091
|
}
|
|
7960
8092
|
if (options.type === "dev") {
|
|
7961
8093
|
return readDevSegment(filePath, maxLines, offset);
|
|
@@ -7987,15 +8119,16 @@ async function readLogsJsonResult(options) {
|
|
|
7987
8119
|
const linesForErrorCheck = allLines ?? lines;
|
|
7988
8120
|
const stackTracePattern = /\bat\s+\S+\s+\([^)]+:\d+:\d+\)/;
|
|
7989
8121
|
const linesToFilter = allLines ?? lines;
|
|
7990
|
-
const
|
|
8122
|
+
const stdLevelFilteringActive = (options.type === "server-std" || options.type === "client-std") && Boolean(normalizeRequestedStdLevels(options.levels));
|
|
8123
|
+
const filteredLines = stdLevelFilteringActive ? linesToFilter : linesToFilter.filter((line) => !stackTracePattern.test(line));
|
|
7991
8124
|
const maxLines = options.maxLines ?? 30;
|
|
7992
8125
|
const offset = options.offset ?? 0;
|
|
7993
8126
|
const endExclusive = Math.max(0, filteredLines.length - offset);
|
|
7994
8127
|
const start = Math.max(0, endExclusive - maxLines);
|
|
7995
|
-
const paginatedLogs = filteredLines.slice(start, endExclusive);
|
|
8128
|
+
const paginatedLogs = stdLevelFilteringActive ? lines : filteredLines.slice(start, endExclusive);
|
|
7996
8129
|
return {
|
|
7997
8130
|
hasError: hasErrorInStdLines(linesForErrorCheck),
|
|
7998
|
-
totalLinesCount: filteredLines.length,
|
|
8131
|
+
totalLinesCount: stdLevelFilteringActive ? totalLinesCount : filteredLines.length,
|
|
7999
8132
|
logs: paginatedLogs
|
|
8000
8133
|
};
|
|
8001
8134
|
}
|
|
@@ -8059,19 +8192,25 @@ function parseLogType(input) {
|
|
|
8059
8192
|
if (LOG_TYPES.includes(value)) {
|
|
8060
8193
|
return value;
|
|
8061
8194
|
}
|
|
8062
|
-
throw new Error(
|
|
8195
|
+
throw new Error(
|
|
8196
|
+
`Invalid --type: ${String(input)}. Expected one of: ${LOG_TYPES.join(", ")}`
|
|
8197
|
+
);
|
|
8063
8198
|
}
|
|
8064
8199
|
function parsePositiveInt(input, flagName) {
|
|
8065
8200
|
const value = typeof input === "number" ? input : Number.parseInt(String(input), 10);
|
|
8066
8201
|
if (!Number.isFinite(value) || value <= 0) {
|
|
8067
|
-
throw new Error(
|
|
8202
|
+
throw new Error(
|
|
8203
|
+
`Invalid ${flagName}: ${String(input)}. Expected a positive integer.`
|
|
8204
|
+
);
|
|
8068
8205
|
}
|
|
8069
8206
|
return value;
|
|
8070
8207
|
}
|
|
8071
8208
|
function parseNonNegativeInt(input, flagName) {
|
|
8072
8209
|
const value = typeof input === "number" ? input : Number.parseInt(String(input), 10);
|
|
8073
8210
|
if (!Number.isFinite(value) || value < 0) {
|
|
8074
|
-
throw new Error(
|
|
8211
|
+
throw new Error(
|
|
8212
|
+
`Invalid ${flagName}: ${String(input)}. Expected a non-negative integer.`
|
|
8213
|
+
);
|
|
8075
8214
|
}
|
|
8076
8215
|
return value;
|
|
8077
8216
|
}
|
|
@@ -8084,7 +8223,10 @@ var readLogsCommand = {
|
|
|
8084
8223
|
name: "read-logs",
|
|
8085
8224
|
description: "Read latest logs from log files",
|
|
8086
8225
|
register(program) {
|
|
8087
|
-
program.command(this.name).description(this.description).option("--dir <path>", "Logs directory", "/tmp").option("--type <type>", `Log type: ${LOG_TYPES.join("|")}`, "server-std").option("--max-lines <lines>", "Max lines to return", "30").option("--offset <lines>", "Skip latest N lines for pagination", "0").option("--trace-id <id>", "Filter structured logs by trace id").option(
|
|
8226
|
+
program.command(this.name).description(this.description).option("--dir <path>", "Logs directory", "/tmp").option("--type <type>", `Log type: ${LOG_TYPES.join("|")}`, "server-std").option("--max-lines <lines>", "Max lines to return", "30").option("--offset <lines>", "Skip latest N lines for pagination", "0").option("--trace-id <id>", "Filter structured logs by trace id").option(
|
|
8227
|
+
"--level <levels>",
|
|
8228
|
+
"Filter structured logs or std diagnostic blocks by level (comma-separated)"
|
|
8229
|
+
).action(async (rawOptions) => {
|
|
8088
8230
|
try {
|
|
8089
8231
|
const logDir = typeof rawOptions.dir === "string" ? rawOptions.dir : "/tmp";
|
|
8090
8232
|
const type = parseLogType(rawOptions.type);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/fullstack-cli",
|
|
3
|
-
"version": "1.1.68-alpha.
|
|
3
|
+
"version": "1.1.68-alpha.20261020063206",
|
|
4
4
|
"description": "CLI tool for fullstack template management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@lark-apaas/http-client": "0.1.
|
|
34
|
+
"@lark-apaas/http-client": "^0.1.7",
|
|
35
35
|
"@lydell/node-pty": "1.1.0",
|
|
36
36
|
"@vercel/nft": "^0.30.3",
|
|
37
37
|
"commander": "^13.0.0",
|