@adobe/data-persistence 0.9.90

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +258 -0
  3. package/dist/backend/memory-backend.d.ts +6 -0
  4. package/dist/backend/memory-backend.js +92 -0
  5. package/dist/backend/memory-backend.js.map +1 -0
  6. package/dist/backend/memory-backend.test.d.ts +1 -0
  7. package/dist/backend/memory-backend.test.js +7 -0
  8. package/dist/backend/memory-backend.test.js.map +1 -0
  9. package/dist/backend/memory-file.d.ts +7 -0
  10. package/dist/backend/memory-file.js +90 -0
  11. package/dist/backend/memory-file.js.map +1 -0
  12. package/dist/backend/memory-file.test.d.ts +1 -0
  13. package/dist/backend/memory-file.test.js +5 -0
  14. package/dist/backend/memory-file.test.js.map +1 -0
  15. package/dist/backend/persistence-backend.conformance.d.ts +10 -0
  16. package/dist/backend/persistence-backend.conformance.js +104 -0
  17. package/dist/backend/persistence-backend.conformance.js.map +1 -0
  18. package/dist/backend/persistence-backend.d.ts +54 -0
  19. package/dist/backend/persistence-backend.js +3 -0
  20. package/dist/backend/persistence-backend.js.map +1 -0
  21. package/dist/backend/random-access-file.conformance.d.ts +20 -0
  22. package/dist/backend/random-access-file.conformance.js +156 -0
  23. package/dist/backend/random-access-file.conformance.js.map +1 -0
  24. package/dist/backend/random-access-file.d.ts +39 -0
  25. package/dist/backend/random-access-file.js +3 -0
  26. package/dist/backend/random-access-file.js.map +1 -0
  27. package/dist/backend/validate-rel-path.d.ts +14 -0
  28. package/dist/backend/validate-rel-path.js +44 -0
  29. package/dist/backend/validate-rel-path.js.map +1 -0
  30. package/dist/backend/validate-rel-path.test.d.ts +1 -0
  31. package/dist/backend/validate-rel-path.test.js +37 -0
  32. package/dist/backend/validate-rel-path.test.js.map +1 -0
  33. package/dist/browser/browser-worker-bootstrap.d.ts +1 -0
  34. package/dist/browser/browser-worker-bootstrap.js +97 -0
  35. package/dist/browser/browser-worker-bootstrap.js.map +1 -0
  36. package/dist/browser/browser-worker-transport.browser.test.d.ts +1 -0
  37. package/dist/browser/browser-worker-transport.browser.test.js +156 -0
  38. package/dist/browser/browser-worker-transport.browser.test.js.map +1 -0
  39. package/dist/browser/browser-worker-transport.d.ts +33 -0
  40. package/dist/browser/browser-worker-transport.js +120 -0
  41. package/dist/browser/browser-worker-transport.js.map +1 -0
  42. package/dist/browser/create-opfs-provider.d.ts +23 -0
  43. package/dist/browser/create-opfs-provider.js +49 -0
  44. package/dist/browser/create-opfs-provider.js.map +1 -0
  45. package/dist/browser/index.d.ts +6 -0
  46. package/dist/browser/index.js +12 -0
  47. package/dist/browser/index.js.map +1 -0
  48. package/dist/browser/mount-opfs.d.ts +12 -0
  49. package/dist/browser/mount-opfs.js +15 -0
  50. package/dist/browser/mount-opfs.js.map +1 -0
  51. package/dist/browser/opfs-backend-lock.browser.test.d.ts +1 -0
  52. package/dist/browser/opfs-backend-lock.browser.test.js +127 -0
  53. package/dist/browser/opfs-backend-lock.browser.test.js.map +1 -0
  54. package/dist/browser/opfs-backend.d.ts +6 -0
  55. package/dist/browser/opfs-backend.js +162 -0
  56. package/dist/browser/opfs-backend.js.map +1 -0
  57. package/dist/browser/opfs-lock-test-worker.d.ts +1 -0
  58. package/dist/browser/opfs-lock-test-worker.js +50 -0
  59. package/dist/browser/opfs-lock-test-worker.js.map +1 -0
  60. package/dist/browser/opfs-sync-file.d.ts +10 -0
  61. package/dist/browser/opfs-sync-file.js +58 -0
  62. package/dist/browser/opfs-sync-file.js.map +1 -0
  63. package/dist/encoder/create-column-encoder.d.ts +15 -0
  64. package/dist/encoder/create-column-encoder.js +110 -0
  65. package/dist/encoder/create-column-encoder.js.map +1 -0
  66. package/dist/encoder/journal-snapshot-codec.d.ts +21 -0
  67. package/dist/encoder/journal-snapshot-codec.js +103 -0
  68. package/dist/encoder/journal-snapshot-codec.js.map +1 -0
  69. package/dist/encoder/journal-snapshot-codec.test.d.ts +1 -0
  70. package/dist/encoder/journal-snapshot-codec.test.js +96 -0
  71. package/dist/encoder/journal-snapshot-codec.test.js.map +1 -0
  72. package/dist/encoder/types.d.ts +72 -0
  73. package/dist/encoder/types.js +3 -0
  74. package/dist/encoder/types.js.map +1 -0
  75. package/dist/index.d.ts +24 -0
  76. package/dist/index.js +15 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/journal/journal-codec.d.ts +28 -0
  79. package/dist/journal/journal-codec.js +82 -0
  80. package/dist/journal/journal-codec.js.map +1 -0
  81. package/dist/journal/journal-codec.test.d.ts +1 -0
  82. package/dist/journal/journal-codec.test.js +106 -0
  83. package/dist/journal/journal-codec.test.js.map +1 -0
  84. package/dist/journal/journal-entry.d.ts +63 -0
  85. package/dist/journal/journal-entry.js +28 -0
  86. package/dist/journal/journal-entry.js.map +1 -0
  87. package/dist/node/create-node-fs-provider.d.ts +34 -0
  88. package/dist/node/create-node-fs-provider.js +48 -0
  89. package/dist/node/create-node-fs-provider.js.map +1 -0
  90. package/dist/node/index.d.ts +6 -0
  91. package/dist/node/index.js +10 -0
  92. package/dist/node/index.js.map +1 -0
  93. package/dist/node/mount-node-fs.d.ts +12 -0
  94. package/dist/node/mount-node-fs.js +15 -0
  95. package/dist/node/mount-node-fs.js.map +1 -0
  96. package/dist/node/node-fs-backend-lock.node.test.d.ts +1 -0
  97. package/dist/node/node-fs-backend-lock.node.test.js +160 -0
  98. package/dist/node/node-fs-backend-lock.node.test.js.map +1 -0
  99. package/dist/node/node-fs-backend.d.ts +21 -0
  100. package/dist/node/node-fs-backend.js +186 -0
  101. package/dist/node/node-fs-backend.js.map +1 -0
  102. package/dist/node/node-fs-backend.node.test.d.ts +1 -0
  103. package/dist/node/node-fs-backend.node.test.js +17 -0
  104. package/dist/node/node-fs-backend.node.test.js.map +1 -0
  105. package/dist/node/node-fs-file.d.ts +6 -0
  106. package/dist/node/node-fs-file.js +57 -0
  107. package/dist/node/node-fs-file.js.map +1 -0
  108. package/dist/node/node-fs-file.node.test.d.ts +1 -0
  109. package/dist/node/node-fs-file.node.test.js +13 -0
  110. package/dist/node/node-fs-file.node.test.js.map +1 -0
  111. package/dist/node/node-fs-provider.node.test.d.ts +1 -0
  112. package/dist/node/node-fs-provider.node.test.js +119 -0
  113. package/dist/node/node-fs-provider.node.test.js.map +1 -0
  114. package/dist/node/node-worker-bootstrap.d.ts +1 -0
  115. package/dist/node/node-worker-bootstrap.js +104 -0
  116. package/dist/node/node-worker-bootstrap.js.map +1 -0
  117. package/dist/node/node-worker-transport.d.ts +27 -0
  118. package/dist/node/node-worker-transport.js +152 -0
  119. package/dist/node/node-worker-transport.js.map +1 -0
  120. package/dist/node/node-worker-transport.node.test.d.ts +1 -0
  121. package/dist/node/node-worker-transport.node.test.js +147 -0
  122. package/dist/node/node-worker-transport.node.test.js.map +1 -0
  123. package/dist/perftest/perf-harness.d.ts +74 -0
  124. package/dist/perftest/perf-harness.js +147 -0
  125. package/dist/perftest/perf-harness.js.map +1 -0
  126. package/dist/perftest/persistence-perf.d.ts +2 -0
  127. package/dist/perftest/persistence-perf.js +290 -0
  128. package/dist/perftest/persistence-perf.js.map +1 -0
  129. package/dist/perftest/run.d.ts +1 -0
  130. package/dist/perftest/run.js +28 -0
  131. package/dist/perftest/run.js.map +1 -0
  132. package/dist/provider/create-memory-provider.d.ts +16 -0
  133. package/dist/provider/create-memory-provider.js +44 -0
  134. package/dist/provider/create-memory-provider.js.map +1 -0
  135. package/dist/provider/mount.d.ts +20 -0
  136. package/dist/provider/mount.js +20 -0
  137. package/dist/provider/mount.js.map +1 -0
  138. package/dist/provider/persistence-provider.d.ts +63 -0
  139. package/dist/provider/persistence-provider.js +3 -0
  140. package/dist/provider/persistence-provider.js.map +1 -0
  141. package/dist/provider/persistence-provider.test.d.ts +9 -0
  142. package/dist/provider/persistence-provider.test.js +139 -0
  143. package/dist/provider/persistence-provider.test.js.map +1 -0
  144. package/dist/service/component-nonpersistent-durability.test.d.ts +1 -0
  145. package/dist/service/component-nonpersistent-durability.test.js +57 -0
  146. package/dist/service/component-nonpersistent-durability.test.js.map +1 -0
  147. package/dist/service/create-incremental-persistence-service.d.ts +7 -0
  148. package/dist/service/create-incremental-persistence-service.js +960 -0
  149. package/dist/service/create-incremental-persistence-service.js.map +1 -0
  150. package/dist/service/create-worker-persistence-service.d.ts +1 -0
  151. package/dist/service/create-worker-persistence-service.js +7 -0
  152. package/dist/service/create-worker-persistence-service.js.map +1 -0
  153. package/dist/service/create-worker-persistence-service.test.d.ts +1 -0
  154. package/dist/service/create-worker-persistence-service.test.js +291 -0
  155. package/dist/service/create-worker-persistence-service.test.js.map +1 -0
  156. package/dist/service/entity-location-cache.d.ts +15 -0
  157. package/dist/service/entity-location-cache.js +75 -0
  158. package/dist/service/entity-location-cache.js.map +1 -0
  159. package/dist/service/entity-location-density.test.d.ts +1 -0
  160. package/dist/service/entity-location-density.test.js +42 -0
  161. package/dist/service/entity-location-density.test.js.map +1 -0
  162. package/dist/service/incremental-persistence-service.d.ts +57 -0
  163. package/dist/service/incremental-persistence-service.js +3 -0
  164. package/dist/service/incremental-persistence-service.js.map +1 -0
  165. package/dist/service/intermediate-relocation-durability.test.d.ts +1 -0
  166. package/dist/service/intermediate-relocation-durability.test.js +89 -0
  167. package/dist/service/intermediate-relocation-durability.test.js.map +1 -0
  168. package/dist/service/internal-access.d.ts +34 -0
  169. package/dist/service/internal-access.js +43 -0
  170. package/dist/service/internal-access.js.map +1 -0
  171. package/dist/service/journal-replay.test.d.ts +1 -0
  172. package/dist/service/journal-replay.test.js +424 -0
  173. package/dist/service/journal-replay.test.js.map +1 -0
  174. package/dist/service/journal-storage-durability.test.d.ts +1 -0
  175. package/dist/service/journal-storage-durability.test.js +171 -0
  176. package/dist/service/journal-storage-durability.test.js.map +1 -0
  177. package/dist/service/load-roundtrip.test.d.ts +1 -0
  178. package/dist/service/load-roundtrip.test.js +224 -0
  179. package/dist/service/load-roundtrip.test.js.map +1 -0
  180. package/dist/service/persistence-complexity.test.d.ts +1 -0
  181. package/dist/service/persistence-complexity.test.js +275 -0
  182. package/dist/service/persistence-complexity.test.js.map +1 -0
  183. package/dist/service/worker-persistence-service.d.ts +24 -0
  184. package/dist/service/worker-persistence-service.js +8 -0
  185. package/dist/service/worker-persistence-service.js.map +1 -0
  186. package/dist/transport/inprocess-transport.d.ts +15 -0
  187. package/dist/transport/inprocess-transport.js +64 -0
  188. package/dist/transport/inprocess-transport.js.map +1 -0
  189. package/dist/transport/inprocess-transport.test.d.ts +1 -0
  190. package/dist/transport/inprocess-transport.test.js +100 -0
  191. package/dist/transport/inprocess-transport.test.js.map +1 -0
  192. package/dist/transport/router.d.ts +12 -0
  193. package/dist/transport/router.js +146 -0
  194. package/dist/transport/router.js.map +1 -0
  195. package/dist/transport/transport.d.ts +105 -0
  196. package/dist/transport/transport.js +3 -0
  197. package/dist/transport/transport.js.map +1 -0
  198. package/package.json +59 -0
@@ -0,0 +1,96 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { describe, expect, it } from "vitest";
3
+ import { decodeJournalSnapshot, encodeJournalSnapshot, } from "./journal-snapshot-codec.js";
4
+ const utf8 = (s) => new TextEncoder().encode(s);
5
+ describe("journal-snapshot-codec", () => {
6
+ it("round-trips an empty row list", () => {
7
+ const buf = encodeJournalSnapshot([]);
8
+ const rows = decodeJournalSnapshot(buf);
9
+ expect(rows).toHaveLength(0);
10
+ });
11
+ it("round-trips a single present row", () => {
12
+ const encoded = utf8(JSON.stringify("hello"));
13
+ const buf = encodeJournalSnapshot([encoded]);
14
+ const rows = decodeJournalSnapshot(buf);
15
+ expect(rows).toHaveLength(1);
16
+ expect(JSON.parse(new TextDecoder().decode(rows[0]))).toBe("hello");
17
+ });
18
+ it("round-trips many rows", () => {
19
+ const input = ["alpha", "beta", "gamma"].map((s) => utf8(JSON.stringify(s)));
20
+ const buf = encodeJournalSnapshot(input);
21
+ const rows = decodeJournalSnapshot(buf);
22
+ expect(rows).toHaveLength(3);
23
+ for (let i = 0; i < input.length; i++) {
24
+ expect(JSON.parse(new TextDecoder().decode(rows[i]))).toBe(["alpha", "beta", "gamma"][i]);
25
+ }
26
+ });
27
+ it("encodes undefined rows as ABSENT and decodes back to undefined", () => {
28
+ const buf = encodeJournalSnapshot([undefined, utf8('"present"'), undefined]);
29
+ const rows = decodeJournalSnapshot(buf);
30
+ expect(rows).toHaveLength(3);
31
+ expect(rows[0]).toBeUndefined();
32
+ expect(JSON.parse(new TextDecoder().decode(rows[1]))).toBe("present");
33
+ expect(rows[2]).toBeUndefined();
34
+ });
35
+ it("encodes empty Uint8Array as ABSENT", () => {
36
+ const buf = encodeJournalSnapshot([new Uint8Array(0)]);
37
+ const rows = decodeJournalSnapshot(buf);
38
+ expect(rows[0]).toBeUndefined();
39
+ });
40
+ it("torn count header returns empty array", () => {
41
+ const truncated = new ArrayBuffer(2); // less than 4 bytes for count
42
+ const rows = decodeJournalSnapshot(truncated);
43
+ expect(rows).toHaveLength(0);
44
+ });
45
+ it("torn record len header returns prefix only", () => {
46
+ const full = encodeJournalSnapshot([
47
+ utf8('"a"'),
48
+ utf8('"b"'),
49
+ utf8('"c"'),
50
+ ]);
51
+ // Truncate to include the count + first record + half the second record's header
52
+ // count(4) + len(4) + 3 bytes for "a" (utf8 of JSON.stringify("a") = '"a"' = 3 chars)
53
+ // + 2 bytes of the second record's len header
54
+ const truncated = full.slice(0, 4 + 4 + 3 + 2);
55
+ const rows = decodeJournalSnapshot(truncated);
56
+ expect(rows).toHaveLength(3);
57
+ // First row is intact
58
+ expect(JSON.parse(new TextDecoder().decode(rows[0]))).toBe("a");
59
+ // Remaining rows should be undefined (torn)
60
+ expect(rows[1]).toBeUndefined();
61
+ expect(rows[2]).toBeUndefined();
62
+ });
63
+ it("torn record body returns prefix only", () => {
64
+ const full = encodeJournalSnapshot([
65
+ utf8('"first"'),
66
+ utf8('"second"'),
67
+ ]);
68
+ // Keep count + first full record + second record's len header but truncate the body
69
+ // '"first"' is 7 bytes
70
+ const truncated = full.slice(0, 4 + 4 + 7 + 4 + 2);
71
+ const rows = decodeJournalSnapshot(truncated);
72
+ expect(rows).toHaveLength(2);
73
+ expect(JSON.parse(new TextDecoder().decode(rows[0]))).toBe("first");
74
+ expect(rows[1]).toBeUndefined();
75
+ });
76
+ it("round-trips array values (JSON arrays as row values)", () => {
77
+ const input = [
78
+ utf8(JSON.stringify(["tag-a", "tag-b"])),
79
+ utf8(JSON.stringify(["tag-c"])),
80
+ ];
81
+ const buf = encodeJournalSnapshot(input);
82
+ const rows = decodeJournalSnapshot(buf);
83
+ expect(rows).toHaveLength(2);
84
+ expect(JSON.parse(new TextDecoder().decode(rows[0]))).toEqual(["tag-a", "tag-b"]);
85
+ expect(JSON.parse(new TextDecoder().decode(rows[1]))).toEqual(["tag-c"]);
86
+ });
87
+ it("produces distinct Uint8Array slices (no shared backing buffer)", () => {
88
+ const input = [utf8('"x"'), utf8('"y"')];
89
+ const buf = encodeJournalSnapshot(input);
90
+ const rows = decodeJournalSnapshot(buf);
91
+ // Modifying one row should not affect the other
92
+ rows[0][0] = 0xff;
93
+ expect(rows[1][0]).not.toBe(0xff);
94
+ });
95
+ });
96
+ //# sourceMappingURL=journal-snapshot-codec.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-snapshot-codec.test.js","sourceRoot":"","sources":["../../src/encoder/journal-snapshot-codec.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import type { TypedBufferType } from "@adobe/data/typed-buffer";
2
+ /**
3
+ * Manifest written to `meta.json` describing the on-disk layout for a
4
+ * specific database snapshot. Versioned for forward-compatible schema
5
+ * evolution.
6
+ */
7
+ export interface Manifest {
8
+ readonly version: 1;
9
+ readonly checkpointId: number;
10
+ readonly archetypes: {
11
+ readonly [archetypeId: number]: ArchetypeManifest;
12
+ };
13
+ /** Entity → archetypeId,rowIndex packed file metadata. */
14
+ readonly entityLocation: {
15
+ readonly stride: number;
16
+ };
17
+ /**
18
+ * Component intern table: numeric componentId → component name. Journal
19
+ * entries reference components by id (u16) for fixed binary header
20
+ * size; this table lets the loader map ids back to live column names
21
+ * during journal replay.
22
+ */
23
+ readonly components: {
24
+ readonly [componentId: number]: string;
25
+ };
26
+ }
27
+ export interface ArchetypeManifest {
28
+ readonly id: number;
29
+ readonly name: string;
30
+ readonly rowCount: number;
31
+ readonly rowCapacity: number;
32
+ readonly columns: {
33
+ readonly [component: string]: ColumnManifest;
34
+ };
35
+ }
36
+ export interface ColumnManifest {
37
+ readonly component: string;
38
+ /** Bytes per row for fixed-stride columns, or 0 for journal-only columns. */
39
+ readonly stride: number;
40
+ /** "fixed" stores in column file; "journal" stores in journal entries only. */
41
+ readonly storage: "fixed" | "journal" | "manifest";
42
+ /** TypedBufferType from @adobe/data. */
43
+ readonly bufferType: TypedBufferType;
44
+ }
45
+ /**
46
+ * A slice of column bytes ready to be transferred to the worker. The
47
+ * `bytes` ArrayBuffer is intended for zero-copy postMessage transfer.
48
+ */
49
+ export interface EncodedColumnSlice {
50
+ readonly archetypeId: number;
51
+ readonly component: string;
52
+ readonly rowOffset: number;
53
+ readonly bytes: ArrayBuffer;
54
+ }
55
+ /**
56
+ * Per-column encoder. Selected at archetype-registration time based on
57
+ * the column's underlying TypedBufferType.
58
+ */
59
+ export interface ColumnEncoder {
60
+ readonly storage: ColumnManifest["storage"];
61
+ readonly stride: number;
62
+ /**
63
+ * Encode a contiguous range of rows into a transferable buffer.
64
+ * Returns null when the column type stores nothing per row (const).
65
+ */
66
+ encodeRows(rowStart: number, rowCount: number): EncodedColumnSlice["bytes"] | null;
67
+ /**
68
+ * For variable-length columns, encode a single row's value as JSON
69
+ * bytes for inclusion in a journal entry.
70
+ */
71
+ encodeRowValue(rowIndex: number): Uint8Array | null;
72
+ }
@@ -0,0 +1,3 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/encoder/types.ts"],"names":[],"mappings":"AAAA,uDAAuD"}
@@ -0,0 +1,24 @@
1
+ export type { RandomAccessFile } from "./backend/random-access-file.js";
2
+ export { createMemoryFile } from "./backend/memory-file.js";
3
+ export type { PersistenceBackend, PersistenceBackendCapabilities, } from "./backend/persistence-backend.js";
4
+ export { createMemoryBackend } from "./backend/memory-backend.js";
5
+ export { validateRelPath } from "./backend/validate-rel-path.js";
6
+ export type { Transport, PersistOp, PersistMessage, AckMessage } from "./transport/transport.js";
7
+ export { createInprocessTransport } from "./transport/inprocess-transport.js";
8
+ export type { ColumnEncoder, EncodedColumnSlice, Manifest, ArchetypeManifest, ColumnManifest, } from "./encoder/types.js";
9
+ export { createColumnEncoder } from "./encoder/create-column-encoder.js";
10
+ export type { JournalEntry, JournalEntryKind } from "./journal/journal-entry.js";
11
+ export { encodeJournalEntry, decodeJournalEntry, decodeJournalStream } from "./journal/journal-codec.js";
12
+ export type { PersistenceProvider, ProviderMountOptions, PersistenceMount, } from "./provider/persistence-provider.js";
13
+ export { mount } from "./provider/mount.js";
14
+ export { createMemoryProvider } from "./provider/create-memory-provider.js";
15
+ export type { IncrementalPersistenceService, IncrementalPersistenceServiceOptions, } from "./service/incremental-persistence-service.js";
16
+ export { createIncrementalPersistenceService } from "./service/create-incremental-persistence-service.js";
17
+ /**
18
+ * @deprecated Use `IncrementalPersistenceService` instead.
19
+ */
20
+ export type { WorkerPersistenceService, WorkerPersistenceServiceOptions, MountOptions } from "./service/worker-persistence-service.js";
21
+ /**
22
+ * @deprecated Use `createIncrementalPersistenceService` instead.
23
+ */
24
+ export { createWorkerPersistenceService } from "./service/create-worker-persistence-service.js";
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ export { createMemoryFile } from "./backend/memory-file.js";
3
+ export { createMemoryBackend } from "./backend/memory-backend.js";
4
+ export { validateRelPath } from "./backend/validate-rel-path.js";
5
+ export { createInprocessTransport } from "./transport/inprocess-transport.js";
6
+ export { createColumnEncoder } from "./encoder/create-column-encoder.js";
7
+ export { encodeJournalEntry, decodeJournalEntry, decodeJournalStream } from "./journal/journal-codec.js";
8
+ export { mount } from "./provider/mount.js";
9
+ export { createMemoryProvider } from "./provider/create-memory-provider.js";
10
+ export { createIncrementalPersistenceService } from "./service/create-incremental-persistence-service.js";
11
+ /**
12
+ * @deprecated Use `createIncrementalPersistenceService` instead.
13
+ */
14
+ export { createWorkerPersistenceService } from "./service/create-worker-persistence-service.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAOvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAM5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAS9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AASzG,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAM5E,OAAO,EAAE,mCAAmC,EAAE,MAAM,qDAAqD,CAAC;AAQ1G;;GAEG;AACH,OAAO,EAAE,8BAA8B,EAAE,MAAM,gDAAgD,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { JournalEntry } from "./journal-entry.js";
2
+ /**
3
+ * Encode a single journal entry into a freshly-allocated, transferable
4
+ * ArrayBuffer ready for `postMessage`'s transfer list (or for direct
5
+ * `appendAt` after wrapping in a Uint8Array). Allocates exactly one
6
+ * buffer per call; variable-length payload is copied in.
7
+ *
8
+ * Returning `ArrayBuffer` (not `Uint8Array`) lets the call site avoid
9
+ * an extra copy when it just needs to forward the bytes to a worker.
10
+ */
11
+ export declare const encodeJournalEntry: (entry: JournalEntry) => ArrayBuffer;
12
+ /**
13
+ * Decode a single journal entry from a buffer at the given offset. Throws
14
+ * if the kind code is unknown or if the buffer is shorter than the
15
+ * declared payload.
16
+ *
17
+ * @returns the decoded entry plus the offset of the next entry.
18
+ */
19
+ export declare const decodeJournalEntry: (buffer: ArrayBufferLike, offset: number) => {
20
+ entry: JournalEntry;
21
+ nextOffset: number;
22
+ };
23
+ /**
24
+ * Decode all journal entries in a buffer. Stops at first truncation,
25
+ * which represents a partial write that crashed mid-entry; entries up
26
+ * to that point are returned.
27
+ */
28
+ export declare const decodeJournalStream: (buffer: ArrayBufferLike) => readonly JournalEntry[];
@@ -0,0 +1,82 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { JOURNAL_HEADER_BYTES, JournalEntryKindCode, JournalEntryKindName, } from "./journal-entry.js";
3
+ /**
4
+ * Encode a single journal entry into a freshly-allocated, transferable
5
+ * ArrayBuffer ready for `postMessage`'s transfer list (or for direct
6
+ * `appendAt` after wrapping in a Uint8Array). Allocates exactly one
7
+ * buffer per call; variable-length payload is copied in.
8
+ *
9
+ * Returning `ArrayBuffer` (not `Uint8Array`) lets the call site avoid
10
+ * an extra copy when it just needs to forward the bytes to a worker.
11
+ */
12
+ export const encodeJournalEntry = (entry) => {
13
+ const total = JOURNAL_HEADER_BYTES + entry.bytes.byteLength;
14
+ const buffer = new ArrayBuffer(total);
15
+ const view = new DataView(buffer);
16
+ view.setUint32(0, entry.txId, true);
17
+ view.setFloat64(4, entry.timestampMs, true);
18
+ view.setUint8(12, JournalEntryKindCode[entry.kind]);
19
+ view.setInt32(13, entry.entity, true);
20
+ view.setUint16(17, entry.archetypeId, true);
21
+ view.setUint32(19, entry.rowIndex, true);
22
+ view.setUint16(23, entry.componentId, true);
23
+ view.setUint32(25, entry.bytes.byteLength, true);
24
+ if (entry.bytes.byteLength > 0) {
25
+ new Uint8Array(buffer, JOURNAL_HEADER_BYTES).set(entry.bytes);
26
+ }
27
+ return buffer;
28
+ };
29
+ /**
30
+ * Decode a single journal entry from a buffer at the given offset. Throws
31
+ * if the kind code is unknown or if the buffer is shorter than the
32
+ * declared payload.
33
+ *
34
+ * @returns the decoded entry plus the offset of the next entry.
35
+ */
36
+ export const decodeJournalEntry = (buffer, offset) => {
37
+ const view = new DataView(buffer, offset);
38
+ const kindCode = view.getUint8(12);
39
+ const kind = JournalEntryKindName[kindCode];
40
+ if (kind === undefined) {
41
+ throw new Error(`Unknown journal entry kind code: ${kindCode}`);
42
+ }
43
+ const txId = view.getUint32(0, true);
44
+ const timestampMs = view.getFloat64(4, true);
45
+ const entity = view.getInt32(13, true);
46
+ const archetypeId = view.getUint16(17, true);
47
+ const rowIndex = view.getUint32(19, true);
48
+ const componentId = view.getUint16(23, true);
49
+ const byteLen = view.getUint32(25, true);
50
+ const payloadStart = offset + JOURNAL_HEADER_BYTES;
51
+ if (payloadStart + byteLen > buffer.byteLength) {
52
+ throw new Error(`Journal entry payload truncated at offset ${offset}: declared ${byteLen} bytes, only ${buffer.byteLength - payloadStart} available`);
53
+ }
54
+ const bytes = new Uint8Array(buffer, payloadStart, byteLen).slice();
55
+ return {
56
+ entry: { txId, timestampMs, kind, entity, archetypeId, rowIndex, componentId, bytes },
57
+ nextOffset: payloadStart + byteLen,
58
+ };
59
+ };
60
+ /**
61
+ * Decode all journal entries in a buffer. Stops at first truncation,
62
+ * which represents a partial write that crashed mid-entry; entries up
63
+ * to that point are returned.
64
+ */
65
+ export const decodeJournalStream = (buffer) => {
66
+ const out = [];
67
+ let offset = 0;
68
+ while (offset + JOURNAL_HEADER_BYTES <= buffer.byteLength) {
69
+ try {
70
+ const { entry, nextOffset } = decodeJournalEntry(buffer, offset);
71
+ out.push(entry);
72
+ offset = nextOffset;
73
+ }
74
+ catch {
75
+ // Truncated tail (partial write at crash) — ignore the
76
+ // remainder and return what we have.
77
+ break;
78
+ }
79
+ }
80
+ return out;
81
+ };
82
+ //# sourceMappingURL=journal-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-codec.js","sourceRoot":"","sources":["../../src/journal/journal-codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { describe, expect, it } from "vitest";
3
+ import { JOURNAL_HEADER_BYTES } from "./journal-entry.js";
4
+ import { decodeJournalEntry, decodeJournalStream, encodeJournalEntry } from "./journal-codec.js";
5
+ const sample = (overrides = {}) => ({
6
+ txId: 42,
7
+ timestampMs: 1735_000_000_000,
8
+ kind: "update",
9
+ entity: 17,
10
+ archetypeId: 7,
11
+ rowIndex: 13,
12
+ componentId: 3,
13
+ bytes: new Uint8Array([1, 2, 3, 4]),
14
+ ...overrides,
15
+ });
16
+ // Tests work in Uint8Array space, so wrap the codec's ArrayBuffer
17
+ // return for ergonomic .set / .subarray access.
18
+ const encodeBytes = (entry) => new Uint8Array(encodeJournalEntry(entry));
19
+ describe("journal codec", () => {
20
+ it("round-trips a single entry", () => {
21
+ const entry = sample();
22
+ const buf = encodeBytes(entry);
23
+ expect(buf.byteLength).toBe(JOURNAL_HEADER_BYTES + entry.bytes.byteLength);
24
+ const { entry: decoded, nextOffset } = decodeJournalEntry(buf.buffer, 0);
25
+ expect(decoded.txId).toBe(entry.txId);
26
+ expect(decoded.timestampMs).toBe(entry.timestampMs);
27
+ expect(decoded.kind).toBe(entry.kind);
28
+ expect(decoded.entity).toBe(entry.entity);
29
+ expect(decoded.archetypeId).toBe(entry.archetypeId);
30
+ expect(decoded.rowIndex).toBe(entry.rowIndex);
31
+ expect(decoded.componentId).toBe(entry.componentId);
32
+ expect(Array.from(decoded.bytes)).toEqual([1, 2, 3, 4]);
33
+ expect(nextOffset).toBe(buf.byteLength);
34
+ });
35
+ it("round-trips an entry with empty payload (e.g. delete)", () => {
36
+ const entry = sample({ kind: "delete", componentId: 0, bytes: new Uint8Array(0) });
37
+ const buf = encodeBytes(entry);
38
+ expect(buf.byteLength).toBe(JOURNAL_HEADER_BYTES);
39
+ const { entry: decoded } = decodeJournalEntry(buf.buffer, 0);
40
+ expect(decoded.kind).toBe("delete");
41
+ expect(decoded.bytes.byteLength).toBe(0);
42
+ });
43
+ it("decodes a stream of multiple entries", () => {
44
+ const entries = [
45
+ sample({ txId: 1 }),
46
+ sample({ txId: 2, kind: "insert", bytes: new Uint8Array([9, 9, 9]) }),
47
+ sample({ txId: 3, kind: "delete", componentId: 0, bytes: new Uint8Array(0) }),
48
+ ];
49
+ const concat = new Uint8Array(entries.reduce((sum, e) => sum + JOURNAL_HEADER_BYTES + e.bytes.byteLength, 0));
50
+ let offset = 0;
51
+ for (const e of entries) {
52
+ const enc = encodeBytes(e);
53
+ concat.set(enc, offset);
54
+ offset += enc.byteLength;
55
+ }
56
+ const decoded = decodeJournalStream(concat.buffer);
57
+ expect(decoded.length).toBe(3);
58
+ expect(decoded.map(d => d.txId)).toEqual([1, 2, 3]);
59
+ expect(decoded[1].kind).toBe("insert");
60
+ });
61
+ it("decodeJournalStream tolerates a truncated tail entry", () => {
62
+ const entry = sample({ bytes: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]) });
63
+ const enc = encodeBytes(entry);
64
+ const truncated = enc.subarray(0, enc.byteLength - 3);
65
+ const decoded = decodeJournalStream(truncated.buffer.slice(truncated.byteOffset, truncated.byteOffset + truncated.byteLength));
66
+ expect(decoded.length).toBe(0);
67
+ });
68
+ it("decodeJournalStream returns the prefix when only the tail is torn", () => {
69
+ const ok = encodeBytes(sample({ txId: 100 }));
70
+ const torn = encodeBytes(sample({ txId: 101, bytes: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]) }));
71
+ const tornShort = torn.subarray(0, torn.byteLength - 3);
72
+ const total = ok.byteLength + tornShort.byteLength;
73
+ const buf = new Uint8Array(total);
74
+ buf.set(ok, 0);
75
+ buf.set(tornShort, ok.byteLength);
76
+ const decoded = decodeJournalStream(buf.buffer);
77
+ expect(decoded.length).toBe(1);
78
+ expect(decoded[0].txId).toBe(100);
79
+ });
80
+ it("rejects unknown kind code", () => {
81
+ const buf = encodeBytes(sample());
82
+ new DataView(buf.buffer).setUint8(12, 99);
83
+ expect(() => decodeJournalEntry(buf.buffer, 0)).toThrow(/Unknown journal entry kind code/);
84
+ });
85
+ it("preserves negative entity values (ephemeral / sentinel)", () => {
86
+ const entry = sample({ entity: -1 });
87
+ const buf = encodeBytes(entry);
88
+ const { entry: decoded } = decodeJournalEntry(buf.buffer, 0);
89
+ expect(decoded.entity).toBe(-1);
90
+ });
91
+ it("preserves a large positive entity id", () => {
92
+ const entry = sample({ entity: 0x7fff_fffe });
93
+ const buf = encodeBytes(entry);
94
+ const { entry: decoded } = decodeJournalEntry(buf.buffer, 0);
95
+ expect(decoded.entity).toBe(0x7fff_fffe);
96
+ });
97
+ it("returns a fresh, transferable ArrayBuffer (zero-copy worker handoff)", () => {
98
+ const buf = encodeJournalEntry(sample());
99
+ // Type guarantee: encodeJournalEntry returns ArrayBuffer (not
100
+ // SharedArrayBuffer / Uint8Array) so the call site can list
101
+ // it directly in postMessage's transfer set.
102
+ expect(buf).toBeInstanceOf(ArrayBuffer);
103
+ expect(buf.byteLength).toBe(JOURNAL_HEADER_BYTES + 4);
104
+ });
105
+ });
106
+ //# sourceMappingURL=journal-codec.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-codec.test.js","sourceRoot":"","sources":["../../src/journal/journal-codec.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Wire codes for each journal entry kind. This is the single source of
3
+ * truth — `JournalEntryKind` and `JournalEntryKindName` are both
4
+ * derived from it so they can never drift.
5
+ *
6
+ * insert - a new row was inserted into an archetype
7
+ * update - an existing row was updated
8
+ * delete - an entity was deleted
9
+ * migrate - an entity moved from one archetype to another
10
+ * commit - end-of-transaction marker. Carries no per-row payload;
11
+ * its presence at txId T tells the replayer that all
12
+ * entries for T are durable. Replay buffers data entries
13
+ * by txId and only applies a tx once its commit entry is
14
+ * seen — torn tails (incomplete tx never reached commit)
15
+ * are dropped wholesale, preserving transactional
16
+ * atomicity across crashes.
17
+ */
18
+ export declare const JournalEntryKindCode: {
19
+ readonly insert: 1;
20
+ readonly update: 2;
21
+ readonly delete: 3;
22
+ readonly migrate: 4;
23
+ readonly commit: 5;
24
+ };
25
+ export type JournalEntryKind = keyof typeof JournalEntryKindCode;
26
+ export declare const JournalEntryKindName: Readonly<Record<number, JournalEntryKind>>;
27
+ /**
28
+ * A single journal entry. Variable-length payloads (`bytes`) are JSON
29
+ * for variable-length columns, or empty for delete/migrate.
30
+ *
31
+ * Wire format (little-endian):
32
+ *
33
+ * u32 txId
34
+ * f64 timestampMs
35
+ * u8 kindCode
36
+ * i32 entity (signed; the affected entity id)
37
+ * u16 archetypeId (0 for delete entries — entity has no archetype)
38
+ * u32 rowIndex (0 for delete entries)
39
+ * u16 componentId (0 when not applicable, e.g. delete)
40
+ * u32 byteLen
41
+ * bytes... (byteLen bytes)
42
+ *
43
+ * Total fixed-header size: 29 bytes.
44
+ *
45
+ * `entity` is required for crash-recovery replay: after restoring the
46
+ * checkpoint snapshot, the journal carries the entity → (archetype, row)
47
+ * mapping for everything that happened since, plus the per-row column
48
+ * bytes needed to reconstruct any partially-written rows.
49
+ */
50
+ export interface JournalEntry {
51
+ readonly txId: number;
52
+ readonly timestampMs: number;
53
+ readonly kind: JournalEntryKind;
54
+ /** The entity affected by this entry. */
55
+ readonly entity: number;
56
+ readonly archetypeId: number;
57
+ readonly rowIndex: number;
58
+ /** Numeric id from the manifest's component intern table (0 = none). */
59
+ readonly componentId: number;
60
+ /** JSON-encoded payload for variable-length columns; empty otherwise. */
61
+ readonly bytes: Uint8Array;
62
+ }
63
+ export declare const JOURNAL_HEADER_BYTES = 29;
@@ -0,0 +1,28 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ /**
3
+ * Wire codes for each journal entry kind. This is the single source of
4
+ * truth — `JournalEntryKind` and `JournalEntryKindName` are both
5
+ * derived from it so they can never drift.
6
+ *
7
+ * insert - a new row was inserted into an archetype
8
+ * update - an existing row was updated
9
+ * delete - an entity was deleted
10
+ * migrate - an entity moved from one archetype to another
11
+ * commit - end-of-transaction marker. Carries no per-row payload;
12
+ * its presence at txId T tells the replayer that all
13
+ * entries for T are durable. Replay buffers data entries
14
+ * by txId and only applies a tx once its commit entry is
15
+ * seen — torn tails (incomplete tx never reached commit)
16
+ * are dropped wholesale, preserving transactional
17
+ * atomicity across crashes.
18
+ */
19
+ export const JournalEntryKindCode = {
20
+ insert: 1,
21
+ update: 2,
22
+ delete: 3,
23
+ migrate: 4,
24
+ commit: 5,
25
+ };
26
+ export const JournalEntryKindName = Object.fromEntries(Object.entries(JournalEntryKindCode).map(([name, code]) => [code, name]));
27
+ export const JOURNAL_HEADER_BYTES = 29;
28
+ //# sourceMappingURL=journal-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-entry.js","sourceRoot":"","sources":["../../src/journal/journal-entry.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAChC,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;CACH,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,WAAW,CAClD,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAC7B,CAAC;AAuChD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { PersistenceProvider } from "../provider/persistence-provider.js";
2
+ export interface NodeFsProviderOptions {
3
+ /**
4
+ * When `true`, delegates all storage I/O to a `node:worker_threads`
5
+ * worker so that file operations never block the event loop.
6
+ *
7
+ * When `false` (the default), runs storage operations in-process using
8
+ * `fs.promises` which is already non-blocking via libuv.
9
+ */
10
+ readonly worker?: boolean;
11
+ /**
12
+ * Override the worker bootstrap script URL. Only used when
13
+ * `worker: true`. Defaults to the built `node-worker-bootstrap.js`
14
+ * shipped alongside this package.
15
+ */
16
+ readonly workerScript?: URL;
17
+ }
18
+ /**
19
+ * Creates a Node.js persistence provider backed by `node:fs`.
20
+ *
21
+ * ```ts
22
+ * import { mount } from "@adobe/data-persistence";
23
+ * import { createNodeFsProvider } from "@adobe/data-persistence/node";
24
+ *
25
+ * const m = await mount(createNodeFsProvider("/tmp/my-db"), database);
26
+ * await m.service.load();
27
+ * // ...run app...
28
+ * await m.dispose();
29
+ * ```
30
+ *
31
+ * Pass `{ worker: true }` to move I/O off the calling thread into a
32
+ * dedicated `node:worker_threads` worker.
33
+ */
34
+ export declare const createNodeFsProvider: (root: string, options?: NodeFsProviderOptions) => PersistenceProvider;