@sfmc-bds/cli 0.2.0-beta.11 → 0.2.0-beta.13

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 (55) hide show
  1. package/dist/commands.d.ts +57 -4
  2. package/dist/commands.d.ts.map +1 -1
  3. package/dist/commands.js.map +2 -2
  4. package/dist/i18n/locales/zh-CN.js +1 -1
  5. package/dist/i18n/locales/zh-CN.js.map +1 -1
  6. package/dist/log-filter.d.ts +18 -2
  7. package/dist/log-filter.d.ts.map +1 -1
  8. package/dist/log-filter.js +54 -4
  9. package/dist/log-filter.js.map +2 -2
  10. package/dist/log-filter.test.js +62 -0
  11. package/dist/log-filter.test.js.map +2 -2
  12. package/dist/log-translator.d.ts +36 -0
  13. package/dist/log-translator.d.ts.map +1 -0
  14. package/dist/log-translator.js +279 -0
  15. package/dist/log-translator.js.map +7 -0
  16. package/dist/log-translator.test.js +120 -0
  17. package/dist/log-translator.test.js.map +7 -0
  18. package/dist/logs.d.ts.map +1 -1
  19. package/dist/logs.js +13 -7
  20. package/dist/logs.js.map +2 -2
  21. package/dist/module-commands.d.ts.map +1 -1
  22. package/dist/module-commands.js +21 -7
  23. package/dist/module-commands.js.map +2 -2
  24. package/dist/module-fingerprint.d.ts.map +1 -1
  25. package/dist/module-fingerprint.js +1 -0
  26. package/dist/module-fingerprint.js.map +2 -2
  27. package/dist/module-pack-build.d.ts.map +1 -1
  28. package/dist/module-pack-build.js +6 -1
  29. package/dist/module-pack-build.js.map +2 -2
  30. package/dist/module-toggle.d.ts +1 -1
  31. package/dist/module-toggle.d.ts.map +1 -1
  32. package/dist/module-toggle.js.map +1 -1
  33. package/dist/pack-lifecycle.d.ts.map +1 -1
  34. package/dist/pack-lifecycle.js +7 -2
  35. package/dist/pack-lifecycle.js.map +2 -2
  36. package/dist/registry.d.ts.map +1 -1
  37. package/dist/registry.js +4 -1
  38. package/dist/registry.js.map +2 -2
  39. package/dist/repl-windows/format-display.d.ts.map +1 -1
  40. package/dist/repl-windows/format-display.js +5 -1
  41. package/dist/repl-windows/format-display.js.map +2 -2
  42. package/dist/services.d.ts +14 -0
  43. package/dist/services.d.ts.map +1 -1
  44. package/dist/services.js.map +2 -2
  45. package/dist/sfmc-modules-root.d.ts.map +1 -1
  46. package/dist/sfmc-modules-root.js +6 -2
  47. package/dist/sfmc-modules-root.js.map +2 -2
  48. package/dist/wizard.d.ts.map +1 -1
  49. package/dist/wizard.js +20 -22
  50. package/dist/wizard.js.map +2 -2
  51. package/package.json +5 -4
  52. package/scripts/module-install/check-modules.mjs +10 -76
  53. package/scripts/module-install/lib/catalog.mjs +1 -1
  54. package/scripts/module-install/lib/lock.mjs +2 -2
  55. package/scripts/module-install/lib/packages.mjs +16 -22
@@ -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
+ }
@@ -0,0 +1,120 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import {
4
+ applyRuleReplacement,
5
+ interpolateRegexTemplate,
6
+ translateBdsLog
7
+ } from "./log-translator.js";
8
+ test("translateBdsLog: Beta APIs \u7F3A\u5931\u963B\u65AD", () => {
9
+ const line = "Plugin [sfmc-modules - 1.0.0] - requesting dependency on beta APIs [@minecraft/server-admin - 1.0.0-beta], but the Beta APIs experiment is not enabled.";
10
+ const res = translateBdsLog(line, "zh-CN");
11
+ assert.equal(res.translated, true);
12
+ assert.equal(res.ruleId, "beta-apis-missing");
13
+ assert.ok(res.text.includes("\u63D2\u4EF6\u300Csfmc-modules - 1.0.0\u300D\u4F9D\u8D56\u6D4B\u8BD5\u7248 API (@minecraft/server-admin - 1.0.0-beta)"));
14
+ assert.ok(res.text.includes("\u672A\u5F00\u542F\u300C\u6D4B\u8BD5\u7248 API (Beta APIs)\u300D\u5B9E\u9A8C\u5F00\u5173"));
15
+ });
16
+ test("translateBdsLog: \u811A\u672C\u8BED\u6CD5\u9519\u8BEF missing export", () => {
17
+ const line = "SyntaxError: Could not find export 'Vector3' in module '@minecraft/server'";
18
+ const res = translateBdsLog(line, "zh-CN");
19
+ assert.equal(res.translated, true);
20
+ assert.equal(res.ruleId, "script-syntax-missing-export");
21
+ assert.ok(res.text.includes("\u6A21\u7EC4\u5C1D\u8BD5\u4ECE\u300C@minecraft/server\u300D\u5BFC\u5165\u4E0D\u5B58\u5728\u7684\u7B26\u53F7\u300CVector3\u300D"));
22
+ });
23
+ test("translateBdsLog: \u6FC0\u6D3B\u5305\u5728\u672C\u5730\u7F3A\u5931", () => {
24
+ const line = "Configured pack (id: 3116e462-9838-48bf-be53-354958c1810f, version: 1.21.100) was not found and was ignored";
25
+ const res = translateBdsLog(line, "zh-CN");
26
+ assert.equal(res.translated, true);
27
+ assert.equal(res.ruleId, "configured-pack-missing");
28
+ assert.ok(res.text.includes("UUID: 3116e462-9838-48bf-be53-354958c1810f"));
29
+ assert.ok(res.text.includes("\u7248\u672C: 1.21.100"));
30
+ });
31
+ test("translateBdsLog: \u81EA\u5B9A\u4E49\u65B9\u5757\u5F62\u6001\u6570\u91CF\u8D85\u9650", () => {
32
+ const line = "World with over 65536 block permutations may degrade performance. Current world has 74227 permutations.";
33
+ const res = translateBdsLog(line, "zh-CN");
34
+ assert.equal(res.translated, true);
35
+ assert.equal(res.ruleId, "block-permutations-limit");
36
+ assert.ok(res.text.includes("74227 \u4E2A"));
37
+ assert.ok(res.text.includes("\u8D85\u51FA\u63A8\u8350\u4E0A\u9650 65,536"));
38
+ });
39
+ test("translateBdsLog: \u914D\u65B9\u7269\u54C1\u7F3A\u5931", () => {
40
+ const line = "[Recipes] recipes/japanese/mochi_rice.json | amp:mochi_rice | The Item: amp:mochi_rice is missing or invalid, can't make the recipe";
41
+ const res = translateBdsLog(line, "zh-CN");
42
+ assert.equal(res.translated, true);
43
+ assert.equal(res.ruleId, "recipe-item-missing");
44
+ assert.ok(res.text.includes("\u914D\u65B9\u6587\u4EF6\u300Crecipes/japanese/mochi_rice.json\u300D"));
45
+ assert.ok(res.text.includes("\u7269\u54C1\u300Camp:mochi_rice\u300D\u4E0D\u5B58\u5728\u6216\u65E0\u6548"));
46
+ });
47
+ test("translateBdsLog: \u914D\u65B9\u539F\u6599\u7F3A\u5931", () => {
48
+ const line = "[Recipes] recipes/japanese/rice_eel.json | amp:rice_eel | Recipe for: amp:rice_eel is missing (unknown) ingredient";
49
+ const res = translateBdsLog(line, "zh-CN");
50
+ assert.equal(res.translated, true);
51
+ assert.equal(res.ruleId, "recipe-ingredient-missing");
52
+ assert.ok(res.text.includes("\u4EA7\u7269: amp:rice_eel"));
53
+ assert.ok(res.text.includes("\u7F3A\u5C11\u6709\u6548\u539F\u6599"));
54
+ });
55
+ test("translateBdsLog: \u914D\u65B9\u4EA7\u7269\u683C\u5F0F\u9519\u8BEF", () => {
56
+ const line = "[Recipes] recipes/furniture/money.json | amp:money | Recipe result malformed";
57
+ const res = translateBdsLog(line, "zh-CN");
58
+ assert.equal(res.translated, true);
59
+ assert.equal(res.ruleId, "recipe-result-malformed");
60
+ assert.ok(res.text.includes("\u4EA7\u7269\u7ED3\u679C\u5B9A\u4E49\u683C\u5F0F\u9519\u8BEF"));
61
+ });
62
+ test("translateBdsLog: \u65B9\u5757 Schema \u672A\u77E5\u7EC4\u4EF6\u4E0E\u5B50\u5C5E\u6027\u9519\u8BEF", () => {
63
+ const line1 = "[Blocks] block_definitions | worlds/Bedrock level/behavior_packs/[BP] TouHouLittleMaid_BP | blocks/skull/fairy_skull_2.json | -> components -> tlm:skull: this component was found in the input, but is not present in the Schema";
64
+ const res1 = translateBdsLog(line1, "zh-CN");
65
+ assert.equal(res1.translated, true);
66
+ assert.equal(res1.ruleId, "block-component-schema-unknown");
67
+ assert.ok(res1.text.includes("blocks/skull/fairy_skull_2.json"));
68
+ assert.ok(res1.text.includes("\u672A\u77E5\u7EC4\u4EF6: components -> tlm:skull"));
69
+ const line2 = "[Blocks] block_definitions | worlds/Bedrock level/behavior_packs/[BP] [BM] [\u81EA\u7814] [\u73A9\u6CD5] GlobalCuisine_BP | blocks/steamer/steamer.json | worlds/Bedrock level/behavior_packs/[BP] [BM] [\u81EA\u7814] [\u73A9\u6CD5] GlobalCuisine_BP | blocks/steamer/steamer.json | amp:steamer | components | amp:steamer | child 'amp:steamer' not valid here.";
70
+ const res2 = translateBdsLog(line2, "zh-CN");
71
+ assert.equal(res2.translated, true);
72
+ assert.equal(res2.ruleId, "block-child-component-invalid");
73
+ assert.ok(res2.text.includes("blocks/steamer/steamer.json"));
74
+ assert.ok(res2.text.includes("\u5B50\u5C5E\u6027\u300Camp:steamer\u300D\u5728\u6B64\u5904\u65E0\u6548"));
75
+ });
76
+ test("translateBdsLog: \u811A\u672C\u7EC4\u4EF6\u672A\u6CE8\u518C", () => {
77
+ const line = "[Scripting] Component 'tlm:deprecated' was not registered in script but used on an item";
78
+ const res = translateBdsLog(line, "zh-CN");
79
+ assert.equal(res.translated, true);
80
+ assert.equal(res.ruleId, "script-component-not-registered");
81
+ assert.ok(res.text.includes("\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300Ctlm:deprecated\u300D"));
82
+ });
83
+ test("translateBdsLog: \u670D\u52A1\u7AEF\u751F\u547D\u5468\u671F\u4E0E\u7AEF\u53E3", () => {
84
+ assert.equal(translateBdsLog("Server started.", "zh-CN").text, "[\u670D\u52A1\u7AEF] BDS \u670D\u52A1\u7AEF\u5DF2\u6210\u529F\u542F\u52A8\uFF0C\u51C6\u5907\u5C31\u7EEA\u3002");
85
+ assert.equal(translateBdsLog("Stopping server...", "zh-CN").text, "[\u670D\u52A1\u7AEF] \u6B63\u5728\u5173\u95ED\u670D\u52A1\u7AEF...");
86
+ assert.equal(translateBdsLog("Quit correctly", "zh-CN").text, "[\u670D\u52A1\u7AEF] \u670D\u52A1\u7AEF\u5DF2\u6B63\u5E38\u5B89\u5168\u9000\u51FA\u3002");
87
+ assert.equal(
88
+ translateBdsLog("IPv4 supported, port: 19132: Used for gameplay and LAN discovery", "zh-CN").text,
89
+ "[\u7F51\u7EDC] IPv4 \u6E38\u620F\u4E0E\u5C40\u57DF\u7F51\u53D1\u73B0\u7AEF\u53E3: 19132 (UDP)"
90
+ );
91
+ assert.equal(
92
+ translateBdsLog("Allow list is enabled but contains no entries.", "zh-CN").text,
93
+ "[\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"
94
+ );
95
+ });
96
+ test("translateBdsLog: \u73A9\u5BB6\u52A0\u5165\u4E0E\u79BB\u5F00", () => {
97
+ const join = translateBdsLog("Player connected: Steve, xuid: 2535412345678901", "zh-CN");
98
+ assert.equal(join.text, "[\u73A9\u5BB6\u8FDE\u63A5] \u73A9\u5BB6 Steve \u5DF2\u52A0\u5165\u4E16\u754C (XUID: 2535412345678901)");
99
+ const leave = translateBdsLog("Player disconnected: Steve, xuid: 2535412345678901", "zh-CN");
100
+ assert.equal(leave.text, "[\u73A9\u5BB6\u65AD\u5F00] \u73A9\u5BB6 Steve \u5DF2\u79BB\u5F00\u4E16\u754C (XUID: 2535412345678901)");
101
+ });
102
+ test("translateBdsLog: \u672A\u5339\u914D\u884C\u539F\u6837\u8FD4\u56DE", () => {
103
+ const plain = "A custom line that has no translation rule.";
104
+ const res = translateBdsLog(plain, "zh-CN");
105
+ assert.equal(res.translated, false);
106
+ assert.equal(res.text, plain);
107
+ });
108
+ test("interpolateRegexTemplate & applyRuleReplacement", () => {
109
+ const m = "Hello world 123".match(/Hello (\w+) (\d+)/);
110
+ assert.ok(m);
111
+ const out = interpolateRegexTemplate(m, "Greeting $1 with id $2");
112
+ assert.equal(out, "Greeting world with id 123");
113
+ const replaced = applyRuleReplacement(
114
+ "Warning: player Steve did action 5",
115
+ /Warning: player (\w+) did action (\d+)/,
116
+ "\u8B66\u544A: \u73A9\u5BB6 $1 \u89E6\u53D1\u4E86\u884C\u4E3A $2"
117
+ );
118
+ assert.equal(replaced, "\u8B66\u544A: \u73A9\u5BB6 Steve \u89E6\u53D1\u4E86\u884C\u4E3A 5");
119
+ });
120
+ //# sourceMappingURL=log-translator.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/log-translator.test.ts"],
4
+ "sourcesContent": ["/**\n * log-translator.test.ts \u2014 BDS \u539F\u7248\u65E5\u5FD7\u672C\u5730\u5316\u7FFB\u8BD1\u5355\u6D4B\n */\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport {\n applyRuleReplacement,\n interpolateRegexTemplate,\n translateBdsLog,\n} from \"./log-translator.js\";\n\ntest(\"translateBdsLog: Beta APIs \u7F3A\u5931\u963B\u65AD\", () => {\n const line =\n \"Plugin [sfmc-modules - 1.0.0] - requesting dependency on beta APIs [@minecraft/server-admin - 1.0.0-beta], but the Beta APIs experiment is not enabled.\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"beta-apis-missing\");\n assert.ok(res.text.includes(\"\u63D2\u4EF6\u300Csfmc-modules - 1.0.0\u300D\u4F9D\u8D56\u6D4B\u8BD5\u7248 API (@minecraft/server-admin - 1.0.0-beta)\"));\n assert.ok(res.text.includes(\"\u672A\u5F00\u542F\u300C\u6D4B\u8BD5\u7248 API (Beta APIs)\u300D\u5B9E\u9A8C\u5F00\u5173\"));\n});\n\ntest(\"translateBdsLog: \u811A\u672C\u8BED\u6CD5\u9519\u8BEF missing export\", () => {\n const line = \"SyntaxError: Could not find export 'Vector3' in module '@minecraft/server'\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"script-syntax-missing-export\");\n assert.ok(res.text.includes(\"\u6A21\u7EC4\u5C1D\u8BD5\u4ECE\u300C@minecraft/server\u300D\u5BFC\u5165\u4E0D\u5B58\u5728\u7684\u7B26\u53F7\u300CVector3\u300D\"));\n});\n\ntest(\"translateBdsLog: \u6FC0\u6D3B\u5305\u5728\u672C\u5730\u7F3A\u5931\", () => {\n const line = \"Configured pack (id: 3116e462-9838-48bf-be53-354958c1810f, version: 1.21.100) was not found and was ignored\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"configured-pack-missing\");\n assert.ok(res.text.includes(\"UUID: 3116e462-9838-48bf-be53-354958c1810f\"));\n assert.ok(res.text.includes(\"\u7248\u672C: 1.21.100\"));\n});\n\ntest(\"translateBdsLog: \u81EA\u5B9A\u4E49\u65B9\u5757\u5F62\u6001\u6570\u91CF\u8D85\u9650\", () => {\n const line = \"World with over 65536 block permutations may degrade performance. Current world has 74227 permutations.\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"block-permutations-limit\");\n assert.ok(res.text.includes(\"74227 \u4E2A\"));\n assert.ok(res.text.includes(\"\u8D85\u51FA\u63A8\u8350\u4E0A\u9650 65,536\"));\n});\n\ntest(\"translateBdsLog: \u914D\u65B9\u7269\u54C1\u7F3A\u5931\", () => {\n const line =\n \"[Recipes] recipes/japanese/mochi_rice.json | amp:mochi_rice | The Item: amp:mochi_rice is missing or invalid, can't make the recipe\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"recipe-item-missing\");\n assert.ok(res.text.includes(\"\u914D\u65B9\u6587\u4EF6\u300Crecipes/japanese/mochi_rice.json\u300D\"));\n assert.ok(res.text.includes(\"\u7269\u54C1\u300Camp:mochi_rice\u300D\u4E0D\u5B58\u5728\u6216\u65E0\u6548\"));\n});\n\ntest(\"translateBdsLog: \u914D\u65B9\u539F\u6599\u7F3A\u5931\", () => {\n const line =\n \"[Recipes] recipes/japanese/rice_eel.json | amp:rice_eel | Recipe for: amp:rice_eel is missing (unknown) ingredient\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"recipe-ingredient-missing\");\n assert.ok(res.text.includes(\"\u4EA7\u7269: amp:rice_eel\"));\n assert.ok(res.text.includes(\"\u7F3A\u5C11\u6709\u6548\u539F\u6599\"));\n});\n\ntest(\"translateBdsLog: \u914D\u65B9\u4EA7\u7269\u683C\u5F0F\u9519\u8BEF\", () => {\n const line = \"[Recipes] recipes/furniture/money.json | amp:money | Recipe result malformed\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"recipe-result-malformed\");\n assert.ok(res.text.includes(\"\u4EA7\u7269\u7ED3\u679C\u5B9A\u4E49\u683C\u5F0F\u9519\u8BEF\"));\n});\n\ntest(\"translateBdsLog: \u65B9\u5757 Schema \u672A\u77E5\u7EC4\u4EF6\u4E0E\u5B50\u5C5E\u6027\u9519\u8BEF\", () => {\n const line1 =\n \"[Blocks] block_definitions | worlds/Bedrock level/behavior_packs/[BP] TouHouLittleMaid_BP | blocks/skull/fairy_skull_2.json | -> components -> tlm:skull: this component was found in the input, but is not present in the Schema\";\n const res1 = translateBdsLog(line1, \"zh-CN\");\n assert.equal(res1.translated, true);\n assert.equal(res1.ruleId, \"block-component-schema-unknown\");\n assert.ok(res1.text.includes(\"blocks/skull/fairy_skull_2.json\"));\n assert.ok(res1.text.includes(\"\u672A\u77E5\u7EC4\u4EF6: components -> tlm:skull\"));\n\n const line2 =\n \"[Blocks] block_definitions | worlds/Bedrock level/behavior_packs/[BP] [BM] [\u81EA\u7814] [\u73A9\u6CD5] GlobalCuisine_BP | blocks/steamer/steamer.json | worlds/Bedrock level/behavior_packs/[BP] [BM] [\u81EA\u7814] [\u73A9\u6CD5] GlobalCuisine_BP | blocks/steamer/steamer.json | amp:steamer | components | amp:steamer | child 'amp:steamer' not valid here.\";\n const res2 = translateBdsLog(line2, \"zh-CN\");\n assert.equal(res2.translated, true);\n assert.equal(res2.ruleId, \"block-child-component-invalid\");\n assert.ok(res2.text.includes(\"blocks/steamer/steamer.json\"));\n assert.ok(res2.text.includes(\"\u5B50\u5C5E\u6027\u300Camp:steamer\u300D\u5728\u6B64\u5904\u65E0\u6548\"));\n});\n\ntest(\"translateBdsLog: \u811A\u672C\u7EC4\u4EF6\u672A\u6CE8\u518C\", () => {\n const line = \"[Scripting] Component 'tlm:deprecated' was not registered in script but used on an item\";\n const res = translateBdsLog(line, \"zh-CN\");\n assert.equal(res.translated, true);\n assert.equal(res.ruleId, \"script-component-not-registered\");\n assert.ok(res.text.includes(\"\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u300Ctlm:deprecated\u300D\"));\n});\n\ntest(\"translateBdsLog: \u670D\u52A1\u7AEF\u751F\u547D\u5468\u671F\u4E0E\u7AEF\u53E3\", () => {\n assert.equal(translateBdsLog(\"Server started.\", \"zh-CN\").text, \"[\u670D\u52A1\u7AEF] BDS \u670D\u52A1\u7AEF\u5DF2\u6210\u529F\u542F\u52A8\uFF0C\u51C6\u5907\u5C31\u7EEA\u3002\");\n assert.equal(translateBdsLog(\"Stopping server...\", \"zh-CN\").text, \"[\u670D\u52A1\u7AEF] \u6B63\u5728\u5173\u95ED\u670D\u52A1\u7AEF...\");\n assert.equal(translateBdsLog(\"Quit correctly\", \"zh-CN\").text, \"[\u670D\u52A1\u7AEF] \u670D\u52A1\u7AEF\u5DF2\u6B63\u5E38\u5B89\u5168\u9000\u51FA\u3002\");\n assert.equal(\n translateBdsLog(\"IPv4 supported, port: 19132: Used for gameplay and LAN discovery\", \"zh-CN\").text,\n \"[\u7F51\u7EDC] IPv4 \u6E38\u620F\u4E0E\u5C40\u57DF\u7F51\u53D1\u73B0\u7AEF\u53E3: 19132 (UDP)\"\n );\n assert.equal(\n translateBdsLog(\"Allow list is enabled but contains no entries.\", \"zh-CN\").text,\n \"[\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\ntest(\"translateBdsLog: \u73A9\u5BB6\u52A0\u5165\u4E0E\u79BB\u5F00\", () => {\n const join = translateBdsLog(\"Player connected: Steve, xuid: 2535412345678901\", \"zh-CN\");\n assert.equal(join.text, \"[\u73A9\u5BB6\u8FDE\u63A5] \u73A9\u5BB6 Steve \u5DF2\u52A0\u5165\u4E16\u754C (XUID: 2535412345678901)\");\n\n const leave = translateBdsLog(\"Player disconnected: Steve, xuid: 2535412345678901\", \"zh-CN\");\n assert.equal(leave.text, \"[\u73A9\u5BB6\u65AD\u5F00] \u73A9\u5BB6 Steve \u5DF2\u79BB\u5F00\u4E16\u754C (XUID: 2535412345678901)\");\n});\n\ntest(\"translateBdsLog: \u672A\u5339\u914D\u884C\u539F\u6837\u8FD4\u56DE\", () => {\n const plain = \"A custom line that has no translation rule.\";\n const res = translateBdsLog(plain, \"zh-CN\");\n assert.equal(res.translated, false);\n assert.equal(res.text, plain);\n});\n\ntest(\"interpolateRegexTemplate & applyRuleReplacement\", () => {\n const m = \"Hello world 123\".match(/Hello (\\w+) (\\d+)/);\n assert.ok(m);\n const out = interpolateRegexTemplate(m, \"Greeting $1 with id $2\");\n assert.equal(out, \"Greeting world with id 123\");\n\n const replaced = applyRuleReplacement(\n \"Warning: player Steve did action 5\",\n /Warning: player (\\w+) did action (\\d+)/,\n \"\u8B66\u544A: \u73A9\u5BB6 $1 \u89E6\u53D1\u4E86\u884C\u4E3A $2\"\n );\n assert.equal(replaced, \"\u8B66\u544A: \u73A9\u5BB6 Steve \u89E6\u53D1\u4E86\u884C\u4E3A 5\");\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -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;AA+BhG,yBAAyB;AACzB,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CA6C9E;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";
@@ -46,7 +47,7 @@ function pushLog(text, source, level) {
46
47
  if (embedded) lvl = embedded;
47
48
  body = stripBdsLogPrefix(text);
48
49
  }
49
- const entry = { time: /* @__PURE__ */ new Date(), text: body, source, level: lvl };
50
+ const rawEntry = { time: /* @__PURE__ */ new Date(), text: body, source, level: lvl };
50
51
  const filter = getCompiledLogFilter((src) => {
51
52
  try {
52
53
  const sink2 = sinkFor("system");
@@ -61,16 +62,18 @@ function pushLog(text, source, level) {
61
62
  } catch {
62
63
  }
63
64
  });
64
- const dropDisplay = shouldDropForDisplay(entry, filter);
65
- const dropDisk = shouldDropForDisk(entry, filter);
65
+ const dropDisplay = shouldDropForDisplay(rawEntry, filter);
66
+ const dropDisk = shouldDropForDisk(rawEntry, filter);
67
+ const { entry: transformedEntry } = transformLogEntry(rawEntry, filter);
66
68
  if (!dropDisplay) {
67
- buffer.pushDirect(body, source, lvl);
69
+ buffer.pushDirect(transformedEntry.text, source, lvl);
68
70
  }
69
71
  if (dropDisk) return;
70
72
  const sink = sinkFor(source);
71
73
  if (!sink) return;
72
74
  try {
73
- sink.write(entry, formatLogLine(entry, false));
75
+ const diskEntry = filter.applyTo === "all" ? { ...rawEntry, text: transformedEntry.text } : rawEntry;
76
+ sink.write(diskEntry, formatLogLine(diskEntry, false));
74
77
  } catch {
75
78
  }
76
79
  }
@@ -210,7 +213,10 @@ function formatLog(l) {
210
213
  const level = resolveDisplayLevel(l);
211
214
  const lvl = levelTag(level);
212
215
  const src = formatSourceTag(l.source);
213
- const txt = highlightLogLine(l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text);
216
+ const body = l.source === "bds" ? stripBdsLogPrefix(l.text) : l.text;
217
+ const filter = getCompiledLogFilter();
218
+ const { entry } = transformLogEntry({ text: body, source: l.source, level }, filter);
219
+ const txt = highlightLogLine(entry.text);
214
220
  return `${ts} ${src} ${lvl} ${txt}`;
215
221
  }
216
222
  function charWidth(ch) {
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/** \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 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\", \"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\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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-commands.d.ts","sourceRoot":"","sources":["../src/module-commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAmBvE,uCAAuC;AACvC,eAAO,MAAM,gBAAgB,YAAI,QAAQ,EAAE,KAAK,CAAU,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,IAAI,aAAa,CAE7E;AAED,wBAAwB;AACxB,eAAO,MAAM,6BAA6B,YAAI,OAAO,EAAE,QAAQ,CAAU,CAAC;AAE1E,yCAAyC;AACzC,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,MAAM,EAAE,CAEhF;AAED,6BAA6B;AAC7B,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtE;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,IAAI,GAAE,WAAoB,GAAG,MAAM,CAK9D;AAmFD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkCpE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAO1D;AAKD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DrE;AAKD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BnE;AAKD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAerE;AAqHD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAIxE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAIzE;AAqCD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDtE;AAKD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BxE;AAuBD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoCpG;AAED,uDAAuD;AACvD,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAWrD"}
1
+ {"version":3,"file":"module-commands.d.ts","sourceRoot":"","sources":["../src/module-commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAmBvE,uCAAuC;AACvC,eAAO,MAAM,gBAAgB,YAAI,QAAQ,EAAE,KAAK,CAAU,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,IAAI,aAAa,CAE7E;AAED,wBAAwB;AACxB,eAAO,MAAM,6BAA6B,YAAI,OAAO,EAAE,QAAQ,CAAU,CAAC;AAE1E,yCAAyC;AACzC,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,MAAM,EAAE,CAEhF;AAED,6BAA6B;AAC7B,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtE;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,IAAI,GAAE,WAAoB,GAAG,MAAM,CAK9D;AAwFD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkCpE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAO1D;AAKD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DrE;AAKD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BnE;AAKD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAerE;AAwHD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAIxE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAIzE;AAqCD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDtE;AAKD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BxE;AAuBD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoCpG;AAED,uDAAuD;AACvD,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAiBrD"}
@@ -1,5 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
- import { existsSync, lstatSync, readdirSync } from "node:fs";
2
+ import { existsSync, lstatSync, readdirSync, statSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { spawn } from "node:child_process";
5
5
  import {
@@ -62,9 +62,13 @@ async function scanInstalled() {
62
62
  const entries = await fs.readdir(dir, { withFileTypes: true });
63
63
  const out = [];
64
64
  for (const e of entries) {
65
- if (!e.isDirectory()) continue;
66
65
  const id = e.name;
67
66
  const modPath = path.join(dir, id);
67
+ try {
68
+ if (!statSync(modPath).isDirectory()) continue;
69
+ } catch {
70
+ continue;
71
+ }
68
72
  const manifestPath = path.join(modPath, "sapi", "manifest.json");
69
73
  let manifest = null;
70
74
  if (existsSync(manifestPath)) {
@@ -85,6 +89,7 @@ async function dirSize(dir) {
85
89
  let fileCount = 0;
86
90
  async function walk(p) {
87
91
  for (const e of await fs.readdir(p, { withFileTypes: true })) {
92
+ if (e.name.startsWith(".") || e.name === "node_modules" || e.name === "dist") continue;
88
93
  const child = path.join(p, e.name);
89
94
  if (e.isDirectory()) await walk(child);
90
95
  else if (e.isFile()) {
@@ -110,7 +115,7 @@ async function cmdModuleList(_args) {
110
115
  const unknown = new Set(await findUnknownModules(ids));
111
116
  const lines = [c.bold(`
112
117
  ${t("mod.list.title")}`), c.dim(` ${modulesDir()}`)];
113
- const header = ` ${"id".padEnd(24)}${"state".padEnd(8)}${"files".padEnd(8)}${"size".padEnd(10)}${"fingerprint"}`;
118
+ const header = ` ${"id".padEnd(28)}${"state".padEnd(8)}${"files".padEnd(8)}${"size".padEnd(10)}${"fingerprint"}`;
114
119
  lines.push(c.dim(header));
115
120
  for (const m of installed) {
116
121
  const logicalId = typeof m.manifest?.id === "string" && m.manifest.id ? m.manifest.id : m.id;
@@ -126,7 +131,7 @@ ${t("mod.list.title")}`), c.dim(` ${modulesDir()}`)];
126
131
  }
127
132
  const idLabel = logicalId !== m.id ? `${m.id}(${logicalId})` : m.id;
128
133
  lines.push(
129
- ` ${mark} ${idLabel.padEnd(22)}${stateCol}${String(m.fileCount).padEnd(8)}${fmtBytes(m.totalBytes).padEnd(10)}${shortHash(m.fingerprint)}`
134
+ ` ${mark} ${idLabel.padEnd(26)} ${stateCol}${String(m.fileCount).padEnd(8)}${fmtBytes(m.totalBytes).padEnd(10)}${shortHash(m.fingerprint)}`
130
135
  );
131
136
  }
132
137
  lines.push(c.dim(`
@@ -260,7 +265,10 @@ function catalogPathOnDisk() {
260
265
  return modulePath(path.join(ROOT, "modules"), "catalog.json");
261
266
  }
262
267
  function buildToggleCandidates(installed) {
263
- const catalog = readJson(catalogPathOnDisk()) ?? {};
268
+ const catalog = readJson(catalogPathOnDisk()) ?? {
269
+ version: 1,
270
+ modules: []
271
+ };
264
272
  const rows = Array.isArray(catalog.modules) ? catalog.modules : [];
265
273
  const byLogical = /* @__PURE__ */ new Map();
266
274
  for (const raw of rows) {
@@ -271,7 +279,7 @@ function buildToggleCandidates(installed) {
271
279
  return installed.map((m) => {
272
280
  const logicalId = typeof m.manifest?.id === "string" && m.manifest.id ? m.manifest.id : m.id;
273
281
  const raw = byLogical.get(logicalId);
274
- const configKeyRaw = raw ? String(raw.configKey || raw.config_key || "").trim() : "";
282
+ const configKeyRaw = raw ? String(raw.configKey || "").trim() : "";
275
283
  const canDisable = raw ? raw.canDisable !== false : true;
276
284
  const out = { logicalId, folderId: m.id, canDisable };
277
285
  if (configKeyRaw) out.configKey = configKeyRaw;
@@ -497,7 +505,13 @@ function listInstalledModuleIdsSync() {
497
505
  const dir = modulesDir();
498
506
  if (!existsSync(dir)) return [];
499
507
  try {
500
- return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort((a, b) => a.localeCompare(b));
508
+ return readdirSync(dir, { withFileTypes: true }).filter((e) => {
509
+ try {
510
+ return statSync(path.join(dir, e.name)).isDirectory();
511
+ } catch {
512
+ return false;
513
+ }
514
+ }).map((e) => e.name).sort((a, b) => a.localeCompare(b));
501
515
  } catch {
502
516
  return [];
503
517
  }