@sfmc-bds/bds-tools 0.2.0-beta.7 → 0.2.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/bds-manager.d.ts.map +1 -1
  2. package/dist/bds-manager.js +40 -65
  3. package/dist/bds-manager.js.map +2 -2
  4. package/dist/check-update.d.ts.map +1 -1
  5. package/dist/check-update.js +4 -6
  6. package/dist/check-update.js.map +2 -2
  7. package/dist/fsx.d.ts +2 -7
  8. package/dist/fsx.d.ts.map +1 -1
  9. package/dist/fsx.js +0 -11
  10. package/dist/fsx.js.map +2 -2
  11. package/dist/host-platform.d.ts +25 -0
  12. package/dist/host-platform.d.ts.map +1 -0
  13. package/dist/host-platform.js +50 -0
  14. package/dist/host-platform.js.map +7 -0
  15. package/dist/pack-manager.d.ts.map +1 -1
  16. package/dist/pack-manager.js +6 -1
  17. package/dist/pack-manager.js.map +2 -2
  18. package/dist/pack-update/bindings.d.ts +16 -0
  19. package/dist/pack-update/bindings.d.ts.map +1 -0
  20. package/dist/pack-update/bindings.js +69 -0
  21. package/dist/pack-update/bindings.js.map +7 -0
  22. package/dist/pack-update/config.d.ts +16 -0
  23. package/dist/pack-update/config.d.ts.map +1 -0
  24. package/dist/pack-update/config.js +146 -0
  25. package/dist/pack-update/config.js.map +7 -0
  26. package/dist/pack-update/deps.d.ts +28 -0
  27. package/dist/pack-update/deps.d.ts.map +1 -0
  28. package/dist/pack-update/deps.js +20 -0
  29. package/dist/pack-update/deps.js.map +7 -0
  30. package/dist/pack-update/index.d.ts +55 -0
  31. package/dist/pack-update/index.d.ts.map +1 -0
  32. package/dist/pack-update/index.js +72 -0
  33. package/dist/pack-update/index.js.map +7 -0
  34. package/dist/pack-update/providers/curseforge.d.ts +23 -0
  35. package/dist/pack-update/providers/curseforge.d.ts.map +1 -0
  36. package/dist/pack-update/providers/curseforge.js +229 -0
  37. package/dist/pack-update/providers/curseforge.js.map +7 -0
  38. package/dist/pack-update/providers/index.d.ts +16 -0
  39. package/dist/pack-update/providers/index.d.ts.map +1 -0
  40. package/dist/pack-update/providers/index.js +37 -0
  41. package/dist/pack-update/providers/index.js.map +7 -0
  42. package/dist/pack-update/service.d.ts +28 -0
  43. package/dist/pack-update/service.d.ts.map +1 -0
  44. package/dist/pack-update/service.js +570 -0
  45. package/dist/pack-update/service.js.map +7 -0
  46. package/dist/pack-update/types.d.ts +126 -0
  47. package/dist/pack-update/types.d.ts.map +1 -0
  48. package/dist/pack-update/types.js +8 -0
  49. package/dist/pack-update/types.js.map +7 -0
  50. package/dist/pack-update/version-policy.d.ts +81 -0
  51. package/dist/pack-update/version-policy.d.ts.map +1 -0
  52. package/dist/pack-update/version-policy.js +210 -0
  53. package/dist/pack-update/version-policy.js.map +7 -0
  54. package/dist/paths.d.ts +1 -1
  55. package/dist/paths.d.ts.map +1 -1
  56. package/dist/paths.js +3 -5
  57. package/dist/paths.js.map +2 -2
  58. package/dist/process-probe.d.ts +34 -0
  59. package/dist/process-probe.d.ts.map +1 -0
  60. package/dist/process-probe.js +152 -0
  61. package/dist/process-probe.js.map +7 -0
  62. package/dist/qq-events-notify.d.ts +16 -0
  63. package/dist/qq-events-notify.d.ts.map +1 -0
  64. package/dist/qq-events-notify.js +70 -0
  65. package/dist/qq-events-notify.js.map +7 -0
  66. package/dist/qq-events-notify.test.d.ts +5 -0
  67. package/dist/qq-events-notify.test.d.ts.map +1 -0
  68. package/dist/qq-events-notify.test.js +41 -0
  69. package/dist/qq-events-notify.test.js.map +7 -0
  70. package/dist/qqutil.d.ts +2 -1
  71. package/dist/qqutil.d.ts.map +1 -1
  72. package/dist/qqutil.js +49 -8
  73. package/dist/qqutil.js.map +2 -2
  74. package/dist/upstream.d.ts +4 -3
  75. package/dist/upstream.d.ts.map +1 -1
  76. package/dist/upstream.js +8 -7
  77. package/dist/upstream.js.map +2 -2
  78. package/dist/version.js +2 -2
  79. package/dist/version.js.map +2 -2
  80. package/dist/world-packs.d.ts +0 -2
  81. package/dist/world-packs.d.ts.map +1 -1
  82. package/dist/world-packs.js +0 -2
  83. package/dist/world-packs.js.map +2 -2
  84. package/package.json +8 -6
@@ -0,0 +1,570 @@
1
+ import {
2
+ enableInstalledPack,
3
+ ensureVersionGreaterThan,
4
+ findInstalledPackById,
5
+ installPackDirectory,
6
+ listInstalledWorldPacks,
7
+ readPackDependencyUuids,
8
+ readPackManifestInfo,
9
+ resolvePackRoots,
10
+ worldPackParentDir
11
+ } from "../world-packs.js";
12
+ import fs from "node:fs";
13
+ import os from "node:os";
14
+ import path from "node:path";
15
+ import {
16
+ createPackSourceProvider,
17
+ providerShortLabel,
18
+ resolveConfiguredPackProvider
19
+ } from "./providers/index.js";
20
+ import {
21
+ decideVersionPolicy,
22
+ buildSearchQueries,
23
+ buildSearchQueriesFromSources,
24
+ packSourceScore
25
+ } from "./version-policy.js";
26
+ function createPackUpdateServiceApi(deps, config, bindings) {
27
+ const { t, paint: c } = deps;
28
+ const {
29
+ loadPackUpdateConfig,
30
+ getPackMatchConfig,
31
+ packUpdateConfigPath,
32
+ ensurePackUpdateConfigFile
33
+ } = config;
34
+ const { getBinding, listBindings, packSourcesPath, setBinding } = bindings;
35
+ function logPack(text, level = "info") {
36
+ deps.log(text, level);
37
+ }
38
+ function fmtVer(v) {
39
+ return v.join(".");
40
+ }
41
+ function bindingEnabledLabel(enabled) {
42
+ return enabled ? t("packs.list.on").trim() : t("packs.list.off").trim();
43
+ }
44
+ function needKeyText() {
45
+ return t("packUpdate.needKey", { path: packUpdateConfigPath() });
46
+ }
47
+ function bindOkParams(opts) {
48
+ return {
49
+ uuid: opts.uuid,
50
+ provider: providerShortLabel(opts.provider),
51
+ slug: opts.slug,
52
+ enabled: bindingEnabledLabel(opts.enabled),
53
+ path: packSourcesPath()
54
+ };
55
+ }
56
+ function touchBinding(bpUuid, binding, patch) {
57
+ if (patch) Object.assign(binding, patch);
58
+ setBinding(bpUuid, binding);
59
+ }
60
+ function isFileIdApplied(binding, fileId) {
61
+ return binding.lastAppliedFileId != null && binding.lastAppliedFileId === fileId;
62
+ }
63
+ async function searchAndRankHits(provider, queries, stripFolderTags) {
64
+ const byId = /* @__PURE__ */ new Map();
65
+ for (const q of queries) {
66
+ const hits = await provider.search(q);
67
+ for (const h of hits) byId.set(h.projectId, h);
68
+ }
69
+ return [...byId.values()].map((h) => ({
70
+ hit: h,
71
+ score: Math.max(...queries.map((q) => packSourceScore(q, h, stripFolderTags)))
72
+ })).sort((a, b) => b.score - a.score);
73
+ }
74
+ function makeBindingFromHit(hit, pairedResourceUuid, opts) {
75
+ const prev = opts?.prev;
76
+ return {
77
+ /* 重绑保留原 enabled;新建走配置契约 defaultBindingEnabled(LSP) */
78
+ enabled: prev?.enabled ?? opts?.defaultEnabled ?? false,
79
+ provider: hit.provider,
80
+ projectId: hit.projectId,
81
+ slug: hit.slug,
82
+ websiteUrl: hit.websiteUrl,
83
+ pairedResourceUuid,
84
+ lastFileId: prev?.lastFileId ?? null,
85
+ lastCheckedAt: null,
86
+ lastAppliedFileId: prev?.lastAppliedFileId ?? null
87
+ };
88
+ }
89
+ function pairedRpUuidFromBpDir(bpDir) {
90
+ const depList = readPackDependencyUuids(bpDir);
91
+ return depList[0] ?? null;
92
+ }
93
+ async function probeSourceAfterInstall(opts) {
94
+ const cfg = loadPackUpdateConfig();
95
+ if (!cfg.enabled || !cfg.probeSourceAfterInstall) return;
96
+ if (opts.info.kind !== "behavior") return;
97
+ ensurePackUpdateConfigFile();
98
+ const provider = resolveConfiguredPackProvider(cfg);
99
+ if (!provider) {
100
+ logPack(needKeyText(), "warn");
101
+ return;
102
+ }
103
+ const match = getPackMatchConfig(cfg);
104
+ const folderName = opts.folderName && String(opts.folderName).trim() || (opts.packDir ? path.basename(opts.packDir) : "");
105
+ const plan = buildSearchQueriesFromSources(
106
+ [
107
+ { id: "header", raw: opts.info.name },
108
+ { id: "folder", raw: folderName }
109
+ ],
110
+ match.stripFolderTags
111
+ );
112
+ const queries = plan.queries;
113
+ if (queries.length === 0) {
114
+ logPack(t("packUpdate.probeNoName"), "warn");
115
+ return;
116
+ }
117
+ logPack(
118
+ t("packUpdate.probeQueries", {
119
+ header: opts.info.name || "-",
120
+ folder: folderName || "-",
121
+ queries: queries.join(" | ")
122
+ }),
123
+ "info"
124
+ );
125
+ let scored;
126
+ try {
127
+ scored = await searchAndRankHits(provider, queries, match.stripFolderTags);
128
+ } catch (e) {
129
+ logPack(t("packUpdate.probeFail", { message: e.message }), "warn");
130
+ return;
131
+ }
132
+ if (scored.length === 0) {
133
+ logPack(t("packUpdate.probeMiss", { name: queries.join(", ") }), "info");
134
+ return;
135
+ }
136
+ const primary = queries.find((q) => /[A-Za-z]/.test(q)) ?? queries[0];
137
+ const best = scored[0];
138
+ if (best.score < match.nameMinScore) {
139
+ logPack(
140
+ t("packUpdate.probeLowScore", {
141
+ name: primary,
142
+ hit: `${best.hit.name} (${best.hit.slug})`,
143
+ score: best.score.toFixed(2),
144
+ url: best.hit.websiteUrl
145
+ }),
146
+ "info"
147
+ );
148
+ return;
149
+ }
150
+ logPack(
151
+ t("packUpdate.probeHit", {
152
+ name: `${opts.info.name} / ${folderName || "-"}`,
153
+ hit: `${best.hit.name} [${best.hit.slug}]`,
154
+ url: best.hit.websiteUrl,
155
+ score: best.score.toFixed(2)
156
+ }),
157
+ "success"
158
+ );
159
+ logPack(t("packUpdate.editHint", { path: packSourcesPath() }), "info");
160
+ const interactive = opts.interactive ?? !!process.stdin.isTTY;
161
+ let accept = false;
162
+ if (interactive && cfg.askConfirmOnBind && process.stdin.isTTY) {
163
+ accept = await deps.askConfirm(t("packUpdate.confirmBind", { hit: best.hit.name }));
164
+ } else {
165
+ accept = true;
166
+ logPack(
167
+ t("packUpdate.probeAutoBind", {
168
+ provider: providerShortLabel(best.hit.provider),
169
+ slug: best.hit.slug,
170
+ path: packSourcesPath()
171
+ }),
172
+ "info"
173
+ );
174
+ }
175
+ if (!accept) {
176
+ logPack(t("packUpdate.bindSkipped"), "info");
177
+ return;
178
+ }
179
+ const paired = (opts.packDir ? pairedRpUuidFromBpDir(opts.packDir) : null) ?? null;
180
+ const binding = makeBindingFromHit(best.hit, paired, { defaultEnabled: cfg.defaultBindingEnabled });
181
+ setBinding(opts.info.uuid, binding);
182
+ logPack(
183
+ t(
184
+ "packUpdate.bindOk",
185
+ bindOkParams({
186
+ uuid: opts.info.uuid,
187
+ provider: best.hit.provider,
188
+ slug: best.hit.slug,
189
+ enabled: binding.enabled
190
+ })
191
+ ),
192
+ "success"
193
+ );
194
+ }
195
+ async function searchRemote(query) {
196
+ const cfg = loadPackUpdateConfig();
197
+ const provider = resolveConfiguredPackProvider(cfg);
198
+ if (!provider) {
199
+ return c.yellow(needKeyText());
200
+ }
201
+ const match = getPackMatchConfig(cfg);
202
+ const queries = buildSearchQueries(query, match.stripFolderTags);
203
+ const ranked = await searchAndRankHits(provider, queries, match.stripFolderTags);
204
+ if (ranked.length === 0) return c.dim(t("packUpdate.searchEmpty", { query }));
205
+ return ranked.map(
206
+ ({ hit: h, score }, i) => `${c.cyan(String(i + 1).padStart(2))}. ${h.name} ${c.dim(`id=${h.projectId} slug=${h.slug} score=${score.toFixed(2)}`)}
207
+ ${h.websiteUrl}`
208
+ ).join("\n");
209
+ }
210
+ async function bindPackSource(packId, ref) {
211
+ const cfg = loadPackUpdateConfig();
212
+ const provider = resolveConfiguredPackProvider(cfg);
213
+ if (!provider) {
214
+ return c.yellow(needKeyText());
215
+ }
216
+ const { bdsRoot, levelName } = deps.resolveBdsContext();
217
+ const packs = listInstalledWorldPacks(bdsRoot, levelName);
218
+ const pack = findInstalledPackById(packs, packId);
219
+ if (!pack) return c.red(t("packs.notFound", { id: packId }));
220
+ if (pack.kind !== "behavior") return c.red(t("packUpdate.bindBpOnly"));
221
+ const hit = await provider.resolveProject(ref);
222
+ if (!hit) return c.red(t("packUpdate.resolveFail", { ref }));
223
+ const paired = pairedRpUuidFromBpDir(pack.dir);
224
+ const binding = makeBindingFromHit(hit, paired, {
225
+ prev: getBinding(pack.uuid),
226
+ defaultEnabled: cfg.defaultBindingEnabled
227
+ });
228
+ setBinding(pack.uuid, binding);
229
+ return c.green(
230
+ t(
231
+ "packUpdate.bindOk",
232
+ bindOkParams({
233
+ uuid: pack.uuid,
234
+ provider: hit.provider,
235
+ slug: hit.slug,
236
+ enabled: binding.enabled
237
+ })
238
+ )
239
+ );
240
+ }
241
+ function formatSourcesList() {
242
+ ensurePackUpdateConfigFile();
243
+ const bindingList = listBindings();
244
+ const lines = [
245
+ t("packUpdate.sourcesHeader", {
246
+ config: packUpdateConfigPath(),
247
+ sources: packSourcesPath()
248
+ })
249
+ ];
250
+ if (bindingList.length === 0) {
251
+ lines.push(c.dim(t("packUpdate.sourcesEmpty")));
252
+ return lines.join("\n");
253
+ }
254
+ for (const { bpUuid, binding } of bindingList) {
255
+ const label = bindingEnabledLabel(binding.enabled);
256
+ const en = binding.enabled ? c.green(label) : c.dim(label);
257
+ const tag = providerShortLabel(binding.provider);
258
+ lines.push(
259
+ ` [${en}] ${bpUuid} ${tag}:${binding.slug || binding.projectId} ${c.dim(binding.websiteUrl || "")}`
260
+ );
261
+ }
262
+ return lines.join("\n");
263
+ }
264
+ function withLocalBp(base, localBp) {
265
+ return localBp ? { ...base, localBp } : { ...base };
266
+ }
267
+ function baseCheckFields(bpUuid, name, localVer, binding, extras) {
268
+ return {
269
+ bpUuid,
270
+ name,
271
+ localVer,
272
+ remoteVer: null,
273
+ updateAvailable: false,
274
+ majorHigher: false,
275
+ shouldBumpRp: false,
276
+ fileId: null,
277
+ binding,
278
+ ...extras
279
+ };
280
+ }
281
+ async function prepareCheck(bpUuid, binding, cfg, packs, downloadArchive) {
282
+ const localBp = packs.find((p) => p.uuid.toLowerCase() === bpUuid.toLowerCase() && p.kind === "behavior");
283
+ const name = localBp?.name ?? bpUuid;
284
+ const localVer = localBp?.version ?? [0, 0, 0];
285
+ const provider = createPackSourceProvider(cfg, binding.provider);
286
+ touchBinding(bpUuid, binding, { lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString() });
287
+ if (!binding.enabled) {
288
+ return withLocalBp(
289
+ baseCheckFields(bpUuid, name, localVer, binding, { message: t("packUpdate.bindingDisabled") }),
290
+ localBp
291
+ );
292
+ }
293
+ const file = await provider.getLatestFile(binding.projectId);
294
+ if (!file) {
295
+ return withLocalBp(
296
+ baseCheckFields(bpUuid, name, localVer, binding, { message: t("packUpdate.noRemoteFile") }),
297
+ localBp
298
+ );
299
+ }
300
+ if (isFileIdApplied(binding, file.fileId)) {
301
+ touchBinding(bpUuid, binding, { lastFileId: file.fileId });
302
+ return withLocalBp(
303
+ baseCheckFields(bpUuid, name, localVer, binding, {
304
+ fileId: file.fileId,
305
+ message: t("packUpdate.upToDate")
306
+ }),
307
+ localBp
308
+ );
309
+ }
310
+ if (!downloadArchive) {
311
+ return withLocalBp(
312
+ baseCheckFields(bpUuid, name, localVer, binding, {
313
+ updateAvailable: true,
314
+ fileId: file.fileId,
315
+ message: t("packUpdate.fileNewer", { file: file.fileName, id: String(file.fileId) })
316
+ }),
317
+ localBp
318
+ );
319
+ }
320
+ const stagingDir = fs.mkdtempSync(path.join(os.tmpdir(), "sfmc-pack-upd-"));
321
+ const archiveFile = path.join(stagingDir, file.fileName || "pack.zip");
322
+ await provider.download(file, archiveFile);
323
+ const resolved = await resolvePackRoots(archiveFile);
324
+ const roots = resolved.roots;
325
+ const bpRoot = roots.find((r) => readPackManifestInfo(r)?.kind === "behavior");
326
+ const remoteBpInfo = bpRoot ? readPackManifestInfo(bpRoot) : null;
327
+ if (!remoteBpInfo) {
328
+ resolved.dispose();
329
+ try {
330
+ fs.rmSync(stagingDir, { recursive: true, force: true });
331
+ } catch {
332
+ }
333
+ return withLocalBp(
334
+ baseCheckFields(bpUuid, name, localVer, binding, {
335
+ fileId: file.fileId,
336
+ message: t("packUpdate.remoteNoBp")
337
+ }),
338
+ localBp
339
+ );
340
+ }
341
+ const decision = decideVersionPolicy(localVer, remoteBpInfo.version, cfg.versionPolicy, {
342
+ treatAsUpdate: true
343
+ });
344
+ touchBinding(bpUuid, binding, { lastFileId: file.fileId });
345
+ const message = decision.remoteNewer ? t("packUpdate.bpNewer", {
346
+ local: fmtVer(localVer),
347
+ remote: fmtVer(remoteBpInfo.version)
348
+ }) : t("packUpdate.needSync", {
349
+ local: fmtVer(localVer),
350
+ remote: fmtVer(remoteBpInfo.version),
351
+ id: String(file.fileId)
352
+ });
353
+ return withLocalBp(
354
+ {
355
+ bpUuid,
356
+ name,
357
+ localVer,
358
+ remoteVer: remoteBpInfo.version,
359
+ updateAvailable: true,
360
+ majorHigher: decision.majorHigher,
361
+ shouldBumpRp: decision.shouldBumpRp,
362
+ fileId: file.fileId,
363
+ message,
364
+ binding,
365
+ remoteBpInfo,
366
+ remoteRoots: roots,
367
+ stagingDir,
368
+ disposeRoots: resolved.dispose
369
+ },
370
+ localBp
371
+ );
372
+ }
373
+ function cleanupCheck(r) {
374
+ if (r.disposeRoots) {
375
+ try {
376
+ r.disposeRoots();
377
+ } catch {
378
+ }
379
+ }
380
+ for (const d of [r.tempDir, r.stagingDir]) {
381
+ if (!d) continue;
382
+ try {
383
+ fs.rmSync(d, { recursive: true, force: true });
384
+ } catch {
385
+ }
386
+ }
387
+ }
388
+ async function tryInstallResourcePack(opts) {
389
+ for (const root of opts.rpRoots) {
390
+ const info = readPackManifestInfo(root);
391
+ if (!info || !opts.accept(info)) continue;
392
+ const rpDest = worldPackParentDir(opts.bdsRoot, opts.levelName, "resource");
393
+ const rpInstall = await installPackDirectory({
394
+ srcDir: root,
395
+ destParent: rpDest,
396
+ force: true,
397
+ ...opts.folderName ? { folderName: opts.folderName } : {}
398
+ });
399
+ if (rpInstall.ok && rpInstall.info && rpInstall.destDir) {
400
+ return { info: rpInstall.info, destDir: rpInstall.destDir };
401
+ }
402
+ }
403
+ return null;
404
+ }
405
+ async function applyUpdate(r, cfg) {
406
+ if (!r.updateAvailable || !r.remoteRoots || !r.remoteBpInfo) {
407
+ return { ok: true, message: r.message };
408
+ }
409
+ const { bdsRoot, levelName } = deps.resolveBdsContext();
410
+ const packs = listInstalledWorldPacks(bdsRoot, levelName);
411
+ const oldRp = r.binding.pairedResourceUuid != null ? packs.find(
412
+ (p) => p.kind === "resource" && p.uuid.toLowerCase() === r.binding.pairedResourceUuid.toLowerCase()
413
+ ) : void 0;
414
+ const oldRpVer = oldRp?.version ?? [0, 0, 0];
415
+ const bpRoot = r.remoteRoots.find((x) => readPackManifestInfo(x)?.kind === "behavior");
416
+ const rpRoots = r.remoteRoots.filter((x) => readPackManifestInfo(x)?.kind === "resource");
417
+ if (!bpRoot) return { ok: false, message: t("packUpdate.remoteNoBp") };
418
+ const bpDest = worldPackParentDir(bdsRoot, levelName, "behavior");
419
+ const bpInstall = await installPackDirectory({
420
+ srcDir: bpRoot,
421
+ destParent: bpDest,
422
+ force: true,
423
+ ...r.localBp?.folderName ? { folderName: r.localBp.folderName } : {}
424
+ });
425
+ if (!bpInstall.ok || !bpInstall.info || !bpInstall.destDir) {
426
+ return { ok: false, message: t("packUpdate.installFail", { reason: bpInstall.reason ?? "?" }) };
427
+ }
428
+ await enableInstalledPack({ bdsRoot, levelName, info: bpInstall.info });
429
+ logPack(
430
+ t("packUpdate.installedBp", {
431
+ dir: bpInstall.destDir,
432
+ version: fmtVer(bpInstall.info.version)
433
+ }),
434
+ "success"
435
+ );
436
+ let rpInfo = null;
437
+ let rpDir = null;
438
+ const wantRp = r.binding.pairedResourceUuid?.toLowerCase();
439
+ const installed = await tryInstallResourcePack({
440
+ rpRoots,
441
+ bdsRoot,
442
+ levelName,
443
+ ...oldRp?.folderName ? { folderName: oldRp.folderName } : {},
444
+ accept: (info) => !wantRp || info.uuid.toLowerCase() === wantRp
445
+ });
446
+ if (installed) {
447
+ rpInfo = installed.info;
448
+ rpDir = installed.destDir;
449
+ }
450
+ if (!rpInfo && rpRoots.length > 0) {
451
+ const depList = readPackDependencyUuids(bpInstall.destDir);
452
+ const fallback = await tryInstallResourcePack({
453
+ rpRoots,
454
+ bdsRoot,
455
+ levelName,
456
+ accept: (info) => depList.length === 0 || depList.some((d) => d.toLowerCase() === info.uuid.toLowerCase())
457
+ });
458
+ if (fallback) {
459
+ rpInfo = fallback.info;
460
+ rpDir = fallback.destDir;
461
+ r.binding.pairedResourceUuid = fallback.info.uuid;
462
+ }
463
+ }
464
+ if (rpInfo && rpDir && r.shouldBumpRp) {
465
+ const next = ensureVersionGreaterThan(rpDir, oldRpVer, cfg.versionPolicy.rpBumpComponent);
466
+ rpInfo = { ...rpInfo, version: next };
467
+ }
468
+ if (rpInfo) {
469
+ await enableInstalledPack({ bdsRoot, levelName, info: rpInfo });
470
+ logPack(
471
+ t("packUpdate.installedRp", {
472
+ dir: rpDir ?? "-",
473
+ version: fmtVer(rpInfo.version)
474
+ }),
475
+ "success"
476
+ );
477
+ } else if (rpRoots.length > 0) {
478
+ logPack(t("packUpdate.rpInstallMiss"), "warn");
479
+ }
480
+ touchBinding(r.bpUuid, r.binding, {
481
+ lastAppliedFileId: r.fileId,
482
+ lastFileId: r.fileId,
483
+ lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString()
484
+ });
485
+ return {
486
+ ok: true,
487
+ message: t("packUpdate.applied", {
488
+ name: r.name,
489
+ bp: fmtVer(bpInstall.info.version),
490
+ rp: rpInfo ? fmtVer(rpInfo.version) : "-"
491
+ })
492
+ };
493
+ }
494
+ async function checkPackUpdates(opts) {
495
+ const cfg = loadPackUpdateConfig();
496
+ if (!cfg.enabled) return c.dim(t("packUpdate.disabled"));
497
+ if (!resolveConfiguredPackProvider(cfg)) {
498
+ return c.yellow(needKeyText());
499
+ }
500
+ const { bdsRoot, levelName } = deps.resolveBdsContext();
501
+ const packs = listInstalledWorldPacks(bdsRoot, levelName);
502
+ let targets = listBindings();
503
+ if (opts?.packId) {
504
+ const pack = findInstalledPackById(packs, opts.packId);
505
+ const uuid = pack?.uuid ?? opts.packId;
506
+ targets = targets.filter((x) => x.bpUuid.toLowerCase() === uuid.toLowerCase());
507
+ if (targets.length === 0) {
508
+ const b = getBinding(uuid);
509
+ if (b) targets = [{ bpUuid: uuid, binding: b }];
510
+ }
511
+ if (targets.length === 0) return c.red(t("packUpdate.noBinding", { id: opts.packId }));
512
+ }
513
+ if (targets.length === 0) return c.dim(t("packUpdate.sourcesEmpty"));
514
+ const lines = [];
515
+ for (const { bpUuid, binding } of targets) {
516
+ if (cfg.startup.skipDisabledBindings && !binding.enabled && !opts?.packId) continue;
517
+ let result = null;
518
+ try {
519
+ result = await prepareCheck(bpUuid, binding, cfg, packs, true);
520
+ if (opts?.apply && result.updateAvailable) {
521
+ const applied = await applyUpdate(result, cfg);
522
+ lines.push(applied.ok ? c.green(applied.message) : c.red(applied.message));
523
+ } else {
524
+ lines.push(
525
+ result.updateAvailable ? c.yellow(`${result.name}: ${result.message}`) : c.dim(`${result.name}: ${result.message}`)
526
+ );
527
+ }
528
+ } catch (e) {
529
+ lines.push(c.red(`${bpUuid}: ${e.message}`));
530
+ if (cfg.startup.failMode === "abort") break;
531
+ } finally {
532
+ if (result) cleanupCheck(result);
533
+ }
534
+ if (cfg.startup.delayMsBetweenPacks > 0) {
535
+ await new Promise((r) => setTimeout(r, cfg.startup.delayMsBetweenPacks));
536
+ }
537
+ }
538
+ return lines.join("\n") || c.dim(t("packUpdate.sourcesEmpty"));
539
+ }
540
+ async function runPackUpdatesOnBdsStart() {
541
+ const cfg = loadPackUpdateConfig();
542
+ if (!cfg.enabled || !cfg.checkOnBdsStart) return;
543
+ try {
544
+ const out = await checkPackUpdates({ apply: cfg.applyOnBdsStart });
545
+ if (out.trim()) logPack(out.replace(/\x1B\[[0-9;]*m/g, ""), "info");
546
+ } catch (e) {
547
+ logPack(t("packUpdate.startupFail", { message: e.message }), "warn");
548
+ }
549
+ }
550
+ function bindingLabelForUuid(uuid) {
551
+ const b = getBinding(uuid);
552
+ if (!b) return "src=-";
553
+ const tag = `${providerShortLabel(b.provider)}:${b.slug || b.projectId}`;
554
+ return b.enabled ? `src=${tag}` : `src=${tag}:off`;
555
+ }
556
+ return {
557
+ pairedRpUuidFromBpDir,
558
+ probeSourceAfterInstall,
559
+ searchRemote,
560
+ bindPackSource,
561
+ formatSourcesList,
562
+ checkPackUpdates,
563
+ runPackUpdatesOnBdsStart,
564
+ bindingLabelForUuid
565
+ };
566
+ }
567
+ export {
568
+ createPackUpdateServiceApi
569
+ };
570
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/pack-update/service.ts"],
4
+ "sourcesContent": ["/**\n * pack-update \u7F16\u6392\uFF1A\u63A2\u6D4B\u7ED1\u5B9A / \u68C0\u67E5 / \u5E94\u7528\u66F4\u65B0\n */\nimport {\n enableInstalledPack,\n ensureVersionGreaterThan,\n findInstalledPackById,\n installPackDirectory,\n listInstalledWorldPacks,\n readPackDependencyUuids,\n readPackManifestInfo,\n resolvePackRoots,\n worldPackParentDir,\n type InstalledWorldPack,\n type PackManifestInfo,\n} from \"../world-packs.js\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { PackUpdateBindingsApi } from \"./bindings.js\";\nimport type { PackUpdateConfigApi } from \"./config.js\";\nimport type { PackUpdateDeps } from \"./deps.js\";\nimport {\n createPackSourceProvider,\n providerShortLabel,\n resolveConfiguredPackProvider,\n} from \"./providers/index.js\";\nimport type {\n PackSourceBinding,\n PackSourceProvider,\n PackUpdateConfig,\n SemVer3,\n SourceSearchHit,\n} from \"./types.js\";\nimport {\n decideVersionPolicy,\n buildSearchQueries,\n buildSearchQueriesFromSources,\n packSourceScore,\n} from \"./version-policy.js\";\n\nexport function createPackUpdateServiceApi(\n deps: PackUpdateDeps,\n config: PackUpdateConfigApi,\n bindings: PackUpdateBindingsApi\n) {\n const { t, paint: c } = deps;\n const {\n loadPackUpdateConfig,\n getPackMatchConfig,\n packUpdateConfigPath,\n ensurePackUpdateConfigFile,\n } = config;\n const { getBinding, listBindings, packSourcesPath, setBinding } = bindings;\n\n function logPack(text: string, level: \"info\" | \"warn\" | \"error\" | \"success\" = \"info\"): void {\n deps.log(text, level);\n }\n\n function fmtVer(v: SemVer3): string {\n return v.join(\".\");\n }\n\n /** \u7ED1\u5B9A\u542F\u7528\u6001\u6587\u6848\uFF1AbindOk / sources list \u5171\u7528\uFF08DRY\uFF09\uFF0C\u8D70 packs.list i18n */\n function bindingEnabledLabel(enabled: boolean): string {\n return enabled ? t(\"packs.list.on\").trim() : t(\"packs.list.off\").trim();\n }\n\n /** \u672A\u914D\u7F6E\u6E90\u65F6\u7684\u7EDF\u4E00\u6587\u6848\uFF08DRY\uFF1A\u5165\u53E3\u52FF\u5404\u81EA\u62FC needKey\uFF1B\u6587\u6848\u6E90\u65E0\u5173 \u2014 OCP\uFF09 */\n function needKeyText(): string {\n return t(\"packUpdate.needKey\", { path: packUpdateConfigPath() });\n }\n\n /** bindOk \u53C2\u6570\u552F\u4E00\u6784\u9020\u70B9\uFF08probe / bind \u5171\u7528 \u2014 DRY\uFF09\uFF0C\u62A5\u544A\u5B9E\u9645 binding.enabled\uFF08LSP\uFF09 */\n function bindOkParams(opts: {\n uuid: string;\n provider: PackSourceBinding[\"provider\"] | SourceSearchHit[\"provider\"];\n slug: string;\n enabled: boolean;\n }): Record<string, string> {\n return {\n uuid: opts.uuid,\n provider: providerShortLabel(opts.provider),\n slug: opts.slug,\n enabled: bindingEnabledLabel(opts.enabled),\n path: packSourcesPath(),\n };\n }\n\n /** \u5C31\u5730\u8865\u4E01\u5E76\u843D\u76D8\uFF08prepareCheck \u591A\u51FA\u53E3\u5171\u7528 \u2014 DRY\uFF1B\u52FF\u6563\u843D Object.assign+setBinding\uFF09 */\n function touchBinding(bpUuid: string, binding: PackSourceBinding, patch?: Partial<PackSourceBinding>): void {\n if (patch) Object.assign(binding, patch);\n setBinding(bpUuid, binding);\n }\n\n /** \u8BE5 fileId \u662F\u5426\u5DF2\u6210\u529F\u5199\u5165\u4E16\u754C\u76EE\u5F55\uFF08DRY\uFF1AprepareCheck \u591A\u5904\u52FF\u624B\u5199 null/!==\uFF09 */\n function isFileIdApplied(binding: PackSourceBinding, fileId: number): boolean {\n return binding.lastAppliedFileId != null && binding.lastAppliedFileId === fileId;\n }\n\n /** \u591A\u67E5\u8BE2\u641C\u7D22 + \u7EFC\u5408\u6253\u5206\u6392\u5E8F\uFF08probe / searchRemote \u5171\u7528\uFF09 */\n async function searchAndRankHits(\n provider: PackSourceProvider,\n queries: string[],\n stripFolderTags: boolean\n ): Promise<Array<{ hit: SourceSearchHit; score: number }>> {\n const byId = new Map<number, SourceSearchHit>();\n for (const q of queries) {\n const hits = await provider.search(q);\n for (const h of hits) byId.set(h.projectId, h);\n }\n return [...byId.values()]\n .map((h) => ({\n hit: h,\n score: Math.max(...queries.map((q) => packSourceScore(q, h, stripFolderTags))),\n }))\n .sort((a, b) => b.score - a.score);\n }\n\n function makeBindingFromHit(\n hit: SourceSearchHit,\n pairedResourceUuid: string | null,\n opts?: { prev?: PackSourceBinding | null; defaultEnabled: boolean }\n ): PackSourceBinding {\n const prev = opts?.prev;\n return {\n /* \u91CD\u7ED1\u4FDD\u7559\u539F enabled\uFF1B\u65B0\u5EFA\u8D70\u914D\u7F6E\u5951\u7EA6 defaultBindingEnabled\uFF08LSP\uFF09 */\n enabled: prev?.enabled ?? opts?.defaultEnabled ?? false,\n provider: hit.provider,\n projectId: hit.projectId,\n slug: hit.slug,\n websiteUrl: hit.websiteUrl,\n pairedResourceUuid,\n lastFileId: prev?.lastFileId ?? null,\n lastCheckedAt: null,\n lastAppliedFileId: prev?.lastAppliedFileId ?? null,\n };\n }\n\n /** \u4ECE\u5DF2\u5B89\u88C5 BP \u63D0\u53D6\u914D\u5BF9 RP uuid */\n function pairedRpUuidFromBpDir(bpDir: string): string | null {\n const depList = readPackDependencyUuids(bpDir);\n return depList[0] ?? null;\n }\n\n async function probeSourceAfterInstall(opts: {\n info: PackManifestInfo;\n packDir?: string;\n /** \u5B89\u88C5\u540E\u7684\u6587\u4EF6\u5939\u540D\uFF08\u4F18\u5148\u4E8E basename(packDir)\uFF09 */\n folderName?: string;\n interactive?: boolean;\n }): Promise<void> {\n const cfg = loadPackUpdateConfig();\n if (!cfg.enabled || !cfg.probeSourceAfterInstall) return;\n if (opts.info.kind !== \"behavior\") return;\n\n ensurePackUpdateConfigFile();\n const provider = resolveConfiguredPackProvider(cfg);\n if (!provider) {\n logPack(needKeyText(), \"warn\");\n return;\n }\n\n const match = getPackMatchConfig(cfg);\n /* header \u5E38\u672C\u5730\u5316\uFF1B\u6587\u4EF6\u5939\u540D\u5F80\u5F80\u542B\u62C9\u4E01\u6838\u5FC3 \u2014 \u4E24\u6E90\u5206\u522B\u6D3E\u751F\u518D\u5408\u5E76\uFF0C\u6709\u62C9\u4E01\u5219\u4E0D\u641C\u7EAF\u4E2D\u6587 */\n const folderName =\n (opts.folderName && String(opts.folderName).trim()) ||\n (opts.packDir ? path.basename(opts.packDir) : \"\");\n const plan = buildSearchQueriesFromSources(\n [\n { id: \"header\", raw: opts.info.name },\n { id: \"folder\", raw: folderName },\n ],\n match.stripFolderTags\n );\n const queries = plan.queries;\n if (queries.length === 0) {\n logPack(t(\"packUpdate.probeNoName\"), \"warn\");\n return;\n }\n\n logPack(\n t(\"packUpdate.probeQueries\", {\n header: opts.info.name || \"-\",\n folder: folderName || \"-\",\n queries: queries.join(\" | \"),\n }),\n \"info\"\n );\n\n let scored: Array<{ hit: SourceSearchHit; score: number }>;\n try {\n scored = await searchAndRankHits(provider, queries, match.stripFolderTags);\n } catch (e) {\n logPack(t(\"packUpdate.probeFail\", { message: (e as Error).message }), \"warn\");\n return;\n }\n\n if (scored.length === 0) {\n logPack(t(\"packUpdate.probeMiss\", { name: queries.join(\", \") }), \"info\");\n return;\n }\n\n const primary = queries.find((q) => /[A-Za-z]/.test(q)) ?? queries[0]!;\n const best = scored[0]!;\n if (best.score < match.nameMinScore) {\n logPack(\n t(\"packUpdate.probeLowScore\", {\n name: primary,\n hit: `${best.hit.name} (${best.hit.slug})`,\n score: best.score.toFixed(2),\n url: best.hit.websiteUrl,\n }),\n \"info\"\n );\n return;\n }\n\n logPack(\n t(\"packUpdate.probeHit\", {\n name: `${opts.info.name} / ${folderName || \"-\"}`,\n hit: `${best.hit.name} [${best.hit.slug}]`,\n url: best.hit.websiteUrl,\n score: best.score.toFixed(2),\n }),\n \"success\"\n );\n logPack(t(\"packUpdate.editHint\", { path: packSourcesPath() }), \"info\");\n\n const interactive = opts.interactive ?? !!process.stdin.isTTY;\n let accept = false;\n if (interactive && cfg.askConfirmOnBind && process.stdin.isTTY) {\n accept = await deps.askConfirm(t(\"packUpdate.confirmBind\", { hit: best.hit.name }));\n } else {\n /* \u975E TTY / BDS \u6536\u4EF6\u7BB1 / askConfirmOnBind=false\uFF1A\u547D\u4E2D\u5373\u5199\u5165\uFF0C\u907F\u514D\u63A2\u6D4B\u6210\u529F\u5374\u65E0 pack-sources.json */\n accept = true;\n logPack(\n t(\"packUpdate.probeAutoBind\", {\n provider: providerShortLabel(best.hit.provider),\n slug: best.hit.slug,\n path: packSourcesPath(),\n }),\n \"info\"\n );\n }\n\n if (!accept) {\n logPack(t(\"packUpdate.bindSkipped\"), \"info\");\n return;\n }\n\n const paired = (opts.packDir ? pairedRpUuidFromBpDir(opts.packDir) : null) ?? null;\n const binding = makeBindingFromHit(best.hit, paired, { defaultEnabled: cfg.defaultBindingEnabled });\n setBinding(opts.info.uuid, binding);\n logPack(\n t(\n \"packUpdate.bindOk\",\n bindOkParams({\n uuid: opts.info.uuid,\n provider: best.hit.provider,\n slug: best.hit.slug,\n enabled: binding.enabled,\n })\n ),\n \"success\"\n );\n }\n\n async function searchRemote(query: string): Promise<string> {\n const cfg = loadPackUpdateConfig();\n const provider = resolveConfiguredPackProvider(cfg);\n if (!provider) {\n return c.yellow(needKeyText());\n }\n const match = getPackMatchConfig(cfg);\n const queries = buildSearchQueries(query, match.stripFolderTags);\n const ranked = await searchAndRankHits(provider, queries, match.stripFolderTags);\n if (ranked.length === 0) return c.dim(t(\"packUpdate.searchEmpty\", { query }));\n return ranked\n .map(\n ({ hit: h, score }, i) =>\n `${c.cyan(String(i + 1).padStart(2))}. ${h.name} ${c.dim(`id=${h.projectId} slug=${h.slug} score=${score.toFixed(2)}`)}\\n ${h.websiteUrl}`\n )\n .join(\"\\n\");\n }\n\n async function bindPackSource(packId: string, ref: string): Promise<string> {\n const cfg = loadPackUpdateConfig();\n const provider = resolveConfiguredPackProvider(cfg);\n if (!provider) {\n return c.yellow(needKeyText());\n }\n const { bdsRoot, levelName } = deps.resolveBdsContext();\n const packs = listInstalledWorldPacks(bdsRoot, levelName);\n const pack = findInstalledPackById(packs, packId);\n if (!pack) return c.red(t(\"packs.notFound\", { id: packId }));\n if (pack.kind !== \"behavior\") return c.red(t(\"packUpdate.bindBpOnly\"));\n\n const hit = await provider.resolveProject(ref);\n if (!hit) return c.red(t(\"packUpdate.resolveFail\", { ref }));\n\n const paired = pairedRpUuidFromBpDir(pack.dir);\n const binding = makeBindingFromHit(hit, paired, {\n prev: getBinding(pack.uuid),\n defaultEnabled: cfg.defaultBindingEnabled,\n });\n setBinding(pack.uuid, binding);\n return c.green(\n t(\n \"packUpdate.bindOk\",\n bindOkParams({\n uuid: pack.uuid,\n provider: hit.provider,\n slug: hit.slug,\n enabled: binding.enabled,\n })\n )\n );\n }\n\n function formatSourcesList(): string {\n ensurePackUpdateConfigFile();\n const bindingList = listBindings();\n const lines = [\n t(\"packUpdate.sourcesHeader\", {\n config: packUpdateConfigPath(),\n sources: packSourcesPath(),\n }),\n ];\n if (bindingList.length === 0) {\n lines.push(c.dim(t(\"packUpdate.sourcesEmpty\")));\n return lines.join(\"\\n\");\n }\n for (const { bpUuid, binding } of bindingList) {\n const label = bindingEnabledLabel(binding.enabled);\n const en = binding.enabled ? c.green(label) : c.dim(label);\n const tag = providerShortLabel(binding.provider);\n lines.push(\n ` [${en}] ${bpUuid} ${tag}:${binding.slug || binding.projectId} ${c.dim(binding.websiteUrl || \"\")}`\n );\n }\n return lines.join(\"\\n\");\n }\n\n interface CheckResult {\n bpUuid: string;\n name: string;\n localVer: SemVer3;\n remoteVer: SemVer3 | null;\n updateAvailable: boolean;\n majorHigher: boolean;\n shouldBumpRp: boolean;\n fileId: number | null;\n message: string;\n binding: PackSourceBinding;\n localBp?: InstalledWorldPack;\n remoteBpInfo?: PackManifestInfo;\n remoteRoots?: string[];\n tempDir?: string;\n /** \u4E0B\u8F7D\u5F52\u6863\u6240\u5728\u7684\u4E34\u65F6 staging \u76EE\u5F55\uFF08\u975E zip \u6587\u4EF6\u8DEF\u5F84\uFF09 */\n stagingDir?: string;\n /** resolvePackRoots \u521B\u5EFA\u7684\u4E34\u65F6\u6811\u6E05\u7406 */\n disposeRoots?: () => void;\n }\n\n function withLocalBp(base: Omit<CheckResult, \"localBp\">, localBp: InstalledWorldPack | undefined): CheckResult {\n return localBp ? { ...base, localBp } : { ...base };\n }\n\n function baseCheckFields(\n bpUuid: string,\n name: string,\n localVer: SemVer3,\n binding: PackSourceBinding,\n extras: Partial<CheckResult> & { message: string }\n ): Omit<CheckResult, \"localBp\"> {\n return {\n bpUuid,\n name,\n localVer,\n remoteVer: null,\n updateAvailable: false,\n majorHigher: false,\n shouldBumpRp: false,\n fileId: null,\n binding,\n ...extras,\n };\n }\n\n async function prepareCheck(\n bpUuid: string,\n binding: PackSourceBinding,\n cfg: PackUpdateConfig,\n packs: InstalledWorldPack[],\n downloadArchive: boolean\n ): Promise<CheckResult> {\n const localBp = packs.find((p) => p.uuid.toLowerCase() === bpUuid.toLowerCase() && p.kind === \"behavior\");\n const name = localBp?.name ?? bpUuid;\n const localVer: SemVer3 = localBp?.version ?? [0, 0, 0];\n const provider = createPackSourceProvider(cfg, binding.provider);\n\n touchBinding(bpUuid, binding, { lastCheckedAt: new Date().toISOString() });\n\n if (!binding.enabled) {\n return withLocalBp(\n baseCheckFields(bpUuid, name, localVer, binding, { message: t(\"packUpdate.bindingDisabled\") }),\n localBp\n );\n }\n\n const file = await provider.getLatestFile(binding.projectId);\n if (!file) {\n return withLocalBp(\n baseCheckFields(bpUuid, name, localVer, binding, { message: t(\"packUpdate.noRemoteFile\") }),\n localBp\n );\n }\n\n /* \u5DF2\u6210\u529F\u5E94\u7528\u540C\u4E00 fileId\uFF1A\u4E0D\u518D\u4E0B\u8F7D */\n if (isFileIdApplied(binding, file.fileId)) {\n touchBinding(bpUuid, binding, { lastFileId: file.fileId });\n return withLocalBp(\n baseCheckFields(bpUuid, name, localVer, binding, {\n fileId: file.fileId,\n message: t(\"packUpdate.upToDate\"),\n }),\n localBp\n );\n }\n\n if (!downloadArchive) {\n /* \u4EC5\u6587\u4EF6 id \u6BD4\u8F83\u7684\u8F7B\u91CF\u68C0\u67E5\uFF08\u672A apply \u5373\u89C6\u4E3A\u6709\u66F4\u65B0\uFF09 */\n return withLocalBp(\n baseCheckFields(bpUuid, name, localVer, binding, {\n updateAvailable: true,\n fileId: file.fileId,\n message: t(\"packUpdate.fileNewer\", { file: file.fileName, id: String(file.fileId) }),\n }),\n localBp\n );\n }\n\n const stagingDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sfmc-pack-upd-\"));\n const archiveFile = path.join(stagingDir, file.fileName || \"pack.zip\");\n await provider.download(file, archiveFile);\n const resolved = await resolvePackRoots(archiveFile);\n const roots = resolved.roots;\n const bpRoot = roots.find((r) => readPackManifestInfo(r)?.kind === \"behavior\");\n const remoteBpInfo = bpRoot ? readPackManifestInfo(bpRoot) : null;\n if (!remoteBpInfo) {\n resolved.dispose();\n try {\n fs.rmSync(stagingDir, { recursive: true, force: true });\n } catch {\n /* ignore */\n }\n return withLocalBp(\n baseCheckFields(bpUuid, name, localVer, binding, {\n fileId: file.fileId,\n message: t(\"packUpdate.remoteNoBp\"),\n }),\n localBp\n );\n }\n\n /*\n * \u80FD\u8D70\u5230\u6B64\u5904\u8BF4\u660E\u8BE5 fileId \u5C1A\u672A\u6210\u529F apply\uFF08\u4E0A\u65B9\u5DF2 early-return\uFF09\u3002\n * - \u8FDC\u7A0B BP \u7248\u672C\u66F4\u9AD8 \u2192 \u8986\u76D6\n * - \u7248\u672C\u672A\u66F4\u9AD8 \u2192 \u4ECD\u8986\u76D6\uFF08\u6C49\u5316\u5305\u7B49\u540C\u7248\u672C\u53F7\u4E0D\u540C\u5185\u5BB9\uFF1B\u52FF\u5728\u672A install \u65F6\u5199 lastAppliedFileId\uFF09\n * RP bump \u89C4\u5219\u96C6\u4E2D\u5728 decideVersionPolicy\uFF08OCP/DRY\uFF1A\u52FF\u5728\u7F16\u6392\u5C42\u590D\u523B policy \u5B57\u6BB5\uFF09\u3002\n */\n const decision = decideVersionPolicy(localVer, remoteBpInfo.version, cfg.versionPolicy, {\n treatAsUpdate: true,\n });\n\n touchBinding(bpUuid, binding, { lastFileId: file.fileId });\n\n const message = decision.remoteNewer\n ? t(\"packUpdate.bpNewer\", {\n local: fmtVer(localVer),\n remote: fmtVer(remoteBpInfo.version),\n })\n : t(\"packUpdate.needSync\", {\n local: fmtVer(localVer),\n remote: fmtVer(remoteBpInfo.version),\n id: String(file.fileId),\n });\n\n return withLocalBp(\n {\n bpUuid,\n name,\n localVer,\n remoteVer: remoteBpInfo.version,\n updateAvailable: true,\n majorHigher: decision.majorHigher,\n shouldBumpRp: decision.shouldBumpRp,\n fileId: file.fileId,\n message,\n binding,\n remoteBpInfo,\n remoteRoots: roots,\n stagingDir,\n disposeRoots: resolved.dispose,\n },\n localBp\n );\n }\n\n function cleanupCheck(r: CheckResult): void {\n if (r.disposeRoots) {\n try {\n r.disposeRoots();\n } catch {\n /* ignore */\n }\n }\n for (const d of [r.tempDir, r.stagingDir]) {\n if (!d) continue;\n try {\n fs.rmSync(d, { recursive: true, force: true });\n } catch {\n /* ignore */\n }\n }\n }\n\n /** \u5C1D\u8BD5\u5B89\u88C5\u914D\u5BF9 RP\uFF1Baccept \u4E3A\u8FC7\u6EE4\u8C13\u8BCD\uFF08DRY\uFF1A\u4E24\u5904\u5FAA\u73AF\u5408\u4E00\uFF09 */\n async function tryInstallResourcePack(opts: {\n rpRoots: string[];\n bdsRoot: string;\n levelName: string;\n folderName?: string;\n accept: (info: PackManifestInfo) => boolean;\n }): Promise<{ info: PackManifestInfo; destDir: string } | null> {\n for (const root of opts.rpRoots) {\n const info = readPackManifestInfo(root);\n if (!info || !opts.accept(info)) continue;\n const rpDest = worldPackParentDir(opts.bdsRoot, opts.levelName, \"resource\");\n const rpInstall = await installPackDirectory({\n srcDir: root,\n destParent: rpDest,\n force: true,\n ...(opts.folderName ? { folderName: opts.folderName } : {}),\n });\n if (rpInstall.ok && rpInstall.info && rpInstall.destDir) {\n return { info: rpInstall.info, destDir: rpInstall.destDir };\n }\n }\n return null;\n }\n\n async function applyUpdate(r: CheckResult, cfg: PackUpdateConfig): Promise<{ ok: boolean; message: string }> {\n if (!r.updateAvailable || !r.remoteRoots || !r.remoteBpInfo) {\n return { ok: true, message: r.message };\n }\n const { bdsRoot, levelName } = deps.resolveBdsContext();\n const packs = listInstalledWorldPacks(bdsRoot, levelName);\n\n const oldRp =\n r.binding.pairedResourceUuid != null\n ? packs.find(\n (p) => p.kind === \"resource\" && p.uuid.toLowerCase() === r.binding.pairedResourceUuid!.toLowerCase()\n )\n : undefined;\n const oldRpVer: SemVer3 = oldRp?.version ?? [0, 0, 0];\n\n const bpRoot = r.remoteRoots.find((x) => readPackManifestInfo(x)?.kind === \"behavior\");\n const rpRoots = r.remoteRoots.filter((x) => readPackManifestInfo(x)?.kind === \"resource\");\n\n if (!bpRoot) return { ok: false, message: t(\"packUpdate.remoteNoBp\") };\n\n /* \u5B89\u88C5 BP\uFF08force \u8986\u76D6\u540C uuid / \u540C\u6587\u4EF6\u5939\uFF09 */\n const bpDest = worldPackParentDir(bdsRoot, levelName, \"behavior\");\n const bpInstall = await installPackDirectory({\n srcDir: bpRoot,\n destParent: bpDest,\n force: true,\n ...(r.localBp?.folderName ? { folderName: r.localBp.folderName } : {}),\n });\n if (!bpInstall.ok || !bpInstall.info || !bpInstall.destDir) {\n return { ok: false, message: t(\"packUpdate.installFail\", { reason: bpInstall.reason ?? \"?\" }) };\n }\n await enableInstalledPack({ bdsRoot, levelName, info: bpInstall.info });\n logPack(\n t(\"packUpdate.installedBp\", {\n dir: bpInstall.destDir,\n version: fmtVer(bpInstall.info.version),\n }),\n \"success\"\n );\n\n /* \u5B89\u88C5\u914D\u5BF9 RP\uFF1A\u5148\u6309 binding uuid\uFF0C\u518D\u6309\u65B0 BP dependencies */\n let rpInfo: PackManifestInfo | null = null;\n let rpDir: string | null = null;\n const wantRp = r.binding.pairedResourceUuid?.toLowerCase();\n const installed = await tryInstallResourcePack({\n rpRoots,\n bdsRoot,\n levelName,\n ...(oldRp?.folderName ? { folderName: oldRp.folderName } : {}),\n accept: (info) => !wantRp || info.uuid.toLowerCase() === wantRp,\n });\n if (installed) {\n rpInfo = installed.info;\n rpDir = installed.destDir;\n }\n\n if (!rpInfo && rpRoots.length > 0) {\n const depList = readPackDependencyUuids(bpInstall.destDir);\n const fallback = await tryInstallResourcePack({\n rpRoots,\n bdsRoot,\n levelName,\n accept: (info) =>\n depList.length === 0 || depList.some((d) => d.toLowerCase() === info.uuid.toLowerCase()),\n });\n if (fallback) {\n rpInfo = fallback.info;\n rpDir = fallback.destDir;\n r.binding.pairedResourceUuid = fallback.info.uuid;\n }\n }\n\n /* \u542F\u7528\u7248\u672C = bump(max(\u65B0\u5305, \u65E7 RP))\uFF0C\u5355\u4E00\u89C4\u5219\u89E6\u53D1\u5BA2\u6237\u7AEF\u5237\u65B0 */\n if (rpInfo && rpDir && r.shouldBumpRp) {\n const next = ensureVersionGreaterThan(rpDir, oldRpVer, cfg.versionPolicy.rpBumpComponent);\n rpInfo = { ...rpInfo, version: next };\n }\n\n if (rpInfo) {\n await enableInstalledPack({ bdsRoot, levelName, info: rpInfo });\n logPack(\n t(\"packUpdate.installedRp\", {\n dir: rpDir ?? \"-\",\n version: fmtVer(rpInfo.version),\n }),\n \"success\"\n );\n } else if (rpRoots.length > 0) {\n logPack(t(\"packUpdate.rpInstallMiss\"), \"warn\");\n }\n\n touchBinding(r.bpUuid, r.binding, {\n lastAppliedFileId: r.fileId,\n lastFileId: r.fileId,\n lastCheckedAt: new Date().toISOString(),\n });\n\n return {\n ok: true,\n message: t(\"packUpdate.applied\", {\n name: r.name,\n bp: fmtVer(bpInstall.info.version),\n rp: rpInfo ? fmtVer(rpInfo.version) : \"-\",\n }),\n };\n }\n\n async function checkPackUpdates(opts?: { packId?: string; apply?: boolean }): Promise<string> {\n const cfg = loadPackUpdateConfig();\n if (!cfg.enabled) return c.dim(t(\"packUpdate.disabled\"));\n /* \u5165\u53E3\u9884\u68C0\uFF1A\u4EFB\u4E00\u5DF2\u914D\u7F6E\u6E90\u5373\u53EF\uFF1B\u9010 binding \u4ECD\u6309 binding.provider \u5206\u6D3E\uFF08LSP/OCP\uFF09 */\n if (!resolveConfiguredPackProvider(cfg)) {\n return c.yellow(needKeyText());\n }\n\n const { bdsRoot, levelName } = deps.resolveBdsContext();\n const packs = listInstalledWorldPacks(bdsRoot, levelName);\n let targets = listBindings();\n if (opts?.packId) {\n const pack = findInstalledPackById(packs, opts.packId);\n const uuid = pack?.uuid ?? opts.packId;\n targets = targets.filter((x) => x.bpUuid.toLowerCase() === uuid.toLowerCase());\n if (targets.length === 0) {\n const b = getBinding(uuid);\n if (b) targets = [{ bpUuid: uuid, binding: b }];\n }\n if (targets.length === 0) return c.red(t(\"packUpdate.noBinding\", { id: opts.packId }));\n }\n\n if (targets.length === 0) return c.dim(t(\"packUpdate.sourcesEmpty\"));\n\n const lines: string[] = [];\n for (const { bpUuid, binding } of targets) {\n if (cfg.startup.skipDisabledBindings && !binding.enabled && !opts?.packId) continue;\n let result: CheckResult | null = null;\n try {\n /* \u59CB\u7EC8\u4E0B\u8F7D\u5F52\u6863\u5E76\u6309 BP \u7248\u672C\u6BD4\u8F83 */\n result = await prepareCheck(bpUuid, binding, cfg, packs, true);\n if (opts?.apply && result.updateAvailable) {\n const applied = await applyUpdate(result, cfg);\n lines.push(applied.ok ? c.green(applied.message) : c.red(applied.message));\n } else {\n lines.push(\n result.updateAvailable\n ? c.yellow(`${result.name}: ${result.message}`)\n : c.dim(`${result.name}: ${result.message}`)\n );\n }\n } catch (e) {\n lines.push(c.red(`${bpUuid}: ${(e as Error).message}`));\n if (cfg.startup.failMode === \"abort\") break;\n } finally {\n if (result) cleanupCheck(result);\n }\n if (cfg.startup.delayMsBetweenPacks > 0) {\n await new Promise((r) => setTimeout(r, cfg.startup.delayMsBetweenPacks));\n }\n }\n return lines.join(\"\\n\") || c.dim(t(\"packUpdate.sourcesEmpty\"));\n }\n\n /** BDS \u542F\u52A8\u94A9\u5B50\uFF1A\u9010\u4E2A\u68C0\u67E5\u5E76\u6309\u914D\u7F6E\u5E94\u7528 */\n async function runPackUpdatesOnBdsStart(): Promise<void> {\n const cfg = loadPackUpdateConfig();\n if (!cfg.enabled || !cfg.checkOnBdsStart) return;\n try {\n const out = await checkPackUpdates({ apply: cfg.applyOnBdsStart });\n if (out.trim()) logPack(out.replace(/\\x1B\\[[0-9;]*m/g, \"\"), \"info\");\n } catch (e) {\n logPack(t(\"packUpdate.startupFail\", { message: (e as Error).message }), \"warn\");\n }\n }\n\n function bindingLabelForUuid(uuid: string): string {\n const b = getBinding(uuid);\n if (!b) return \"src=-\";\n const tag = `${providerShortLabel(b.provider)}:${b.slug || b.projectId}`;\n /* \u4E0E packs list / sources \u4E00\u81F4\uFF1A\u5173\u95ED\u65F6\u4ECD\u663E\u793A\u6E90\uFF0C\u5E76\u6807\u6CE8 off */\n return b.enabled ? `src=${tag}` : `src=${tag}:off`;\n }\n\n return {\n pairedRpUuidFromBpDir,\n probeSourceAfterInstall,\n searchRemote,\n bindPackSource,\n formatSourcesList,\n checkPackUpdates,\n runPackUpdatesOnBdsStart,\n bindingLabelForUuid,\n };\n}\n\nexport type PackUpdateServiceApi = ReturnType<typeof createPackUpdateServiceApi>;\n"],
5
+ "mappings": "AAGA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AAIjB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,SAAS,2BACd,MACA,QACA,UACA;AACA,QAAM,EAAE,GAAG,OAAO,EAAE,IAAI;AACxB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,EAAE,YAAY,cAAc,iBAAiB,WAAW,IAAI;AAElE,WAAS,QAAQ,MAAc,QAA+C,QAAc;AAC1F,SAAK,IAAI,MAAM,KAAK;AAAA,EACtB;AAEA,WAAS,OAAO,GAAoB;AAClC,WAAO,EAAE,KAAK,GAAG;AAAA,EACnB;AAGA,WAAS,oBAAoB,SAA0B;AACrD,WAAO,UAAU,EAAE,eAAe,EAAE,KAAK,IAAI,EAAE,gBAAgB,EAAE,KAAK;AAAA,EACxE;AAGA,WAAS,cAAsB;AAC7B,WAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,EAAE,CAAC;AAAA,EACjE;AAGA,WAAS,aAAa,MAKK;AACzB,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,UAAU,mBAAmB,KAAK,QAAQ;AAAA,MAC1C,MAAM,KAAK;AAAA,MACX,SAAS,oBAAoB,KAAK,OAAO;AAAA,MACzC,MAAM,gBAAgB;AAAA,IACxB;AAAA,EACF;AAGA,WAAS,aAAa,QAAgB,SAA4B,OAA0C;AAC1G,QAAI,MAAO,QAAO,OAAO,SAAS,KAAK;AACvC,eAAW,QAAQ,OAAO;AAAA,EAC5B;AAGA,WAAS,gBAAgB,SAA4B,QAAyB;AAC5E,WAAO,QAAQ,qBAAqB,QAAQ,QAAQ,sBAAsB;AAAA,EAC5E;AAGA,iBAAe,kBACb,UACA,SACA,iBACyD;AACzD,UAAM,OAAO,oBAAI,IAA6B;AAC9C,eAAW,KAAK,SAAS;AACvB,YAAM,OAAO,MAAM,SAAS,OAAO,CAAC;AACpC,iBAAW,KAAK,KAAM,MAAK,IAAI,EAAE,WAAW,CAAC;AAAA,IAC/C;AACA,WAAO,CAAC,GAAG,KAAK,OAAO,CAAC,EACrB,IAAI,CAAC,OAAO;AAAA,MACX,KAAK;AAAA,MACL,OAAO,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,gBAAgB,GAAG,GAAG,eAAe,CAAC,CAAC;AAAA,IAC/E,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAAA,EACrC;AAEA,WAAS,mBACP,KACA,oBACA,MACmB;AACnB,UAAM,OAAO,MAAM;AACnB,WAAO;AAAA;AAAA,MAEL,SAAS,MAAM,WAAW,MAAM,kBAAkB;AAAA,MAClD,UAAU,IAAI;AAAA,MACd,WAAW,IAAI;AAAA,MACf,MAAM,IAAI;AAAA,MACV,YAAY,IAAI;AAAA,MAChB;AAAA,MACA,YAAY,MAAM,cAAc;AAAA,MAChC,eAAe;AAAA,MACf,mBAAmB,MAAM,qBAAqB;AAAA,IAChD;AAAA,EACF;AAGA,WAAS,sBAAsB,OAA8B;AAC3D,UAAM,UAAU,wBAAwB,KAAK;AAC7C,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAEA,iBAAe,wBAAwB,MAMrB;AAChB,UAAM,MAAM,qBAAqB;AACjC,QAAI,CAAC,IAAI,WAAW,CAAC,IAAI,wBAAyB;AAClD,QAAI,KAAK,KAAK,SAAS,WAAY;AAEnC,+BAA2B;AAC3B,UAAM,WAAW,8BAA8B,GAAG;AAClD,QAAI,CAAC,UAAU;AACb,cAAQ,YAAY,GAAG,MAAM;AAC7B;AAAA,IACF;AAEA,UAAM,QAAQ,mBAAmB,GAAG;AAEpC,UAAM,aACH,KAAK,cAAc,OAAO,KAAK,UAAU,EAAE,KAAK,MAChD,KAAK,UAAU,KAAK,SAAS,KAAK,OAAO,IAAI;AAChD,UAAM,OAAO;AAAA,MACX;AAAA,QACE,EAAE,IAAI,UAAU,KAAK,KAAK,KAAK,KAAK;AAAA,QACpC,EAAE,IAAI,UAAU,KAAK,WAAW;AAAA,MAClC;AAAA,MACA,MAAM;AAAA,IACR;AACA,UAAM,UAAU,KAAK;AACrB,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,EAAE,wBAAwB,GAAG,MAAM;AAC3C;AAAA,IACF;AAEA;AAAA,MACE,EAAE,2BAA2B;AAAA,QAC3B,QAAQ,KAAK,KAAK,QAAQ;AAAA,QAC1B,QAAQ,cAAc;AAAA,QACtB,SAAS,QAAQ,KAAK,KAAK;AAAA,MAC7B,CAAC;AAAA,MACD;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,kBAAkB,UAAU,SAAS,MAAM,eAAe;AAAA,IAC3E,SAAS,GAAG;AACV,cAAQ,EAAE,wBAAwB,EAAE,SAAU,EAAY,QAAQ,CAAC,GAAG,MAAM;AAC5E;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,GAAG;AACvB,cAAQ,EAAE,wBAAwB,EAAE,MAAM,QAAQ,KAAK,IAAI,EAAE,CAAC,GAAG,MAAM;AACvE;AAAA,IACF;AAEA,UAAM,UAAU,QAAQ,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC;AACpE,UAAM,OAAO,OAAO,CAAC;AACrB,QAAI,KAAK,QAAQ,MAAM,cAAc;AACnC;AAAA,QACE,EAAE,4BAA4B;AAAA,UAC5B,MAAM;AAAA,UACN,KAAK,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI;AAAA,UACvC,OAAO,KAAK,MAAM,QAAQ,CAAC;AAAA,UAC3B,KAAK,KAAK,IAAI;AAAA,QAChB,CAAC;AAAA,QACD;AAAA,MACF;AACA;AAAA,IACF;AAEA;AAAA,MACE,EAAE,uBAAuB;AAAA,QACvB,MAAM,GAAG,KAAK,KAAK,IAAI,MAAM,cAAc,GAAG;AAAA,QAC9C,KAAK,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI;AAAA,QACvC,KAAK,KAAK,IAAI;AAAA,QACd,OAAO,KAAK,MAAM,QAAQ,CAAC;AAAA,MAC7B,CAAC;AAAA,MACD;AAAA,IACF;AACA,YAAQ,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,EAAE,CAAC,GAAG,MAAM;AAErE,UAAM,cAAc,KAAK,eAAe,CAAC,CAAC,QAAQ,MAAM;AACxD,QAAI,SAAS;AACb,QAAI,eAAe,IAAI,oBAAoB,QAAQ,MAAM,OAAO;AAC9D,eAAS,MAAM,KAAK,WAAW,EAAE,0BAA0B,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC;AAAA,IACpF,OAAO;AAEL,eAAS;AACT;AAAA,QACE,EAAE,4BAA4B;AAAA,UAC5B,UAAU,mBAAmB,KAAK,IAAI,QAAQ;AAAA,UAC9C,MAAM,KAAK,IAAI;AAAA,UACf,MAAM,gBAAgB;AAAA,QACxB,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ;AACX,cAAQ,EAAE,wBAAwB,GAAG,MAAM;AAC3C;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,UAAU,sBAAsB,KAAK,OAAO,IAAI,SAAS;AAC9E,UAAM,UAAU,mBAAmB,KAAK,KAAK,QAAQ,EAAE,gBAAgB,IAAI,sBAAsB,CAAC;AAClG,eAAW,KAAK,KAAK,MAAM,OAAO;AAClC;AAAA,MACE;AAAA,QACE;AAAA,QACA,aAAa;AAAA,UACX,MAAM,KAAK,KAAK;AAAA,UAChB,UAAU,KAAK,IAAI;AAAA,UACnB,MAAM,KAAK,IAAI;AAAA,UACf,SAAS,QAAQ;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,aAAa,OAAgC;AAC1D,UAAM,MAAM,qBAAqB;AACjC,UAAM,WAAW,8BAA8B,GAAG;AAClD,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,OAAO,YAAY,CAAC;AAAA,IAC/B;AACA,UAAM,QAAQ,mBAAmB,GAAG;AACpC,UAAM,UAAU,mBAAmB,OAAO,MAAM,eAAe;AAC/D,UAAM,SAAS,MAAM,kBAAkB,UAAU,SAAS,MAAM,eAAe;AAC/E,QAAI,OAAO,WAAW,EAAG,QAAO,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,CAAC,CAAC;AAC5E,WAAO,OACJ;AAAA,MACC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAClB,GAAG,EAAE,KAAK,OAAO,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,MAAM,EAAE,SAAS,SAAS,EAAE,IAAI,UAAU,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC;AAAA,MAAS,EAAE,UAAU;AAAA,IAChJ,EACC,KAAK,IAAI;AAAA,EACd;AAEA,iBAAe,eAAe,QAAgB,KAA8B;AAC1E,UAAM,MAAM,qBAAqB;AACjC,UAAM,WAAW,8BAA8B,GAAG;AAClD,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,OAAO,YAAY,CAAC;AAAA,IAC/B;AACA,UAAM,EAAE,SAAS,UAAU,IAAI,KAAK,kBAAkB;AACtD,UAAM,QAAQ,wBAAwB,SAAS,SAAS;AACxD,UAAM,OAAO,sBAAsB,OAAO,MAAM;AAChD,QAAI,CAAC,KAAM,QAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,OAAO,CAAC,CAAC;AAC3D,QAAI,KAAK,SAAS,WAAY,QAAO,EAAE,IAAI,EAAE,uBAAuB,CAAC;AAErE,UAAM,MAAM,MAAM,SAAS,eAAe,GAAG;AAC7C,QAAI,CAAC,IAAK,QAAO,EAAE,IAAI,EAAE,0BAA0B,EAAE,IAAI,CAAC,CAAC;AAE3D,UAAM,SAAS,sBAAsB,KAAK,GAAG;AAC7C,UAAM,UAAU,mBAAmB,KAAK,QAAQ;AAAA,MAC9C,MAAM,WAAW,KAAK,IAAI;AAAA,MAC1B,gBAAgB,IAAI;AAAA,IACtB,CAAC;AACD,eAAW,KAAK,MAAM,OAAO;AAC7B,WAAO,EAAE;AAAA,MACP;AAAA,QACE;AAAA,QACA,aAAa;AAAA,UACX,MAAM,KAAK;AAAA,UACX,UAAU,IAAI;AAAA,UACd,MAAM,IAAI;AAAA,UACV,SAAS,QAAQ;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,WAAS,oBAA4B;AACnC,+BAA2B;AAC3B,UAAM,cAAc,aAAa;AACjC,UAAM,QAAQ;AAAA,MACZ,EAAE,4BAA4B;AAAA,QAC5B,QAAQ,qBAAqB;AAAA,QAC7B,SAAS,gBAAgB;AAAA,MAC3B,CAAC;AAAA,IACH;AACA,QAAI,YAAY,WAAW,GAAG;AAC5B,YAAM,KAAK,EAAE,IAAI,EAAE,yBAAyB,CAAC,CAAC;AAC9C,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AACA,eAAW,EAAE,QAAQ,QAAQ,KAAK,aAAa;AAC7C,YAAM,QAAQ,oBAAoB,QAAQ,OAAO;AACjD,YAAM,KAAK,QAAQ,UAAU,EAAE,MAAM,KAAK,IAAI,EAAE,IAAI,KAAK;AACzD,YAAM,MAAM,mBAAmB,QAAQ,QAAQ;AAC/C,YAAM;AAAA,QACJ,MAAM,EAAE,KAAK,MAAM,KAAK,GAAG,IAAI,QAAQ,QAAQ,QAAQ,SAAS,KAAK,EAAE,IAAI,QAAQ,cAAc,EAAE,CAAC;AAAA,MACtG;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAuBA,WAAS,YAAY,MAAoC,SAAsD;AAC7G,WAAO,UAAU,EAAE,GAAG,MAAM,QAAQ,IAAI,EAAE,GAAG,KAAK;AAAA,EACpD;AAEA,WAAS,gBACP,QACA,MACA,UACA,SACA,QAC8B;AAC9B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,QAAQ;AAAA,MACR;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAEA,iBAAe,aACb,QACA,SACA,KACA,OACA,iBACsB;AACtB,UAAM,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,KAAK,YAAY,MAAM,OAAO,YAAY,KAAK,EAAE,SAAS,UAAU;AACxG,UAAM,OAAO,SAAS,QAAQ;AAC9B,UAAM,WAAoB,SAAS,WAAW,CAAC,GAAG,GAAG,CAAC;AACtD,UAAM,WAAW,yBAAyB,KAAK,QAAQ,QAAQ;AAE/D,iBAAa,QAAQ,SAAS,EAAE,gBAAe,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAEzE,QAAI,CAAC,QAAQ,SAAS;AACpB,aAAO;AAAA,QACL,gBAAgB,QAAQ,MAAM,UAAU,SAAS,EAAE,SAAS,EAAE,4BAA4B,EAAE,CAAC;AAAA,QAC7F;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,cAAc,QAAQ,SAAS;AAC3D,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,gBAAgB,QAAQ,MAAM,UAAU,SAAS,EAAE,SAAS,EAAE,yBAAyB,EAAE,CAAC;AAAA,QAC1F;AAAA,MACF;AAAA,IACF;AAGA,QAAI,gBAAgB,SAAS,KAAK,MAAM,GAAG;AACzC,mBAAa,QAAQ,SAAS,EAAE,YAAY,KAAK,OAAO,CAAC;AACzD,aAAO;AAAA,QACL,gBAAgB,QAAQ,MAAM,UAAU,SAAS;AAAA,UAC/C,QAAQ,KAAK;AAAA,UACb,SAAS,EAAE,qBAAqB;AAAA,QAClC,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB;AAEpB,aAAO;AAAA,QACL,gBAAgB,QAAQ,MAAM,UAAU,SAAS;AAAA,UAC/C,iBAAiB;AAAA,UACjB,QAAQ,KAAK;AAAA,UACb,SAAS,EAAE,wBAAwB,EAAE,MAAM,KAAK,UAAU,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;AAAA,QACrF,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,GAAG,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAC1E,UAAM,cAAc,KAAK,KAAK,YAAY,KAAK,YAAY,UAAU;AACrE,UAAM,SAAS,SAAS,MAAM,WAAW;AACzC,UAAM,WAAW,MAAM,iBAAiB,WAAW;AACnD,UAAM,QAAQ,SAAS;AACvB,UAAM,SAAS,MAAM,KAAK,CAAC,MAAM,qBAAqB,CAAC,GAAG,SAAS,UAAU;AAC7E,UAAM,eAAe,SAAS,qBAAqB,MAAM,IAAI;AAC7D,QAAI,CAAC,cAAc;AACjB,eAAS,QAAQ;AACjB,UAAI;AACF,WAAG,OAAO,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACxD,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,QACL,gBAAgB,QAAQ,MAAM,UAAU,SAAS;AAAA,UAC/C,QAAQ,KAAK;AAAA,UACb,SAAS,EAAE,uBAAuB;AAAA,QACpC,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAQA,UAAM,WAAW,oBAAoB,UAAU,aAAa,SAAS,IAAI,eAAe;AAAA,MACtF,eAAe;AAAA,IACjB,CAAC;AAED,iBAAa,QAAQ,SAAS,EAAE,YAAY,KAAK,OAAO,CAAC;AAEzD,UAAM,UAAU,SAAS,cACrB,EAAE,sBAAsB;AAAA,MACtB,OAAO,OAAO,QAAQ;AAAA,MACtB,QAAQ,OAAO,aAAa,OAAO;AAAA,IACrC,CAAC,IACD,EAAE,uBAAuB;AAAA,MACvB,OAAO,OAAO,QAAQ;AAAA,MACtB,QAAQ,OAAO,aAAa,OAAO;AAAA,MACnC,IAAI,OAAO,KAAK,MAAM;AAAA,IACxB,CAAC;AAEL,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,aAAa;AAAA,QACxB,iBAAiB;AAAA,QACjB,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,QACvB,QAAQ,KAAK;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,cAAc,SAAS;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,WAAS,aAAa,GAAsB;AAC1C,QAAI,EAAE,cAAc;AAClB,UAAI;AACF,UAAE,aAAa;AAAA,MACjB,QAAQ;AAAA,MAER;AAAA,IACF;AACA,eAAW,KAAK,CAAC,EAAE,SAAS,EAAE,UAAU,GAAG;AACzC,UAAI,CAAC,EAAG;AACR,UAAI;AACF,WAAG,OAAO,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAC/C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAGA,iBAAe,uBAAuB,MAM0B;AAC9D,eAAW,QAAQ,KAAK,SAAS;AAC/B,YAAM,OAAO,qBAAqB,IAAI;AACtC,UAAI,CAAC,QAAQ,CAAC,KAAK,OAAO,IAAI,EAAG;AACjC,YAAM,SAAS,mBAAmB,KAAK,SAAS,KAAK,WAAW,UAAU;AAC1E,YAAM,YAAY,MAAM,qBAAqB;AAAA,QAC3C,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,GAAI,KAAK,aAAa,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,MAC3D,CAAC;AACD,UAAI,UAAU,MAAM,UAAU,QAAQ,UAAU,SAAS;AACvD,eAAO,EAAE,MAAM,UAAU,MAAM,SAAS,UAAU,QAAQ;AAAA,MAC5D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,YAAY,GAAgB,KAAkE;AAC3G,QAAI,CAAC,EAAE,mBAAmB,CAAC,EAAE,eAAe,CAAC,EAAE,cAAc;AAC3D,aAAO,EAAE,IAAI,MAAM,SAAS,EAAE,QAAQ;AAAA,IACxC;AACA,UAAM,EAAE,SAAS,UAAU,IAAI,KAAK,kBAAkB;AACtD,UAAM,QAAQ,wBAAwB,SAAS,SAAS;AAExD,UAAM,QACJ,EAAE,QAAQ,sBAAsB,OAC5B,MAAM;AAAA,MACJ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,KAAK,YAAY,MAAM,EAAE,QAAQ,mBAAoB,YAAY;AAAA,IACrG,IACA;AACN,UAAM,WAAoB,OAAO,WAAW,CAAC,GAAG,GAAG,CAAC;AAEpD,UAAM,SAAS,EAAE,YAAY,KAAK,CAAC,MAAM,qBAAqB,CAAC,GAAG,SAAS,UAAU;AACrF,UAAM,UAAU,EAAE,YAAY,OAAO,CAAC,MAAM,qBAAqB,CAAC,GAAG,SAAS,UAAU;AAExF,QAAI,CAAC,OAAQ,QAAO,EAAE,IAAI,OAAO,SAAS,EAAE,uBAAuB,EAAE;AAGrE,UAAM,SAAS,mBAAmB,SAAS,WAAW,UAAU;AAChE,UAAM,YAAY,MAAM,qBAAqB;AAAA,MAC3C,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,GAAI,EAAE,SAAS,aAAa,EAAE,YAAY,EAAE,QAAQ,WAAW,IAAI,CAAC;AAAA,IACtE,CAAC;AACD,QAAI,CAAC,UAAU,MAAM,CAAC,UAAU,QAAQ,CAAC,UAAU,SAAS;AAC1D,aAAO,EAAE,IAAI,OAAO,SAAS,EAAE,0BAA0B,EAAE,QAAQ,UAAU,UAAU,IAAI,CAAC,EAAE;AAAA,IAChG;AACA,UAAM,oBAAoB,EAAE,SAAS,WAAW,MAAM,UAAU,KAAK,CAAC;AACtE;AAAA,MACE,EAAE,0BAA0B;AAAA,QAC1B,KAAK,UAAU;AAAA,QACf,SAAS,OAAO,UAAU,KAAK,OAAO;AAAA,MACxC,CAAC;AAAA,MACD;AAAA,IACF;AAGA,QAAI,SAAkC;AACtC,QAAI,QAAuB;AAC3B,UAAM,SAAS,EAAE,QAAQ,oBAAoB,YAAY;AACzD,UAAM,YAAY,MAAM,uBAAuB;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,OAAO,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC5D,QAAQ,CAAC,SAAS,CAAC,UAAU,KAAK,KAAK,YAAY,MAAM;AAAA,IAC3D,CAAC;AACD,QAAI,WAAW;AACb,eAAS,UAAU;AACnB,cAAQ,UAAU;AAAA,IACpB;AAEA,QAAI,CAAC,UAAU,QAAQ,SAAS,GAAG;AACjC,YAAM,UAAU,wBAAwB,UAAU,OAAO;AACzD,YAAM,WAAW,MAAM,uBAAuB;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,CAAC,SACP,QAAQ,WAAW,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,KAAK,KAAK,YAAY,CAAC;AAAA,MAC3F,CAAC;AACD,UAAI,UAAU;AACZ,iBAAS,SAAS;AAClB,gBAAQ,SAAS;AACjB,UAAE,QAAQ,qBAAqB,SAAS,KAAK;AAAA,MAC/C;AAAA,IACF;AAGA,QAAI,UAAU,SAAS,EAAE,cAAc;AACrC,YAAM,OAAO,yBAAyB,OAAO,UAAU,IAAI,cAAc,eAAe;AACxF,eAAS,EAAE,GAAG,QAAQ,SAAS,KAAK;AAAA,IACtC;AAEA,QAAI,QAAQ;AACV,YAAM,oBAAoB,EAAE,SAAS,WAAW,MAAM,OAAO,CAAC;AAC9D;AAAA,QACE,EAAE,0BAA0B;AAAA,UAC1B,KAAK,SAAS;AAAA,UACd,SAAS,OAAO,OAAO,OAAO;AAAA,QAChC,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,GAAG;AAC7B,cAAQ,EAAE,0BAA0B,GAAG,MAAM;AAAA,IAC/C;AAEA,iBAAa,EAAE,QAAQ,EAAE,SAAS;AAAA,MAChC,mBAAmB,EAAE;AAAA,MACrB,YAAY,EAAE;AAAA,MACd,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,IACxC,CAAC;AAED,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,EAAE,sBAAsB;AAAA,QAC/B,MAAM,EAAE;AAAA,QACR,IAAI,OAAO,UAAU,KAAK,OAAO;AAAA,QACjC,IAAI,SAAS,OAAO,OAAO,OAAO,IAAI;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,iBAAe,iBAAiB,MAA8D;AAC5F,UAAM,MAAM,qBAAqB;AACjC,QAAI,CAAC,IAAI,QAAS,QAAO,EAAE,IAAI,EAAE,qBAAqB,CAAC;AAEvD,QAAI,CAAC,8BAA8B,GAAG,GAAG;AACvC,aAAO,EAAE,OAAO,YAAY,CAAC;AAAA,IAC/B;AAEA,UAAM,EAAE,SAAS,UAAU,IAAI,KAAK,kBAAkB;AACtD,UAAM,QAAQ,wBAAwB,SAAS,SAAS;AACxD,QAAI,UAAU,aAAa;AAC3B,QAAI,MAAM,QAAQ;AAChB,YAAM,OAAO,sBAAsB,OAAO,KAAK,MAAM;AACrD,YAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,YAAY,MAAM,KAAK,YAAY,CAAC;AAC7E,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,IAAI,WAAW,IAAI;AACzB,YAAI,EAAG,WAAU,CAAC,EAAE,QAAQ,MAAM,SAAS,EAAE,CAAC;AAAA,MAChD;AACA,UAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;AAAA,IACvF;AAEA,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,IAAI,EAAE,yBAAyB,CAAC;AAEnE,UAAM,QAAkB,CAAC;AACzB,eAAW,EAAE,QAAQ,QAAQ,KAAK,SAAS;AACzC,UAAI,IAAI,QAAQ,wBAAwB,CAAC,QAAQ,WAAW,CAAC,MAAM,OAAQ;AAC3E,UAAI,SAA6B;AACjC,UAAI;AAEF,iBAAS,MAAM,aAAa,QAAQ,SAAS,KAAK,OAAO,IAAI;AAC7D,YAAI,MAAM,SAAS,OAAO,iBAAiB;AACzC,gBAAM,UAAU,MAAM,YAAY,QAAQ,GAAG;AAC7C,gBAAM,KAAK,QAAQ,KAAK,EAAE,MAAM,QAAQ,OAAO,IAAI,EAAE,IAAI,QAAQ,OAAO,CAAC;AAAA,QAC3E,OAAO;AACL,gBAAM;AAAA,YACJ,OAAO,kBACH,EAAE,OAAO,GAAG,OAAO,IAAI,KAAK,OAAO,OAAO,EAAE,IAC5C,EAAE,IAAI,GAAG,OAAO,IAAI,KAAK,OAAO,OAAO,EAAE;AAAA,UAC/C;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,cAAM,KAAK,EAAE,IAAI,GAAG,MAAM,KAAM,EAAY,OAAO,EAAE,CAAC;AACtD,YAAI,IAAI,QAAQ,aAAa,QAAS;AAAA,MACxC,UAAE;AACA,YAAI,OAAQ,cAAa,MAAM;AAAA,MACjC;AACA,UAAI,IAAI,QAAQ,sBAAsB,GAAG;AACvC,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,IAAI,QAAQ,mBAAmB,CAAC;AAAA,MACzE;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,EAAE,yBAAyB,CAAC;AAAA,EAC/D;AAGA,iBAAe,2BAA0C;AACvD,UAAM,MAAM,qBAAqB;AACjC,QAAI,CAAC,IAAI,WAAW,CAAC,IAAI,gBAAiB;AAC1C,QAAI;AACF,YAAM,MAAM,MAAM,iBAAiB,EAAE,OAAO,IAAI,gBAAgB,CAAC;AACjE,UAAI,IAAI,KAAK,EAAG,SAAQ,IAAI,QAAQ,mBAAmB,EAAE,GAAG,MAAM;AAAA,IACpE,SAAS,GAAG;AACV,cAAQ,EAAE,0BAA0B,EAAE,SAAU,EAAY,QAAQ,CAAC,GAAG,MAAM;AAAA,IAChF;AAAA,EACF;AAEA,WAAS,oBAAoB,MAAsB;AACjD,UAAM,IAAI,WAAW,IAAI;AACzB,QAAI,CAAC,EAAG,QAAO;AACf,UAAM,MAAM,GAAG,mBAAmB,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS;AAEtE,WAAO,EAAE,UAAU,OAAO,GAAG,KAAK,OAAO,GAAG;AAAA,EAC9C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }