@sfmc-bds/cli 0.2.0-beta.14 → 0.2.0-beta.15

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.
@@ -12,7 +12,7 @@ export declare function buildModulePacks(force?: boolean): Promise<BuildModulePa
12
12
  /**
13
13
  * `sfmc mod build` —— 组装 BP + RP(不部署)。
14
14
  */
15
- export declare function cmdModuleBuild(args?: string[]): Promise<string>;
15
+ export declare function cmdModuleBuild(_args?: string[]): Promise<string>;
16
16
  /**
17
17
  * `sfmc mod reload [--build-only] [--force]` —— 组装 + 部署 + 清理过期 + 写权限 + (默认)发 reload 到 BDS。
18
18
  */
@@ -1 +1 @@
1
- {"version":3,"file":"module-pack-build.d.ts","sourceRoot":"","sources":["../src/module-pack-build.ts"],"names":[],"mappings":"AAoBA,OAAO,EAgBL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAyU7B,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA6DrF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAIzE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD1E"}
1
+ {"version":3,"file":"module-pack-build.d.ts","sourceRoot":"","sources":["../src/module-pack-build.ts"],"names":[],"mappings":"AAsBA,OAAO,EAgBL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAsS7B,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAyDrF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAI1E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD1E"}
@@ -1,30 +1,30 @@
1
+ import { writeJson } from "@sfmc-bds/sdk/node/config";
1
2
  import { spawn } from "node:child_process";
2
3
  import { existsSync } from "node:fs";
3
4
  import fs from "node:fs/promises";
4
5
  import path from "node:path";
5
6
  import process from "node:process";
6
- import { writeJson } from "@sfmc-bds/sdk/node/config";
7
+ import { t } from "./i18n/index.js";
8
+ import { pushLog } from "./logs.js";
7
9
  import {
8
10
  BP_NAME,
9
- RP_NAME,
10
11
  DEPLOY_CATALOG_NAME,
12
+ RP_NAME,
11
13
  bpOut,
12
14
  bpSrc,
13
- rpOut,
14
15
  buildRoot,
15
- computeDesiredCatalog,
16
- readDeployedCatalog,
17
16
  catalogsEqual,
18
- resolveBdsContext,
17
+ computeDesiredCatalog,
18
+ createSdkResolvePlugin,
19
19
  deployedBpDir,
20
20
  formatPackLoadInfo,
21
- scanLocalModules,
22
- createSdkResolvePlugin
21
+ readDeployedCatalog,
22
+ resolveBdsContext,
23
+ rpOut,
24
+ scanLocalModules
23
25
  } from "./pack-lifecycle.js";
24
- import { ROOT, getRoot, resolveServiceScript, resolveSdkPackageRoot } from "./runtime.js";
26
+ import { ROOT, getRoot, resolveSdkPackageRoot, resolveServiceScript } from "./runtime.js";
25
27
  import { c } from "./theme.js";
26
- import { t } from "./i18n/index.js";
27
- import { pushLog } from "./logs.js";
28
28
  function spawnPackManager(args) {
29
29
  return new Promise((resolve) => {
30
30
  const script = resolveServiceScript("pack-manager");
@@ -138,11 +138,7 @@ async function spawnAssembleRp(catalog, rpDirs) {
138
138
  if (catalog.rpModuleUuid) args.push("--module-uuid", catalog.rpModuleUuid);
139
139
  const r = await spawnPackManager(args);
140
140
  if (r.code === 0) {
141
- pushLog(
142
- `assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`,
143
- "pack",
144
- "info"
145
- );
141
+ pushLog(`assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`, "pack", "info");
146
142
  }
147
143
  return r;
148
144
  }
@@ -192,11 +188,7 @@ async function spawnEnablePacks(catalog) {
192
188
  const bpR = await spawnPackManager(bpArgs);
193
189
  output += bpR.output;
194
190
  if (bpR.code !== 0) return { code: bpR.code, output };
195
- pushLog(
196
- `enabled behavior pack ${catalog.bpUuid} in world list`,
197
- "pack",
198
- "info"
199
- );
191
+ pushLog(`enabled behavior pack ${catalog.bpUuid} in world list`, "pack", "info");
200
192
  if (catalog.rpUuid && catalog.rpVersion) {
201
193
  const rpArgs = [
202
194
  "enable-pack",
@@ -214,11 +206,7 @@ async function spawnEnablePacks(catalog) {
214
206
  const rpR = await spawnPackManager(rpArgs);
215
207
  output += rpR.output;
216
208
  if (rpR.code !== 0) return { code: rpR.code, output };
217
- pushLog(
218
- `enabled resource pack ${catalog.rpUuid} in world list`,
219
- "pack",
220
- "info"
221
- );
209
+ pushLog(`enabled resource pack ${catalog.rpUuid} in world list`, "pack", "info");
222
210
  }
223
211
  return { code: 0, output };
224
212
  }
@@ -243,11 +231,7 @@ async function spawnDisableStale(current, bdsRoot, levelName) {
243
231
  if (r.code === 0) {
244
232
  pushLog(`disabled stale resource pack ${staleRp}`, "pack", "info");
245
233
  } else {
246
- pushLog(
247
- `disable stale RP ${staleRp} failed: ${r.output.trim()}`,
248
- "pack",
249
- "warn"
250
- );
234
+ pushLog(`disable stale RP ${staleRp} failed: ${r.output.trim()}`, "pack", "warn");
251
235
  }
252
236
  }
253
237
  for (const staleBp of previous.bp) {
@@ -268,11 +252,7 @@ async function spawnDisableStale(current, bdsRoot, levelName) {
268
252
  if (r.code === 0) {
269
253
  pushLog(`disabled stale behavior pack ${staleBp}`, "pack", "info");
270
254
  } else {
271
- pushLog(
272
- `disable stale BP ${staleBp} failed: ${r.output.trim()}`,
273
- "pack",
274
- "warn"
275
- );
255
+ pushLog(`disable stale BP ${staleBp} failed: ${r.output.trim()}`, "pack", "warn");
276
256
  }
277
257
  }
278
258
  }
@@ -304,13 +284,7 @@ async function collectDeployedPackUuids(bdsRoot, levelName) {
304
284
  }
305
285
  async function spawnEnsurePermission(catalog) {
306
286
  const { bdsRoot } = resolveBdsContext();
307
- const r = await spawnPackManager([
308
- "ensure-permission",
309
- "--bds-root",
310
- bdsRoot,
311
- "--pack-id",
312
- catalog.bpUuid
313
- ]);
287
+ const r = await spawnPackManager(["ensure-permission", "--bds-root", bdsRoot, "--pack-id", catalog.bpUuid]);
314
288
  return r;
315
289
  }
316
290
  async function buildModulePacks(force = false) {
@@ -325,11 +299,7 @@ async function buildModulePacks(force = false) {
325
299
  catalog: deployed
326
300
  };
327
301
  }
328
- pushLog(
329
- `building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`,
330
- "pack",
331
- "info"
332
- );
302
+ pushLog(`building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`, "pack", "info");
333
303
  await bundleBehaviorPackScript();
334
304
  const mods = await scanLocalModules();
335
305
  const rpDirs = {};
@@ -369,9 +339,8 @@ async function buildModulePacks(force = false) {
369
339
  };
370
340
  }
371
341
  }
372
- async function cmdModuleBuild(args = []) {
373
- const force = args.includes("--force") || args.includes("-f");
374
- const res = await buildModulePacks(force);
342
+ async function cmdModuleBuild(_args = []) {
343
+ const res = await buildModulePacks(true);
375
344
  return res.message;
376
345
  }
377
346
  async function cmdModuleReload(args = []) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/module-pack-build.ts"],
4
- "sourcesContent": ["/**\n * module-pack-build.ts \u2014 `mod build` / `mod reload` \u7684 spawn-based \u5B9E\u73B0\n *\n * CLI \u6D3E\u53D1\u7684 module build / reload \u5B50\u547D\u4EE4\u8D70\u8FD9\u91CC\uFF1Bpack-lifecycle.ts \u4FDD\u7559\n * ensurePacksReady \u542F\u52A8\u94A9\u5B50\u4E0E wizard \u5185\u90E8\u6D88\u8D39\u65B9\u7684 in-process \u5165\u53E3\u3002\n *\n * \u5B9E\u9645\u6587\u4EF6\u5199\u5165\uFF08assemble-bp / assemble-rp / deploy / enable-pack / disable-pack /\n * ensure-permission\uFF09\u901A\u8FC7 spawn bds-tools/cli-pack-manager.ts \u7684 verb \u6267\u884C\uFF1B\n * \u4E0E module install/uninstall\uFF08\u2192 scripts/module-install/fetch-module.mjs\uFF09\u4FDD\u6301\u540C\u4E00\u67B6\u6784\uFF1A\n * CLI \u662F thin wrapper\uFF1B\u5EFA\u4ED3\u811A\u624B\u67B6\u5728 @sfmc-bds/create-module\uFF08npm create\uFF09\u3002\n *\n * \u552F\u4E00\u6743\u5A01\uFF1A\u672C\u6587\u4EF6 = `sfmc mod build|reload` \u7684\u6D3E\u53D1\u5165\u53E3\uFF1B\u5176\u4ED6\u6587\u4EF6\u4E0D\u5F97\u518D\n * \u76F4\u63A5 import pack-lifecycle \u7684 cmdPackBuild / deployPacks\uFF08\u786E\u4FDD\u53EA\u6709\u4E00\u4E2A spawn \u5165\u53E3\uFF09\u3002\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport {\n BP_NAME,\n RP_NAME,\n DEPLOY_CATALOG_NAME,\n bpOut,\n bpSrc,\n rpOut,\n buildRoot,\n computeDesiredCatalog,\n readDeployedCatalog,\n catalogsEqual,\n resolveBdsContext,\n deployedBpDir,\n formatPackLoadInfo,\n scanLocalModules,\n createSdkResolvePlugin,\n type DeployCatalog,\n} from \"./pack-lifecycle.js\";\nimport { ROOT, getRoot, resolveServiceScript, resolveSdkPackageRoot } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\nimport { t } from \"./i18n/index.js\";\nimport { pushLog } from \"./logs.js\";\n\ntype SpawnResult = { code: number | null; output: string };\n\n/** spawn bds-tools/cli-pack-manager.ts \u5B50\u8FDB\u7A0B\uFF1B\u6355\u83B7 stdout+stderr\u3002 */\nfunction spawnPackManager(args: string[]): Promise<SpawnResult> {\n return new Promise((resolve) => {\n const script = resolveServiceScript(\"pack-manager\");\n const proc = spawn(process.execPath, [script, ...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: getRoot(), SFMC_SERVICE: \"pack-manager\" },\n });\n let output = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: `${output}${e.message}` }));\n });\n}\n\n/* esbuild bundle \u2014\u2014 JS bundler \u662F in-process \u5E93\uFF0C\u4E0D\u8D70 spawn\u3002 */\nasync function bundleBehaviorPackScript(): Promise<void> {\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n pushLog(\"no enabled SAPI modules \u2014 empty main.js\", \"pack\", \"warn\");\n return;\n }\n\n const { build } = await import(\"esbuild\");\n const sdkRoot = resolveSdkPackageRoot();\n await build({\n stdin: {\n contents: [\n 'import \"sfmc:host\";',\n ...entries.map((e) => `import ${JSON.stringify(path.resolve(e).replace(/\\\\/g, \"/\"))};`),\n ].join(\"\\n\"),\n resolveDir: ROOT,\n sourcefile: \"bootstrap.ts\",\n loader: \"ts\",\n },\n outfile: outFile,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n logLevel: \"warning\",\n sourcemap: true,\n external: [\"@minecraft/*\"],\n tsconfigRaw: JSON.stringify({\n compilerOptions: {\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n target: \"ES2022\",\n strict: true,\n skipLibCheck: true,\n },\n }),\n plugins: [createSdkResolvePlugin(sdkRoot)],\n });\n pushLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"pack\", \"info\");\n}\n\n/** spawn assemble-bp verb\u3002 */\nasync function spawnAssembleBp(catalog: DeployCatalog): Promise<SpawnResult> {\n const args = [\n \"assemble-bp\",\n \"--src\",\n bpSrc(),\n \"--out\",\n bpOut(),\n \"--name\",\n BP_NAME,\n \"--uuid\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n if (catalog.bpModuleUuid) args.push(\"--module-uuid\", catalog.bpModuleUuid);\n if (catalog.dependencies && catalog.dependencies.length > 0) {\n const depsFile = path.join(buildRoot(), \"bp-dependencies.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(depsFile, JSON.stringify(catalog.dependencies), \"utf8\");\n args.push(\"--dependencies-json\", depsFile);\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`assembled BP uuid=${catalog.bpUuid}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn assemble-rp verb\uFF1B\u65E0 RP \u65F6\u6E05\u7406\u65E7\u4EA7\u7269\u3002 */\nasync function spawnAssembleRp(\n catalog: DeployCatalog,\n rpDirs: Record<string, string>\n): Promise<SpawnResult> {\n if (!catalog.rpUuid || Object.keys(rpDirs).length === 0) {\n await fs.rm(rpOut(), { recursive: true, force: true });\n pushLog(\"no enabled resource packs \u2014 RP skipped\", \"pack\", \"info\");\n return { code: 0, output: \"[pack-manager] no enabled resource packs \u2014 RP skipped\\n\" };\n }\n const mapFile = path.join(buildRoot(), \"rp-map.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(mapFile, JSON.stringify(rpDirs), \"utf8\");\n const args = [\n \"assemble-rp\",\n \"--modules-json\",\n mapFile,\n \"--out\",\n rpOut(),\n \"--name\",\n RP_NAME,\n \"--uuid\",\n catalog.rpUuid,\n \"--version\",\n (catalog.rpVersion ?? [1, 0, 0]).join(\",\"),\n ];\n if (catalog.rpModuleUuid) args.push(\"--module-uuid\", catalog.rpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(\n `assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`,\n \"pack\",\n \"info\"\n );\n }\n return r;\n}\n\n/** spawn deploy verb\uFF1B\u65E0 RP \u65F6\u5E26 --clear-rp\u3002 */\nasync function spawnDeploy(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const args = [\n \"deploy\",\n \"--bds-root\",\n bdsRoot,\n \"--level\",\n levelName,\n \"--bp-src\",\n bpOut(),\n \"--bp-name\",\n BP_NAME,\n \"--rp-name\",\n RP_NAME,\n ];\n if (catalog.rpUuid && existsSync(rpOut())) {\n args.push(\"--rp-src\", rpOut());\n } else {\n args.push(\"--clear-rp\");\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`deployed to worlds/${levelName}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn enable-pack verb\uFF1ABP \u5FC5\u987B\uFF0CRP \u4EC5\u5728\u6709 UUID \u65F6\u3002 */\nasync function spawnEnablePacks(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const worldsDir = path.join(bdsRoot, \"worlds\");\n let output = \"\";\n const bpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n const bpR = await spawnPackManager(bpArgs);\n output += bpR.output;\n if (bpR.code !== 0) return { code: bpR.code, output };\n pushLog(\n `enabled behavior pack ${catalog.bpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n if (catalog.rpUuid && catalog.rpVersion) {\n const rpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n catalog.rpUuid,\n \"--version\",\n catalog.rpVersion.join(\",\"),\n ];\n const rpR = await spawnPackManager(rpArgs);\n output += rpR.output;\n if (rpR.code !== 0) return { code: rpR.code, output };\n pushLog(\n `enabled resource pack ${catalog.rpUuid} in world list`,\n \"pack\",\n \"info\"\n );\n }\n return { code: 0, output };\n}\n\n/** spawn disable-pack verb\uFF1A\u6E05\u7406\u8FC7\u671F UUID\uFF08uuid \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP\uFF09\u3002 */\nasync function spawnDisableStale(\n current: DeployCatalog,\n bdsRoot: string,\n levelName: string\n): Promise<void> {\n const previous = await collectDeployedPackUuids(bdsRoot, levelName);\n const worldsDir = path.join(bdsRoot, \"worlds\");\n for (const staleRp of previous.rp) {\n if (staleRp === (current.rpUuid ?? null)) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n staleRp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale resource pack ${staleRp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale RP ${staleRp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n for (const staleBp of previous.bp) {\n if (staleBp === current.bpUuid) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n staleBp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale behavior pack ${staleBp}`, \"pack\", \"info\");\n } else {\n pushLog(\n `disable stale BP ${staleBp} failed: ${r.output.trim()}`,\n \"pack\",\n \"warn\"\n );\n }\n }\n}\n\n/** \u901A\u8FC7 bds-tools \u7684 list-installed + read-manifest \u62FF\u5230 deployed UUID\uFF08spawn\uFF09\u3002 */\nasync function collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): Promise<{ bp: Set<string>; rp: Set<string> }> {\n const bp = new Set<string>();\n const rp = new Set<string>();\n const cat = readDeployedCatalog(bdsRoot, levelName);\n if (cat?.bpUuid) bp.add(cat.bpUuid);\n if (cat?.rpUuid) rp.add(cat.rpUuid);\n // \u901A\u8FC7 read-manifest \u770B\u4E16\u754C\u78C1\u76D8 BP/RP manifest \u7684 uuid\uFF0C\u4F5C\u4E3A catalog \u7F3A\u5931\u65F6\u7684\u515C\u5E95\u3002\n const bpDir = path.join(bdsRoot, \"worlds\", levelName, \"behavior_packs\", BP_NAME);\n const rpDir = path.join(bdsRoot, \"worlds\", levelName, \"resource_packs\", RP_NAME);\n const bpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", bpDir]);\n if (bpR.code === 0) {\n try {\n const j = JSON.parse(bpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) bp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n const rpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", rpDir]);\n if (rpR.code === 0) {\n try {\n const j = JSON.parse(rpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) rp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n return { bp, rp };\n}\n\n/** spawn ensure-permission verb\u3002 */\nasync function spawnEnsurePermission(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot } = resolveBdsContext();\n const r = await spawnPackManager([\n \"ensure-permission\",\n \"--bds-root\",\n bdsRoot,\n \"--pack-id\",\n catalog.bpUuid,\n ]);\n return r;\n}\n\nexport type BuildModulePacksResult = {\n success: boolean;\n message: string;\n catalog?: DeployCatalog;\n};\n\n/**\n * \u7EC4\u88C5 BP + RP \u7EAF\u903B\u8F91\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n * \u4EC5\u5F53 catalog \u4E0E\u4E16\u754C\u5185\u5DF2\u90E8\u7F72\u4E0D\u4E00\u81F4\u65F6\u6267\u884C\uFF1B\u5426\u5219\u76F4\u63A5\u6253\"\u5DF2\u540C\u6B65\"\u3002\n */\nexport async function buildModulePacks(force = false): Promise<BuildModulePacksResult> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n const desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n if (!force && deployed && catalogsEqual(desired, deployed)) {\n return {\n success: true,\n message: formatPackLoadInfo(desired, false),\n catalog: deployed,\n };\n }\n\n pushLog(\n `building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`,\n \"pack\",\n \"info\"\n );\n await bundleBehaviorPackScript();\n\n const mods = await scanLocalModules();\n const rpDirs: Record<string, string> = {};\n for (const m of mods) {\n if (!m.enabled || !m.hasResourcePack) continue;\n rpDirs[m.folderId] = path.join(\"modules\", \"packages\", m.folderId, \"resource_pack\");\n }\n\n const bpR = await spawnAssembleBp(desired);\n if (bpR.code !== 0) {\n return {\n success: false,\n message: c.red(bpR.output.trim() || `assemble-bp exit ${bpR.code}`),\n };\n }\n const rpR = await spawnAssembleRp(desired, rpDirs);\n if (rpR.code !== 0) {\n return {\n success: false,\n message: c.red(rpR.output.trim() || `assemble-rp exit ${rpR.code}`),\n };\n }\n\n desired.generatedAt = Date.now();\n if (Object.keys(rpDirs).length === 0) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), desired);\n\n return {\n success: true,\n message: formatPackLoadInfo(desired, true),\n catalog: desired,\n };\n } catch (e) {\n return {\n success: false,\n message: c.red((e as Error).message),\n };\n }\n}\n\n/**\n * `sfmc mod build` \u2014\u2014 \u7EC4\u88C5 BP + RP\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n */\nexport async function cmdModuleBuild(args: string[] = []): Promise<string> {\n const force = args.includes(\"--force\") || args.includes(\"-f\");\n const res = await buildModulePacks(force);\n return res.message;\n}\n\n/**\n * `sfmc mod reload [--build-only] [--force]` \u2014\u2014 \u7EC4\u88C5 + \u90E8\u7F72 + \u6E05\u7406\u8FC7\u671F + \u5199\u6743\u9650 + \uFF08\u9ED8\u8BA4\uFF09\u53D1 reload \u5230 BDS\u3002\n */\nexport async function cmdModuleReload(args: string[] = []): Promise<string> {\n const buildOnly = args?.includes(\"--build-only\") ?? false;\n const force = args?.includes(\"--force\") || args?.includes(\"-f\");\n const parts: string[] = [];\n\n const buildRes = await buildModulePacks(force);\n parts.push(buildRes.message.trimEnd());\n if (!buildRes.success || !buildRes.catalog) {\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const desired = buildRes.catalog;\n\n const depR = await spawnDeploy(desired);\n if (depR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(depR.output.trim() || `deploy exit ${depR.code}`);\n }\n parts.push(depR.output.trimEnd());\n\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), desired);\n\n await spawnDisableStale(desired, bdsRoot, levelName);\n\n const enR = await spawnEnablePacks(desired);\n if (enR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(enR.output.trim() || `enable-pack exit ${enR.code}`);\n }\n parts.push(enR.output.trimEnd());\n\n const perR = await spawnEnsurePermission(desired);\n if (perR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(perR.output.trim() || `ensure-permission exit ${perR.code}`);\n }\n parts.push(perR.output.trimEnd());\n } catch (e) {\n return parts.join(\"\\n\") + \"\\n\" + c.red((e as Error).message);\n }\n\n if (buildOnly) {\n parts.push(c.dim(t(\"reload.buildOnly\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n const { isServiceRunning } = await import(\"./services.js\");\n if (!(await isServiceRunning(\"bds\"))) {\n parts.push(c.yellow(t(\"reload.bdsNotRunning\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n const { cmdSend } = await import(\"./commands.js\");\n parts.push((await cmdSend(\"bds\", \"reload\")).trimEnd());\n parts.push(c.green(t(\"reload.sent\")));\n return parts.join(\"\\n\") + \"\\n\";\n}\n\nfunction reusePackIds(\n deployed: DeployCatalog\n): Parameters<typeof computeDesiredCatalog>[0] {\n return {\n bpUuid: deployed.bpUuid,\n rpUuid: deployed.rpUuid,\n bpVersion: deployed.bpVersion,\n rpVersion: deployed.rpVersion,\n ...(deployed.bpModuleUuid ? { bpModuleUuid: deployed.bpModuleUuid } : {}),\n ...(deployed.rpModuleUuid ? { rpModuleUuid: deployed.rpModuleUuid } : {}),\n };\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * module-pack-build.ts \u2014 `mod build` / `mod reload` \u7684 spawn-based \u5B9E\u73B0\n *\n * CLI \u6D3E\u53D1\u7684 module build / reload \u5B50\u547D\u4EE4\u8D70\u8FD9\u91CC\uFF1Bpack-lifecycle.ts \u4FDD\u7559\n * ensurePacksReady \u542F\u52A8\u94A9\u5B50\u4E0E wizard \u5185\u90E8\u6D88\u8D39\u65B9\u7684 in-process \u5165\u53E3\u3002\n *\n * \u5B9E\u9645\u6587\u4EF6\u5199\u5165\uFF08assemble-bp / assemble-rp / deploy / enable-pack / disable-pack /\n * ensure-permission\uFF09\u901A\u8FC7 spawn bds-tools/cli-pack-manager.ts \u7684 verb \u6267\u884C\uFF1B\n * \u4E0E module install/uninstall\uFF08\u2192 scripts/module-install/fetch-module.mjs\uFF09\u4FDD\u6301\u540C\u4E00\u67B6\u6784\uFF1A\n * CLI \u662F thin wrapper\uFF1B\u5EFA\u4ED3\u811A\u624B\u67B6\u5728 @sfmc-bds/create-module\uFF08npm create\uFF09\u3002\n *\n * \u552F\u4E00\u6743\u5A01\uFF1A\u672C\u6587\u4EF6 = `sfmc mod build|reload` \u7684\u6D3E\u53D1\u5165\u53E3\uFF1B\u5176\u4ED6\u6587\u4EF6\u4E0D\u5F97\u518D\n * \u76F4\u63A5 import pack-lifecycle \u7684 cmdPackBuild / deployPacks\uFF08\u786E\u4FDD\u53EA\u6709\u4E00\u4E2A spawn \u5165\u53E3\uFF09\u3002\n */\nimport { writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { t } from \"./i18n/index.js\";\nimport { pushLog } from \"./logs.js\";\nimport {\n BP_NAME,\n DEPLOY_CATALOG_NAME,\n RP_NAME,\n bpOut,\n bpSrc,\n buildRoot,\n catalogsEqual,\n computeDesiredCatalog,\n createSdkResolvePlugin,\n deployedBpDir,\n formatPackLoadInfo,\n readDeployedCatalog,\n resolveBdsContext,\n rpOut,\n scanLocalModules,\n type DeployCatalog,\n} from \"./pack-lifecycle.js\";\nimport { ROOT, getRoot, resolveSdkPackageRoot, resolveServiceScript } from \"./runtime.js\";\nimport { c } from \"./theme.js\";\n\ntype SpawnResult = { code: number | null; output: string };\n\n/** spawn bds-tools/cli-pack-manager.ts \u5B50\u8FDB\u7A0B\uFF1B\u6355\u83B7 stdout+stderr\u3002 */\nfunction spawnPackManager(args: string[]): Promise<SpawnResult> {\n return new Promise((resolve) => {\n const script = resolveServiceScript(\"pack-manager\");\n const proc = spawn(process.execPath, [script, ...args], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: getRoot(), SFMC_SERVICE: \"pack-manager\" },\n });\n let output = \"\";\n proc.stdout?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.stderr?.on(\"data\", (d: Buffer) => {\n output += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: `${output}${e.message}` }));\n });\n}\n\n/* esbuild bundle \u2014\u2014 JS bundler \u662F in-process \u5E93\uFF0C\u4E0D\u8D70 spawn\u3002 */\nasync function bundleBehaviorPackScript(): Promise<void> {\n const mods = await scanLocalModules();\n const entries = mods.filter((m) => m.enabled && m.entryPath).map((m) => m.entryPath!);\n const outFile = path.join(bpSrc(), \"scripts\", \"main.js\");\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n\n if (entries.length === 0) {\n await fs.writeFile(outFile, \"/* no modules enabled */\\n\", \"utf8\");\n pushLog(\"no enabled SAPI modules \u2014 empty main.js\", \"pack\", \"warn\");\n return;\n }\n\n const { build } = await import(\"esbuild\");\n const sdkRoot = resolveSdkPackageRoot();\n await build({\n stdin: {\n contents: [\n 'import \"sfmc:host\";',\n ...entries.map((e) => `import ${JSON.stringify(path.resolve(e).replace(/\\\\/g, \"/\"))};`),\n ].join(\"\\n\"),\n resolveDir: ROOT,\n sourcefile: \"bootstrap.ts\",\n loader: \"ts\",\n },\n outfile: outFile,\n bundle: true,\n platform: \"neutral\",\n format: \"esm\",\n target: \"es2022\",\n logLevel: \"warning\",\n sourcemap: true,\n external: [\"@minecraft/*\"],\n tsconfigRaw: JSON.stringify({\n compilerOptions: {\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n target: \"ES2022\",\n strict: true,\n skipLibCheck: true,\n },\n }),\n plugins: [createSdkResolvePlugin(sdkRoot)],\n });\n pushLog(`esbuild bundled ${entries.length} entr(y/ies)`, \"pack\", \"info\");\n}\n\n/** spawn assemble-bp verb\u3002 */\nasync function spawnAssembleBp(catalog: DeployCatalog): Promise<SpawnResult> {\n const args = [\n \"assemble-bp\",\n \"--src\",\n bpSrc(),\n \"--out\",\n bpOut(),\n \"--name\",\n BP_NAME,\n \"--uuid\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n if (catalog.bpModuleUuid) args.push(\"--module-uuid\", catalog.bpModuleUuid);\n if (catalog.dependencies && catalog.dependencies.length > 0) {\n const depsFile = path.join(buildRoot(), \"bp-dependencies.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(depsFile, JSON.stringify(catalog.dependencies), \"utf8\");\n args.push(\"--dependencies-json\", depsFile);\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`assembled BP uuid=${catalog.bpUuid}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn assemble-rp verb\uFF1B\u65E0 RP \u65F6\u6E05\u7406\u65E7\u4EA7\u7269\u3002 */\nasync function spawnAssembleRp(catalog: DeployCatalog, rpDirs: Record<string, string>): Promise<SpawnResult> {\n if (!catalog.rpUuid || Object.keys(rpDirs).length === 0) {\n await fs.rm(rpOut(), { recursive: true, force: true });\n pushLog(\"no enabled resource packs \u2014 RP skipped\", \"pack\", \"info\");\n return { code: 0, output: \"[pack-manager] no enabled resource packs \u2014 RP skipped\\n\" };\n }\n const mapFile = path.join(buildRoot(), \"rp-map.json\");\n await fs.mkdir(buildRoot(), { recursive: true });\n await fs.writeFile(mapFile, JSON.stringify(rpDirs), \"utf8\");\n const args = [\n \"assemble-rp\",\n \"--modules-json\",\n mapFile,\n \"--out\",\n rpOut(),\n \"--name\",\n RP_NAME,\n \"--uuid\",\n catalog.rpUuid,\n \"--version\",\n (catalog.rpVersion ?? [1, 0, 0]).join(\",\"),\n ];\n if (catalog.rpModuleUuid) args.push(\"--module-uuid\", catalog.rpModuleUuid);\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`assembled RP uuid=${catalog.rpUuid} (${Object.keys(rpDirs).length} modules)`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn deploy verb\uFF1B\u65E0 RP \u65F6\u5E26 --clear-rp\u3002 */\nasync function spawnDeploy(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const args = [\n \"deploy\",\n \"--bds-root\",\n bdsRoot,\n \"--level\",\n levelName,\n \"--bp-src\",\n bpOut(),\n \"--bp-name\",\n BP_NAME,\n \"--rp-name\",\n RP_NAME,\n ];\n if (catalog.rpUuid && existsSync(rpOut())) {\n args.push(\"--rp-src\", rpOut());\n } else {\n args.push(\"--clear-rp\");\n }\n const r = await spawnPackManager(args);\n if (r.code === 0) {\n pushLog(`deployed to worlds/${levelName}`, \"pack\", \"info\");\n }\n return r;\n}\n\n/** spawn enable-pack verb\uFF1ABP \u5FC5\u987B\uFF0CRP \u4EC5\u5728\u6709 UUID \u65F6\u3002 */\nasync function spawnEnablePacks(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot, levelName } = resolveBdsContext();\n const worldsDir = path.join(bdsRoot, \"worlds\");\n let output = \"\";\n const bpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n catalog.bpUuid,\n \"--version\",\n catalog.bpVersion.join(\",\"),\n ];\n const bpR = await spawnPackManager(bpArgs);\n output += bpR.output;\n if (bpR.code !== 0) return { code: bpR.code, output };\n pushLog(`enabled behavior pack ${catalog.bpUuid} in world list`, \"pack\", \"info\");\n if (catalog.rpUuid && catalog.rpVersion) {\n const rpArgs = [\n \"enable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n catalog.rpUuid,\n \"--version\",\n catalog.rpVersion.join(\",\"),\n ];\n const rpR = await spawnPackManager(rpArgs);\n output += rpR.output;\n if (rpR.code !== 0) return { code: rpR.code, output };\n pushLog(`enabled resource pack ${catalog.rpUuid} in world list`, \"pack\", \"info\");\n }\n return { code: 0, output };\n}\n\n/** spawn disable-pack verb\uFF1A\u6E05\u7406\u8FC7\u671F UUID\uFF08uuid \u8F6E\u6362 / \u4E0D\u518D\u63D0\u4F9B RP\uFF09\u3002 */\nasync function spawnDisableStale(current: DeployCatalog, bdsRoot: string, levelName: string): Promise<void> {\n const previous = await collectDeployedPackUuids(bdsRoot, levelName);\n const worldsDir = path.join(bdsRoot, \"worlds\");\n for (const staleRp of previous.rp) {\n if (staleRp === (current.rpUuid ?? null)) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"resource\",\n \"--pack-id\",\n staleRp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale resource pack ${staleRp}`, \"pack\", \"info\");\n } else {\n pushLog(`disable stale RP ${staleRp} failed: ${r.output.trim()}`, \"pack\", \"warn\");\n }\n }\n for (const staleBp of previous.bp) {\n if (staleBp === current.bpUuid) continue;\n const r = await spawnPackManager([\n \"disable-pack\",\n \"--worlds-dir\",\n worldsDir,\n \"--level\",\n levelName,\n \"--kind\",\n \"behavior\",\n \"--pack-id\",\n staleBp,\n \"--version\",\n \"1,0,0\",\n ]);\n if (r.code === 0) {\n pushLog(`disabled stale behavior pack ${staleBp}`, \"pack\", \"info\");\n } else {\n pushLog(`disable stale BP ${staleBp} failed: ${r.output.trim()}`, \"pack\", \"warn\");\n }\n }\n}\n\n/** \u901A\u8FC7 bds-tools \u7684 list-installed + read-manifest \u62FF\u5230 deployed UUID\uFF08spawn\uFF09\u3002 */\nasync function collectDeployedPackUuids(\n bdsRoot: string,\n levelName: string\n): Promise<{ bp: Set<string>; rp: Set<string> }> {\n const bp = new Set<string>();\n const rp = new Set<string>();\n const cat = readDeployedCatalog(bdsRoot, levelName);\n if (cat?.bpUuid) bp.add(cat.bpUuid);\n if (cat?.rpUuid) rp.add(cat.rpUuid);\n // \u901A\u8FC7 read-manifest \u770B\u4E16\u754C\u78C1\u76D8 BP/RP manifest \u7684 uuid\uFF0C\u4F5C\u4E3A catalog \u7F3A\u5931\u65F6\u7684\u515C\u5E95\u3002\n const bpDir = path.join(bdsRoot, \"worlds\", levelName, \"behavior_packs\", BP_NAME);\n const rpDir = path.join(bdsRoot, \"worlds\", levelName, \"resource_packs\", RP_NAME);\n const bpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", bpDir]);\n if (bpR.code === 0) {\n try {\n const j = JSON.parse(bpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) bp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n const rpR = await spawnPackManager([\"read-manifest\", \"--pack-dir\", rpDir]);\n if (rpR.code === 0) {\n try {\n const j = JSON.parse(rpR.output.trim()) as { uuid?: string } | null;\n if (j?.uuid) rp.add(j.uuid);\n } catch {\n /* ignore */\n }\n }\n return { bp, rp };\n}\n\n/** spawn ensure-permission verb\u3002 */\nasync function spawnEnsurePermission(catalog: DeployCatalog): Promise<SpawnResult> {\n const { bdsRoot } = resolveBdsContext();\n const r = await spawnPackManager([\"ensure-permission\", \"--bds-root\", bdsRoot, \"--pack-id\", catalog.bpUuid]);\n return r;\n}\n\nexport type BuildModulePacksResult = {\n success: boolean;\n message: string;\n catalog?: DeployCatalog;\n};\n\n/**\n * \u7EC4\u88C5 BP + RP \u7EAF\u903B\u8F91\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n * \u4EC5\u5F53 catalog \u4E0E\u4E16\u754C\u5185\u5DF2\u90E8\u7F72\u4E0D\u4E00\u81F4\u65F6\u6267\u884C\uFF1B\u5426\u5219\u76F4\u63A5\u6253\"\u5DF2\u540C\u6B65\"\u3002\n */\nexport async function buildModulePacks(force = false): Promise<BuildModulePacksResult> {\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const deployed = readDeployedCatalog(bdsRoot, levelName);\n const desired = await computeDesiredCatalog(deployed ? reusePackIds(deployed) : undefined);\n\n if (!force && deployed && catalogsEqual(desired, deployed)) {\n return {\n success: true,\n message: formatPackLoadInfo(desired, false),\n catalog: deployed,\n };\n }\n\n pushLog(`building BP/RP (modules=${Object.keys(desired.modules).length})\u2026`, \"pack\", \"info\");\n await bundleBehaviorPackScript();\n\n const mods = await scanLocalModules();\n const rpDirs: Record<string, string> = {};\n for (const m of mods) {\n if (!m.enabled || !m.hasResourcePack) continue;\n rpDirs[m.folderId] = path.join(\"modules\", \"packages\", m.folderId, \"resource_pack\");\n }\n\n const bpR = await spawnAssembleBp(desired);\n if (bpR.code !== 0) {\n return {\n success: false,\n message: c.red(bpR.output.trim() || `assemble-bp exit ${bpR.code}`),\n };\n }\n const rpR = await spawnAssembleRp(desired, rpDirs);\n if (rpR.code !== 0) {\n return {\n success: false,\n message: c.red(rpR.output.trim() || `assemble-rp exit ${rpR.code}`),\n };\n }\n\n desired.generatedAt = Date.now();\n if (Object.keys(rpDirs).length === 0) {\n desired.rpUuid = null;\n desired.rpVersion = null;\n }\n writeJson(path.join(bpOut(), DEPLOY_CATALOG_NAME), desired);\n\n return {\n success: true,\n message: formatPackLoadInfo(desired, true),\n catalog: desired,\n };\n } catch (e) {\n return {\n success: false,\n message: c.red((e as Error).message),\n };\n }\n}\n\n/**\n * `sfmc mod build` \u2014\u2014 \u7EC4\u88C5 BP + RP\uFF08\u4E0D\u90E8\u7F72\uFF09\u3002\n */\nexport async function cmdModuleBuild(_args: string[] = []): Promise<string> {\n // \u663E\u5F0F `mod build` \u5FC5\u987B\u91CD\u5EFA\uFF1B\u589E\u91CF\u8DF3\u8FC7\u53EA\u5C5E\u4E8E\u542F\u52A8\u81EA\u68C0\u4E0E\u975E\u5F3A\u5236 reload\u3002\n const res = await buildModulePacks(true);\n return res.message;\n}\n\n/**\n * `sfmc mod reload [--build-only] [--force]` \u2014\u2014 \u7EC4\u88C5 + \u90E8\u7F72 + \u6E05\u7406\u8FC7\u671F + \u5199\u6743\u9650 + \uFF08\u9ED8\u8BA4\uFF09\u53D1 reload \u5230 BDS\u3002\n */\nexport async function cmdModuleReload(args: string[] = []): Promise<string> {\n const buildOnly = args?.includes(\"--build-only\") ?? false;\n const force = args?.includes(\"--force\") || args?.includes(\"-f\");\n const parts: string[] = [];\n\n const buildRes = await buildModulePacks(force);\n parts.push(buildRes.message.trimEnd());\n if (!buildRes.success || !buildRes.catalog) {\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n try {\n const { bdsRoot, levelName } = resolveBdsContext();\n const desired = buildRes.catalog;\n\n const depR = await spawnDeploy(desired);\n if (depR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(depR.output.trim() || `deploy exit ${depR.code}`);\n }\n parts.push(depR.output.trimEnd());\n\n writeJson(path.join(deployedBpDir(bdsRoot, levelName), DEPLOY_CATALOG_NAME), desired);\n\n await spawnDisableStale(desired, bdsRoot, levelName);\n\n const enR = await spawnEnablePacks(desired);\n if (enR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(enR.output.trim() || `enable-pack exit ${enR.code}`);\n }\n parts.push(enR.output.trimEnd());\n\n const perR = await spawnEnsurePermission(desired);\n if (perR.code !== 0) {\n return parts.join(\"\\n\") + \"\\n\" + c.red(perR.output.trim() || `ensure-permission exit ${perR.code}`);\n }\n parts.push(perR.output.trimEnd());\n } catch (e) {\n return parts.join(\"\\n\") + \"\\n\" + c.red((e as Error).message);\n }\n\n if (buildOnly) {\n parts.push(c.dim(t(\"reload.buildOnly\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n\n const { isServiceRunning } = await import(\"./services.js\");\n if (!(await isServiceRunning(\"bds\"))) {\n parts.push(c.yellow(t(\"reload.bdsNotRunning\")));\n return parts.join(\"\\n\") + \"\\n\";\n }\n const { cmdSend } = await import(\"./commands.js\");\n parts.push((await cmdSend(\"bds\", \"reload\")).trimEnd());\n parts.push(c.green(t(\"reload.sent\")));\n return parts.join(\"\\n\") + \"\\n\";\n}\n\nfunction reusePackIds(deployed: DeployCatalog): Parameters<typeof computeDesiredCatalog>[0] {\n return {\n bpUuid: deployed.bpUuid,\n rpUuid: deployed.rpUuid,\n bpVersion: deployed.bpVersion,\n rpVersion: deployed.rpVersion,\n ...(deployed.bpModuleUuid ? { bpModuleUuid: deployed.bpModuleUuid } : {}),\n ...(deployed.rpModuleUuid ? { rpModuleUuid: deployed.rpModuleUuid } : {}),\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -34,15 +34,18 @@ export declare class WindowHost {
34
34
  setBuffer(id: string, lines: string[]): void;
35
35
  invalidateBuffer(id: string): void;
36
36
  private appendToBuffer;
37
- /** 按活跃服务同步 ServiceWindow id 列表(id = svc:<name>) */
37
+ /** 按活跃服务与平台窗同步轮转 id 列表(id = svc:<name> 或 sfmc) */
38
38
  setServiceOrder(ids: string[]): void;
39
39
  open(id: string): boolean;
40
40
  back(): boolean;
41
41
  /**
42
- * 在服务窗之间循环;返回新激活窗的 serviceName(供同步发送目标)。
42
+ * 在服务窗与平台窗之间循环;返回是否成功切换及新激活窗的 serviceName(供同步发送目标)。
43
43
  * 若当前在非服务窗,先回到服务环。
44
44
  */
45
- cycleServiceWindows(): ServiceName | null;
45
+ cycleServiceWindows(): {
46
+ switched: boolean;
47
+ serviceName: ServiceName | null;
48
+ };
46
49
  /**
47
50
  * 新日志:写入所有已 seed 缓存且 accept 的窗口;仅活动窗刷到 TTY。
48
51
  * 活动窗尚未 seed:只刷 TTY(随后 showActiveWindow 会 seed 含历史的缓存)。
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/repl-windows/host.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,qBAAqB;IACrB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;IAE1D,YAAY,IAAI,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAGxE;IAED,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAE9B;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAS3B;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED,SAAS,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,SAAS,IAAI,YAAY,CAUxB;IAED,6BAA6B;IAC7B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7B;IAED,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEvC;IAED,iBAAiB;IACjB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3C;IAED,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,OAAO,CAAC,cAAc;IAStB,mDAAmD;IACnD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAenC;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiBxB;IAED,IAAI,IAAI,OAAO,CAYd;IAED;;;OAGG;IACH,mBAAmB,IAAI,WAAW,GAAG,IAAI,CAWxC;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAe9B;IAED,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAIxE;IAED,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,eAAe,CASzC;IAED,YAAY,IAAI,OAAO,CAEtB;CACF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEzD"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/repl-windows/host.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,qBAAqB;IACrB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;IAE1D,YAAY,IAAI,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,EAGxE;IAED,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAE9B;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAS3B;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED,SAAS,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,SAAS,IAAI,YAAY,CAUxB;IAED,6BAA6B;IAC7B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7B;IAED,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEvC;IAED,iBAAiB;IACjB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAE3C;IAED,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,OAAO,CAAC,cAAc;IAStB,kDAAkD;IAClD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAqBnC;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiBxB;IAED,IAAI,IAAI,OAAO,CAYd;IAED;;;OAGG;IACH,mBAAmB,IAAI;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,CAc5E;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAe9B;IAED,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAIxE;IAED,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,eAAe,CASzC;IAED,YAAY,IAAI,OAAO,CAEtB;CACF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEzD"}
@@ -1,4 +1,5 @@
1
1
  import { wrapLogLine } from "../logs.js";
2
+ import { SFMC_WINDOW_ID } from "./sfmc-window.js";
2
3
  class WindowHost {
3
4
  windows = /* @__PURE__ */ new Map();
4
5
  /** 窗口 id → 已渲染(已 wrap)的行;切回时直接 dump,无需重拉源 */
@@ -68,17 +69,19 @@ class WindowHost {
68
69
  }
69
70
  buf.push(wrappedLine);
70
71
  }
71
- /** 按活跃服务同步 ServiceWindow id 列表(id = svc:<name>) */
72
+ /** 按活跃服务与平台窗同步轮转 id 列表(id = svc:<name> 或 sfmc) */
72
73
  setServiceOrder(ids) {
73
74
  this.serviceOrder = [...ids];
74
- const stale = [...this.windows.keys()].filter((id) => id.startsWith("svc:") && !ids.includes(id));
75
+ const stale = [...this.windows.keys()].filter(
76
+ (id) => (id.startsWith("svc:") || id === SFMC_WINDOW_ID) && !ids.includes(id)
77
+ );
75
78
  for (const id of stale) {
76
79
  this.windows.delete(id);
77
80
  this.buffers.delete(id);
78
81
  if (this.activeId === id) this.activeId = null;
79
82
  if (this.previousId === id) this.previousId = null;
80
83
  }
81
- if (this.activeId?.startsWith("svc:") && !ids.includes(this.activeId)) {
84
+ if (this.activeId && (this.activeId.startsWith("svc:") || this.activeId === SFMC_WINDOW_ID) && !ids.includes(this.activeId)) {
82
85
  this.activeId = null;
83
86
  }
84
87
  if (!this.activeId && ids.length > 0) {
@@ -114,11 +117,11 @@ class WindowHost {
114
117
  return this.open(fallback);
115
118
  }
116
119
  /**
117
- * 在服务窗之间循环;返回新激活窗的 serviceName(供同步发送目标)。
120
+ * 在服务窗与平台窗之间循环;返回是否成功切换及新激活窗的 serviceName(供同步发送目标)。
118
121
  * 若当前在非服务窗,先回到服务环。
119
122
  */
120
123
  cycleServiceWindows() {
121
- if (this.serviceOrder.length === 0) return null;
124
+ if (this.serviceOrder.length === 0) return { switched: false, serviceName: null };
122
125
  const cur = this.activeId;
123
126
  const idx = cur ? this.serviceOrder.indexOf(cur) : -1;
124
127
  if (idx < 0) {
@@ -127,7 +130,10 @@ class WindowHost {
127
130
  const next = this.serviceOrder[(idx + 1) % this.serviceOrder.length];
128
131
  this.open(next);
129
132
  }
130
- return this.getActive()?.serviceName ?? null;
133
+ return {
134
+ switched: true,
135
+ serviceName: this.getActive()?.serviceName ?? null
136
+ };
131
137
  }
132
138
  /**
133
139
  * 新日志:写入所有已 seed 缓存且 accept 的窗口;仅活动窗刷到 TTY。
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/repl-windows/host.ts"],
4
- "sourcesContent": ["/**\n * repl-windows/host.ts \u2014 \u7A97\u53E3\u6CE8\u518C\u4E0E\u5207\u6362\uFF08\u4E0D\u5199\u4E1A\u52A1\uFF0C\u53EA\u8C03\u5EA6 ReplWindow\uFF09\n *\n * \u6BCF\u6247\u7A97\u7EF4\u62A4\u5DF2\u6E32\u67D3\u884C\u7F13\u5B58\uFF1A\u5207\u8D70\u6E05\u5C4F\uFF0C\u5207\u56DE\u76F4\u63A5\u6062\u590D\uFF1B\u540E\u53F0\u4ECD\u628A\u5339\u914D\u65E5\u5FD7\u5199\u5165\u5BF9\u5E94\u7F13\u5B58\u3002\n */\nimport { wrapLogLine, type UnifiedLog } from \"../logs.js\";\nimport type { ServiceName } from \"../services.js\";\nimport type { ReplWindow, WindowChrome, WindowKeyEvent, WindowKeyResult } from \"./types.js\";\n\nexport type HostWriteLog = (wrappedLine: string) => void;\n\nexport class WindowHost {\n private readonly windows = new Map<string, ReplWindow>();\n /** \u7A97\u53E3 id \u2192 \u5DF2\u6E32\u67D3\uFF08\u5DF2 wrap\uFF09\u7684\u884C\uFF1B\u5207\u56DE\u65F6\u76F4\u63A5 dump\uFF0C\u65E0\u9700\u91CD\u62C9\u6E90 */\n private readonly buffers = new Map<string, string[]>();\n /** \u670D\u52A1\u7A97\u5FAA\u73AF\u987A\u5E8F\uFF08\u4EC5\u6D3B\u8DC3\u670D\u52A1\uFF09 */\n private serviceOrder: string[] = [];\n private activeId: string | null = null;\n private previousId: string | null = null;\n private readonly writeLog: HostWriteLog;\n private readonly onChromeChange: (() => void) | undefined;\n\n constructor(opts: { writeLog: HostWriteLog; onChromeChange?: () => void }) {\n this.writeLog = opts.writeLog;\n this.onChromeChange = opts.onChromeChange;\n }\n\n register(win: ReplWindow): void {\n this.windows.set(win.id, win);\n }\n\n unregister(id: string): void {\n if (this.activeId === id) {\n this.activeId = this.previousId;\n this.previousId = null;\n }\n if (this.previousId === id) this.previousId = null;\n this.windows.delete(id);\n this.buffers.delete(id);\n this.serviceOrder = this.serviceOrder.filter((x) => x !== id);\n }\n\n has(id: string): boolean {\n return this.windows.has(id);\n }\n\n getActive(): ReplWindow | undefined {\n return this.activeId ? this.windows.get(this.activeId) : undefined;\n }\n\n getActiveId(): string | null {\n return this.activeId;\n }\n\n getChrome(): WindowChrome {\n const w = this.getActive();\n if (!w) {\n return { showsInput: true, footerShortcuts: \"\", title: \"\" };\n }\n return {\n showsInput: w.showsInput,\n footerShortcuts: w.footerShortcuts,\n title: w.title,\n };\n }\n\n /** \u662F\u5426\u5DF2\u6709\u5C55\u793A\u7F13\u5B58\uFF08\u6709\u5219\u5207\u56DE\u65F6\u52FF\u518D seed\uFF09 */\n hasBuffer(id: string): boolean {\n return this.buffers.has(id);\n }\n\n getBuffer(id: string): readonly string[] {\n return this.buffers.get(id) ?? [];\n }\n\n /** \u9996\u6B21\u8FDB\u5165\u65F6\u5199\u5165\u79CD\u5B50\u884C */\n setBuffer(id: string, lines: string[]): void {\n this.buffers.set(id, [...lines]);\n }\n\n invalidateBuffer(id: string): void {\n this.buffers.delete(id);\n }\n\n private appendToBuffer(id: string, wrappedLine: string): void {\n let buf = this.buffers.get(id);\n if (!buf) {\n buf = [];\n this.buffers.set(id, buf);\n }\n buf.push(wrappedLine);\n }\n\n /** \u6309\u6D3B\u8DC3\u670D\u52A1\u540C\u6B65 ServiceWindow id \u5217\u8868\uFF08id = svc:<name>\uFF09 */\n setServiceOrder(ids: string[]): void {\n this.serviceOrder = [...ids];\n const stale = [...this.windows.keys()].filter((id) => id.startsWith(\"svc:\") && !ids.includes(id));\n for (const id of stale) {\n this.windows.delete(id);\n this.buffers.delete(id);\n if (this.activeId === id) this.activeId = null;\n if (this.previousId === id) this.previousId = null;\n }\n if (this.activeId?.startsWith(\"svc:\") && !ids.includes(this.activeId)) {\n this.activeId = null;\n }\n if (!this.activeId && ids.length > 0) {\n this.open(ids[0]!);\n }\n }\n\n open(id: string): boolean {\n const next = this.windows.get(id);\n if (!next) return false;\n if (this.activeId === id) {\n next.onActivate?.();\n this.onChromeChange?.();\n return true;\n }\n const prev = this.getActive();\n prev?.onDeactivate?.();\n if (this.activeId && this.activeId !== id) {\n this.previousId = this.activeId;\n }\n this.activeId = id;\n next.onActivate?.();\n this.onChromeChange?.();\n return true;\n }\n\n back(): boolean {\n const fallback =\n (this.previousId && this.windows.has(this.previousId) ? this.previousId : null) ??\n this.serviceOrder.find((id) => this.windows.has(id)) ??\n null;\n this.previousId = null;\n if (!fallback) {\n this.activeId = null;\n this.onChromeChange?.();\n return false;\n }\n return this.open(fallback);\n }\n\n /**\n * \u5728\u670D\u52A1\u7A97\u4E4B\u95F4\u5FAA\u73AF\uFF1B\u8FD4\u56DE\u65B0\u6FC0\u6D3B\u7A97\u7684 serviceName\uFF08\u4F9B\u540C\u6B65\u53D1\u9001\u76EE\u6807\uFF09\u3002\n * \u82E5\u5F53\u524D\u5728\u975E\u670D\u52A1\u7A97\uFF0C\u5148\u56DE\u5230\u670D\u52A1\u73AF\u3002\n */\n cycleServiceWindows(): ServiceName | null {\n if (this.serviceOrder.length === 0) return null;\n const cur = this.activeId;\n const idx = cur ? this.serviceOrder.indexOf(cur) : -1;\n if (idx < 0) {\n this.open(this.serviceOrder[0]!);\n } else {\n const next = this.serviceOrder[(idx + 1) % this.serviceOrder.length]!;\n this.open(next);\n }\n return this.getActive()?.serviceName ?? null;\n }\n\n /**\n * \u65B0\u65E5\u5FD7\uFF1A\u5199\u5165\u6240\u6709\u5DF2 seed \u7F13\u5B58\u4E14 accept \u7684\u7A97\u53E3\uFF1B\u4EC5\u6D3B\u52A8\u7A97\u5237\u5230 TTY\u3002\n * \u6D3B\u52A8\u7A97\u5C1A\u672A seed\uFF1A\u53EA\u5237 TTY\uFF08\u968F\u540E showActiveWindow \u4F1A seed \u542B\u5386\u53F2\u7684\u7F13\u5B58\uFF09\u3002\n */\n routeLog(log: UnifiedLog): void {\n for (const [id, w] of this.windows) {\n if (!w.acceptLog(log)) continue;\n if (!this.buffers.has(id)) {\n if (id === this.activeId) {\n const { text, indent } = w.formatLogLine(log);\n this.writeLog(wrapLogLine(text, indent));\n }\n continue;\n }\n const { text, indent } = w.formatLogLine(log);\n const wrapped = wrapLogLine(text, indent);\n this.appendToBuffer(id, wrapped);\n if (id === this.activeId) this.writeLog(wrapped);\n }\n }\n\n /** \u8FD4\u56DE\u6D3B\u52A8\u7A97\u5BF9\u65E5\u5FD7\u7684\u5C55\u793A\u7ED3\u679C\uFF08\u542B acceptLog\uFF09 */\n formatActiveLog(log: UnifiedLog): { text: string; indent: number } | null {\n const w = this.getActive();\n if (!w || !w.acceptLog(log)) return null;\n return w.formatLogLine(log);\n }\n\n onKey(ev: WindowKeyEvent): WindowKeyResult {\n const w = this.getActive();\n if (!w?.onKey) return { action: \"none\" };\n const r = w.onKey(ev);\n if (r.action === \"back\") {\n this.back();\n return { action: \"redraw\" };\n }\n return r;\n }\n\n isLogsActive(): boolean {\n return this.activeId === \"logs\";\n }\n}\n\nexport function serviceWindowId(name: ServiceName): string {\n return `svc:${name}`;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * repl-windows/host.ts \u2014 \u7A97\u53E3\u6CE8\u518C\u4E0E\u5207\u6362\uFF08\u4E0D\u5199\u4E1A\u52A1\uFF0C\u53EA\u8C03\u5EA6 ReplWindow\uFF09\n *\n * \u6BCF\u6247\u7A97\u7EF4\u62A4\u5DF2\u6E32\u67D3\u884C\u7F13\u5B58\uFF1A\u5207\u8D70\u6E05\u5C4F\uFF0C\u5207\u56DE\u76F4\u63A5\u6062\u590D\uFF1B\u540E\u53F0\u4ECD\u628A\u5339\u914D\u65E5\u5FD7\u5199\u5165\u5BF9\u5E94\u7F13\u5B58\u3002\n */\nimport { wrapLogLine, type UnifiedLog } from \"../logs.js\";\nimport type { ServiceName } from \"../services.js\";\nimport { SFMC_WINDOW_ID } from \"./sfmc-window.js\";\nimport type { ReplWindow, WindowChrome, WindowKeyEvent, WindowKeyResult } from \"./types.js\";\n\nexport type HostWriteLog = (wrappedLine: string) => void;\n\nexport class WindowHost {\n private readonly windows = new Map<string, ReplWindow>();\n /** \u7A97\u53E3 id \u2192 \u5DF2\u6E32\u67D3\uFF08\u5DF2 wrap\uFF09\u7684\u884C\uFF1B\u5207\u56DE\u65F6\u76F4\u63A5 dump\uFF0C\u65E0\u9700\u91CD\u62C9\u6E90 */\n private readonly buffers = new Map<string, string[]>();\n /** \u670D\u52A1\u7A97\u5FAA\u73AF\u987A\u5E8F\uFF08\u4EC5\u6D3B\u8DC3\u670D\u52A1\uFF09 */\n private serviceOrder: string[] = [];\n private activeId: string | null = null;\n private previousId: string | null = null;\n private readonly writeLog: HostWriteLog;\n private readonly onChromeChange: (() => void) | undefined;\n\n constructor(opts: { writeLog: HostWriteLog; onChromeChange?: () => void }) {\n this.writeLog = opts.writeLog;\n this.onChromeChange = opts.onChromeChange;\n }\n\n register(win: ReplWindow): void {\n this.windows.set(win.id, win);\n }\n\n unregister(id: string): void {\n if (this.activeId === id) {\n this.activeId = this.previousId;\n this.previousId = null;\n }\n if (this.previousId === id) this.previousId = null;\n this.windows.delete(id);\n this.buffers.delete(id);\n this.serviceOrder = this.serviceOrder.filter((x) => x !== id);\n }\n\n has(id: string): boolean {\n return this.windows.has(id);\n }\n\n getActive(): ReplWindow | undefined {\n return this.activeId ? this.windows.get(this.activeId) : undefined;\n }\n\n getActiveId(): string | null {\n return this.activeId;\n }\n\n getChrome(): WindowChrome {\n const w = this.getActive();\n if (!w) {\n return { showsInput: true, footerShortcuts: \"\", title: \"\" };\n }\n return {\n showsInput: w.showsInput,\n footerShortcuts: w.footerShortcuts,\n title: w.title,\n };\n }\n\n /** \u662F\u5426\u5DF2\u6709\u5C55\u793A\u7F13\u5B58\uFF08\u6709\u5219\u5207\u56DE\u65F6\u52FF\u518D seed\uFF09 */\n hasBuffer(id: string): boolean {\n return this.buffers.has(id);\n }\n\n getBuffer(id: string): readonly string[] {\n return this.buffers.get(id) ?? [];\n }\n\n /** \u9996\u6B21\u8FDB\u5165\u65F6\u5199\u5165\u79CD\u5B50\u884C */\n setBuffer(id: string, lines: string[]): void {\n this.buffers.set(id, [...lines]);\n }\n\n invalidateBuffer(id: string): void {\n this.buffers.delete(id);\n }\n\n private appendToBuffer(id: string, wrappedLine: string): void {\n let buf = this.buffers.get(id);\n if (!buf) {\n buf = [];\n this.buffers.set(id, buf);\n }\n buf.push(wrappedLine);\n }\n\n /** \u6309\u6D3B\u8DC3\u670D\u52A1\u4E0E\u5E73\u53F0\u7A97\u540C\u6B65\u8F6E\u8F6C id \u5217\u8868\uFF08id = svc:<name> \u6216 sfmc\uFF09 */\n setServiceOrder(ids: string[]): void {\n this.serviceOrder = [...ids];\n const stale = [...this.windows.keys()].filter(\n (id) => (id.startsWith(\"svc:\") || id === SFMC_WINDOW_ID) && !ids.includes(id)\n );\n for (const id of stale) {\n this.windows.delete(id);\n this.buffers.delete(id);\n if (this.activeId === id) this.activeId = null;\n if (this.previousId === id) this.previousId = null;\n }\n if (\n this.activeId &&\n (this.activeId.startsWith(\"svc:\") || this.activeId === SFMC_WINDOW_ID) &&\n !ids.includes(this.activeId)\n ) {\n this.activeId = null;\n }\n if (!this.activeId && ids.length > 0) {\n this.open(ids[0]!);\n }\n }\n\n open(id: string): boolean {\n const next = this.windows.get(id);\n if (!next) return false;\n if (this.activeId === id) {\n next.onActivate?.();\n this.onChromeChange?.();\n return true;\n }\n const prev = this.getActive();\n prev?.onDeactivate?.();\n if (this.activeId && this.activeId !== id) {\n this.previousId = this.activeId;\n }\n this.activeId = id;\n next.onActivate?.();\n this.onChromeChange?.();\n return true;\n }\n\n back(): boolean {\n const fallback =\n (this.previousId && this.windows.has(this.previousId) ? this.previousId : null) ??\n this.serviceOrder.find((id) => this.windows.has(id)) ??\n null;\n this.previousId = null;\n if (!fallback) {\n this.activeId = null;\n this.onChromeChange?.();\n return false;\n }\n return this.open(fallback);\n }\n\n /**\n * \u5728\u670D\u52A1\u7A97\u4E0E\u5E73\u53F0\u7A97\u4E4B\u95F4\u5FAA\u73AF\uFF1B\u8FD4\u56DE\u662F\u5426\u6210\u529F\u5207\u6362\u53CA\u65B0\u6FC0\u6D3B\u7A97\u7684 serviceName\uFF08\u4F9B\u540C\u6B65\u53D1\u9001\u76EE\u6807\uFF09\u3002\n * \u82E5\u5F53\u524D\u5728\u975E\u670D\u52A1\u7A97\uFF0C\u5148\u56DE\u5230\u670D\u52A1\u73AF\u3002\n */\n cycleServiceWindows(): { switched: boolean; serviceName: ServiceName | null } {\n if (this.serviceOrder.length === 0) return { switched: false, serviceName: null };\n const cur = this.activeId;\n const idx = cur ? this.serviceOrder.indexOf(cur) : -1;\n if (idx < 0) {\n this.open(this.serviceOrder[0]!);\n } else {\n const next = this.serviceOrder[(idx + 1) % this.serviceOrder.length]!;\n this.open(next);\n }\n return {\n switched: true,\n serviceName: this.getActive()?.serviceName ?? null,\n };\n }\n\n /**\n * \u65B0\u65E5\u5FD7\uFF1A\u5199\u5165\u6240\u6709\u5DF2 seed \u7F13\u5B58\u4E14 accept \u7684\u7A97\u53E3\uFF1B\u4EC5\u6D3B\u52A8\u7A97\u5237\u5230 TTY\u3002\n * \u6D3B\u52A8\u7A97\u5C1A\u672A seed\uFF1A\u53EA\u5237 TTY\uFF08\u968F\u540E showActiveWindow \u4F1A seed \u542B\u5386\u53F2\u7684\u7F13\u5B58\uFF09\u3002\n */\n routeLog(log: UnifiedLog): void {\n for (const [id, w] of this.windows) {\n if (!w.acceptLog(log)) continue;\n if (!this.buffers.has(id)) {\n if (id === this.activeId) {\n const { text, indent } = w.formatLogLine(log);\n this.writeLog(wrapLogLine(text, indent));\n }\n continue;\n }\n const { text, indent } = w.formatLogLine(log);\n const wrapped = wrapLogLine(text, indent);\n this.appendToBuffer(id, wrapped);\n if (id === this.activeId) this.writeLog(wrapped);\n }\n }\n\n /** \u8FD4\u56DE\u6D3B\u52A8\u7A97\u5BF9\u65E5\u5FD7\u7684\u5C55\u793A\u7ED3\u679C\uFF08\u542B acceptLog\uFF09 */\n formatActiveLog(log: UnifiedLog): { text: string; indent: number } | null {\n const w = this.getActive();\n if (!w || !w.acceptLog(log)) return null;\n return w.formatLogLine(log);\n }\n\n onKey(ev: WindowKeyEvent): WindowKeyResult {\n const w = this.getActive();\n if (!w?.onKey) return { action: \"none\" };\n const r = w.onKey(ev);\n if (r.action === \"back\") {\n this.back();\n return { action: \"redraw\" };\n }\n return r;\n }\n\n isLogsActive(): boolean {\n return this.activeId === \"logs\";\n }\n}\n\nexport function serviceWindowId(name: ServiceName): string {\n return `svc:${name}`;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["text", "indent"]
7
7
  }
@@ -0,0 +1,72 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { WindowHost, serviceWindowId } from "./host.js";
4
+ import { createServiceWindow } from "./service-window.js";
5
+ import { createSfmcWindow, SFMC_WINDOW_ID } from "./sfmc-window.js";
6
+ test("WindowHost: \u7BA1\u7406\u670D\u52A1\u7A97\u4E0E SFMC \u5E73\u53F0\u7A97\u751F\u547D\u5468\u671F", () => {
7
+ const written = [];
8
+ const host = new WindowHost({ writeLog: (l) => written.push(l) });
9
+ let activeTargets = ["bds"];
10
+ host.register(createServiceWindow("bds"));
11
+ host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));
12
+ host.setServiceOrder([serviceWindowId("bds"), SFMC_WINDOW_ID]);
13
+ assert.equal(host.getActiveId(), serviceWindowId("bds"));
14
+ assert.equal(host.getActive()?.title, "BDS");
15
+ assert.equal(host.getActive()?.serviceName, "bds");
16
+ const res1 = host.cycleServiceWindows();
17
+ assert.equal(res1.switched, true);
18
+ assert.equal(res1.serviceName, null);
19
+ assert.equal(host.getActiveId(), SFMC_WINDOW_ID);
20
+ assert.equal(host.getActive()?.title, "SFMC");
21
+ assert.equal(host.getActive()?.serviceName, void 0);
22
+ const res2 = host.cycleServiceWindows();
23
+ assert.equal(res2.switched, true);
24
+ assert.equal(res2.serviceName, "bds");
25
+ assert.equal(host.getActiveId(), serviceWindowId("bds"));
26
+ activeTargets = [];
27
+ host.setServiceOrder([]);
28
+ assert.equal(host.getActiveId(), null);
29
+ assert.equal(host.has(serviceWindowId("bds")), false);
30
+ assert.equal(host.has(SFMC_WINDOW_ID), false);
31
+ });
32
+ test("createSfmcWindow: acceptLog \u8FC7\u6EE4\u6D3B\u8DC3\u670D\u52A1\u65E5\u5FD7\u5E76\u63A5\u6536\u975E\u670D\u52A1/\u5E73\u53F0\u65E5\u5FD7", () => {
33
+ const activeTargets = ["bds", "db"];
34
+ const win = createSfmcWindow({ getActiveTargets: () => activeTargets });
35
+ const now = /* @__PURE__ */ new Date();
36
+ const bdsLog = { time: now, source: "bds", level: "info", text: "Server started" };
37
+ const dbLog = { time: now, source: "db", level: "info", text: "Database ready" };
38
+ const packLog = { time: now, source: "pack", level: "info", text: "assembled BP uuid=xxx" };
39
+ const sysLog = { time: now, source: "system", level: "info", text: "Platform initialized" };
40
+ const qqLog = { time: now, source: "qq", level: "info", text: "QQ stopped" };
41
+ assert.equal(win.acceptLog(bdsLog), false);
42
+ assert.equal(win.acceptLog(dbLog), false);
43
+ assert.equal(win.acceptLog(packLog), true);
44
+ assert.equal(win.acceptLog(sysLog), true);
45
+ assert.equal(win.acceptLog(qqLog), true);
46
+ const formatted = win.formatLogLine(packLog);
47
+ assert.ok(formatted.text.includes("[PAK]"));
48
+ });
49
+ test("WindowHost: routeLog \u5C06\u65E5\u5FD7\u6B63\u786E\u5206\u6D41\u5230\u6D3B\u52A8\u7A97\u53E3\u4E0E\u540E\u53F0\u7A97\u53E3\u7F13\u5B58", () => {
50
+ const written = [];
51
+ const host = new WindowHost({ writeLog: (l) => written.push(l) });
52
+ const activeTargets = ["bds"];
53
+ host.register(createServiceWindow("bds"));
54
+ host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));
55
+ host.setServiceOrder([serviceWindowId("bds"), SFMC_WINDOW_ID]);
56
+ host.setBuffer(serviceWindowId("bds"), []);
57
+ host.setBuffer(SFMC_WINDOW_ID, []);
58
+ assert.equal(host.getActiveId(), serviceWindowId("bds"));
59
+ const now = /* @__PURE__ */ new Date();
60
+ const bdsLog = { time: now, source: "bds", level: "info", text: "Hello BDS" };
61
+ const packLog = { time: now, source: "pack", level: "info", text: "Building pack" };
62
+ host.routeLog(bdsLog);
63
+ assert.equal(written.length, 1);
64
+ assert.ok(written[0]?.includes("Hello BDS"));
65
+ host.routeLog(packLog);
66
+ assert.equal(written.length, 1);
67
+ const sfmcBuffer = host.getBuffer(SFMC_WINDOW_ID);
68
+ assert.equal(sfmcBuffer.length, 1);
69
+ assert.ok(sfmcBuffer[0]?.includes("Building pack"));
70
+ assert.ok(sfmcBuffer[0]?.includes("[PAK]"));
71
+ });
72
+ //# sourceMappingURL=host.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/repl-windows/host.test.ts"],
4
+ "sourcesContent": ["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport type { UnifiedLog } from \"../logs.js\";\nimport type { ServiceName } from \"../services.js\";\nimport { WindowHost, serviceWindowId } from \"./host.js\";\nimport { createServiceWindow } from \"./service-window.js\";\nimport { createSfmcWindow, SFMC_WINDOW_ID } from \"./sfmc-window.js\";\n\ntest(\"WindowHost: \u7BA1\u7406\u670D\u52A1\u7A97\u4E0E SFMC \u5E73\u53F0\u7A97\u751F\u547D\u5468\u671F\", () => {\n const written: string[] = [];\n const host = new WindowHost({ writeLog: (l) => written.push(l) });\n\n let activeTargets: ServiceName[] = [\"bds\"];\n host.register(createServiceWindow(\"bds\"));\n host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));\n\n host.setServiceOrder([serviceWindowId(\"bds\"), SFMC_WINDOW_ID]);\n\n // \u521D\u59CB\u6FC0\u6D3B\u7B2C 1 \u4E2A\u7A97\u53E3\uFF08bds\uFF09\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n assert.equal(host.getActive()?.title, \"BDS\");\n assert.equal(host.getActive()?.serviceName, \"bds\");\n\n // Tab \u8F6E\u6362\u81F3 SFMC \u7A97\n const res1 = host.cycleServiceWindows();\n assert.equal(res1.switched, true);\n assert.equal(res1.serviceName, null);\n assert.equal(host.getActiveId(), SFMC_WINDOW_ID);\n assert.equal(host.getActive()?.title, \"SFMC\");\n assert.equal(host.getActive()?.serviceName, undefined);\n\n // \u518D\u6B21 Tab \u8F6E\u6362\u56DE BDS \u7A97\n const res2 = host.cycleServiceWindows();\n assert.equal(res2.switched, true);\n assert.equal(res2.serviceName, \"bds\");\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n\n // \u670D\u52A1\u505C\u6B62\uFF1AsetServiceOrder \u6E05\u7A7A\u65F6\u5E94\u6CE8\u9500\u670D\u52A1\u7A97\u4E0E SFMC \u7A97\n activeTargets = [];\n host.setServiceOrder([]);\n assert.equal(host.getActiveId(), null);\n assert.equal(host.has(serviceWindowId(\"bds\")), false);\n assert.equal(host.has(SFMC_WINDOW_ID), false);\n});\n\ntest(\"createSfmcWindow: acceptLog \u8FC7\u6EE4\u6D3B\u8DC3\u670D\u52A1\u65E5\u5FD7\u5E76\u63A5\u6536\u975E\u670D\u52A1/\u5E73\u53F0\u65E5\u5FD7\", () => {\n const activeTargets: ServiceName[] = [\"bds\", \"db\"];\n const win = createSfmcWindow({ getActiveTargets: () => activeTargets });\n\n const now = new Date();\n const bdsLog: UnifiedLog = { time: now, source: \"bds\", level: \"info\", text: \"Server started\" };\n const dbLog: UnifiedLog = { time: now, source: \"db\", level: \"info\", text: \"Database ready\" };\n const packLog: UnifiedLog = { time: now, source: \"pack\", level: \"info\", text: \"assembled BP uuid=xxx\" };\n const sysLog: UnifiedLog = { time: now, source: \"system\", level: \"info\", text: \"Platform initialized\" };\n const qqLog: UnifiedLog = { time: now, source: \"qq\", level: \"info\", text: \"QQ stopped\" };\n\n // \u6D3B\u8DC3\u670D\u52A1\uFF08bds, db\uFF09\u7684\u65E5\u5FD7\u5728 SFMC \u7A97\u88AB\u8FC7\u6EE4\n assert.equal(win.acceptLog(bdsLog), false);\n assert.equal(win.acceptLog(dbLog), false);\n\n // \u975E\u6D3B\u8DC3\u670D\u52A1\u6216\u5E73\u53F0\u65E5\u5FD7\uFF08pack, system, qq\uFF09\u5728 SFMC \u7A97\u88AB\u63A5\u6536\n assert.equal(win.acceptLog(packLog), true);\n assert.equal(win.acceptLog(sysLog), true);\n assert.equal(win.acceptLog(qqLog), true);\n\n // \u683C\u5F0F\u5316\u8F93\u51FA\u5E94\u5305\u542B\u6765\u6E90\u6807\u7B7E\uFF08omitSource: false\uFF09\n const formatted = win.formatLogLine(packLog);\n assert.ok(formatted.text.includes(\"[PAK]\"));\n});\n\ntest(\"WindowHost: routeLog \u5C06\u65E5\u5FD7\u6B63\u786E\u5206\u6D41\u5230\u6D3B\u52A8\u7A97\u53E3\u4E0E\u540E\u53F0\u7A97\u53E3\u7F13\u5B58\", () => {\n const written: string[] = [];\n const host = new WindowHost({ writeLog: (l) => written.push(l) });\n\n const activeTargets: ServiceName[] = [\"bds\"];\n host.register(createServiceWindow(\"bds\"));\n host.register(createSfmcWindow({ getActiveTargets: () => activeTargets }));\n host.setServiceOrder([serviceWindowId(\"bds\"), SFMC_WINDOW_ID]);\n\n // \u7ED9\u4E24\u4E2A\u7A97\u53E3\u9884\u8BBE buffer\uFF08\u6A21\u62DF seed\uFF09\n host.setBuffer(serviceWindowId(\"bds\"), []);\n host.setBuffer(SFMC_WINDOW_ID, []);\n\n // \u5F53\u524D\u5728 BDS \u7A97\n assert.equal(host.getActiveId(), serviceWindowId(\"bds\"));\n\n const now = new Date();\n const bdsLog: UnifiedLog = { time: now, source: \"bds\", level: \"info\", text: \"Hello BDS\" };\n const packLog: UnifiedLog = { time: now, source: \"pack\", level: \"info\", text: \"Building pack\" };\n\n // \u4EA7\u751F BDS \u65E5\u5FD7\uFF1A\u6D3B\u52A8\u7A97\u7ACB\u5373\u6536\u5230\u5199\u5165\n host.routeLog(bdsLog);\n assert.equal(written.length, 1);\n assert.ok(written[0]?.includes(\"Hello BDS\"));\n\n // \u4EA7\u751F Pack \u65E5\u5FD7\uFF1A\u5F53\u524D\u5728 BDS \u7A97\uFF0CTty \u4E0D\u76F4\u63A5\u5199\uFF0C\u4F46 SFMC \u7A97\u53E3\u540E\u53F0 buffer \u5E94\u8FFD\u52A0\n host.routeLog(packLog);\n assert.equal(written.length, 1); // \u6CA1\u6709\u76F4\u63A5\u5199\u5230\u5F53\u524D Tty\n const sfmcBuffer = host.getBuffer(SFMC_WINDOW_ID);\n assert.equal(sfmcBuffer.length, 1);\n assert.ok(sfmcBuffer[0]?.includes(\"Building pack\"));\n assert.ok(sfmcBuffer[0]?.includes(\"[PAK]\"));\n});\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -5,5 +5,6 @@ export { formatLogDisplay, logDisplayPrefixWidth } from "./format-display.js";
5
5
  export { WindowHost, serviceWindowId } from "./host.js";
6
6
  export { createLogsFilterWindow, type LogsFilterState } from "./logs-filter-window.js";
7
7
  export { createServiceWindow } from "./service-window.js";
8
+ export { createSfmcWindow, SFMC_WINDOW_ID } from "./sfmc-window.js";
8
9
  export type { ReplWindow, WindowChrome, WindowKeyEvent, WindowKeyResult } from "./types.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repl-windows/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repl-windows/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -2,10 +2,13 @@ import { formatLogDisplay, logDisplayPrefixWidth } from "./format-display.js";
2
2
  import { WindowHost, serviceWindowId } from "./host.js";
3
3
  import { createLogsFilterWindow } from "./logs-filter-window.js";
4
4
  import { createServiceWindow } from "./service-window.js";
5
+ import { createSfmcWindow, SFMC_WINDOW_ID } from "./sfmc-window.js";
5
6
  export {
7
+ SFMC_WINDOW_ID,
6
8
  WindowHost,
7
9
  createLogsFilterWindow,
8
10
  createServiceWindow,
11
+ createSfmcWindow,
9
12
  formatLogDisplay,
10
13
  logDisplayPrefixWidth,
11
14
  serviceWindowId
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/repl-windows/index.ts"],
4
- "sourcesContent": ["/**\n * repl-windows/index.ts \u2014 \u7C7B\u7A97\u53E3\u7CFB\u7EDF\u51FA\u53E3\n */\nexport { formatLogDisplay, logDisplayPrefixWidth } from \"./format-display.js\";\nexport { WindowHost, serviceWindowId } from \"./host.js\";\nexport { createLogsFilterWindow, type LogsFilterState } from \"./logs-filter-window.js\";\nexport { createServiceWindow } from \"./service-window.js\";\nexport type { ReplWindow, WindowChrome, WindowKeyEvent, WindowKeyResult } from \"./types.js\";\n"],
5
- "mappings": "AAGA,SAAS,kBAAkB,6BAA6B;AACxD,SAAS,YAAY,uBAAuB;AAC5C,SAAS,8BAAoD;AAC7D,SAAS,2BAA2B;",
4
+ "sourcesContent": ["/**\n * repl-windows/index.ts \u2014 \u7C7B\u7A97\u53E3\u7CFB\u7EDF\u51FA\u53E3\n */\nexport { formatLogDisplay, logDisplayPrefixWidth } from \"./format-display.js\";\nexport { WindowHost, serviceWindowId } from \"./host.js\";\nexport { createLogsFilterWindow, type LogsFilterState } from \"./logs-filter-window.js\";\nexport { createServiceWindow } from \"./service-window.js\";\nexport { createSfmcWindow, SFMC_WINDOW_ID } from \"./sfmc-window.js\";\nexport type { ReplWindow, WindowChrome, WindowKeyEvent, WindowKeyResult } from \"./types.js\";\n"],
5
+ "mappings": "AAGA,SAAS,kBAAkB,6BAA6B;AACxD,SAAS,YAAY,uBAAuB;AAC5C,SAAS,8BAAoD;AAC7D,SAAS,2BAA2B;AACpC,SAAS,kBAAkB,sBAAsB;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,7 @@
1
+ import type { ServiceName } from "../services.js";
2
+ import type { ReplWindow } from "./types.js";
3
+ export declare const SFMC_WINDOW_ID = "sfmc";
4
+ export declare function createSfmcWindow(opts: {
5
+ getActiveTargets: () => ServiceName[];
6
+ }): ReplWindow;
7
+ //# sourceMappingURL=sfmc-window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfmc-window.d.ts","sourceRoot":"","sources":["../../src/repl-windows/sfmc-window.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,gBAAgB,EAAE,MAAM,WAAW,EAAE,CAAC;CACvC,GAAG,UAAU,CAoBb"}