@sfmc-bds/cli 0.2.0-beta.9 → 0.2.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.
Files changed (128) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +4 -5
  3. package/dist/bds-runtime-version.d.ts +3 -0
  4. package/dist/bds-runtime-version.d.ts.map +1 -0
  5. package/dist/bds-runtime-version.js +15 -0
  6. package/dist/bds-runtime-version.js.map +7 -0
  7. package/dist/command-surface.d.ts.map +1 -1
  8. package/dist/command-surface.js +3 -1
  9. package/dist/command-surface.js.map +2 -2
  10. package/dist/commands.d.ts +57 -4
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/commands.js +78 -75
  13. package/dist/commands.js.map +2 -2
  14. package/dist/directory-picker.d.ts +27 -0
  15. package/dist/directory-picker.d.ts.map +1 -0
  16. package/dist/directory-picker.js +112 -0
  17. package/dist/directory-picker.js.map +7 -0
  18. package/dist/i18n/locales/en.d.ts +25 -1
  19. package/dist/i18n/locales/en.d.ts.map +1 -1
  20. package/dist/i18n/locales/en.js +25 -1
  21. package/dist/i18n/locales/en.js.map +2 -2
  22. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  23. package/dist/i18n/locales/zh-CN.js +26 -2
  24. package/dist/i18n/locales/zh-CN.js.map +2 -2
  25. package/dist/interactive-prompts.d.ts +1 -2
  26. package/dist/interactive-prompts.d.ts.map +1 -1
  27. package/dist/interactive-prompts.js +12 -23
  28. package/dist/interactive-prompts.js.map +3 -3
  29. package/dist/llbot-launch.d.ts +3 -3
  30. package/dist/llbot-launch.js.map +1 -1
  31. package/dist/log-filter.d.ts +18 -2
  32. package/dist/log-filter.d.ts.map +1 -1
  33. package/dist/log-filter.js +54 -4
  34. package/dist/log-filter.js.map +2 -2
  35. package/dist/log-translator.d.ts +36 -0
  36. package/dist/log-translator.d.ts.map +1 -0
  37. package/dist/log-translator.js +279 -0
  38. package/dist/log-translator.js.map +7 -0
  39. package/dist/logs.d.ts +2 -0
  40. package/dist/logs.d.ts.map +1 -1
  41. package/dist/logs.js +24 -11
  42. package/dist/logs.js.map +2 -2
  43. package/dist/main.js +5 -0
  44. package/dist/main.js.map +2 -2
  45. package/dist/module-commands.d.ts.map +1 -1
  46. package/dist/module-commands.js +22 -8
  47. package/dist/module-commands.js.map +2 -2
  48. package/dist/module-fingerprint.d.ts.map +1 -1
  49. package/dist/module-fingerprint.js +1 -0
  50. package/dist/module-fingerprint.js.map +2 -2
  51. package/dist/module-pack-build.d.ts +14 -4
  52. package/dist/module-pack-build.d.ts.map +1 -1
  53. package/dist/module-pack-build.js +81 -108
  54. package/dist/module-pack-build.js.map +2 -2
  55. package/dist/module-toggle.d.ts +1 -1
  56. package/dist/module-toggle.d.ts.map +1 -1
  57. package/dist/module-toggle.js.map +1 -1
  58. package/dist/pack-lifecycle.d.ts +15 -1
  59. package/dist/pack-lifecycle.d.ts.map +1 -1
  60. package/dist/pack-lifecycle.js +242 -15
  61. package/dist/pack-lifecycle.js.map +2 -2
  62. package/dist/player-session.d.ts +13 -0
  63. package/dist/player-session.d.ts.map +1 -0
  64. package/dist/player-session.js +26 -0
  65. package/dist/player-session.js.map +7 -0
  66. package/dist/registry.d.ts +1 -1
  67. package/dist/registry.d.ts.map +1 -1
  68. package/dist/registry.js +4 -1
  69. package/dist/registry.js.map +2 -2
  70. package/dist/repl-windows/format-display.d.ts.map +1 -1
  71. package/dist/repl-windows/format-display.js +5 -1
  72. package/dist/repl-windows/format-display.js.map +2 -2
  73. package/dist/repl-windows/host.d.ts +6 -3
  74. package/dist/repl-windows/host.d.ts.map +1 -1
  75. package/dist/repl-windows/host.js +12 -6
  76. package/dist/repl-windows/host.js.map +2 -2
  77. package/dist/repl-windows/index.d.ts +1 -0
  78. package/dist/repl-windows/index.d.ts.map +1 -1
  79. package/dist/repl-windows/index.js +3 -0
  80. package/dist/repl-windows/index.js.map +2 -2
  81. package/dist/repl-windows/service-window.d.ts.map +1 -1
  82. package/dist/repl-windows/service-window.js +1 -0
  83. package/dist/repl-windows/service-window.js.map +2 -2
  84. package/dist/repl-windows/sfmc-window.d.ts +7 -0
  85. package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
  86. package/dist/repl-windows/sfmc-window.js +28 -0
  87. package/dist/repl-windows/sfmc-window.js.map +7 -0
  88. package/dist/repl.d.ts.map +1 -1
  89. package/dist/repl.js +38 -13
  90. package/dist/repl.js.map +2 -2
  91. package/dist/runtime.d.ts +2 -2
  92. package/dist/runtime.d.ts.map +1 -1
  93. package/dist/runtime.js +15 -2
  94. package/dist/runtime.js.map +2 -2
  95. package/dist/send-target.d.ts +2 -0
  96. package/dist/send-target.d.ts.map +1 -1
  97. package/dist/send-target.js +6 -0
  98. package/dist/send-target.js.map +2 -2
  99. package/dist/services.d.ts +26 -1
  100. package/dist/services.d.ts.map +1 -1
  101. package/dist/services.js +179 -45
  102. package/dist/services.js.map +2 -2
  103. package/dist/sfmc-modules-root.d.ts.map +1 -1
  104. package/dist/sfmc-modules-root.js +6 -2
  105. package/dist/sfmc-modules-root.js.map +2 -2
  106. package/dist/ui-command.d.ts +6 -0
  107. package/dist/ui-command.d.ts.map +1 -0
  108. package/dist/ui-command.js +68 -0
  109. package/dist/ui-command.js.map +7 -0
  110. package/dist/wizard.d.ts.map +1 -1
  111. package/dist/wizard.js +36 -31
  112. package/dist/wizard.js.map +2 -2
  113. package/dist/world-packs.d.ts +2 -0
  114. package/dist/world-packs.d.ts.map +1 -1
  115. package/dist/world-packs.js +161 -18
  116. package/dist/world-packs.js.map +2 -2
  117. package/package.json +22 -15
  118. package/scripts/module-install/check-modules.mjs +178 -0
  119. package/scripts/module-install/fetch-module.mjs +1083 -0
  120. package/scripts/module-install/lib/catalog.mjs +96 -0
  121. package/scripts/module-install/lib/config-seeding.mjs +128 -0
  122. package/scripts/module-install/lib/io.mjs +37 -0
  123. package/scripts/module-install/lib/link-from.mjs +80 -0
  124. package/scripts/module-install/lib/lock.mjs +78 -0
  125. package/scripts/module-install/lib/npm-resolver.mjs +55 -0
  126. package/scripts/module-install/lib/packages.mjs +136 -0
  127. package/scripts/module-install/lib/paths.mjs +48 -0
  128. package/scripts/module-install/lib/registry-index.mjs +50 -0
@@ -0,0 +1,279 @@
1
+ const BUILTIN_BDS_TRANSLATIONS = [
2
+ // 1. 实验性 / 测试版 API 未开启导致脚本阻断加载
3
+ {
4
+ id: "beta-apis-missing",
5
+ pattern: /(?:Plugin|Script)\s+\[(.+?)\]\s*-\s*requesting dependency on beta APIs\s*\[(.+?)\],\s*but the Beta APIs experiment is not enabled\./i,
6
+ translations: {
7
+ "zh-CN": "[\u811A\u672C\u963B\u65AD] \u63D2\u4EF6\u300C$1\u300D\u4F9D\u8D56\u6D4B\u8BD5\u7248 API ($2)\uFF0C\u4F46\u5F53\u524D\u4E16\u754C\u672A\u5F00\u542F\u300C\u6D4B\u8BD5\u7248 API (Beta APIs)\u300D\u5B9E\u9A8C\u5F00\u5173\uFF0C\u5DF2\u88AB BDS \u62D2\u7EDD\u8FD0\u884C\u3002\u8BF7\u5728\u4E16\u754C\u914D\u7F6E\u4E2D\u5F00\u542F\u8BE5\u5B9E\u9A8C\u5F00\u5173\u3002"
8
+ }
9
+ },
10
+ // 2. 脚本语法错误 / 符号缺失
11
+ {
12
+ id: "script-syntax-missing-export",
13
+ pattern: /SyntaxError:\s*Could not find export '(.+?)' in module '(.+?)'/i,
14
+ translations: {
15
+ "zh-CN": "[\u811A\u672C\u8BED\u6CD5\u9519\u8BEF] \u6A21\u7EC4\u5C1D\u8BD5\u4ECE\u300C$2\u300D\u5BFC\u5165\u4E0D\u5B58\u5728\u7684\u7B26\u53F7\u300C$1\u300D\uFF0C\u811A\u672C\u52A0\u8F7D\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u6A21\u7EC4\u811A\u672C\u8BED\u6CD5\u6216 API \u7248\u672C\u517C\u5BB9\u6027\u3002"
16
+ }
17
+ },
18
+ // 3. 世界配置清单中的包在磁盘上不存在
19
+ {
20
+ id: "configured-pack-missing",
21
+ pattern: /Configured pack \(id:\s*([0-9a-fA-F-]+),\s*version:\s*([^)]+)\)\s*was not found and was ignored/i,
22
+ translations: {
23
+ "zh-CN": "[\u5305\u7F3A\u5931] \u4E16\u754C\u6FC0\u6D3B\u6E05\u5355\u4E2D\u7684\u5305 (UUID: $1, \u7248\u672C: $2) \u5728\u672C\u5730\u672A\u627E\u5230\uFF0C\u5DF2\u88AB BDS \u81EA\u52A8\u5FFD\u7565\u3002"
24
+ }
25
+ },
26
+ // 4. 自定义方块形态数量超限警告
27
+ {
28
+ id: "block-permutations-limit",
29
+ pattern: /World with over 65536 block permutations may degrade performance\.\s*Current world has (\d+) permutations\./i,
30
+ translations: {
31
+ "zh-CN": "[\u6027\u80FD\u63D0\u793A] \u81EA\u5B9A\u4E49\u65B9\u5757\u5F62\u6001\u6570\u91CF\u8FBE $1 \u4E2A (\u8D85\u51FA\u63A8\u8350\u4E0A\u9650 65,536)\uFF0C\u53EF\u80FD\u5F71\u54CD\u670D\u52A1\u7AEF\u53CA\u5BA2\u6237\u7AEF\u52A0\u8F7D\u6027\u80FD\u3002"
32
+ }
33
+ },
34
+ // 5. 配方物品不存在或无效
35
+ {
36
+ id: "recipe-item-missing",
37
+ pattern: /(?:\[Recipes\]\s+)?(.+?)\s+\|\s+(.+?)\s+\|\s+The Item:\s*(\S+)\s+is missing or invalid,\s*can't make the recipe/i,
38
+ translations: {
39
+ "zh-CN": "[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u914D\u65B9\u6807\u8BC6: $2) \u5F15\u7528\u7684\u7269\u54C1\u300C$3\u300D\u4E0D\u5B58\u5728\u6216\u65E0\u6548\uFF0C\u65E0\u6CD5\u751F\u6210\u5408\u6210\u914D\u65B9\u3002"
40
+ }
41
+ },
42
+ // 6. 配方缺少有效原料
43
+ {
44
+ id: "recipe-ingredient-missing",
45
+ pattern: /(?:\[Recipes\]\s+)?(.+?)\s+\|\s+(.+?)\s+\|\s+Recipe for:\s*(\S+)\s+is missing \(unknown\) ingredient/i,
46
+ translations: {
47
+ "zh-CN": "[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u4EA7\u7269: $2) \u7F3A\u5C11\u6709\u6548\u539F\u6599\uFF08\u5305\u542B\u672A\u8BC6\u522B\u7684\u539F\u6599\uFF09\uFF0C\u65E0\u6CD5\u6CE8\u518C\u3002"
48
+ }
49
+ },
50
+ // 7. 配方产物格式错误
51
+ {
52
+ id: "recipe-result-malformed",
53
+ pattern: /(?:\[Recipes\]\s+)?(.+?)\s+\|\s+(.+?)\s+\|\s+Recipe result malformed/i,
54
+ translations: {
55
+ "zh-CN": "[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u914D\u65B9\u6807\u8BC6: $2) \u7684\u4EA7\u7269\u7ED3\u679C\u5B9A\u4E49\u683C\u5F0F\u9519\u8BEF (Malformed result)\u3002"
56
+ }
57
+ },
58
+ // 8. 方块定义组件未在 Schema 中声明
59
+ {
60
+ id: "block-component-schema-unknown",
61
+ pattern: /(?:\[Blocks\]\s+)?block_definitions\s*\|.*?\|\s*([^|\r\n]+?)\.json\s*\|\s*(?:->\s*)?(.+?):\s*this component was found in the input,\s*but is not present in the Schema/i,
62
+ translations: {
63
+ "zh-CN": "[\u65B9\u5757\u89C4\u8303\u9519\u8BEF] \u65B9\u5757\u5B9A\u4E49\u300C$1.json\u300D\u5305\u542B\u672A\u5728\u5F53\u524D\u7248\u672C Schema \u4E2D\u5B9A\u4E49\u7684\u672A\u77E5\u7EC4\u4EF6: $2"
64
+ }
65
+ },
66
+ // 9. 方块组件子项在此处无效
67
+ {
68
+ id: "block-child-component-invalid",
69
+ pattern: /(?:\[Blocks\]\s+)?block_definitions\s*\|.*?\|\s*([^|\r\n]+?)\.json\s*\|.*?\|\s*components\s*\|\s*([^|\r\n]+?)\s*\|\s*child '(.+?)' not valid here\./i,
70
+ translations: {
71
+ "zh-CN": "[\u65B9\u5757\u914D\u7F6E\u9519\u8BEF] \u65B9\u5757\u5B9A\u4E49\u300C$1.json\u300D\u7EC4\u4EF6\u300C$2\u300D\u7684\u5B50\u5C5E\u6027\u300C$3\u300D\u5728\u6B64\u5904\u65E0\u6548\u3002"
72
+ }
73
+ },
74
+ // 10. 方块定义解析失败
75
+ {
76
+ id: "block-definition-parse-failed",
77
+ pattern: /(?:\[Blocks\]\s+)?block_definitions\s*\|.*?\|\s*([^|\r\n]+?)\.json\s*\|\s*Block definition parsing failed/i,
78
+ translations: {
79
+ "zh-CN": "[\u65B9\u5757\u89E3\u6790\u5931\u8D25] \u65E0\u6CD5\u89E3\u6790\u65B9\u5757\u5B9A\u4E49\u6587\u4EF6\u300C$1.json\u300D\u3002"
80
+ }
81
+ },
82
+ // 11. 脚本组件未在脚本中注册但被物品使用
83
+ {
84
+ id: "script-component-not-registered",
85
+ pattern: /(?:\[Scripting\]\s+)?Component '(.+?)' was not registered in script but used on an item/i,
86
+ translations: {
87
+ "zh-CN": "[\u811A\u672C\u7EC4\u4EF6\u672A\u6CE8\u518C] \u7269\u54C1\u5F15\u7528\u4E86\u672A\u5728\u811A\u672C\u4E2D\u6CE8\u518C\u7684\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u3002"
88
+ }
89
+ },
90
+ // 12. 脚本注册的方块组件未被任何方块使用
91
+ {
92
+ id: "block-component-unused",
93
+ pattern: /(?:\[Scripting\]\s+)?Block custom component '(.+?)' is not being used by a block/i,
94
+ translations: {
95
+ "zh-CN": "[\u7EC4\u4EF6\u63D0\u793A] \u811A\u672C\u6CE8\u518C\u7684\u65B9\u5757\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u672A\u88AB\u4EFB\u4F55\u65B9\u5757\u4F7F\u7528\u3002"
96
+ }
97
+ },
98
+ // 13. 脚本注册的物品组件未被任何物品使用
99
+ {
100
+ id: "item-component-unused",
101
+ pattern: /(?:\[Scripting\]\s+)?Item custom component '(.+?)' is not being used by an item/i,
102
+ translations: {
103
+ "zh-CN": "[\u7EC4\u4EF6\u63D0\u793A] \u811A\u672C\u6CE8\u518C\u7684\u7269\u54C1\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u672A\u88AB\u4EFB\u4F55\u7269\u54C1\u4F7F\u7528\u3002"
104
+ }
105
+ },
106
+ // 14. 服务端启动就绪
107
+ {
108
+ id: "server-started",
109
+ pattern: /^Server started\./i,
110
+ translations: {
111
+ "zh-CN": "[\u670D\u52A1\u7AEF] BDS \u670D\u52A1\u7AEF\u5DF2\u6210\u529F\u542F\u52A8\uFF0C\u51C6\u5907\u5C31\u7EEA\u3002"
112
+ }
113
+ },
114
+ // 15. 服务端停机流程
115
+ {
116
+ id: "server-stop-requested",
117
+ pattern: /^Server stop requested\./i,
118
+ translations: {
119
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u6536\u5230\u505C\u670D\u8BF7\u6C42\uFF0C\u6B63\u5728\u901A\u77E5\u5E76\u4FDD\u5B58\u4E16\u754C\u6570\u636E..."
120
+ }
121
+ },
122
+ {
123
+ id: "server-stopping",
124
+ pattern: /^Stopping server\.\.\./i,
125
+ translations: {
126
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u6B63\u5728\u5173\u95ED\u670D\u52A1\u7AEF..."
127
+ }
128
+ },
129
+ {
130
+ id: "server-quit-correctly",
131
+ pattern: /^Quit correctly/i,
132
+ translations: {
133
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u670D\u52A1\u7AEF\u5DF2\u6B63\u5E38\u5B89\u5168\u9000\u51FA\u3002"
134
+ }
135
+ },
136
+ {
137
+ id: "server-starting",
138
+ pattern: /^Starting Server/i,
139
+ translations: {
140
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u6B63\u5728\u542F\u52A8 BDS \u670D\u52A1\u7AEF..."
141
+ }
142
+ },
143
+ {
144
+ id: "server-setting-up-logging",
145
+ pattern: /^NO LOG FILE! - setting up server logging\.\.\./i,
146
+ translations: {
147
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u6B63\u5728\u521D\u59CB\u5316\u670D\u52A1\u7AEF\u65E5\u5FD7\u7CFB\u7EDF..."
148
+ }
149
+ },
150
+ // 16. 打开世界数据
151
+ {
152
+ id: "opening-level",
153
+ pattern: /^Opening level '(.+?)'/i,
154
+ translations: {
155
+ "zh-CN": "[\u4E16\u754C] \u6B63\u5728\u6253\u5F00\u4E16\u754C\u6570\u636E: $1"
156
+ }
157
+ },
158
+ // 17. 网络端口与信令服务
159
+ {
160
+ id: "ipv4-port",
161
+ pattern: /^IPv4 supported, port: (\d+): Used for gameplay and LAN discovery/i,
162
+ translations: {
163
+ "zh-CN": "[\u7F51\u7EDC] IPv4 \u6E38\u620F\u4E0E\u5C40\u57DF\u7F51\u53D1\u73B0\u7AEF\u53E3: $1 (UDP)"
164
+ }
165
+ },
166
+ {
167
+ id: "ipv6-port",
168
+ pattern: /^IPv6 supported, port: (\d+): Used for gameplay/i,
169
+ translations: {
170
+ "zh-CN": "[\u7F51\u7EDC] IPv6 \u6E38\u620F\u7AEF\u53E3: $1 (UDP)"
171
+ }
172
+ },
173
+ {
174
+ id: "signaling-signed-in",
175
+ pattern: /^Signed in to signaling service successfully/i,
176
+ translations: {
177
+ "zh-CN": "[\u7F51\u7EDC] \u5DF2\u6210\u529F\u767B\u5F55\u5FAE\u8F6F\u8054\u673A\u4FE1\u4EE4\u670D\u52A1\u3002"
178
+ }
179
+ },
180
+ {
181
+ id: "waiting-minecraft-services",
182
+ pattern: /^Waiting for Minecraft services\.\.\./i,
183
+ translations: {
184
+ "zh-CN": "[\u670D\u52A1\u7AEF] \u6B63\u5728\u7B49\u5F85 Minecraft \u57FA\u7840\u670D\u52A1\u8FDE\u63A5..."
185
+ }
186
+ },
187
+ // 18. 白名单警告与提示
188
+ {
189
+ id: "allowlist-empty-warning",
190
+ pattern: /^Allow list is enabled but contains no entries\./i,
191
+ translations: {
192
+ "zh-CN": "[\u767D\u540D\u5355\u8B66\u544A] \u767D\u540D\u5355\u529F\u80FD\u5DF2\u5F00\u542F\u4F46\u540D\u5355\u4E3A\u7A7A\uFF01\u9664\u7BA1\u7406\u5458\u5916\u5176\u4ED6\u73A9\u5BB6\u5C06\u65E0\u6CD5\u52A0\u5165\u670D\u52A1\u5668\u3002"
193
+ }
194
+ },
195
+ {
196
+ id: "allowlist-add-hint",
197
+ pattern: /^Use allowlist add <playername> for you and your friends so that they can access the server, or modify allowlist\.json manually\./i,
198
+ translations: {
199
+ "zh-CN": "[\u767D\u540D\u5355\u63D0\u793A] \u8BF7\u4F7F\u7528\u300Callowlist add <\u73A9\u5BB6\u540D>\u300D\u6DFB\u52A0\u5141\u8BB8\u8FDB\u5165\u7684\u73A9\u5BB6\uFF0C\u6216\u624B\u52A8\u7F16\u8F91 allowlist.json\u3002"
200
+ }
201
+ },
202
+ {
203
+ id: "allowlist-toggle-hint",
204
+ pattern: /^Alternatively, the allow list can be turned off by typing allowlist off or manually toggled in the server\.properties file\./i,
205
+ translations: {
206
+ "zh-CN": "[\u767D\u540D\u5355\u63D0\u793A] \u53EF\u901A\u8FC7\u8F93\u5165\u300Callowlist off\u300D\u6216\u5728 server.properties \u4E2D\u5173\u95ED\u767D\u540D\u5355\u63A7\u5236\u3002"
207
+ }
208
+ },
209
+ // 19. 控制台内容日志已禁用
210
+ {
211
+ id: "content-log-disabled",
212
+ pattern: /^Content logging to console is disabled\.\s*Enable it with content-log-console-output-enabled=true in server\.properties/i,
213
+ translations: {
214
+ "zh-CN": "[\u63D0\u793A] \u6A21\u7EC4\u5185\u5BB9\u65E5\u5FD7\u8F93\u51FA\u81F3\u63A7\u5236\u53F0\u5F53\u524D\u5DF2\u5173\u95ED\uFF08\u53EF\u901A\u8FC7 server.properties \u4E2D\u7684 content-log-console-output-enabled=true \u5F00\u542F\uFF09\u3002"
215
+ }
216
+ },
217
+ // 20. 未知指令提示
218
+ {
219
+ id: "unknown-command",
220
+ pattern: /^Unknown command:\s*(.+?)\.\s*Please check that the command exists and that you have permission to use it\./i,
221
+ translations: {
222
+ "zh-CN": "[\u6307\u4EE4\u9519\u8BEF] \u672A\u77E5\u6307\u4EE4\u300C$1\u300D\u3002\u8BF7\u68C0\u67E5\u6307\u4EE4\u662F\u5426\u5B58\u5728\u6216\u60A8\u662F\u5426\u5177\u5907\u6267\u884C\u6743\u9650\u3002"
223
+ }
224
+ },
225
+ // 21. 玩家连接与断开
226
+ {
227
+ id: "player-connected",
228
+ pattern: /^Player connected:\s*([^,]+),\s*xuid:\s*(\S+)/i,
229
+ translations: {
230
+ "zh-CN": "[\u73A9\u5BB6\u8FDE\u63A5] \u73A9\u5BB6 $1 \u5DF2\u52A0\u5165\u4E16\u754C (XUID: $2)"
231
+ }
232
+ },
233
+ {
234
+ id: "player-disconnected",
235
+ pattern: /^Player disconnected:\s*([^,]+),\s*xuid:\s*(\S+)/i,
236
+ translations: {
237
+ "zh-CN": "[\u73A9\u5BB6\u65AD\u5F00] \u73A9\u5BB6 $1 \u5DF2\u79BB\u5F00\u4E16\u754C (XUID: $2)"
238
+ }
239
+ }
240
+ ];
241
+ function interpolateRegexTemplate(match, template) {
242
+ return template.replace(/\$(\d+)/g, (full, indexStr) => {
243
+ const idx = parseInt(indexStr, 10);
244
+ if (!isNaN(idx) && idx < match.length) {
245
+ return match[idx] ?? "";
246
+ }
247
+ return full;
248
+ });
249
+ }
250
+ function applyRuleReplacement(text, regex, replaceTemplate) {
251
+ const m = text.match(regex);
252
+ if (!m) return text;
253
+ return interpolateRegexTemplate(m, replaceTemplate);
254
+ }
255
+ function translateBdsLog(text, locale = "zh-CN") {
256
+ const trimmed = text.trim();
257
+ if (!trimmed) {
258
+ return { translated: false, text };
259
+ }
260
+ const targetLocale = locale === "zh" ? "zh-CN" : locale;
261
+ for (const rule of BUILTIN_BDS_TRANSLATIONS) {
262
+ const m = trimmed.match(rule.pattern);
263
+ if (m) {
264
+ const template = rule.translations[targetLocale];
265
+ if (template) {
266
+ const translatedText = interpolateRegexTemplate(m, template);
267
+ return { translated: true, text: translatedText, ruleId: rule.id };
268
+ }
269
+ }
270
+ }
271
+ return { translated: false, text };
272
+ }
273
+ export {
274
+ BUILTIN_BDS_TRANSLATIONS,
275
+ applyRuleReplacement,
276
+ interpolateRegexTemplate,
277
+ translateBdsLog
278
+ };
279
+ //# sourceMappingURL=log-translator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/log-translator.ts"],
4
+ "sourcesContent": ["/**\n * log-translator.ts \u2014 BDS \u539F\u7248\u65E5\u5FD7\u672C\u5730\u5316\u7FFB\u8BD1\u4E0E\u53CB\u597D\u8F6C\u6362\u5F15\u64CE\n *\n * \u5C06 Minecraft \u57FA\u5CA9\u7248\u4E13\u7528\u670D\u52A1\u7AEF (BDS) \u5F15\u64CE\u8F93\u51FA\u7684\u6666\u6DA9\u82F1\u6587\u65E5\u5FD7\n * \uFF08\u5982 Beta APIs \u963B\u65AD\u3001\u65B9\u5757\u5F62\u6001\u8D85\u9650\u3001\u5305\u7F3A\u5931\u3001\u914D\u65B9\u5931\u6548\u3001\u8BED\u6CD5\u9519\u8BEF\u7B49\uFF09\n * \u8F6C\u6362\u4E3A\u670D\u4E3B\u4E0E\u5F00\u53D1\u8005\u6613\u61C2\u7684\u672C\u5730\u5316\u8BED\u8A00\u65E5\u5FD7\u3002\n */\n\nexport interface TranslationRule {\n id: string;\n pattern: RegExp;\n translations: {\n \"zh-CN\": string;\n [locale: string]: string;\n };\n}\n\n/**\n * \u5185\u7F6E\u5E38\u89C1 BDS \u539F\u7248\u65E5\u5FD7\u7FFB\u8BD1\u5B57\u5178\n */\nexport const BUILTIN_BDS_TRANSLATIONS: TranslationRule[] = [\n // 1. \u5B9E\u9A8C\u6027 / \u6D4B\u8BD5\u7248 API \u672A\u5F00\u542F\u5BFC\u81F4\u811A\u672C\u963B\u65AD\u52A0\u8F7D\n {\n id: \"beta-apis-missing\",\n pattern: /(?:Plugin|Script)\\s+\\[(.+?)\\]\\s*-\\s*requesting dependency on beta APIs\\s*\\[(.+?)\\],\\s*but the Beta APIs experiment is not enabled\\./i,\n translations: {\n \"zh-CN\": \"[\u811A\u672C\u963B\u65AD] \u63D2\u4EF6\u300C$1\u300D\u4F9D\u8D56\u6D4B\u8BD5\u7248 API ($2)\uFF0C\u4F46\u5F53\u524D\u4E16\u754C\u672A\u5F00\u542F\u300C\u6D4B\u8BD5\u7248 API (Beta APIs)\u300D\u5B9E\u9A8C\u5F00\u5173\uFF0C\u5DF2\u88AB BDS \u62D2\u7EDD\u8FD0\u884C\u3002\u8BF7\u5728\u4E16\u754C\u914D\u7F6E\u4E2D\u5F00\u542F\u8BE5\u5B9E\u9A8C\u5F00\u5173\u3002\",\n },\n },\n // 2. \u811A\u672C\u8BED\u6CD5\u9519\u8BEF / \u7B26\u53F7\u7F3A\u5931\n {\n id: \"script-syntax-missing-export\",\n pattern: /SyntaxError:\\s*Could not find export '(.+?)' in module '(.+?)'/i,\n translations: {\n \"zh-CN\": \"[\u811A\u672C\u8BED\u6CD5\u9519\u8BEF] \u6A21\u7EC4\u5C1D\u8BD5\u4ECE\u300C$2\u300D\u5BFC\u5165\u4E0D\u5B58\u5728\u7684\u7B26\u53F7\u300C$1\u300D\uFF0C\u811A\u672C\u52A0\u8F7D\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u6A21\u7EC4\u811A\u672C\u8BED\u6CD5\u6216 API \u7248\u672C\u517C\u5BB9\u6027\u3002\",\n },\n },\n // 3. \u4E16\u754C\u914D\u7F6E\u6E05\u5355\u4E2D\u7684\u5305\u5728\u78C1\u76D8\u4E0A\u4E0D\u5B58\u5728\n {\n id: \"configured-pack-missing\",\n pattern: /Configured pack \\(id:\\s*([0-9a-fA-F-]+),\\s*version:\\s*([^)]+)\\)\\s*was not found and was ignored/i,\n translations: {\n \"zh-CN\": \"[\u5305\u7F3A\u5931] \u4E16\u754C\u6FC0\u6D3B\u6E05\u5355\u4E2D\u7684\u5305 (UUID: $1, \u7248\u672C: $2) \u5728\u672C\u5730\u672A\u627E\u5230\uFF0C\u5DF2\u88AB BDS \u81EA\u52A8\u5FFD\u7565\u3002\",\n },\n },\n // 4. \u81EA\u5B9A\u4E49\u65B9\u5757\u5F62\u6001\u6570\u91CF\u8D85\u9650\u8B66\u544A\n {\n id: \"block-permutations-limit\",\n pattern: /World with over 65536 block permutations may degrade performance\\.\\s*Current world has (\\d+) permutations\\./i,\n translations: {\n \"zh-CN\": \"[\u6027\u80FD\u63D0\u793A] \u81EA\u5B9A\u4E49\u65B9\u5757\u5F62\u6001\u6570\u91CF\u8FBE $1 \u4E2A (\u8D85\u51FA\u63A8\u8350\u4E0A\u9650 65,536)\uFF0C\u53EF\u80FD\u5F71\u54CD\u670D\u52A1\u7AEF\u53CA\u5BA2\u6237\u7AEF\u52A0\u8F7D\u6027\u80FD\u3002\",\n },\n },\n // 5. \u914D\u65B9\u7269\u54C1\u4E0D\u5B58\u5728\u6216\u65E0\u6548\n {\n id: \"recipe-item-missing\",\n pattern: /(?:\\[Recipes\\]\\s+)?(.+?)\\s+\\|\\s+(.+?)\\s+\\|\\s+The Item:\\s*(\\S+)\\s+is missing or invalid,\\s*can't make the recipe/i,\n translations: {\n \"zh-CN\": \"[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u914D\u65B9\u6807\u8BC6: $2) \u5F15\u7528\u7684\u7269\u54C1\u300C$3\u300D\u4E0D\u5B58\u5728\u6216\u65E0\u6548\uFF0C\u65E0\u6CD5\u751F\u6210\u5408\u6210\u914D\u65B9\u3002\",\n },\n },\n // 6. \u914D\u65B9\u7F3A\u5C11\u6709\u6548\u539F\u6599\n {\n id: \"recipe-ingredient-missing\",\n pattern: /(?:\\[Recipes\\]\\s+)?(.+?)\\s+\\|\\s+(.+?)\\s+\\|\\s+Recipe for:\\s*(\\S+)\\s+is missing \\(unknown\\) ingredient/i,\n translations: {\n \"zh-CN\": \"[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u4EA7\u7269: $2) \u7F3A\u5C11\u6709\u6548\u539F\u6599\uFF08\u5305\u542B\u672A\u8BC6\u522B\u7684\u539F\u6599\uFF09\uFF0C\u65E0\u6CD5\u6CE8\u518C\u3002\",\n },\n },\n // 7. \u914D\u65B9\u4EA7\u7269\u683C\u5F0F\u9519\u8BEF\n {\n id: \"recipe-result-malformed\",\n pattern: /(?:\\[Recipes\\]\\s+)?(.+?)\\s+\\|\\s+(.+?)\\s+\\|\\s+Recipe result malformed/i,\n translations: {\n \"zh-CN\": \"[\u914D\u65B9\u9519\u8BEF] \u914D\u65B9\u6587\u4EF6\u300C$1\u300D(\u914D\u65B9\u6807\u8BC6: $2) \u7684\u4EA7\u7269\u7ED3\u679C\u5B9A\u4E49\u683C\u5F0F\u9519\u8BEF (Malformed result)\u3002\",\n },\n },\n // 8. \u65B9\u5757\u5B9A\u4E49\u7EC4\u4EF6\u672A\u5728 Schema \u4E2D\u58F0\u660E\n {\n id: \"block-component-schema-unknown\",\n pattern: /(?:\\[Blocks\\]\\s+)?block_definitions\\s*\\|.*?\\|\\s*([^|\\r\\n]+?)\\.json\\s*\\|\\s*(?:->\\s*)?(.+?):\\s*this component was found in the input,\\s*but is not present in the Schema/i,\n translations: {\n \"zh-CN\": \"[\u65B9\u5757\u89C4\u8303\u9519\u8BEF] \u65B9\u5757\u5B9A\u4E49\u300C$1.json\u300D\u5305\u542B\u672A\u5728\u5F53\u524D\u7248\u672C Schema \u4E2D\u5B9A\u4E49\u7684\u672A\u77E5\u7EC4\u4EF6: $2\",\n },\n },\n // 9. \u65B9\u5757\u7EC4\u4EF6\u5B50\u9879\u5728\u6B64\u5904\u65E0\u6548\n {\n id: \"block-child-component-invalid\",\n pattern: /(?:\\[Blocks\\]\\s+)?block_definitions\\s*\\|.*?\\|\\s*([^|\\r\\n]+?)\\.json\\s*\\|.*?\\|\\s*components\\s*\\|\\s*([^|\\r\\n]+?)\\s*\\|\\s*child '(.+?)' not valid here\\./i,\n translations: {\n \"zh-CN\": \"[\u65B9\u5757\u914D\u7F6E\u9519\u8BEF] \u65B9\u5757\u5B9A\u4E49\u300C$1.json\u300D\u7EC4\u4EF6\u300C$2\u300D\u7684\u5B50\u5C5E\u6027\u300C$3\u300D\u5728\u6B64\u5904\u65E0\u6548\u3002\",\n },\n },\n // 10. \u65B9\u5757\u5B9A\u4E49\u89E3\u6790\u5931\u8D25\n {\n id: \"block-definition-parse-failed\",\n pattern: /(?:\\[Blocks\\]\\s+)?block_definitions\\s*\\|.*?\\|\\s*([^|\\r\\n]+?)\\.json\\s*\\|\\s*Block definition parsing failed/i,\n translations: {\n \"zh-CN\": \"[\u65B9\u5757\u89E3\u6790\u5931\u8D25] \u65E0\u6CD5\u89E3\u6790\u65B9\u5757\u5B9A\u4E49\u6587\u4EF6\u300C$1.json\u300D\u3002\",\n },\n },\n // 11. \u811A\u672C\u7EC4\u4EF6\u672A\u5728\u811A\u672C\u4E2D\u6CE8\u518C\u4F46\u88AB\u7269\u54C1\u4F7F\u7528\n {\n id: \"script-component-not-registered\",\n pattern: /(?:\\[Scripting\\]\\s+)?Component '(.+?)' was not registered in script but used on an item/i,\n translations: {\n \"zh-CN\": \"[\u811A\u672C\u7EC4\u4EF6\u672A\u6CE8\u518C] \u7269\u54C1\u5F15\u7528\u4E86\u672A\u5728\u811A\u672C\u4E2D\u6CE8\u518C\u7684\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u3002\",\n },\n },\n // 12. \u811A\u672C\u6CE8\u518C\u7684\u65B9\u5757\u7EC4\u4EF6\u672A\u88AB\u4EFB\u4F55\u65B9\u5757\u4F7F\u7528\n {\n id: \"block-component-unused\",\n pattern: /(?:\\[Scripting\\]\\s+)?Block custom component '(.+?)' is not being used by a block/i,\n translations: {\n \"zh-CN\": \"[\u7EC4\u4EF6\u63D0\u793A] \u811A\u672C\u6CE8\u518C\u7684\u65B9\u5757\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u672A\u88AB\u4EFB\u4F55\u65B9\u5757\u4F7F\u7528\u3002\",\n },\n },\n // 13. \u811A\u672C\u6CE8\u518C\u7684\u7269\u54C1\u7EC4\u4EF6\u672A\u88AB\u4EFB\u4F55\u7269\u54C1\u4F7F\u7528\n {\n id: \"item-component-unused\",\n pattern: /(?:\\[Scripting\\]\\s+)?Item custom component '(.+?)' is not being used by an item/i,\n translations: {\n \"zh-CN\": \"[\u7EC4\u4EF6\u63D0\u793A] \u811A\u672C\u6CE8\u518C\u7684\u7269\u54C1\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300C$1\u300D\u672A\u88AB\u4EFB\u4F55\u7269\u54C1\u4F7F\u7528\u3002\",\n },\n },\n // 14. \u670D\u52A1\u7AEF\u542F\u52A8\u5C31\u7EEA\n {\n id: \"server-started\",\n pattern: /^Server started\\./i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] BDS \u670D\u52A1\u7AEF\u5DF2\u6210\u529F\u542F\u52A8\uFF0C\u51C6\u5907\u5C31\u7EEA\u3002\",\n },\n },\n // 15. \u670D\u52A1\u7AEF\u505C\u673A\u6D41\u7A0B\n {\n id: \"server-stop-requested\",\n pattern: /^Server stop requested\\./i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u6536\u5230\u505C\u670D\u8BF7\u6C42\uFF0C\u6B63\u5728\u901A\u77E5\u5E76\u4FDD\u5B58\u4E16\u754C\u6570\u636E...\",\n },\n },\n {\n id: \"server-stopping\",\n pattern: /^Stopping server\\.\\.\\./i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u6B63\u5728\u5173\u95ED\u670D\u52A1\u7AEF...\",\n },\n },\n {\n id: \"server-quit-correctly\",\n pattern: /^Quit correctly/i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u670D\u52A1\u7AEF\u5DF2\u6B63\u5E38\u5B89\u5168\u9000\u51FA\u3002\",\n },\n },\n {\n id: \"server-starting\",\n pattern: /^Starting Server/i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u6B63\u5728\u542F\u52A8 BDS \u670D\u52A1\u7AEF...\",\n },\n },\n {\n id: \"server-setting-up-logging\",\n pattern: /^NO LOG FILE! - setting up server logging\\.\\.\\./i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u6B63\u5728\u521D\u59CB\u5316\u670D\u52A1\u7AEF\u65E5\u5FD7\u7CFB\u7EDF...\",\n },\n },\n // 16. \u6253\u5F00\u4E16\u754C\u6570\u636E\n {\n id: \"opening-level\",\n pattern: /^Opening level '(.+?)'/i,\n translations: {\n \"zh-CN\": \"[\u4E16\u754C] \u6B63\u5728\u6253\u5F00\u4E16\u754C\u6570\u636E: $1\",\n },\n },\n // 17. \u7F51\u7EDC\u7AEF\u53E3\u4E0E\u4FE1\u4EE4\u670D\u52A1\n {\n id: \"ipv4-port\",\n pattern: /^IPv4 supported, port: (\\d+): Used for gameplay and LAN discovery/i,\n translations: {\n \"zh-CN\": \"[\u7F51\u7EDC] IPv4 \u6E38\u620F\u4E0E\u5C40\u57DF\u7F51\u53D1\u73B0\u7AEF\u53E3: $1 (UDP)\",\n },\n },\n {\n id: \"ipv6-port\",\n pattern: /^IPv6 supported, port: (\\d+): Used for gameplay/i,\n translations: {\n \"zh-CN\": \"[\u7F51\u7EDC] IPv6 \u6E38\u620F\u7AEF\u53E3: $1 (UDP)\",\n },\n },\n {\n id: \"signaling-signed-in\",\n pattern: /^Signed in to signaling service successfully/i,\n translations: {\n \"zh-CN\": \"[\u7F51\u7EDC] \u5DF2\u6210\u529F\u767B\u5F55\u5FAE\u8F6F\u8054\u673A\u4FE1\u4EE4\u670D\u52A1\u3002\",\n },\n },\n {\n id: \"waiting-minecraft-services\",\n pattern: /^Waiting for Minecraft services\\.\\.\\./i,\n translations: {\n \"zh-CN\": \"[\u670D\u52A1\u7AEF] \u6B63\u5728\u7B49\u5F85 Minecraft \u57FA\u7840\u670D\u52A1\u8FDE\u63A5...\",\n },\n },\n // 18. \u767D\u540D\u5355\u8B66\u544A\u4E0E\u63D0\u793A\n {\n id: \"allowlist-empty-warning\",\n pattern: /^Allow list is enabled but contains no entries\\./i,\n translations: {\n \"zh-CN\": \"[\u767D\u540D\u5355\u8B66\u544A] \u767D\u540D\u5355\u529F\u80FD\u5DF2\u5F00\u542F\u4F46\u540D\u5355\u4E3A\u7A7A\uFF01\u9664\u7BA1\u7406\u5458\u5916\u5176\u4ED6\u73A9\u5BB6\u5C06\u65E0\u6CD5\u52A0\u5165\u670D\u52A1\u5668\u3002\",\n },\n },\n {\n id: \"allowlist-add-hint\",\n pattern: /^Use allowlist add <playername> for you and your friends so that they can access the server, or modify allowlist\\.json manually\\./i,\n translations: {\n \"zh-CN\": \"[\u767D\u540D\u5355\u63D0\u793A] \u8BF7\u4F7F\u7528\u300Callowlist add <\u73A9\u5BB6\u540D>\u300D\u6DFB\u52A0\u5141\u8BB8\u8FDB\u5165\u7684\u73A9\u5BB6\uFF0C\u6216\u624B\u52A8\u7F16\u8F91 allowlist.json\u3002\",\n },\n },\n {\n id: \"allowlist-toggle-hint\",\n pattern: /^Alternatively, the allow list can be turned off by typing allowlist off or manually toggled in the server\\.properties file\\./i,\n translations: {\n \"zh-CN\": \"[\u767D\u540D\u5355\u63D0\u793A] \u53EF\u901A\u8FC7\u8F93\u5165\u300Callowlist off\u300D\u6216\u5728 server.properties \u4E2D\u5173\u95ED\u767D\u540D\u5355\u63A7\u5236\u3002\",\n },\n },\n // 19. \u63A7\u5236\u53F0\u5185\u5BB9\u65E5\u5FD7\u5DF2\u7981\u7528\n {\n id: \"content-log-disabled\",\n pattern: /^Content logging to console is disabled\\.\\s*Enable it with content-log-console-output-enabled=true in server\\.properties/i,\n translations: {\n \"zh-CN\": \"[\u63D0\u793A] \u6A21\u7EC4\u5185\u5BB9\u65E5\u5FD7\u8F93\u51FA\u81F3\u63A7\u5236\u53F0\u5F53\u524D\u5DF2\u5173\u95ED\uFF08\u53EF\u901A\u8FC7 server.properties \u4E2D\u7684 content-log-console-output-enabled=true \u5F00\u542F\uFF09\u3002\",\n },\n },\n // 20. \u672A\u77E5\u6307\u4EE4\u63D0\u793A\n {\n id: \"unknown-command\",\n pattern: /^Unknown command:\\s*(.+?)\\.\\s*Please check that the command exists and that you have permission to use it\\./i,\n translations: {\n \"zh-CN\": \"[\u6307\u4EE4\u9519\u8BEF] \u672A\u77E5\u6307\u4EE4\u300C$1\u300D\u3002\u8BF7\u68C0\u67E5\u6307\u4EE4\u662F\u5426\u5B58\u5728\u6216\u60A8\u662F\u5426\u5177\u5907\u6267\u884C\u6743\u9650\u3002\",\n },\n },\n // 21. \u73A9\u5BB6\u8FDE\u63A5\u4E0E\u65AD\u5F00\n {\n id: \"player-connected\",\n pattern: /^Player connected:\\s*([^,]+),\\s*xuid:\\s*(\\S+)/i,\n translations: {\n \"zh-CN\": \"[\u73A9\u5BB6\u8FDE\u63A5] \u73A9\u5BB6 $1 \u5DF2\u52A0\u5165\u4E16\u754C (XUID: $2)\",\n },\n },\n {\n id: \"player-disconnected\",\n pattern: /^Player disconnected:\\s*([^,]+),\\s*xuid:\\s*(\\S+)/i,\n translations: {\n \"zh-CN\": \"[\u73A9\u5BB6\u65AD\u5F00] \u73A9\u5BB6 $1 \u5DF2\u79BB\u5F00\u4E16\u754C (XUID: $2)\",\n },\n },\n];\n\n/**\n * \u5C06\u6B63\u5219\u5339\u914D\u7ED3\u679C\u5957\u5165\u542B $1, $2 \u7B49\u5360\u4F4D\u7B26\u7684\u6A21\u677F\u5B57\u7B26\u4E32\n */\nexport function interpolateRegexTemplate(match: RegExpMatchArray, template: string): string {\n return template.replace(/\\$(\\d+)/g, (full, indexStr: string) => {\n const idx = parseInt(indexStr, 10);\n if (!isNaN(idx) && idx < match.length) {\n return match[idx] ?? \"\";\n }\n return full;\n });\n}\n\n/**\n * \u5E94\u7528\u89C4\u5219\u6B63\u5219\u66FF\u6362\u6A21\u677F\n */\nexport function applyRuleReplacement(text: string, regex: RegExp, replaceTemplate: string): string {\n const m = text.match(regex);\n if (!m) return text;\n return interpolateRegexTemplate(m, replaceTemplate);\n}\n\n/**\n * \u7FFB\u8BD1\u5355\u6761 BDS \u65E5\u5FD7\u6587\u672C\uFF08\u7EAF\u51FD\u6570\uFF09\n */\nexport function translateBdsLog(\n text: string,\n locale: string = \"zh-CN\"\n): { translated: boolean; text: string; ruleId?: string } {\n const trimmed = text.trim();\n if (!trimmed) {\n return { translated: false, text };\n }\n\n // \u4EC5\u5728\u975E\u82F1\u6587\uFF08\u5982 zh-CN\uFF09\u6216\u914D\u7F6E\u4E86\u8BE5\u8BED\u8A00\u65F6\u7FFB\u8BD1\n const targetLocale = locale === \"zh\" ? \"zh-CN\" : locale;\n\n for (const rule of BUILTIN_BDS_TRANSLATIONS) {\n const m = trimmed.match(rule.pattern);\n if (m) {\n const template = rule.translations[targetLocale];\n if (template) {\n const translatedText = interpolateRegexTemplate(m, template);\n return { translated: true, text: translatedText, ruleId: rule.id };\n }\n }\n }\n\n return { translated: false, text };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/logs.d.ts CHANGED
@@ -19,6 +19,8 @@ export interface UnifiedLog extends LogEntry {
19
19
  }
20
20
  /** 再导出 SDK BDS 解析(测试与调用方统一入口,权威在 @sfmc-bds/sdk/logs) */
21
21
  export { mapBdsLevelToken, parseBdsEmbeddedLevel, stripBdsLogPrefix } from "@sfmc-bds/sdk/logs";
22
+ /** 剥离 BDS 自带前缀;若前缀后没有正文,则判定为仅用于排版的空行。 */
23
+ export declare function normalizeBdsLogBody(text: string): string | null;
22
24
  /** 推送一条日志到内存缓冲,并按策略落盘 */
23
25
  export declare function pushLog(text: string, source: LogSource, level: LogLevel): void;
24
26
  /** 订阅新日志事件,返回取消订阅函数 */
@@ -1 +1 @@
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;AAY5B,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;AASD,6BAA6B;AAC7B,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIxD;AAuBD,2BAA2B;AAC3B,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAS/D;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,gBAAqB,GAAG,UAAU,EAAE,CA+BtE;AAMD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,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"}
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;AAa5B,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;AAShG,yCAAyC;AACzC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/D;AAwBD,yBAAyB;AACzB,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CA+C9E;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;AASD,6BAA6B;AAC7B,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIxD;AAuBD,2BAA2B;AAC3B,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAS/D;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,gBAAqB,GAAG,UAAU,EAAE,CA+BtE;AAMD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,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,CAW/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"}
package/dist/logs.js CHANGED
@@ -12,7 +12,8 @@ import path from "node:path";
12
12
  import {
13
13
  getCompiledLogFilter,
14
14
  shouldDropForDisk,
15
- shouldDropForDisplay
15
+ shouldDropForDisplay,
16
+ transformLogEntry
16
17
  } from "./log-filter.js";
17
18
  import { c, highlightLogLine } from "./theme.js";
18
19
  import { ROOT } from "./runtime.js";
@@ -20,9 +21,13 @@ import { mapBdsLevelToken, parseBdsEmbeddedLevel as parseBdsEmbeddedLevel2, stri
20
21
  const buffer = createMemoryBuffer(5e3);
21
22
  const CHILD_OWNED_SOURCES = /* @__PURE__ */ new Set(["db", "qq", "update"]);
22
23
  const fileSinks = /* @__PURE__ */ new Map();
24
+ function normalizeBdsLogBody(text) {
25
+ const body = stripBdsLogPrefix(text);
26
+ return body.trim().length > 0 ? body : null;
27
+ }
23
28
  function resolveDiskLogName(source) {
24
29
  if (CHILD_OWNED_SOURCES.has(source)) return null;
25
- if (source === "bds" || source === "llbot") return source;
30
+ if (source === "bds" || source === "llbot" || source === "tunnel") return source;
26
31
  return "sfmc";
27
32
  }
28
33
  function sinkFor(source) {
@@ -44,9 +49,11 @@ function pushLog(text, source, level) {
44
49
  if (source === "bds") {
45
50
  const embedded = parseBdsEmbeddedLevel(text);
46
51
  if (embedded) lvl = embedded;
47
- body = stripBdsLogPrefix(text);
52
+ const normalized = normalizeBdsLogBody(text);
53
+ if (normalized === null) return;
54
+ body = normalized;
48
55
  }
49
- const entry = { time: /* @__PURE__ */ new Date(), text: body, source, level: lvl };
56
+ const rawEntry = { time: /* @__PURE__ */ new Date(), text: body, source, level: lvl };
50
57
  const filter = getCompiledLogFilter((src) => {
51
58
  try {
52
59
  const sink2 = sinkFor("system");
@@ -61,16 +68,18 @@ function pushLog(text, source, level) {
61
68
  } catch {
62
69
  }
63
70
  });
64
- const dropDisplay = shouldDropForDisplay(entry, filter);
65
- const dropDisk = shouldDropForDisk(entry, filter);
71
+ const dropDisplay = shouldDropForDisplay(rawEntry, filter);
72
+ const dropDisk = shouldDropForDisk(rawEntry, filter);
73
+ const { entry: transformedEntry } = transformLogEntry(rawEntry, filter);
66
74
  if (!dropDisplay) {
67
- buffer.pushDirect(body, source, lvl);
75
+ buffer.pushDirect(transformedEntry.text, source, lvl);
68
76
  }
69
77
  if (dropDisk) return;
70
78
  const sink = sinkFor(source);
71
79
  if (!sink) return;
72
80
  try {
73
- sink.write(entry, formatLogLine(entry, false));
81
+ const diskEntry = filter.applyTo === "all" ? { ...rawEntry, text: transformedEntry.text } : rawEntry;
82
+ sink.write(diskEntry, formatLogLine(diskEntry, false));
74
83
  } catch {
75
84
  }
76
85
  }
@@ -85,10 +94,10 @@ function getAllLogs() {
85
94
  const filter = getCompiledLogFilter();
86
95
  return buffer.getAll().filter((l) => !shouldDropForDisplay(l, filter));
87
96
  }
88
- const DISK_LOG_FILES = ["bds", "llbot", "db", "qq", "bds-update", "sfmc"];
97
+ const DISK_LOG_FILES = ["bds", "llbot", "tunnel", "db", "qq", "bds-update", "sfmc"];
89
98
  function diskFileForSource(source) {
90
99
  if (source === "update") return "bds-update";
91
- if (source === "bds" || source === "llbot" || source === "db" || source === "qq") return source;
100
+ if (source === "bds" || source === "llbot" || source === "tunnel" || source === "db" || source === "qq") return source;
92
101
  return "sfmc";
93
102
  }
94
103
  const DISK_LINE_RE = /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[([^\]]+)\] \[(INFO|WARN|ERROR|OK|DEBUG|SUCCESS|FATAL)\]\s?(.*)$/;
@@ -210,7 +219,10 @@ function formatLog(l) {
210
219
  const level = resolveDisplayLevel(l);
211
220
  const lvl = levelTag(level);
212
221
  const src = formatSourceTag(l.source);
213
- const txt = highlightLogLine(l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text);
222
+ const body = l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text;
223
+ const filter = getCompiledLogFilter();
224
+ const { entry } = transformLogEntry({ text: body, source: l.source, level }, filter);
225
+ const txt = highlightLogLine(entry.text);
214
226
  return `${ts} ${src} ${lvl} ${txt}`;
215
227
  }
216
228
  function charWidth(ch) {
@@ -296,6 +308,7 @@ export {
296
308
  inferLevel,
297
309
  logPrefixWidth,
298
310
  mapBdsLevelToken,
311
+ normalizeBdsLogBody,
299
312
  onLog,
300
313
  parseBdsEmbeddedLevel2 as parseBdsEmbeddedLevel,
301
314
  parseDiskLogLine,
package/dist/logs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/logs.ts"],
4
- "sourcesContent": ["/**\n * logs.ts \u2014 sfmc \u4E3B\u8FDB\u7A0B\u7EDF\u4E00\u65E5\u5FD7\u805A\u5408\u5C42\n *\n * \u5185\u90E8\u59D4\u6258 @sfmc-bds/logs \u5171\u4EAB\u5305\u7684 createMemoryBuffer + inferLevel,\n * \u4FDD\u6301\u5411\u540E\u517C\u5BB9\u7684 pushLog / onLog / getAllLogs / getRecentLogs API\n * (services.ts \u6355\u83B7\u5B50\u8FDB\u7A0B stdout \u540E\u8C03\u7528 pushLog \u6C47\u805A\u5230\u6B64)\u3002\n *\n * \u843D\u76D8\u7B56\u7565(\u4E0E\u5B50\u8FDB\u7A0B\u81EA\u5199\u6587\u4EF6\u5206\u5DE5,\u907F\u514D\u91CD\u590D):\n * - db / qq / update \u2192 \u5B50\u8FDB\u7A0B\u5DF2\u5199 `.sfmc/logs/{db,qq,bds-update}.log`,\u6B64\u5904\u8DF3\u8FC7\n * - bds / llbot \u2192 `.sfmc/logs/{bds,llbot}.log`(\u5916\u90E8\u8FDB\u7A0B\u65E0\u81EA\u5E26 file sink)\n * - \u5176\u4F59(system / pack / \u2026) \u2192 `.sfmc/logs/sfmc.log`\n *\n * formatLog \u4FDD\u7559 theme.ts (chalk) \u914D\u8272,\u6BD4\u5171\u4EAB\u5305\u7684\u7EAF ANSI \u7248\u672C\u89C6\u89C9\u66F4\u4E30\u5BCC\u3002\n */\n\nimport {\n createFileSink,\n createMemoryBuffer,\n formatLogLine,\n inferLevel as sharedInferLevel,\n parseBdsEmbeddedLevel,\n stripBdsLogPrefix,\n type FileSink,\n type LogEntry,\n type LogLevel as SharedLogLevel,\n} from \"@sfmc-bds/sdk/logs\";\nimport { logFile, logsDir } from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n getCompiledLogFilter,\n shouldDropForDisk,\n shouldDropForDisplay,\n} from \"./log-filter.js\";\nimport { c, highlightLogLine } from \"./theme.js\";\nimport { ROOT } from \"./runtime.js\";\n\nexport type LogLevel = SharedLogLevel;\nexport type LogSource = string;\nexport interface UnifiedLog extends LogEntry {}\n\n/** \u518D\u5BFC\u51FA SDK BDS \u89E3\u6790\uFF08\u6D4B\u8BD5\u4E0E\u8C03\u7528\u65B9\u7EDF\u4E00\u5165\u53E3\uFF0C\u6743\u5A01\u5728 @sfmc-bds/sdk/logs\uFF09 */\nexport { mapBdsLevelToken, parseBdsEmbeddedLevel, stripBdsLogPrefix } from \"@sfmc-bds/sdk/logs\";\n\nconst buffer = createMemoryBuffer(5000);\n\n/** \u5B50\u8FDB\u7A0B\u5DF2\u7528 createNodeServiceLogger \u81EA\u884C\u843D\u76D8\u7684 source */\nconst CHILD_OWNED_SOURCES = new Set([\"db\", \"qq\", \"update\"]);\n\nconst fileSinks = new Map<string, FileSink>();\n\n/** \u89E3\u6790\u672C\u6761\u65E5\u5FD7\u5E94\u5199\u5165\u7684\u6587\u4EF6\u540D(\u4E0D\u542B .log);null \u8868\u793A\u8DF3\u8FC7(\u5B50\u8FDB\u7A0B\u5DF2\u5199) */\nfunction resolveDiskLogName(source: string): string | null {\n if (CHILD_OWNED_SOURCES.has(source)) return null;\n if (source === \"bds\" || source === \"llbot\") return source;\n return \"sfmc\";\n}\n\nfunction sinkFor(source: string): FileSink | null {\n const name = resolveDiskLogName(source);\n if (!name) return null;\n let sink = fileSinks.get(name);\n if (!sink) {\n sink = createFileSink(logFile(ROOT, name));\n fileSinks.set(name, sink);\n }\n return sink;\n}\n\nprocess.on(\"exit\", () => {\n for (const sink of fileSinks.values()) sink.close();\n});\n\n/** \u63A8\u9001\u4E00\u6761\u65E5\u5FD7\u5230\u5185\u5B58\u7F13\u51B2,\u5E76\u6309\u7B56\u7565\u843D\u76D8 */\nexport function pushLog(text: string, source: LogSource, level: LogLevel): void {\n let body = text;\n let lvl = level;\n /* BDS\uFF1A\u5148\u63D0\u53D6\u5185\u5D4C\u7EA7\u522B\uFF0C\u518D\u5265\u6389\u81EA\u5E26\u65F6\u95F4\u6233+\u7B49\u7EA7\uFF0C\u907F\u514D\u5C55\u793A/\u843D\u76D8\u91CD\u590D */\n if (source === \"bds\") {\n const embedded = parseBdsEmbeddedLevel(text);\n if (embedded) lvl = embedded;\n body = stripBdsLogPrefix(text);\n }\n\n const entry: LogEntry = { time: new Date(), text: body, source, level: lvl };\n const filter = getCompiledLogFilter((src) => {\n /* \u907F\u514D\u9012\u5F52\uFF1A\u975E\u6CD5\u6B63\u5219\u53EA\u5199\u6587\u4EF6 sink\uFF0C\u4E0D\u7ECF pushLog */\n try {\n const sink = sinkFor(\"system\");\n if (!sink) return;\n const warn: LogEntry = {\n time: new Date(),\n text: `log-filter: invalid regex skipped: ${src}`,\n source: \"system\",\n level: \"warn\",\n };\n sink.write(warn, formatLogLine(warn, false));\n } catch {\n /* ignore */\n }\n });\n\n const dropDisplay = shouldDropForDisplay(entry, filter);\n const dropDisk = shouldDropForDisk(entry, filter);\n\n if (!dropDisplay) {\n buffer.pushDirect(body, source, lvl);\n }\n\n if (dropDisk) return;\n const sink = sinkFor(source);\n if (!sink) return;\n try {\n sink.write(entry, formatLogLine(entry, false));\n } catch {\n /* \u843D\u76D8\u5931\u8D25\u4E0D\u963B\u65AD\u4E3B\u6D41\u7A0B */\n }\n}\n\n/** \u8BA2\u9605\u65B0\u65E5\u5FD7\u4E8B\u4EF6,\u8FD4\u56DE\u53D6\u6D88\u8BA2\u9605\u51FD\u6570 */\nexport function onLog(fn: (log: UnifiedLog) => void): () => void {\n return buffer.subscribe(fn);\n}\n\n/** \u83B7\u53D6\u6700\u8FD1 n \u6761,\u53EF\u6309 level / source \u8FC7\u6EE4\uFF1B\u518D\u5957\u914D\u7F6E\u8FC7\u6EE4\uFF08display\uFF09 */\nexport function getRecentLogs(n: number, levels: LogLevel[], sources: LogSource[]): UnifiedLog[] {\n const filter = getCompiledLogFilter();\n return buffer.getRecent(n, levels, sources).filter((l) => !shouldDropForDisplay(l, filter));\n}\n\n/** \u83B7\u53D6\u5168\u90E8\u65E5\u5FD7\uFF1B\u914D\u7F6E\u8FC7\u6EE4\u4EC5\u5F71\u54CD\u8FD4\u56DE\u89C6\u56FE\uFF08\u7F13\u51B2\u5185\u53EF\u80FD\u4ECD\u6709\u5168\u91CF\uFF0C\u89C6 push \u65F6 applyTo\uFF09 */\nexport function getAllLogs(): UnifiedLog[] {\n const filter = getCompiledLogFilter();\n return buffer.getAll().filter((l) => !shouldDropForDisplay(l, filter));\n}\n\n/* ==================================================================\n * \u843D\u76D8\u6587\u4EF6\u8BFB\u53D6\uFF08/logs \u7A97\u7528\uFF0C\u4E0D\u8D70\u5185\u5B58\u7F13\u51B2\uFF09\n * ================================================================== */\n\n/** \u4E0E\u843D\u76D8\u7B56\u7565\u5BF9\u5E94\u7684\u6587\u4EF6\u57FA\u540D\uFF08\u4E0D\u542B .log\uFF09 */\nconst DISK_LOG_FILES = [\"bds\", \"llbot\", \"db\", \"qq\", \"bds-update\", \"sfmc\"] as const;\n\n/** source \u2192 \u843D\u76D8\u6587\u4EF6\u540D\uFF08\u542B\u5B50\u8FDB\u7A0B\u81EA\u5199\uFF09 */\nexport function diskFileForSource(source: string): string {\n if (source === \"update\") return \"bds-update\";\n if (source === \"bds\" || source === \"llbot\" || source === \"db\" || source === \"qq\") return source;\n return \"sfmc\";\n}\n\n/** formatLogLine \u65E0\u8272\u884C\uFF1A`YYYY-MM-DD HH:mm:ss [source] [LEVEL] text` */\nconst DISK_LINE_RE =\n /^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[([^\\]]+)\\] \\[(INFO|WARN|ERROR|OK|DEBUG|SUCCESS|FATAL)\\]\\s?(.*)$/;\n\nfunction mapDiskLevelTag(tag: string): LogLevel {\n switch (tag) {\n case \"ERROR\":\n case \"FATAL\":\n return \"error\";\n case \"WARN\":\n return \"warn\";\n case \"OK\":\n case \"SUCCESS\":\n return \"success\";\n case \"DEBUG\":\n return \"debug\";\n default:\n return \"info\";\n }\n}\n\n/** \u89E3\u6790\u5355\u884C\u843D\u76D8\u65E5\u5FD7\uFF1B\u4E0D\u7B26\u683C\u5F0F\u8FD4\u56DE null */\nexport function parseDiskLogLine(raw: string): UnifiedLog | null {\n const m = DISK_LINE_RE.exec(raw);\n if (!m) return null;\n const ts = m[1]!;\n const source = m[2]!.trim();\n const level = mapDiskLevelTag(m[3]!);\n const body = m[4] ?? \"\";\n const time = new Date(ts.replace(\" \", \"T\") + \"Z\");\n return { time, source, level, text: body };\n}\n\nexport type ReadDiskLogsOpts = {\n levels?: LogLevel[];\n sources?: LogSource[];\n /** \u8986\u76D6\u65E5\u5FD7\u76EE\u5F55\uFF08\u6D4B\u8BD5\u7528\uFF09\uFF1B\u9ED8\u8BA4 `<ROOT>/.sfmc/logs` */\n dir?: string;\n};\n\n/**\n * \u4ECE `.sfmc/logs/*.log` \u8BFB\u53D6\u5E76\u89E3\u6790\u4E3A UnifiedLog\uFF08\u6309\u65F6\u95F4\u5347\u5E8F\uFF09\u3002\n * \u4F9B /logs \u7B5B\u9009\u7A97\u56DE\u653E\uFF1B\u4E0E\u5185\u5B58\u7F13\u51B2\u65E0\u5173\u3002\n */\nexport function readDiskLogs(opts: ReadDiskLogsOpts = {}): UnifiedLog[] {\n const levels = opts.levels ?? [];\n const sources = opts.sources ?? [];\n const dir = opts.dir ?? logsDir(ROOT);\n const fileNames = new Set<string>();\n if (sources.length === 0) {\n for (const n of DISK_LOG_FILES) fileNames.add(n);\n } else {\n for (const s of sources) fileNames.add(diskFileForSource(s));\n }\n\n const out: UnifiedLog[] = [];\n for (const name of fileNames) {\n const fp = path.join(dir, name.endsWith(\".log\") ? name : `${name}.log`);\n let text: string;\n try {\n text = fs.readFileSync(fp, \"utf8\");\n } catch {\n continue;\n }\n for (const raw of text.split(/\\r?\\n/)) {\n if (!raw) continue;\n const entry = parseDiskLogLine(raw);\n if (!entry) continue;\n if (sources.length && !sources.includes(entry.source)) continue;\n if (levels.length && !levels.includes(entry.level)) continue;\n out.push(entry);\n }\n }\n out.sort((a, b) => a.time.getTime() - b.time.getTime());\n return out;\n}\n\n/* ==================================================================\n * \u6765\u6E90\u6807\u7B7E\u5143\u6570\u636E (\u65B9\u62EC\u53F7\u4E0E\u6587\u5B57\u540C\u8272,\u5BF9\u9F50 levelTag)\n * ================================================================== */\n\nexport interface SourceMeta {\n value: string;\n /** \u65B9\u62EC\u53F7\u5185\u56FA\u5B9A 3 \u5B57\u7B26\uFF0C\u4E0E [INF] \u5BF9\u9F50 */\n name: string;\n paint: (s: string) => string;\n}\n\nexport const SOURCE_META: SourceMeta[] = [\n { value: \"bds\", name: \"BDS\", paint: (s) => c.green(s) },\n { value: \"db\", name: \"DB \", paint: (s) => c.blue(s) },\n { value: \"qq\", name: \"QQ \", paint: (s) => c.purple(s) },\n { value: \"llbot\", name: \"BOT\", paint: (s) => c.yellow(s) },\n { value: \"system\", name: \"SYS\", paint: (s) => c.cyan(s) },\n { value: \"update\", name: \"UPD\", paint: (s) => c.orange(s) },\n { value: \"pack\", name: \"PAK\", paint: (s) => c.purple(s) },\n { value: \"bds-tools\", name: \"TOL\", paint: (s) => c.red(s) },\n];\n\n/** \u6E90\u6807\u7B7E\u65E0\u8272\u6587\u672C\uFF08formatSourceTag / logPrefixWidth \u5171\u7528\uFF09 */\nfunction sourceTagPlain(source: string): string {\n const meta = SOURCE_META.find((m) => m.value === source);\n if (meta) return `[${meta.name}]`;\n return `[${source.toUpperCase().padEnd(3).slice(0, 3)}]`;\n}\n\nexport function formatSourceTag(source: string): string {\n const meta = SOURCE_META.find((m) => m.value === source);\n const plain = sourceTagPlain(source);\n if (meta) return meta.paint(plain);\n return c.bold(plain);\n}\n\n/**\n * \u5C55\u793A\u7528\u7EA7\u522B\uFF1ABDS \u82E5\u4ECD\u5E26\u65F6\u95F4\u6233\u524D\u7F00\u5219\u89E3\u6790\u5185\u5D4C\u7EA7\u522B\uFF1B\u5DF2\u5265\u79BB\uFF08pushLog \u5165\u5E93\uFF09\u5219\u4FE1\u4EFB entry.level\u3002\n * \u7981\u6B62\u5BF9\u6B63\u6587\u505A\u677E\u6563\u5173\u952E\u8BCD\u5339\u914D\uFF08\u4F1A\u628A `[Commands] Error on line` \u8BEF\u5224\u4E3A error\uFF09\u3002\n */\nexport function resolveDisplayLevel(l: UnifiedLog): LogLevel {\n if (l.source === \"bds\") {\n const embedded = parseBdsEmbeddedLevel(l.text);\n if (embedded) return embedded;\n }\n return l.level;\n}\n\n/** \u4ECE\u539F\u59CB\u6587\u672C\u63A8\u65AD\u7EA7\u522B\uFF1A\u59D4\u6258\u5171\u4EAB\u5305\uFF08\u5185\u542B BDS \u65F6\u95F4\u6233\u89E3\u6790\uFF09 */\nexport function inferLevel(text: string): LogLevel {\n return sharedInferLevel(text);\n}\n\n/** \u65E0\u8272\u7EA7\u522B\u6807\u7B7E\u6587\u672C\uFF08\u53EF\u89C1\u5BBD\u5EA6\u6743\u5A01\u6E90\uFF1B\u62EC\u53F7\u5185\u5747\u4E3A 3 \u5B57\u7B26\uFF09 */\nconst LEVEL_TAG_TEXT: Record<LogLevel, string> = {\n error: \"[ERR]\",\n warn: \"[WRN]\",\n success: \"[SUC]\",\n debug: \"[DBG]\",\n info: \"[INF]\",\n};\n\nfunction levelTagPlain(lvl: LogLevel): string {\n return LEVEL_TAG_TEXT[lvl] ?? LEVEL_TAG_TEXT.info;\n}\n\nfunction levelTag(lvl: LogLevel): string {\n const text = levelTagPlain(lvl);\n switch (lvl) {\n case \"error\":\n return c.red(text);\n case \"warn\":\n return c.yellow(text);\n case \"success\":\n return c.green(c.bold(text));\n case \"debug\":\n return c.dim(text);\n default:\n return c.blue(text);\n }\n}\n\n/** \u683C\u5F0F\u5316\u65E5\u5FD7\u7528\u4E8E REPL \u5C55\u793A (\u7528 theme.ts chalk \u914D\u8272) */\nexport function formatLog(l: UnifiedLog): string {\n const ts = c.dim(l.time.toLocaleTimeString());\n const level = resolveDisplayLevel(l);\n const lvl = levelTag(level);\n const src = formatSourceTag(l.source);\n /* BDS\uFF1A\u53BB\u6389\u81EA\u5E26\u65F6\u95F4\u6233+\u7B49\u7EA7\u524D\u7F00\u540E\u518D\u9AD8\u4EAE\u6B63\u6587\uFF08push \u65F6\u591A\u534A\u5DF2\u5265\u8FC7\uFF0C\u6B64\u5904\u5E42\u7B49\uFF09 */\n const txt = highlightLogLine(l.source === \"bds\" ? stripBdsLogPrefix(l.text) : l.text);\n return `${ts} ${src} ${lvl} ${txt}`;\n}\n\n/* ==================================================================\n * \u8F6F\u6362\u884C: \u8D85\u7EC8\u7AEF\u5BBD\u5EA6\u65F6\u6362\u884C,\u540E\u7EED\u884C\u7F29\u8FDB\u5BF9\u9F50\n * ================================================================== */\n\n/** \u5355\u4E2A\u5B57\u7B26\u5728\u7EC8\u7AEF\u7684\u663E\u793A\u5BBD\u5EA6 (CJK \u5168\u89D2=2, \u5176\u4F59=1) */\nfunction charWidth(ch: string): number {\n const cp = ch.codePointAt(0) ?? 0;\n if (\n cp >= 0x1100 &&\n (cp <= 0x115f ||\n (cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||\n (cp >= 0xac00 && cp <= 0xd7a3) ||\n (cp >= 0xf900 && cp <= 0xfaff) ||\n (cp >= 0xfe30 && cp <= 0xfe4f) ||\n (cp >= 0xff00 && cp <= 0xff60) ||\n (cp >= 0xffe0 && cp <= 0xffe6) ||\n (cp >= 0x20000 && cp <= 0x2fffd))\n )\n return 2;\n return 1;\n}\n\n/** \u5B57\u7B26\u4E32\u5728\u7EC8\u7AEF\u7684\u53EF\u89C1\u5BBD\u5EA6 (strip ANSI \u540E\u6309 CJK \u5BBD\u5EA6\u7D2F\u52A0) */\nexport function visibleWidth(s: string): number {\n const stripped = s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n let w = 0;\n for (const ch of stripped) w += charWidth(ch);\n return w;\n}\n\n/**\n * \u65E5\u5FD7\u524D\u7F00\u53EF\u89C1\u5BBD\u5EA6(\u65F6\u95F4 + \u6E90 + \u7EA7\u522B + \u5C3E\u7A7A\u683C),\u4F9B\u60AC\u6302\u7F29\u8FDB\u5BF9\u9F50\u6B63\u6587\u8D77\u70B9\u3002\n * \u4E0E formatLog \u62FC\u63A5\u987A\u5E8F\u4FDD\u6301\u4E00\u81F4\uFF08\u5171\u7528 resolveDisplayLevel / sourceTagPlain / levelTagPlain\uFF09\u3002\n */\nexport function logPrefixWidth(l: UnifiedLog): number {\n const ts = l.time.toLocaleTimeString();\n const src = sourceTagPlain(l.source);\n const level = resolveDisplayLevel(l);\n return visibleWidth(`${ts} ${src} ${levelTagPlain(level)} `);\n}\n\n/**\n * \u6309\u7EC8\u7AEF\u53EF\u89C1\u5BBD\u5EA6\u6362\u884C;\u663E\u5F0F \\\\n \u4E0E\u8F6F\u6362\u884C\u7684\u540E\u7EED\u884C\u4E00\u5F8B\u5DE6\u4FA7\u7F29\u8FDB indent \u5217\u3002\n * \u4FDD\u7559 ANSI:\u6362\u884C\u65F6 reset,\u65B0\u884C\u6062\u590D\u5F53\u524D\u989C\u8272\u72B6\u6001(\u53EF\u591A\u5C42\u53E0\u52A0)\u3002\n * \u5BBD\u5B57\u7B26(CJK)\u6309 2 \u5217;cols \u9884\u7559 1 \u5217,\u907F\u514D Windows Terminal \u8FB9\u754C\u518D\u8F6F\u6298\u5230\u7B2C 0 \u5217\u3002\n */\nexport function wrapLogLine(s: string, indent: number): string {\n const rawCols = process.stdout.columns || 80;\n /* \u81F3\u5C11\u7559\u7ED9\u6B63\u6587\u82E5\u5E72\u5217,\u907F\u514D indent >= cols \u65F6\u6B7B\u5FAA\u73AF */\n const cols = Math.max(rawCols - 1, indent + 4);\n const segments = s.split(/\\r?\\n/);\n const out: string[] = [];\n for (let si = 0; si < segments.length; si++) {\n const raw = segments[si]!;\n /* \u663E\u5F0F\u6362\u884C\u6BB5\u53BB\u6389\u6587\u6848\u81EA\u5E26\u7684\u5DE6\u7A7A\u683C,\u7EDF\u4E00\u7531 hang indent \u5BF9\u9F50\u6B63\u6587 */\n const piece = si === 0 ? raw : raw.replace(/^[ \\t]+/, \"\");\n out.push(wrapSegment(piece, cols, si === 0 ? 0 : indent, indent));\n }\n return out.join(\"\\n\");\n}\n\n/** \u5355\u6BB5(\u65E0\u5185\u5D4C \\\\n)\u8F6F\u6362\u884C;startPad>0 \u8868\u793A\u672C\u6BB5\u5F00\u5934\u5DF2\u5360\u7528\u7684\u5217(\u663E\u5F0F\u6362\u884C\u540E\u7684\u60AC\u6302) */\nfunction wrapSegment(s: string, cols: number, startPad: number, hangIndent: number): string {\n if (s.length === 0) return startPad > 0 ? \" \".repeat(startPad) : \"\";\n\n const lines: string[] = [];\n let cur = startPad > 0 ? \" \".repeat(startPad) : \"\";\n let w = startPad;\n /** \u5F53\u524D\u751F\u6548\u7684 ANSI \u5F00\u7801\u6808(\u4E0D\u542B reset),\u6362\u884C\u540E\u91CD\u653E */\n const ansiStack: string[] = [];\n\n const resetIfNeeded = (): void => {\n if (ansiStack.length) cur += \"\\x1b[0m\";\n };\n const replayAnsi = (): void => {\n for (const code of ansiStack) cur += code;\n };\n\n let i = 0;\n while (i < s.length) {\n const m = /^\\x1b\\[[0-9;]*m/.exec(s.slice(i));\n if (m) {\n const code = m[0]!;\n cur += code;\n if (code === \"\\x1b[0m\") ansiStack.length = 0;\n else ansiStack.push(code);\n i += code.length;\n continue;\n }\n\n const cp = s.codePointAt(i)!;\n const ch = String.fromCodePoint(cp);\n const cw = charWidth(ch);\n const advance = ch.length;\n\n /* w > startPad:\u5F53\u524D\u884C\u9664\u5DE6\u57AB\u5916\u5DF2\u6709\u5185\u5BB9,\u53EF\u4EE5\u62C6\u884C;\u5426\u5219\u5F3A\u5236\u585E\u5165\u907F\u514D\u6B7B\u5FAA\u73AF */\n if (w + cw > cols && w > startPad) {\n resetIfNeeded();\n lines.push(cur);\n cur = \" \".repeat(hangIndent);\n replayAnsi();\n w = hangIndent;\n startPad = hangIndent;\n }\n\n cur += ch;\n w += cw;\n i += advance;\n }\n\n if (ansiStack.length) cur += \"\\x1b[0m\";\n lines.push(cur);\n return lines.join(\"\\n\");\n}\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * logs.ts \u2014 sfmc \u4E3B\u8FDB\u7A0B\u7EDF\u4E00\u65E5\u5FD7\u805A\u5408\u5C42\n *\n * \u5185\u90E8\u59D4\u6258 @sfmc-bds/logs \u5171\u4EAB\u5305\u7684 createMemoryBuffer + inferLevel,\n * \u4FDD\u6301\u5411\u540E\u517C\u5BB9\u7684 pushLog / onLog / getAllLogs / getRecentLogs API\n * (services.ts \u6355\u83B7\u5B50\u8FDB\u7A0B stdout \u540E\u8C03\u7528 pushLog \u6C47\u805A\u5230\u6B64)\u3002\n *\n * \u843D\u76D8\u7B56\u7565(\u4E0E\u5B50\u8FDB\u7A0B\u81EA\u5199\u6587\u4EF6\u5206\u5DE5,\u907F\u514D\u91CD\u590D):\n * - db / qq / update \u2192 \u5B50\u8FDB\u7A0B\u5DF2\u5199 `.sfmc/logs/{db,qq,bds-update}.log`,\u6B64\u5904\u8DF3\u8FC7\n * - bds / llbot \u2192 `.sfmc/logs/{bds,llbot}.log`(\u5916\u90E8\u8FDB\u7A0B\u65E0\u81EA\u5E26 file sink)\n * - \u5176\u4F59(system / pack / \u2026) \u2192 `.sfmc/logs/sfmc.log`\n *\n * formatLog \u4FDD\u7559 theme.ts (chalk) \u914D\u8272,\u6BD4\u5171\u4EAB\u5305\u7684\u7EAF ANSI \u7248\u672C\u89C6\u89C9\u66F4\u4E30\u5BCC\u3002\n */\n\nimport {\n createFileSink,\n createMemoryBuffer,\n formatLogLine,\n inferLevel as sharedInferLevel,\n parseBdsEmbeddedLevel,\n stripBdsLogPrefix,\n type FileSink,\n type LogEntry,\n type LogLevel as SharedLogLevel,\n} from \"@sfmc-bds/sdk/logs\";\nimport { logFile, logsDir } from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n getCompiledLogFilter,\n shouldDropForDisk,\n shouldDropForDisplay,\n transformLogEntry,\n} from \"./log-filter.js\";\nimport { c, highlightLogLine } from \"./theme.js\";\nimport { ROOT } from \"./runtime.js\";\n\nexport type LogLevel = SharedLogLevel;\nexport type LogSource = string;\nexport interface UnifiedLog extends LogEntry {}\n\n/** \u518D\u5BFC\u51FA SDK BDS \u89E3\u6790\uFF08\u6D4B\u8BD5\u4E0E\u8C03\u7528\u65B9\u7EDF\u4E00\u5165\u53E3\uFF0C\u6743\u5A01\u5728 @sfmc-bds/sdk/logs\uFF09 */\nexport { mapBdsLevelToken, parseBdsEmbeddedLevel, stripBdsLogPrefix } from \"@sfmc-bds/sdk/logs\";\n\nconst buffer = createMemoryBuffer(5000);\n\n/** \u5B50\u8FDB\u7A0B\u5DF2\u7528 createNodeServiceLogger \u81EA\u884C\u843D\u76D8\u7684 source */\nconst CHILD_OWNED_SOURCES = new Set([\"db\", \"qq\", \"update\"]);\n\nconst fileSinks = new Map<string, FileSink>();\n\n/** \u5265\u79BB BDS \u81EA\u5E26\u524D\u7F00\uFF1B\u82E5\u524D\u7F00\u540E\u6CA1\u6709\u6B63\u6587\uFF0C\u5219\u5224\u5B9A\u4E3A\u4EC5\u7528\u4E8E\u6392\u7248\u7684\u7A7A\u884C\u3002 */\nexport function normalizeBdsLogBody(text: string): string | null {\n const body = stripBdsLogPrefix(text);\n return body.trim().length > 0 ? body : null;\n}\n\n/** \u89E3\u6790\u672C\u6761\u65E5\u5FD7\u5E94\u5199\u5165\u7684\u6587\u4EF6\u540D(\u4E0D\u542B .log);null \u8868\u793A\u8DF3\u8FC7(\u5B50\u8FDB\u7A0B\u5DF2\u5199) */\nfunction resolveDiskLogName(source: string): string | null {\n if (CHILD_OWNED_SOURCES.has(source)) return null;\n if (source === \"bds\" || source === \"llbot\" || source === \"tunnel\") return source;\n return \"sfmc\";\n}\n\nfunction sinkFor(source: string): FileSink | null {\n const name = resolveDiskLogName(source);\n if (!name) return null;\n let sink = fileSinks.get(name);\n if (!sink) {\n sink = createFileSink(logFile(ROOT, name));\n fileSinks.set(name, sink);\n }\n return sink;\n}\n\nprocess.on(\"exit\", () => {\n for (const sink of fileSinks.values()) sink.close();\n});\n\n/** \u63A8\u9001\u4E00\u6761\u65E5\u5FD7\u5230\u5185\u5B58\u7F13\u51B2,\u5E76\u6309\u7B56\u7565\u843D\u76D8 */\nexport function pushLog(text: string, source: LogSource, level: LogLevel): void {\n let body = text;\n let lvl = level;\n /* BDS\uFF1A\u5148\u63D0\u53D6\u5185\u5D4C\u7EA7\u522B\uFF0C\u518D\u5265\u6389\u81EA\u5E26\u65F6\u95F4\u6233+\u7B49\u7EA7\uFF0C\u907F\u514D\u5C55\u793A/\u843D\u76D8\u91CD\u590D */\n if (source === \"bds\") {\n const embedded = parseBdsEmbeddedLevel(text);\n if (embedded) lvl = embedded;\n const normalized = normalizeBdsLogBody(text);\n if (normalized === null) return;\n body = normalized;\n }\n\n const rawEntry: LogEntry = { time: new Date(), text: body, source, level: lvl };\n const filter = getCompiledLogFilter((src) => {\n /* \u907F\u514D\u9012\u5F52\uFF1A\u975E\u6CD5\u6B63\u5219\u53EA\u5199\u6587\u4EF6 sink\uFF0C\u4E0D\u7ECF pushLog */\n try {\n const sink = sinkFor(\"system\");\n if (!sink) return;\n const warn: LogEntry = {\n time: new Date(),\n text: `log-filter: invalid regex skipped: ${src}`,\n source: \"system\",\n level: \"warn\",\n };\n sink.write(warn, formatLogLine(warn, false));\n } catch {\n /* ignore */\n }\n });\n\n const dropDisplay = shouldDropForDisplay(rawEntry, filter);\n const dropDisk = shouldDropForDisk(rawEntry, filter);\n const { entry: transformedEntry } = transformLogEntry(rawEntry, filter);\n\n if (!dropDisplay) {\n buffer.pushDirect(transformedEntry.text, source, lvl);\n }\n\n if (dropDisk) return;\n const sink = sinkFor(source);\n if (!sink) return;\n try {\n const diskEntry: LogEntry = filter.applyTo === \"all\" ? { ...rawEntry, text: transformedEntry.text } : rawEntry;\n sink.write(diskEntry, formatLogLine(diskEntry, false));\n } catch {\n /* \u843D\u76D8\u5931\u8D25\u4E0D\u963B\u65AD\u4E3B\u6D41\u7A0B */\n }\n}\n\n/** \u8BA2\u9605\u65B0\u65E5\u5FD7\u4E8B\u4EF6,\u8FD4\u56DE\u53D6\u6D88\u8BA2\u9605\u51FD\u6570 */\nexport function onLog(fn: (log: UnifiedLog) => void): () => void {\n return buffer.subscribe(fn);\n}\n\n/** \u83B7\u53D6\u6700\u8FD1 n \u6761,\u53EF\u6309 level / source \u8FC7\u6EE4\uFF1B\u518D\u5957\u914D\u7F6E\u8FC7\u6EE4\uFF08display\uFF09 */\nexport function getRecentLogs(n: number, levels: LogLevel[], sources: LogSource[]): UnifiedLog[] {\n const filter = getCompiledLogFilter();\n return buffer.getRecent(n, levels, sources).filter((l) => !shouldDropForDisplay(l, filter));\n}\n\n/** \u83B7\u53D6\u5168\u90E8\u65E5\u5FD7\uFF1B\u914D\u7F6E\u8FC7\u6EE4\u4EC5\u5F71\u54CD\u8FD4\u56DE\u89C6\u56FE\uFF08\u7F13\u51B2\u5185\u53EF\u80FD\u4ECD\u6709\u5168\u91CF\uFF0C\u89C6 push \u65F6 applyTo\uFF09 */\nexport function getAllLogs(): UnifiedLog[] {\n const filter = getCompiledLogFilter();\n return buffer.getAll().filter((l) => !shouldDropForDisplay(l, filter));\n}\n\n/* ==================================================================\n * \u843D\u76D8\u6587\u4EF6\u8BFB\u53D6\uFF08/logs \u7A97\u7528\uFF0C\u4E0D\u8D70\u5185\u5B58\u7F13\u51B2\uFF09\n * ================================================================== */\n\n/** \u4E0E\u843D\u76D8\u7B56\u7565\u5BF9\u5E94\u7684\u6587\u4EF6\u57FA\u540D\uFF08\u4E0D\u542B .log\uFF09 */\nconst DISK_LOG_FILES = [\"bds\", \"llbot\", \"tunnel\", \"db\", \"qq\", \"bds-update\", \"sfmc\"] as const;\n\n/** source \u2192 \u843D\u76D8\u6587\u4EF6\u540D\uFF08\u542B\u5B50\u8FDB\u7A0B\u81EA\u5199\uFF09 */\nexport function diskFileForSource(source: string): string {\n if (source === \"update\") return \"bds-update\";\n if (source === \"bds\" || source === \"llbot\" || source === \"tunnel\" || source === \"db\" || source === \"qq\") return source;\n return \"sfmc\";\n}\n\n/** formatLogLine \u65E0\u8272\u884C\uFF1A`YYYY-MM-DD HH:mm:ss [source] [LEVEL] text` */\nconst DISK_LINE_RE =\n /^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[([^\\]]+)\\] \\[(INFO|WARN|ERROR|OK|DEBUG|SUCCESS|FATAL)\\]\\s?(.*)$/;\n\nfunction mapDiskLevelTag(tag: string): LogLevel {\n switch (tag) {\n case \"ERROR\":\n case \"FATAL\":\n return \"error\";\n case \"WARN\":\n return \"warn\";\n case \"OK\":\n case \"SUCCESS\":\n return \"success\";\n case \"DEBUG\":\n return \"debug\";\n default:\n return \"info\";\n }\n}\n\n/** \u89E3\u6790\u5355\u884C\u843D\u76D8\u65E5\u5FD7\uFF1B\u4E0D\u7B26\u683C\u5F0F\u8FD4\u56DE null */\nexport function parseDiskLogLine(raw: string): UnifiedLog | null {\n const m = DISK_LINE_RE.exec(raw);\n if (!m) return null;\n const ts = m[1]!;\n const source = m[2]!.trim();\n const level = mapDiskLevelTag(m[3]!);\n const body = m[4] ?? \"\";\n const time = new Date(ts.replace(\" \", \"T\") + \"Z\");\n return { time, source, level, text: body };\n}\n\nexport type ReadDiskLogsOpts = {\n levels?: LogLevel[];\n sources?: LogSource[];\n /** \u8986\u76D6\u65E5\u5FD7\u76EE\u5F55\uFF08\u6D4B\u8BD5\u7528\uFF09\uFF1B\u9ED8\u8BA4 `<ROOT>/.sfmc/logs` */\n dir?: string;\n};\n\n/**\n * \u4ECE `.sfmc/logs/*.log` \u8BFB\u53D6\u5E76\u89E3\u6790\u4E3A UnifiedLog\uFF08\u6309\u65F6\u95F4\u5347\u5E8F\uFF09\u3002\n * \u4F9B /logs \u7B5B\u9009\u7A97\u56DE\u653E\uFF1B\u4E0E\u5185\u5B58\u7F13\u51B2\u65E0\u5173\u3002\n */\nexport function readDiskLogs(opts: ReadDiskLogsOpts = {}): UnifiedLog[] {\n const levels = opts.levels ?? [];\n const sources = opts.sources ?? [];\n const dir = opts.dir ?? logsDir(ROOT);\n const fileNames = new Set<string>();\n if (sources.length === 0) {\n for (const n of DISK_LOG_FILES) fileNames.add(n);\n } else {\n for (const s of sources) fileNames.add(diskFileForSource(s));\n }\n\n const out: UnifiedLog[] = [];\n for (const name of fileNames) {\n const fp = path.join(dir, name.endsWith(\".log\") ? name : `${name}.log`);\n let text: string;\n try {\n text = fs.readFileSync(fp, \"utf8\");\n } catch {\n continue;\n }\n for (const raw of text.split(/\\r?\\n/)) {\n if (!raw) continue;\n const entry = parseDiskLogLine(raw);\n if (!entry) continue;\n if (sources.length && !sources.includes(entry.source)) continue;\n if (levels.length && !levels.includes(entry.level)) continue;\n out.push(entry);\n }\n }\n out.sort((a, b) => a.time.getTime() - b.time.getTime());\n return out;\n}\n\n/* ==================================================================\n * \u6765\u6E90\u6807\u7B7E\u5143\u6570\u636E (\u65B9\u62EC\u53F7\u4E0E\u6587\u5B57\u540C\u8272,\u5BF9\u9F50 levelTag)\n * ================================================================== */\n\nexport interface SourceMeta {\n value: string;\n /** \u65B9\u62EC\u53F7\u5185\u56FA\u5B9A 3 \u5B57\u7B26\uFF0C\u4E0E [INF] \u5BF9\u9F50 */\n name: string;\n paint: (s: string) => string;\n}\n\nexport const SOURCE_META: SourceMeta[] = [\n { value: \"bds\", name: \"BDS\", paint: (s) => c.green(s) },\n { value: \"db\", name: \"DB \", paint: (s) => c.blue(s) },\n { value: \"qq\", name: \"QQ \", paint: (s) => c.purple(s) },\n { value: \"llbot\", name: \"BOT\", paint: (s) => c.yellow(s) },\n { value: \"system\", name: \"SYS\", paint: (s) => c.cyan(s) },\n { value: \"update\", name: \"UPD\", paint: (s) => c.orange(s) },\n { value: \"pack\", name: \"PAK\", paint: (s) => c.purple(s) },\n { value: \"bds-tools\", name: \"TOL\", paint: (s) => c.red(s) },\n];\n\n/** \u6E90\u6807\u7B7E\u65E0\u8272\u6587\u672C\uFF08formatSourceTag / logPrefixWidth \u5171\u7528\uFF09 */\nfunction sourceTagPlain(source: string): string {\n const meta = SOURCE_META.find((m) => m.value === source);\n if (meta) return `[${meta.name}]`;\n return `[${source.toUpperCase().padEnd(3).slice(0, 3)}]`;\n}\n\nexport function formatSourceTag(source: string): string {\n const meta = SOURCE_META.find((m) => m.value === source);\n const plain = sourceTagPlain(source);\n if (meta) return meta.paint(plain);\n return c.bold(plain);\n}\n\n/**\n * \u5C55\u793A\u7528\u7EA7\u522B\uFF1ABDS \u82E5\u4ECD\u5E26\u65F6\u95F4\u6233\u524D\u7F00\u5219\u89E3\u6790\u5185\u5D4C\u7EA7\u522B\uFF1B\u5DF2\u5265\u79BB\uFF08pushLog \u5165\u5E93\uFF09\u5219\u4FE1\u4EFB entry.level\u3002\n * \u7981\u6B62\u5BF9\u6B63\u6587\u505A\u677E\u6563\u5173\u952E\u8BCD\u5339\u914D\uFF08\u4F1A\u628A `[Commands] Error on line` \u8BEF\u5224\u4E3A error\uFF09\u3002\n */\nexport function resolveDisplayLevel(l: UnifiedLog): LogLevel {\n if (l.source === \"bds\") {\n const embedded = parseBdsEmbeddedLevel(l.text);\n if (embedded) return embedded;\n }\n return l.level;\n}\n\n/** \u4ECE\u539F\u59CB\u6587\u672C\u63A8\u65AD\u7EA7\u522B\uFF1A\u59D4\u6258\u5171\u4EAB\u5305\uFF08\u5185\u542B BDS \u65F6\u95F4\u6233\u89E3\u6790\uFF09 */\nexport function inferLevel(text: string): LogLevel {\n return sharedInferLevel(text);\n}\n\n/** \u65E0\u8272\u7EA7\u522B\u6807\u7B7E\u6587\u672C\uFF08\u53EF\u89C1\u5BBD\u5EA6\u6743\u5A01\u6E90\uFF1B\u62EC\u53F7\u5185\u5747\u4E3A 3 \u5B57\u7B26\uFF09 */\nconst LEVEL_TAG_TEXT: Record<LogLevel, string> = {\n error: \"[ERR]\",\n warn: \"[WRN]\",\n success: \"[SUC]\",\n debug: \"[DBG]\",\n info: \"[INF]\",\n};\n\nfunction levelTagPlain(lvl: LogLevel): string {\n return LEVEL_TAG_TEXT[lvl] ?? LEVEL_TAG_TEXT.info;\n}\n\nfunction levelTag(lvl: LogLevel): string {\n const text = levelTagPlain(lvl);\n switch (lvl) {\n case \"error\":\n return c.red(text);\n case \"warn\":\n return c.yellow(text);\n case \"success\":\n return c.green(c.bold(text));\n case \"debug\":\n return c.dim(text);\n default:\n return c.blue(text);\n }\n}\n\n/** \u683C\u5F0F\u5316\u65E5\u5FD7\u7528\u4E8E REPL \u5C55\u793A (\u7528 theme.ts chalk \u914D\u8272) */\nexport function formatLog(l: UnifiedLog): string {\n const ts = c.dim(l.time.toLocaleTimeString());\n const level = resolveDisplayLevel(l);\n const lvl = levelTag(level);\n const src = formatSourceTag(l.source);\n /* BDS\uFF1A\u53BB\u6389\u81EA\u5E26\u65F6\u95F4\u6233+\u7B49\u7EA7\u524D\u7F00\u540E\u518D\u672C\u5730\u5316\u7FFB\u8BD1\u4E0E\u9AD8\u4EAE\u6B63\u6587\uFF08push \u65F6\u591A\u534A\u5DF2\u8F6C\u8FC7\uFF0C\u6B64\u5904\u5E42\u7B49\u4E14\u8986\u76D6\u56DE\u653E\uFF09 */\n const body = l.source === \"bds\" ? stripBdsLogPrefix(l.text) : l.text;\n const filter = getCompiledLogFilter();\n const { entry } = transformLogEntry({ text: body, source: l.source, level }, filter);\n const txt = highlightLogLine(entry.text);\n return `${ts} ${src} ${lvl} ${txt}`;\n}\n\n/* ==================================================================\n * \u8F6F\u6362\u884C: \u8D85\u7EC8\u7AEF\u5BBD\u5EA6\u65F6\u6362\u884C,\u540E\u7EED\u884C\u7F29\u8FDB\u5BF9\u9F50\n * ================================================================== */\n\n/** \u5355\u4E2A\u5B57\u7B26\u5728\u7EC8\u7AEF\u7684\u663E\u793A\u5BBD\u5EA6 (CJK \u5168\u89D2=2, \u5176\u4F59=1) */\nfunction charWidth(ch: string): number {\n const cp = ch.codePointAt(0) ?? 0;\n if (\n cp >= 0x1100 &&\n (cp <= 0x115f ||\n (cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||\n (cp >= 0xac00 && cp <= 0xd7a3) ||\n (cp >= 0xf900 && cp <= 0xfaff) ||\n (cp >= 0xfe30 && cp <= 0xfe4f) ||\n (cp >= 0xff00 && cp <= 0xff60) ||\n (cp >= 0xffe0 && cp <= 0xffe6) ||\n (cp >= 0x20000 && cp <= 0x2fffd))\n )\n return 2;\n return 1;\n}\n\n/** \u5B57\u7B26\u4E32\u5728\u7EC8\u7AEF\u7684\u53EF\u89C1\u5BBD\u5EA6 (strip ANSI \u540E\u6309 CJK \u5BBD\u5EA6\u7D2F\u52A0) */\nexport function visibleWidth(s: string): number {\n const stripped = s.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n let w = 0;\n for (const ch of stripped) w += charWidth(ch);\n return w;\n}\n\n/**\n * \u65E5\u5FD7\u524D\u7F00\u53EF\u89C1\u5BBD\u5EA6(\u65F6\u95F4 + \u6E90 + \u7EA7\u522B + \u5C3E\u7A7A\u683C),\u4F9B\u60AC\u6302\u7F29\u8FDB\u5BF9\u9F50\u6B63\u6587\u8D77\u70B9\u3002\n * \u4E0E formatLog \u62FC\u63A5\u987A\u5E8F\u4FDD\u6301\u4E00\u81F4\uFF08\u5171\u7528 resolveDisplayLevel / sourceTagPlain / levelTagPlain\uFF09\u3002\n */\nexport function logPrefixWidth(l: UnifiedLog): number {\n const ts = l.time.toLocaleTimeString();\n const src = sourceTagPlain(l.source);\n const level = resolveDisplayLevel(l);\n return visibleWidth(`${ts} ${src} ${levelTagPlain(level)} `);\n}\n\n/**\n * \u6309\u7EC8\u7AEF\u53EF\u89C1\u5BBD\u5EA6\u6362\u884C;\u663E\u5F0F \\\\n \u4E0E\u8F6F\u6362\u884C\u7684\u540E\u7EED\u884C\u4E00\u5F8B\u5DE6\u4FA7\u7F29\u8FDB indent \u5217\u3002\n * \u4FDD\u7559 ANSI:\u6362\u884C\u65F6 reset,\u65B0\u884C\u6062\u590D\u5F53\u524D\u989C\u8272\u72B6\u6001(\u53EF\u591A\u5C42\u53E0\u52A0)\u3002\n * \u5BBD\u5B57\u7B26(CJK)\u6309 2 \u5217;cols \u9884\u7559 1 \u5217,\u907F\u514D Windows Terminal \u8FB9\u754C\u518D\u8F6F\u6298\u5230\u7B2C 0 \u5217\u3002\n */\nexport function wrapLogLine(s: string, indent: number): string {\n const rawCols = process.stdout.columns || 80;\n /* \u81F3\u5C11\u7559\u7ED9\u6B63\u6587\u82E5\u5E72\u5217,\u907F\u514D indent >= cols \u65F6\u6B7B\u5FAA\u73AF */\n const cols = Math.max(rawCols - 1, indent + 4);\n const segments = s.split(/\\r?\\n/);\n const out: string[] = [];\n for (let si = 0; si < segments.length; si++) {\n const raw = segments[si]!;\n /* \u663E\u5F0F\u6362\u884C\u6BB5\u53BB\u6389\u6587\u6848\u81EA\u5E26\u7684\u5DE6\u7A7A\u683C,\u7EDF\u4E00\u7531 hang indent \u5BF9\u9F50\u6B63\u6587 */\n const piece = si === 0 ? raw : raw.replace(/^[ \\t]+/, \"\");\n out.push(wrapSegment(piece, cols, si === 0 ? 0 : indent, indent));\n }\n return out.join(\"\\n\");\n}\n\n/** \u5355\u6BB5(\u65E0\u5185\u5D4C \\\\n)\u8F6F\u6362\u884C;startPad>0 \u8868\u793A\u672C\u6BB5\u5F00\u5934\u5DF2\u5360\u7528\u7684\u5217(\u663E\u5F0F\u6362\u884C\u540E\u7684\u60AC\u6302) */\nfunction wrapSegment(s: string, cols: number, startPad: number, hangIndent: number): string {\n if (s.length === 0) return startPad > 0 ? \" \".repeat(startPad) : \"\";\n\n const lines: string[] = [];\n let cur = startPad > 0 ? \" \".repeat(startPad) : \"\";\n let w = startPad;\n /** \u5F53\u524D\u751F\u6548\u7684 ANSI \u5F00\u7801\u6808(\u4E0D\u542B reset),\u6362\u884C\u540E\u91CD\u653E */\n const ansiStack: string[] = [];\n\n const resetIfNeeded = (): void => {\n if (ansiStack.length) cur += \"\\x1b[0m\";\n };\n const replayAnsi = (): void => {\n for (const code of ansiStack) cur += code;\n };\n\n let i = 0;\n while (i < s.length) {\n const m = /^\\x1b\\[[0-9;]*m/.exec(s.slice(i));\n if (m) {\n const code = m[0]!;\n cur += code;\n if (code === \"\\x1b[0m\") ansiStack.length = 0;\n else ansiStack.push(code);\n i += code.length;\n continue;\n }\n\n const cp = s.codePointAt(i)!;\n const ch = String.fromCodePoint(cp);\n const cw = charWidth(ch);\n const advance = ch.length;\n\n /* w > startPad:\u5F53\u524D\u884C\u9664\u5DE6\u57AB\u5916\u5DF2\u6709\u5185\u5BB9,\u53EF\u4EE5\u62C6\u884C;\u5426\u5219\u5F3A\u5236\u585E\u5165\u907F\u514D\u6B7B\u5FAA\u73AF */\n if (w + cw > cols && w > startPad) {\n resetIfNeeded();\n lines.push(cur);\n cur = \" \".repeat(hangIndent);\n replayAnsi();\n w = hangIndent;\n startPad = hangIndent;\n }\n\n cur += ch;\n w += cw;\n i += advance;\n }\n\n if (ansiStack.length) cur += \"\\x1b[0m\";\n lines.push(cur);\n return lines.join(\"\\n\");\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": ["parseBdsEmbeddedLevel", "stripBdsLogPrefix", "sink"]
7
7
  }
package/dist/main.js CHANGED
@@ -81,6 +81,11 @@ async function main() {
81
81
  case "debug":
82
82
  console.log(await cmdDebug(rest));
83
83
  break;
84
+ case "ui": {
85
+ const { cmdUi } = await import("./ui-command.js");
86
+ console.log(await cmdUi(rest, { block: true }));
87
+ break;
88
+ }
84
89
  case "status":
85
90
  console.log(await cmdStatus());
86
91
  break;