@sfmc-bds/cli 0.6.1 → 0.7.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/management/server.ts"],
4
- "sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { EventEmitter } from \"node:events\";\nimport { MANAGEMENT_PROTOCOL_VERSION, type ManagementRequest, type ManagementEvent } from \"@sfmc-bds/management\";\nimport { readQqBindings } from \"@sfmc-bds/db-server/qq-bindings\";\nimport { ROOT, isRuntimeInitialized, spawnService } from \"../runtime.js\";\nimport { queryServicesRuntimeLocal, services, START_ORDER, SERVICE_NAMES, refreshServices, onServiceStateChange, type ServiceName } from \"../services.js\";\nimport { readDiskLogs, onLog } from \"../logs.js\";\nimport { cmdModuleEnable, cmdModuleDisable } from \"../module-commands.js\";\nimport { ensureCoreConfigs } from \"@sfmc-bds/sdk/node/config\";\nimport { TaskStore, atomicJson, type TaskContext } from \"./tasks.js\";\nimport { configFiles, readDocument, revision, saveDocument, validateDocument } from \"./config.js\";\nimport { listModules, searchModules, identifier, runFetch, readJson, listPacks, togglePack, importPack, playerFiles, savePlayerPermissions, modulePlan, applyModulePlan } from \"./domain.js\";\nimport { attachmentPlan, platformVersion, withStoppedServices, launchPlatformUpdate, createBackup, restoreSnapshot, verifyRunning } from \"./maintenance.js\";\nimport { startupPlan } from \"./startup.js\";\nimport { cmdPackBuild, cmdPackDeploy } from \"../pack-lifecycle.js\";\nimport { withMaintenanceLock } from \"@sfmc-bds/management/node\";\nimport { deploymentPreflight, deploymentPort } from \"./deployment.js\";\nimport { resolveBdsContext } from \"../pack-lifecycle.js\";\nimport { readRuntimeMetrics } from \"./metrics-read.js\";\n\nconst events = new EventEmitter();\n/** \u7A7A\u76EE\u5F55\u4E5F\u8981\u80FD\u5B8C\u6210\u63E1\u624B\uFF0C\u4F9B\u684C\u9762\u521D\u59CB\u5316\u5411\u5BFC\u7EE7\u7EED\uFF1B\u65E7\u90E8\u7F72\u4ECD\u8BC6\u522B\u5DF2\u6709 BDS\u3002 */\nfunction deploymentInitialized(): boolean {\n if (isRuntimeInitialized()) return true;\n const config = readJson<{ bds_path?: string }>(path.join(ROOT, \"configs\", \"bds_updater.json\"), {});\n if (!config.bds_path) return false;\n return fs.existsSync(path.join(resolveBdsContext().bdsRoot, process.platform === \"win32\" ? \"bedrock_server.exe\" : \"bedrock_server\"));\n}\nlet tasks: TaskStore | undefined;\nexport function managementTasks() {\n if (!tasks) {\n tasks = new TaskStore(ROOT);\n tasks.on(\"operation\", payload => events.emit(\"event\", { type: \"event\", event: \"operation\", instanceId: ROOT, payload }));\n onLog(log => events.emit(\"event\", { type: \"event\", event: \"log\", instanceId: ROOT, payload: { ...log, time: log.time.toISOString() } }));\n onServiceStateChange(payload => events.emit(\"event\", { type: \"event\", event: \"serviceState\", instanceId: ROOT, payload }));\n }\n return tasks;\n}\nexport function onManagementEvent(callback: (event: ManagementEvent) => void) { events.on(\"event\", callback); return () => events.off(\"event\", callback); }\nfunction params(request: ManagementRequest): Record<string, unknown> {\n if (request.params === undefined) return {};\n if (!request.params || typeof request.params !== \"object\" || Array.isArray(request.params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return request.params as Record<string, unknown>;\n}\nfunction string(value: unknown, label: string) { if (typeof value !== \"string\" || value.length > 2 * 1024 * 1024) throw new Error(`\u975E\u6CD5 ${label}`); return value; }\nfunction service(value: unknown): ServiceName { if (!SERVICE_NAMES.includes(value as ServiceName)) throw new Error(\"\u672A\u77E5\u670D\u52A1\"); return value as ServiceName; }\nasync function rebuildModules() {\n const build = await cmdPackBuild([]); if (!build.ok) throw new Error(build.message);\n const deploy = await cmdPackDeploy([]); if (!deploy.ok) throw new Error(deploy.message);\n return { changed: true };\n}\n\nasync function players() {\n const files = playerFiles(); const allowlist = readJson<unknown[]>(files.allowlist, []);\n const cfg = readJson<{ db_port?: number; http_auth?: string; dbDir?: string }>(path.join(ROOT, \"configs\", \"db_config.json\"), {});\n const database = path.resolve(ROOT, typeof cfg.dbDir === \"string\" && cfg.dbDir.trim() ? cfg.dbDir : \"data/sfmc_data.db\");\n let data: { online?: { name: string }[]; updatedAt?: number } = {};\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/status`, { headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {}, signal: AbortSignal.timeout(5000) });\n if (response.ok) data = await response.json() as typeof data;\n } catch { /* \u672A\u8FDE\u63A5\u65F6\u4F7F\u7528\u672A\u77E5\u72B6\u6001 */ }\n const fresh = typeof data.updatedAt === \"number\" && Date.now() - data.updatedAt < 60_000;\n return { players: (data.online ?? []).map(row => ({ name: row.name, xuid: \"\", online: fresh ? true : null })), updatedAt: data.updatedAt ? new Date(data.updatedAt).toISOString() : \"\", fresh, allowlist, permissions: readJson<unknown[]>(files.permissions, []), sfmcPermissions: readJson<unknown[]>(files.sfmcPermissions, []), bindings: readQqBindings(database) };\n}\nasync function bdsUpdate(context: TaskContext, checkOnly = false) {\n context.phase(\"download\", checkOnly ? \"\u68C0\u67E5 BDS \u66F4\u65B0\" : \"\u66F4\u65B0 BDS\");\n const args = checkOnly ? [\"--check-only\", \"--no-notify\"] : [\"--no-start\", \"--no-notify\"];\n let output = \"\";\n await new Promise<void>((resolve, reject) => {\n const child = spawnService(\"update\", args, { stdio: \"pipe\", cwd: ROOT });\n for (const stream of [child.stdout, child.stderr]) stream?.on(\"data\", chunk => { output = (output + String(chunk)).slice(-64_000); });\n child.on(\"error\", reject); child.on(\"close\", code => code === 0 ? resolve() : reject(new Error(`BDS \u66F4\u65B0\u5931\u8D25 (${code})`)));\n });\n return { checked: checkOnly, updated: /SFMC_UPDATE_RESULT=deployed/.test(output), currentVersion: /CURRENT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", latestVersion: /LATEST=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", result: /SFMC_UPDATE_RESULT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\" };\n}\nexport async function dispatchManagement(request: ManagementRequest): Promise<unknown> {\n const p = params(request); const store = managementTasks();\n switch (request.method) {\n case \"handshake\": return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === \"win32\" ? \"windows\" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: [\"services\", \"logs\", \"modules\", \"config\", \"packs\", \"players\", \"updates\", \"operations\", \"metrics\", \"manual-restart\", \"manual-backup\"], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1000).toISOString(), initialized: deploymentInitialized() };\n case \"events.subscribe\": return { subscribed: true };\n case \"services.list\": return { rows: await queryServicesRuntimeLocal() };\n case \"services.start\": case \"services.stop\": case \"services.restart\": {\n const requestedNames = p.name === \"all\" ? [...START_ORDER] : [service(p.name)];\n const reloadConfig = p.reloadConfig === true;\n if (reloadConfig && (p.name !== \"all\" || request.method !== \"services.restart\")) throw new Error(\"\u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u9700\u8981\u91CD\u542F\u5168\u90E8\u670D\u52A1\");\n return store.submit(request.method, async context => {\n context.phase(\"execute\");\n const rows = await queryServicesRuntimeLocal();\n const names = p.runningOnly === true\n ? requestedNames.filter(name => rows.some(row => row.name === name && row.running))\n : requestedNames;\n if (rows.some(row => names.includes(row.name) && row.running && row.ownership === \"external\") && request.method !== \"services.start\") throw new Error(\"\u5916\u90E8\u8FDB\u7A0B\u65E0\u6CD5\u5B89\u5168\u505C\u6B62\uFF0C\u8BF7\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u64CD\u4F5C\");\n if (request.method !== \"services.start\") for (const name of [...names].reverse()) await services[name].stop(false, false);\n if (reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (after.some(row => requestedNames.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u914D\u7F6E\u5237\u65B0\");\n refreshServices();\n }\n if (request.method !== \"services.stop\") {\n if (!reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (request.method === \"services.restart\" && after.some(row => names.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u91CD\u542F\");\n const stopped = names.filter(name => !after.some(row => row.name === name && row.running));\n if (stopped.length) refreshServices(stopped);\n }\n const outcomes = [];\n for (const name of names) outcomes.push({ name, ...(await services[name].start()) });\n await verifyRunning(outcomes.filter(row => row.status !== \"skipped\").map(row => row.name));\n return { outcomes };\n }\n return { stopped: names };\n });\n }\n case \"services.send\": {\n const name = service(p.name); const message = string(p.message, \"\u547D\u4EE4\");\n if (/[\\r\\n]/.test(message) || !message.trim()) throw new Error(\"\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4\");\n const target = services[name]; if (!target.proc?.stdin || !target.running) throw new Error(\"\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053\");\n return withMaintenanceLock(ROOT, async () => { target.proc!.stdin!.write(message + \"\\n\"); return { delivered: true }; });\n }\n case \"logs.tail\": return { entries: readDiskLogs({ limit: Math.min(5000, Math.max(1, Number(p.limit) || 1000)), ...(Array.isArray(p.sources) ? { sources: p.sources.map(value => string(value, \"\u65E5\u5FD7\u6765\u6E90\")) } : {}), ...(Array.isArray(p.levels) ? { levels: p.levels as (\"info\" | \"warn\" | \"error\")[] } : {}) }).map(log => ({ ...log, time: log.time.toISOString() })) };\n case \"operations.list\": return { operations: store.list().filter(row => !Array.isArray(p.statuses) || p.statuses.includes(row.status)).slice(0, Math.min(Number(p.limit) || 100, 200)) };\n case \"operations.get\": return { operation: store.get(string(p.operationId, \"\u4EFB\u52A1\u7F16\u53F7\")) };\n case \"modules.list\": return listModules();\n case \"modules.search\": return searchModules(typeof p.query === \"string\" ? p.query : \"\");\n case \"modules.install\": {\n const id = identifier(p.id);\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n return store.submit(request.method, async context => {\n context.phase(\"download\", \"\u4E0B\u8F7D\u5E76\u5B89\u88C5\u6A21\u5757\uFF0C\u670D\u52A1\u5668\u4FDD\u6301\u8FD0\u884C\");\n const args = [\"install\", id];\n if (typeof p.source === \"string\" && p.source) args.push(\"--from\", p.source);\n await runFetch(args);\n context.phase(\"execute\", \"\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"modules.uninstall\": case \"modules.toggle\": {\n const id = identifier(p.id);\n if (request.method !== \"modules.toggle\") {\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n }\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u66F4\u65B0\u6A21\u5757\u5E76\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n if (request.method === \"modules.toggle\") {\n const result = await (p.enabled === true ? cmdModuleEnable([id]) : cmdModuleDisable([id])); if (!result.ok) throw new Error(result.message);\n } else {\n await runFetch([\"uninstall\", id]);\n }\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"config.list\": return { keys: [...configFiles().keys()] };\n case \"config.read\": return readDocument(string(p.key, \"\u914D\u7F6E\u540D\u79F0\"));\n case \"config.save\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u914D\u7F6E\u6587\u4EF6\uFF0C\u4E0D\u91CD\u542F\u670D\u52A1\");\n saveDocument(key, expected, text);\n return { saved: true, revision: revision(text), restartRequired: true };\n });\n }\n case \"config.apply\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n let saved = false;\n try { return await withStoppedServices(context, [...START_ORDER], async () => {\n saveDocument(key, expected, text); context.phase(\"apply\", \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u5E94\u7528\u8FD0\u884C\u914D\u7F6E\");\n saved = true;\n refreshServices(); return { saved: true, revision: readDocument(key).revision, applied: true };\n }); } catch (error) { throw Object.assign(new Error(`${saved ? \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u8FD0\u884C\u65F6\u5E94\u7528\u5931\u8D25\" : \"\u914D\u7F6E\u672A\u4FDD\u5B58\"}: ${error instanceof Error ? error.message : String(error)}`), { code: \"io\", details: { saved, applied: false } }); }\n });\n }\n case \"packs.list\": return listPacks();\n case \"packs.import\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5BFC\u5165\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return importPack(identifier(p.filename));\n });\n case \"packs.toggle\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u4E16\u754C\u5305\u72B6\u6001\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return togglePack(identifier(p.id), p.enabled === true);\n });\n case \"players.list\": return players();\n case \"metrics.read\": return readRuntimeMetrics(request.params);\n case \"players.apply\": return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => savePlayerPermissions(string(p.kind, \"\u6743\u9650\u7C7B\u578B\"), p.entries)));\n case \"attachment.plan\": return attachmentPlan();\n case \"attachment.apply\": return store.submit(request.method, async context => {\n const plan = await attachmentPlan(false);\n if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" });\n if (plan.externalServices.length) throw new Error(\"\u65E0\u6CD5\u53EF\u9760\u8FC1\u79FB\u5916\u90E8\u8FDB\u7A0B\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u4F18\u96C5\u505C\u670D\");\n if (plan.upgradeRequired) return launchPlatformUpdate(store, context, plan.targetVersion);\n return { attached: true, version: plan.currentVersion, development: plan.development };\n });\n case \"updates.check\": {\n const results = await Promise.allSettled([attachmentPlan(), modulePlan(), bdsUpdate({ id: \"check\", phase: () => {} }, true)]);\n return Object.fromEntries(results.map((result, index) => [[\"platform\", \"modules\", \"bds\"][index], result.status === \"fulfilled\" ? result.value : { error: String(result.reason) }]));\n }\n case \"updates.run\": {\n if (p.kind === \"platform\") return store.submit(request.method, async context => { const plan = await attachmentPlan(false); if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" }); return plan.upgradeRequired ? launchPlatformUpdate(store, context, plan.targetVersion) : { upToDate: true, version: plan.currentVersion }; });\n if (p.kind === \"modules\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => { const result = await applyModulePlan(Array.isArray(p.ids) ? p.ids.map(identifier) : []); await rebuildModules(); return result; }));\n if (p.kind === \"bds\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => bdsUpdate(context)));\n throw new Error(\"\u672A\u77E5\u66F4\u65B0\u7C7B\u578B\");\n }\n case \"deployment.create\": {\n if (p.acceptEula !== true) throw new Error(\"\u521B\u5EFA\u90E8\u7F72\u524D\u5FC5\u987B\u786E\u8BA4 BDS \u4F7F\u7528\u6761\u6B3E\");\n return store.submit(request.method, async context => {\n if (isRuntimeInitialized()) throw new Error(\"\u76EE\u5F55\u5DF2\u7ECF\u521D\u59CB\u5316\uFF0C\u4E0D\u8986\u76D6\u5DF2\u6709\u90E8\u7F72\");\n const ports = { db: deploymentPort(p.dbPort, 3001), bds: deploymentPort(p.bdsPort, 19132), bds6: deploymentPort(p.bdsPort6, 19133) };\n context.phase(\"preflight\", \"\u68C0\u67E5\u76EE\u5F55\u3001\u78C1\u76D8\u7A7A\u95F4\u548C TCP\uFF0FUDP \u7AEF\u53E3\"); await deploymentPreflight(ports);\n context.phase(\"prepare\"); ensureCoreConfigs(ROOT, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\", \"qq_link\"]);\n const updater = path.join(ROOT, \"configs\", \"bds_updater.json\");\n atomicJson(updater, { ...readJson(updater, {}), bds_path: \"BDS\", backup_dir: \"backups\" });\n const dbFile = path.join(ROOT, \"configs\", \"db_config.json\"); atomicJson(dbFile, { ...readJson(dbFile, {}), db_port: ports.db });\n fs.mkdirSync(path.join(ROOT, \"modules\", \"packages\"), { recursive: true });\n await bdsUpdate(context);\n const properties = path.join(ROOT, \"BDS\", \"server.properties\");\n let text = fs.readFileSync(properties, \"utf8\");\n for (const [key, port] of [[\"server-port\", ports.bds], [\"server-portv6\", ports.bds6]] as const) text = text.replace(new RegExp(`^${key}=.*$`, \"m\"), `${key}=${port}`);\n fs.writeFileSync(properties, text);\n await rebuildModules();\n refreshServices(); context.phase(\"start\");\n const started: ServiceName[] = [];\n try { for (const name of START_ORDER) { const result = await services[name].start(); if (result.status !== \"skipped\") started.push(name); } await verifyRunning(started); }\n catch (error) { for (const name of [...START_ORDER].reverse()) await services[name].stop(false, false).catch(() => {}); throw error; }\n atomicJson(path.join(ROOT, \"configs\", \"runtime.json\"), { ...readJson(path.join(ROOT, \"configs\", \"runtime.json\"), {}), initialized_at: new Date().toISOString() });\n return { created: true, rows: await queryServicesRuntimeLocal() };\n });\n }\n case \"backups.list\": { const directory = path.join(ROOT, \".sfmc\", \"backups\"); return { backups: fs.existsSync(directory) ? fs.readdirSync(directory).filter(id => fs.existsSync(path.join(directory, id, \"manifest.json\"))) : [] }; }\n case \"backups.create\": return store.submit(request.method, context => createBackup(context));\n case \"backups.restore\": {\n if (p.confirmDataLoss !== true) throw new Error(\"\u6062\u590D\u6570\u636E\u9700\u8981\u660E\u786E\u786E\u8BA4\u4E22\u5F03\u5907\u4EFD\u4E4B\u540E\u7684\u53D8\u66F4\");\n return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => restoreSnapshot(identifier(p.id), context.phase)));\n }\n case \"startup.plan\": return startupPlan();\n default: throw Object.assign(new Error(`\u4E0D\u652F\u6301\u7684\u7BA1\u7406\u65B9\u6CD5: ${request.method}`), { code: \"unsupported\" });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { EventEmitter } from \"node:events\";\nimport { LOG_TAIL_MAX, MANAGEMENT_PROTOCOL_VERSION, type ManagementRequest, type ManagementEvent } from \"@sfmc-bds/management\";\nimport { readQqBindings } from \"@sfmc-bds/db-server/qq-bindings\";\nimport { ROOT, isRuntimeInitialized, spawnService } from \"../runtime.js\";\nimport { queryServicesRuntimeLocal, services, START_ORDER, SERVICE_NAMES, refreshServices, onServiceStateChange, type ServiceName } from \"../services.js\";\nimport { readDiskLogs, deleteStoredLogs, onLog } from \"../logs.js\";\nimport { cmdModuleEnable, cmdModuleDisable } from \"../module-commands.js\";\nimport { ensureCoreConfigs } from \"@sfmc-bds/sdk/node/config\";\nimport { TaskStore, atomicJson, type TaskContext } from \"./tasks.js\";\nimport { configFiles, readDocument, revision, saveDocument, validateDocument } from \"./config.js\";\nimport { listModules, searchModules, identifier, runFetch, readJson, listPacks, togglePack, readPackIcon, uninstallPack, setPackVersion, playerFiles, savePlayerPermissions, modulePlan, applyModulePlan, moduleInstallBlock } from \"./domain.js\";\nimport { attachmentPlan, platformVersion, withStoppedServices, launchPlatformUpdate, createBackup, restoreSnapshot, deleteSnapshot, verifyRunning } from \"./maintenance.js\";\nimport { startupPlan } from \"./startup.js\";\nimport { cmdPackBuild, cmdPackDeploy } from \"../pack-lifecycle.js\";\nimport { withMaintenanceLock } from \"@sfmc-bds/management/node\";\nimport { deploymentPreflight, deploymentPort } from \"./deployment.js\";\nimport { resolveBdsContext } from \"../pack-lifecycle.js\";\nimport { readRuntimeMetrics } from \"./metrics-read.js\";\n\nimport { importPacks, planPackImport, readImportFilenames } from \"./pack-import.js\";\n\nconst events = new EventEmitter();\n/** \u7A7A\u76EE\u5F55\u4E5F\u8981\u80FD\u5B8C\u6210\u63E1\u624B\uFF0C\u4F9B\u684C\u9762\u521D\u59CB\u5316\u5411\u5BFC\u7EE7\u7EED\uFF1B\u65E7\u90E8\u7F72\u4ECD\u8BC6\u522B\u5DF2\u6709 BDS\u3002 */\nfunction deploymentInitialized(): boolean {\n if (isRuntimeInitialized()) return true;\n const config = readJson<{ bds_path?: string }>(path.join(ROOT, \"configs\", \"bds_updater.json\"), {});\n if (!config.bds_path) return false;\n return fs.existsSync(path.join(resolveBdsContext().bdsRoot, process.platform === \"win32\" ? \"bedrock_server.exe\" : \"bedrock_server\"));\n}\nlet tasks: TaskStore | undefined;\nexport function managementTasks() {\n if (!tasks) {\n tasks = new TaskStore(ROOT);\n tasks.on(\"operation\", payload => events.emit(\"event\", { type: \"event\", event: \"operation\", instanceId: ROOT, payload }));\n onLog(log => events.emit(\"event\", { type: \"event\", event: \"log\", instanceId: ROOT, payload: { ...log, time: log.time.toISOString() } }));\n onServiceStateChange(payload => events.emit(\"event\", { type: \"event\", event: \"serviceState\", instanceId: ROOT, payload }));\n }\n return tasks;\n}\nexport function onManagementEvent(callback: (event: ManagementEvent) => void) { events.on(\"event\", callback); return () => events.off(\"event\", callback); }\nfunction params(request: ManagementRequest): Record<string, unknown> {\n if (request.params === undefined) return {};\n if (!request.params || typeof request.params !== \"object\" || Array.isArray(request.params)) throw new Error(\"\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61\");\n return request.params as Record<string, unknown>;\n}\nfunction string(value: unknown, label: string) { if (typeof value !== \"string\" || value.length > 2 * 1024 * 1024) throw new Error(`\u975E\u6CD5 ${label}`); return value; }\n/** \u89E3\u6790\u65E5\u5FD7\u67E5\u8BE2\u7528\u7684 ISO \u65F6\u95F4\u3002\u7F3A\u7701\u8FD4\u56DE undefined\u3002 */\nfunction timeBound(value: unknown, label: string): Date | undefined {\n if (value === undefined) return undefined;\n const date = new Date(string(value, label));\n if (Number.isNaN(date.getTime())) throw new Error(`\u975E\u6CD5 ${label}`);\n return date;\n}\nfunction service(value: unknown): ServiceName { if (!SERVICE_NAMES.includes(value as ServiceName)) throw new Error(\"\u672A\u77E5\u670D\u52A1\"); return value as ServiceName; }\nasync function rebuildModules() {\n const build = await cmdPackBuild([]); if (!build.ok) throw new Error(build.message);\n const deploy = await cmdPackDeploy([]); if (!deploy.ok) throw new Error(deploy.message);\n return { changed: true };\n}\n\nasync function players() {\n const files = playerFiles(); const allowlist = readJson<unknown[]>(files.allowlist, []);\n const cfg = readJson<{ db_port?: number; http_auth?: string; dbDir?: string }>(path.join(ROOT, \"configs\", \"db_config.json\"), {});\n const database = path.resolve(ROOT, typeof cfg.dbDir === \"string\" && cfg.dbDir.trim() ? cfg.dbDir : \"data/sfmc_data.db\");\n let data: { online?: { name: string }[]; updatedAt?: number } = {};\n try {\n const response = await fetch(`http://127.0.0.1:${cfg.db_port ?? 3001}/api/sfmc/status`, { headers: cfg.http_auth ? { authorization: `Bearer ${cfg.http_auth}` } : {}, signal: AbortSignal.timeout(5000) });\n if (response.ok) data = await response.json() as typeof data;\n } catch { /* \u672A\u8FDE\u63A5\u65F6\u4F7F\u7528\u672A\u77E5\u72B6\u6001 */ }\n const fresh = typeof data.updatedAt === \"number\" && Date.now() - data.updatedAt < 60_000;\n return { players: (data.online ?? []).map(row => ({ name: row.name, xuid: \"\", online: fresh ? true : null })), updatedAt: data.updatedAt ? new Date(data.updatedAt).toISOString() : \"\", fresh, allowlist, permissions: readJson<unknown[]>(files.permissions, []), sfmcPermissions: readJson<unknown[]>(files.sfmcPermissions, []), bindings: readQqBindings(database) };\n}\nasync function bdsUpdate(context: TaskContext, checkOnly = false) {\n context.phase(\"download\", checkOnly ? \"\u68C0\u67E5 BDS \u66F4\u65B0\" : \"\u66F4\u65B0 BDS\");\n const args = checkOnly ? [\"--check-only\", \"--no-notify\"] : [\"--no-start\", \"--no-notify\"];\n let output = \"\";\n await new Promise<void>((resolve, reject) => {\n const child = spawnService(\"update\", args, { stdio: \"pipe\", cwd: ROOT });\n for (const stream of [child.stdout, child.stderr]) stream?.on(\"data\", chunk => { output = (output + String(chunk)).slice(-64_000); });\n child.on(\"error\", reject); child.on(\"close\", code => code === 0 ? resolve() : reject(new Error(`BDS \u66F4\u65B0\u5931\u8D25 (${code})`)));\n });\n return { checked: checkOnly, updated: /SFMC_UPDATE_RESULT=deployed/.test(output), currentVersion: /CURRENT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", latestVersion: /LATEST=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\", result: /SFMC_UPDATE_RESULT=([^\\r\\n]+)/.exec(output)?.[1] ?? \"unknown\" };\n}\nexport async function dispatchManagement(request: ManagementRequest): Promise<unknown> {\n const p = params(request); const store = managementTasks();\n switch (request.method) {\n case \"handshake\": return { protocolVersion: MANAGEMENT_PROTOCOL_VERSION, platformVersion: platformVersion(), host: { os: process.platform === \"win32\" ? \"windows\" : process.platform, arch: process.arch, release: os.release() }, root: ROOT, capabilities: [\"services\", \"logs\", \"logs-range\", \"modules\", \"config\", \"packs\", \"players\", \"updates\", \"operations\", \"metrics\", \"manual-restart\", \"manual-backup\", \"pack-import-plan\", \"pack-icons\", \"pack-uninstall\", \"backup-delete\", \"pack-import-batch\", \"pack-version\"], daemonPid: process.pid, daemonStartedAt: new Date(Date.now() - process.uptime() * 1000).toISOString(), initialized: deploymentInitialized() };\n case \"events.subscribe\": return { subscribed: true };\n case \"services.list\": return { rows: await queryServicesRuntimeLocal() };\n case \"services.start\": case \"services.stop\": case \"services.restart\": {\n const requestedNames = p.name === \"all\" ? [...START_ORDER] : [service(p.name)];\n const reloadConfig = p.reloadConfig === true;\n if (reloadConfig && (p.name !== \"all\" || request.method !== \"services.restart\")) throw new Error(\"\u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u9700\u8981\u91CD\u542F\u5168\u90E8\u670D\u52A1\");\n return store.submit(request.method, async context => {\n context.phase(\"execute\");\n const rows = await queryServicesRuntimeLocal();\n const names = p.runningOnly === true\n ? requestedNames.filter(name => rows.some(row => row.name === name && row.running))\n : requestedNames;\n if (rows.some(row => names.includes(row.name) && row.running && row.ownership === \"external\") && request.method !== \"services.start\") throw new Error(\"\u5916\u90E8\u8FDB\u7A0B\u65E0\u6CD5\u5B89\u5168\u505C\u6B62\uFF0C\u8BF7\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u64CD\u4F5C\");\n if (request.method !== \"services.start\") for (const name of [...names].reverse()) await services[name].stop(false, false);\n if (reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (after.some(row => requestedNames.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u914D\u7F6E\u5237\u65B0\");\n refreshServices();\n }\n if (request.method !== \"services.stop\") {\n if (!reloadConfig) {\n const after = await queryServicesRuntimeLocal();\n if (request.method === \"services.restart\" && after.some(row => names.includes(row.name) && row.running)) throw new Error(\"\u670D\u52A1\u672A\u5B8C\u5168\u9000\u51FA\uFF0C\u5DF2\u4E2D\u6B62\u91CD\u542F\");\n const stopped = names.filter(name => !after.some(row => row.name === name && row.running));\n if (stopped.length) refreshServices(stopped);\n }\n const outcomes = [];\n for (const name of names) outcomes.push({ name, ...(await services[name].start()) });\n await verifyRunning(outcomes.filter(row => row.status !== \"skipped\").map(row => row.name));\n return { outcomes };\n }\n return { stopped: names };\n });\n }\n case \"services.send\": {\n const name = service(p.name); const message = string(p.message, \"\u547D\u4EE4\");\n if (/[\\r\\n]/.test(message) || !message.trim()) throw new Error(\"\u4E00\u6B21\u53EA\u80FD\u53D1\u9001\u4E00\u884C\u547D\u4EE4\");\n const target = services[name]; if (!target.proc?.stdin || !target.running) throw new Error(\"\u670D\u52A1\u672A\u6258\u7BA1\u6216\u6CA1\u6709\u547D\u4EE4\u8F93\u5165\u901A\u9053\");\n return withMaintenanceLock(ROOT, async () => { target.proc!.stdin!.write(message + \"\\n\"); return { delivered: true }; });\n }\n case \"logs.tail\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (since && until && until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const limit = Math.min(LOG_TAIL_MAX, Math.max(1, Number(p.limit) || 1000));\n const ranged = Boolean(since || until);\n const entries = readDiskLogs({\n ...(ranged ? {} : { limit }),\n ...(since ? { since } : {}),\n ...(until ? { until } : {}),\n ...(Array.isArray(p.sources) ? { sources: p.sources.map(value => string(value, \"\u65E5\u5FD7\u6765\u6E90\")) } : {}),\n ...(Array.isArray(p.levels) ? { levels: p.levels as (\"info\" | \"warn\" | \"error\")[] } : {}),\n });\n const truncated = entries.length > limit;\n return { entries: (truncated ? entries.slice(entries.length - limit) : entries).map(log => ({ ...log, time: log.time.toISOString() })), ...(truncated ? { truncated: true } : {}) };\n }\n case \"logs.delete\": {\n const since = timeBound(p.since, \"\u5F00\u59CB\u65F6\u95F4\");\n const until = timeBound(p.until, \"\u7ED3\u675F\u65F6\u95F4\");\n if (!since || !until) throw new Error(\"\u5220\u9664\u65E5\u5FD7\u9700\u8981\u5F00\u59CB\u548C\u7ED3\u675F\u65F6\u95F4\");\n if (until < since) throw new Error(\"\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4\");\n const source = p.source === undefined ? undefined : string(p.source, \"\u65E5\u5FD7\u6765\u6E90\");\n if (source !== undefined && (source.length > 128 || /[\\r\\n]/.test(source))) throw new Error(\"\u975E\u6CD5\u65E5\u5FD7\u6765\u6E90\");\n const text = p.text === undefined ? undefined : string(p.text, \"\u65E5\u5FD7\u6B63\u6587\");\n return deleteStoredLogs({ since, until, ...(source === undefined ? {} : { source }), ...(text === undefined ? {} : { text }) });\n }\n case \"operations.list\": return { operations: store.list().filter(row => !Array.isArray(p.statuses) || p.statuses.includes(row.status)).slice(0, Math.min(Number(p.limit) || 100, 200)) };\n case \"operations.get\": return { operation: store.get(string(p.operationId, \"\u4EFB\u52A1\u7F16\u53F7\")) };\n case \"modules.list\": return listModules();\n case \"modules.search\": return searchModules(typeof p.query === \"string\" ? p.query : \"\");\n case \"modules.install\": {\n const id = identifier(p.id);\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n const block = await moduleInstallBlock(id);\n if (block) throw new Error(block);\n return store.submit(request.method, async context => {\n context.phase(\"download\", \"\u4E0B\u8F7D\u5E76\u5B89\u88C5\u6A21\u5757\uFF0C\u670D\u52A1\u5668\u4FDD\u6301\u8FD0\u884C\");\n const args = [\"install\", id];\n if (typeof p.source === \"string\" && p.source) args.push(\"--from\", p.source);\n await runFetch(args);\n context.phase(\"execute\", \"\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"modules.uninstall\": case \"modules.toggle\": {\n const id = identifier(p.id);\n if (request.method !== \"modules.toggle\") {\n const linked = (await listModules()).modules.find(row => row.id === id || row.folder === id)?.linked;\n if (linked) throw new Error(\"\u4FDD\u7559\u672C\u5730\u94FE\u63A5\u6A21\u5757\uFF0C\u4E0D\u901A\u8FC7\u5305\u5B89\u88C5\u6216\u5378\u8F7D\u8986\u76D6\u5F00\u53D1\u76EE\u5F55\");\n }\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u66F4\u65B0\u6A21\u5757\u5E76\u91CD\u5EFA\u884C\u4E3A\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n if (request.method === \"modules.toggle\") {\n const result = await (p.enabled === true ? cmdModuleEnable([id]) : cmdModuleDisable([id])); if (!result.ok) throw new Error(result.message);\n } else {\n await runFetch([\"uninstall\", id]);\n }\n return { ...(await rebuildModules()), restartRequired: true };\n });\n }\n case \"config.list\": return { keys: [...configFiles().keys()] };\n case \"config.read\": return readDocument(string(p.key, \"\u914D\u7F6E\u540D\u79F0\"));\n case \"config.save\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u914D\u7F6E\u6587\u4EF6\uFF0C\u4E0D\u91CD\u542F\u670D\u52A1\");\n saveDocument(key, expected, text);\n return { saved: true, revision: revision(text), restartRequired: true };\n });\n }\n case \"config.apply\": {\n const key = string(p.key, \"\u914D\u7F6E\u540D\u79F0\"); const text = string(p.text, \"\u914D\u7F6E\u5185\u5BB9\"); const expected = string(p.revision, \"\u914D\u7F6E\u7248\u672C\");\n const document = readDocument(key); validateDocument(document, text);\n if (document.revision !== expected) throw Object.assign(new Error(\"\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\"), { code: \"conflict\" });\n return store.submit(request.method, async context => {\n let saved = false;\n try { return await withStoppedServices(context, [...START_ORDER], async () => {\n saveDocument(key, expected, text); context.phase(\"apply\", \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u5E94\u7528\u8FD0\u884C\u914D\u7F6E\");\n saved = true;\n refreshServices(); return { saved: true, revision: readDocument(key).revision, applied: true };\n }); } catch (error) { throw Object.assign(new Error(`${saved ? \"\u6587\u4EF6\u5DF2\u4FDD\u5B58\uFF0C\u8FD0\u884C\u65F6\u5E94\u7528\u5931\u8D25\" : \"\u914D\u7F6E\u672A\u4FDD\u5B58\"}: ${error instanceof Error ? error.message : String(error)}`), { code: \"io\", details: { saved, applied: false } }); }\n });\n }\n case \"packs.list\": return listPacks();\n case \"packs.icon\": return readPackIcon(identifier(p.id));\n case \"packs.import.plan\": return planPackImport(identifier(p.filename));\n case \"packs.import\": {\n const names = readImportFilenames(p);\n return store.submit(request.method, async context => {\n context.phase(\"execute\", names.length > 1 ? `\u5BFC\u5165 ${names.length} \u4E2A\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS` : \"\u5BFC\u5165\u4E16\u754C\u5305\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return importPacks(names, { force: p.force === true, ...(p.revision === undefined ? {} : { revision: string(p.revision, \"\u5BFC\u5165\u8BA1\u5212\u7248\u672C\") }) });\n });\n }\n case \"packs.toggle\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u4FDD\u5B58\u4E16\u754C\u5305\u72B6\u6001\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return togglePack(identifier(p.id), p.enabled === true);\n });\n case \"packs.uninstall\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5378\u8F7D\u4E16\u754C\u5305\u5E76\u79FB\u5165\u56DE\u6536\u7AD9\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return uninstallPack(identifier(p.id));\n });\n case \"packs.version\": {\n const id = identifier(p.id);\n const version = p.version;\n return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5199\u5165\u8D44\u6E90\u5305\u7248\u672C\uFF0C\u7B49\u5F85\u624B\u52A8\u91CD\u542F BDS\");\n return setPackVersion(id, version);\n });\n }\n case \"players.list\": return players();\n case \"metrics.read\": return readRuntimeMetrics(request.params);\n case \"players.apply\": return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => savePlayerPermissions(string(p.kind, \"\u6743\u9650\u7C7B\u578B\"), p.entries)));\n case \"attachment.plan\": return attachmentPlan();\n case \"attachment.apply\": return store.submit(request.method, async context => {\n const plan = await attachmentPlan(false);\n if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" });\n if (plan.externalServices.length) throw new Error(\"\u65E0\u6CD5\u53EF\u9760\u8FC1\u79FB\u5916\u90E8\u8FDB\u7A0B\uFF1B\u8BF7\u5148\u901A\u8FC7\u539F\u7BA1\u7406\u5668\u4F18\u96C5\u505C\u670D\");\n if (plan.upgradeRequired) return launchPlatformUpdate(store, context, plan.targetVersion);\n return { attached: true, version: plan.currentVersion, development: plan.development };\n });\n case \"updates.check\": {\n const results = await Promise.allSettled([attachmentPlan(), modulePlan(), bdsUpdate({ id: \"check\", phase: () => {} }, true)]);\n return Object.fromEntries(results.map((result, index) => [[\"platform\", \"modules\", \"bds\"][index], result.status === \"fulfilled\" ? result.value : { error: String(result.reason) }]));\n }\n case \"updates.run\": {\n if (p.kind === \"platform\") return store.submit(request.method, async context => { const plan = await attachmentPlan(false); if (p.targetVersion !== undefined && p.targetVersion !== plan.targetVersion) throw Object.assign(new Error(\"\u76EE\u6807\u7248\u672C\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0\u65E5\u5FD7\u540E\u786E\u8BA4\"), { code: \"conflict\" }); return plan.upgradeRequired ? launchPlatformUpdate(store, context, plan.targetVersion) : { upToDate: true, version: plan.currentVersion }; });\n if (p.kind === \"modules\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], async () => { const result = await applyModulePlan(Array.isArray(p.ids) ? p.ids.map(identifier) : []); await rebuildModules(); return result; }));\n if (p.kind === \"bds\") return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => bdsUpdate(context)));\n throw new Error(\"\u672A\u77E5\u66F4\u65B0\u7C7B\u578B\");\n }\n case \"deployment.create\": {\n if (p.acceptEula !== true) throw new Error(\"\u521B\u5EFA\u90E8\u7F72\u524D\u5FC5\u987B\u786E\u8BA4 BDS \u4F7F\u7528\u6761\u6B3E\");\n return store.submit(request.method, async context => {\n if (isRuntimeInitialized()) throw new Error(\"\u76EE\u5F55\u5DF2\u7ECF\u521D\u59CB\u5316\uFF0C\u4E0D\u8986\u76D6\u5DF2\u6709\u90E8\u7F72\");\n const ports = { db: deploymentPort(p.dbPort, 3001), bds: deploymentPort(p.bdsPort, 19132), bds6: deploymentPort(p.bdsPort6, 19133) };\n context.phase(\"preflight\", \"\u68C0\u67E5\u76EE\u5F55\u3001\u78C1\u76D8\u7A7A\u95F4\u548C TCP\uFF0FUDP \u7AEF\u53E3\"); await deploymentPreflight(ports);\n context.phase(\"prepare\"); ensureCoreConfigs(ROOT, [\"db_config\", \"qq_config\", \"bds_updater\", \"permissions\", \"qq_link\"]);\n const updater = path.join(ROOT, \"configs\", \"bds_updater.json\");\n atomicJson(updater, { ...readJson(updater, {}), bds_path: \"BDS\", backup_dir: \"backups\" });\n const dbFile = path.join(ROOT, \"configs\", \"db_config.json\"); atomicJson(dbFile, { ...readJson(dbFile, {}), db_port: ports.db });\n fs.mkdirSync(path.join(ROOT, \"modules\", \"packages\"), { recursive: true });\n await bdsUpdate(context);\n const properties = path.join(ROOT, \"BDS\", \"server.properties\");\n let text = fs.readFileSync(properties, \"utf8\");\n for (const [key, port] of [[\"server-port\", ports.bds], [\"server-portv6\", ports.bds6]] as const) text = text.replace(new RegExp(`^${key}=.*$`, \"m\"), `${key}=${port}`);\n fs.writeFileSync(properties, text);\n await rebuildModules();\n refreshServices(); context.phase(\"start\");\n const started: ServiceName[] = [];\n try { for (const name of START_ORDER) { const result = await services[name].start(); if (result.status !== \"skipped\") started.push(name); } await verifyRunning(started); }\n catch (error) { for (const name of [...START_ORDER].reverse()) await services[name].stop(false, false).catch(() => {}); throw error; }\n atomicJson(path.join(ROOT, \"configs\", \"runtime.json\"), { ...readJson(path.join(ROOT, \"configs\", \"runtime.json\"), {}), initialized_at: new Date().toISOString() });\n return { created: true, rows: await queryServicesRuntimeLocal() };\n });\n }\n case \"backups.list\": { const directory = path.join(ROOT, \".sfmc\", \"backups\"); return { backups: fs.existsSync(directory) ? fs.readdirSync(directory).filter(id => fs.existsSync(path.join(directory, id, \"manifest.json\"))) : [] }; }\n case \"backups.create\": return store.submit(request.method, context => createBackup(context));\n case \"backups.restore\": {\n if (p.confirmDataLoss !== true) throw new Error(\"\u6062\u590D\u6570\u636E\u9700\u8981\u660E\u786E\u786E\u8BA4\u4E22\u5F03\u5907\u4EFD\u4E4B\u540E\u7684\u53D8\u66F4\");\n return store.submit(request.method, context => withStoppedServices(context, [...START_ORDER], () => restoreSnapshot(identifier(p.id), context.phase)));\n }\n case \"backups.delete\": return store.submit(request.method, async context => {\n context.phase(\"execute\", \"\u5220\u9664\u5907\u4EFD\u76EE\u5F55\");\n return deleteSnapshot(identifier(p.id));\n });\n case \"startup.plan\": return startupPlan();\n default: throw Object.assign(new Error(`\u4E0D\u652F\u6301\u7684\u7BA1\u7406\u65B9\u6CD5: ${request.method}`), { code: \"unsupported\" });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -19,13 +19,19 @@ export interface RegistryEntry {
19
19
  sdk?: string;
20
20
  repo?: string;
21
21
  tag?: string;
22
+ /** 索引里的展示名。旧缓存可能没有。 */
23
+ name?: string;
24
+ description?: string;
25
+ category?: string;
26
+ license?: string;
27
+ official?: boolean;
28
+ /**
29
+ * 安装前必须已经启用的模块 id。
30
+ * 字段缺失表示这份索引没有声明依赖,调用方应拒绝安装。
31
+ */
32
+ requires?: string[];
22
33
  }
23
34
  export type RegistryIndex = Record<string, RegistryEntry>;
24
- /**
25
- * 解析 first-party index.json。
26
- * 契约与 scripts/module-install/lib/registry-index.mjs#parseRegistryIndex 保持一致:
27
- * `{ modules: { <id>: { npm? | repo+tag } } }`。忽略 `_` 前缀元数据键。
28
- */
29
35
  export declare function parseRegistryIndex(json: unknown): RegistryIndex;
30
36
  export interface RegistryResult {
31
37
  index: RegistryIndex;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,QAAA,MAAM,qBAAqB,yBAAyB,CAAC;AACrD,QAAA,MAAM,oBAAoB,SAAS,CAAC;AAGpC,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AACD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAyB1D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CA8B/D;AAWD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB9F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAIpD;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQlF;AAED,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,QAAA,MAAM,qBAAqB,yBAAyB,CAAC;AACrD,QAAA,MAAM,oBAAoB,SAAS,CAAC;AAGpC,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AACD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AA8C1D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CA2C/D;AAWD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB9F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAIpD;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQlF;AAED,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
package/dist/registry.js CHANGED
@@ -23,6 +23,18 @@ function writeCache(cache) {
23
23
  } catch {
24
24
  }
25
25
  }
26
+ function optionalText(value) {
27
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
28
+ }
29
+ function optionalRequires(value) {
30
+ if (!Array.isArray(value)) return void 0;
31
+ const items = [];
32
+ for (const item of value) {
33
+ if (typeof item !== "string" || !item.trim()) return void 0;
34
+ items.push(item.trim());
35
+ }
36
+ return items;
37
+ }
26
38
  function parseRegistryIndex(json) {
27
39
  if (typeof json !== "object" || json === null || Array.isArray(json)) {
28
40
  throw new Error("registry index must be a JSON object with a 'modules' field");
@@ -37,19 +49,31 @@ function parseRegistryIndex(json) {
37
49
  if (k.startsWith("_")) continue;
38
50
  if (typeof v !== "object" || v === null || Array.isArray(v)) continue;
39
51
  const entry = v;
40
- const hasNpm = typeof entry.npm === "string" && entry.npm.length > 0;
41
- const hasGh = typeof entry.repo === "string" && typeof entry.tag === "string";
52
+ const npm = optionalText(entry.npm);
53
+ const repo = optionalText(entry.repo);
54
+ const tag = optionalText(entry.tag);
55
+ const hasNpm = Boolean(npm);
56
+ const hasGh = Boolean(repo && tag);
42
57
  if (!hasNpm && !hasGh) continue;
43
58
  const out = {};
44
- if (hasNpm) {
45
- out.npm = entry.npm;
46
- if (typeof entry.version === "string") out.version = entry.version;
47
- if (typeof entry.sdk === "string") out.sdk = entry.sdk;
48
- }
49
- if (hasGh) {
50
- out.repo = entry.repo;
51
- out.tag = entry.tag;
52
- }
59
+ if (npm) out.npm = npm;
60
+ const version = optionalText(entry.version);
61
+ const sdk = optionalText(entry.sdk);
62
+ const name = optionalText(entry.name);
63
+ const description = optionalText(entry.description);
64
+ const category = optionalText(entry.category);
65
+ const license = optionalText(entry.license);
66
+ const requires = optionalRequires(entry.requires);
67
+ if (version) out.version = version;
68
+ if (sdk) out.sdk = sdk;
69
+ if (repo) out.repo = repo;
70
+ if (repo && tag) out.tag = tag;
71
+ if (name) out.name = name;
72
+ if (description) out.description = description;
73
+ if (category) out.category = category;
74
+ if (license) out.license = license;
75
+ if (typeof entry.official === "boolean") out.official = entry.official;
76
+ if (requires !== void 0) out.requires = requires;
53
77
  filtered[k] = out;
54
78
  }
55
79
  return filtered;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/registry.ts"],
4
- "sourcesContent": ["/**\n * registry.ts \u2014 first-party sfmc-modules index resolution, shared between\n * the module CLI and the startup unknown-source warning.\n *\n * Talks to https://raw.githubusercontent.com/Tanya7z/sfmc-modules/main/index.json\n * (the registry lives in a separate repo to keep this one free of \"what\n * modules exist\" governance). Caches to <sfmc/src/.sfmc-registry-cache.json>\n * with a 1h TTL so a brief network blip doesn't degrade the CLI.\n *\n * Both helpers are best-effort: failures are surfaced as `null` and a\n * console warning, never an exception, because the CLI must still boot\n * when the registry is unreachable.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_PATH = path.join(__dirname, \".sfmc-registry-cache.json\");\nconst TTL_MS = 60 * 60 * 1000;\n\nconst DEFAULT_REGISTRY_REPO = \"Tanya7z/sfmc-modules\";\nconst DEFAULT_REGISTRY_TAG = \"main\";\nconst INDEX_URL = `https://raw.githubusercontent.com/${DEFAULT_REGISTRY_REPO}/${DEFAULT_REGISTRY_TAG}/index.json`;\n\nexport interface RegistryEntry {\n npm?: string;\n version?: string;\n sdk?: string;\n repo?: string;\n tag?: string;\n}\nexport type RegistryIndex = Record<string, RegistryEntry>;\n\ninterface RegistryCache {\n fetchedAt: number;\n index: RegistryIndex;\n}\n\nfunction readCache(): RegistryCache | null {\n try {\n if (!existsSync(CACHE_PATH)) return null;\n return JSON.parse(readFileSync(CACHE_PATH, \"utf8\")) as RegistryCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: RegistryCache): void {\n try {\n mkdirSync(path.dirname(CACHE_PATH), { recursive: true });\n writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));\n } catch {\n /* cache write is best-effort */\n }\n}\n\n/**\n * \u89E3\u6790 first-party index.json\u3002\n * \u5951\u7EA6\u4E0E scripts/module-install/lib/registry-index.mjs#parseRegistryIndex \u4FDD\u6301\u4E00\u81F4\uFF1A\n * `{ modules: { <id>: { npm? | repo+tag } } }`\u3002\u5FFD\u7565 `_` \u524D\u7F00\u5143\u6570\u636E\u952E\u3002\n */\nexport function parseRegistryIndex(json: unknown): RegistryIndex {\n if (typeof json !== \"object\" || json === null || Array.isArray(json)) {\n throw new Error(\"registry index must be a JSON object with a 'modules' field\");\n }\n const root = json as Record<string, unknown>;\n const modulesRaw = root.modules;\n if (typeof modulesRaw !== \"object\" || modulesRaw === null || Array.isArray(modulesRaw)) {\n throw new Error(\"registry index must have a 'modules' object mapping id \u2192 entry\");\n }\n const filtered: RegistryIndex = {};\n for (const [k, v] of Object.entries(modulesRaw as Record<string, unknown>)) {\n if (k.startsWith(\"_\")) continue;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) continue;\n const entry = v as Record<string, unknown>;\n const hasNpm = typeof entry.npm === \"string\" && entry.npm.length > 0;\n const hasGh = typeof entry.repo === \"string\" && typeof entry.tag === \"string\";\n if (!hasNpm && !hasGh) continue;\n const out: RegistryEntry = {};\n if (hasNpm) {\n out.npm = entry.npm as string;\n if (typeof entry.version === \"string\") out.version = entry.version;\n if (typeof entry.sdk === \"string\") out.sdk = entry.sdk;\n }\n if (hasGh) {\n out.repo = entry.repo as string;\n out.tag = entry.tag as string;\n }\n filtered[k] = out;\n }\n return filtered;\n}\n\nasync function fetchFresh(): Promise<RegistryIndex> {\n const res = await fetch(INDEX_URL, {\n headers: { \"User-Agent\": \"sfmc-cli\" },\n signal: AbortSignal.timeout(3000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status} for ${INDEX_URL}`);\n return parseRegistryIndex(await res.json());\n}\n\nexport interface RegistryResult {\n index: RegistryIndex;\n /** True when the index came from a stale cache because the live fetch failed. */\n stale: boolean;\n}\n\n/**\n * Resolve the first-party index.\n *\n * Order (default):\n * 1. If the cache is fresh (< TTL): return it without trying the network.\n * 2. Otherwise attempt a live fetch.\n * - success \u2192 write cache, return fresh.\n * - failure + cache exists \u2192 return cache with `stale: true` and a warning.\n * - failure + no cache \u2192 return `{ index: {}, stale: true }` and warn.\n *\n * `force: true` \u8DF3\u8FC7 TTL \u65E9\u9000,\u59CB\u7EC8\u5C1D\u8BD5\u62C9\u7F51(\u4F9B `mod search` \u4E3B\u52A8\u5237\u65B0\u5217\u8868)\u3002\n * \u5931\u8D25\u65F6\u4ECD\u56DE\u9000\u5230\u7F13\u5B58,\u6C38\u4E0D\u629B\u5F02\u5E38\u3002\n */\nexport async function resolveRegistryIndex(opts?: { force?: boolean }): Promise<RegistryResult> {\n const cache = readCache();\n if (!opts?.force && cache && Date.now() - cache.fetchedAt < TTL_MS) {\n return { index: cache.index, stale: false };\n }\n try {\n const fresh = await fetchFresh();\n writeCache({ fetchedAt: Date.now(), index: fresh });\n return { index: fresh, stale: false };\n } catch (err) {\n if (cache) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry offline (${msg}); using cached index from ${new Date(cache.fetchedAt).toISOString()}\\n`);\n return { index: cache.index, stale: true };\n }\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry unreachable and no cache: ${msg}\\n`);\n return { index: {}, stale: true };\n }\n}\n\n/**\n * \u4ECE\u672C\u5730\u7F13\u5B58\u540C\u6B65\u8BFB\u51FA registry \u6A21\u5757 id(\u4F9B Tab \u8865\u5168)\u3002\n * \u65E0\u7F13\u5B58\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4,\u4E0D\u89E6\u53D1\u7F51\u7EDC\u3002\n */\nexport function listRegistryModuleIdsSync(): string[] {\n const cache = readCache();\n if (!cache) return [];\n return Object.keys(cache.index).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Compare a set of installed module ids to the registry and return the\n * subset that isn't published in the first-party index. The \"best-effort\"\n * guarantee: this returns an empty array when the registry can't be reached\n * (we don't want a network outage to mark every local module as unknown).\n */\nexport async function findUnknownModules(installedIds: string[]): Promise<string[]> {\n const { index, stale } = await resolveRegistryIndex();\n if (stale && Object.keys(index).length === 0) {\n /* No cache either \u2014 silently treat every module as \"we couldn't tell\".\n * Otherwise offline mode would scream warnings at every boot. */\n return [];\n }\n return installedIds.filter((id) => !index[id]);\n}\n\nexport { DEFAULT_REGISTRY_REPO, DEFAULT_REGISTRY_TAG };"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * registry.ts \u2014 first-party sfmc-modules index resolution, shared between\n * the module CLI and the startup unknown-source warning.\n *\n * Talks to https://raw.githubusercontent.com/Tanya7z/sfmc-modules/main/index.json\n * (the registry lives in a separate repo to keep this one free of \"what\n * modules exist\" governance). Caches to <sfmc/src/.sfmc-registry-cache.json>\n * with a 1h TTL so a brief network blip doesn't degrade the CLI.\n *\n * Both helpers are best-effort: failures are surfaced as `null` and a\n * console warning, never an exception, because the CLI must still boot\n * when the registry is unreachable.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_PATH = path.join(__dirname, \".sfmc-registry-cache.json\");\nconst TTL_MS = 60 * 60 * 1000;\n\nconst DEFAULT_REGISTRY_REPO = \"Tanya7z/sfmc-modules\";\nconst DEFAULT_REGISTRY_TAG = \"main\";\nconst INDEX_URL = `https://raw.githubusercontent.com/${DEFAULT_REGISTRY_REPO}/${DEFAULT_REGISTRY_TAG}/index.json`;\n\nexport interface RegistryEntry {\n npm?: string;\n version?: string;\n sdk?: string;\n repo?: string;\n tag?: string;\n /** \u7D22\u5F15\u91CC\u7684\u5C55\u793A\u540D\u3002\u65E7\u7F13\u5B58\u53EF\u80FD\u6CA1\u6709\u3002 */\n name?: string;\n description?: string;\n category?: string;\n license?: string;\n official?: boolean;\n /**\n * \u5B89\u88C5\u524D\u5FC5\u987B\u5DF2\u7ECF\u542F\u7528\u7684\u6A21\u5757 id\u3002\n * \u5B57\u6BB5\u7F3A\u5931\u8868\u793A\u8FD9\u4EFD\u7D22\u5F15\u6CA1\u6709\u58F0\u660E\u4F9D\u8D56\uFF0C\u8C03\u7528\u65B9\u5E94\u62D2\u7EDD\u5B89\u88C5\u3002\n */\n requires?: string[];\n}\nexport type RegistryIndex = Record<string, RegistryEntry>;\n\ninterface RegistryCache {\n fetchedAt: number;\n index: RegistryIndex;\n}\n\nfunction readCache(): RegistryCache | null {\n try {\n if (!existsSync(CACHE_PATH)) return null;\n return JSON.parse(readFileSync(CACHE_PATH, \"utf8\")) as RegistryCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: RegistryCache): void {\n try {\n mkdirSync(path.dirname(CACHE_PATH), { recursive: true });\n writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));\n } catch {\n /* cache write is best-effort */\n }\n}\n\n/**\n * \u89E3\u6790 first-party index.json\u3002\n * \u5951\u7EA6\u4E0E scripts/module-install/lib/registry-index.mjs#parseRegistryIndex \u4FDD\u6301\u4E00\u81F4\uFF1A\n * `{ modules: { <id>: { npm? | repo+tag, name?, description?, requires? } } }`\u3002\u5FFD\u7565 `_` \u524D\u7F00\u5143\u6570\u636E\u952E\u3002\n * requires \u53EA\u6709\u5728\u5168\u90E8\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u65F6\u624D\u4FDD\u7559\uFF1B\u7F3A\u4E86\u8FD9\u4E2A\u5B57\u6BB5\u5C31\u8868\u793A\u7D22\u5F15\u6CA1\u6709\u7ED9\u51FA\u4F9D\u8D56\u58F0\u660E\u3002\n */\nfunction optionalText(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\n/** \u7D22\u5F15 requires\u3002\u683C\u5F0F\u4E0D\u5BF9\u65F6\u8FD4\u56DE undefined\uFF0C\u8BA9\u5B89\u88C5\u65B9\u62D2\u7EDD\uFF0C\u800C\u4E0D\u662F\u5F53\u6210\u6CA1\u6709\u4F9D\u8D56\u3002 */\nfunction optionalRequires(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const items: string[] = [];\n for (const item of value) {\n if (typeof item !== \"string\" || !item.trim()) return undefined;\n items.push(item.trim());\n }\n return items;\n}\n\nexport function parseRegistryIndex(json: unknown): RegistryIndex {\n if (typeof json !== \"object\" || json === null || Array.isArray(json)) {\n throw new Error(\"registry index must be a JSON object with a 'modules' field\");\n }\n const root = json as Record<string, unknown>;\n const modulesRaw = root.modules;\n if (typeof modulesRaw !== \"object\" || modulesRaw === null || Array.isArray(modulesRaw)) {\n throw new Error(\"registry index must have a 'modules' object mapping id \u2192 entry\");\n }\n const filtered: RegistryIndex = {};\n for (const [k, v] of Object.entries(modulesRaw as Record<string, unknown>)) {\n if (k.startsWith(\"_\")) continue;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) continue;\n const entry = v as Record<string, unknown>;\n const npm = optionalText(entry.npm);\n const repo = optionalText(entry.repo);\n const tag = optionalText(entry.tag);\n const hasNpm = Boolean(npm);\n const hasGh = Boolean(repo && tag);\n if (!hasNpm && !hasGh) continue;\n const out: RegistryEntry = {};\n if (npm) out.npm = npm;\n const version = optionalText(entry.version);\n const sdk = optionalText(entry.sdk);\n const name = optionalText(entry.name);\n const description = optionalText(entry.description);\n const category = optionalText(entry.category);\n const license = optionalText(entry.license);\n const requires = optionalRequires(entry.requires);\n if (version) out.version = version;\n if (sdk) out.sdk = sdk;\n if (repo) out.repo = repo;\n if (repo && tag) out.tag = tag;\n if (name) out.name = name;\n if (description) out.description = description;\n if (category) out.category = category;\n if (license) out.license = license;\n if (typeof entry.official === \"boolean\") out.official = entry.official;\n // \u7A7A\u6570\u7EC4\u8868\u793A\u6CA1\u6709\u989D\u5916\u4F9D\u8D56\uFF0C\u5FC5\u987B\u4FDD\u7559\uFF1B\u7F3A\u5B57\u6BB5\u624D\u8868\u793A\u7D22\u5F15\u6CA1\u58F0\u660E\u3002\n if (requires !== undefined) out.requires = requires;\n filtered[k] = out;\n }\n return filtered;\n}\n\nasync function fetchFresh(): Promise<RegistryIndex> {\n const res = await fetch(INDEX_URL, {\n headers: { \"User-Agent\": \"sfmc-cli\" },\n signal: AbortSignal.timeout(3000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status} for ${INDEX_URL}`);\n return parseRegistryIndex(await res.json());\n}\n\nexport interface RegistryResult {\n index: RegistryIndex;\n /** True when the index came from a stale cache because the live fetch failed. */\n stale: boolean;\n}\n\n/**\n * Resolve the first-party index.\n *\n * Order (default):\n * 1. If the cache is fresh (< TTL): return it without trying the network.\n * 2. Otherwise attempt a live fetch.\n * - success \u2192 write cache, return fresh.\n * - failure + cache exists \u2192 return cache with `stale: true` and a warning.\n * - failure + no cache \u2192 return `{ index: {}, stale: true }` and warn.\n *\n * `force: true` \u8DF3\u8FC7 TTL \u65E9\u9000,\u59CB\u7EC8\u5C1D\u8BD5\u62C9\u7F51(\u4F9B `mod search` \u4E3B\u52A8\u5237\u65B0\u5217\u8868)\u3002\n * \u5931\u8D25\u65F6\u4ECD\u56DE\u9000\u5230\u7F13\u5B58,\u6C38\u4E0D\u629B\u5F02\u5E38\u3002\n */\nexport async function resolveRegistryIndex(opts?: { force?: boolean }): Promise<RegistryResult> {\n const cache = readCache();\n if (!opts?.force && cache && Date.now() - cache.fetchedAt < TTL_MS) {\n return { index: cache.index, stale: false };\n }\n try {\n const fresh = await fetchFresh();\n writeCache({ fetchedAt: Date.now(), index: fresh });\n return { index: fresh, stale: false };\n } catch (err) {\n if (cache) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry offline (${msg}); using cached index from ${new Date(cache.fetchedAt).toISOString()}\\n`);\n return { index: cache.index, stale: true };\n }\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[sfmc] registry unreachable and no cache: ${msg}\\n`);\n return { index: {}, stale: true };\n }\n}\n\n/**\n * \u4ECE\u672C\u5730\u7F13\u5B58\u540C\u6B65\u8BFB\u51FA registry \u6A21\u5757 id(\u4F9B Tab \u8865\u5168)\u3002\n * \u65E0\u7F13\u5B58\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4,\u4E0D\u89E6\u53D1\u7F51\u7EDC\u3002\n */\nexport function listRegistryModuleIdsSync(): string[] {\n const cache = readCache();\n if (!cache) return [];\n return Object.keys(cache.index).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Compare a set of installed module ids to the registry and return the\n * subset that isn't published in the first-party index. The \"best-effort\"\n * guarantee: this returns an empty array when the registry can't be reached\n * (we don't want a network outage to mark every local module as unknown).\n */\nexport async function findUnknownModules(installedIds: string[]): Promise<string[]> {\n const { index, stale } = await resolveRegistryIndex();\n if (stale && Object.keys(index).length === 0) {\n /* No cache either \u2014 silently treat every module as \"we couldn't tell\".\n * Otherwise offline mode would scream warnings at every boot. */\n return [];\n }\n return installedIds.filter((id) => !index[id]);\n}\n\nexport { DEFAULT_REGISTRY_REPO, DEFAULT_REGISTRY_TAG };"],
5
+ "mappings": "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",
6
6
  "names": ["msg"]
7
7
  }
@@ -5,6 +5,20 @@ export declare function isPacksCommand(cmd: string | undefined): cmd is string;
5
5
  export declare function packsInboxDir(): string;
6
6
  /** 平台聚合包不可经 packs uninstall 卸出(策略集中,CLI 只消费) */
7
7
  export declare function isProtectedSfmcPack(pack: Pick<InstalledWorldPack, "folderName">): boolean;
8
+ type UninstallOneOutcome = {
9
+ status: "protected";
10
+ folder: string;
11
+ } | {
12
+ status: "trashed";
13
+ folder: string;
14
+ dest: string;
15
+ } | {
16
+ status: "deleted";
17
+ folder: string;
18
+ } | {
19
+ status: "missing";
20
+ folder: string;
21
+ };
8
22
  /**
9
23
  * 按 CLI id 列表解析待卸载包(DIP:解析与 TTY/确认/执行分离,便于单测)。
10
24
  * - 任一 id 找不到 → not_found
@@ -20,6 +34,38 @@ export declare function resolveUninstallTargets(packs: InstalledWorldPack[], ids
20
34
  status: "protected";
21
35
  folder: string;
22
36
  };
37
+ /** 待卸载队列中的一项。pairedOf 表示该项是某个行为包带上的配对资源包。 */
38
+ export interface PackUninstallQueueItem {
39
+ pack: InstalledWorldPack;
40
+ pairedOf?: string;
41
+ }
42
+ /** 单包卸载的结构化结果,供 CLI 文案与桌面管理任务共用。 */
43
+ export interface PackUninstallOutcome {
44
+ folder: string;
45
+ uuid: string;
46
+ kind: InstalledWorldPack["kind"];
47
+ pairedOf?: string;
48
+ status: UninstallOneOutcome["status"];
49
+ dest?: string;
50
+ /** 行为包卸载后是否清掉了更新源绑定 */
51
+ bindingRemoved: boolean;
52
+ }
53
+ /**
54
+ * 把用户选中的包展开成卸载队列。
55
+ * 使用场景:CLI 多选确认,以及桌面 packs.uninstall。同一 uuid 只出现一次。
56
+ * 受保护的平台聚合包不展开配对资源包。
57
+ */
58
+ export declare function buildPackUninstallQueue(selected: InstalledWorldPack[], allPacks: InstalledWorldPack[], noPaired: boolean): PackUninstallQueueItem[];
59
+ /**
60
+ * 按队列卸载。不询问确认。
61
+ * 使用场景:CLI 在用户确认之后调用;桌面管理在用户确认之后调用。
62
+ * 行为包实际卸下后会清除更新源绑定;受保护包保持原样。
63
+ */
64
+ export declare function runPackUninstallQueue(queue: PackUninstallQueueItem[], opts: {
65
+ bdsRoot: string;
66
+ levelName: string;
67
+ purge: boolean;
68
+ }): Promise<PackUninstallOutcome[]>;
23
69
  /**
24
70
  * 扫描收件箱并安装。空收件箱时不打日志(启动钩子友好)。
25
71
  */
@@ -36,4 +82,5 @@ export declare function scanAndInstallInbox(opts?: {
36
82
  export declare function shouldDisplayPackSourceLabel(sourceLabel: string): boolean;
37
83
  export declare function dispatchPacksCommand(sub: string | undefined, args: string[]): Promise<string>;
38
84
  export declare function packsUsage(): string;
85
+ export {};
39
86
  //# sourceMappingURL=world-packs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"world-packs.d.ts","sourceRoot":"","sources":["../src/world-packs.ts"],"names":[],"mappings":"AAKA,OAAO,EAkBL,KAAK,kBAAkB,EAExB,MAAM,iCAAiC,CAAC;AAwBzC,eAAO,MAAM,eAAe,YAAI,OAAO,EAAE,OAAO,CAAU,CAAC;AAC3D,eAAO,MAAM,iBAAiB,YAC5B,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,EACN,SAAS,EACT,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,SAAS,EACT,OAAO,EACP,QAAQ,CACA,CAAC;AAcX,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,IAAI,MAAM,CAErE;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AA4ED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,YAAY,CAAC,GAAG,OAAO,CAGzF;AAqED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,EAAE,EAC3B,GAAG,EAAE,MAAM,EAAE,GAEX;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAgB1C;AAmND;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiJlE;AAgBD,qCAAqC;AACrC,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEzE;AAyRD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnG;AAiQD,wBAAgB,UAAU,IAAI,MAAM,CAuBnC"}
1
+ {"version":3,"file":"world-packs.d.ts","sourceRoot":"","sources":["../src/world-packs.ts"],"names":[],"mappings":"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"}
@@ -215,8 +215,7 @@ async function pickPacksForUninstall(packs) {
215
215
  const set = new Set(selected);
216
216
  return candidates.filter((p) => set.has(p.uuid));
217
217
  }
218
- async function uninstallPacksBatch(selected, allPacks, opts) {
219
- if (selected.length === 0) return c.yellow(t("packs.uninstall.none"));
218
+ function buildPackUninstallQueue(selected, allPacks, noPaired) {
220
219
  const queue = [];
221
220
  const seen = /* @__PURE__ */ new Set();
222
221
  for (const pack of selected) {
@@ -225,7 +224,7 @@ async function uninstallPacksBatch(selected, allPacks, opts) {
225
224
  seen.add(key);
226
225
  queue.push({ pack });
227
226
  if (isProtectedSfmcPack(pack)) continue;
228
- const paired = resolvePairedResource(pack, allPacks, opts.noPaired);
227
+ const paired = resolvePairedResource(pack, allPacks, noPaired);
229
228
  if (paired) {
230
229
  const pk = paired.uuid.toLowerCase();
231
230
  if (!seen.has(pk)) {
@@ -234,6 +233,36 @@ async function uninstallPacksBatch(selected, allPacks, opts) {
234
233
  }
235
234
  }
236
235
  }
236
+ return queue;
237
+ }
238
+ async function runPackUninstallQueue(queue, opts) {
239
+ const outcomes = [];
240
+ for (const item of queue) {
241
+ const outcome = await uninstallOneInstalledPack(item.pack, opts);
242
+ const bindingRemoved = item.pack.kind === "behavior" && outcome.status !== "protected" && removeBinding(item.pack.uuid);
243
+ outcomes.push({
244
+ folder: item.pack.folderName,
245
+ uuid: item.pack.uuid,
246
+ kind: item.pack.kind,
247
+ ...item.pairedOf ? { pairedOf: item.pairedOf } : {},
248
+ status: outcome.status,
249
+ ...outcome.status === "trashed" ? { dest: outcome.dest } : {},
250
+ bindingRemoved
251
+ });
252
+ }
253
+ return outcomes;
254
+ }
255
+ function formatQueueOutcome(outcome) {
256
+ if (outcome.status === "trashed") {
257
+ return formatUninstallOutcome({ status: "trashed", folder: outcome.folder, dest: outcome.dest ?? "" });
258
+ }
259
+ if (outcome.status === "protected") return formatUninstallOutcome({ status: "protected", folder: outcome.folder });
260
+ if (outcome.status === "missing") return formatUninstallOutcome({ status: "missing", folder: outcome.folder });
261
+ return formatUninstallOutcome({ status: "deleted", folder: outcome.folder });
262
+ }
263
+ async function uninstallPacksBatch(selected, allPacks, opts) {
264
+ if (selected.length === 0) return c.yellow(t("packs.uninstall.none"));
265
+ const queue = buildPackUninstallQueue(selected, allPacks, opts.noPaired);
237
266
  if (opts.askConfirm && process.stdin.isTTY) {
238
267
  const preview = queue.map((q) => {
239
268
  const kind = q.pack.kind === "behavior" ? "BP" : "RP";
@@ -249,14 +278,10 @@ async function uninstallPacksBatch(selected, allPacks, opts) {
249
278
  if (isCancel(ans) || !ans) return c.dim(t("packs.uninstall.cancelled"));
250
279
  }
251
280
  const lines = [];
252
- for (const item of queue) {
253
- const outcome = await uninstallOneInstalledPack(item.pack, opts);
254
- lines.push(formatUninstallOutcome(outcome));
255
- if (item.pack.kind === "behavior" && outcome.status !== "protected") {
256
- const removed = removeBinding(item.pack.uuid);
257
- if (removed) {
258
- lines.push(c.dim(t("packs.uninstall.bindingRemoved", { uuid: item.pack.uuid })));
259
- }
281
+ for (const outcome of await runPackUninstallQueue(queue, opts)) {
282
+ lines.push(formatQueueOutcome(outcome));
283
+ if (outcome.bindingRemoved) {
284
+ lines.push(c.dim(t("packs.uninstall.bindingRemoved", { uuid: outcome.uuid })));
260
285
  }
261
286
  }
262
287
  lines.push(c.yellow(restartHint()));
@@ -1013,12 +1038,14 @@ ${t("packs.usage.moduleNote", { cmd: c.green("sfmc mod") })}`;
1013
1038
  export {
1014
1039
  PACKS_CMD_NAMES,
1015
1040
  PACKS_SUBCOMMANDS,
1041
+ buildPackUninstallQueue,
1016
1042
  dispatchPacksCommand,
1017
1043
  isPacksCommand,
1018
1044
  isProtectedSfmcPack,
1019
1045
  packsInboxDir,
1020
1046
  packsUsage,
1021
1047
  resolveUninstallTargets,
1048
+ runPackUninstallQueue,
1022
1049
  scanAndInstallInbox,
1023
1050
  shouldDisplayPackSourceLabel
1024
1051
  };