@sfmc-bds/cli 0.2.0-beta.19 → 0.2.0-beta.21

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 (75) hide show
  1. package/dist/bds-runtime-version.d.ts +3 -0
  2. package/dist/bds-runtime-version.d.ts.map +1 -0
  3. package/dist/bds-runtime-version.js +15 -0
  4. package/dist/bds-runtime-version.js.map +7 -0
  5. package/dist/command-surface.d.ts.map +1 -1
  6. package/dist/command-surface.js +2 -0
  7. package/dist/command-surface.js.map +2 -2
  8. package/dist/commands.d.ts.map +1 -1
  9. package/dist/commands.js +78 -75
  10. package/dist/commands.js.map +2 -2
  11. package/dist/i18n/locales/en.d.ts +8 -0
  12. package/dist/i18n/locales/en.d.ts.map +1 -1
  13. package/dist/i18n/locales/en.js +8 -0
  14. package/dist/i18n/locales/en.js.map +2 -2
  15. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  16. package/dist/i18n/locales/zh-CN.js +8 -0
  17. package/dist/i18n/locales/zh-CN.js.map +2 -2
  18. package/dist/llbot-launch.d.ts +3 -3
  19. package/dist/llbot-launch.js.map +1 -1
  20. package/dist/logs.js +3 -3
  21. package/dist/logs.js.map +2 -2
  22. package/dist/main.js +5 -0
  23. package/dist/main.js.map +2 -2
  24. package/dist/repl-windows/service-window.d.ts.map +1 -1
  25. package/dist/repl-windows/service-window.js +1 -0
  26. package/dist/repl-windows/service-window.js.map +2 -2
  27. package/dist/repl.d.ts.map +1 -1
  28. package/dist/repl.js +23 -12
  29. package/dist/repl.js.map +2 -2
  30. package/dist/send-target.d.ts.map +1 -1
  31. package/dist/send-target.js +2 -0
  32. package/dist/send-target.js.map +2 -2
  33. package/dist/services.d.ts +8 -1
  34. package/dist/services.d.ts.map +1 -1
  35. package/dist/services.js +151 -15
  36. package/dist/services.js.map +2 -2
  37. package/dist/ui-command.d.ts +6 -0
  38. package/dist/ui-command.d.ts.map +1 -0
  39. package/dist/ui-command.js +68 -0
  40. package/dist/ui-command.js.map +7 -0
  41. package/dist/wizard.d.ts.map +1 -1
  42. package/dist/wizard.js +15 -8
  43. package/dist/wizard.js.map +2 -2
  44. package/package.json +4 -5
  45. package/scripts/module-install/lib/catalog.mjs +1 -1
  46. package/dist/command-surface.test.js +0 -92
  47. package/dist/command-surface.test.js.map +0 -7
  48. package/dist/debug-command.test.js +0 -76
  49. package/dist/debug-command.test.js.map +0 -7
  50. package/dist/log-filter.test.js +0 -181
  51. package/dist/log-filter.test.js.map +0 -7
  52. package/dist/log-translator.test.js +0 -120
  53. package/dist/log-translator.test.js.map +0 -7
  54. package/dist/logs-blank-line.test.js +0 -16
  55. package/dist/logs-blank-line.test.js.map +0 -7
  56. package/dist/module-toggle.test.js +0 -37
  57. package/dist/module-toggle.test.js.map +0 -7
  58. package/dist/pack-bundle.test.js +0 -111
  59. package/dist/pack-bundle.test.js.map +0 -7
  60. package/dist/player-session.test.js +0 -19
  61. package/dist/player-session.test.js.map +0 -7
  62. package/dist/repl-windows/host.test.js +0 -72
  63. package/dist/repl-windows/host.test.js.map +0 -7
  64. package/dist/services-output.test.js +0 -9
  65. package/dist/services-output.test.js.map +0 -7
  66. package/dist/world-packs-list.test.js +0 -11
  67. package/dist/world-packs-list.test.js.map +0 -7
  68. package/dist/world-packs-uninstall.test.js +0 -54
  69. package/dist/world-packs-uninstall.test.js.map +0 -7
  70. package/scripts/module-install/test/check-modules-config.test.ts +0 -46
  71. package/scripts/module-install/test/config-seeding.test.ts +0 -99
  72. package/scripts/module-install/test/install-resolver.test.ts +0 -47
  73. package/scripts/module-install/test/link-local.test.ts +0 -50
  74. package/scripts/module-install/test/local-resolver.test.ts +0 -44
  75. package/scripts/module-install/test/registry-index.test.ts +0 -27
@@ -1,120 +0,0 @@
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
@@ -1,7 +0,0 @@
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,16 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { normalizeBdsLogBody } from "./logs.js";
4
- describe("BDS \u7A7A\u65E5\u5FD7\u6B63\u6587", () => {
5
- it("\u8FC7\u6EE4\u7EAF\u7A7A\u767D\u4EE5\u53CA\u4EC5\u542B BDS \u524D\u7F00\u7684\u884C", () => {
6
- assert.equal(normalizeBdsLogBody("\r"), null);
7
- assert.equal(normalizeBdsLogBody("[2026-09-09 18:07:44:123 INFO] \r"), null);
8
- });
9
- it("\u5265\u79BB\u524D\u7F00\u540E\u4FDD\u7559\u771F\u5B9E\u6B63\u6587", () => {
10
- assert.equal(
11
- normalizeBdsLogBody("[2026-09-09 18:07:44:123 WARN] [Scripting] farmersdelight:cutting_board_recipe"),
12
- "[Scripting] farmersdelight:cutting_board_recipe"
13
- );
14
- });
15
- });
16
- //# sourceMappingURL=logs-blank-line.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/logs-blank-line.test.ts"],
4
- "sourcesContent": ["/**\n * BDS \u6392\u7248\u7A7A\u884C\u5951\u7EA6\uFF1A\u5265\u79BB\u5176\u81EA\u5E26\u65F6\u95F4\u6233\u548C\u7B49\u7EA7\u540E\u4E3A\u7A7A\u7684\u884C\u4E0D\u5F97\u8FDB\u5165\u7EDF\u4E00\u65E5\u5FD7\u3002\n */\nimport assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\nimport { normalizeBdsLogBody } from \"./logs.js\";\n\ndescribe(\"BDS \u7A7A\u65E5\u5FD7\u6B63\u6587\", () => {\n it(\"\u8FC7\u6EE4\u7EAF\u7A7A\u767D\u4EE5\u53CA\u4EC5\u542B BDS \u524D\u7F00\u7684\u884C\", () => {\n assert.equal(normalizeBdsLogBody(\"\\r\"), null);\n assert.equal(normalizeBdsLogBody(\"[2026-09-09 18:07:44:123 INFO] \\r\"), null);\n });\n\n it(\"\u5265\u79BB\u524D\u7F00\u540E\u4FDD\u7559\u771F\u5B9E\u6B63\u6587\", () => {\n assert.equal(\n normalizeBdsLogBody(\"[2026-09-09 18:07:44:123 WARN] [Scripting] farmersdelight:cutting_board_recipe\"),\n \"[Scripting] farmersdelight:cutting_board_recipe\"\n );\n });\n});\n"],
5
- "mappings": "AAGA,OAAO,YAAY;AACnB,SAAS,UAAU,UAAU;AAC7B,SAAS,2BAA2B;AAEpC,SAAS,sCAAa,MAAM;AAC1B,KAAG,uFAAsB,MAAM;AAC7B,WAAO,MAAM,oBAAoB,IAAI,GAAG,IAAI;AAC5C,WAAO,MAAM,oBAAoB,qCAAqC,GAAG,IAAI;AAAA,EAC/E,CAAC;AAED,KAAG,sEAAe,MAAM;AACtB,WAAO;AAAA,MACL,oBAAoB,gFAAgF;AAAA,MACpG;AAAA,IACF;AAAA,EACF,CAAC;AACH,CAAC;",
6
- "names": []
7
- }
@@ -1,37 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { applyLockEnabled, finalizeToggle, resolveToggleTarget } from "./module-toggle.js";
4
- const candidates = [
5
- { logicalId: "feature-afk", folderId: "afk", configKey: "afk", canDisable: true },
6
- { logicalId: "core-gui", folderId: "gui", configKey: "gui", canDisable: false }
7
- ];
8
- test("resolveToggleTarget\uFF1AfolderId / logicalId / configKey", () => {
9
- assert.equal(resolveToggleTarget("afk", candidates)?.logicalId, "feature-afk");
10
- assert.equal(resolveToggleTarget("feature-afk", candidates)?.logicalId, "feature-afk");
11
- assert.equal(resolveToggleTarget("afk", candidates)?.folderId, "afk");
12
- assert.equal(resolveToggleTarget("missing", candidates), null);
13
- });
14
- test("resolveToggleTarget\uFF1AcanDisable \u6765\u81EA\u5019\u9009", () => {
15
- assert.equal(resolveToggleTarget("gui", candidates)?.canDisable, false);
16
- assert.equal(resolveToggleTarget("core-gui", candidates)?.canDisable, false);
17
- });
18
- test("applyLockEnabled\uFF1A\u5199\u5165 enabled + updatedAt", () => {
19
- const lock = { version: 1, modules: {} };
20
- const next = applyLockEnabled(lock, "feature-afk", true);
21
- assert.equal(next.modules["feature-afk"]?.enabled, true);
22
- assert.equal(typeof next.modules["feature-afk"]?.updatedAt, "number");
23
- assert.equal(lock.modules["feature-afk"]?.enabled, true);
24
- });
25
- test("finalizeToggle\uFF1A\u672C\u5730\u5DF2\u5199 + \u901A\u77E5\u5931\u8D25 \u2192 ok \u4E14 warn", () => {
26
- assert.deepEqual(finalizeToggle(true, { ok: true }), { ok: true, warnNotify: false });
27
- assert.deepEqual(finalizeToggle(true, { ok: false, reason: "unreachable" }), {
28
- ok: true,
29
- warnNotify: true
30
- });
31
- assert.deepEqual(finalizeToggle(true, { ok: false, reason: "http", detail: "x" }), {
32
- ok: true,
33
- warnNotify: true
34
- });
35
- assert.deepEqual(finalizeToggle(false, { ok: true }), { ok: false, warnNotify: false });
36
- });
37
- //# sourceMappingURL=module-toggle.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/module-toggle.test.ts"],
4
- "sourcesContent": ["/**\n * module-toggle \u672C\u5730\u5199 lock + \u901A\u77E5\u7ED3\u679C\u4FE1\u5C01\uFF08\u7EAF\u51FD\u6570\uFF09\n */\nimport assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { applyLockEnabled, finalizeToggle, resolveToggleTarget } from \"./module-toggle.js\";\n\nconst candidates = [\n { logicalId: \"feature-afk\", folderId: \"afk\", configKey: \"afk\", canDisable: true },\n { logicalId: \"core-gui\", folderId: \"gui\", configKey: \"gui\", canDisable: false },\n];\n\ntest(\"resolveToggleTarget\uFF1AfolderId / logicalId / configKey\", () => {\n assert.equal(resolveToggleTarget(\"afk\", candidates)?.logicalId, \"feature-afk\");\n assert.equal(resolveToggleTarget(\"feature-afk\", candidates)?.logicalId, \"feature-afk\");\n assert.equal(resolveToggleTarget(\"afk\", candidates)?.folderId, \"afk\");\n assert.equal(resolveToggleTarget(\"missing\", candidates), null);\n});\n\ntest(\"resolveToggleTarget\uFF1AcanDisable \u6765\u81EA\u5019\u9009\", () => {\n assert.equal(resolveToggleTarget(\"gui\", candidates)?.canDisable, false);\n assert.equal(resolveToggleTarget(\"core-gui\", candidates)?.canDisable, false);\n});\n\ntest(\"applyLockEnabled\uFF1A\u5199\u5165 enabled + updatedAt\", () => {\n const lock = { version: 1, modules: {} as Record<string, { enabled: boolean; updatedAt?: number }> };\n const next = applyLockEnabled(lock, \"feature-afk\", true);\n assert.equal(next.modules[\"feature-afk\"]?.enabled, true);\n assert.equal(typeof next.modules[\"feature-afk\"]?.updatedAt, \"number\");\n assert.equal(lock.modules[\"feature-afk\"]?.enabled, true);\n});\n\ntest(\"finalizeToggle\uFF1A\u672C\u5730\u5DF2\u5199 + \u901A\u77E5\u5931\u8D25 \u2192 ok \u4E14 warn\", () => {\n assert.deepEqual(finalizeToggle(true, { ok: true }), { ok: true, warnNotify: false });\n assert.deepEqual(finalizeToggle(true, { ok: false, reason: \"unreachable\" }), {\n ok: true,\n warnNotify: true,\n });\n assert.deepEqual(finalizeToggle(true, { ok: false, reason: \"http\", detail: \"x\" }), {\n ok: true,\n warnNotify: true,\n });\n assert.deepEqual(finalizeToggle(false, { ok: true }), { ok: false, warnNotify: false });\n});\n"],
5
- "mappings": "AAGA,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,SAAS,kBAAkB,gBAAgB,2BAA2B;AAEtE,MAAM,aAAa;AAAA,EACjB,EAAE,WAAW,eAAe,UAAU,OAAO,WAAW,OAAO,YAAY,KAAK;AAAA,EAChF,EAAE,WAAW,YAAY,UAAU,OAAO,WAAW,OAAO,YAAY,MAAM;AAChF;AAEA,KAAK,6DAAwD,MAAM;AACjE,SAAO,MAAM,oBAAoB,OAAO,UAAU,GAAG,WAAW,aAAa;AAC7E,SAAO,MAAM,oBAAoB,eAAe,UAAU,GAAG,WAAW,aAAa;AACrF,SAAO,MAAM,oBAAoB,OAAO,UAAU,GAAG,UAAU,KAAK;AACpE,SAAO,MAAM,oBAAoB,WAAW,UAAU,GAAG,IAAI;AAC/D,CAAC;AAED,KAAK,gEAAuC,MAAM;AAChD,SAAO,MAAM,oBAAoB,OAAO,UAAU,GAAG,YAAY,KAAK;AACtE,SAAO,MAAM,oBAAoB,YAAY,UAAU,GAAG,YAAY,KAAK;AAC7E,CAAC;AAED,KAAK,0DAA2C,MAAM;AACpD,QAAM,OAAO,EAAE,SAAS,GAAG,SAAS,CAAC,EAA8D;AACnG,QAAM,OAAO,iBAAiB,MAAM,eAAe,IAAI;AACvD,SAAO,MAAM,KAAK,QAAQ,aAAa,GAAG,SAAS,IAAI;AACvD,SAAO,MAAM,OAAO,KAAK,QAAQ,aAAa,GAAG,WAAW,QAAQ;AACpE,SAAO,MAAM,KAAK,QAAQ,aAAa,GAAG,SAAS,IAAI;AACzD,CAAC;AAED,KAAK,iGAA0C,MAAM;AACnD,SAAO,UAAU,eAAe,MAAM,EAAE,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,MAAM,YAAY,MAAM,CAAC;AACpF,SAAO,UAAU,eAAe,MAAM,EAAE,IAAI,OAAO,QAAQ,cAAc,CAAC,GAAG;AAAA,IAC3E,IAAI;AAAA,IACJ,YAAY;AAAA,EACd,CAAC;AACD,SAAO,UAAU,eAAe,MAAM,EAAE,IAAI,OAAO,QAAQ,QAAQ,QAAQ,IAAI,CAAC,GAAG;AAAA,IACjF,IAAI;AAAA,IACJ,YAAY;AAAA,EACd,CAAC;AACD,SAAO,UAAU,eAAe,OAAO,EAAE,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,OAAO,YAAY,MAAM,CAAC;AACxF,CAAC;",
6
- "names": []
7
- }
@@ -1,111 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import fs from "node:fs";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import test from "node:test";
6
- import { build } from "esbuild";
7
- import { createSdkResolvePlugin } from "./pack-lifecycle.js";
8
- import { resolveSdkPackageRoot } from "./runtime.js";
9
- test("pack bundling: sfmc:host bundles installHostBootstrap without unbundled SDK imports", async () => {
10
- const sdkRoot = resolveSdkPackageRoot();
11
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-bundle-test-"));
12
- const dummyModFile = path.join(tmpDir, "dummy-mod.ts");
13
- fs.writeFileSync(
14
- dummyModFile,
15
- `
16
- import { ModuleRegistry } from "@sfmc-bds/sdk/module-loader";
17
- import { Command, Permission } from "@sfmc-bds/sdk/sapi/runtime";
18
- globalThis.__testEvalOrder = (globalThis.__testEvalOrder || []).concat("module");
19
- Command.register("dummy", Permission.Any, () => undefined, "dummy", "test-feature");
20
- ModuleRegistry.register({ id: "test-feature", lifecycle: {} });
21
- `
22
- );
23
- try {
24
- const res = await build({
25
- stdin: {
26
- contents: [
27
- 'import "sfmc:host";',
28
- `import ${JSON.stringify(dummyModFile.replace(/\\/g, "/"))};`
29
- ].join("\n"),
30
- resolveDir: tmpDir,
31
- sourcefile: "bootstrap.ts",
32
- loader: "ts"
33
- },
34
- write: false,
35
- bundle: true,
36
- platform: "neutral",
37
- format: "esm",
38
- target: "es2022",
39
- external: ["@minecraft/*"],
40
- plugins: [createSdkResolvePlugin(sdkRoot)]
41
- });
42
- const code = res.outputFiles[0].text;
43
- assert.doesNotMatch(
44
- code,
45
- /import\s+.*from\s+["']@sfmc(?:-bds)?\/sdk/i,
46
- "Bundle must not contain unbundled @sfmc-bds/sdk bare imports"
47
- );
48
- assert.match(code, /installHostBootstrap\(\)/, "Bundle must call installHostBootstrap()");
49
- const importLines = code.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("import ") && l.includes(" from "));
50
- for (const line of importLines) {
51
- assert.match(
52
- line,
53
- /from\s+["']@minecraft\//,
54
- `Unexpected external import line in bundle: ${line}`
55
- );
56
- }
57
- const hostCallIdx = code.indexOf("installHostBootstrap();");
58
- const modMarkerIdx = code.indexOf("__testEvalOrder");
59
- assert.ok(hostCallIdx !== -1, "installHostBootstrap call exists");
60
- assert.ok(modMarkerIdx !== -1, "module eval marker exists");
61
- assert.ok(
62
- hostCallIdx < modMarkerIdx,
63
- `installHostBootstrap() (idx: ${hostCallIdx}) must execute before module evaluation (idx: ${modMarkerIdx})`
64
- );
65
- const commandStateRefs = code.match(/__sfmcCommandState/g)?.length ?? 0;
66
- const permissionStateRefs = code.match(/__sfmcPermissionRegistry/g)?.length ?? 0;
67
- assert.ok(commandStateRefs >= 2, "Bundled SDK copies must share __sfmcCommandState");
68
- assert.ok(permissionStateRefs >= 2, "Bundled SDK copies must share __sfmcPermissionRegistry");
69
- } finally {
70
- fs.rmSync(tmpDir, { recursive: true, force: true });
71
- }
72
- });
73
- test("extractModuleBedrockDependencies: \u4ECE sapi/manifest.json \u4E0E package.json \u63D0\u53D6\u539F\u751F\u4F9D\u8D56", async () => {
74
- const { extractModuleBedrockDependencies } = await import("./pack-lifecycle.js");
75
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-extract-dep-test-"));
76
- try {
77
- fs.mkdirSync(path.join(tmpDir, "sapi"), { recursive: true });
78
- fs.writeFileSync(
79
- path.join(tmpDir, "sapi", "manifest.json"),
80
- JSON.stringify({
81
- schemaVersion: 2,
82
- id: "test-menu",
83
- name: "\u6D4B\u8BD5\u83DC\u5355",
84
- configKey: "test",
85
- requires: [],
86
- permissions: [],
87
- dependencies: [
88
- { module_name: "@minecraft/server-ui", version: "2.0.0-beta" }
89
- ]
90
- })
91
- );
92
- fs.writeFileSync(
93
- path.join(tmpDir, "package.json"),
94
- JSON.stringify({
95
- peerDependencies: {
96
- "@minecraft/server": ">=1.18.0"
97
- },
98
- devDependencies: {
99
- "@minecraft/server": "2.10.0-beta.1.26.40-preview.30"
100
- }
101
- })
102
- );
103
- const deps = await extractModuleBedrockDependencies(tmpDir);
104
- assert.equal(deps.length, 2);
105
- assert.ok(deps.some((d) => d.module_name === "@minecraft/server-ui" && d.version === "2.0.0-beta"));
106
- assert.ok(deps.some((d) => d.module_name === "@minecraft/server" && d.version === ">=1.18.0"));
107
- } finally {
108
- fs.rmSync(tmpDir, { recursive: true, force: true });
109
- }
110
- });
111
- //# sourceMappingURL=pack-bundle.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/pack-bundle.test.ts"],
4
- "sourcesContent": ["import assert from \"node:assert/strict\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport test from \"node:test\";\nimport { build } from \"esbuild\";\nimport { createSdkResolvePlugin } from \"./pack-lifecycle.js\";\nimport { resolveSdkPackageRoot } from \"./runtime.js\";\n\ntest(\"pack bundling: sfmc:host bundles installHostBootstrap without unbundled SDK imports\", async () => {\n const sdkRoot = resolveSdkPackageRoot();\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-bundle-test-\"));\n const dummyModFile = path.join(tmpDir, \"dummy-mod.ts\");\n\n fs.writeFileSync(\n dummyModFile,\n `\nimport { ModuleRegistry } from \"@sfmc-bds/sdk/module-loader\";\nimport { Command, Permission } from \"@sfmc-bds/sdk/sapi/runtime\";\nglobalThis.__testEvalOrder = (globalThis.__testEvalOrder || []).concat(\"module\");\nCommand.register(\"dummy\", Permission.Any, () => undefined, \"dummy\", \"test-feature\");\nModuleRegistry.register({ id: \"test-feature\", lifecycle: {} });\n`\n );\n\n try {\n const res = await build({\n stdin: {\n contents: [\n 'import \"sfmc:host\";',\n `import ${JSON.stringify(dummyModFile.replace(/\\\\/g, \"/\"))};`,\n ].join(\"\\n\"),\n resolveDir: tmpDir,\n sourcefile: \"bootstrap.ts\",\n loader: \"ts\",\n },\n write: false,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n external: [\"@minecraft/*\"],\n plugins: [createSdkResolvePlugin(sdkRoot)],\n });\n\n const code = res.outputFiles[0].text;\n\n // 1. \u786E\u4FDD\u672A\u6B8B\u7559\u672A\u6253\u5305\u7684 @sfmc-bds/sdk import\n assert.doesNotMatch(\n code,\n /import\\s+.*from\\s+[\"']@sfmc(?:-bds)?\\/sdk/i,\n \"Bundle must not contain unbundled @sfmc-bds/sdk bare imports\"\n );\n\n // 2. \u786E\u4FDD installHostBootstrap \u5305\u542B\u5728\u4EA7\u7269\u4E2D\u4E14\u5DF2\u88AB\u8C03\u7528\n assert.match(code, /installHostBootstrap\\(\\)/, \"Bundle must call installHostBootstrap()\");\n\n // 3. \u786E\u4FDD\u6240\u6709\u5916\u90E8 import \u5747\u5C40\u9650\u4E8E @minecraft/* \u539F\u751F\u6A21\u5757\n const importLines = code\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.startsWith(\"import \") && l.includes(\" from \"));\n for (const line of importLines) {\n assert.match(\n line,\n /from\\s+[\"']@minecraft\\//,\n `Unexpected external import line in bundle: ${line}`\n );\n }\n\n // 4. \u786E\u4FDD installHostBootstrap \u5728\u4E1A\u52A1\u6A21\u5757 evaluation \u4E4B\u524D\u6267\u884C\n const hostCallIdx = code.indexOf(\"installHostBootstrap();\");\n const modMarkerIdx = code.indexOf(\"__testEvalOrder\");\n assert.ok(hostCallIdx !== -1, \"installHostBootstrap call exists\");\n assert.ok(modMarkerIdx !== -1, \"module eval marker exists\");\n assert.ok(\n hostCallIdx < modMarkerIdx,\n `installHostBootstrap() (idx: ${hostCallIdx}) must execute before module evaluation (idx: ${modMarkerIdx})`\n );\n\n // 5. SDK \u5B50\u8DEF\u5F84\u4F1A\u5206\u522B\u9884\u6253\u5305\uFF0C\u4F46\u6240\u6709\u526F\u672C\u5FC5\u987B\u7ED1\u5B9A\u540C\u4E00\u4E2A\u5168\u5C40\u547D\u4EE4/\u6743\u9650\u72B6\u6001\u3002\n const commandStateRefs = code.match(/__sfmcCommandState/g)?.length ?? 0;\n const permissionStateRefs = code.match(/__sfmcPermissionRegistry/g)?.length ?? 0;\n assert.ok(commandStateRefs >= 2, \"Bundled SDK copies must share __sfmcCommandState\");\n assert.ok(permissionStateRefs >= 2, \"Bundled SDK copies must share __sfmcPermissionRegistry\");\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n});\n\ntest(\"extractModuleBedrockDependencies: \u4ECE sapi/manifest.json \u4E0E package.json \u63D0\u53D6\u539F\u751F\u4F9D\u8D56\", async () => {\n const { extractModuleBedrockDependencies } = await import(\"./pack-lifecycle.js\");\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-extract-dep-test-\"));\n try {\n fs.mkdirSync(path.join(tmpDir, \"sapi\"), { recursive: true });\n fs.writeFileSync(\n path.join(tmpDir, \"sapi\", \"manifest.json\"),\n JSON.stringify({\n schemaVersion: 2,\n id: \"test-menu\",\n name: \"\u6D4B\u8BD5\u83DC\u5355\",\n configKey: \"test\",\n requires: [],\n permissions: [],\n dependencies: [\n { module_name: \"@minecraft/server-ui\", version: \"2.0.0-beta\" },\n ],\n })\n );\n fs.writeFileSync(\n path.join(tmpDir, \"package.json\"),\n JSON.stringify({\n peerDependencies: {\n \"@minecraft/server\": \">=1.18.0\",\n },\n devDependencies: {\n \"@minecraft/server\": \"2.10.0-beta.1.26.40-preview.30\",\n },\n })\n );\n\n const deps = await extractModuleBedrockDependencies(tmpDir);\n assert.equal(deps.length, 2);\n assert.ok(deps.some((d) => d.module_name === \"@minecraft/server-ui\" && d.version === \"2.0.0-beta\"));\n assert.ok(deps.some((d) => d.module_name === \"@minecraft/server\" && d.version === \">=1.18.0\"));\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n});\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,19 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { parseBdsPlayerSession } from "./player-session.js";
4
- test("\u89E3\u6790 BDS \u73A9\u5BB6\u8FDE\u63A5\u65E5\u5FD7", () => {
5
- assert.deepEqual(parseBdsPlayerSession("[INFO] Player connected: Steve, xuid: 2535412345678901"), {
6
- connected: true,
7
- playerName: "Steve",
8
- xuid: "2535412345678901"
9
- });
10
- });
11
- test("\u89E3\u6790 BDS \u73A9\u5BB6\u65AD\u5F00\u65E5\u5FD7", () => {
12
- assert.deepEqual(parseBdsPlayerSession("Player disconnected: Alex, xuid: 42"), {
13
- connected: false,
14
- playerName: "Alex",
15
- xuid: "42"
16
- });
17
- assert.equal(parseBdsPlayerSession("Server started."), null);
18
- });
19
- //# sourceMappingURL=player-session.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/player-session.test.ts"],
4
- "sourcesContent": ["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { parseBdsPlayerSession } from \"./player-session.js\";\n\ntest(\"\u89E3\u6790 BDS \u73A9\u5BB6\u8FDE\u63A5\u65E5\u5FD7\", () => {\n assert.deepEqual(parseBdsPlayerSession(\"[INFO] Player connected: Steve, xuid: 2535412345678901\"), {\n connected: true,\n playerName: \"Steve\",\n xuid: \"2535412345678901\",\n });\n});\n\ntest(\"\u89E3\u6790 BDS \u73A9\u5BB6\u65AD\u5F00\u65E5\u5FD7\", () => {\n assert.deepEqual(parseBdsPlayerSession(\"Player disconnected: Alex, xuid: 42\"), {\n connected: false,\n playerName: \"Alex\",\n xuid: \"42\",\n });\n assert.equal(parseBdsPlayerSession(\"Server started.\"), null);\n});\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,SAAS,6BAA6B;AAEtC,KAAK,yDAAiB,MAAM;AAC1B,SAAO,UAAU,sBAAsB,wDAAwD,GAAG;AAAA,IAChG,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,MAAM;AAAA,EACR,CAAC;AACH,CAAC;AAED,KAAK,yDAAiB,MAAM;AAC1B,SAAO,UAAU,sBAAsB,qCAAqC,GAAG;AAAA,IAC7E,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,MAAM;AAAA,EACR,CAAC;AACD,SAAO,MAAM,sBAAsB,iBAAiB,GAAG,IAAI;AAC7D,CAAC;",
6
- "names": []
7
- }
@@ -1,72 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { WindowHost, serviceWindowId } from "./host.js";
4
- import { createServiceWindow } from "./service-window.js";
5
- import { createSfmcWindow, SFMC_WINDOW_ID } from "./sfmc-window.js";
6
- test("WindowHost: \u7BA1\u7406\u670D\u52A1\u7A97\u4E0E SFMC \u5E73\u53F0\u7A97\u751F\u547D\u5468\u671F", () => {
7
- const written = [];
8
- const host = new WindowHost({ writeLog: (l) => written.push(l) });
9
- let activeTargets = ["bds"];
10
- host.register(createServiceWindow("bds"));
11
- host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));
12
- host.setServiceOrder([serviceWindowId("bds"), SFMC_WINDOW_ID]);
13
- assert.equal(host.getActiveId(), serviceWindowId("bds"));
14
- assert.equal(host.getActive()?.title, "BDS");
15
- assert.equal(host.getActive()?.serviceName, "bds");
16
- const res1 = host.cycleServiceWindows();
17
- assert.equal(res1.switched, true);
18
- assert.equal(res1.serviceName, null);
19
- assert.equal(host.getActiveId(), SFMC_WINDOW_ID);
20
- assert.equal(host.getActive()?.title, "SFMC");
21
- assert.equal(host.getActive()?.serviceName, void 0);
22
- const res2 = host.cycleServiceWindows();
23
- assert.equal(res2.switched, true);
24
- assert.equal(res2.serviceName, "bds");
25
- assert.equal(host.getActiveId(), serviceWindowId("bds"));
26
- activeTargets = [];
27
- host.setServiceOrder([]);
28
- assert.equal(host.getActiveId(), null);
29
- assert.equal(host.has(serviceWindowId("bds")), false);
30
- assert.equal(host.has(SFMC_WINDOW_ID), false);
31
- });
32
- test("createSfmcWindow: acceptLog \u8FC7\u6EE4\u6D3B\u8DC3\u670D\u52A1\u65E5\u5FD7\u5E76\u63A5\u6536\u975E\u670D\u52A1/\u5E73\u53F0\u65E5\u5FD7", () => {
33
- const activeTargets = ["bds", "db"];
34
- const win = createSfmcWindow({ getActiveTargets: () => activeTargets });
35
- const now = /* @__PURE__ */ new Date();
36
- const bdsLog = { time: now, source: "bds", level: "info", text: "Server started" };
37
- const dbLog = { time: now, source: "db", level: "info", text: "Database ready" };
38
- const packLog = { time: now, source: "pack", level: "info", text: "assembled BP uuid=xxx" };
39
- const sysLog = { time: now, source: "system", level: "info", text: "Platform initialized" };
40
- const qqLog = { time: now, source: "qq", level: "info", text: "QQ stopped" };
41
- assert.equal(win.acceptLog(bdsLog), false);
42
- assert.equal(win.acceptLog(dbLog), false);
43
- assert.equal(win.acceptLog(packLog), true);
44
- assert.equal(win.acceptLog(sysLog), true);
45
- assert.equal(win.acceptLog(qqLog), true);
46
- const formatted = win.formatLogLine(packLog);
47
- assert.ok(formatted.text.includes("[PAK]"));
48
- });
49
- test("WindowHost: routeLog \u5C06\u65E5\u5FD7\u6B63\u786E\u5206\u6D41\u5230\u6D3B\u52A8\u7A97\u53E3\u4E0E\u540E\u53F0\u7A97\u53E3\u7F13\u5B58", () => {
50
- const written = [];
51
- const host = new WindowHost({ writeLog: (l) => written.push(l) });
52
- const activeTargets = ["bds"];
53
- host.register(createServiceWindow("bds"));
54
- host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));
55
- host.setServiceOrder([serviceWindowId("bds"), SFMC_WINDOW_ID]);
56
- host.setBuffer(serviceWindowId("bds"), []);
57
- host.setBuffer(SFMC_WINDOW_ID, []);
58
- assert.equal(host.getActiveId(), serviceWindowId("bds"));
59
- const now = /* @__PURE__ */ new Date();
60
- const bdsLog = { time: now, source: "bds", level: "info", text: "Hello BDS" };
61
- const packLog = { time: now, source: "pack", level: "info", text: "Building pack" };
62
- host.routeLog(bdsLog);
63
- assert.equal(written.length, 1);
64
- assert.ok(written[0]?.includes("Hello BDS"));
65
- host.routeLog(packLog);
66
- assert.equal(written.length, 1);
67
- const sfmcBuffer = host.getBuffer(SFMC_WINDOW_ID);
68
- assert.equal(sfmcBuffer.length, 1);
69
- assert.ok(sfmcBuffer[0]?.includes("Building pack"));
70
- assert.ok(sfmcBuffer[0]?.includes("[PAK]"));
71
- });
72
- //# sourceMappingURL=host.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/repl-windows/host.test.ts"],
4
- "sourcesContent": ["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport type { UnifiedLog } from \"../logs.js\";\nimport type { ServiceName } from \"../services.js\";\nimport { WindowHost, serviceWindowId } from \"./host.js\";\nimport { createServiceWindow } from \"./service-window.js\";\nimport { createSfmcWindow, SFMC_WINDOW_ID } from \"./sfmc-window.js\";\n\ntest(\"WindowHost: \u7BA1\u7406\u670D\u52A1\u7A97\u4E0E SFMC \u5E73\u53F0\u7A97\u751F\u547D\u5468\u671F\", () => {\n const written: string[] = [];\n const host = new WindowHost({ writeLog: (l) => written.push(l) });\n\n let activeTargets: ServiceName[] = [\"bds\"];\n host.register(createServiceWindow(\"bds\"));\n host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));\n\n host.setServiceOrder([serviceWindowId(\"bds\"), SFMC_WINDOW_ID]);\n\n // \u521D\u59CB\u6FC0\u6D3B\u7B2C 1 \u4E2A\u7A97\u53E3\uFF08bds\uFF09\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n assert.equal(host.getActive()?.title, \"BDS\");\n assert.equal(host.getActive()?.serviceName, \"bds\");\n\n // Tab \u8F6E\u6362\u81F3 SFMC \u7A97\n const res1 = host.cycleServiceWindows();\n assert.equal(res1.switched, true);\n assert.equal(res1.serviceName, null);\n assert.equal(host.getActiveId(), SFMC_WINDOW_ID);\n assert.equal(host.getActive()?.title, \"SFMC\");\n assert.equal(host.getActive()?.serviceName, undefined);\n\n // \u518D\u6B21 Tab \u8F6E\u6362\u56DE BDS \u7A97\n const res2 = host.cycleServiceWindows();\n assert.equal(res2.switched, true);\n assert.equal(res2.serviceName, \"bds\");\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n\n // \u670D\u52A1\u505C\u6B62\uFF1AsetServiceOrder \u6E05\u7A7A\u65F6\u5E94\u6CE8\u9500\u670D\u52A1\u7A97\u4E0E SFMC \u7A97\n activeTargets = [];\n host.setServiceOrder([]);\n assert.equal(host.getActiveId(), null);\n assert.equal(host.has(serviceWindowId(\"bds\")), false);\n assert.equal(host.has(SFMC_WINDOW_ID), false);\n});\n\ntest(\"createSfmcWindow: acceptLog \u8FC7\u6EE4\u6D3B\u8DC3\u670D\u52A1\u65E5\u5FD7\u5E76\u63A5\u6536\u975E\u670D\u52A1/\u5E73\u53F0\u65E5\u5FD7\", () => {\n const activeTargets: ServiceName[] = [\"bds\", \"db\"];\n const win = createSfmcWindow({ getActiveTargets: () => activeTargets });\n\n const now = new Date();\n const bdsLog: UnifiedLog = { time: now, source: \"bds\", level: \"info\", text: \"Server started\" };\n const dbLog: UnifiedLog = { time: now, source: \"db\", level: \"info\", text: \"Database ready\" };\n const packLog: UnifiedLog = { time: now, source: \"pack\", level: \"info\", text: \"assembled BP uuid=xxx\" };\n const sysLog: UnifiedLog = { time: now, source: \"system\", level: \"info\", text: \"Platform initialized\" };\n const qqLog: UnifiedLog = { time: now, source: \"qq\", level: \"info\", text: \"QQ stopped\" };\n\n // \u6D3B\u8DC3\u670D\u52A1\uFF08bds, db\uFF09\u7684\u65E5\u5FD7\u5728 SFMC \u7A97\u88AB\u8FC7\u6EE4\n assert.equal(win.acceptLog(bdsLog), false);\n assert.equal(win.acceptLog(dbLog), false);\n\n // \u975E\u6D3B\u8DC3\u670D\u52A1\u6216\u5E73\u53F0\u65E5\u5FD7\uFF08pack, system, qq\uFF09\u5728 SFMC \u7A97\u88AB\u63A5\u6536\n assert.equal(win.acceptLog(packLog), true);\n assert.equal(win.acceptLog(sysLog), true);\n assert.equal(win.acceptLog(qqLog), true);\n\n // \u683C\u5F0F\u5316\u8F93\u51FA\u5E94\u5305\u542B\u6765\u6E90\u6807\u7B7E\uFF08omitSource: false\uFF09\n const formatted = win.formatLogLine(packLog);\n assert.ok(formatted.text.includes(\"[PAK]\"));\n});\n\ntest(\"WindowHost: routeLog \u5C06\u65E5\u5FD7\u6B63\u786E\u5206\u6D41\u5230\u6D3B\u52A8\u7A97\u53E3\u4E0E\u540E\u53F0\u7A97\u53E3\u7F13\u5B58\", () => {\n const written: string[] = [];\n const host = new WindowHost({ writeLog: (l) => written.push(l) });\n\n const activeTargets: ServiceName[] = [\"bds\"];\n host.register(createServiceWindow(\"bds\"));\n host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));\n host.setServiceOrder([serviceWindowId(\"bds\"), SFMC_WINDOW_ID]);\n\n // \u7ED9\u4E24\u4E2A\u7A97\u53E3\u9884\u8BBE buffer\uFF08\u6A21\u62DF seed\uFF09\n host.setBuffer(serviceWindowId(\"bds\"), []);\n host.setBuffer(SFMC_WINDOW_ID, []);\n\n // \u5F53\u524D\u5728 BDS \u7A97\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n\n const now = new Date();\n const bdsLog: UnifiedLog = { time: now, source: \"bds\", level: \"info\", text: \"Hello BDS\" };\n const packLog: UnifiedLog = { time: now, source: \"pack\", level: \"info\", text: \"Building pack\" };\n\n // \u4EA7\u751F BDS \u65E5\u5FD7\uFF1A\u6D3B\u52A8\u7A97\u7ACB\u5373\u6536\u5230\u5199\u5165\n host.routeLog(bdsLog);\n assert.equal(written.length, 1);\n assert.ok(written[0]?.includes(\"Hello BDS\"));\n\n // \u4EA7\u751F Pack \u65E5\u5FD7\uFF1A\u5F53\u524D\u5728 BDS \u7A97\uFF0CTty \u4E0D\u76F4\u63A5\u5199\uFF0C\u4F46 SFMC \u7A97\u53E3\u540E\u53F0 buffer \u5E94\u8FFD\u52A0\n host.routeLog(packLog);\n assert.equal(written.length, 1); // \u6CA1\u6709\u76F4\u63A5\u5199\u5230\u5F53\u524D Tty\n const sfmcBuffer = host.getBuffer(SFMC_WINDOW_ID);\n assert.equal(sfmcBuffer.length, 1);\n assert.ok(sfmcBuffer[0]?.includes(\"Building pack\"));\n assert.ok(sfmcBuffer[0]?.includes(\"[PAK]\"));\n});\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,9 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { nonBlankOutputLines } from "./services.js";
4
- describe("\u5B50\u8FDB\u7A0B\u8F93\u51FA\u5206\u884C", () => {
5
- it("\u8FC7\u6EE4 LF\u3001CRLF \u4E0E\u7EAF\u7A7A\u767D\u884C\uFF0C\u4FDD\u7559\u771F\u5B9E\u65E5\u5FD7\u5185\u5BB9", () => {
6
- assert.deepEqual(nonBlankOutputLines("first\r\n\r\n \r\nsecond\r\n"), ["first", "second"]);
7
- });
8
- });
9
- //# sourceMappingURL=services-output.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/services-output.test.ts"],
4
- "sourcesContent": ["/**\n * \u5B50\u8FDB\u7A0B\u65E5\u5FD7\u5165\u53E3\u5951\u7EA6\uFF1A\u7EAF\u7A7A\u767D\u884C\u4E0D\u80FD\u8FDB\u5165\u7EDF\u4E00\u65E5\u5FD7\u5E76\u88AB\u5305\u88C5\u6210 [INF]\u3002\n */\nimport assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\nimport { nonBlankOutputLines } from \"./services.js\";\n\ndescribe(\"\u5B50\u8FDB\u7A0B\u8F93\u51FA\u5206\u884C\", () => {\n it(\"\u8FC7\u6EE4 LF\u3001CRLF \u4E0E\u7EAF\u7A7A\u767D\u884C\uFF0C\u4FDD\u7559\u771F\u5B9E\u65E5\u5FD7\u5185\u5BB9\", () => {\n assert.deepEqual(nonBlankOutputLines(\"first\\r\\n\\r\\n \\r\\nsecond\\r\\n\"), [\"first\", \"second\"]);\n });\n});\n"],
5
- "mappings": "AAGA,OAAO,YAAY;AACnB,SAAS,UAAU,UAAU;AAC7B,SAAS,2BAA2B;AAEpC,SAAS,8CAAW,MAAM;AACxB,KAAG,kHAA6B,MAAM;AACpC,WAAO,UAAU,oBAAoB,+BAA+B,GAAG,CAAC,SAAS,QAAQ,CAAC;AAAA,EAC5F,CAAC;AACH,CAAC;",
6
- "names": []
7
- }
@@ -1,11 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { shouldDisplayPackSourceLabel } from "./world-packs.js";
4
- describe("packs list \u66F4\u65B0\u6E90\u5217", () => {
5
- it("\u9690\u85CF\u672A\u7ED1\u5B9A\u5360\u4F4D\u7B26\uFF0C\u4FDD\u7559\u5DF2\u7ED1\u5B9A\u4E0E\u5DF2\u505C\u7528\u6765\u6E90", () => {
6
- assert.equal(shouldDisplayPackSourceLabel("src=-"), false);
7
- assert.equal(shouldDisplayPackSourceLabel("src=CF:farmers-delight"), true);
8
- assert.equal(shouldDisplayPackSourceLabel("src=CF:farmers-delight:off"), true);
9
- });
10
- });
11
- //# sourceMappingURL=world-packs-list.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/world-packs-list.test.ts"],
4
- "sourcesContent": ["/**\n * packs list \u5C55\u793A\u5951\u7EA6\uFF1A\u672A\u7ED1\u5B9A\u66F4\u65B0\u6E90\u65F6\u4E0D\u8F93\u51FA\u65E0\u610F\u4E49\u7684 src=- \u5217\u3002\n */\nimport assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\nimport { shouldDisplayPackSourceLabel } from \"./world-packs.js\";\n\ndescribe(\"packs list \u66F4\u65B0\u6E90\u5217\", () => {\n it(\"\u9690\u85CF\u672A\u7ED1\u5B9A\u5360\u4F4D\u7B26\uFF0C\u4FDD\u7559\u5DF2\u7ED1\u5B9A\u4E0E\u5DF2\u505C\u7528\u6765\u6E90\", () => {\n assert.equal(shouldDisplayPackSourceLabel(\"src=-\"), false);\n assert.equal(shouldDisplayPackSourceLabel(\"src=CF:farmers-delight\"), true);\n assert.equal(shouldDisplayPackSourceLabel(\"src=CF:farmers-delight:off\"), true);\n });\n});\n"],
5
- "mappings": "AAGA,OAAO,YAAY;AACnB,SAAS,UAAU,UAAU;AAC7B,SAAS,oCAAoC;AAE7C,SAAS,uCAAmB,MAAM;AAChC,KAAG,4HAAwB,MAAM;AAC/B,WAAO,MAAM,6BAA6B,OAAO,GAAG,KAAK;AACzD,WAAO,MAAM,6BAA6B,wBAAwB,GAAG,IAAI;AACzE,WAAO,MAAM,6BAA6B,4BAA4B,GAAG,IAAI;AAAA,EAC/E,CAAC;AACH,CAAC;",
6
- "names": []
7
- }
@@ -1,54 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { isProtectedSfmcPack, resolveUninstallTargets } from "./world-packs.js";
4
- function fakePack(folderName, uuid = `uuid-${folderName}`) {
5
- return {
6
- folderName,
7
- uuid,
8
- name: folderName,
9
- kind: "behavior",
10
- version: [1, 0, 0],
11
- enabled: true,
12
- dir: `/tmp/${folderName}`
13
- };
14
- }
15
- describe("packs uninstall protection", () => {
16
- it("\u8BC6\u522B sfmc-modules / sfmc-modules-rp\uFF0C\u5FFD\u7565\u5927\u5C0F\u5199", () => {
17
- assert.equal(isProtectedSfmcPack({ folderName: "sfmc-modules" }), true);
18
- assert.equal(isProtectedSfmcPack({ folderName: "SFMC-Modules" }), true);
19
- assert.equal(isProtectedSfmcPack({ folderName: "sfmc-modules-rp" }), true);
20
- assert.equal(isProtectedSfmcPack({ folderName: "[BP] MyAddon" }), false);
21
- });
22
- });
23
- describe("resolveUninstallTargets LSP", () => {
24
- const packs = [
25
- fakePack("sfmc-modules", "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
26
- fakePack("[BP] Addon", "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
27
- fakePack("[BP] Other", "cccccccc-cccc-cccc-cccc-cccccccccccc")
28
- ];
29
- it("\u5355 id \u53D7\u4FDD\u62A4 \u2192 protected", () => {
30
- const r = resolveUninstallTargets(packs, ["sfmc-modules"]);
31
- assert.equal(r.status, "protected");
32
- if (r.status === "protected") assert.equal(r.folder, "sfmc-modules");
33
- });
34
- it("\u591A id \u542B\u53D7\u4FDD\u62A4 \u2192 \u6574\u4F53 protected\uFF08\u4E0D\u8FD4\u56DE ok\uFF09", () => {
35
- const r = resolveUninstallTargets(packs, ["[BP] Addon", "sfmc-modules"]);
36
- assert.equal(r.status, "protected");
37
- if (r.status === "protected") assert.equal(r.folder, "sfmc-modules");
38
- });
39
- it("\u591A id \u5747\u53EF\u5378 \u2192 ok\uFF0C\u6309 uuid \u53BB\u91CD", () => {
40
- const r = resolveUninstallTargets(packs, [
41
- "[BP] Addon",
42
- "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
43
- "[BP] Other"
44
- ]);
45
- assert.equal(r.status, "ok");
46
- if (r.status === "ok") assert.equal(r.selected.length, 2);
47
- });
48
- it("\u7F3A id \u2192 not_found", () => {
49
- const r = resolveUninstallTargets(packs, ["nope", "[BP] Addon"]);
50
- assert.equal(r.status, "not_found");
51
- if (r.status === "not_found") assert.deepEqual(r.missing, ["nope"]);
52
- });
53
- });
54
- //# sourceMappingURL=world-packs-uninstall.test.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/world-packs-uninstall.test.ts"],
4
- "sourcesContent": ["/**\n * packs uninstall \u7B56\u7565\u5951\u7EA6\uFF1A\u53D7\u4FDD\u62A4\u5E73\u53F0\u5305\u8BC6\u522B + \u591A id \u89E3\u6790\n */\nimport assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\nimport { isProtectedSfmcPack, resolveUninstallTargets, type InstalledWorldPack } from \"./world-packs.js\";\n\nfunction fakePack(folderName: string, uuid = `uuid-${folderName}`): InstalledWorldPack {\n return {\n folderName,\n uuid,\n name: folderName,\n kind: \"behavior\",\n version: [1, 0, 0],\n enabled: true,\n dir: `/tmp/${folderName}`,\n };\n}\n\ndescribe(\"packs uninstall protection\", () => {\n it(\"\u8BC6\u522B sfmc-modules / sfmc-modules-rp\uFF0C\u5FFD\u7565\u5927\u5C0F\u5199\", () => {\n assert.equal(isProtectedSfmcPack({ folderName: \"sfmc-modules\" }), true);\n assert.equal(isProtectedSfmcPack({ folderName: \"SFMC-Modules\" }), true);\n assert.equal(isProtectedSfmcPack({ folderName: \"sfmc-modules-rp\" }), true);\n assert.equal(isProtectedSfmcPack({ folderName: \"[BP] MyAddon\" }), false);\n });\n});\n\ndescribe(\"resolveUninstallTargets LSP\", () => {\n const packs = [\n fakePack(\"sfmc-modules\", \"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa\"),\n fakePack(\"[BP] Addon\", \"bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb\"),\n fakePack(\"[BP] Other\", \"cccccccc-cccc-cccc-cccc-cccccccccccc\"),\n ];\n\n it(\"\u5355 id \u53D7\u4FDD\u62A4 \u2192 protected\", () => {\n const r = resolveUninstallTargets(packs, [\"sfmc-modules\"]);\n assert.equal(r.status, \"protected\");\n if (r.status === \"protected\") assert.equal(r.folder, \"sfmc-modules\");\n });\n\n it(\"\u591A id \u542B\u53D7\u4FDD\u62A4 \u2192 \u6574\u4F53 protected\uFF08\u4E0D\u8FD4\u56DE ok\uFF09\", () => {\n const r = resolveUninstallTargets(packs, [\"[BP] Addon\", \"sfmc-modules\"]);\n assert.equal(r.status, \"protected\");\n if (r.status === \"protected\") assert.equal(r.folder, \"sfmc-modules\");\n });\n\n it(\"\u591A id \u5747\u53EF\u5378 \u2192 ok\uFF0C\u6309 uuid \u53BB\u91CD\", () => {\n const r = resolveUninstallTargets(packs, [\n \"[BP] Addon\",\n \"bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb\",\n \"[BP] Other\",\n ]);\n assert.equal(r.status, \"ok\");\n if (r.status === \"ok\") assert.equal(r.selected.length, 2);\n });\n\n it(\"\u7F3A id \u2192 not_found\", () => {\n const r = resolveUninstallTargets(packs, [\"nope\", \"[BP] Addon\"]);\n assert.equal(r.status, \"not_found\");\n if (r.status === \"not_found\") assert.deepEqual(r.missing, [\"nope\"]);\n });\n});\n"],
5
- "mappings": "AAGA,OAAO,YAAY;AACnB,SAAS,UAAU,UAAU;AAC7B,SAAS,qBAAqB,+BAAwD;AAEtF,SAAS,SAAS,YAAoB,OAAO,QAAQ,UAAU,IAAwB;AACrF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,CAAC,GAAG,GAAG,CAAC;AAAA,IACjB,SAAS;AAAA,IACT,KAAK,QAAQ,UAAU;AAAA,EACzB;AACF;AAEA,SAAS,8BAA8B,MAAM;AAC3C,KAAG,mFAA2C,MAAM;AAClD,WAAO,MAAM,oBAAoB,EAAE,YAAY,eAAe,CAAC,GAAG,IAAI;AACtE,WAAO,MAAM,oBAAoB,EAAE,YAAY,eAAe,CAAC,GAAG,IAAI;AACtE,WAAO,MAAM,oBAAoB,EAAE,YAAY,kBAAkB,CAAC,GAAG,IAAI;AACzE,WAAO,MAAM,oBAAoB,EAAE,YAAY,eAAe,CAAC,GAAG,KAAK;AAAA,EACzE,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,MAAM;AAC5C,QAAM,QAAQ;AAAA,IACZ,SAAS,gBAAgB,sCAAsC;AAAA,IAC/D,SAAS,cAAc,sCAAsC;AAAA,IAC7D,SAAS,cAAc,sCAAsC;AAAA,EAC/D;AAEA,KAAG,iDAAwB,MAAM;AAC/B,UAAM,IAAI,wBAAwB,OAAO,CAAC,cAAc,CAAC;AACzD,WAAO,MAAM,EAAE,QAAQ,WAAW;AAClC,QAAI,EAAE,WAAW,YAAa,QAAO,MAAM,EAAE,QAAQ,cAAc;AAAA,EACrE,CAAC;AAED,KAAG,qGAAoC,MAAM;AAC3C,UAAM,IAAI,wBAAwB,OAAO,CAAC,cAAc,cAAc,CAAC;AACvE,WAAO,MAAM,EAAE,QAAQ,WAAW;AAClC,QAAI,EAAE,WAAW,YAAa,QAAO,MAAM,EAAE,QAAQ,cAAc;AAAA,EACrE,CAAC;AAED,KAAG,wEAA2B,MAAM;AAClC,UAAM,IAAI,wBAAwB,OAAO;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,MAAM,EAAE,QAAQ,IAAI;AAC3B,QAAI,EAAE,WAAW,KAAM,QAAO,MAAM,EAAE,SAAS,QAAQ,CAAC;AAAA,EAC1D,CAAC;AAED,KAAG,8BAAoB,MAAM;AAC3B,UAAM,IAAI,wBAAwB,OAAO,CAAC,QAAQ,YAAY,CAAC;AAC/D,WAAO,MAAM,EAAE,QAAQ,WAAW;AAClC,QAAI,EAAE,WAAW,YAAa,QAAO,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC;AAAA,EACpE,CAAC;AACH,CAAC;",
6
- "names": []
7
- }