@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.
- package/dist/bds-runtime-version.d.ts +3 -0
- package/dist/bds-runtime-version.d.ts.map +1 -0
- package/dist/bds-runtime-version.js +15 -0
- package/dist/bds-runtime-version.js.map +7 -0
- package/dist/command-surface.d.ts.map +1 -1
- package/dist/command-surface.js +2 -0
- package/dist/command-surface.js.map +2 -2
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +78 -75
- package/dist/commands.js.map +2 -2
- package/dist/i18n/locales/en.d.ts +8 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +8 -0
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.js +8 -0
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/llbot-launch.d.ts +3 -3
- package/dist/llbot-launch.js.map +1 -1
- package/dist/logs.js +3 -3
- package/dist/logs.js.map +2 -2
- package/dist/main.js +5 -0
- package/dist/main.js.map +2 -2
- package/dist/repl-windows/service-window.d.ts.map +1 -1
- package/dist/repl-windows/service-window.js +1 -0
- package/dist/repl-windows/service-window.js.map +2 -2
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +23 -12
- package/dist/repl.js.map +2 -2
- package/dist/send-target.d.ts.map +1 -1
- package/dist/send-target.js +2 -0
- package/dist/send-target.js.map +2 -2
- package/dist/services.d.ts +8 -1
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +151 -15
- package/dist/services.js.map +2 -2
- package/dist/ui-command.d.ts +6 -0
- package/dist/ui-command.d.ts.map +1 -0
- package/dist/ui-command.js +68 -0
- package/dist/ui-command.js.map +7 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +15 -8
- package/dist/wizard.js.map +2 -2
- package/package.json +4 -5
- package/scripts/module-install/lib/catalog.mjs +1 -1
- package/dist/command-surface.test.js +0 -92
- package/dist/command-surface.test.js.map +0 -7
- package/dist/debug-command.test.js +0 -76
- package/dist/debug-command.test.js.map +0 -7
- package/dist/log-filter.test.js +0 -181
- package/dist/log-filter.test.js.map +0 -7
- package/dist/log-translator.test.js +0 -120
- package/dist/log-translator.test.js.map +0 -7
- package/dist/logs-blank-line.test.js +0 -16
- package/dist/logs-blank-line.test.js.map +0 -7
- package/dist/module-toggle.test.js +0 -37
- package/dist/module-toggle.test.js.map +0 -7
- package/dist/pack-bundle.test.js +0 -111
- package/dist/pack-bundle.test.js.map +0 -7
- package/dist/player-session.test.js +0 -19
- package/dist/player-session.test.js.map +0 -7
- package/dist/repl-windows/host.test.js +0 -72
- package/dist/repl-windows/host.test.js.map +0 -7
- package/dist/services-output.test.js +0 -9
- package/dist/services-output.test.js.map +0 -7
- package/dist/world-packs-list.test.js +0 -11
- package/dist/world-packs-list.test.js.map +0 -7
- package/dist/world-packs-uninstall.test.js +0 -54
- package/dist/world-packs-uninstall.test.js.map +0 -7
- package/scripts/module-install/test/check-modules-config.test.ts +0 -46
- package/scripts/module-install/test/config-seeding.test.ts +0 -99
- package/scripts/module-install/test/install-resolver.test.ts +0 -47
- package/scripts/module-install/test/link-local.test.ts +0 -50
- package/scripts/module-install/test/local-resolver.test.ts +0 -44
- package/scripts/module-install/test/registry-index.test.ts +0 -27
|
@@ -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
|
-
});
|