@minnowdb/core 0.2.1 → 0.4.0

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 (270) hide show
  1. package/README.md +23 -32
  2. package/dist/block-format/block.d.ts +32 -13
  3. package/dist/block-format/block.js +179 -55
  4. package/dist/block-format/checksum.d.ts +2 -1
  5. package/dist/block-format/checksum.js +5 -2
  6. package/dist/block-format/codecs.d.ts +7 -2
  7. package/dist/block-format/codecs.js +53 -12
  8. package/dist/block-format/column.d.ts +3 -2
  9. package/dist/block-format/column.js +96 -30
  10. package/dist/block-format/index.d.ts +2 -2
  11. package/dist/block-format/index.js +2 -2
  12. package/dist/block-format/physical.d.ts +8 -2
  13. package/dist/block-format/physical.js +14 -6
  14. package/dist/block-format/types.d.ts +7 -3
  15. package/dist/block-format/types.js +0 -1
  16. package/dist/block-format/unicode.d.ts +11 -0
  17. package/dist/block-format/unicode.js +46 -0
  18. package/dist/date-value.d.ts +15 -0
  19. package/dist/date-value.js +64 -0
  20. package/dist/engine/artifact-cache.d.ts +2 -1
  21. package/dist/engine/artifact-cache.js +5 -1
  22. package/dist/engine/batch.d.ts +11 -3
  23. package/dist/engine/batch.js +17 -7
  24. package/dist/engine/buffered-writer.d.ts +2 -1
  25. package/dist/engine/buffered-writer.js +34 -9
  26. package/dist/engine/cache-limits.d.ts +25 -0
  27. package/dist/engine/cache-limits.js +25 -0
  28. package/dist/engine/catalog.d.ts +24 -5
  29. package/dist/engine/catalog.js +34 -7
  30. package/dist/engine/client.d.ts +29 -7
  31. package/dist/engine/client.js +216 -40
  32. package/dist/engine/database.d.ts +224 -39
  33. package/dist/engine/database.js +7475 -1539
  34. package/dist/engine/defaults.d.ts +4 -8
  35. package/dist/engine/defaults.js +46 -22
  36. package/dist/engine/errors.d.ts +19 -1
  37. package/dist/engine/errors.js +32 -2
  38. package/dist/engine/fts.d.ts +0 -6
  39. package/dist/engine/fts.js +41 -14
  40. package/dist/engine/group-index.d.ts +0 -1
  41. package/dist/engine/group-index.js +6 -11
  42. package/dist/engine/index.d.ts +16 -10
  43. package/dist/engine/index.js +12 -9
  44. package/dist/engine/join-index.d.ts +0 -1
  45. package/dist/engine/join-index.js +2 -2
  46. package/dist/engine/keyed-live.d.ts +57 -0
  47. package/dist/engine/keyed-live.js +226 -0
  48. package/dist/engine/live-api.d.ts +4 -0
  49. package/dist/engine/live-api.js +4 -0
  50. package/dist/engine/live.d.ts +43 -26
  51. package/dist/engine/live.js +504 -126
  52. package/dist/engine/memory.d.ts +2 -1
  53. package/dist/engine/memory.js +3 -2
  54. package/dist/engine/optimizer.d.ts +0 -1
  55. package/dist/engine/optimizer.js +262 -27
  56. package/dist/engine/query-api.d.ts +3 -0
  57. package/dist/engine/query-api.js +3 -0
  58. package/dist/engine/query-cache.d.ts +1 -2
  59. package/dist/engine/query-cache.js +7 -5
  60. package/dist/engine/query.d.ts +134 -29
  61. package/dist/engine/query.js +1668 -372
  62. package/dist/engine/result-wire.d.ts +0 -1
  63. package/dist/engine/result-wire.js +2 -2
  64. package/dist/engine/schema-wire.d.ts +6 -3
  65. package/dist/engine/schema-wire.js +40 -34
  66. package/dist/engine/schema.d.ts +156 -80
  67. package/dist/engine/schema.js +570 -108
  68. package/dist/engine/sort-keys.d.ts +4 -4
  69. package/dist/engine/sort-keys.js +44 -29
  70. package/dist/engine/sql-domains.d.ts +31 -0
  71. package/dist/engine/sql-domains.js +585 -0
  72. package/dist/engine/sql-driver.d.ts +19 -0
  73. package/dist/engine/sql-driver.js +1 -0
  74. package/dist/engine/sql-json.d.ts +7 -9
  75. package/dist/engine/sql-json.js +75 -15
  76. package/dist/engine/sql-semantics.d.ts +8 -3
  77. package/dist/engine/sql-semantics.js +458 -30
  78. package/dist/engine/typed-live.d.ts +67 -0
  79. package/dist/engine/typed-live.js +349 -0
  80. package/dist/engine/vector.d.ts +12 -2
  81. package/dist/engine/vector.js +635 -119
  82. package/dist/engine/worker-host.d.ts +9 -2
  83. package/dist/engine/worker-host.js +620 -152
  84. package/dist/engine/worker.d.ts +0 -1
  85. package/dist/engine/worker.js +3 -3
  86. package/dist/engine/write-block-planner.d.ts +18 -0
  87. package/dist/engine/write-block-planner.js +112 -0
  88. package/dist/index.d.ts +0 -1
  89. package/dist/index.js +0 -1
  90. package/dist/plan/index.d.ts +3 -4
  91. package/dist/plan/index.js +3 -4
  92. package/dist/storage/index.d.ts +1 -1
  93. package/dist/storage/index.js +1 -1
  94. package/dist/storage/indexeddb.d.ts +99 -51
  95. package/dist/storage/indexeddb.js +13448 -2660
  96. package/dist/storage/memory.d.ts +64 -57
  97. package/dist/storage/memory.js +1042 -128
  98. package/dist/storage/opfs/files.d.ts +18 -7
  99. package/dist/storage/opfs/files.js +115 -28
  100. package/dist/storage/opfs/index.d.ts +1 -1
  101. package/dist/storage/opfs/index.js +1 -1
  102. package/dist/storage/opfs/leader.d.ts +409 -75
  103. package/dist/storage/opfs/leader.js +4621 -650
  104. package/dist/storage/opfs/rpc.d.ts +15 -3
  105. package/dist/storage/opfs/rpc.js +224 -2
  106. package/dist/storage/opfs/snapshot-ledger.d.ts +40 -0
  107. package/dist/storage/opfs/snapshot-ledger.js +281 -0
  108. package/dist/storage/opfs/store.d.ts +33 -99
  109. package/dist/storage/opfs/store.js +453 -364
  110. package/dist/storage/persistence.d.ts +37 -0
  111. package/dist/storage/persistence.js +78 -0
  112. package/dist/storage/snapshot-stream.d.ts +24 -0
  113. package/dist/storage/snapshot-stream.js +897 -0
  114. package/dist/storage/snapshot.d.ts +9 -85
  115. package/dist/storage/snapshot.js +33 -265
  116. package/dist/storage/toolkit/extents.d.ts +41 -7
  117. package/dist/storage/toolkit/extents.js +402 -39
  118. package/dist/storage/toolkit/index.d.ts +4 -5
  119. package/dist/storage/toolkit/index.js +28 -4
  120. package/dist/storage/toolkit/record-core.d.ts +182 -55
  121. package/dist/storage/toolkit/record-core.js +6158 -1331
  122. package/dist/storage/toolkit/sync-file.d.ts +10 -1
  123. package/dist/storage/toolkit/sync-file.js +50 -2
  124. package/dist/storage/toolkit/wal.d.ts +23 -5
  125. package/dist/storage/toolkit/wal.js +89 -27
  126. package/dist/storage/toolkit/wire.d.ts +15 -2
  127. package/dist/storage/toolkit/wire.js +199 -10
  128. package/dist/storage/types.d.ts +1439 -204
  129. package/dist/storage/types.js +1745 -141
  130. package/dist/testing/block-store-conformance.d.ts +0 -1
  131. package/dist/testing/block-store-conformance.js +1009 -119
  132. package/dist/testing/index.d.ts +46 -26
  133. package/dist/testing/index.js +112 -57
  134. package/dist/testing/opfs-shim.d.ts +13 -3
  135. package/dist/testing/opfs-shim.js +40 -6
  136. package/dist/testing/simulator.d.ts +97 -0
  137. package/dist/testing/simulator.js +591 -0
  138. package/dist/testing/sqllogictest.d.ts +89 -0
  139. package/dist/testing/sqllogictest.js +434 -0
  140. package/dist/transactions/index.d.ts +92 -16
  141. package/dist/transactions/index.js +1074 -236
  142. package/dist/worker-protocol/index.d.ts +3 -2
  143. package/dist/worker-protocol/index.js +2 -5
  144. package/package.json +53 -3
  145. package/postgres-feature-profile.json +223 -0
  146. package/sql-feature-matrix.json +172 -252
  147. package/dist/block-format/block.d.ts.map +0 -1
  148. package/dist/block-format/block.js.map +0 -1
  149. package/dist/block-format/checksum.d.ts.map +0 -1
  150. package/dist/block-format/checksum.js.map +0 -1
  151. package/dist/block-format/codecs.d.ts.map +0 -1
  152. package/dist/block-format/codecs.js.map +0 -1
  153. package/dist/block-format/column.d.ts.map +0 -1
  154. package/dist/block-format/column.js.map +0 -1
  155. package/dist/block-format/index.d.ts.map +0 -1
  156. package/dist/block-format/index.js.map +0 -1
  157. package/dist/block-format/physical.d.ts.map +0 -1
  158. package/dist/block-format/physical.js.map +0 -1
  159. package/dist/block-format/types.d.ts.map +0 -1
  160. package/dist/block-format/types.js.map +0 -1
  161. package/dist/engine/artifact-cache.d.ts.map +0 -1
  162. package/dist/engine/artifact-cache.js.map +0 -1
  163. package/dist/engine/batch.d.ts.map +0 -1
  164. package/dist/engine/batch.js.map +0 -1
  165. package/dist/engine/buffered-writer.d.ts.map +0 -1
  166. package/dist/engine/buffered-writer.js.map +0 -1
  167. package/dist/engine/catalog.d.ts.map +0 -1
  168. package/dist/engine/catalog.js.map +0 -1
  169. package/dist/engine/client.d.ts.map +0 -1
  170. package/dist/engine/client.js.map +0 -1
  171. package/dist/engine/coordinator.d.ts +0 -17
  172. package/dist/engine/coordinator.d.ts.map +0 -1
  173. package/dist/engine/coordinator.js +0 -60
  174. package/dist/engine/coordinator.js.map +0 -1
  175. package/dist/engine/database.d.ts.map +0 -1
  176. package/dist/engine/database.js.map +0 -1
  177. package/dist/engine/defaults.d.ts.map +0 -1
  178. package/dist/engine/defaults.js.map +0 -1
  179. package/dist/engine/errors.d.ts.map +0 -1
  180. package/dist/engine/errors.js.map +0 -1
  181. package/dist/engine/fts.d.ts.map +0 -1
  182. package/dist/engine/fts.js.map +0 -1
  183. package/dist/engine/group-index.d.ts.map +0 -1
  184. package/dist/engine/group-index.js.map +0 -1
  185. package/dist/engine/index.d.ts.map +0 -1
  186. package/dist/engine/index.js.map +0 -1
  187. package/dist/engine/join-index.d.ts.map +0 -1
  188. package/dist/engine/join-index.js.map +0 -1
  189. package/dist/engine/live.d.ts.map +0 -1
  190. package/dist/engine/live.js.map +0 -1
  191. package/dist/engine/memory.d.ts.map +0 -1
  192. package/dist/engine/memory.js.map +0 -1
  193. package/dist/engine/optimizer.d.ts.map +0 -1
  194. package/dist/engine/optimizer.js.map +0 -1
  195. package/dist/engine/query-cache.d.ts.map +0 -1
  196. package/dist/engine/query-cache.js.map +0 -1
  197. package/dist/engine/query.d.ts.map +0 -1
  198. package/dist/engine/query.js.map +0 -1
  199. package/dist/engine/result-wire.d.ts.map +0 -1
  200. package/dist/engine/result-wire.js.map +0 -1
  201. package/dist/engine/schema-wire.d.ts.map +0 -1
  202. package/dist/engine/schema-wire.js.map +0 -1
  203. package/dist/engine/schema.d.ts.map +0 -1
  204. package/dist/engine/schema.js.map +0 -1
  205. package/dist/engine/sort-keys.d.ts.map +0 -1
  206. package/dist/engine/sort-keys.js.map +0 -1
  207. package/dist/engine/sql-json.d.ts.map +0 -1
  208. package/dist/engine/sql-json.js.map +0 -1
  209. package/dist/engine/sql-semantics.d.ts.map +0 -1
  210. package/dist/engine/sql-semantics.js.map +0 -1
  211. package/dist/engine/vector.d.ts.map +0 -1
  212. package/dist/engine/vector.js.map +0 -1
  213. package/dist/engine/worker-host.d.ts.map +0 -1
  214. package/dist/engine/worker-host.js.map +0 -1
  215. package/dist/engine/worker.d.ts.map +0 -1
  216. package/dist/engine/worker.js.map +0 -1
  217. package/dist/index.d.ts.map +0 -1
  218. package/dist/index.js.map +0 -1
  219. package/dist/plan/index.d.ts.map +0 -1
  220. package/dist/plan/index.js.map +0 -1
  221. package/dist/storage/fixture-shape.d.ts +0 -42
  222. package/dist/storage/fixture-shape.d.ts.map +0 -1
  223. package/dist/storage/fixture-shape.js +0 -146
  224. package/dist/storage/fixture-shape.js.map +0 -1
  225. package/dist/storage/index.d.ts.map +0 -1
  226. package/dist/storage/index.js.map +0 -1
  227. package/dist/storage/indexeddb.d.ts.map +0 -1
  228. package/dist/storage/indexeddb.js.map +0 -1
  229. package/dist/storage/memory.d.ts.map +0 -1
  230. package/dist/storage/memory.js.map +0 -1
  231. package/dist/storage/opfs/files.d.ts.map +0 -1
  232. package/dist/storage/opfs/files.js.map +0 -1
  233. package/dist/storage/opfs/index.d.ts.map +0 -1
  234. package/dist/storage/opfs/index.js.map +0 -1
  235. package/dist/storage/opfs/leader.d.ts.map +0 -1
  236. package/dist/storage/opfs/leader.js.map +0 -1
  237. package/dist/storage/opfs/rpc.d.ts.map +0 -1
  238. package/dist/storage/opfs/rpc.js.map +0 -1
  239. package/dist/storage/opfs/store.d.ts.map +0 -1
  240. package/dist/storage/opfs/store.js.map +0 -1
  241. package/dist/storage/snapshot.d.ts.map +0 -1
  242. package/dist/storage/snapshot.js.map +0 -1
  243. package/dist/storage/toolkit/extents.d.ts.map +0 -1
  244. package/dist/storage/toolkit/extents.js.map +0 -1
  245. package/dist/storage/toolkit/index.d.ts.map +0 -1
  246. package/dist/storage/toolkit/index.js.map +0 -1
  247. package/dist/storage/toolkit/record-core.d.ts.map +0 -1
  248. package/dist/storage/toolkit/record-core.js.map +0 -1
  249. package/dist/storage/toolkit/sync-file.d.ts.map +0 -1
  250. package/dist/storage/toolkit/sync-file.js.map +0 -1
  251. package/dist/storage/toolkit/wal.d.ts.map +0 -1
  252. package/dist/storage/toolkit/wal.js.map +0 -1
  253. package/dist/storage/toolkit/wire.d.ts.map +0 -1
  254. package/dist/storage/toolkit/wire.js.map +0 -1
  255. package/dist/storage/types.d.ts.map +0 -1
  256. package/dist/storage/types.js.map +0 -1
  257. package/dist/testing/block-store-conformance.d.ts.map +0 -1
  258. package/dist/testing/block-store-conformance.js.map +0 -1
  259. package/dist/testing/index.d.ts.map +0 -1
  260. package/dist/testing/index.js.map +0 -1
  261. package/dist/testing/opfs-shim.d.ts.map +0 -1
  262. package/dist/testing/opfs-shim.js.map +0 -1
  263. package/dist/testing/seeds.d.ts +0 -11
  264. package/dist/testing/seeds.d.ts.map +0 -1
  265. package/dist/testing/seeds.js +0 -50
  266. package/dist/testing/seeds.js.map +0 -1
  267. package/dist/transactions/index.d.ts.map +0 -1
  268. package/dist/transactions/index.js.map +0 -1
  269. package/dist/worker-protocol/index.d.ts.map +0 -1
  270. package/dist/worker-protocol/index.js.map +0 -1
@@ -1,67 +1,85 @@
1
- import type { BlockStore, BlockWrite, CompactionJobRecord, CompactionJobRecordUpdate, CreateGarbageCollectionJobInput, GarbageCollectionJobRecord, GarbageCollectionStepResult, CommitTransactionInput, LeaseRecord, Manifest, ManifestSummary, PublishManifestInput, CatalogProbe, QueryCatalogState, RowIdRange, RunGarbageCollectionStepInput, SegmentRecord, StoragePage, TableRecord, TempOwnerRecord, TempRunPage, TransactionRecord, TransactionRecordUpdate } from "../storage/index.js";
2
- export declare const faultPoints: readonly ["beforeBlockWrite", "afterBlockWrite", "beforeBlockRead", "afterBlockRead", "beforeManifestCommit", "afterManifestCommit", "beforeTransactionCommit", "afterTransactionCommit"];
1
+ import type { BlockStore, AdoptAbortedSegmentInput, AbortTransactionIfExpiredInput, CompactionJobRecord, CompactionJobRecordUpdate, CreateGarbageCollectionJobInput, GarbageCollectionJobRecord, GarbageCollectionStepResult, CommitTransactionInput, LeaseRecord, Manifest, ManifestSummary, CatalogProbe, RowIdRange, RenewTransactionInput, RunGarbageCollectionStepInput, RollbackTransactionArtifactsInput, SegmentRecord, StageTransactionArtifactsInput, StoragePage, TableRecord, TempOwnerRecord, TempRunPage, TransactionRecord, TransactionRecordUpdate } from "../storage/index.js";
2
+ export declare const faultPoints: readonly ["beforeBlockWrite", "afterBlockWrite", "beforeBlockRead", "afterBlockRead", "beforeTransactionCommit", "afterTransactionCommit"];
3
3
  export type FaultPoint = (typeof faultPoints)[number];
4
4
  export type FaultInjector = (point: FaultPoint) => void | Promise<void>;
5
5
  export declare class FaultInjectingBlockStore implements BlockStore {
6
6
  private readonly inner;
7
7
  private readonly inject;
8
- /** Present only when the inner store implements it, so callers' fallbacks stay honest. */
9
- getQueryCatalogState?: (tableNames: readonly string[]) => Promise<QueryCatalogState>;
10
- /** Present only when the inner store implements it, so callers' fallbacks stay honest. */
11
- getCatalogProbe?: () => Promise<CatalogProbe>;
12
8
  constructor(inner: BlockStore, inject: FaultInjector);
13
- addBlock(id: string, bytes: Uint8Array): Promise<void>;
14
- addBlocks(blocks: readonly BlockWrite[]): Promise<void>;
9
+ getCatalogProbe(): Promise<CatalogProbe>;
10
+ beginTransaction(input: Parameters<BlockStore["beginTransaction"]>[0]): ReturnType<BlockStore["beginTransaction"]>;
15
11
  getBlock(id: string): Promise<Uint8Array | undefined>;
16
12
  getBlocks(ids: readonly string[]): Promise<Array<Uint8Array | undefined>>;
17
- removeBlock(id: string): Promise<void>;
18
- listBlockIds(): Promise<string[]>;
19
- addTable(record: TableRecord): Promise<void>;
13
+ readManifestBlock(version: number | null, id: string): Promise<Uint8Array | undefined>;
14
+ hasManifestBlocks(version: number | null, ids: readonly string[]): Promise<boolean[]>;
15
+ addTable(record: TableRecord, options?: Parameters<BlockStore["addTable"]>[1]): Promise<void>;
20
16
  getTable(id: string): Promise<TableRecord | undefined>;
21
17
  getTableByName(name: string): Promise<TableRecord | undefined>;
22
18
  listTables(): Promise<TableRecord[]>;
23
19
  updateTable(id: string, expectedRevision: number, update: Parameters<BlockStore["updateTable"]>[2]): Promise<TableRecord>;
24
- removeTable(id: string, expectedRevision: number): Promise<void>;
25
- addSegment(record: SegmentRecord): Promise<void>;
20
+ removeTable(id: string, expectedRevision: number, options?: Parameters<BlockStore["removeTable"]>[2]): Promise<void>;
21
+ dropTable(input: Parameters<BlockStore["dropTable"]>[0]): Promise<ManifestSummary>;
22
+ dropTableColumn(input: Parameters<BlockStore["dropTableColumn"]>[0]): Promise<ManifestSummary>;
26
23
  getSegment(id: string): Promise<SegmentRecord | undefined>;
27
- listSegments(tableId?: string): Promise<SegmentRecord[]>;
28
- removeSegment(id: string): Promise<void>;
24
+ listSegmentPage(afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
25
+ listTableSegmentPage(tableId: string, afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
26
+ removeAbortedSegment(id: string, expectedTransactionId: string): Promise<boolean>;
27
+ adoptAbortedSegment(input: AdoptAbortedSegmentInput): Promise<TransactionRecord>;
29
28
  reserveRowIds(tableId: string, count: number): Promise<RowIdRange>;
30
29
  reserveAutoIncrement(tableId: string, columnId: string, count: number, atLeast?: bigint): Promise<RowIdRange>;
31
30
  writeFtsBase(tableId: string, columnId: string, input: Parameters<BlockStore["writeFtsBase"]>[2]): Promise<void>;
31
+ beginFtsBaseBuild(input: Parameters<BlockStore["beginFtsBaseBuild"]>[0]): Promise<void>;
32
+ renewFtsBaseBuild(input: Parameters<BlockStore["renewFtsBaseBuild"]>[0]): Promise<void>;
33
+ writeFtsBaseBuildChunk(input: Parameters<BlockStore["writeFtsBaseBuildChunk"]>[0]): Promise<void>;
34
+ finishFtsBaseBuild(input: Parameters<BlockStore["finishFtsBaseBuild"]>[0]): Promise<void>;
35
+ abortFtsBaseBuild(input: Parameters<BlockStore["abortFtsBaseBuild"]>[0]): Promise<void>;
36
+ removeFtsColumn(tableId: string, columnId: string): Promise<void>;
32
37
  readFtsCandidates(tableId: string, columnId: string, terms: Parameters<BlockStore["readFtsCandidates"]>[2], upToVersion: number): ReturnType<BlockStore["readFtsCandidates"]>;
38
+ readFtsPostings(tableId: string, columnId: string, upToVersion: number, maxRowIds?: number, maxRetainedBytes?: number): ReturnType<BlockStore["readFtsPostings"]>;
33
39
  getExistingUniqueKeys(tableId: string, keyTokens: readonly string[]): Promise<string[]>;
40
+ beginUniqueKeyBuild(input: Parameters<BlockStore["beginUniqueKeyBuild"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
41
+ getUniqueKeyBuild(buildId: string): Promise<import("../storage/types.js").UniqueKeyBuildRecord | undefined>;
42
+ renewUniqueKeyBuild(input: Parameters<BlockStore["renewUniqueKeyBuild"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
43
+ appendUniqueKeyBuildChunk(input: Parameters<BlockStore["appendUniqueKeyBuildChunk"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
44
+ finishUniqueKeyBuild(input: Parameters<BlockStore["finishUniqueKeyBuild"]>[0]): Promise<TableRecord>;
45
+ abortUniqueKeyBuild(input: Parameters<BlockStore["abortUniqueKeyBuild"]>[0]): Promise<boolean>;
34
46
  getCurrentManifestVersion(): Promise<number | null>;
35
47
  getCurrentManifest(): Promise<Manifest | undefined>;
36
48
  getManifest(version: number): Promise<Manifest | undefined>;
37
- listManifests(): Promise<Manifest[]>;
38
- listManifestPage(afterVersion: number | null, limit: number): Promise<StoragePage<Manifest, number>>;
39
- publishManifest(input: PublishManifestInput): Promise<Manifest>;
49
+ listManifestBlockPage(input: Parameters<BlockStore["listManifestBlockPage"]>[0]): Promise<import("../storage/types.js").ManifestBlockPage>;
50
+ listRetiredManifestBlockPage(input: Parameters<BlockStore["listRetiredManifestBlockPage"]>[0]): Promise<import("../storage/types.js").ManifestBlockPage>;
51
+ listManifestPage(afterVersion: number | null, limit: number): Promise<StoragePage<ManifestSummary, number>>;
40
52
  createTransaction(record: TransactionRecord): Promise<void>;
41
53
  getTransaction(id: string): Promise<TransactionRecord | undefined>;
42
54
  getTransactions(ids: readonly string[]): Promise<Array<TransactionRecord | undefined>>;
43
- listTransactions(): Promise<TransactionRecord[]>;
44
55
  listTransactionPage(afterId: string | null, limit: number): Promise<StoragePage<TransactionRecord, string>>;
45
56
  updateTransaction(id: string, expectedRevision: number, update: TransactionRecordUpdate): Promise<TransactionRecord>;
57
+ renewTransaction(input: RenewTransactionInput): Promise<boolean>;
58
+ abortTransactionIfExpired(input: AbortTransactionIfExpiredInput): Promise<TransactionRecord | undefined>;
59
+ stageTransactionArtifacts(input: StageTransactionArtifactsInput): Promise<TransactionRecord>;
60
+ rollbackTransactionArtifacts(input: RollbackTransactionArtifactsInput): Promise<TransactionRecord>;
46
61
  commitTransaction(input: CommitTransactionInput): Promise<ManifestSummary>;
47
62
  createLease(record: LeaseRecord): Promise<void>;
48
63
  getLease(id: string): Promise<LeaseRecord | undefined>;
49
64
  listLeases(): Promise<LeaseRecord[]>;
50
- renewLease(id: string, expectedRevision: number, expiresAt: string): Promise<LeaseRecord>;
65
+ listExpiredLeasePage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<LeaseRecord, string>>;
66
+ renewLease(input: Parameters<BlockStore["renewLease"]>[0]): Promise<LeaseRecord>;
51
67
  removeLeaseIfExpired(id: string, expectedRevision: number, expiresAtCutoff: string): Promise<boolean>;
52
- removeLease(id: string): Promise<void>;
68
+ removeLease(input: Parameters<BlockStore["removeLease"]>[0]): Promise<boolean>;
53
69
  createCompactionJob(record: CompactionJobRecord): Promise<void>;
54
70
  getCompactionJob(id: string): Promise<CompactionJobRecord | undefined>;
55
71
  listCompactionJobs(tableId?: string): Promise<CompactionJobRecord[]>;
56
72
  listCompactionJobPage(afterId: string | null, limit: number): Promise<StoragePage<CompactionJobRecord, string>>;
57
73
  updateCompactionJob(id: string, expectedRevision: number, update: CompactionJobRecordUpdate): Promise<CompactionJobRecord>;
58
74
  cancelCompactionJob(id: string, expectedRevision: number, cancelledAt: string): Promise<CompactionJobRecord>;
59
- removeCompactionJob(id: string): Promise<void>;
75
+ removeCompactionJob(id: string): Promise<boolean>;
60
76
  createGarbageCollectionJob(input: CreateGarbageCollectionJobInput): Promise<GarbageCollectionJobRecord>;
77
+ updateGarbageCollectionPlanning(input: Parameters<BlockStore["updateGarbageCollectionPlanning"]>[0]): Promise<GarbageCollectionJobRecord>;
61
78
  getGarbageCollectionJob(id: string): Promise<GarbageCollectionJobRecord | undefined>;
62
79
  listGarbageCollectionJobs(): Promise<GarbageCollectionJobRecord[]>;
80
+ listGarbageCollectionJobPage(afterId: string | null, limit: number): Promise<StoragePage<GarbageCollectionJobRecord, string>>;
63
81
  runGarbageCollectionStep(input: RunGarbageCollectionStepInput): Promise<GarbageCollectionStepResult>;
64
- removePrunedManifestRecords(): Promise<number>;
82
+ removePrunedManifestRecords(maxItems: number): Promise<number>;
65
83
  removeGarbageCollectionJob(id: string): Promise<void>;
66
84
  putTempRunPage(page: TempRunPage): Promise<void>;
67
85
  getTempRunPage(ownerId: string, runId: string, pageIndex: number): Promise<Uint8Array | undefined>;
@@ -69,11 +87,13 @@ export declare class FaultInjectingBlockStore implements BlockStore {
69
87
  removeTempOwner(ownerId: string): Promise<void>;
70
88
  createTempOwner(record: TempOwnerRecord): Promise<void>;
71
89
  getTempOwner(ownerId: string): Promise<TempOwnerRecord | undefined>;
72
- renewTempOwner(ownerId: string, expectedRevision: number, expiresAt: string): Promise<TempOwnerRecord>;
90
+ renewTempOwner(input: Parameters<BlockStore["renewTempOwner"]>[0]): Promise<TempOwnerRecord>;
73
91
  removeTempOwnerIfExpired(ownerId: string, expiresAtCutoff: string): Promise<boolean>;
74
92
  listTempOwnerIdsPage(afterOwnerId: string | null, limit: number): Promise<StoragePage<string, string>>;
93
+ listExpiredTempOwnerPage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<string, string>>;
75
94
  close(): void;
76
95
  }
77
96
  export { blockStoreConformanceCases, runBlockStoreConformance, type BlockStoreConformanceCase, type BlockStoreConformanceTarget, } from "./block-store-conformance.js";
78
- export { MemoryOpfs, type WriteFault } from "./opfs-shim.js";
79
- //# sourceMappingURL=index.d.ts.map
97
+ export { MemoryOpfs, type TransferLimit, type WriteFault } from "./opfs-shim.js";
98
+ export { DeterministicScheduler, generateSimulationPlan, parseSimulationPlan, runSimulation, scheduledBlockStore, type CollectionPassSummary, type SimulationDelete, type SimulationMutation, type SimulationOptions, type SimulationPlan, type SimulationPut, type SimulationResult, type SimulationStep, type SimulationTraceEvent, } from "./simulator.js";
99
+ export { SqlLogicFailure, SqlLogicParseError, md5Hex, parseSqlLogicTest, parseSqlLogicTestLines, renderSqlLogicValue, runSqlLogicTest, type SqlLogicCondition, type SqlLogicDatabase, type SqlLogicExpectedHash, type SqlLogicExpectedValues, type SqlLogicHalt, type SqlLogicHashThreshold, type SqlLogicLocation, type SqlLogicQuery, type SqlLogicRecord, type SqlLogicRunStatistics, type SqlLogicRunOptions, type SqlLogicSortMode, type SqlLogicStatement, type SqlLogicType, } from "./sqllogictest.js";
@@ -3,39 +3,21 @@ export const faultPoints = [
3
3
  "afterBlockWrite",
4
4
  "beforeBlockRead",
5
5
  "afterBlockRead",
6
- "beforeManifestCommit",
7
- "afterManifestCommit",
8
6
  "beforeTransactionCommit",
9
7
  "afterTransactionCommit",
10
8
  ];
11
9
  export class FaultInjectingBlockStore {
12
10
  inner;
13
11
  inject;
14
- /** Present only when the inner store implements it, so callers' fallbacks stay honest. */
15
- getQueryCatalogState;
16
- /** Present only when the inner store implements it, so callers' fallbacks stay honest. */
17
- getCatalogProbe;
18
12
  constructor(inner, inject) {
19
13
  this.inner = inner;
20
14
  this.inject = inject;
21
- const innerCatalogState = inner.getQueryCatalogState?.bind(inner);
22
- if (innerCatalogState !== undefined) {
23
- this.getQueryCatalogState = (tableNames) => innerCatalogState(tableNames);
24
- }
25
- const innerCatalogProbe = inner.getCatalogProbe?.bind(inner);
26
- if (innerCatalogProbe !== undefined) {
27
- this.getCatalogProbe = () => innerCatalogProbe();
28
- }
29
- }
30
- async addBlock(id, bytes) {
31
- await this.inject("beforeBlockWrite");
32
- await this.inner.addBlock(id, bytes);
33
- await this.inject("afterBlockWrite");
34
15
  }
35
- async addBlocks(blocks) {
36
- await this.inject("beforeBlockWrite");
37
- await this.inner.addBlocks(blocks);
38
- await this.inject("afterBlockWrite");
16
+ getCatalogProbe() {
17
+ return this.inner.getCatalogProbe();
18
+ }
19
+ beginTransaction(input) {
20
+ return this.inner.beginTransaction(input);
39
21
  }
40
22
  async getBlock(id) {
41
23
  await this.inject("beforeBlockRead");
@@ -49,14 +31,17 @@ export class FaultInjectingBlockStore {
49
31
  await this.inject("afterBlockRead");
50
32
  return blocks;
51
33
  }
52
- removeBlock(id) {
53
- return this.inner.removeBlock(id);
34
+ async readManifestBlock(version, id) {
35
+ await this.inject("beforeBlockRead");
36
+ const bytes = await this.inner.readManifestBlock(version, id);
37
+ await this.inject("afterBlockRead");
38
+ return bytes;
54
39
  }
55
- listBlockIds() {
56
- return this.inner.listBlockIds();
40
+ hasManifestBlocks(version, ids) {
41
+ return this.inner.hasManifestBlocks(version, ids);
57
42
  }
58
- addTable(record) {
59
- return this.inner.addTable(record);
43
+ addTable(record, options) {
44
+ return this.inner.addTable(record, options);
60
45
  }
61
46
  getTable(id) {
62
47
  return this.inner.getTable(id);
@@ -70,20 +55,29 @@ export class FaultInjectingBlockStore {
70
55
  updateTable(id, expectedRevision, update) {
71
56
  return this.inner.updateTable(id, expectedRevision, update);
72
57
  }
73
- removeTable(id, expectedRevision) {
74
- return this.inner.removeTable(id, expectedRevision);
58
+ removeTable(id, expectedRevision, options) {
59
+ return this.inner.removeTable(id, expectedRevision, options);
75
60
  }
76
- addSegment(record) {
77
- return this.inner.addSegment(record);
61
+ dropTable(input) {
62
+ return this.inner.dropTable(input);
63
+ }
64
+ dropTableColumn(input) {
65
+ return this.inner.dropTableColumn(input);
78
66
  }
79
67
  getSegment(id) {
80
68
  return this.inner.getSegment(id);
81
69
  }
82
- listSegments(tableId) {
83
- return this.inner.listSegments(tableId);
70
+ listSegmentPage(afterId, limit) {
71
+ return this.inner.listSegmentPage(afterId, limit);
72
+ }
73
+ listTableSegmentPage(tableId, afterId, limit) {
74
+ return this.inner.listTableSegmentPage(tableId, afterId, limit);
84
75
  }
85
- removeSegment(id) {
86
- return this.inner.removeSegment(id);
76
+ removeAbortedSegment(id, expectedTransactionId) {
77
+ return this.inner.removeAbortedSegment(id, expectedTransactionId);
78
+ }
79
+ adoptAbortedSegment(input) {
80
+ return this.inner.adoptAbortedSegment(input);
87
81
  }
88
82
  reserveRowIds(tableId, count) {
89
83
  return this.inner.reserveRowIds(tableId, count);
@@ -94,12 +88,51 @@ export class FaultInjectingBlockStore {
94
88
  writeFtsBase(tableId, columnId, input) {
95
89
  return this.inner.writeFtsBase(tableId, columnId, input);
96
90
  }
91
+ beginFtsBaseBuild(input) {
92
+ return this.inner.beginFtsBaseBuild(input);
93
+ }
94
+ renewFtsBaseBuild(input) {
95
+ return this.inner.renewFtsBaseBuild(input);
96
+ }
97
+ writeFtsBaseBuildChunk(input) {
98
+ return this.inner.writeFtsBaseBuildChunk(input);
99
+ }
100
+ finishFtsBaseBuild(input) {
101
+ return this.inner.finishFtsBaseBuild(input);
102
+ }
103
+ abortFtsBaseBuild(input) {
104
+ return this.inner.abortFtsBaseBuild(input);
105
+ }
106
+ removeFtsColumn(tableId, columnId) {
107
+ return this.inner.removeFtsColumn(tableId, columnId);
108
+ }
97
109
  readFtsCandidates(tableId, columnId, terms, upToVersion) {
98
110
  return this.inner.readFtsCandidates(tableId, columnId, terms, upToVersion);
99
111
  }
112
+ readFtsPostings(tableId, columnId, upToVersion, maxRowIds, maxRetainedBytes) {
113
+ return this.inner.readFtsPostings(tableId, columnId, upToVersion, maxRowIds, maxRetainedBytes);
114
+ }
100
115
  getExistingUniqueKeys(tableId, keyTokens) {
101
116
  return this.inner.getExistingUniqueKeys(tableId, keyTokens);
102
117
  }
118
+ beginUniqueKeyBuild(input) {
119
+ return this.inner.beginUniqueKeyBuild(input);
120
+ }
121
+ getUniqueKeyBuild(buildId) {
122
+ return this.inner.getUniqueKeyBuild(buildId);
123
+ }
124
+ renewUniqueKeyBuild(input) {
125
+ return this.inner.renewUniqueKeyBuild(input);
126
+ }
127
+ appendUniqueKeyBuildChunk(input) {
128
+ return this.inner.appendUniqueKeyBuildChunk(input);
129
+ }
130
+ finishUniqueKeyBuild(input) {
131
+ return this.inner.finishUniqueKeyBuild(input);
132
+ }
133
+ abortUniqueKeyBuild(input) {
134
+ return this.inner.abortUniqueKeyBuild(input);
135
+ }
103
136
  getCurrentManifestVersion() {
104
137
  return this.inner.getCurrentManifestVersion();
105
138
  }
@@ -109,18 +142,15 @@ export class FaultInjectingBlockStore {
109
142
  getManifest(version) {
110
143
  return this.inner.getManifest(version);
111
144
  }
112
- listManifests() {
113
- return this.inner.listManifests();
145
+ listManifestBlockPage(input) {
146
+ return this.inner.listManifestBlockPage(input);
147
+ }
148
+ listRetiredManifestBlockPage(input) {
149
+ return this.inner.listRetiredManifestBlockPage(input);
114
150
  }
115
151
  listManifestPage(afterVersion, limit) {
116
152
  return this.inner.listManifestPage(afterVersion, limit);
117
153
  }
118
- async publishManifest(input) {
119
- await this.inject("beforeManifestCommit");
120
- const manifest = await this.inner.publishManifest(input);
121
- await this.inject("afterManifestCommit");
122
- return manifest;
123
- }
124
154
  createTransaction(record) {
125
155
  return this.inner.createTransaction(record);
126
156
  }
@@ -130,15 +160,27 @@ export class FaultInjectingBlockStore {
130
160
  getTransactions(ids) {
131
161
  return this.inner.getTransactions(ids);
132
162
  }
133
- listTransactions() {
134
- return this.inner.listTransactions();
135
- }
136
163
  listTransactionPage(afterId, limit) {
137
164
  return this.inner.listTransactionPage(afterId, limit);
138
165
  }
139
166
  updateTransaction(id, expectedRevision, update) {
140
167
  return this.inner.updateTransaction(id, expectedRevision, update);
141
168
  }
169
+ renewTransaction(input) {
170
+ return this.inner.renewTransaction(input);
171
+ }
172
+ abortTransactionIfExpired(input) {
173
+ return this.inner.abortTransactionIfExpired(input);
174
+ }
175
+ async stageTransactionArtifacts(input) {
176
+ await this.inject("beforeBlockWrite");
177
+ const transaction = await this.inner.stageTransactionArtifacts(input);
178
+ await this.inject("afterBlockWrite");
179
+ return transaction;
180
+ }
181
+ rollbackTransactionArtifacts(input) {
182
+ return this.inner.rollbackTransactionArtifacts(input);
183
+ }
142
184
  async commitTransaction(input) {
143
185
  await this.inject("beforeTransactionCommit");
144
186
  const manifest = await this.inner.commitTransaction(input);
@@ -154,14 +196,17 @@ export class FaultInjectingBlockStore {
154
196
  listLeases() {
155
197
  return this.inner.listLeases();
156
198
  }
157
- renewLease(id, expectedRevision, expiresAt) {
158
- return this.inner.renewLease(id, expectedRevision, expiresAt);
199
+ listExpiredLeasePage(expiresAtCutoff, afterCursor, limit) {
200
+ return this.inner.listExpiredLeasePage(expiresAtCutoff, afterCursor, limit);
201
+ }
202
+ renewLease(input) {
203
+ return this.inner.renewLease(input);
159
204
  }
160
205
  removeLeaseIfExpired(id, expectedRevision, expiresAtCutoff) {
161
206
  return this.inner.removeLeaseIfExpired(id, expectedRevision, expiresAtCutoff);
162
207
  }
163
- removeLease(id) {
164
- return this.inner.removeLease(id);
208
+ removeLease(input) {
209
+ return this.inner.removeLease(input);
165
210
  }
166
211
  createCompactionJob(record) {
167
212
  return this.inner.createCompactionJob(record);
@@ -187,17 +232,23 @@ export class FaultInjectingBlockStore {
187
232
  createGarbageCollectionJob(input) {
188
233
  return this.inner.createGarbageCollectionJob(input);
189
234
  }
235
+ updateGarbageCollectionPlanning(input) {
236
+ return this.inner.updateGarbageCollectionPlanning(input);
237
+ }
190
238
  getGarbageCollectionJob(id) {
191
239
  return this.inner.getGarbageCollectionJob(id);
192
240
  }
193
241
  listGarbageCollectionJobs() {
194
242
  return this.inner.listGarbageCollectionJobs();
195
243
  }
244
+ listGarbageCollectionJobPage(afterId, limit) {
245
+ return this.inner.listGarbageCollectionJobPage(afterId, limit);
246
+ }
196
247
  runGarbageCollectionStep(input) {
197
248
  return this.inner.runGarbageCollectionStep(input);
198
249
  }
199
- removePrunedManifestRecords() {
200
- return this.inner.removePrunedManifestRecords();
250
+ removePrunedManifestRecords(maxItems) {
251
+ return this.inner.removePrunedManifestRecords(maxItems);
201
252
  }
202
253
  removeGarbageCollectionJob(id) {
203
254
  return this.inner.removeGarbageCollectionJob(id);
@@ -220,8 +271,8 @@ export class FaultInjectingBlockStore {
220
271
  getTempOwner(ownerId) {
221
272
  return this.inner.getTempOwner(ownerId);
222
273
  }
223
- renewTempOwner(ownerId, expectedRevision, expiresAt) {
224
- return this.inner.renewTempOwner(ownerId, expectedRevision, expiresAt);
274
+ renewTempOwner(input) {
275
+ return this.inner.renewTempOwner(input);
225
276
  }
226
277
  removeTempOwnerIfExpired(ownerId, expiresAtCutoff) {
227
278
  return this.inner.removeTempOwnerIfExpired(ownerId, expiresAtCutoff);
@@ -229,10 +280,14 @@ export class FaultInjectingBlockStore {
229
280
  listTempOwnerIdsPage(afterOwnerId, limit) {
230
281
  return this.inner.listTempOwnerIdsPage(afterOwnerId, limit);
231
282
  }
283
+ listExpiredTempOwnerPage(expiresAtCutoff, afterCursor, limit) {
284
+ return this.inner.listExpiredTempOwnerPage(expiresAtCutoff, afterCursor, limit);
285
+ }
232
286
  close() {
233
287
  this.inner.close();
234
288
  }
235
289
  }
236
290
  export { blockStoreConformanceCases, runBlockStoreConformance, } from "./block-store-conformance.js";
237
291
  export { MemoryOpfs } from "./opfs-shim.js";
238
- //# sourceMappingURL=index.js.map
292
+ export { DeterministicScheduler, generateSimulationPlan, parseSimulationPlan, runSimulation, scheduledBlockStore, } from "./simulator.js";
293
+ export { SqlLogicFailure, SqlLogicParseError, md5Hex, parseSqlLogicTest, parseSqlLogicTestLines, renderSqlLogicValue, runSqlLogicTest, } from "./sqllogictest.js";
@@ -12,24 +12,34 @@
12
12
  * `InvalidModificationError`, `NoModificationAllowedError`, and injected
13
13
  * `QuotaExceededError`s are actual `DOMException`s, since error identity is part of the
14
14
  * storage contract.
15
- * - **Injectable write faults.** `setWriteFault` throws from inside sync writes, creates, or
16
- * flushes how the quota and crash suites produce a failure at an exact byte boundary.
15
+ * - **Injectable write faults and short transfers.** `setWriteFault` throws from inside sync
16
+ * writes, creates, or flushes; `setTransferLimit` makes reads or writes return any valid short
17
+ * byte count, including zero progress, at deterministic offsets.
17
18
  *
18
19
  * For applications, `MemoryBlockStore` remains the right store in Node tests. This shim is for
19
20
  * adapter authors: it hosts `OpfsBlockStore` (pass `root`) or anything built on the storage
20
21
  * toolkit's `SyncFileHandle` surface, in plain vitest, with crashes and quota failures on tap.
21
22
  */
22
23
  export type WriteFault = (path: string, phase: "create" | "write" | "flush") => void;
24
+ export type DeleteFault = (path: string) => void;
25
+ export type TransferLimit = (path: string, operation: "read" | "write", requestedBytes: number, at: number) => number | undefined;
23
26
  export declare class MemoryOpfs {
24
27
  #private;
25
28
  /** The tree's root, shaped like `navigator.storage.getDirectory()`'s result. */
26
29
  get root(): FileSystemDirectoryHandle;
27
30
  /** Installs (or clears, with `null`) a fault thrown from inside write paths. */
28
31
  setWriteFault(fault: WriteFault | null): void;
32
+ /** Installs a fault at file/directory removal, for post-commit cleanup tests. */
33
+ setDeleteFault(fault: DeleteFault | null): void;
34
+ /** Limits individual sync-handle transfers so tests can deterministically exercise short I/O. */
35
+ setTransferLimit(limit: TransferLimit | null): void;
29
36
  maybeFault(path: string, phase: "create" | "write" | "flush"): void;
37
+ maybeDeleteFault(path: string): void;
38
+ limitTransfer(path: string, operation: "read" | "write", requestedBytes: number, at: number): number;
30
39
  /** Test-side peek: the file's current bytes, or undefined. Bypasses locks on purpose. */
31
40
  readFileBytes(path: string): Uint8Array | undefined;
32
41
  /** Test-side poke: writes bytes directly, creating parents. Bypasses locks on purpose. */
33
42
  writeFileBytes(path: string, bytes: Uint8Array): void;
43
+ /** Test-side in-place corruption: existing sync handles observe the changed byte. */
44
+ corruptFileByte(path: string, offset: number): void;
34
45
  }
35
- //# sourceMappingURL=opfs-shim.d.ts.map
@@ -12,8 +12,9 @@
12
12
  * `InvalidModificationError`, `NoModificationAllowedError`, and injected
13
13
  * `QuotaExceededError`s are actual `DOMException`s, since error identity is part of the
14
14
  * storage contract.
15
- * - **Injectable write faults.** `setWriteFault` throws from inside sync writes, creates, or
16
- * flushes how the quota and crash suites produce a failure at an exact byte boundary.
15
+ * - **Injectable write faults and short transfers.** `setWriteFault` throws from inside sync
16
+ * writes, creates, or flushes; `setTransferLimit` makes reads or writes return any valid short
17
+ * byte count, including zero progress, at deterministic offsets.
17
18
  *
18
19
  * For applications, `MemoryBlockStore` remains the right store in Node tests. This shim is for
19
20
  * adapter authors: it hosts `OpfsBlockStore` (pass `root`) or anything built on the storage
@@ -22,6 +23,8 @@
22
23
  export class MemoryOpfs {
23
24
  #rootNode = { kind: "directory", name: "", children: new Map() };
24
25
  #writeFault = null;
26
+ #deleteFault = null;
27
+ #transferLimit = null;
25
28
  /** The tree's root, shaped like `navigator.storage.getDirectory()`'s result. */
26
29
  get root() {
27
30
  return new ShimDirectoryHandle(this, this.#rootNode, "");
@@ -30,9 +33,27 @@ export class MemoryOpfs {
30
33
  setWriteFault(fault) {
31
34
  this.#writeFault = fault;
32
35
  }
36
+ /** Installs a fault at file/directory removal, for post-commit cleanup tests. */
37
+ setDeleteFault(fault) {
38
+ this.#deleteFault = fault;
39
+ }
40
+ /** Limits individual sync-handle transfers so tests can deterministically exercise short I/O. */
41
+ setTransferLimit(limit) {
42
+ this.#transferLimit = limit;
43
+ }
33
44
  maybeFault(path, phase) {
34
45
  this.#writeFault?.(path, phase);
35
46
  }
47
+ maybeDeleteFault(path) {
48
+ this.#deleteFault?.(path);
49
+ }
50
+ limitTransfer(path, operation, requestedBytes, at) {
51
+ const limited = this.#transferLimit?.(path, operation, requestedBytes, at) ?? requestedBytes;
52
+ if (!Number.isSafeInteger(limited) || limited < 0 || limited > requestedBytes) {
53
+ throw new RangeError(`Invalid test transfer limit ${String(limited)} for ${String(requestedBytes)} requested bytes`);
54
+ }
55
+ return limited;
56
+ }
36
57
  /** Test-side peek: the file's current bytes, or undefined. Bypasses locks on purpose. */
37
58
  readFileBytes(path) {
38
59
  const node = this.#find(path);
@@ -65,6 +86,16 @@ export class MemoryOpfs {
65
86
  lockHolder: existing?.lockHolder ?? null,
66
87
  });
67
88
  }
89
+ /** Test-side in-place corruption: existing sync handles observe the changed byte. */
90
+ corruptFileByte(path, offset) {
91
+ const node = this.#find(path);
92
+ if (node?.kind !== "file")
93
+ throw new Error(`Not a file: ${path}`);
94
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset >= node.bytes.byteLength) {
95
+ throw new RangeError(`Invalid corruption offset ${String(offset)} for ${path}`);
96
+ }
97
+ node.bytes[offset] = (node.bytes[offset] ?? 0) ^ 0xff;
98
+ }
68
99
  #find(path) {
69
100
  let node = this.#rootNode;
70
101
  for (const segment of path.split("/").filter((segment) => segment.length > 0)) {
@@ -138,6 +169,7 @@ class ShimDirectoryHandle {
138
169
  const existing = this.#node.children.get(name);
139
170
  if (existing === undefined)
140
171
  throw notFound(name);
172
+ this.#shim.maybeDeleteFault(this.#childPath(name));
141
173
  if (existing.kind === "file") {
142
174
  if (existing.lockHolder !== null)
143
175
  throw locked(name);
@@ -251,7 +283,8 @@ class ShimSyncAccessHandle {
251
283
  this.#assertOpen();
252
284
  const at = options?.at ?? 0;
253
285
  const target = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
254
- const source = this.#node.bytes.subarray(at, at + target.byteLength);
286
+ const limit = this.#shim.limitTransfer(this.#path, "read", target.byteLength, at);
287
+ const source = this.#node.bytes.subarray(at, at + limit);
255
288
  target.set(source);
256
289
  return source.byteLength;
257
290
  }
@@ -259,9 +292,11 @@ class ShimSyncAccessHandle {
259
292
  this.#assertOpen();
260
293
  this.#shim.maybeFault(this.#path, "write");
261
294
  const at = options?.at ?? 0;
262
- const source = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
295
+ const requested = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
296
+ const limit = this.#shim.limitTransfer(this.#path, "write", requested.byteLength, at);
297
+ const source = requested.subarray(0, limit);
263
298
  const end = at + source.byteLength;
264
- if (end > this.#node.bytes.byteLength) {
299
+ if (source.byteLength > 0 && end > this.#node.bytes.byteLength) {
265
300
  const grown = new Uint8Array(end);
266
301
  grown.set(this.#node.bytes);
267
302
  this.#node.bytes = grown;
@@ -292,4 +327,3 @@ class ShimSyncAccessHandle {
292
327
  this.#node.lockHolder = null;
293
328
  }
294
329
  }
295
- //# sourceMappingURL=opfs-shim.js.map
@@ -0,0 +1,97 @@
1
+ import { type BlockStore } from "../storage/index.js";
2
+ import { type FaultPoint } from "./index.js";
3
+ export interface SimulationPut {
4
+ readonly kind: "put";
5
+ readonly client: number;
6
+ readonly key: number;
7
+ readonly amount: number;
8
+ }
9
+ export interface SimulationDelete {
10
+ readonly kind: "delete";
11
+ readonly client: number;
12
+ readonly key: number;
13
+ }
14
+ export type SimulationMutation = SimulationPut | SimulationDelete;
15
+ export type SimulationStep = {
16
+ readonly kind: "concurrent";
17
+ readonly operations: readonly SimulationMutation[];
18
+ } | {
19
+ readonly kind: "checkpoint";
20
+ } | {
21
+ readonly kind: "maintenance";
22
+ } | {
23
+ readonly kind: "fault";
24
+ readonly point: FaultPoint;
25
+ readonly occurrence: number;
26
+ readonly operation: SimulationMutation;
27
+ };
28
+ export interface SimulationPlan {
29
+ readonly version: 1;
30
+ readonly seed: number;
31
+ readonly clients: number;
32
+ readonly keySpace: number;
33
+ readonly steps: readonly SimulationStep[];
34
+ }
35
+ export interface SimulationTraceEvent {
36
+ readonly sequence: number;
37
+ readonly operation: string;
38
+ readonly outcome: "resolved" | "rejected";
39
+ }
40
+ export interface SimulationResult {
41
+ readonly seed: number;
42
+ readonly acceptedMutations: number;
43
+ readonly rejectedConflicts: number;
44
+ readonly injectedFaults: number;
45
+ readonly checkpoints: number;
46
+ readonly maintenanceCompactions: number;
47
+ readonly compactionStop: string;
48
+ readonly collectionPasses: number;
49
+ readonly collectionTail: readonly CollectionPassSummary[];
50
+ readonly rows: ReadonlyArray<{
51
+ readonly id: number;
52
+ readonly client: number;
53
+ readonly amount: number;
54
+ }>;
55
+ readonly blockCount: number;
56
+ readonly segmentCount: number;
57
+ readonly transactionCount: number;
58
+ readonly manifestCount: number;
59
+ readonly leaseCount: number;
60
+ readonly storageBytes: number;
61
+ readonly schedulerHighWater: number;
62
+ readonly trace: readonly SimulationTraceEvent[];
63
+ readonly traceDigest: string;
64
+ }
65
+ export interface SimulationOptions {
66
+ /** Bounded diagnostic tail; old events are evicted as the simulator runs. */
67
+ readonly traceEvents?: number;
68
+ }
69
+ export interface CollectionPassSummary {
70
+ readonly prunedManifests: number;
71
+ readonly retainedManifests: number;
72
+ readonly reclaimedSegments: number;
73
+ readonly retainedSegments: number;
74
+ readonly reclaimedBlocks: number;
75
+ readonly retainedBlocks: number;
76
+ readonly reclaimedTransactions: number;
77
+ readonly retainedTransactions: number;
78
+ }
79
+ /** Chooses every storage completion from a seeded queue and keeps only a bounded trace tail. */
80
+ export declare class DeterministicScheduler {
81
+ #private;
82
+ constructor(seed: number, traceLimit?: number);
83
+ get highWater(): number;
84
+ get trace(): readonly SimulationTraceEvent[];
85
+ schedule<T>(label: string, run: () => Promise<T>): Promise<T>;
86
+ settle<T>(promises: ReadonlyArray<Promise<T>>): Promise<Array<PromiseSettledResult<T>>>;
87
+ }
88
+ /** Wraps every asynchronous BlockStore entry point in the deterministic completion scheduler. */
89
+ export declare function scheduledBlockStore(store: BlockStore, scheduler: DeterministicScheduler): BlockStore;
90
+ export declare function generateSimulationPlan(seed: number, options?: {
91
+ readonly rounds?: number;
92
+ readonly clients?: number;
93
+ readonly keySpace?: number;
94
+ }): SimulationPlan;
95
+ export declare function parseSimulationPlan(source: string): SimulationPlan;
96
+ /** Runs a replayable state-machine plan through production SQL, transactions, and block storage. */
97
+ export declare function runSimulation(plan: SimulationPlan, options?: SimulationOptions): Promise<SimulationResult>;