labull-framework 0.1.24 → 0.1.26

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.
@@ -64,10 +64,18 @@ export interface WriteFailure {
64
64
  export interface WriteResult {
65
65
  written: number;
66
66
  failed: WriteFailure[];
67
- /** 一共排了几个文件(= `written + skipped + failed.length`,进度条的分母)。 */
67
+ /** 一共排了几个文件(= `written + skipped + trusted + failed.length`,进度条的分母)。 */
68
68
  total: number;
69
- /** 盘上那份与要写的那份**一模一样**、因此一下都没动的文件数(`verify` 打开时才有)。 */
69
+ /** 读过一眼、确认盘上那份一模一样,因此没写的文件数(`verify` 打开时才有)。 */
70
70
  skipped: number;
71
+ /** **账本命中**、一下都没碰的文件数(见 `WriteOptions.trust`)。 */
72
+ trusted: number;
73
+ /**
74
+ * 这一趟之后"哪个路径上是哪一份内容"是**确定**的(写过的 + 读过的 + 账本命中的)。
75
+ * 🔴 调用方把它当**下一趟的账本**存起来(见 `WriteOptions.trust`):这就是"重复导出秒出"的来源。
76
+ * ⚠️ 失败的那些**不在里面**(盘上那份不是我们写的,不能算数)。
77
+ */
78
+ fingerprints: Map<string, string>;
71
79
  }
72
80
  /** `writePackage` 的开关。 */
73
81
  export interface WriteOptions {
@@ -85,7 +93,37 @@ export interface WriteOptions {
85
93
  * ⚠️ 刚 `clearChildren()` 过的目录可以传 `false`:那里**一个文件都不存在**,读那一趟纯属白问。
86
94
  */
87
95
  verify?: boolean;
96
+ /**
97
+ * **账本**:`包内相对路径 → 内容指纹`,记的是**上一趟我们亲手铺在那儿的**那一份
98
+ * (`WriteResult.fingerprints`)。指纹一样 + `existing` 说盘上真有这一份 ⇒ **一下都不碰**。
99
+ *
100
+ * 🔴 为什么还要它(`verify` 已经是"读一眼再决定"了):**问题在"读一眼"这个动作本身**。
101
+ * 真实开发包 136 个文件,每份要 `getFileHandle` + `getFile` + `text()` 三次往返 ——
102
+ * 文件多起来之后(15 个块)这一趟就是几秒。而"上一趟铺的就是这一份"这件事我们**自己知道**,
103
+ * 不必每次去问盘。实测(用户真实项目 13 个块 / 136 个文件):93 个块-文件那一档
104
+ * "逐字节核对"要 3 次往返/文件,账本命中是 **0 次**。
105
+ * 🔴 **代价是一条语义上的让步(必须让用户知道)**:账本命中就**不再看盘**,所以
106
+ * ① 用户在自己编辑器里改过、又没读回库的那些文件**会保留他的改动**(不会被盖掉 ——
107
+ * 这通常是好事,但"导出=覆盖"这句话就不再完全成立);
108
+ * ② 因此**必须**同时给 `existing`(`listExisting()` 的返回值):少了它,用户手动删掉的
109
+ * 文件会被我们"跳过"成永远缺失。
110
+ * 🔴 账本只是**加速**,不是判据:丢了、换了目录、刷新了页面 ⇒ 自动退回"读一眼逐字节比对",
111
+ * 结论一模一样,只是慢一次。
112
+ */
113
+ trust?: ReadonlyMap<string, string>;
114
+ /** `listExisting()` 的结果:这一包里哪些路径**盘上真有**(`trust` 命中时用它确认文件还在)。 */
115
+ existing?: ReadonlySet<string>;
88
116
  }
117
+ /**
118
+ * 正文的**内容指纹**(同一路径上"是不是我们上次写的那一份")。
119
+ *
120
+ * 🔴 **不是安全判据**,所以不必上 SHA-256:这里只回答"和上一趟那一份一样吗",
121
+ * 撞车的后果仅仅是**少写一次**(文件停在我们上一趟写的内容上),不是写错内容。
122
+ * 53 位 + 长度,几百个文件的规模上撞车概率可以忽略。
123
+ * 🔴 **同步**:它在进写盘循环**之前**把整包算完(2 MB 上下 ≈ 20 ms),
124
+ * 换成 `crypto.subtle` 就得把一串 Promise 织进那个并发循环里 —— 不值得。
125
+ */
126
+ export declare function contentDigest(text: string): string;
89
127
  /**
90
128
  * 把一整个开发包写进用户选的目录(`{相对路径: 正文}`)。
91
129
  *
@@ -151,10 +189,28 @@ export declare function clearChildren(dir: LocalDir): Promise<number>;
151
189
  * "这一包要的文件 / 目录"集合里,于是被删掉,紧接着由写那一步按正确的形状建出来。
152
190
  * (这是"全删再铺"顺带保证的一件事,这里必须显式保住:否则同名目录会让那一次写直接失败。)
153
191
  *
154
- * :return: 删掉的**条目数**(每层各算一个;被整棵删掉的目录算它自己那一个 —— 与
155
- * `clearChildren` 报的"几项"同一个口径)。
192
+ * :return: `{ removed, existing }` —— 删掉的**条目数**(每层各算一个;被整棵删掉的目录算它自己
193
+ * 那一个,与 `clearChildren` 报的"几项"同一个口径)+ 这一包里**盘上真有**的那些路径
194
+ * (顺手数出来的,`WriteOptions.existing` 直接用,省掉再多走一遍目录树)。
195
+ */
196
+ export declare function pruneTo(dir: LocalDir, files: Record<string, string>): Promise<PruneResult>;
197
+ /** `pruneTo()` 的结果。 */
198
+ export interface PruneResult {
199
+ /** 删掉的条目数(每层各算一个)。 */
200
+ removed: number;
201
+ /** 这一包里**盘上真有**的那些文件路径(顺手数出来的)。 */
202
+ existing: Set<string>;
203
+ }
204
+ /**
205
+ * 这一包里**哪些路径盘上真有**(只读:一个字节都不改)。
206
+ *
207
+ * 🔴 它是"账本快路"的**存在性判据**(`WriteOptions.trust` + `existing`):账本只说"我们上一趟
208
+ * 把这一份铺在那儿了",而"现在还在不在"只有盘知道 —— 少了这一步,用户手动删掉的文件会被
209
+ * 我们一直跳过(永远缺失)。
210
+ * 🔴 **只走这一包要的那些目录**(不是整棵树):一个块文件夹有 5-10 个文件但只有 2-3 层目录,
211
+ * 于是"问清 136 个文件在不在"只要几十次目录遍历,而不是 136×3 次文件往返。
156
212
  */
157
- export declare function pruneTo(dir: LocalDir, files: Record<string, string>): Promise<number>;
213
+ export declare function listExisting(dir: LocalDir, files: Record<string, string>): Promise<Set<string>>;
158
214
  /**
159
215
  * 选中的目录**本身**就是代码那一层时当场说清(`workspace/workspace/…` 是没人想要的)。
160
216
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "labull-framework",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Labull 前端 SDK:主题 CSS + 登录态 / 外壳组件 / magic block(四块合一,一个包)",