/** * 便携持久化端口:定义 scope、leader/fence、恢复图像与原子 DurableBatch。 * 这里不导入 IndexedDB/Web Locks 实现,Node/测试宿主可以提供其它 adapter。 * 成功 commit 才能确认 durable,内存发布或排队成功不能替代它。 */ import type { Json } from '../canvas-core/types.ts'; /** Portable durable-store contract. Browser database types belong to the adapter. */ /** 账号/工作区/项目共同隔离持久事实;同 projectId 不得串用其它账号的存储。 */ export type StorageScope = { readonly accountId: string; readonly workspaceId: string; readonly projectId: string }; /** 可恢复单 Root 图像;formatVersion 是解释器版本,rootRevision 与文档 localRevision 分开。 */ export type RecoveryImage = { readonly formatVersion: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17; readonly rootRevision: number; readonly localRevision: number; readonly payload: Json }; /** 同一提交携带恢复图像、文件写入/删除及可选共享 depot cut,adapter 保证合同中的原子性。 */ export type DurableBatch = { readonly image: RecoveryImage; readonly deleteFiles?:readonly string[]; readonly depot?:import('./asset-depot.ts').DepotCut; readonly files?: readonly { readonly id: string; readonly bytes: Blob }[] }; /** 排他写者句柄;fence 区分代次,active 检查加实际存储校验阻止旧 writer 在新 leader 后继续写。 */ export type StorageLeader = { readonly scope: StorageScope; readonly fence: number; readonly active: boolean; release(): Promise }; /** 文件盘点只返回元信息,不为扫描加载全部 Blob 字节。 */ export type StoredFileInfo={readonly id:string;readonly byteLength:number;readonly mimeType:string}; /** 分页盘点绑定 rootRevision,nextAfter 是后续页游标,不能跨变更拼接成完整清理依据。 */ export type FileInventoryPage={readonly files:readonly StoredFileInfo[];readonly rootRevision:number;readonly nextAfter?:string}; /** 宿主实现的存储能力;可选字段必须显式探测,缺能力不能假装已完成扫描或原子删除。 */ export type StoragePort = { /** 可选工作区共享资源仓库,文件/引用保留通过 depot 合同处理。 */ readonly assetDepot?:import('./asset-depot.ts').AssetDepotPort; /** 在 expectedRootRevision 下按稳定游标读取文件页,revision 不匹配应拒绝。 */ scanFiles?(leader:StorageLeader,input:{readonly expectedRootRevision:number;readonly after?:string;readonly limit:number}):Promise; /** atomic-v1 明确声明支持与 Root 一起提交文件删除,不能用普通异步 delete 冒充。 */ readonly fileDeletion?: 'atomic-v1'; /** 取得作用域 leader,已有有效写者时拒绝,而不是悄悄允许两个 writer。 */ claim(scope: StorageScope): Promise; /** 在有效 leader 下恢复最后可靠图像;null 表示没有已提交快照。 */ recover(leader: StorageLeader): Promise; /** 原子提交 DurableBatch 并返回真实完成的 rootRevision,不能提前在请求入队时 resolve。 */ commit(leader: StorageLeader, batch: DurableBatch): Promise<{ readonly durableRootRevision: number }>; /** 读取指定文件的 Blob,缺失用 undefined;不从文档资源引用猜字节已经存在。 */ readFile(leader: StorageLeader, id: string): Promise; /** 关闭 adapter 的本地句柄,leader 的异步释放仍通过其 release 合同完成。 */ close(): void; };