@sfmc-bds/cli 0.2.0-beta.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +663 -0
- package/README.md +4 -5
- 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 +3 -1
- package/dist/command-surface.js.map +2 -2
- package/dist/commands.d.ts +57 -4
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +78 -75
- package/dist/commands.js.map +2 -2
- package/dist/directory-picker.d.ts +27 -0
- package/dist/directory-picker.d.ts.map +1 -0
- package/dist/directory-picker.js +112 -0
- package/dist/directory-picker.js.map +7 -0
- package/dist/i18n/locales/en.d.ts +25 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +25 -1
- 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 +26 -2
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/interactive-prompts.d.ts +1 -2
- package/dist/interactive-prompts.d.ts.map +1 -1
- package/dist/interactive-prompts.js +12 -23
- package/dist/interactive-prompts.js.map +3 -3
- package/dist/llbot-launch.d.ts +3 -3
- package/dist/llbot-launch.js.map +1 -1
- package/dist/log-filter.d.ts +18 -2
- package/dist/log-filter.d.ts.map +1 -1
- package/dist/log-filter.js +54 -4
- package/dist/log-filter.js.map +2 -2
- package/dist/log-translator.d.ts +36 -0
- package/dist/log-translator.d.ts.map +1 -0
- package/dist/log-translator.js +279 -0
- package/dist/log-translator.js.map +7 -0
- package/dist/logs.d.ts +2 -0
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +24 -11
- package/dist/logs.js.map +2 -2
- package/dist/main.js +5 -0
- package/dist/main.js.map +2 -2
- package/dist/module-commands.d.ts.map +1 -1
- package/dist/module-commands.js +22 -8
- package/dist/module-commands.js.map +2 -2
- package/dist/module-fingerprint.d.ts.map +1 -1
- package/dist/module-fingerprint.js +1 -0
- package/dist/module-fingerprint.js.map +2 -2
- package/dist/module-pack-build.d.ts +14 -4
- package/dist/module-pack-build.d.ts.map +1 -1
- package/dist/module-pack-build.js +81 -108
- package/dist/module-pack-build.js.map +2 -2
- package/dist/module-toggle.d.ts +1 -1
- package/dist/module-toggle.d.ts.map +1 -1
- package/dist/module-toggle.js.map +1 -1
- package/dist/pack-lifecycle.d.ts +15 -1
- package/dist/pack-lifecycle.d.ts.map +1 -1
- package/dist/pack-lifecycle.js +242 -15
- package/dist/pack-lifecycle.js.map +2 -2
- package/dist/player-session.d.ts +13 -0
- package/dist/player-session.d.ts.map +1 -0
- package/dist/player-session.js +26 -0
- package/dist/player-session.js.map +7 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -1
- package/dist/registry.js.map +2 -2
- package/dist/repl-windows/format-display.d.ts.map +1 -1
- package/dist/repl-windows/format-display.js +5 -1
- package/dist/repl-windows/format-display.js.map +2 -2
- package/dist/repl-windows/host.d.ts +6 -3
- package/dist/repl-windows/host.d.ts.map +1 -1
- package/dist/repl-windows/host.js +12 -6
- package/dist/repl-windows/host.js.map +2 -2
- package/dist/repl-windows/index.d.ts +1 -0
- package/dist/repl-windows/index.d.ts.map +1 -1
- package/dist/repl-windows/index.js +3 -0
- package/dist/repl-windows/index.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-windows/sfmc-window.d.ts +7 -0
- package/dist/repl-windows/sfmc-window.d.ts.map +1 -0
- package/dist/repl-windows/sfmc-window.js +28 -0
- package/dist/repl-windows/sfmc-window.js.map +7 -0
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +38 -13
- package/dist/repl.js.map +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +15 -2
- package/dist/runtime.js.map +2 -2
- package/dist/send-target.d.ts +2 -0
- package/dist/send-target.d.ts.map +1 -1
- package/dist/send-target.js +6 -0
- package/dist/send-target.js.map +2 -2
- package/dist/services.d.ts +26 -1
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +179 -45
- package/dist/services.js.map +2 -2
- package/dist/sfmc-modules-root.d.ts.map +1 -1
- package/dist/sfmc-modules-root.js +6 -2
- package/dist/sfmc-modules-root.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 +36 -31
- package/dist/wizard.js.map +2 -2
- package/dist/world-packs.d.ts +2 -0
- package/dist/world-packs.d.ts.map +1 -1
- package/dist/world-packs.js +161 -18
- package/dist/world-packs.js.map +2 -2
- package/package.json +22 -15
- package/scripts/module-install/check-modules.mjs +178 -0
- package/scripts/module-install/fetch-module.mjs +1083 -0
- package/scripts/module-install/lib/catalog.mjs +96 -0
- package/scripts/module-install/lib/config-seeding.mjs +128 -0
- package/scripts/module-install/lib/io.mjs +37 -0
- package/scripts/module-install/lib/link-from.mjs +80 -0
- package/scripts/module-install/lib/lock.mjs +78 -0
- package/scripts/module-install/lib/npm-resolver.mjs +55 -0
- package/scripts/module-install/lib/packages.mjs +136 -0
- package/scripts/module-install/lib/paths.mjs +48 -0
- package/scripts/module-install/lib/registry-index.mjs +50 -0
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfmc-bds/cli",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "SFMC management CLI — REPL, service supervisor, module install, behavior-pack build/deploy",
|
|
5
5
|
"author": "Shiroha7z",
|
|
6
|
-
"license": "AGPL-
|
|
6
|
+
"license": "AGPL-3.0-only",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"homepage": "https://github.com/DogeLakeDev/ScriptsForMinecraftServer/tree/main/packages/cli#readme",
|
|
9
9
|
"repository": {
|
|
@@ -35,30 +35,37 @@
|
|
|
35
35
|
"types": "./dist/main.d.ts",
|
|
36
36
|
"import": "./dist/main.js",
|
|
37
37
|
"default": "./dist/main.js"
|
|
38
|
-
}
|
|
38
|
+
},
|
|
39
|
+
"./fetch-module.mjs": "./scripts/module-install/fetch-module.mjs",
|
|
40
|
+
"./package.json": "./package.json"
|
|
39
41
|
},
|
|
40
42
|
"bin": {
|
|
41
|
-
"sfmc": "./dist/main.js"
|
|
43
|
+
"sfmc": "./dist/main.js",
|
|
44
|
+
"sfmc-fetch-module": "./scripts/module-install/fetch-module.mjs"
|
|
42
45
|
},
|
|
43
46
|
"files": [
|
|
44
47
|
"dist",
|
|
48
|
+
"scripts",
|
|
45
49
|
"README.md"
|
|
46
50
|
],
|
|
47
|
-
"scripts": {
|
|
48
|
-
"build": "sfmc-esbuild-transpile --dts",
|
|
49
|
-
"prepublishOnly": "npm run build",
|
|
50
|
-
"start": "node ./dist/main.js",
|
|
51
|
-
"test": "npm run build && node --test terminal-progress.test.mjs wrap-log-line.test.mjs world-packs-uninstall.test.mjs log-filter.test.mjs debug-command.test.mjs command-surface.test.mjs argv-parse.test.mjs command-palette.test.mjs repl-windows.test.mjs module-toggle.test.mjs llbot-launch.test.mjs",
|
|
52
|
-
"typecheck": "tsc7 --noEmit -p tsconfig.json"
|
|
53
|
-
},
|
|
54
51
|
"dependencies": {
|
|
55
52
|
"@clack/prompts": "^1.7.0",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
53
|
+
"chalk": "^6.0.0",
|
|
54
|
+
"cross-spawn": "7.0.6",
|
|
55
|
+
"esbuild": "^0.28.1",
|
|
56
|
+
"@sfmc-bds/bds-tools": "0.2.0",
|
|
57
|
+
"@sfmc-bds/sdk": "0.2.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@sfmc-bds/tools": "0.2.0"
|
|
59
61
|
},
|
|
60
62
|
"publishConfig": {
|
|
61
63
|
"access": "public",
|
|
62
64
|
"registry": "https://registry.npmjs.org/"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "sfmc-esbuild-transpile --dts",
|
|
68
|
+
"start": "node ./dist/main.js",
|
|
69
|
+
"typecheck": "tsc7 --noEmit -p tsconfig.json"
|
|
63
70
|
}
|
|
64
|
-
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
/**
|
|
4
|
+
* @sfmc-bds/cli — 离线校验 catalog 与已安装模块包的全局一致性
|
|
5
|
+
*
|
|
6
|
+
* 职责分工边界:
|
|
7
|
+
* - 全局目录一致性:本文件专注于校验 catalog 唯一性(id / configKey)、requires 依赖闭包、以及 catalog.id 与 manifest.id 的严格对齐;
|
|
8
|
+
* - 字段形状校验解耦:模块 manifest 的具体字段结构、版本判定与必填规则完全委托给 SDK 的权威总入口 `validateManifest`,不再在本地重复实现字段形状检查。
|
|
9
|
+
*
|
|
10
|
+
* 用法:
|
|
11
|
+
* node packages/cli/scripts/module-install/check-modules.mjs
|
|
12
|
+
* node …/check-modules.mjs --sync # 先 sync catalog 再执行校验
|
|
13
|
+
*/
|
|
14
|
+
import { validateManifest } from "@sfmc-bds/sdk/module-loader";
|
|
15
|
+
import fs from "node:fs";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
import process from "node:process";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
import { readCatalog, syncCatalogFromPackages } from "./lib/catalog.mjs";
|
|
20
|
+
import { exists } from "./lib/io.mjs";
|
|
21
|
+
import { folderFromEntryPath, scanInstalledPackages } from "./lib/packages.mjs";
|
|
22
|
+
import { ROOT } from "./lib/paths.mjs";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {object} CheckModulesOpts
|
|
26
|
+
* @property {boolean} [sync]
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {object} CheckModulesResult
|
|
31
|
+
* @property {boolean} ok
|
|
32
|
+
* @property {string} [error]
|
|
33
|
+
* @property {string} [summary]
|
|
34
|
+
* @property {string[]} [warnings]
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} moduleRoot
|
|
39
|
+
* @param {string} configKey
|
|
40
|
+
* @returns {{ ok: true; warning?: string } | { ok: false; error: string }}
|
|
41
|
+
*/
|
|
42
|
+
export function validateDefaultConfig(moduleRoot, configKey) {
|
|
43
|
+
const defaultsDir = path.join(moduleRoot, "configs-default");
|
|
44
|
+
const expected = path.join(defaultsDir, `${configKey}.json`);
|
|
45
|
+
if (!exists(expected)) {
|
|
46
|
+
const jsonFiles = exists(defaultsDir)
|
|
47
|
+
? fs.readdirSync(defaultsDir).filter((name) => name.toLowerCase().endsWith(".json"))
|
|
48
|
+
: [];
|
|
49
|
+
if (jsonFiles.length > 0) {
|
|
50
|
+
return {
|
|
51
|
+
ok: false,
|
|
52
|
+
error: `默认配置文件名必须为 configs-default/${configKey}.json,实际为 ${jsonFiles.join(", ")}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return { ok: true, warning: `未提供默认配置 configs-default/${configKey}.json` };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(fs.readFileSync(expected, "utf8"));
|
|
59
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
60
|
+
return { ok: false, error: `默认配置 configs-default/${configKey}.json 顶层必须是 JSON 对象` };
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
return { ok: false, error: `默认配置 configs-default/${configKey}.json 解析失败: ${message}` };
|
|
65
|
+
}
|
|
66
|
+
return { ok: true };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {CheckModulesOpts} [opts]
|
|
71
|
+
* @returns {CheckModulesResult}
|
|
72
|
+
*/
|
|
73
|
+
export function runCheckModules(opts = {}) {
|
|
74
|
+
const doSync = opts.sync ?? false;
|
|
75
|
+
/** @type {string[]} */
|
|
76
|
+
const warnings = [];
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
if (doSync) {
|
|
80
|
+
syncCatalogFromPackages();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const catalog = readCatalog();
|
|
84
|
+
const modules = catalog.modules;
|
|
85
|
+
|
|
86
|
+
if (modules.length === 0) {
|
|
87
|
+
const pkgs = scanInstalledPackages();
|
|
88
|
+
if (pkgs.length > 0) {
|
|
89
|
+
return {
|
|
90
|
+
ok: false,
|
|
91
|
+
error: `catalog 为空但 packages/ 有 ${pkgs.length} 个已装包 — 运行 catalog-sync 或 fetch-module install`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return { ok: true, summary: "check-modules OK (空 catalog,无已装包)" };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const ids = new Set();
|
|
98
|
+
const keys = new Set();
|
|
99
|
+
|
|
100
|
+
for (const m of modules) {
|
|
101
|
+
if (!m.id || typeof m.id !== "string") return { ok: false, error: "条目缺少 id" };
|
|
102
|
+
if (!m.configKey || typeof m.configKey !== "string") return { ok: false, error: `${m.id}: 缺少 configKey` };
|
|
103
|
+
if (ids.has(m.id)) return { ok: false, error: `重复 id: ${m.id}` };
|
|
104
|
+
if (keys.has(m.configKey)) return { ok: false, error: `重复 configKey: ${m.configKey}` };
|
|
105
|
+
ids.add(m.id);
|
|
106
|
+
keys.add(m.configKey);
|
|
107
|
+
|
|
108
|
+
if (!m.entry || !m.entry.path) return { ok: false, error: `${m.id}: 缺少 entry.path` };
|
|
109
|
+
const abs = path.join(ROOT, m.entry.path);
|
|
110
|
+
if (!exists(abs)) return { ok: false, error: `${m.id}: entry 不存在: ${m.entry.path}` };
|
|
111
|
+
|
|
112
|
+
const folder = folderFromEntryPath(m.entry.path);
|
|
113
|
+
if (!folder) return { ok: false, error: `${m.id}: 无法从 entry.path 解析 packages 目录` };
|
|
114
|
+
|
|
115
|
+
const manifestPath = path.join(ROOT, "modules", "packages", folder, "sapi", "manifest.json");
|
|
116
|
+
if (!exists(manifestPath)) return { ok: false, error: `${m.id}: 缺少 manifest.json` };
|
|
117
|
+
|
|
118
|
+
let manifest;
|
|
119
|
+
try {
|
|
120
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
121
|
+
} catch (e) {
|
|
122
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
123
|
+
return { ok: false, error: `${m.id}: manifest 解析失败: ${message}` };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 单个 manifest 字段形状校验:委托 SDK validateManifest 权威入口,本脚本不重复实现字段检查
|
|
127
|
+
const v = validateManifest(manifest);
|
|
128
|
+
if (!v.ok) {
|
|
129
|
+
return { ok: false, error: `${m.id}: manifest 校验未通过 — ${v.errors.join("; ")}` };
|
|
130
|
+
}
|
|
131
|
+
// 校验 catalog 条目与 manifest 实际声明的模块身份(id)严格一致
|
|
132
|
+
if (manifest.id !== m.id) {
|
|
133
|
+
return { ok: false, error: `${m.id}: catalog.id 与 manifest.id(${manifest.id}) 不一致` };
|
|
134
|
+
}
|
|
135
|
+
const defaultConfig = validateDefaultConfig(path.dirname(path.dirname(manifestPath)), manifest.configKey);
|
|
136
|
+
if (!defaultConfig.ok) return { ok: false, error: `${m.id}: ${defaultConfig.error}` };
|
|
137
|
+
if (defaultConfig.warning) warnings.push(`${m.id}: ${defaultConfig.warning}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (const m of modules) {
|
|
141
|
+
const reqs = Array.isArray(m.requires) ? m.requires : [];
|
|
142
|
+
for (const dep of reqs) {
|
|
143
|
+
if (!ids.has(dep)) return { ok: false, error: `${m.id}: requires "${dep}" 不在 catalog 中` };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const pkg of scanInstalledPackages()) {
|
|
148
|
+
if (!ids.has(pkg.manifest.id)) {
|
|
149
|
+
console.warn(
|
|
150
|
+
`[check-modules] WARN: packages/${pkg.folder} (${pkg.manifest.id}) 未入 catalog — 运行 catalog-sync`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return { ok: true, summary: `check-modules OK (${modules.length} modules)`, warnings };
|
|
156
|
+
} catch (e) {
|
|
157
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
158
|
+
return { ok: false, error: message };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function main() {
|
|
163
|
+
const doSync = process.argv.includes("--sync");
|
|
164
|
+
const result = runCheckModules({ sync: doSync });
|
|
165
|
+
if (!result.ok) {
|
|
166
|
+
console.error(`[check-modules] FAIL: ${result.error}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
for (const warning of result.warnings ?? []) {
|
|
170
|
+
console.warn(`[check-modules] WARN: ${warning}`);
|
|
171
|
+
}
|
|
172
|
+
console.log(`[check-modules] ${result.summary}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const __checkModulesMain = fileURLToPath(import.meta.url);
|
|
176
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(__checkModulesMain)) {
|
|
177
|
+
main();
|
|
178
|
+
}
|