@sfmc-bds/cli 0.2.0-beta.20 → 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 (61) 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/commands.d.ts.map +1 -1
  6. package/dist/commands.js +78 -75
  7. package/dist/commands.js.map +2 -2
  8. package/dist/llbot-launch.d.ts +3 -3
  9. package/dist/llbot-launch.js.map +1 -1
  10. package/dist/logs.js +3 -3
  11. package/dist/logs.js.map +2 -2
  12. package/dist/repl-windows/service-window.d.ts.map +1 -1
  13. package/dist/repl-windows/service-window.js +1 -0
  14. package/dist/repl-windows/service-window.js.map +2 -2
  15. package/dist/repl.d.ts.map +1 -1
  16. package/dist/repl.js +18 -12
  17. package/dist/repl.js.map +2 -2
  18. package/dist/send-target.d.ts.map +1 -1
  19. package/dist/send-target.js +2 -0
  20. package/dist/send-target.js.map +2 -2
  21. package/dist/services.d.ts +8 -1
  22. package/dist/services.d.ts.map +1 -1
  23. package/dist/services.js +151 -15
  24. package/dist/services.js.map +2 -2
  25. package/dist/ui-command.d.ts.map +1 -1
  26. package/dist/ui-command.js.map +2 -2
  27. package/dist/wizard.d.ts.map +1 -1
  28. package/dist/wizard.js +15 -8
  29. package/dist/wizard.js.map +2 -2
  30. package/package.json +4 -5
  31. package/scripts/module-install/lib/catalog.mjs +1 -1
  32. package/dist/command-surface.test.js +0 -92
  33. package/dist/command-surface.test.js.map +0 -7
  34. package/dist/debug-command.test.js +0 -76
  35. package/dist/debug-command.test.js.map +0 -7
  36. package/dist/log-filter.test.js +0 -181
  37. package/dist/log-filter.test.js.map +0 -7
  38. package/dist/log-translator.test.js +0 -120
  39. package/dist/log-translator.test.js.map +0 -7
  40. package/dist/logs-blank-line.test.js +0 -16
  41. package/dist/logs-blank-line.test.js.map +0 -7
  42. package/dist/module-toggle.test.js +0 -37
  43. package/dist/module-toggle.test.js.map +0 -7
  44. package/dist/pack-bundle.test.js +0 -111
  45. package/dist/pack-bundle.test.js.map +0 -7
  46. package/dist/player-session.test.js +0 -19
  47. package/dist/player-session.test.js.map +0 -7
  48. package/dist/repl-windows/host.test.js +0 -72
  49. package/dist/repl-windows/host.test.js.map +0 -7
  50. package/dist/services-output.test.js +0 -9
  51. package/dist/services-output.test.js.map +0 -7
  52. package/dist/world-packs-list.test.js +0 -11
  53. package/dist/world-packs-list.test.js.map +0 -7
  54. package/dist/world-packs-uninstall.test.js +0 -54
  55. package/dist/world-packs-uninstall.test.js.map +0 -7
  56. package/scripts/module-install/test/check-modules-config.test.ts +0 -46
  57. package/scripts/module-install/test/config-seeding.test.ts +0 -99
  58. package/scripts/module-install/test/install-resolver.test.ts +0 -47
  59. package/scripts/module-install/test/link-local.test.ts +0 -50
  60. package/scripts/module-install/test/local-resolver.test.ts +0 -44
  61. package/scripts/module-install/test/registry-index.test.ts +0 -27
@@ -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
- }
@@ -1,46 +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 { validateDefaultConfig } from "../check-modules.mjs";
7
-
8
- function moduleFixture(files: Record<string, string> = {}) {
9
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-check-config-"));
10
- const dir = path.join(root, "configs-default");
11
- if (Object.keys(files).length > 0) fs.mkdirSync(dir, { recursive: true });
12
- for (const [name, body] of Object.entries(files)) fs.writeFileSync(path.join(dir, name), body);
13
- return root;
14
- }
15
-
16
- test("validateDefaultConfig 接受标准对象配置", () => {
17
- const root = moduleFixture({ "demo.json": '{"enabled":true}' });
18
- assert.deepEqual(validateDefaultConfig(root, "demo"), { ok: true });
19
- fs.rmSync(root, { recursive: true, force: true });
20
- });
21
-
22
- test("validateDefaultConfig 对缺失默认配置给出警告", () => {
23
- const root = moduleFixture();
24
- const result = validateDefaultConfig(root, "demo");
25
- assert.equal(result.ok, true);
26
- if (result.ok) assert.match(result.warning ?? "", /未提供默认配置/);
27
- fs.rmSync(root, { recursive: true, force: true });
28
- });
29
-
30
- test("validateDefaultConfig 拒绝错名、损坏及非对象配置", () => {
31
- const wrong = moduleFixture({ "other.json": "{}" });
32
- assert.deepEqual(validateDefaultConfig(wrong, "demo").ok, false);
33
- fs.rmSync(wrong, { recursive: true, force: true });
34
-
35
- const broken = moduleFixture({ "demo.json": "{" });
36
- const brokenResult = validateDefaultConfig(broken, "demo");
37
- assert.equal(brokenResult.ok, false);
38
- if (!brokenResult.ok) assert.match(brokenResult.error, /解析失败/);
39
- fs.rmSync(broken, { recursive: true, force: true });
40
-
41
- const array = moduleFixture({ "demo.json": "[]" });
42
- const arrayResult = validateDefaultConfig(array, "demo");
43
- assert.equal(arrayResult.ok, false);
44
- if (!arrayResult.ok) assert.match(arrayResult.error, /顶层必须是 JSON 对象/);
45
- fs.rmSync(array, { recursive: true, force: true });
46
- });
@@ -1,99 +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 { mergeMissing, seedModuleConfig } from "../lib/config-seeding.mjs";
7
-
8
- function fixture(defaults?: unknown, current?: unknown) {
9
- const root = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-config-seeding-"));
10
- const moduleRoot = path.join(root, "module");
11
- const projectRoot = path.join(root, "project");
12
- fs.mkdirSync(path.join(moduleRoot, "configs-default"), { recursive: true });
13
- if (defaults !== undefined) {
14
- const body = typeof defaults === "string" ? defaults : JSON.stringify(defaults);
15
- fs.writeFileSync(path.join(moduleRoot, "configs-default", "demo.json"), body);
16
- }
17
- if (current !== undefined) {
18
- fs.mkdirSync(path.join(projectRoot, "configs"), { recursive: true });
19
- const body = typeof current === "string" ? current : JSON.stringify(current);
20
- fs.writeFileSync(path.join(projectRoot, "configs", "demo.json"), body);
21
- }
22
- return { root, moduleRoot, projectRoot, target: path.join(projectRoot, "configs", "demo.json") };
23
- }
24
-
25
- test("mergeMissing 递归补缺且不覆盖或修改输入", () => {
26
- const current = { enabled: false, nested: { keep: 1 }, list: ["user"], extra: true };
27
- const defaults = { enabled: true, nested: { keep: 0, added: 2 }, list: ["default"], fresh: "x" };
28
- const before = structuredClone(current);
29
- const result = mergeMissing(current, defaults);
30
- assert.deepEqual(current, before);
31
- assert.deepEqual(result.value, {
32
- enabled: false,
33
- nested: { keep: 1, added: 2 },
34
- list: ["user"],
35
- extra: true,
36
- fresh: "x",
37
- });
38
- assert.deepEqual(result.addedPaths, ["fresh", "nested.added"]);
39
- });
40
-
41
- test("seedModuleConfig 创建、补缺与无变化", () => {
42
- const f = fixture({ enabled: true, nested: { first: 1 } });
43
- const created = seedModuleConfig({ ...f, configKey: "demo" });
44
- assert.equal(created.status, "created");
45
- assert.deepEqual(JSON.parse(fs.readFileSync(f.target, "utf8")), {
46
- enabled: true,
47
- nested: { first: 1 },
48
- });
49
-
50
- fs.writeFileSync(f.target, JSON.stringify({ enabled: false, nested: { first: 9 } }));
51
- fs.writeFileSync(
52
- path.join(f.moduleRoot, "configs-default", "demo.json"),
53
- JSON.stringify({ enabled: true, nested: { first: 1, second: 2 }, list: ["default"] })
54
- );
55
- const updated = seedModuleConfig({ ...f, configKey: "demo" });
56
- assert.equal(updated.status, "updated");
57
- assert.deepEqual(updated.addedPaths, ["list", "nested.second"]);
58
- assert.deepEqual(JSON.parse(fs.readFileSync(f.target, "utf8")), {
59
- enabled: false,
60
- nested: { first: 9, second: 2 },
61
- list: ["default"],
62
- });
63
- assert.equal(seedModuleConfig({ ...f, configKey: "demo" }).status, "unchanged");
64
- fs.rmSync(f.root, { recursive: true, force: true });
65
- });
66
-
67
- test("seedModuleConfig 缺失默认文件时保持兼容", () => {
68
- const f = fixture();
69
- assert.equal(seedModuleConfig({ ...f, configKey: "demo" }).status, "missing-defaults");
70
- assert.equal(fs.existsSync(f.target), false);
71
- fs.rmSync(f.root, { recursive: true, force: true });
72
- });
73
-
74
- test("seedModuleConfig 拒绝与 configKey 不一致的默认文件名", () => {
75
- const f = fixture();
76
- fs.writeFileSync(path.join(f.moduleRoot, "configs-default", "other.json"), "{}");
77
- assert.throws(() => seedModuleConfig({ ...f, configKey: "demo" }), /文件名必须为/);
78
- fs.rmSync(f.root, { recursive: true, force: true });
79
- });
80
-
81
- test("seedModuleConfig 拒绝损坏 JSON、非对象与非法 configKey", () => {
82
- const brokenDefault = fixture("{");
83
- assert.throws(() => seedModuleConfig({ ...brokenDefault, configKey: "demo" }), /默认配置.*解析失败/);
84
- fs.rmSync(brokenDefault.root, { recursive: true, force: true });
85
-
86
- const scalar = fixture([]);
87
- assert.throws(() => seedModuleConfig({ ...scalar, configKey: "demo" }), /顶层必须是 JSON 对象/);
88
- fs.rmSync(scalar.root, { recursive: true, force: true });
89
-
90
- const brokenUser = fixture({ ok: true }, "{broken");
91
- const before = fs.readFileSync(brokenUser.target);
92
- assert.throws(() => seedModuleConfig({ ...brokenUser, configKey: "demo" }), /用户配置.*解析失败/);
93
- assert.deepEqual(fs.readFileSync(brokenUser.target), before);
94
- fs.rmSync(brokenUser.root, { recursive: true, force: true });
95
-
96
- const invalid = fixture({});
97
- assert.throws(() => seedModuleConfig({ ...invalid, configKey: "../escape" }), /invalid configKey/);
98
- fs.rmSync(invalid.root, { recursive: true, force: true });
99
- });
@@ -1,47 +0,0 @@
1
- /**
2
- * install-resolver npm 包名解析表驱动
3
- */
4
- import assert from "node:assert/strict";
5
- import test from "node:test";
6
- import {
7
- folderFromNpmPackageName,
8
- normalizeNpmPackageName,
9
- resolveNpmPackageName,
10
- } from "../lib/npm-resolver.mjs";
11
-
12
- test("短 id → @sfmc-bds/module-<id>", () => {
13
- assert.equal(resolveNpmPackageName("land"), "@sfmc-bds/module-land");
14
- assert.equal(resolveNpmPackageName("my-mod"), "@sfmc-bds/module-my-mod");
15
- });
16
-
17
- test("logical id (feature-* / core-*) → @sfmc-bds/module-<folder>", () => {
18
- assert.equal(resolveNpmPackageName("feature-land"), "@sfmc-bds/module-land");
19
- assert.equal(resolveNpmPackageName("core-data-backup"), "@sfmc-bds/module-data-backup");
20
- });
21
-
22
- test("已带 scope 原样透传", () => {
23
- assert.equal(resolveNpmPackageName("@alice/sfmc-module-foo"), "@alice/sfmc-module-foo");
24
- assert.equal(resolveNpmPackageName("@sfmc-bds/module-land"), "@sfmc-bds/module-land");
25
- });
26
-
27
- test("非 kebab 报错", () => {
28
- assert.throws(() => resolveNpmPackageName("NotKebab"), /invalid module id/);
29
- assert.throws(() => resolveNpmPackageName("feature-"), /invalid module id/);
30
- });
31
-
32
- test("@ 但无 / → invalid scoped package name", () => {
33
- assert.throws(() => resolveNpmPackageName("@orphan"), /invalid scoped package name/);
34
- });
35
-
36
- test("folderFromNpmPackageName 反向解析", () => {
37
- assert.equal(folderFromNpmPackageName("@sfmc-bds/module-land"), "land");
38
- assert.equal(folderFromNpmPackageName("@alice/sfmc-module-foo"), "foo");
39
- assert.equal(folderFromNpmPackageName("@alice/sfmc-module-my-mod"), "my-mod");
40
- assert.equal(folderFromNpmPackageName("@alice/random"), null);
41
- });
42
-
43
- test("normalizeNpmPackageName 兼容两种前缀", () => {
44
- assert.equal(normalizeNpmPackageName("@sfmc-bds/module-land"), "land");
45
- assert.equal(normalizeNpmPackageName("@alice/sfmc-module-foo"), "foo");
46
- assert.equal(normalizeNpmPackageName("@alice/module-bar"), "bar");
47
- });
@@ -1,50 +0,0 @@
1
- /**
2
- * link-local normalizeLinkFrom 表驱动
3
- */
4
- import assert from "node:assert/strict";
5
- import fs from "node:fs";
6
- import os from "node:os";
7
- import path from "node:path";
8
- import test from "node:test";
9
- import { normalizeLinkFrom } from "../lib/link-from.mjs";
10
-
11
- const CWD = process.cwd();
12
-
13
- test("local 无路径 → dir:cwd", () => {
14
- const r = normalizeLinkFrom("local", CWD);
15
- assert.equal(r.ok, true);
16
- if (r.ok) assert.equal(r.from, `dir:${path.resolve(CWD)}`);
17
- });
18
-
19
- test("local:相对目录 → dir:绝对路径", () => {
20
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-link-rel-"));
21
- const rel = path.relative(CWD, tmp) || ".";
22
- const r = normalizeLinkFrom(`local:${rel}`, CWD);
23
- assert.equal(r.ok, true);
24
- if (r.ok) assert.equal(r.from, `dir:${path.resolve(CWD, rel)}`);
25
- fs.rmSync(tmp, { recursive: true, force: true });
26
- });
27
-
28
- test("local:file.tgz + link → 拒绝", () => {
29
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-link-"));
30
- const tgz = path.join(tmp, "x.tgz");
31
- fs.writeFileSync(tgz, "");
32
- const r = normalizeLinkFrom(`local:${tgz}`, CWD);
33
- assert.equal(r.ok, false);
34
- if (!r.ok) assert.match(r.error, /tgz|zip|--link/i);
35
- fs.rmSync(tmp, { recursive: true, force: true });
36
- });
37
-
38
- test("dir: 原样通过", () => {
39
- const r = normalizeLinkFrom("dir:D:/mods/foo", CWD);
40
- assert.equal(r.ok, true);
41
- if (r.ok) assert.equal(r.from, "dir:D:/mods/foo");
42
- });
43
-
44
- test("裸路径目录 → dir:绝对路径", () => {
45
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-link-bare-"));
46
- const r = normalizeLinkFrom(tmp, CWD);
47
- assert.equal(r.ok, true);
48
- if (r.ok) assert.equal(r.from, `dir:${path.resolve(tmp)}`);
49
- fs.rmSync(tmp, { recursive: true, force: true });
50
- });
@@ -1,44 +0,0 @@
1
- /**
2
- * local-resolver `--from local` 路径解析表驱动
3
- */
4
- import assert from "node:assert/strict";
5
- import path from "node:path";
6
- import process from "node:process";
7
- import test from "node:test";
8
-
9
- /** 镜像 fetch-module.mjs#resolveLocalPath */
10
- function resolveLocalPath(tail: string | undefined): string {
11
- const p = String(tail ?? "").trim();
12
- if (!p || p === "." || p === "./") return path.resolve(process.cwd());
13
- return path.isAbsolute(p) ? path.resolve(p) : path.resolve(process.cwd(), p);
14
- }
15
-
16
- const CWD = process.cwd();
17
-
18
- test("空 → cwd", () => assert.equal(resolveLocalPath(""), path.resolve(CWD)));
19
- test("undefined → cwd", () => assert.equal(resolveLocalPath(undefined), path.resolve(CWD)));
20
- test(". → cwd", () => assert.equal(resolveLocalPath("."), path.resolve(CWD)));
21
- test("./ → cwd", () => assert.equal(resolveLocalPath("./"), path.resolve(CWD)));
22
-
23
- test("相对 ./foo → 相对 cwd 解析", () => {
24
- assert.equal(resolveLocalPath("./foo"), path.resolve(CWD, "foo"));
25
- });
26
-
27
- test("相对无点 foo", () => {
28
- assert.equal(resolveLocalPath("foo"), path.resolve(CWD, "foo"));
29
- });
30
-
31
- test("绝对路径原样", () => {
32
- const abs = process.platform === "win32" ? "D:\\work\\my-mod" : "/tmp/my-mod";
33
- assert.equal(resolveLocalPath(abs), path.resolve(abs));
34
- });
35
-
36
- test("绝对路径 .tgz", () => {
37
- const abs = process.platform === "win32" ? "D:\\work\\foo-1.0.0.tgz" : "/tmp/foo-1.0.0.tgz";
38
- assert.equal(resolveLocalPath(abs), path.resolve(abs));
39
- });
40
-
41
- test("绝对路径 .zip", () => {
42
- const abs = process.platform === "win32" ? "D:\\work\\foo.zip" : "/tmp/foo.zip";
43
- assert.equal(resolveLocalPath(abs), path.resolve(abs));
44
- });
@@ -1,27 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { parseRegistryIndex } from "../lib/registry-index.mjs";
4
-
5
- test("接受 npm 条目", () => {
6
- const idx = parseRegistryIndex({
7
- version: 2,
8
- modules: {
9
- land: { npm: "@sfmc-bds/module-land", version: "1.0.0", sdk: ">=0.2.0" },
10
- },
11
- });
12
- assert.equal(idx.land?.npm, "@sfmc-bds/module-land");
13
- assert.equal(idx.land?.version, "1.0.0");
14
- });
15
-
16
- test("仍接受 repo+tag", () => {
17
- const idx = parseRegistryIndex({
18
- modules: { afk: { repo: "Tanya7z/sfmc-modules", tag: "modules-v0.4.0" } },
19
- });
20
- assert.equal(idx.afk?.repo, "Tanya7z/sfmc-modules");
21
- assert.equal(idx.afk?.tag, "modules-v0.4.0");
22
- });
23
-
24
- test("既无 npm 也无 repo 则跳过", () => {
25
- const idx = parseRegistryIndex({ modules: { bad: { version: "1" } } });
26
- assert.equal(idx.bad, undefined);
27
- });