@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,126 @@
1
+ /**
2
+ * pack-update 类型定义
3
+ */
4
+ export type PackReleaseType = "release" | "beta" | "alpha";
5
+ /** 已实现的源提供者 id(扩展时只加字面量,编排层走 PackSourceProvider) */
6
+ export type PackProviderId = "curseforge";
7
+ /**
8
+ * 名称/slug 匹配策略。
9
+ * 探测与 search 共用;勿再加未接线的开关(曾出现 byUuidInArchive/byName 死配置)。
10
+ */
11
+ export interface PackUpdateMatchConfig {
12
+ nameMinScore: number;
13
+ stripFolderTags: boolean;
14
+ }
15
+ /** CF 源专属配置(不含通用 match;match 在 PackUpdateConfig 顶层) */
16
+ export interface CurseForgeProviderConfig {
17
+ enabled: boolean;
18
+ apiKey: string;
19
+ /** 官方 Core API,用于 getMod / files / download-url */
20
+ baseUrl: string;
21
+ /**
22
+ * 搜索用镜像(官方 /v1/mods/search 部分 key 会 403)。
23
+ * 默认 https://api.curse.tools/v1/cf
24
+ */
25
+ searchBaseUrl: string;
26
+ /** Minecraft Bedrock = 78022(不是 459) */
27
+ gameId: number;
28
+ /** Addons class = 4984;null 时自动解析 */
29
+ classId: number | null;
30
+ pageSize: number;
31
+ preferredReleaseTypes: PackReleaseType[];
32
+ }
33
+ export interface VersionPolicyConfig {
34
+ authority: "behavior_pack";
35
+ onUpdateOverwriteBoth: boolean;
36
+ rpBumpWhenSameMajor: boolean;
37
+ rpBumpComponent: "patch" | "minor";
38
+ majorHigherSkipRpBump: boolean;
39
+ }
40
+ export interface StartupUpdateConfig {
41
+ sequential: boolean;
42
+ delayMsBetweenPacks: number;
43
+ skipDisabledBindings: boolean;
44
+ failMode: "continue" | "abort";
45
+ }
46
+ /** 世界包卸载策略(与 CF 更新同属 packs 生命周期配置) */
47
+ export interface PackUninstallConfig {
48
+ /** true:移入回收站;false:直接删除目录 */
49
+ recycleBin: boolean;
50
+ /** 相对 SFMC_ROOT 的回收站路径,默认 packs/_trash */
51
+ trashRelativeDir: string;
52
+ }
53
+ /** 卸载策略内置默认(DEFAULTS / resolve / schema 文案的唯一权威) */
54
+ export declare const DEFAULT_PACK_UNINSTALL: PackUninstallConfig;
55
+ export interface PackUpdateConfig {
56
+ enabled: boolean;
57
+ checkOnBdsStart: boolean;
58
+ applyOnBdsStart: boolean;
59
+ askConfirmOnBind: boolean;
60
+ probeSourceAfterInstall: boolean;
61
+ /**
62
+ * 新建绑定的默认 enabled。
63
+ * false 时探测/手动 bind 仍写入 pack-sources,但不会自动检查/更新,需手改或改此默认。
64
+ */
65
+ defaultBindingEnabled: boolean;
66
+ /**
67
+ * 名称/slug 匹配策略(源无关)。
68
+ * 勿再塞进 providers.*(曾挂在 curseforge 下,违反 DIP/OCP)。
69
+ */
70
+ match: PackUpdateMatchConfig;
71
+ providers: {
72
+ curseforge: CurseForgeProviderConfig;
73
+ };
74
+ versionPolicy: VersionPolicyConfig;
75
+ startup: StartupUpdateConfig;
76
+ uninstall: PackUninstallConfig;
77
+ }
78
+ export interface PackSourceBinding {
79
+ enabled: boolean;
80
+ provider: PackProviderId;
81
+ projectId: number;
82
+ slug: string;
83
+ websiteUrl: string;
84
+ pairedResourceUuid: string | null;
85
+ lastFileId: number | null;
86
+ lastCheckedAt: string | null;
87
+ lastAppliedFileId: number | null;
88
+ }
89
+ export interface PackSourcesFile {
90
+ bindings: Record<string, PackSourceBinding>;
91
+ }
92
+ export interface SourceSearchHit {
93
+ provider: PackProviderId;
94
+ projectId: number;
95
+ slug: string;
96
+ name: string;
97
+ summary: string;
98
+ websiteUrl: string;
99
+ downloadCount?: number;
100
+ }
101
+ export interface SourceFileRef {
102
+ provider: PackProviderId;
103
+ projectId: number;
104
+ fileId: number;
105
+ fileName: string;
106
+ displayName: string;
107
+ downloadUrl: string;
108
+ fileDate?: string;
109
+ releaseType?: PackReleaseType;
110
+ }
111
+ /** 源提供者契约:编排层只依赖此接口(DIP),具体实现可互换(LSP) */
112
+ export interface PackSourceProvider {
113
+ readonly id: PackProviderId;
114
+ isConfigured(): boolean;
115
+ search(query: string): Promise<SourceSearchHit[]>;
116
+ getLatestFile(projectId: number): Promise<SourceFileRef | null>;
117
+ download(file: SourceFileRef, destPath: string, onProgress?: (dl: number, total: number) => void): Promise<void>;
118
+ resolveProject(ref: string | number): Promise<SourceSearchHit | null>;
119
+ }
120
+ export type SemVer3 = [number, number, number];
121
+ export interface VersionCompareResult {
122
+ remoteNewer: boolean;
123
+ majorHigher: boolean;
124
+ shouldBumpRp: boolean;
125
+ }
126
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pack-update/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ const DEFAULT_PACK_UNINSTALL = {
2
+ recycleBin: true,
3
+ trashRelativeDir: "packs/_trash"
4
+ };
5
+ export {
6
+ DEFAULT_PACK_UNINSTALL
7
+ };
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/pack-update/types.ts"],
4
+ "sourcesContent": ["/**\n * pack-update \u7C7B\u578B\u5B9A\u4E49\n */\n\nexport type PackReleaseType = \"release\" | \"beta\" | \"alpha\";\n\n/** \u5DF2\u5B9E\u73B0\u7684\u6E90\u63D0\u4F9B\u8005 id\uFF08\u6269\u5C55\u65F6\u53EA\u52A0\u5B57\u9762\u91CF\uFF0C\u7F16\u6392\u5C42\u8D70 PackSourceProvider\uFF09 */\nexport type PackProviderId = \"curseforge\";\n\n/**\n * \u540D\u79F0/slug \u5339\u914D\u7B56\u7565\u3002\n * \u63A2\u6D4B\u4E0E search \u5171\u7528\uFF1B\u52FF\u518D\u52A0\u672A\u63A5\u7EBF\u7684\u5F00\u5173\uFF08\u66FE\u51FA\u73B0 byUuidInArchive/byName \u6B7B\u914D\u7F6E\uFF09\u3002\n */\nexport interface PackUpdateMatchConfig {\n nameMinScore: number;\n stripFolderTags: boolean;\n}\n\n/** CF \u6E90\u4E13\u5C5E\u914D\u7F6E\uFF08\u4E0D\u542B\u901A\u7528 match\uFF1Bmatch \u5728 PackUpdateConfig \u9876\u5C42\uFF09 */\nexport interface CurseForgeProviderConfig {\n enabled: boolean;\n apiKey: string;\n /** \u5B98\u65B9 Core API\uFF0C\u7528\u4E8E getMod / files / download-url */\n baseUrl: string;\n /**\n * \u641C\u7D22\u7528\u955C\u50CF\uFF08\u5B98\u65B9 /v1/mods/search \u90E8\u5206 key \u4F1A 403\uFF09\u3002\n * \u9ED8\u8BA4 https://api.curse.tools/v1/cf\n */\n searchBaseUrl: string;\n /** Minecraft Bedrock = 78022\uFF08\u4E0D\u662F 459\uFF09 */\n gameId: number;\n /** Addons class = 4984\uFF1Bnull \u65F6\u81EA\u52A8\u89E3\u6790 */\n classId: number | null;\n pageSize: number;\n preferredReleaseTypes: PackReleaseType[];\n}\n\nexport interface VersionPolicyConfig {\n authority: \"behavior_pack\";\n onUpdateOverwriteBoth: boolean;\n rpBumpWhenSameMajor: boolean;\n rpBumpComponent: \"patch\" | \"minor\";\n majorHigherSkipRpBump: boolean;\n}\n\nexport interface StartupUpdateConfig {\n sequential: boolean;\n delayMsBetweenPacks: number;\n skipDisabledBindings: boolean;\n failMode: \"continue\" | \"abort\";\n}\n\n/** \u4E16\u754C\u5305\u5378\u8F7D\u7B56\u7565\uFF08\u4E0E CF \u66F4\u65B0\u540C\u5C5E packs \u751F\u547D\u5468\u671F\u914D\u7F6E\uFF09 */\nexport interface PackUninstallConfig {\n /** true\uFF1A\u79FB\u5165\u56DE\u6536\u7AD9\uFF1Bfalse\uFF1A\u76F4\u63A5\u5220\u9664\u76EE\u5F55 */\n recycleBin: boolean;\n /** \u76F8\u5BF9 SFMC_ROOT \u7684\u56DE\u6536\u7AD9\u8DEF\u5F84\uFF0C\u9ED8\u8BA4 packs/_trash */\n trashRelativeDir: string;\n}\n\n/** \u5378\u8F7D\u7B56\u7565\u5185\u7F6E\u9ED8\u8BA4\uFF08DEFAULTS / resolve / schema \u6587\u6848\u7684\u552F\u4E00\u6743\u5A01\uFF09 */\nexport const DEFAULT_PACK_UNINSTALL: PackUninstallConfig = {\n recycleBin: true,\n trashRelativeDir: \"packs/_trash\",\n};\n\nexport interface PackUpdateConfig {\n enabled: boolean;\n checkOnBdsStart: boolean;\n applyOnBdsStart: boolean;\n askConfirmOnBind: boolean;\n probeSourceAfterInstall: boolean;\n /**\n * \u65B0\u5EFA\u7ED1\u5B9A\u7684\u9ED8\u8BA4 enabled\u3002\n * false \u65F6\u63A2\u6D4B/\u624B\u52A8 bind \u4ECD\u5199\u5165 pack-sources\uFF0C\u4F46\u4E0D\u4F1A\u81EA\u52A8\u68C0\u67E5/\u66F4\u65B0\uFF0C\u9700\u624B\u6539\u6216\u6539\u6B64\u9ED8\u8BA4\u3002\n */\n defaultBindingEnabled: boolean;\n /**\n * \u540D\u79F0/slug \u5339\u914D\u7B56\u7565\uFF08\u6E90\u65E0\u5173\uFF09\u3002\n * \u52FF\u518D\u585E\u8FDB providers.*\uFF08\u66FE\u6302\u5728 curseforge \u4E0B\uFF0C\u8FDD\u53CD DIP/OCP\uFF09\u3002\n */\n match: PackUpdateMatchConfig;\n providers: {\n curseforge: CurseForgeProviderConfig;\n };\n versionPolicy: VersionPolicyConfig;\n startup: StartupUpdateConfig;\n uninstall: PackUninstallConfig;\n}\n\nexport interface PackSourceBinding {\n enabled: boolean;\n provider: PackProviderId;\n projectId: number;\n slug: string;\n websiteUrl: string;\n pairedResourceUuid: string | null;\n lastFileId: number | null;\n lastCheckedAt: string | null;\n lastAppliedFileId: number | null;\n}\n\nexport interface PackSourcesFile {\n bindings: Record<string, PackSourceBinding>;\n}\n\nexport interface SourceSearchHit {\n provider: PackProviderId;\n projectId: number;\n slug: string;\n name: string;\n summary: string;\n websiteUrl: string;\n downloadCount?: number;\n}\n\nexport interface SourceFileRef {\n provider: PackProviderId;\n projectId: number;\n fileId: number;\n fileName: string;\n displayName: string;\n downloadUrl: string;\n fileDate?: string;\n releaseType?: PackReleaseType;\n}\n\n/** \u6E90\u63D0\u4F9B\u8005\u5951\u7EA6\uFF1A\u7F16\u6392\u5C42\u53EA\u4F9D\u8D56\u6B64\u63A5\u53E3\uFF08DIP\uFF09\uFF0C\u5177\u4F53\u5B9E\u73B0\u53EF\u4E92\u6362\uFF08LSP\uFF09 */\nexport interface PackSourceProvider {\n readonly id: PackProviderId;\n isConfigured(): boolean;\n search(query: string): Promise<SourceSearchHit[]>;\n getLatestFile(projectId: number): Promise<SourceFileRef | null>;\n download(file: SourceFileRef, destPath: string, onProgress?: (dl: number, total: number) => void): Promise<void>;\n resolveProject(ref: string | number): Promise<SourceSearchHit | null>;\n}\n\nexport type SemVer3 = [number, number, number];\n\nexport interface VersionCompareResult {\n remoteNewer: boolean;\n majorHigher: boolean;\n shouldBumpRp: boolean;\n}\n"],
5
+ "mappings": "AA6DO,MAAM,yBAA8C;AAAA,EACzD,YAAY;AAAA,EACZ,kBAAkB;AACpB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * 版本策略:以 BP 为准比较;同 major 更新时抬高 RP 版本触发客户端刷新
3
+ */
4
+ import { bumpSemVer3, maxSemVer3, nextEnabledVersion } from "../world-packs.js";
5
+ import type { SemVer3, VersionCompareResult, VersionPolicyConfig } from "./types.js";
6
+ /** 归一化为 -1 | 0 | 1,供策略比较 */
7
+ export declare function compareSemVer3(a: SemVer3, b: SemVer3): number;
8
+ export declare function isNewer(remote: SemVer3, local: SemVer3): boolean;
9
+ export { bumpSemVer3, maxSemVer3, nextEnabledVersion };
10
+ /**
11
+ * 根据本地/远程 BP 版本与策略,决定是否更新以及是否额外 bump RP。
12
+ * `treatAsUpdate`:同版本/未更高但需强制同步写入时(如 fileId 尚未 apply)也走更新侧 RP bump 规则(OCP:策略集中于此,勿在编排层复刻)。
13
+ */
14
+ export declare function decideVersionPolicy(localBp: SemVer3, remoteBp: SemVer3, policy: VersionPolicyConfig, opts?: {
15
+ treatAsUpdate?: boolean;
16
+ }): VersionCompareResult;
17
+ /** 中日韩与拉丁粘连时插入空格:拔刀剑Slash → 拔刀剑 Slash */
18
+ export declare function insertCjkLatinBoundaries(name: string): string;
19
+ /** 去掉整词包角色标记(末尾 BP/RP/Addon 等) */
20
+ export declare function stripPackRoleTokens(name: string): string;
21
+ /** 去掉 v4 / 1.21.100 一类版本尾巴 */
22
+ export declare function stripVersionTokens(name: string): string;
23
+ /** 仅保留拉丁词(CF slug/search 主路径) */
24
+ export declare function extractLatinPhrase(name: string): string;
25
+ /**
26
+ * 共享预处理:§码、方括号标签、扩展名、CJK/拉丁分界、下划线→空格。
27
+ * normalize / collectQuerySeeds 共用,避免两处各写一遍(DRY)。
28
+ */
29
+ export declare function preprocessPackNameRaw(name: string, stripFolderTags?: boolean): string;
30
+ /**
31
+ * 基础清洗:预处理 + 包角色 + 版本号。
32
+ * 例:"[BP] [BA] [玩法] 拔刀剑Slash Blade v4 BP" → "拔刀剑 Slash Blade"
33
+ */
34
+ export declare function normalizePackSearchName(name: string, stripFolderTags?: boolean): string;
35
+ /**
36
+ * 从原始文件夹名/展示名收集多级清洗种子(由脏到净)。
37
+ * 例:"[BP] [BA] [玩法] 拔刀剑Slash Blade v4 BP"
38
+ * → 拔刀剑 Slash Blade v4 BP → Slash Blade v4 BP → Slash Blade v4 → Slash Blade
39
+ */
40
+ export declare function collectQuerySeeds(raw: string, stripFolderTags?: boolean): string[];
41
+ /**
42
+ * 从展示名推导 CF slug 候选(无空格、小写、连字符)。
43
+ * 例:"Slash Blade v4 BP" → "slash-blade"
44
+ */
45
+ export declare function toCfSlugCandidate(name: string, stripFolderTags?: boolean): string;
46
+ /** Title-Case 连字符:slash-blade → Slash-Blade(部分 CF 搜索更吃这个) */
47
+ export declare function toCfTitleSlug(slug: string): string;
48
+ /**
49
+ * 派生一组搜索词:多源输入 × 多级清洗种子 ×(展示名 / slug / Title-Slug / slug-addon)。
50
+ * `name` 可为字符串或数组(如 header.name + 文件夹名)。
51
+ *
52
+ * 规则:只要存在含拉丁字母的候选,就**丢弃纯 CJK 查询**(CF Bedrock 几乎不靠中文搜)。
53
+ */
54
+ export declare function buildSearchQueries(name: string | readonly string[], stripFolderTags?: boolean, maxQueries?: number): string[];
55
+ export type SearchQuerySource = {
56
+ id: string;
57
+ raw: string;
58
+ };
59
+ export type SearchQueryPlan = {
60
+ /** 最终发给 CF 的查询(已去重、排序、截断) */
61
+ queries: string[];
62
+ /** 各源原始输入(便于日志) */
63
+ sources: SearchQuerySource[];
64
+ /** 每源贡献了哪些词(截断前,便于确认双源都参与) */
65
+ perSource: Record<string, string[]>;
66
+ };
67
+ /**
68
+ * 按源分别派生,再合并:保证 header / 文件夹名都会贡献候选,而非混成一锅被截断偏科。
69
+ */
70
+ export declare function buildSearchQueriesFromSources(sources: readonly SearchQuerySource[], stripFolderTags?: boolean, maxQueries?: number): SearchQueryPlan;
71
+ /** 简单相似度:0~1(基于共同 token 与包含关系) */
72
+ export declare function nameSimilarity(a: string, b: string): number;
73
+ /**
74
+ * 综合展示名 + CF slug 打分。
75
+ * slug 无空格(slash-blade-addon),与本地「Slash Blade v4」对齐时权重大于纯 name。
76
+ */
77
+ export declare function packSourceScore(query: string, hit: {
78
+ name: string;
79
+ slug: string;
80
+ }, stripFolderTags?: boolean): number;
81
+ //# sourceMappingURL=version-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-policy.d.ts","sourceRoot":"","sources":["../../src/pack-update/version-policy.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,WAAW,EAEX,UAAU,EACV,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAErF,4BAA4B;AAC5B,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAG7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAEhE;AAED,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,mBAAmB,EAC3B,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,oBAAoB,CAatB;AAMD,yCAAyC;AACzC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED,kCAAkC;AAClC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED,iCAAiC;AACjC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,UAAO,GAAG,MAAM,CAUlF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,UAAO,GAAG,MAAM,CAKpF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,UAAO,GAAG,MAAM,EAAE,CAgC/E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,UAAO,GAAG,MAAM,CAS9E;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EAChC,eAAe,UAAO,EACtB,UAAU,SAAK,GACd,MAAM,EAAE,CAMV;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mBAAmB;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,eAAe,UAAO,EACtB,UAAU,SAAK,GACd,eAAe,CA4EjB;AAED,kCAAkC;AAClC,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAY3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACnC,eAAe,UAAO,GACrB,MAAM,CAcR"}
@@ -0,0 +1,210 @@
1
+ import {
2
+ bumpSemVer3,
3
+ compareSemVer3 as compareSemVer3Raw,
4
+ maxSemVer3,
5
+ nextEnabledVersion
6
+ } from "../world-packs.js";
7
+ function compareSemVer3(a, b) {
8
+ const d = compareSemVer3Raw(a, b);
9
+ return d > 0 ? 1 : d < 0 ? -1 : 0;
10
+ }
11
+ function isNewer(remote, local) {
12
+ return compareSemVer3(remote, local) > 0;
13
+ }
14
+ function decideVersionPolicy(localBp, remoteBp, policy, opts) {
15
+ const remoteNewer = isNewer(remoteBp, localBp);
16
+ const majorHigher = remoteBp[0] > localBp[0];
17
+ const asUpdate = remoteNewer || Boolean(opts?.treatAsUpdate);
18
+ let shouldBumpRp = false;
19
+ if (asUpdate && policy.onUpdateOverwriteBoth) {
20
+ if (majorHigher && policy.majorHigherSkipRpBump) {
21
+ shouldBumpRp = false;
22
+ } else if (policy.rpBumpWhenSameMajor) {
23
+ shouldBumpRp = true;
24
+ }
25
+ }
26
+ return { remoteNewer, majorHigher, shouldBumpRp };
27
+ }
28
+ const PACK_ROLE_TOKEN = /^(?:bp|rp|ba|behavior|behaviours?|resource|resources|pack|packs|addon|addons|mcpack|mcaddon|behavior.?pack|resource.?pack|行为包|资源包|附加包|基岩|bedrock)$/iu;
29
+ function insertCjkLatinBoundaries(name) {
30
+ return String(name ?? "").replace(/([\u3400-\u9fff\uF900-\uFAFF])([A-Za-z])/g, "$1 $2").replace(/([A-Za-z])([\u3400-\u9fff\uF900-\uFAFF])/g, "$1 $2");
31
+ }
32
+ function stripPackRoleTokens(name) {
33
+ return String(name ?? "").split(/[\s_]+/).filter((t) => t && !PACK_ROLE_TOKEN.test(t)).join(" ").replace(/\s+/g, " ").trim();
34
+ }
35
+ function stripVersionTokens(name) {
36
+ return String(name ?? "").replace(/\bv\d+(?:\.\d+)*\b/gi, " ").replace(/\b\d+\.\d+(?:\.\d+)?\b/g, " ").replace(/\s+/g, " ").trim();
37
+ }
38
+ function extractLatinPhrase(name) {
39
+ const words = String(name ?? "").match(/[A-Za-z][A-Za-z0-9]*/g);
40
+ return words ? words.join(" ") : "";
41
+ }
42
+ function preprocessPackNameRaw(name, stripFolderTags = true) {
43
+ let s = String(name ?? "");
44
+ s = s.replace(/§[0-9a-zA-Z]/g, "");
45
+ if (stripFolderTags) {
46
+ s = s.replace(/\[[^\]]*]/g, " ");
47
+ }
48
+ s = s.replace(/\.(zip|mcpack|mcaddon)$/i, "");
49
+ s = insertCjkLatinBoundaries(s);
50
+ s = s.replace(/[_]+/g, " ").replace(/\s+/g, " ").trim();
51
+ return s;
52
+ }
53
+ function normalizePackSearchName(name, stripFolderTags = true) {
54
+ let s = preprocessPackNameRaw(name, stripFolderTags);
55
+ s = stripPackRoleTokens(s);
56
+ s = stripVersionTokens(s);
57
+ return s;
58
+ }
59
+ function collectQuerySeeds(raw, stripFolderTags = true) {
60
+ const seeds = [];
61
+ const push = (q) => {
62
+ const t = q.replace(/\s+/g, " ").trim();
63
+ if (!t) return;
64
+ if (!seeds.some((x) => x.toLowerCase() === t.toLowerCase())) seeds.push(t);
65
+ };
66
+ const s = preprocessPackNameRaw(raw, stripFolderTags);
67
+ push(s);
68
+ const noRole = stripPackRoleTokens(s);
69
+ push(noRole);
70
+ push(stripVersionTokens(s));
71
+ push(stripVersionTokens(noRole));
72
+ const latin = extractLatinPhrase(s);
73
+ push(latin);
74
+ const latinNoRole = stripPackRoleTokens(latin);
75
+ push(latinNoRole);
76
+ const latinCore = stripVersionTokens(latinNoRole);
77
+ push(latinCore);
78
+ let tokens = latinCore.split(/\s+/).filter(Boolean);
79
+ while (tokens.length >= 2) {
80
+ push(tokens.join(" "));
81
+ tokens = tokens.slice(0, -1);
82
+ }
83
+ push(normalizePackSearchName(raw, stripFolderTags));
84
+ return seeds;
85
+ }
86
+ function toCfSlugCandidate(name, stripFolderTags = true) {
87
+ const base = normalizePackSearchName(name, stripFolderTags);
88
+ let s = base.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
89
+ return s;
90
+ }
91
+ function toCfTitleSlug(slug) {
92
+ return String(slug ?? "").split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("-");
93
+ }
94
+ function buildSearchQueries(name, stripFolderTags = true, maxQueries = 14) {
95
+ const inputs = (Array.isArray(name) ? name : [name]).map((x) => String(x ?? "").trim()).filter(Boolean).map((raw, i) => ({ id: `src${i}`, raw }));
96
+ return buildSearchQueriesFromSources(inputs, stripFolderTags, maxQueries).queries;
97
+ }
98
+ function buildSearchQueriesFromSources(sources, stripFolderTags = true, maxQueries = 14) {
99
+ const cleaned = sources.map((s) => ({ id: s.id, raw: String(s.raw ?? "").trim() })).filter((s) => s.raw);
100
+ const hasCjk = (q) => /[\u3400-\u9fff]/.test(q);
101
+ const hasLatin = (q) => /[A-Za-z]/.test(q);
102
+ const kindRank = (q) => {
103
+ if (/^[a-z0-9]+(?:-[a-z0-9]+)*-addon$/.test(q)) return 0;
104
+ if (/^[a-z0-9]+(?:-[a-z0-9]+)+$/.test(q)) return 1;
105
+ if (/^[A-Z][a-z0-9]*(?:-[A-Z][a-z0-9]*)+$/.test(q)) return 2;
106
+ if (hasCjk(q) && !hasLatin(q)) return 5;
107
+ if (hasCjk(q)) return 4;
108
+ return 3;
109
+ };
110
+ const sortQueries = (list) => [...list].sort((a, b) => {
111
+ const ka = kindRank(a);
112
+ const kb = kindRank(b);
113
+ if (ka !== kb) return ka - kb;
114
+ const ta = a.split(/[\s\-]+/).filter(Boolean).length;
115
+ const tb = b.split(/[\s\-]+/).filter(Boolean).length;
116
+ if (ta !== tb) return ta - tb;
117
+ return a.length - b.length;
118
+ });
119
+ const expandOne = (raw) => {
120
+ const out = [];
121
+ const push = (q) => {
122
+ const t = q.trim();
123
+ if (!t) return;
124
+ if (!out.some((x) => x.toLowerCase() === t.toLowerCase())) out.push(t);
125
+ };
126
+ for (const seed of collectQuerySeeds(raw, stripFolderTags)) {
127
+ push(seed);
128
+ const slug = toCfSlugCandidate(seed, false);
129
+ push(slug);
130
+ if (slug) {
131
+ push(toCfTitleSlug(slug));
132
+ if (!slug.endsWith("-addon")) push(`${slug}-addon`);
133
+ }
134
+ }
135
+ return sortQueries(out);
136
+ };
137
+ const perSource = {};
138
+ const perSourcePreferred = [];
139
+ for (const src of cleaned) {
140
+ const all = expandOne(src.raw);
141
+ const latinish = all.filter((q) => hasLatin(q));
142
+ const preferred = latinish.length > 0 ? latinish : all;
143
+ perSource[src.id] = preferred;
144
+ perSourcePreferred.push(preferred);
145
+ }
146
+ const merged = [];
147
+ const pushMerged = (q) => {
148
+ if (!q) return;
149
+ if (merged.some((x) => x.toLowerCase() === q.toLowerCase())) return;
150
+ merged.push(q);
151
+ };
152
+ const maxLen = Math.max(0, ...perSourcePreferred.map((x) => x.length));
153
+ for (let i = 0; i < maxLen; i++) {
154
+ for (const list of perSourcePreferred) {
155
+ if (i < list.length) pushMerged(list[i]);
156
+ }
157
+ }
158
+ const anyLatin = merged.some((q) => hasLatin(q));
159
+ const filtered = anyLatin ? merged.filter((q) => hasLatin(q)) : merged;
160
+ const queries = sortQueries(filtered).slice(0, Math.max(1, maxQueries));
161
+ return { queries, sources: cleaned, perSource };
162
+ }
163
+ function nameSimilarity(a, b) {
164
+ const na = normalizePackSearchName(a).toLowerCase();
165
+ const nb = normalizePackSearchName(b).toLowerCase();
166
+ if (!na || !nb) return 0;
167
+ if (na === nb) return 1;
168
+ if (na.includes(nb) || nb.includes(na)) return 0.85;
169
+ const ta = new Set(na.split(/[\s_\-]+/).filter(Boolean));
170
+ const tb = new Set(nb.split(/[\s_\-]+/).filter(Boolean));
171
+ if (ta.size === 0 || tb.size === 0) return 0;
172
+ let inter = 0;
173
+ for (const t of ta) if (tb.has(t)) inter++;
174
+ return inter / Math.max(ta.size, tb.size);
175
+ }
176
+ function packSourceScore(query, hit, stripFolderTags = true) {
177
+ const byName = nameSimilarity(query, hit.name);
178
+ const qSlug = toCfSlugCandidate(query, stripFolderTags);
179
+ const hSlug = String(hit.slug ?? "").toLowerCase().replace(/^-+|-+$/g, "");
180
+ let bySlug = 0;
181
+ if (qSlug && hSlug) {
182
+ if (hSlug === qSlug) bySlug = 1;
183
+ else if (hSlug === `${qSlug}-addon` || hSlug.startsWith(`${qSlug}-`)) bySlug = 0.96;
184
+ else if (hSlug.includes(qSlug) || qSlug.includes(hSlug)) bySlug = 0.88;
185
+ else bySlug = nameSimilarity(qSlug.replace(/-/g, " "), hSlug.replace(/-/g, " "));
186
+ }
187
+ return Math.max(byName, bySlug);
188
+ }
189
+ export {
190
+ buildSearchQueries,
191
+ buildSearchQueriesFromSources,
192
+ bumpSemVer3,
193
+ collectQuerySeeds,
194
+ compareSemVer3,
195
+ decideVersionPolicy,
196
+ extractLatinPhrase,
197
+ insertCjkLatinBoundaries,
198
+ isNewer,
199
+ maxSemVer3,
200
+ nameSimilarity,
201
+ nextEnabledVersion,
202
+ normalizePackSearchName,
203
+ packSourceScore,
204
+ preprocessPackNameRaw,
205
+ stripPackRoleTokens,
206
+ stripVersionTokens,
207
+ toCfSlugCandidate,
208
+ toCfTitleSlug
209
+ };
210
+ //# sourceMappingURL=version-policy.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/pack-update/version-policy.ts"],
4
+ "sourcesContent": ["/**\n * \u7248\u672C\u7B56\u7565\uFF1A\u4EE5 BP \u4E3A\u51C6\u6BD4\u8F83\uFF1B\u540C major \u66F4\u65B0\u65F6\u62AC\u9AD8 RP \u7248\u672C\u89E6\u53D1\u5BA2\u6237\u7AEF\u5237\u65B0\n */\nimport {\n bumpSemVer3,\n compareSemVer3 as compareSemVer3Raw,\n maxSemVer3,\n nextEnabledVersion,\n} from \"../world-packs.js\";\nimport type { SemVer3, VersionCompareResult, VersionPolicyConfig } from \"./types.js\";\n\n/** \u5F52\u4E00\u5316\u4E3A -1 | 0 | 1\uFF0C\u4F9B\u7B56\u7565\u6BD4\u8F83 */\nexport function compareSemVer3(a: SemVer3, b: SemVer3): number {\n const d = compareSemVer3Raw(a, b);\n return d > 0 ? 1 : d < 0 ? -1 : 0;\n}\n\nexport function isNewer(remote: SemVer3, local: SemVer3): boolean {\n return compareSemVer3(remote, local) > 0;\n}\n\nexport { bumpSemVer3, maxSemVer3, nextEnabledVersion };\n\n/**\n * \u6839\u636E\u672C\u5730/\u8FDC\u7A0B BP \u7248\u672C\u4E0E\u7B56\u7565\uFF0C\u51B3\u5B9A\u662F\u5426\u66F4\u65B0\u4EE5\u53CA\u662F\u5426\u989D\u5916 bump RP\u3002\n * `treatAsUpdate`\uFF1A\u540C\u7248\u672C/\u672A\u66F4\u9AD8\u4F46\u9700\u5F3A\u5236\u540C\u6B65\u5199\u5165\u65F6\uFF08\u5982 fileId \u5C1A\u672A apply\uFF09\u4E5F\u8D70\u66F4\u65B0\u4FA7 RP bump \u89C4\u5219\uFF08OCP\uFF1A\u7B56\u7565\u96C6\u4E2D\u4E8E\u6B64\uFF0C\u52FF\u5728\u7F16\u6392\u5C42\u590D\u523B\uFF09\u3002\n */\nexport function decideVersionPolicy(\n localBp: SemVer3,\n remoteBp: SemVer3,\n policy: VersionPolicyConfig,\n opts?: { treatAsUpdate?: boolean }\n): VersionCompareResult {\n const remoteNewer = isNewer(remoteBp, localBp);\n const majorHigher = remoteBp[0] > localBp[0];\n const asUpdate = remoteNewer || Boolean(opts?.treatAsUpdate);\n let shouldBumpRp = false;\n if (asUpdate && policy.onUpdateOverwriteBoth) {\n if (majorHigher && policy.majorHigherSkipRpBump) {\n shouldBumpRp = false;\n } else if (policy.rpBumpWhenSameMajor) {\n shouldBumpRp = true;\n }\n }\n return { remoteNewer, majorHigher, shouldBumpRp };\n}\n\n/** \u5305\u7C7B\u578B/\u6E20\u9053\u7B49\u566A\u97F3 token\uFF08\u6574\u8BCD\u53BB\u6389\uFF0C\u52FF\u5220\u4EA7\u54C1\u540D\uFF09 */\nconst PACK_ROLE_TOKEN =\n /^(?:bp|rp|ba|behavior|behaviours?|resource|resources|pack|packs|addon|addons|mcpack|mcaddon|behavior.?pack|resource.?pack|\u884C\u4E3A\u5305|\u8D44\u6E90\u5305|\u9644\u52A0\u5305|\u57FA\u5CA9|bedrock)$/iu;\n\n/** \u4E2D\u65E5\u97E9\u4E0E\u62C9\u4E01\u7C98\u8FDE\u65F6\u63D2\u5165\u7A7A\u683C\uFF1A\u62D4\u5200\u5251Slash \u2192 \u62D4\u5200\u5251 Slash */\nexport function insertCjkLatinBoundaries(name: string): string {\n return String(name ?? \"\")\n .replace(/([\\u3400-\\u9fff\\uF900-\\uFAFF])([A-Za-z])/g, \"$1 $2\")\n .replace(/([A-Za-z])([\\u3400-\\u9fff\\uF900-\\uFAFF])/g, \"$1 $2\");\n}\n\n/** \u53BB\u6389\u6574\u8BCD\u5305\u89D2\u8272\u6807\u8BB0\uFF08\u672B\u5C3E BP/RP/Addon \u7B49\uFF09 */\nexport function stripPackRoleTokens(name: string): string {\n return String(name ?? \"\")\n .split(/[\\s_]+/)\n .filter((t) => t && !PACK_ROLE_TOKEN.test(t))\n .join(\" \")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** \u53BB\u6389 v4 / 1.21.100 \u4E00\u7C7B\u7248\u672C\u5C3E\u5DF4 */\nexport function stripVersionTokens(name: string): string {\n return String(name ?? \"\")\n .replace(/\\bv\\d+(?:\\.\\d+)*\\b/gi, \" \")\n .replace(/\\b\\d+\\.\\d+(?:\\.\\d+)?\\b/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** \u4EC5\u4FDD\u7559\u62C9\u4E01\u8BCD\uFF08CF slug/search \u4E3B\u8DEF\u5F84\uFF09 */\nexport function extractLatinPhrase(name: string): string {\n const words = String(name ?? \"\").match(/[A-Za-z][A-Za-z0-9]*/g);\n return words ? words.join(\" \") : \"\";\n}\n\n/**\n * \u5171\u4EAB\u9884\u5904\u7406\uFF1A\u00A7\u7801\u3001\u65B9\u62EC\u53F7\u6807\u7B7E\u3001\u6269\u5C55\u540D\u3001CJK/\u62C9\u4E01\u5206\u754C\u3001\u4E0B\u5212\u7EBF\u2192\u7A7A\u683C\u3002\n * normalize / collectQuerySeeds \u5171\u7528\uFF0C\u907F\u514D\u4E24\u5904\u5404\u5199\u4E00\u904D\uFF08DRY\uFF09\u3002\n */\nexport function preprocessPackNameRaw(name: string, stripFolderTags = true): string {\n let s = String(name ?? \"\");\n s = s.replace(/\u00A7[0-9a-zA-Z]/g, \"\");\n if (stripFolderTags) {\n s = s.replace(/\\[[^\\]]*]/g, \" \");\n }\n s = s.replace(/\\.(zip|mcpack|mcaddon)$/i, \"\");\n s = insertCjkLatinBoundaries(s);\n s = s.replace(/[_]+/g, \" \").replace(/\\s+/g, \" \").trim();\n return s;\n}\n\n/**\n * \u57FA\u7840\u6E05\u6D17\uFF1A\u9884\u5904\u7406 + \u5305\u89D2\u8272 + \u7248\u672C\u53F7\u3002\n * \u4F8B\uFF1A\"[BP] [BA] [\u73A9\u6CD5] \u62D4\u5200\u5251Slash Blade v4 BP\" \u2192 \"\u62D4\u5200\u5251 Slash Blade\"\n */\nexport function normalizePackSearchName(name: string, stripFolderTags = true): string {\n let s = preprocessPackNameRaw(name, stripFolderTags);\n s = stripPackRoleTokens(s);\n s = stripVersionTokens(s);\n return s;\n}\n\n/**\n * \u4ECE\u539F\u59CB\u6587\u4EF6\u5939\u540D/\u5C55\u793A\u540D\u6536\u96C6\u591A\u7EA7\u6E05\u6D17\u79CD\u5B50\uFF08\u7531\u810F\u5230\u51C0\uFF09\u3002\n * \u4F8B\uFF1A\"[BP] [BA] [\u73A9\u6CD5] \u62D4\u5200\u5251Slash Blade v4 BP\"\n * \u2192 \u62D4\u5200\u5251 Slash Blade v4 BP \u2192 Slash Blade v4 BP \u2192 Slash Blade v4 \u2192 Slash Blade\n */\nexport function collectQuerySeeds(raw: string, stripFolderTags = true): string[] {\n const seeds: string[] = [];\n const push = (q: string): void => {\n const t = q.replace(/\\s+/g, \" \").trim();\n if (!t) return;\n if (!seeds.some((x) => x.toLowerCase() === t.toLowerCase())) seeds.push(t);\n };\n\n const s = preprocessPackNameRaw(raw, stripFolderTags);\n push(s);\n\n const noRole = stripPackRoleTokens(s);\n push(noRole);\n push(stripVersionTokens(s));\n push(stripVersionTokens(noRole));\n\n const latin = extractLatinPhrase(s);\n push(latin);\n const latinNoRole = stripPackRoleTokens(latin);\n push(latinNoRole);\n const latinCore = stripVersionTokens(latinNoRole);\n push(latinCore);\n\n /* \u62C9\u4E01\u6838\u5FC3\u518D\u9010\u7EA7\u7F29\u77ED\uFF0C\u81F3\u5C11\u4FDD\u7559 2 \u4E2A\u8BCD\uFF08\u907F\u514D\u5355\u72EC\u641C Blade \u8FC7\u6CDB\uFF09 */\n let tokens = latinCore.split(/\\s+/).filter(Boolean);\n while (tokens.length >= 2) {\n push(tokens.join(\" \"));\n tokens = tokens.slice(0, -1);\n }\n\n push(normalizePackSearchName(raw, stripFolderTags));\n return seeds;\n}\n\n/**\n * \u4ECE\u5C55\u793A\u540D\u63A8\u5BFC CF slug \u5019\u9009\uFF08\u65E0\u7A7A\u683C\u3001\u5C0F\u5199\u3001\u8FDE\u5B57\u7B26\uFF09\u3002\n * \u4F8B\uFF1A\"Slash Blade v4 BP\" \u2192 \"slash-blade\"\n */\nexport function toCfSlugCandidate(name: string, stripFolderTags = true): string {\n const base = normalizePackSearchName(name, stripFolderTags);\n /* slug \u4FA7\u51E0\u4E4E\u603B\u662F\u62C9\u4E01\u7247\u6BB5\uFF1B\u4FDD\u7559\u5B57\u6BCD\u6570\u5B57\uFF0C\u5176\u4F59\u53D8\u8FDE\u5B57\u7B26 */\n let s = base\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-+/g, \"-\");\n return s;\n}\n\n/** Title-Case \u8FDE\u5B57\u7B26\uFF1Aslash-blade \u2192 Slash-Blade\uFF08\u90E8\u5206 CF \u641C\u7D22\u66F4\u5403\u8FD9\u4E2A\uFF09 */\nexport function toCfTitleSlug(slug: string): string {\n return String(slug ?? \"\")\n .split(\"-\")\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join(\"-\");\n}\n\n/**\n * \u6D3E\u751F\u4E00\u7EC4\u641C\u7D22\u8BCD\uFF1A\u591A\u6E90\u8F93\u5165 \u00D7 \u591A\u7EA7\u6E05\u6D17\u79CD\u5B50 \u00D7\uFF08\u5C55\u793A\u540D / slug / Title-Slug / slug-addon\uFF09\u3002\n * `name` \u53EF\u4E3A\u5B57\u7B26\u4E32\u6216\u6570\u7EC4\uFF08\u5982 header.name + \u6587\u4EF6\u5939\u540D\uFF09\u3002\n *\n * \u89C4\u5219\uFF1A\u53EA\u8981\u5B58\u5728\u542B\u62C9\u4E01\u5B57\u6BCD\u7684\u5019\u9009\uFF0C\u5C31**\u4E22\u5F03\u7EAF CJK \u67E5\u8BE2**\uFF08CF Bedrock \u51E0\u4E4E\u4E0D\u9760\u4E2D\u6587\u641C\uFF09\u3002\n */\nexport function buildSearchQueries(\n name: string | readonly string[],\n stripFolderTags = true,\n maxQueries = 14\n): string[] {\n const inputs = (Array.isArray(name) ? name : [name])\n .map((x) => String(x ?? \"\").trim())\n .filter(Boolean)\n .map((raw, i) => ({ id: `src${i}`, raw }));\n return buildSearchQueriesFromSources(inputs, stripFolderTags, maxQueries).queries;\n}\n\nexport type SearchQuerySource = { id: string; raw: string };\n\nexport type SearchQueryPlan = {\n /** \u6700\u7EC8\u53D1\u7ED9 CF \u7684\u67E5\u8BE2\uFF08\u5DF2\u53BB\u91CD\u3001\u6392\u5E8F\u3001\u622A\u65AD\uFF09 */\n queries: string[];\n /** \u5404\u6E90\u539F\u59CB\u8F93\u5165\uFF08\u4FBF\u4E8E\u65E5\u5FD7\uFF09 */\n sources: SearchQuerySource[];\n /** \u6BCF\u6E90\u8D21\u732E\u4E86\u54EA\u4E9B\u8BCD\uFF08\u622A\u65AD\u524D\uFF0C\u4FBF\u4E8E\u786E\u8BA4\u53CC\u6E90\u90FD\u53C2\u4E0E\uFF09 */\n perSource: Record<string, string[]>;\n};\n\n/**\n * \u6309\u6E90\u5206\u522B\u6D3E\u751F\uFF0C\u518D\u5408\u5E76\uFF1A\u4FDD\u8BC1 header / \u6587\u4EF6\u5939\u540D\u90FD\u4F1A\u8D21\u732E\u5019\u9009\uFF0C\u800C\u975E\u6DF7\u6210\u4E00\u9505\u88AB\u622A\u65AD\u504F\u79D1\u3002\n */\nexport function buildSearchQueriesFromSources(\n sources: readonly SearchQuerySource[],\n stripFolderTags = true,\n maxQueries = 14\n): SearchQueryPlan {\n const cleaned = sources\n .map((s) => ({ id: s.id, raw: String(s.raw ?? \"\").trim() }))\n .filter((s) => s.raw);\n\n const hasCjk = (q: string): boolean => /[\\u3400-\\u9fff]/.test(q);\n const hasLatin = (q: string): boolean => /[A-Za-z]/.test(q);\n const kindRank = (q: string): number => {\n if (/^[a-z0-9]+(?:-[a-z0-9]+)*-addon$/.test(q)) return 0;\n if (/^[a-z0-9]+(?:-[a-z0-9]+)+$/.test(q)) return 1;\n if (/^[A-Z][a-z0-9]*(?:-[A-Z][a-z0-9]*)+$/.test(q)) return 2;\n if (hasCjk(q) && !hasLatin(q)) return 5;\n if (hasCjk(q)) return 4;\n return 3;\n };\n const sortQueries = (list: string[]): string[] =>\n [...list].sort((a, b) => {\n const ka = kindRank(a);\n const kb = kindRank(b);\n if (ka !== kb) return ka - kb;\n const ta = a.split(/[\\s\\-]+/).filter(Boolean).length;\n const tb = b.split(/[\\s\\-]+/).filter(Boolean).length;\n if (ta !== tb) return ta - tb;\n return a.length - b.length;\n });\n\n const expandOne = (raw: string): string[] => {\n const out: string[] = [];\n const push = (q: string): void => {\n const t = q.trim();\n if (!t) return;\n if (!out.some((x) => x.toLowerCase() === t.toLowerCase())) out.push(t);\n };\n for (const seed of collectQuerySeeds(raw, stripFolderTags)) {\n push(seed);\n const slug = toCfSlugCandidate(seed, false);\n push(slug);\n if (slug) {\n push(toCfTitleSlug(slug));\n if (!slug.endsWith(\"-addon\")) push(`${slug}-addon`);\n }\n }\n return sortQueries(out);\n };\n\n const perSource: Record<string, string[]> = {};\n const perSourcePreferred: string[][] = [];\n for (const src of cleaned) {\n const all = expandOne(src.raw);\n /* \u5355\u6E90\u5185\uFF1A\u6709\u62C9\u4E01\u5219\u4E22\u6389\u7EAF\u4E2D\u6587 */\n const latinish = all.filter((q) => hasLatin(q));\n const preferred = latinish.length > 0 ? latinish : all;\n perSource[src.id] = preferred;\n perSourcePreferred.push(preferred);\n }\n\n /* \u8F6E\u8BE2\u5408\u5E76\u5404\u6E90\uFF0C\u907F\u514D\u67D0\u4E00\u6E90\u5360\u6EE1\u914D\u989D\u5BFC\u81F4\u53E6\u4E00\u6E90\u5B8C\u5168\u6CA1\u641C */\n const merged: string[] = [];\n const pushMerged = (q: string): void => {\n if (!q) return;\n if (merged.some((x) => x.toLowerCase() === q.toLowerCase())) return;\n merged.push(q);\n };\n const maxLen = Math.max(0, ...perSourcePreferred.map((x) => x.length));\n for (let i = 0; i < maxLen; i++) {\n for (const list of perSourcePreferred) {\n if (i < list.length) pushMerged(list[i]!);\n }\n }\n\n /* \u5168\u5C40\u518D\u6EE4\u4E00\u6B21\uFF1A\u6574\u4F53\u5DF2\u6709\u62C9\u4E01\u65F6\uFF0C\u4E22\u6389\u6DF7\u8FDB\u6765\u7684\u7EAF CJK */\n const anyLatin = merged.some((q) => hasLatin(q));\n const filtered = anyLatin ? merged.filter((q) => hasLatin(q)) : merged;\n const queries = sortQueries(filtered).slice(0, Math.max(1, maxQueries));\n\n return { queries, sources: cleaned, perSource };\n}\n\n/** \u7B80\u5355\u76F8\u4F3C\u5EA6\uFF1A0~1\uFF08\u57FA\u4E8E\u5171\u540C token \u4E0E\u5305\u542B\u5173\u7CFB\uFF09 */\nexport function nameSimilarity(a: string, b: string): number {\n const na = normalizePackSearchName(a).toLowerCase();\n const nb = normalizePackSearchName(b).toLowerCase();\n if (!na || !nb) return 0;\n if (na === nb) return 1;\n if (na.includes(nb) || nb.includes(na)) return 0.85;\n const ta = new Set(na.split(/[\\s_\\-]+/).filter(Boolean));\n const tb = new Set(nb.split(/[\\s_\\-]+/).filter(Boolean));\n if (ta.size === 0 || tb.size === 0) return 0;\n let inter = 0;\n for (const t of ta) if (tb.has(t)) inter++;\n return inter / Math.max(ta.size, tb.size);\n}\n\n/**\n * \u7EFC\u5408\u5C55\u793A\u540D + CF slug \u6253\u5206\u3002\n * slug \u65E0\u7A7A\u683C\uFF08slash-blade-addon\uFF09\uFF0C\u4E0E\u672C\u5730\u300CSlash Blade v4\u300D\u5BF9\u9F50\u65F6\u6743\u91CD\u5927\u4E8E\u7EAF name\u3002\n */\nexport function packSourceScore(\n query: string,\n hit: { name: string; slug: string },\n stripFolderTags = true\n): number {\n const byName = nameSimilarity(query, hit.name);\n const qSlug = toCfSlugCandidate(query, stripFolderTags);\n const hSlug = String(hit.slug ?? \"\")\n .toLowerCase()\n .replace(/^-+|-+$/g, \"\");\n let bySlug = 0;\n if (qSlug && hSlug) {\n if (hSlug === qSlug) bySlug = 1;\n else if (hSlug === `${qSlug}-addon` || hSlug.startsWith(`${qSlug}-`)) bySlug = 0.96;\n else if (hSlug.includes(qSlug) || qSlug.includes(hSlug)) bySlug = 0.88;\n else bySlug = nameSimilarity(qSlug.replace(/-/g, \" \"), hSlug.replace(/-/g, \" \"));\n }\n return Math.max(byName, bySlug);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/paths.d.ts CHANGED
@@ -28,6 +28,6 @@ export interface BdsPaths {
28
28
  cfg: BdsUpdaterConfig;
29
29
  }
30
30
  export declare function resolvePaths(cfg: BdsUpdaterConfig): BdsPaths;
31
- /** 删除 PID 文件 */
31
+ /** 删除 PID 文件(委托 process-probe,与 bds-manager / sfmc 共用) */
32
32
  export declare function clearPid(): void;
33
33
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAOL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAOnC,wCAAwC;AACxC,eAAO,MAAM,QAAQ,EAAE,MAAiE,CAAC;AACzF,eAAO,MAAM,QAAQ,EAAE,MAAiD,CAAC;AAEzE,sCAAsC;AACtC,eAAO,MAAM,SAAS,EAAE,MAA2B,CAAC;AACpD,eAAO,MAAM,QAAQ,EAAE,MAAwC,CAAC;AAChE,eAAO,MAAM,aAAa,EAAE,MAAuD,CAAC;AACpF,eAAO,MAAM,QAAQ,EAAE,MAAwC,CAAC;AAChE,qBAAqB;AACrB,eAAO,MAAM,eAAe,EAAE,MAA0D,CAAC;AAEzF,kDAAkD;AAClD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED;yEACyE;AACzE,wBAAgB,UAAU,IAAI,gBAAgB,CAO7C;AAED,yBAAyB;AACzB,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,gBAAgB,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,QAAQ,CAS5D;AAED,gBAAgB;AAChB,wBAAgB,QAAQ,IAAI,IAAI,CAM/B"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAOL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAQnC,wCAAwC;AACxC,eAAO,MAAM,QAAQ,EAAE,MAAuC,CAAC;AAC/D,eAAO,MAAM,QAAQ,EAAE,MAAiD,CAAC;AAEzE,sCAAsC;AACtC,eAAO,MAAM,SAAS,EAAE,MAA2B,CAAC;AACpD,eAAO,MAAM,QAAQ,EAAE,MAAwC,CAAC;AAChE,eAAO,MAAM,aAAa,EAAE,MAAuD,CAAC;AACpF,eAAO,MAAM,QAAQ,EAAE,MAAwC,CAAC;AAChE,qBAAqB;AACrB,eAAO,MAAM,eAAe,EAAE,MAA0D,CAAC;AAEzF,kDAAkD;AAClD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED;yEACyE;AACzE,wBAAgB,UAAU,IAAI,gBAAgB,CAO7C;AAED,yBAAyB;AACzB,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,gBAAgB,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,QAAQ,CAS5D;AAED,0DAA0D;AAC1D,wBAAgB,QAAQ,IAAI,IAAI,CAE/B"}
package/dist/paths.js CHANGED
@@ -9,9 +9,10 @@ import {
9
9
  import fs from "node:fs";
10
10
  import path from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
+ import { clearBdsPidFile } from "./process-probe.js";
12
13
  const __filename = fileURLToPath(import.meta.url);
13
14
  const SCRIPT_DIR = path.dirname(__filename);
14
- const ROOT_DIR = resolveRuntimeRoot(path.resolve(SCRIPT_DIR, "..", ".."));
15
+ const ROOT_DIR = resolveRuntimeRoot(SCRIPT_DIR);
15
16
  const CFG_PATH = configPath(ROOT_DIR, "bds_updater.json");
16
17
  const STATE_DIR = stateDir(ROOT_DIR);
17
18
  const LOG_PATH = logFile(ROOT_DIR, "bds-update");
@@ -40,10 +41,7 @@ function resolvePaths(cfg) {
40
41
  return { bds_path, backup_dir, preserve, cfg };
41
42
  }
42
43
  function clearPid() {
43
- try {
44
- if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
45
- } catch {
46
- }
44
+ clearBdsPidFile(ROOT_DIR);
47
45
  }
48
46
  export {
49
47
  CFG_PATH,
package/dist/paths.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/paths.ts"],
4
- "sourcesContent": ["/**\n * paths.ts \u2014 \u8DEF\u5F84\u5E38\u91CF & \u52A0\u8F7D bds_updater.json\n *\n * ROOT_DIR = \u9879\u76EE/\u6570\u636E\u6839,\u901A\u8FC7 SDK \u7EDF\u4E00\u89E3\u6790(env SFMC_ROOT > __dirname \u4E0A\u6EAF)\u3002\n * STATE_DIR / LOG_PATH \u7B49\u8FD0\u884C\u6001\u8DEF\u5F84\u4E00\u5F8B\u8D70 SDK stateDir / logFile,\u52FF\u518D\u624B\u5199 \".sfmc\"\u3002\n */\n\nimport {\n configPath,\n DEFAULT_BDS_UPDATER_CONFIG,\n loadEnsuredConfig,\n logFile,\n resolveRuntimeRoot,\n stateDir,\n type BdsUpdaterConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst SCRIPT_DIR: string = path.dirname(__filename);\n/** \u9879\u76EE\u6839\u76EE\u5F55:bds-tools \u7684\u4E0A\u4E00\u7EA7\u3002\u7EDF\u4E00\u901A\u8FC7 SDK \u89E3\u6790\u3002 */\nexport const ROOT_DIR: string = resolveRuntimeRoot(path.resolve(SCRIPT_DIR, \"..\", \"..\"));\nexport const CFG_PATH: string = configPath(ROOT_DIR, \"bds_updater.json\");\n\n/** \u8FD0\u884C\u6001\u76EE\u5F55(\u76F8\u5BF9\u6570\u636E\u6839\uFF0C\u52FF\u843D\u5728 bds-tools/dist) */\nexport const STATE_DIR: string = stateDir(ROOT_DIR);\nexport const LOG_PATH: string = logFile(ROOT_DIR, \"bds-update\");\nexport const VERSION_CACHE: string = path.join(STATE_DIR, \"bds-version-cache.json\");\nexport const PID_FILE: string = path.join(STATE_DIR, \"bds.pid\");\n/** \u66F4\u65B0\u4E2D\u9014\u5931\u8D25\u53EF\u6062\u590D\u7684\u56DE\u6EDA\u6807\u8BB0 */\nexport const ROLLBACK_MARKER: string = path.join(STATE_DIR, \"last_update_rollback.json\");\n\n/** \u786E\u4FDD .sfmc \u8FD0\u884C\u6001\u76EE\u5F55\u5B58\u5728(PID \u5199\u5165\u7B49\u4E0D\u7ECF writeJson \u7684\u8DEF\u5F84\u9700\u8981) */\nexport function ensureStateDir(): void {\n fs.mkdirSync(STATE_DIR, { recursive: true });\n}\n\n/** \u52A0\u8F7D\u5E76\u89E3\u6790 bds_updater.json\u3002\n * \u542F\u52A8\u65F6 ensure \u6587\u4EF6\u5B58\u5728,\u907F\u514D wizard \u6CA1\u8DD1\u65F6 bds_updater.json \u7F3A\u5931\u5BFC\u81F4 loadConfig \u629B\u9519\u3002 */\nexport function loadConfig(): BdsUpdaterConfig {\n return loadEnsuredConfig(\n ROOT_DIR,\n \"bds_updater.json\",\n \"bds_updater\",\n { ...DEFAULT_BDS_UPDATER_CONFIG } as Record<string, unknown>\n ) as BdsUpdaterConfig;\n}\n\n/** \u89E3\u6790\u540E\u7684 BDS \u8DEF\u5F84 / \u5907\u4EFD\u76EE\u5F55 */\nexport interface BdsPaths {\n bds_path: string;\n backup_dir: string;\n preserve: string[];\n cfg: BdsUpdaterConfig;\n}\n\nexport function resolvePaths(cfg: BdsUpdaterConfig): BdsPaths {\n const bds_path = path.resolve(cfg.bds_path || process.cwd());\n const backup_dir = path.resolve(cfg.backup_dir || path.join(bds_path, \"..\", \"backups\"));\n const relativeBackup = path.relative(bds_path, backup_dir);\n if (relativeBackup === \"\" || (!relativeBackup.startsWith(\"..\") && !path.isAbsolute(relativeBackup))) {\n throw new Error(\"backup_dir must be outside bds_path so deployment cannot delete the backup\");\n }\n const preserve = Array.isArray(cfg.preserve) ? cfg.preserve : [];\n return { bds_path, backup_dir, preserve, cfg };\n}\n\n/** \u5220\u9664 PID \u6587\u4EF6 */\nexport function clearPid(): void {\n try {\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n } catch {\n /* ignore */\n }\n}\n"],
5
- "mappings": "AAOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,aAAqB,KAAK,QAAQ,UAAU;AAE3C,MAAM,WAAmB,mBAAmB,KAAK,QAAQ,YAAY,MAAM,IAAI,CAAC;AAChF,MAAM,WAAmB,WAAW,UAAU,kBAAkB;AAGhE,MAAM,YAAoB,SAAS,QAAQ;AAC3C,MAAM,WAAmB,QAAQ,UAAU,YAAY;AACvD,MAAM,gBAAwB,KAAK,KAAK,WAAW,wBAAwB;AAC3E,MAAM,WAAmB,KAAK,KAAK,WAAW,SAAS;AAEvD,MAAM,kBAA0B,KAAK,KAAK,WAAW,2BAA2B;AAGhF,SAAS,iBAAuB;AACrC,KAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C;AAIO,SAAS,aAA+B;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,GAAG,2BAA2B;AAAA,EAClC;AACF;AAUO,SAAS,aAAa,KAAiC;AAC5D,QAAM,WAAW,KAAK,QAAQ,IAAI,YAAY,QAAQ,IAAI,CAAC;AAC3D,QAAM,aAAa,KAAK,QAAQ,IAAI,cAAc,KAAK,KAAK,UAAU,MAAM,SAAS,CAAC;AACtF,QAAM,iBAAiB,KAAK,SAAS,UAAU,UAAU;AACzD,MAAI,mBAAmB,MAAO,CAAC,eAAe,WAAW,IAAI,KAAK,CAAC,KAAK,WAAW,cAAc,GAAI;AACnG,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AACA,QAAM,WAAW,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC;AAC/D,SAAO,EAAE,UAAU,YAAY,UAAU,IAAI;AAC/C;AAGO,SAAS,WAAiB;AAC/B,MAAI;AACF,QAAI,GAAG,WAAW,QAAQ,EAAG,IAAG,WAAW,QAAQ;AAAA,EACrD,QAAQ;AAAA,EAER;AACF;",
4
+ "sourcesContent": ["/**\n * paths.ts \u2014 \u8DEF\u5F84\u5E38\u91CF & \u52A0\u8F7D bds_updater.json\n *\n * ROOT_DIR = \u9879\u76EE/\u6570\u636E\u6839,\u901A\u8FC7 SDK \u7EDF\u4E00\u89E3\u6790(env SFMC_ROOT > __dirname \u4E0A\u6EAF)\u3002\n * STATE_DIR / LOG_PATH \u7B49\u8FD0\u884C\u6001\u8DEF\u5F84\u4E00\u5F8B\u8D70 SDK stateDir / logFile,\u52FF\u518D\u624B\u5199 \".sfmc\"\u3002\n */\n\nimport {\n configPath,\n DEFAULT_BDS_UPDATER_CONFIG,\n loadEnsuredConfig,\n logFile,\n resolveRuntimeRoot,\n stateDir,\n type BdsUpdaterConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { clearBdsPidFile } from \"./process-probe.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst SCRIPT_DIR: string = path.dirname(__filename);\n/** \u9879\u76EE\u6839\u76EE\u5F55:bds-tools \u7684\u4E0A\u4E00\u7EA7\u3002\u7EDF\u4E00\u901A\u8FC7 SDK \u89E3\u6790\u3002 */\nexport const ROOT_DIR: string = resolveRuntimeRoot(SCRIPT_DIR);\nexport const CFG_PATH: string = configPath(ROOT_DIR, \"bds_updater.json\");\n\n/** \u8FD0\u884C\u6001\u76EE\u5F55(\u76F8\u5BF9\u6570\u636E\u6839\uFF0C\u52FF\u843D\u5728 bds-tools/dist) */\nexport const STATE_DIR: string = stateDir(ROOT_DIR);\nexport const LOG_PATH: string = logFile(ROOT_DIR, \"bds-update\");\nexport const VERSION_CACHE: string = path.join(STATE_DIR, \"bds-version-cache.json\");\nexport const PID_FILE: string = path.join(STATE_DIR, \"bds.pid\");\n/** \u66F4\u65B0\u4E2D\u9014\u5931\u8D25\u53EF\u6062\u590D\u7684\u56DE\u6EDA\u6807\u8BB0 */\nexport const ROLLBACK_MARKER: string = path.join(STATE_DIR, \"last_update_rollback.json\");\n\n/** \u786E\u4FDD .sfmc \u8FD0\u884C\u6001\u76EE\u5F55\u5B58\u5728(PID \u5199\u5165\u7B49\u4E0D\u7ECF writeJson \u7684\u8DEF\u5F84\u9700\u8981) */\nexport function ensureStateDir(): void {\n fs.mkdirSync(STATE_DIR, { recursive: true });\n}\n\n/** \u52A0\u8F7D\u5E76\u89E3\u6790 bds_updater.json\u3002\n * \u542F\u52A8\u65F6 ensure \u6587\u4EF6\u5B58\u5728,\u907F\u514D wizard \u6CA1\u8DD1\u65F6 bds_updater.json \u7F3A\u5931\u5BFC\u81F4 loadConfig \u629B\u9519\u3002 */\nexport function loadConfig(): BdsUpdaterConfig {\n return loadEnsuredConfig(\n ROOT_DIR,\n \"bds_updater.json\",\n \"bds_updater\",\n { ...DEFAULT_BDS_UPDATER_CONFIG } as Record<string, unknown>\n ) as BdsUpdaterConfig;\n}\n\n/** \u89E3\u6790\u540E\u7684 BDS \u8DEF\u5F84 / \u5907\u4EFD\u76EE\u5F55 */\nexport interface BdsPaths {\n bds_path: string;\n backup_dir: string;\n preserve: string[];\n cfg: BdsUpdaterConfig;\n}\n\nexport function resolvePaths(cfg: BdsUpdaterConfig): BdsPaths {\n const bds_path = path.resolve(cfg.bds_path || process.cwd());\n const backup_dir = path.resolve(cfg.backup_dir || path.join(bds_path, \"..\", \"backups\"));\n const relativeBackup = path.relative(bds_path, backup_dir);\n if (relativeBackup === \"\" || (!relativeBackup.startsWith(\"..\") && !path.isAbsolute(relativeBackup))) {\n throw new Error(\"backup_dir must be outside bds_path so deployment cannot delete the backup\");\n }\n const preserve = Array.isArray(cfg.preserve) ? cfg.preserve : [];\n return { bds_path, backup_dir, preserve, cfg };\n}\n\n/** \u5220\u9664 PID \u6587\u4EF6\uFF08\u59D4\u6258 process-probe\uFF0C\u4E0E bds-manager / sfmc \u5171\u7528\uFF09 */\nexport function clearPid(): void {\n clearBdsPidFile(ROOT_DIR);\n}\n"],
5
+ "mappings": "AAOA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAEhC,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,aAAqB,KAAK,QAAQ,UAAU;AAE3C,MAAM,WAAmB,mBAAmB,UAAU;AACtD,MAAM,WAAmB,WAAW,UAAU,kBAAkB;AAGhE,MAAM,YAAoB,SAAS,QAAQ;AAC3C,MAAM,WAAmB,QAAQ,UAAU,YAAY;AACvD,MAAM,gBAAwB,KAAK,KAAK,WAAW,wBAAwB;AAC3E,MAAM,WAAmB,KAAK,KAAK,WAAW,SAAS;AAEvD,MAAM,kBAA0B,KAAK,KAAK,WAAW,2BAA2B;AAGhF,SAAS,iBAAuB;AACrC,KAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C;AAIO,SAAS,aAA+B;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,GAAG,2BAA2B;AAAA,EAClC;AACF;AAUO,SAAS,aAAa,KAAiC;AAC5D,QAAM,WAAW,KAAK,QAAQ,IAAI,YAAY,QAAQ,IAAI,CAAC;AAC3D,QAAM,aAAa,KAAK,QAAQ,IAAI,cAAc,KAAK,KAAK,UAAU,MAAM,SAAS,CAAC;AACtF,QAAM,iBAAiB,KAAK,SAAS,UAAU,UAAU;AACzD,MAAI,mBAAmB,MAAO,CAAC,eAAe,WAAW,IAAI,KAAK,CAAC,KAAK,WAAW,cAAc,GAAI;AACnG,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AACA,QAAM,WAAW,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC;AAC/D,SAAO,EAAE,UAAU,YAAY,UAAU,IAAI;AAC/C;AAGO,SAAS,WAAiB;AAC/B,kBAAgB,QAAQ;AAC1B;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * process-probe.ts — OS 级 BDS 进程探测与 PID 文件管理
3
+ *
4
+ * 供 bds-manager / sfmc 共用,避免重复 tasklist / taskkill 逻辑。
5
+ */
6
+ export type ExecFn = (cmd: string, opts?: {
7
+ windowsHide?: boolean;
8
+ }) => Promise<{
9
+ stdout: string;
10
+ stderr: string;
11
+ }>;
12
+ /** 测试注入 exec,传 null 恢复默认 */
13
+ export declare function setExecForTesting(fn: ExecFn | null): void;
14
+ export declare function readBdsPidFile(rootDir?: string): number;
15
+ export declare function writeBdsPidFile(pid: number, rootDir?: string): void;
16
+ export declare function clearBdsPidFile(rootDir?: string): void;
17
+ /** 测试注入探活,传 null 恢复默认(避免 Linux 上 process.kill 碰到真实 PID) */
18
+ export declare function setIsAliveForTesting(fn: ((pid: number) => boolean) | null): void;
19
+ export declare function isProcessAlive(pid: number): Promise<boolean>;
20
+ /** 同步探活(供 sync 的 sendCommand 等路径;避免 Promise 被当 truthy) */
21
+ export declare function isProcessAliveSync(pid: number): boolean;
22
+ export declare function findBedrockServerPids(): Promise<number[]>;
23
+ export declare function killBedrockServerByImage(): Promise<void>;
24
+ export type BdsProbeState = "stopped" | "managed" | "external";
25
+ export interface BdsProbeResult {
26
+ state: BdsProbeState;
27
+ pid: number;
28
+ }
29
+ export declare function probeBdsStatus(opts: {
30
+ managedPid?: number;
31
+ hasStdin?: boolean;
32
+ rootDir?: string;
33
+ }): Promise<BdsProbeResult>;
34
+ //# sourceMappingURL=process-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-probe.d.ts","sourceRoot":"","sources":["../src/process-probe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,MAAM,MAAM,MAAM,GAAG,CACnB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,KAC7B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAOjD,4BAA4B;AAC5B,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAOzD;AAcD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAMvD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAOnE;AAED,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAOtD;AAID,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAEhF;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAalE;AAED,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAgBvD;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CA0B/D;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAU9D;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuB1B"}