@sfmc-bds/cli 0.1.0 → 0.2.0-beta.1
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/README.md +7 -1
- package/dist/cli-result.d.ts +12 -0
- package/dist/cli-result.d.ts.map +1 -0
- package/dist/cli-result.js +15 -0
- package/dist/cli-result.js.map +7 -0
- package/dist/commands-behavior-pack.d.ts +11 -42
- package/dist/commands-behavior-pack.d.ts.map +1 -1
- package/dist/commands-behavior-pack.js +40 -159
- package/dist/commands-behavior-pack.js.map +7 -1
- package/dist/commands-reload.d.ts +9 -0
- package/dist/commands-reload.d.ts.map +1 -0
- package/dist/commands-reload.js +30 -0
- package/dist/commands-reload.js.map +7 -0
- package/dist/commands.d.ts +7 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +182 -172
- package/dist/commands.js.map +7 -1
- package/dist/i18n/index.d.ts +26 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +107 -0
- package/dist/i18n/index.js.map +7 -0
- package/dist/i18n/locales/en.d.ts +381 -0
- package/dist/i18n/locales/en.d.ts.map +1 -0
- package/dist/i18n/locales/en.js +393 -0
- package/dist/i18n/locales/en.js.map +7 -0
- package/dist/i18n/locales/zh-CN.d.ts +4 -0
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -0
- package/dist/i18n/locales/zh-CN.js +379 -0
- package/dist/i18n/locales/zh-CN.js.map +7 -0
- package/dist/i18n/types.d.ts +7 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +17 -0
- package/dist/i18n/types.js.map +7 -0
- package/dist/index.d.ts +5 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -43
- package/dist/index.js.map +7 -1
- package/dist/interactive-prompts.d.ts +8 -0
- package/dist/interactive-prompts.d.ts.map +1 -0
- package/dist/interactive-prompts.js +57 -0
- package/dist/interactive-prompts.js.map +7 -0
- package/dist/locale-command.d.ts +3 -0
- package/dist/locale-command.d.ts.map +1 -0
- package/dist/locale-command.js +19 -0
- package/dist/locale-command.js.map +7 -0
- package/dist/log-filter.d.ts +69 -0
- package/dist/log-filter.d.ts.map +1 -0
- package/dist/log-filter.js +150 -0
- package/dist/log-filter.js.map +7 -0
- package/dist/logs.d.ts +33 -8
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +232 -194
- package/dist/logs.js.map +7 -1
- package/dist/main.js +135 -173
- package/dist/main.js.map +7 -1
- package/dist/module-commands.d.ts +43 -4
- package/dist/module-commands.d.ts.map +1 -1
- package/dist/module-commands.js +440 -327
- package/dist/module-commands.js.map +7 -1
- package/dist/module-fingerprint.d.ts +7 -0
- package/dist/module-fingerprint.d.ts.map +1 -0
- package/dist/module-fingerprint.js +31 -0
- package/dist/module-fingerprint.js.map +7 -0
- package/dist/module-wizard.d.ts +14 -0
- package/dist/module-wizard.d.ts.map +1 -0
- package/dist/module-wizard.js +313 -0
- package/dist/module-wizard.js.map +7 -0
- package/dist/pack-lifecycle.d.ts +95 -0
- package/dist/pack-lifecycle.d.ts.map +1 -0
- package/dist/pack-lifecycle.js +634 -0
- package/dist/pack-lifecycle.js.map +7 -0
- package/dist/pack-update/bindings.d.ts +12 -0
- package/dist/pack-update/bindings.d.ts.map +1 -0
- package/dist/pack-update/bindings.js +64 -0
- package/dist/pack-update/bindings.js.map +7 -0
- package/dist/pack-update/config.d.ts +22 -0
- package/dist/pack-update/config.d.ts.map +1 -0
- package/dist/pack-update/config.js +141 -0
- package/dist/pack-update/config.js.map +7 -0
- package/dist/pack-update/providers/curseforge.d.ts +23 -0
- package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
- package/dist/pack-update/providers/curseforge.js +229 -0
- package/dist/pack-update/providers/curseforge.js.map +7 -0
- package/dist/pack-update/providers/index.d.ts +16 -0
- package/dist/pack-update/providers/index.d.ts.map +1 -0
- package/dist/pack-update/providers/index.js +37 -0
- package/dist/pack-update/providers/index.js.map +7 -0
- package/dist/pack-update/service.d.ts +21 -0
- package/dist/pack-update/service.d.ts.map +1 -0
- package/dist/pack-update/service.js +572 -0
- package/dist/pack-update/service.js.map +7 -0
- package/dist/pack-update/types.d.ts +126 -0
- package/dist/pack-update/types.d.ts.map +1 -0
- package/dist/pack-update/types.js +8 -0
- package/dist/pack-update/types.js.map +7 -0
- package/dist/pack-update/version-policy.d.ts +81 -0
- package/dist/pack-update/version-policy.d.ts.map +1 -0
- package/dist/pack-update/version-policy.js +210 -0
- package/dist/pack-update/version-policy.js.map +7 -0
- package/dist/registry.d.ts +12 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +73 -106
- package/dist/registry.js.map +7 -1
- package/dist/remote-agent.d.ts.map +1 -1
- package/dist/remote-agent.js +160 -176
- package/dist/remote-agent.js.map +7 -1
- package/dist/repl.d.ts +4 -0
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +683 -605
- package/dist/repl.js.map +7 -1
- package/dist/runtime.d.ts +40 -14
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +185 -62
- package/dist/runtime.js.map +7 -1
- package/dist/services.d.ts +2 -0
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +251 -238
- package/dist/services.js.map +7 -1
- package/dist/sfmc-modules-root.d.ts +24 -0
- package/dist/sfmc-modules-root.d.ts.map +1 -0
- package/dist/sfmc-modules-root.js +70 -0
- package/dist/sfmc-modules-root.js.map +7 -0
- package/dist/theme.d.ts +4 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +134 -48
- package/dist/theme.js.map +7 -1
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +363 -438
- package/dist/wizard.js.map +7 -1
- package/dist/world-packs.d.ts +37 -0
- package/dist/world-packs.d.ts.map +1 -0
- package/dist/world-packs.js +872 -0
- package/dist/world-packs.js.map +7 -0
- package/package.json +10 -10
- package/dist/dispatcher.d.ts +0 -13
- package/dist/dispatcher.d.ts.map +0 -1
- package/dist/dispatcher.js +0 -23
- package/dist/dispatcher.js.map +0 -1
- package/dist/terminal.d.ts +0 -3
- package/dist/terminal.d.ts.map +0 -1
- package/dist/terminal.js +0 -178
- package/dist/terminal.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,43 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
import { ROOT, isMonorepoLayout, isRuntimeInitialized, resolveServiceScript, resolveFetchModule, spawnService, spawnServiceSync } from "./runtime.js";
|
|
2
|
+
import {
|
|
3
|
+
SERVICE_NAMES,
|
|
4
|
+
refreshServices,
|
|
5
|
+
startAll,
|
|
6
|
+
stopAll,
|
|
7
|
+
forceStopAll,
|
|
8
|
+
serviceStatus,
|
|
9
|
+
services,
|
|
10
|
+
START_ORDER
|
|
11
|
+
} from "./services.js";
|
|
12
|
+
import { pushLog, onLog, getAllLogs, getRecentLogs } from "./logs.js";
|
|
13
|
+
import { startRepl, getHelp, HELP } from "./repl.js";
|
|
14
|
+
import { t, getLocale, setLocale, initLocale } from "./i18n/index.js";
|
|
15
|
+
import { runWizard } from "./wizard.js";
|
|
16
|
+
import { cmdModuleList, cmdModuleInstall, cmdModuleUninstall, cmdModuleVerify, cmdModuleInfo } from "./module-commands.js";
|
|
17
|
+
export {
|
|
18
|
+
HELP,
|
|
19
|
+
ROOT,
|
|
20
|
+
SERVICE_NAMES,
|
|
21
|
+
START_ORDER,
|
|
22
|
+
cmdModuleInfo,
|
|
23
|
+
cmdModuleInstall,
|
|
24
|
+
cmdModuleList,
|
|
25
|
+
cmdModuleUninstall,
|
|
26
|
+
cmdModuleVerify,
|
|
27
|
+
forceStopAll,
|
|
28
|
+
getAllLogs,
|
|
29
|
+
getHelp,
|
|
30
|
+
getLocale,
|
|
31
|
+
getRecentLogs,
|
|
32
|
+
initLocale,
|
|
33
|
+
isMonorepoLayout,
|
|
34
|
+
isRuntimeInitialized,
|
|
35
|
+
onLog,
|
|
36
|
+
pushLog,
|
|
37
|
+
refreshServices,
|
|
38
|
+
resolveFetchModule,
|
|
39
|
+
resolveServiceScript,
|
|
40
|
+
runWizard,
|
|
41
|
+
serviceStatus,
|
|
42
|
+
services,
|
|
43
|
+
setLocale,
|
|
44
|
+
spawnService,
|
|
45
|
+
spawnServiceSync,
|
|
46
|
+
startAll,
|
|
47
|
+
startRepl,
|
|
48
|
+
stopAll,
|
|
49
|
+
t
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * sfmc/ public runtime surface (Stage J \u2014 minimum entry design)\n *\n * This is the clean API that downstream callers (CLI commands,\n * external scripts, CI tooling) consume to manage the runtime stack\n * without re-implementing process lifecycle logic.\n *\n * Design:\n * - Single process tree. sfmc/ does not spawn itself recursively \u2014 it spawns\n * the actual services (db-server, qq-bridge, bds-tools, BDS).\n * - `ROOT` from runtime.ts describes the deployment root so callers\n * can adapt (path lookup, config dir).\n * - Service lifecycle goes through ServiceRegistry (start/stop/restart/status).\n *\n * Re-exports are deliberately thin: each item is a stable contract. Internal\n * helpers (LogLine buffers, child-process piping) are NOT re-exported.\n */\n\nexport { ROOT, isMonorepoLayout, isRuntimeInitialized, resolveServiceScript, resolveFetchModule, spawnService, spawnServiceSync, type ServiceId } from \"./runtime.js\";\n\nexport {\n SERVICE_NAMES,\n type ServiceName,\n type ServiceStatus,\n refreshServices,\n startAll,\n stopAll,\n forceStopAll,\n serviceStatus,\n services,\n START_ORDER,\n} from \"./services.js\";\n\nexport { pushLog, onLog, getAllLogs, getRecentLogs, type UnifiedLog, type LogLevel, type LogSource } from \"./logs.js\";\n\nexport { startRepl, getHelp, HELP } from \"./repl.js\";\nexport { t, getLocale, setLocale, initLocale, type Locale } from \"./i18n/index.js\";\nexport { runWizard } from \"./wizard.js\";\nexport { cmdModuleList, cmdModuleInstall, cmdModuleUninstall, cmdModuleVerify, cmdModuleInfo } from \"./module-commands.js\";\n"],
|
|
5
|
+
"mappings": "AAkBA,SAAS,MAAM,kBAAkB,sBAAsB,sBAAsB,oBAAoB,cAAc,wBAAwC;AAEvJ;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,SAAS,OAAO,YAAY,qBAAqE;AAE1G,SAAS,WAAW,SAAS,YAAY;AACzC,SAAS,GAAG,WAAW,WAAW,kBAA+B;AACjE,SAAS,iBAAiB;AAC1B,SAAS,eAAe,kBAAkB,oBAAoB,iBAAiB,qBAAqB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** 与 init 向导一致:文本输入或系统文件夹选择器。 */
|
|
2
|
+
export declare function pickDirectory(message: string, defaultDirectory: string): Promise<string>;
|
|
3
|
+
/** Windows 文件夹选择器;非 Windows 或失败时返回 null。 */
|
|
4
|
+
export declare function pickDirectoryDialog(title: string, defaultDirectory: string): string | null;
|
|
5
|
+
export declare function ensureDirectory(directory: string): boolean;
|
|
6
|
+
/** 将用户输入规范为绝对路径(兼容含 # 的 Windows 路径)。 */
|
|
7
|
+
export declare function resolveUserPath(input: string, base?: string): string;
|
|
8
|
+
//# sourceMappingURL=interactive-prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-prompts.d.ts","sourceRoot":"","sources":["../src/interactive-prompts.ts"],"names":[],"mappings":"AAMA,iCAAiC;AACjC,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa9F;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqB1F;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,SAAgB,GAAG,MAAM,CAE3E"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isCancel, select, text } from "@clack/prompts";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { t } from "./i18n/index.js";
|
|
6
|
+
async function pickDirectory(message, defaultDirectory) {
|
|
7
|
+
const method = await select({
|
|
8
|
+
message,
|
|
9
|
+
options: [
|
|
10
|
+
{ value: "text", label: t("prompt.enterPath"), hint: defaultDirectory },
|
|
11
|
+
{ value: "browse", label: t("prompt.browse"), hint: t("prompt.browseHint") }
|
|
12
|
+
]
|
|
13
|
+
});
|
|
14
|
+
if (isCancel(method)) return defaultDirectory;
|
|
15
|
+
if (method === "browse") return pickDirectoryDialog(message, defaultDirectory) ?? defaultDirectory;
|
|
16
|
+
const selected = await text({ message, initialValue: defaultDirectory });
|
|
17
|
+
return isCancel(selected) || !selected ? defaultDirectory : selected;
|
|
18
|
+
}
|
|
19
|
+
function pickDirectoryDialog(title, defaultDirectory) {
|
|
20
|
+
if (process.platform !== "win32") return null;
|
|
21
|
+
const escape = (value) => value.replace(/'/g, "''");
|
|
22
|
+
const script = [
|
|
23
|
+
"Add-Type -AssemblyName System.Windows.Forms",
|
|
24
|
+
"$dialog = New-Object System.Windows.Forms.FolderBrowserDialog",
|
|
25
|
+
`$dialog.Description = '${escape(title)}'`,
|
|
26
|
+
`$dialog.SelectedPath = '${escape(defaultDirectory)}'`,
|
|
27
|
+
"if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $dialog.SelectedPath }"
|
|
28
|
+
].join("; ");
|
|
29
|
+
try {
|
|
30
|
+
const output = execFileSync("powershell.exe", ["-NoProfile", "-STA", "-Command", script], {
|
|
31
|
+
encoding: "utf-8",
|
|
32
|
+
timeout: 3e4,
|
|
33
|
+
windowsHide: true
|
|
34
|
+
});
|
|
35
|
+
return output.trim() || null;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function ensureDirectory(directory) {
|
|
41
|
+
try {
|
|
42
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
43
|
+
return fs.statSync(directory).isDirectory();
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function resolveUserPath(input, base = process.cwd()) {
|
|
49
|
+
return path.resolve(base, input.trim());
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
ensureDirectory,
|
|
53
|
+
pickDirectory,
|
|
54
|
+
pickDirectoryDialog,
|
|
55
|
+
resolveUserPath
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=interactive-prompts.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/interactive-prompts.ts"],
|
|
4
|
+
"sourcesContent": ["import { isCancel, select, text } from \"@clack/prompts\";\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { t } from \"./i18n/index.js\";\n\n/** \u4E0E init \u5411\u5BFC\u4E00\u81F4\uFF1A\u6587\u672C\u8F93\u5165\u6216\u7CFB\u7EDF\u6587\u4EF6\u5939\u9009\u62E9\u5668\u3002 */\nexport async function pickDirectory(message: string, defaultDirectory: string): Promise<string> {\n const method = await select({\n message,\n options: [\n { value: \"text\", label: t(\"prompt.enterPath\"), hint: defaultDirectory },\n { value: \"browse\", label: t(\"prompt.browse\"), hint: t(\"prompt.browseHint\") },\n ],\n });\n if (isCancel(method)) return defaultDirectory;\n if (method === \"browse\") return pickDirectoryDialog(message, defaultDirectory) ?? defaultDirectory;\n\n const selected = await text({ message, initialValue: defaultDirectory });\n return isCancel(selected) || !selected ? defaultDirectory : selected;\n}\n\n/** Windows \u6587\u4EF6\u5939\u9009\u62E9\u5668\uFF1B\u975E Windows \u6216\u5931\u8D25\u65F6\u8FD4\u56DE null\u3002 */\nexport function pickDirectoryDialog(title: string, defaultDirectory: string): string | null {\n if (process.platform !== \"win32\") return null;\n const escape = (value: string): string => value.replace(/'/g, \"''\");\n const script = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$dialog = New-Object System.Windows.Forms.FolderBrowserDialog\",\n `$dialog.Description = '${escape(title)}'`,\n `$dialog.SelectedPath = '${escape(defaultDirectory)}'`,\n \"if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $dialog.SelectedPath }\",\n ].join(\"; \");\n\n try {\n const output = execFileSync(\"powershell.exe\", [\"-NoProfile\", \"-STA\", \"-Command\", script], {\n encoding: \"utf-8\",\n timeout: 30_000,\n windowsHide: true,\n });\n return output.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function ensureDirectory(directory: string): boolean {\n try {\n fs.mkdirSync(directory, { recursive: true });\n return fs.statSync(directory).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** \u5C06\u7528\u6237\u8F93\u5165\u89C4\u8303\u4E3A\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u517C\u5BB9\u542B # \u7684 Windows \u8DEF\u5F84\uFF09\u3002 */\nexport function resolveUserPath(input: string, base = process.cwd()): string {\n return path.resolve(base, input.trim());\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,UAAU,QAAQ,YAAY;AACvC,SAAS,oBAAoB;AAC7B,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,SAAS;AAGlB,eAAsB,cAAc,SAAiB,kBAA2C;AAC9F,QAAM,SAAS,MAAM,OAAO;AAAA,IAC1B;AAAA,IACA,SAAS;AAAA,MACP,EAAE,OAAO,QAAQ,OAAO,EAAE,kBAAkB,GAAG,MAAM,iBAAiB;AAAA,MACtE,EAAE,OAAO,UAAU,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,mBAAmB,EAAE;AAAA,IAC7E;AAAA,EACF,CAAC;AACD,MAAI,SAAS,MAAM,EAAG,QAAO;AAC7B,MAAI,WAAW,SAAU,QAAO,oBAAoB,SAAS,gBAAgB,KAAK;AAElF,QAAM,WAAW,MAAM,KAAK,EAAE,SAAS,cAAc,iBAAiB,CAAC;AACvE,SAAO,SAAS,QAAQ,KAAK,CAAC,WAAW,mBAAmB;AAC9D;AAGO,SAAS,oBAAoB,OAAe,kBAAyC;AAC1F,MAAI,QAAQ,aAAa,QAAS,QAAO;AACzC,QAAM,SAAS,CAAC,UAA0B,MAAM,QAAQ,MAAM,IAAI;AAClE,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA,0BAA0B,OAAO,KAAK,CAAC;AAAA,IACvC,2BAA2B,OAAO,gBAAgB,CAAC;AAAA,IACnD;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,MAAI;AACF,UAAM,SAAS,aAAa,kBAAkB,CAAC,cAAc,QAAQ,YAAY,MAAM,GAAG;AAAA,MACxF,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf,CAAC;AACD,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,gBAAgB,WAA4B;AAC1D,MAAI;AACF,OAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,WAAO,GAAG,SAAS,SAAS,EAAE,YAAY;AAAA,EAC5C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,gBAAgB,OAAe,OAAO,QAAQ,IAAI,GAAW;AAC3E,SAAO,KAAK,QAAQ,MAAM,MAAM,KAAK,CAAC;AACxC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale-command.d.ts","sourceRoot":"","sources":["../src/locale-command.ts"],"names":[],"mappings":"AAIA,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAWhD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getLocale, normalizeLocale, persistLocale, t } from "./i18n/index.js";
|
|
2
|
+
import { ROOT } from "./runtime.js";
|
|
3
|
+
import { c } from "./theme.js";
|
|
4
|
+
function cmdLocale(args) {
|
|
5
|
+
const raw = args[0];
|
|
6
|
+
if (!raw) {
|
|
7
|
+
return c.text(t("locale.current", { locale: getLocale() }));
|
|
8
|
+
}
|
|
9
|
+
const locale = normalizeLocale(raw);
|
|
10
|
+
if (!locale) {
|
|
11
|
+
return c.red(t("locale.invalid", { value: raw })) + "\n" + c.dim(t("locale.usage"));
|
|
12
|
+
}
|
|
13
|
+
persistLocale(ROOT, locale);
|
|
14
|
+
return c.green(t("locale.set", { locale }));
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
cmdLocale
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=locale-command.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/locale-command.ts"],
|
|
4
|
+
"sourcesContent": ["import { getLocale, normalizeLocale, persistLocale, t } from \"./i18n/index.js\";\nimport { ROOT } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\n\n/** `sfmc locale [zh-CN|en]` \u2014 \u67E5\u770B\u6216\u8BBE\u7F6E CLI \u8BED\u8A00\u5E76\u5199\u5165 runtime.json\u3002 */\nexport function cmdLocale(args: string[]): string {\n const raw = args[0];\n if (!raw) {\n return c.text(t(\"locale.current\", { locale: getLocale() }));\n }\n const locale = normalizeLocale(raw);\n if (!locale) {\n return c.red(t(\"locale.invalid\", { value: raw })) + \"\\n\" + c.dim(t(\"locale.usage\"));\n }\n persistLocale(ROOT, locale);\n return c.green(t(\"locale.set\", { locale }));\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,WAAW,iBAAiB,eAAe,SAAS;AAC7D,SAAS,YAAY;AACrB,SAAS,SAAS;AAGX,SAAS,UAAU,MAAwB;AAChD,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,QAAQ,UAAU,EAAE,CAAC,CAAC;AAAA,EAC5D;AACA,QAAM,SAAS,gBAAgB,GAAG;AAClC,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC;AAAA,EACpF;AACA,gBAAc,MAAM,MAAM;AAC1B,SAAO,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AAC5C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { LogLevel } from "@sfmc-bds/sdk/logs";
|
|
2
|
+
export type LogFilterMode = "drop" | "keep";
|
|
3
|
+
export type LogFilterApplyTo = "display" | "all";
|
|
4
|
+
export interface LogFilterRule {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
sources?: string[];
|
|
7
|
+
levels?: LogLevel[];
|
|
8
|
+
contains?: string;
|
|
9
|
+
/** JS RegExp 源;支持前缀 (?i) 表示忽略大小写 */
|
|
10
|
+
regex?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface LogFilterConfig {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
mode: LogFilterMode;
|
|
15
|
+
applyTo: LogFilterApplyTo;
|
|
16
|
+
rules: LogFilterRule[];
|
|
17
|
+
}
|
|
18
|
+
export type LogFilterEntry = {
|
|
19
|
+
text: string;
|
|
20
|
+
source: string;
|
|
21
|
+
level: LogLevel;
|
|
22
|
+
};
|
|
23
|
+
export declare function logFilterConfigPath(): string;
|
|
24
|
+
/** 确保 configs/log-filter.json 存在(委托 SDK ensureSchemaConfig,禁止手写 withConfigSchema) */
|
|
25
|
+
export declare function ensureLogFilterConfigFile(): string;
|
|
26
|
+
type CompiledRule = {
|
|
27
|
+
sources?: Set<string>;
|
|
28
|
+
levels?: Set<string>;
|
|
29
|
+
contains?: string;
|
|
30
|
+
regex?: RegExp;
|
|
31
|
+
};
|
|
32
|
+
type CompiledFilter = {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
mode: LogFilterMode;
|
|
35
|
+
applyTo: LogFilterApplyTo;
|
|
36
|
+
rules: CompiledRule[];
|
|
37
|
+
mtimeMs: number;
|
|
38
|
+
};
|
|
39
|
+
/** 将 (?i) 前缀转为 RegExp i 旗标(JS 无内联 (?i)) */
|
|
40
|
+
export declare function compileLogFilterRegex(src: string): RegExp | null;
|
|
41
|
+
/**
|
|
42
|
+
* 加载并编译过滤配置(按文件 mtime 热读)。
|
|
43
|
+
* onBadRegex:正则非法时回调(由 logs 层打 warn,避免循环依赖)。
|
|
44
|
+
*/
|
|
45
|
+
export declare function getCompiledLogFilter(onBadRegex?: (src: string) => void): CompiledFilter;
|
|
46
|
+
/** 单条规则是否命中(同条 AND) */
|
|
47
|
+
export declare function ruleMatchesEntry(rule: CompiledRule, entry: LogFilterEntry): boolean;
|
|
48
|
+
/** 任一规则命中即为 matched */
|
|
49
|
+
export declare function entryMatchesAnyRule(entry: LogFilterEntry, rules: CompiledRule[]): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* 是否应丢弃该条(对展示/内存而言)。
|
|
52
|
+
* enabled=false → 不丢;keep 模式未匹配 → 丢;drop 模式匹配 → 丢。
|
|
53
|
+
*/
|
|
54
|
+
export declare function shouldDropForDisplay(entry: LogFilterEntry, filter: CompiledFilter): boolean;
|
|
55
|
+
/** 是否应跳过落盘(仅 applyTo=all 时与 display 一致) */
|
|
56
|
+
export declare function shouldDropForDisk(entry: LogFilterEntry, filter: CompiledFilter): boolean;
|
|
57
|
+
/** 测试用:清空缓存 */
|
|
58
|
+
export declare function resetLogFilterCacheForTests(): void;
|
|
59
|
+
/**
|
|
60
|
+
* 纯函数判定(不读盘):供单测与调用方表驱动。
|
|
61
|
+
* dropDisplay / dropDisk 语义与 pushLog 一致。
|
|
62
|
+
*/
|
|
63
|
+
export declare function evaluateLogFilter(entry: LogFilterEntry, cfg: LogFilterConfig): {
|
|
64
|
+
dropDisplay: boolean;
|
|
65
|
+
dropDisk: boolean;
|
|
66
|
+
matched: boolean;
|
|
67
|
+
};
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=log-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-filter.d.ts","sourceRoot":"","sources":["../src/log-filter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAKnD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAC5C,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,KAAK,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;CACjB,CAAC;AASF,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,qFAAqF;AACrF,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,2CAA2C;AAC3C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYhE;AAiDD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,cAAc,CA8BvF;AAED,uBAAuB;AACvB,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAMnF;AAED,uBAAuB;AACvB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAGzF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAK3F;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAGxF;AAED,eAAe;AACf,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,eAAe,GACnB;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAa/D"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { ensureSchemaConfig, readJson, stripConfigMeta } from "@sfmc-bds/sdk/node/config";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { ROOT } from "./runtime.js";
|
|
5
|
+
const DEFAULTS = {
|
|
6
|
+
enabled: false,
|
|
7
|
+
mode: "drop",
|
|
8
|
+
applyTo: "display",
|
|
9
|
+
rules: []
|
|
10
|
+
};
|
|
11
|
+
function logFilterConfigPath() {
|
|
12
|
+
return path.join(ROOT, "configs", "log-filter.json");
|
|
13
|
+
}
|
|
14
|
+
function ensureLogFilterConfigFile() {
|
|
15
|
+
ensureSchemaConfig(ROOT, "log-filter.json", "log_filter", { ...DEFAULTS });
|
|
16
|
+
return logFilterConfigPath();
|
|
17
|
+
}
|
|
18
|
+
let cache = null;
|
|
19
|
+
function compileLogFilterRegex(src) {
|
|
20
|
+
let pattern = String(src ?? "");
|
|
21
|
+
let flags = "";
|
|
22
|
+
if (pattern.startsWith("(?i)")) {
|
|
23
|
+
pattern = pattern.slice(4);
|
|
24
|
+
flags = "i";
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return new RegExp(pattern, flags);
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function compileRules(rules, onBadRegex) {
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const r of rules) {
|
|
35
|
+
if (r.enabled === false) continue;
|
|
36
|
+
const hasAny = r.sources && r.sources.length > 0 || r.levels && r.levels.length > 0 || typeof r.contains === "string" && r.contains.length > 0 || typeof r.regex === "string" && r.regex.length > 0;
|
|
37
|
+
if (!hasAny) continue;
|
|
38
|
+
const compiled = {};
|
|
39
|
+
if (r.sources && r.sources.length > 0) {
|
|
40
|
+
compiled.sources = new Set(r.sources.map((s) => s.toLowerCase()));
|
|
41
|
+
}
|
|
42
|
+
if (r.levels && r.levels.length > 0) {
|
|
43
|
+
compiled.levels = new Set(r.levels.map((l) => l.toLowerCase()));
|
|
44
|
+
}
|
|
45
|
+
if (typeof r.contains === "string" && r.contains.length > 0) {
|
|
46
|
+
compiled.contains = r.contains;
|
|
47
|
+
}
|
|
48
|
+
if (typeof r.regex === "string" && r.regex.length > 0) {
|
|
49
|
+
const re = compileLogFilterRegex(r.regex);
|
|
50
|
+
if (!re) {
|
|
51
|
+
onBadRegex?.(r.regex);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
compiled.regex = re;
|
|
55
|
+
}
|
|
56
|
+
out.push(compiled);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
function normalizeConfig(raw) {
|
|
61
|
+
const stripped = stripConfigMeta(raw);
|
|
62
|
+
const mode = stripped.mode === "keep" ? "keep" : "drop";
|
|
63
|
+
const applyTo = stripped.applyTo === "all" ? "all" : "display";
|
|
64
|
+
const rules = Array.isArray(stripped.rules) ? stripped.rules : [];
|
|
65
|
+
return {
|
|
66
|
+
enabled: Boolean(stripped.enabled),
|
|
67
|
+
mode,
|
|
68
|
+
applyTo,
|
|
69
|
+
rules
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function getCompiledLogFilter(onBadRegex) {
|
|
73
|
+
const p = ensureLogFilterConfigFile();
|
|
74
|
+
let mtimeMs = 0;
|
|
75
|
+
try {
|
|
76
|
+
mtimeMs = fs.statSync(p).mtimeMs;
|
|
77
|
+
} catch {
|
|
78
|
+
mtimeMs = 0;
|
|
79
|
+
}
|
|
80
|
+
if (cache && cache.mtimeMs === mtimeMs) return cache;
|
|
81
|
+
let cfg = { ...DEFAULTS };
|
|
82
|
+
const raw = readJson(p);
|
|
83
|
+
if (raw) {
|
|
84
|
+
try {
|
|
85
|
+
cfg = normalizeConfig(raw);
|
|
86
|
+
} catch {
|
|
87
|
+
cfg = { ...DEFAULTS };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const rules = compileRules(cfg.rules, onBadRegex);
|
|
91
|
+
cache = {
|
|
92
|
+
enabled: cfg.enabled,
|
|
93
|
+
mode: cfg.mode,
|
|
94
|
+
applyTo: cfg.applyTo,
|
|
95
|
+
rules,
|
|
96
|
+
mtimeMs
|
|
97
|
+
};
|
|
98
|
+
return cache;
|
|
99
|
+
}
|
|
100
|
+
function ruleMatchesEntry(rule, entry) {
|
|
101
|
+
if (rule.sources && !rule.sources.has(entry.source.toLowerCase())) return false;
|
|
102
|
+
if (rule.levels && !rule.levels.has(entry.level.toLowerCase())) return false;
|
|
103
|
+
if (rule.contains != null && !entry.text.includes(rule.contains)) return false;
|
|
104
|
+
if (rule.regex && !rule.regex.test(entry.text)) return false;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
function entryMatchesAnyRule(entry, rules) {
|
|
108
|
+
if (rules.length === 0) return false;
|
|
109
|
+
return rules.some((r) => ruleMatchesEntry(r, entry));
|
|
110
|
+
}
|
|
111
|
+
function shouldDropForDisplay(entry, filter) {
|
|
112
|
+
if (!filter.enabled) return false;
|
|
113
|
+
const matched = entryMatchesAnyRule(entry, filter.rules);
|
|
114
|
+
if (filter.mode === "keep") return !matched;
|
|
115
|
+
return matched;
|
|
116
|
+
}
|
|
117
|
+
function shouldDropForDisk(entry, filter) {
|
|
118
|
+
if (filter.applyTo !== "all") return false;
|
|
119
|
+
return shouldDropForDisplay(entry, filter);
|
|
120
|
+
}
|
|
121
|
+
function resetLogFilterCacheForTests() {
|
|
122
|
+
cache = null;
|
|
123
|
+
}
|
|
124
|
+
function evaluateLogFilter(entry, cfg) {
|
|
125
|
+
const compiled = {
|
|
126
|
+
enabled: cfg.enabled,
|
|
127
|
+
mode: cfg.mode,
|
|
128
|
+
applyTo: cfg.applyTo,
|
|
129
|
+
rules: compileRules(cfg.rules),
|
|
130
|
+
mtimeMs: 0
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
matched: entryMatchesAnyRule(entry, compiled.rules),
|
|
134
|
+
dropDisplay: shouldDropForDisplay(entry, compiled),
|
|
135
|
+
dropDisk: shouldDropForDisk(entry, compiled)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
compileLogFilterRegex,
|
|
140
|
+
ensureLogFilterConfigFile,
|
|
141
|
+
entryMatchesAnyRule,
|
|
142
|
+
evaluateLogFilter,
|
|
143
|
+
getCompiledLogFilter,
|
|
144
|
+
logFilterConfigPath,
|
|
145
|
+
resetLogFilterCacheForTests,
|
|
146
|
+
ruleMatchesEntry,
|
|
147
|
+
shouldDropForDisk,
|
|
148
|
+
shouldDropForDisplay
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=log-filter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/log-filter.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * log-filter.ts \u2014 configs/log-filter.json \u52A0\u8F7D\u4E0E\u5339\u914D\uFF08\u7EAF\u5224\u5B9A + \u70ED\u8BFB\u7F13\u5B58\uFF09\n */\nimport { ensureSchemaConfig, readJson, stripConfigMeta } from \"@sfmc-bds/sdk/node/config\";\nimport type { LogLevel } from \"@sfmc-bds/sdk/logs\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ROOT } from \"./runtime.js\";\n\nexport type LogFilterMode = \"drop\" | \"keep\";\nexport type LogFilterApplyTo = \"display\" | \"all\";\n\nexport interface LogFilterRule {\n enabled?: boolean;\n sources?: string[];\n levels?: LogLevel[];\n contains?: string;\n /** JS RegExp \u6E90\uFF1B\u652F\u6301\u524D\u7F00 (?i) \u8868\u793A\u5FFD\u7565\u5927\u5C0F\u5199 */\n regex?: string;\n}\n\nexport interface LogFilterConfig {\n enabled: boolean;\n mode: LogFilterMode;\n applyTo: LogFilterApplyTo;\n rules: LogFilterRule[];\n}\n\nexport type LogFilterEntry = {\n text: string;\n source: string;\n level: LogLevel;\n};\n\nconst DEFAULTS: LogFilterConfig = {\n enabled: false,\n mode: \"drop\",\n applyTo: \"display\",\n rules: [],\n};\n\nexport function logFilterConfigPath(): string {\n return path.join(ROOT, \"configs\", \"log-filter.json\");\n}\n\n/** \u786E\u4FDD configs/log-filter.json \u5B58\u5728\uFF08\u59D4\u6258 SDK ensureSchemaConfig\uFF0C\u7981\u6B62\u624B\u5199 withConfigSchema\uFF09 */\nexport function ensureLogFilterConfigFile(): string {\n ensureSchemaConfig(ROOT, \"log-filter.json\", \"log_filter\", { ...DEFAULTS } as Record<string, unknown>);\n return logFilterConfigPath();\n}\n\ntype CompiledRule = {\n sources?: Set<string>;\n levels?: Set<string>;\n contains?: string;\n regex?: RegExp;\n};\n\ntype CompiledFilter = {\n enabled: boolean;\n mode: LogFilterMode;\n applyTo: LogFilterApplyTo;\n rules: CompiledRule[];\n mtimeMs: number;\n};\n\nlet cache: CompiledFilter | null = null;\n\n/** \u5C06 (?i) \u524D\u7F00\u8F6C\u4E3A RegExp i \u65D7\u6807\uFF08JS \u65E0\u5185\u8054 (?i)\uFF09 */\nexport function compileLogFilterRegex(src: string): RegExp | null {\n let pattern = String(src ?? \"\");\n let flags = \"\";\n if (pattern.startsWith(\"(?i)\")) {\n pattern = pattern.slice(4);\n flags = \"i\";\n }\n try {\n return new RegExp(pattern, flags);\n } catch {\n return null;\n }\n}\n\nfunction compileRules(rules: LogFilterRule[], onBadRegex?: (src: string) => void): CompiledRule[] {\n const out: CompiledRule[] = [];\n for (const r of rules) {\n if (r.enabled === false) continue;\n const hasAny =\n (r.sources && r.sources.length > 0) ||\n (r.levels && r.levels.length > 0) ||\n (typeof r.contains === \"string\" && r.contains.length > 0) ||\n (typeof r.regex === \"string\" && r.regex.length > 0);\n if (!hasAny) continue;\n\n const compiled: CompiledRule = {};\n if (r.sources && r.sources.length > 0) {\n compiled.sources = new Set(r.sources.map((s) => s.toLowerCase()));\n }\n if (r.levels && r.levels.length > 0) {\n compiled.levels = new Set(r.levels.map((l) => l.toLowerCase()));\n }\n if (typeof r.contains === \"string\" && r.contains.length > 0) {\n compiled.contains = r.contains;\n }\n if (typeof r.regex === \"string\" && r.regex.length > 0) {\n const re = compileLogFilterRegex(r.regex);\n if (!re) {\n onBadRegex?.(r.regex);\n continue;\n }\n compiled.regex = re;\n }\n out.push(compiled);\n }\n return out;\n}\n\nfunction normalizeConfig(raw: Record<string, unknown>): LogFilterConfig {\n const stripped = stripConfigMeta(raw);\n const mode = stripped.mode === \"keep\" ? \"keep\" : \"drop\";\n const applyTo = stripped.applyTo === \"all\" ? \"all\" : \"display\";\n const rules = Array.isArray(stripped.rules) ? (stripped.rules as LogFilterRule[]) : [];\n return {\n enabled: Boolean(stripped.enabled),\n mode,\n applyTo,\n rules,\n };\n}\n\n/**\n * \u52A0\u8F7D\u5E76\u7F16\u8BD1\u8FC7\u6EE4\u914D\u7F6E\uFF08\u6309\u6587\u4EF6 mtime \u70ED\u8BFB\uFF09\u3002\n * onBadRegex\uFF1A\u6B63\u5219\u975E\u6CD5\u65F6\u56DE\u8C03\uFF08\u7531 logs \u5C42\u6253 warn\uFF0C\u907F\u514D\u5FAA\u73AF\u4F9D\u8D56\uFF09\u3002\n */\nexport function getCompiledLogFilter(onBadRegex?: (src: string) => void): CompiledFilter {\n const p = ensureLogFilterConfigFile();\n let mtimeMs = 0;\n try {\n mtimeMs = fs.statSync(p).mtimeMs;\n } catch {\n mtimeMs = 0;\n }\n if (cache && cache.mtimeMs === mtimeMs) return cache;\n\n let cfg = { ...DEFAULTS };\n const raw = readJson<Record<string, unknown>>(p);\n if (raw) {\n try {\n cfg = normalizeConfig(raw);\n } catch {\n cfg = { ...DEFAULTS };\n }\n }\n\n const rules = compileRules(cfg.rules, onBadRegex);\n\n cache = {\n enabled: cfg.enabled,\n mode: cfg.mode,\n applyTo: cfg.applyTo,\n rules,\n mtimeMs,\n };\n return cache;\n}\n\n/** \u5355\u6761\u89C4\u5219\u662F\u5426\u547D\u4E2D\uFF08\u540C\u6761 AND\uFF09 */\nexport function ruleMatchesEntry(rule: CompiledRule, entry: LogFilterEntry): boolean {\n if (rule.sources && !rule.sources.has(entry.source.toLowerCase())) return false;\n if (rule.levels && !rule.levels.has(entry.level.toLowerCase())) return false;\n if (rule.contains != null && !entry.text.includes(rule.contains)) return false;\n if (rule.regex && !rule.regex.test(entry.text)) return false;\n return true;\n}\n\n/** \u4EFB\u4E00\u89C4\u5219\u547D\u4E2D\u5373\u4E3A matched */\nexport function entryMatchesAnyRule(entry: LogFilterEntry, rules: CompiledRule[]): boolean {\n if (rules.length === 0) return false;\n return rules.some((r) => ruleMatchesEntry(r, entry));\n}\n\n/**\n * \u662F\u5426\u5E94\u4E22\u5F03\u8BE5\u6761\uFF08\u5BF9\u5C55\u793A/\u5185\u5B58\u800C\u8A00\uFF09\u3002\n * enabled=false \u2192 \u4E0D\u4E22\uFF1Bkeep \u6A21\u5F0F\u672A\u5339\u914D \u2192 \u4E22\uFF1Bdrop \u6A21\u5F0F\u5339\u914D \u2192 \u4E22\u3002\n */\nexport function shouldDropForDisplay(entry: LogFilterEntry, filter: CompiledFilter): boolean {\n if (!filter.enabled) return false;\n const matched = entryMatchesAnyRule(entry, filter.rules);\n if (filter.mode === \"keep\") return !matched;\n return matched;\n}\n\n/** \u662F\u5426\u5E94\u8DF3\u8FC7\u843D\u76D8\uFF08\u4EC5 applyTo=all \u65F6\u4E0E display \u4E00\u81F4\uFF09 */\nexport function shouldDropForDisk(entry: LogFilterEntry, filter: CompiledFilter): boolean {\n if (filter.applyTo !== \"all\") return false;\n return shouldDropForDisplay(entry, filter);\n}\n\n/** \u6D4B\u8BD5\u7528\uFF1A\u6E05\u7A7A\u7F13\u5B58 */\nexport function resetLogFilterCacheForTests(): void {\n cache = null;\n}\n\n/**\n * \u7EAF\u51FD\u6570\u5224\u5B9A\uFF08\u4E0D\u8BFB\u76D8\uFF09\uFF1A\u4F9B\u5355\u6D4B\u4E0E\u8C03\u7528\u65B9\u8868\u9A71\u52A8\u3002\n * dropDisplay / dropDisk \u8BED\u4E49\u4E0E pushLog \u4E00\u81F4\u3002\n */\nexport function evaluateLogFilter(\n entry: LogFilterEntry,\n cfg: LogFilterConfig\n): { dropDisplay: boolean; dropDisk: boolean; matched: boolean } {\n const compiled = {\n enabled: cfg.enabled,\n mode: cfg.mode,\n applyTo: cfg.applyTo,\n rules: compileRules(cfg.rules),\n mtimeMs: 0,\n };\n return {\n matched: entryMatchesAnyRule(entry, compiled.rules),\n dropDisplay: shouldDropForDisplay(entry, compiled),\n dropDisk: shouldDropForDisk(entry, compiled),\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/logs.d.ts
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* 保持向后兼容的 pushLog / onLog / getAllLogs / getRecentLogs API
|
|
6
6
|
* (services.ts 捕获子进程 stdout 后调用 pushLog 汇聚到此)。
|
|
7
7
|
*
|
|
8
|
+
* 落盘策略(与子进程自写文件分工,避免重复):
|
|
9
|
+
* - db / qq / update → 子进程已写 `.sfmc/logs/{db,qq,bds-update}.log`,此处跳过
|
|
10
|
+
* - bds / llbot → `.sfmc/logs/{bds,llbot}.log`(外部进程无自带 file sink)
|
|
11
|
+
* - 其余(system / pack / …) → `.sfmc/logs/sfmc.log`
|
|
12
|
+
*
|
|
8
13
|
* formatLog 保留 theme.ts (chalk) 配色,比共享包的纯 ANSI 版本视觉更丰富。
|
|
9
14
|
*/
|
|
10
15
|
import { type LogEntry, type LogLevel as SharedLogLevel } from "@sfmc-bds/sdk/logs";
|
|
@@ -12,24 +17,44 @@ export type LogLevel = SharedLogLevel;
|
|
|
12
17
|
export type LogSource = string;
|
|
13
18
|
export interface UnifiedLog extends LogEntry {
|
|
14
19
|
}
|
|
15
|
-
/**
|
|
20
|
+
/** 再导出 SDK BDS 解析(测试与调用方统一入口,权威在 @sfmc-bds/sdk/logs) */
|
|
21
|
+
export { mapBdsLevelToken, parseBdsEmbeddedLevel, stripBdsLogPrefix } from "@sfmc-bds/sdk/logs";
|
|
22
|
+
/** 推送一条日志到内存缓冲,并按策略落盘 */
|
|
16
23
|
export declare function pushLog(text: string, source: LogSource, level: LogLevel): void;
|
|
17
24
|
/** 订阅新日志事件,返回取消订阅函数 */
|
|
18
25
|
export declare function onLog(fn: (log: UnifiedLog) => void): () => void;
|
|
19
|
-
/**
|
|
20
|
-
export declare function getAllLogs(): UnifiedLog[];
|
|
21
|
-
/** 获取最近 n 条,可按 level / source 过滤 */
|
|
26
|
+
/** 获取最近 n 条,可按 level / source 过滤;再套配置过滤(display) */
|
|
22
27
|
export declare function getRecentLogs(n: number, levels: LogLevel[], sources: LogSource[]): UnifiedLog[];
|
|
23
|
-
/**
|
|
28
|
+
/** 获取全部日志;配置过滤仅影响返回视图(缓冲内可能仍有全量,视 push 时 applyTo) */
|
|
29
|
+
export declare function getAllLogs(): UnifiedLog[];
|
|
30
|
+
export interface SourceMeta {
|
|
31
|
+
value: string;
|
|
32
|
+
/** 显示名,尽量 8 宽对齐 */
|
|
33
|
+
name: string;
|
|
34
|
+
paint: (s: string) => string;
|
|
35
|
+
}
|
|
36
|
+
export declare const SOURCE_META: SourceMeta[];
|
|
37
|
+
export declare function formatSourceTag(source: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* 展示用级别:BDS 若仍带时间戳前缀则解析内嵌级别;已剥离(pushLog 入库)则信任 entry.level。
|
|
40
|
+
* 禁止对正文做松散关键词匹配(会把 `[Commands] Error on line` 误判为 error)。
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveDisplayLevel(l: UnifiedLog): LogLevel;
|
|
43
|
+
/** 从原始文本推断级别:委托共享包(内含 BDS 时间戳解析) */
|
|
24
44
|
export declare function inferLevel(text: string): LogLevel;
|
|
25
45
|
/** 格式化日志用于 REPL 展示 (用 theme.ts chalk 配色) */
|
|
26
46
|
export declare function formatLog(l: UnifiedLog): string;
|
|
27
47
|
/** 字符串在终端的可见宽度 (strip ANSI 后按 CJK 宽度累加) */
|
|
28
48
|
export declare function visibleWidth(s: string): number;
|
|
29
49
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
|
|
50
|
+
* 日志前缀可见宽度(时间 + 源 + 级别 + 尾空格),供悬挂缩进对齐正文起点。
|
|
51
|
+
* 与 formatLog 拼接顺序保持一致(共用 resolveDisplayLevel / sourceTagPlain / levelTagPlain)。
|
|
52
|
+
*/
|
|
53
|
+
export declare function logPrefixWidth(l: UnifiedLog): number;
|
|
54
|
+
/**
|
|
55
|
+
* 按终端可见宽度换行;显式 \\n 与软换行的后续行一律左侧缩进 indent 列。
|
|
56
|
+
* 保留 ANSI:换行时 reset,新行恢复当前颜色状态(可多层叠加)。
|
|
57
|
+
* 宽字符(CJK)按 2 列;cols 预留 1 列,避免 Windows Terminal 边界再软折到第 0 列。
|
|
33
58
|
*/
|
|
34
59
|
export declare function wrapLogLine(s: string, indent: number): string;
|
|
35
60
|
//# sourceMappingURL=logs.d.ts.map
|
package/dist/logs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAQL,KAAK,QAAQ,EACb,KAAK,QAAQ,IAAI,cAAc,EAChC,MAAM,oBAAoB,CAAC;AAU5B,MAAM,MAAM,QAAQ,GAAG,cAAc,CAAC;AACtC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,WAAW,UAAW,SAAQ,QAAQ;CAAG;AAE/C,wDAAwD;AACxD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AA+BhG,yBAAyB;AACzB,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CA2C9E;AAED,uBAAuB;AACvB,wBAAgB,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAE/D;AAED,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAG/F;AAED,qDAAqD;AACrD,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAGzC;AAMD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,WAAW,EAAE,UAAU,EASnC,CAAC;AASF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,UAAU,GAAG,QAAQ,CAM3D;AAED,oCAAoC;AACpC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAEjD;AA+BD,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAQ/C;AAwBD,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAKpD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAa7D"}
|