@evolu/common 7.4.0 → 8.0.0-next.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 (251) hide show
  1. package/README.md +4 -61
  2. package/dist/src/Array.d.ts +343 -102
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +181 -85
  5. package/dist/src/Assert.d.ts +57 -11
  6. package/dist/src/Assert.d.ts.map +1 -1
  7. package/dist/src/Assert.js +47 -11
  8. package/dist/src/BigInt.d.ts +6 -1
  9. package/dist/src/BigInt.d.ts.map +1 -1
  10. package/dist/src/BigInt.js +5 -0
  11. package/dist/src/Brand.d.ts +40 -12
  12. package/dist/src/Brand.d.ts.map +1 -1
  13. package/dist/src/Brand.js +5 -0
  14. package/dist/src/Buffer.d.ts +6 -1
  15. package/dist/src/Buffer.d.ts.map +1 -1
  16. package/dist/src/Buffer.js +7 -2
  17. package/dist/src/Cache.d.ts +10 -2
  18. package/dist/src/Cache.d.ts.map +1 -1
  19. package/dist/src/Cache.js +6 -0
  20. package/dist/src/Callbacks.d.ts +10 -7
  21. package/dist/src/Callbacks.d.ts.map +1 -1
  22. package/dist/src/Callbacks.js +23 -13
  23. package/dist/src/Console.d.ts +361 -69
  24. package/dist/src/Console.d.ts.map +1 -1
  25. package/dist/src/Console.js +217 -117
  26. package/dist/src/Crypto.d.ts +70 -21
  27. package/dist/src/Crypto.d.ts.map +1 -1
  28. package/dist/src/Crypto.js +72 -27
  29. package/dist/src/Eq.d.ts +22 -2
  30. package/dist/src/Eq.d.ts.map +1 -1
  31. package/dist/src/Eq.js +21 -1
  32. package/dist/src/Error.d.ts +23 -12
  33. package/dist/src/Error.d.ts.map +1 -1
  34. package/dist/src/Error.js +27 -11
  35. package/dist/src/Function.d.ts +128 -56
  36. package/dist/src/Function.d.ts.map +1 -1
  37. package/dist/src/Function.js +118 -14
  38. package/dist/src/Identicon.d.ts +5 -0
  39. package/dist/src/Identicon.d.ts.map +1 -1
  40. package/dist/src/Identicon.js +6 -1
  41. package/dist/src/Lookup.d.ts +160 -0
  42. package/dist/src/Lookup.d.ts.map +1 -0
  43. package/dist/src/Lookup.js +192 -0
  44. package/dist/src/Microtask.d.ts +21 -0
  45. package/dist/src/Microtask.d.ts.map +1 -0
  46. package/dist/src/Microtask.js +37 -0
  47. package/dist/src/Number.d.ts +18 -4
  48. package/dist/src/Number.d.ts.map +1 -1
  49. package/dist/src/Number.js +23 -1
  50. package/dist/src/Object.d.ts +110 -5
  51. package/dist/src/Object.d.ts.map +1 -1
  52. package/dist/src/Object.js +108 -5
  53. package/dist/src/Option.d.ts +58 -0
  54. package/dist/src/Option.d.ts.map +1 -0
  55. package/dist/src/Option.js +43 -0
  56. package/dist/src/Order.d.ts +5 -0
  57. package/dist/src/Order.d.ts.map +1 -1
  58. package/dist/src/Order.js +8 -3
  59. package/dist/src/Platform.d.ts +36 -2
  60. package/dist/src/Platform.d.ts.map +1 -1
  61. package/dist/src/Platform.js +10 -6
  62. package/dist/src/Polyfills.d.ts +27 -0
  63. package/dist/src/Polyfills.d.ts.map +1 -0
  64. package/dist/src/Polyfills.js +299 -0
  65. package/dist/src/Random.d.ts +18 -7
  66. package/dist/src/Random.d.ts.map +1 -1
  67. package/dist/src/Random.js +9 -7
  68. package/dist/src/Redacted.d.ts +7 -4
  69. package/dist/src/Redacted.d.ts.map +1 -1
  70. package/dist/src/Redacted.js +5 -0
  71. package/dist/src/Ref.d.ts +31 -16
  72. package/dist/src/Ref.d.ts.map +1 -1
  73. package/dist/src/Ref.js +35 -7
  74. package/dist/src/RefCount.d.ts +62 -0
  75. package/dist/src/RefCount.d.ts.map +1 -0
  76. package/dist/src/RefCount.js +83 -0
  77. package/dist/src/Relation.d.ts +84 -29
  78. package/dist/src/Relation.d.ts.map +1 -1
  79. package/dist/src/Relation.js +83 -105
  80. package/dist/src/Resource.d.ts +263 -0
  81. package/dist/src/Resource.d.ts.map +1 -0
  82. package/dist/src/Resource.js +389 -0
  83. package/dist/src/Result.d.ts +390 -374
  84. package/dist/src/Result.d.ts.map +1 -1
  85. package/dist/src/Result.js +142 -70
  86. package/dist/src/Schedule.d.ts +953 -0
  87. package/dist/src/Schedule.d.ts.map +1 -0
  88. package/dist/src/Schedule.js +1199 -0
  89. package/dist/src/Set.d.ts +181 -0
  90. package/dist/src/Set.d.ts.map +1 -0
  91. package/dist/src/Set.js +137 -0
  92. package/dist/src/Skiplist.d.ts +6 -1
  93. package/dist/src/Skiplist.d.ts.map +1 -1
  94. package/dist/src/Skiplist.js +5 -0
  95. package/dist/src/Sqlite.d.ts +160 -60
  96. package/dist/src/Sqlite.d.ts.map +1 -1
  97. package/dist/src/Sqlite.js +290 -190
  98. package/dist/src/Store.d.ts +36 -28
  99. package/dist/src/Store.d.ts.map +1 -1
  100. package/dist/src/Store.js +55 -15
  101. package/dist/src/String.d.ts +5 -0
  102. package/dist/src/String.d.ts.map +1 -1
  103. package/dist/src/String.js +5 -0
  104. package/dist/src/Task.d.ts +2263 -423
  105. package/dist/src/Task.d.ts.map +1 -1
  106. package/dist/src/Task.js +1488 -348
  107. package/dist/src/Test.d.ts +122 -0
  108. package/dist/src/Test.d.ts.map +1 -0
  109. package/dist/src/Test.js +66 -0
  110. package/dist/src/Time.d.ts +201 -48
  111. package/dist/src/Time.d.ts.map +1 -1
  112. package/dist/src/Time.js +190 -86
  113. package/dist/src/Tracer.d.ts +48 -0
  114. package/dist/src/Tracer.d.ts.map +1 -0
  115. package/dist/src/Tracer.js +6 -0
  116. package/dist/src/Type.d.ts +582 -209
  117. package/dist/src/Type.d.ts.map +1 -1
  118. package/dist/src/Type.js +362 -240
  119. package/dist/src/Types.d.ts +160 -6
  120. package/dist/src/Types.d.ts.map +1 -1
  121. package/dist/src/Types.js +22 -2
  122. package/dist/src/WebSocket.d.ts +113 -58
  123. package/dist/src/WebSocket.d.ts.map +1 -1
  124. package/dist/src/WebSocket.js +210 -118
  125. package/dist/src/Worker.d.ts +245 -60
  126. package/dist/src/Worker.d.ts.map +1 -1
  127. package/dist/src/Worker.js +220 -64
  128. package/dist/src/index.d.ts +25 -3
  129. package/dist/src/index.d.ts.map +1 -1
  130. package/dist/src/index.js +19 -3
  131. package/dist/src/local-first/Db.d.ts +24 -213
  132. package/dist/src/local-first/Db.d.ts.map +1 -1
  133. package/dist/src/local-first/Db.js +622 -293
  134. package/dist/src/local-first/Error.d.ts +12 -0
  135. package/dist/src/local-first/Error.d.ts.map +1 -0
  136. package/dist/src/local-first/Error.js +6 -0
  137. package/dist/src/local-first/Evolu.d.ts +330 -285
  138. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  139. package/dist/src/local-first/Evolu.js +472 -402
  140. package/dist/src/local-first/LocalAuth.d.ts +10 -10
  141. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  142. package/dist/src/local-first/LocalAuth.js +6 -1
  143. package/dist/src/local-first/Owner.d.ts +70 -27
  144. package/dist/src/local-first/Owner.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.js +27 -14
  146. package/dist/src/local-first/Protocol.d.ts +58 -50
  147. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  148. package/dist/src/local-first/Protocol.js +253 -155
  149. package/dist/src/local-first/Query.d.ts +133 -43
  150. package/dist/src/local-first/Query.d.ts.map +1 -1
  151. package/dist/src/local-first/Query.js +139 -90
  152. package/dist/src/local-first/Relay.d.ts +18 -38
  153. package/dist/src/local-first/Relay.d.ts.map +1 -1
  154. package/dist/src/local-first/Relay.js +59 -171
  155. package/dist/src/local-first/Schema.d.ts +139 -144
  156. package/dist/src/local-first/Schema.d.ts.map +1 -1
  157. package/dist/src/local-first/Schema.js +78 -163
  158. package/dist/src/local-first/Shared.d.ts +125 -0
  159. package/dist/src/local-first/Shared.d.ts.map +1 -0
  160. package/dist/src/local-first/Shared.js +569 -0
  161. package/dist/src/local-first/Storage.d.ts +50 -53
  162. package/dist/src/local-first/Storage.d.ts.map +1 -1
  163. package/dist/src/local-first/Storage.js +121 -173
  164. package/dist/src/local-first/Timestamp.d.ts +28 -35
  165. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  166. package/dist/src/local-first/Timestamp.js +24 -25
  167. package/dist/src/local-first/index.d.ts +2 -15
  168. package/dist/src/local-first/index.d.ts.map +1 -1
  169. package/dist/src/local-first/index.js +2 -15
  170. package/package.json +36 -26
  171. package/src/Array.ts +467 -106
  172. package/src/Assert.ts +87 -12
  173. package/src/BigInt.ts +7 -1
  174. package/src/Brand.ts +41 -12
  175. package/src/Buffer.ts +10 -4
  176. package/src/Cache.ts +11 -2
  177. package/src/Callbacks.ts +33 -23
  178. package/src/Console.ts +567 -178
  179. package/src/Crypto.ts +111 -62
  180. package/src/Eq.ts +30 -3
  181. package/src/Error.ts +50 -34
  182. package/src/Function.ts +140 -68
  183. package/src/Identicon.ts +7 -1
  184. package/src/Lookup.ts +415 -0
  185. package/src/Microtask.ts +58 -0
  186. package/src/Number.ts +40 -7
  187. package/src/Object.ts +155 -16
  188. package/src/Option.ts +74 -0
  189. package/src/Order.ts +11 -3
  190. package/src/Platform.ts +43 -7
  191. package/src/Polyfills.ts +465 -0
  192. package/src/Random.ts +25 -11
  193. package/src/Redacted.ts +8 -4
  194. package/src/Ref.ts +72 -21
  195. package/src/RefCount.ts +170 -0
  196. package/src/Relation.ts +188 -136
  197. package/src/Resource.ts +864 -0
  198. package/src/Result.ts +548 -381
  199. package/src/Schedule.ts +1471 -0
  200. package/src/Set.ts +247 -0
  201. package/src/Skiplist.ts +7 -1
  202. package/src/Sqlite.ts +409 -304
  203. package/src/Store.ts +94 -48
  204. package/src/String.ts +6 -0
  205. package/src/Task.ts +3685 -740
  206. package/src/Test.ts +162 -0
  207. package/src/Time.ts +348 -145
  208. package/src/Tracer.ts +54 -0
  209. package/src/Type.ts +1064 -630
  210. package/src/Types.ts +202 -7
  211. package/src/WebSocket.ts +311 -178
  212. package/src/Worker.ts +527 -147
  213. package/src/index.ts +74 -3
  214. package/src/local-first/Db.ts +871 -597
  215. package/src/local-first/Error.ts +17 -0
  216. package/src/local-first/Evolu.ts +884 -823
  217. package/src/local-first/LocalAuth.ts +10 -10
  218. package/src/local-first/Owner.ts +94 -42
  219. package/src/local-first/Protocol.ts +440 -303
  220. package/src/local-first/Query.ts +243 -194
  221. package/src/local-first/Relay.ts +91 -252
  222. package/src/local-first/Schema.ts +284 -394
  223. package/src/local-first/Shared.ts +932 -0
  224. package/src/local-first/Storage.ts +209 -282
  225. package/src/local-first/Timestamp.ts +38 -45
  226. package/src/local-first/index.ts +2 -16
  227. package/LICENSE +0 -21
  228. package/dist/src/Instances.d.ts +0 -34
  229. package/dist/src/Instances.d.ts.map +0 -1
  230. package/dist/src/Instances.js +0 -44
  231. package/dist/src/Resources.d.ts +0 -118
  232. package/dist/src/Resources.d.ts.map +0 -1
  233. package/dist/src/Resources.js +0 -197
  234. package/dist/src/local-first/Platform.d.ts +0 -25
  235. package/dist/src/local-first/Platform.d.ts.map +0 -1
  236. package/dist/src/local-first/Platform.js +0 -1
  237. package/dist/src/local-first/Public.d.ts +0 -22
  238. package/dist/src/local-first/Public.d.ts.map +0 -1
  239. package/dist/src/local-first/Public.js +0 -15
  240. package/dist/src/local-first/PublicKysely.d.ts +0 -148
  241. package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
  242. package/dist/src/local-first/PublicKysely.js +0 -184
  243. package/dist/src/local-first/Sync.d.ts +0 -112
  244. package/dist/src/local-first/Sync.d.ts.map +0 -1
  245. package/dist/src/local-first/Sync.js +0 -529
  246. package/src/Instances.ts +0 -90
  247. package/src/Resources.ts +0 -367
  248. package/src/local-first/Platform.ts +0 -27
  249. package/src/local-first/Public.ts +0 -42
  250. package/src/local-first/PublicKysely.ts +0 -239
  251. package/src/local-first/Sync.ts +0 -960
@@ -1,24 +1,45 @@
1
+ /**
2
+ * Encrypted storage layer for local-first data.
3
+ *
4
+ * @module
5
+ */
1
6
  import { sha256 } from "@noble/hashes/sha2.js";
2
- import { firstInArray, isNonEmptyReadonlyArray, } from "../Array.js";
7
+ import { firstInArray, isNonEmptyArray } from "../Array.js";
3
8
  import { assert } from "../Assert.js";
4
9
  import { concatBytes } from "../Buffer.js";
5
10
  import { decrement } from "../Number.js";
6
11
  import { err, ok } from "../Result.js";
7
12
  import { sql, SqliteValue } from "../Sqlite.js";
13
+ import { Millis } from "../Time.js";
8
14
  import { Boolean, brand, Id, NonNegativeInt, nullOr, object, PositiveInt, record, String, } from "../Type.js";
15
+ import { OwnerId, OwnerWriteKey } from "./Owner.js";
9
16
  import { systemColumnsWithId } from "./Schema.js";
10
- import { orderTimestampBytes } from "./Timestamp.js";
11
- export const fingerprintSize = NonNegativeInt.orThrow(12);
17
+ import { createTimestamp, orderTimestampBytes, Timestamp, TimestampBytes, } from "./Timestamp.js";
18
+ export const fingerprintSize = /*#__PURE__*/ NonNegativeInt.orThrow(12);
12
19
  /** A fingerprint of an empty range. */
13
- export const zeroFingerprint = new Uint8Array(fingerprintSize);
14
- export const InfiniteUpperBound = Symbol("InfiniteUpperBound");
20
+ export const zeroFingerprint = /*#__PURE__*/ new Uint8Array(fingerprintSize);
21
+ export const InfiniteUpperBound = /*#__PURE__*/ Symbol("evolu.local-first.Storage.InfiniteUpperBound");
15
22
  export const RangeType = {
16
23
  Fingerprint: 1,
17
24
  Skip: 0,
18
25
  Timestamps: 2,
19
26
  };
20
- export const DbChangeValues = record(String, SqliteValue);
21
- export const ValidDbChangeValues = brand("ValidDbChangeValues", DbChangeValues, (value) => {
27
+ /** Test helper for creating a simple {@link CrdtMessage}. */
28
+ export const testCreateCrdtMessage = (id, millis, name) => ({
29
+ timestamp: createTimestamp({
30
+ millis: Millis.orThrow(millis),
31
+ counter: 0,
32
+ }),
33
+ change: DbChange.orThrow({
34
+ table: "testTable",
35
+ id,
36
+ values: { name },
37
+ isInsert: true,
38
+ isDelete: false,
39
+ }),
40
+ });
41
+ export const DbChangeValues = /*#__PURE__*/ record(String, SqliteValue);
42
+ export const ValidDbChangeValues = /*#__PURE__*/ brand("ValidDbChangeValues", DbChangeValues, (value) => {
22
43
  const invalidColumns = systemColumnsWithId.filter((key) => key in value);
23
44
  if (invalidColumns.length > 0)
24
45
  return err({
@@ -32,12 +53,12 @@ export const ValidDbChangeValues = brand("ValidDbChangeValues", DbChangeValues,
32
53
  * A DbChange is a change to a table row. Together with a unique
33
54
  * {@link Timestamp}, it forms a {@link CrdtMessage}.
34
55
  */
35
- export const DbChange = object({
56
+ export const DbChange = /*#__PURE__*/ object({
36
57
  table: String,
37
58
  id: Id,
38
59
  values: ValidDbChangeValues,
39
60
  isInsert: Boolean,
40
- isDelete: nullOr(Boolean),
61
+ isDelete: /*#__PURE__*/ nullOr(Boolean),
41
62
  });
42
63
  /**
43
64
  * Creates a {@link BaseSqliteStorage} implementation.
@@ -52,124 +73,80 @@ export const DbChange = object({
52
73
  * doesn't persist between requests. While not extensively tested in all these
53
74
  * environments yet, the stateless design should work well across them.
54
75
  */
55
- export const createBaseSqliteStorage = (deps) => (config) => {
56
- return {
57
- insertTimestamp: (ownerId, timestamp, strategy) => {
58
- const level = randomSkiplistLevel(deps);
59
- return insertTimestamp(deps)(ownerId, timestamp, level, strategy);
60
- },
61
- getExistingTimestamps: (ownerIdBytes, timestampsBytes) => {
62
- const concatenatedTimestamps = concatBytes(...timestampsBytes);
63
- const result = deps.sqlite.exec(sql `
64
- with recursive
65
- split_timestamps(timestampBytes, pos) as (
66
- select
67
- substr(${concatenatedTimestamps}, 1, 16),
68
- 17 as pos
69
- union all
70
- select
71
- substr(${concatenatedTimestamps}, pos, 16),
72
- pos + 16
73
- from split_timestamps
74
- where pos <= length(${concatenatedTimestamps})
75
- )
76
- select s.timestampBytes
77
- from
78
- split_timestamps s
79
- join evolu_timestamp t
80
- on t.ownerId = ${ownerIdBytes} and s.timestampBytes = t.t;
81
- `);
82
- if (!result.ok)
83
- return result;
84
- return ok(result.value.rows.map((row) => row.timestampBytes));
85
- },
86
- getSize: (ownerId) => {
87
- const size = getSize(deps)(ownerId);
88
- if (!size.ok) {
89
- config.onStorageError(size.error);
90
- return null;
91
- }
92
- return size.value;
93
- },
94
- fingerprint: (ownerId, begin, end) => {
95
- assertBeginEnd(begin, end);
96
- const result = fingerprint(deps)(ownerId, begin, end);
97
- if (!result.ok) {
98
- config.onStorageError(result.error);
99
- return null;
100
- }
101
- return result.value;
102
- },
103
- fingerprintRanges: (ownerId, buckets, upperBound) => {
104
- const ranges = fingerprintRanges(deps)(ownerId, buckets, upperBound);
105
- if (!ranges.ok) {
106
- config.onStorageError(ranges.error);
107
- return null;
108
- }
109
- return ranges.value;
110
- },
111
- findLowerBound: (ownerId, begin, end, upperBound) => {
112
- const lowerBound = findLowerBound(deps)(ownerId, begin, end, upperBound);
113
- if (!lowerBound.ok) {
114
- config.onStorageError(lowerBound.error);
115
- return null;
116
- }
117
- return lowerBound.value;
118
- },
119
- iterate: (ownerId, begin, end, callback) => {
120
- assertBeginEnd(begin, end);
121
- const length = end - begin;
122
- if (length === 0)
123
- return;
124
- // This is much faster than SQL limit with offset.
125
- const first = getTimestampByIndex(deps)(ownerId, begin);
126
- if (!first.ok) {
127
- config.onStorageError(first.error);
128
- return;
129
- }
130
- if (!callback(first.value, begin))
131
- return;
132
- if (length === 1)
133
- return;
134
- /**
135
- * TODO: In rare cases, we might overfetch a lot of rows here, but we
136
- * don't have real usage numbers yet. Fetching one row at a time would
137
- * probably be slower in almost all cases. In the future, we should
138
- * fetch in chunks (e.g., 1,000 rows at a time). For now, consider
139
- * logging unused rows to gather data and calculate an average, then use
140
- * that information to determine an optimal chunk size. Before
141
- * implementing chunking, be sure to run performance tests (including
142
- * fetching one by one).
143
- */
144
- const result = deps.sqlite.exec(sql `
145
- select t
146
- from evolu_timestamp
147
- where ownerId = ${ownerId} and t > ${first.value}
148
- order by t
149
- limit ${length - 1};
150
- `);
151
- if (!result.ok) {
152
- config.onStorageError(result.error);
76
+ export const createBaseSqliteStorage = (deps) => ({
77
+ insertTimestamp: (ownerId, timestamp, strategy) => {
78
+ const level = randomSkiplistLevel(deps);
79
+ insertTimestamp(deps)(ownerId, timestamp, level, strategy);
80
+ },
81
+ getExistingTimestamps: (ownerIdBytes, timestampsBytes) => {
82
+ const concatenatedTimestamps = concatBytes(...timestampsBytes);
83
+ const result = deps.sqlite.exec(sql `
84
+ with recursive
85
+ split_timestamps(timestampBytes, pos) as (
86
+ select
87
+ substr(${concatenatedTimestamps}, 1, 16),
88
+ 17 as pos
89
+ union all
90
+ select
91
+ substr(${concatenatedTimestamps}, pos, 16),
92
+ pos + 16
93
+ from split_timestamps
94
+ where pos <= length(${concatenatedTimestamps})
95
+ )
96
+ select s.timestampBytes
97
+ from
98
+ split_timestamps s
99
+ join evolu_timestamp t
100
+ on t.ownerId = ${ownerIdBytes} and s.timestampBytes = t.t;
101
+ `);
102
+ return result.rows.map((row) => row.timestampBytes);
103
+ },
104
+ getSize: getSize(deps),
105
+ fingerprint: (ownerId, begin, end) => {
106
+ assertBeginEnd(begin, end);
107
+ return fingerprint(deps)(ownerId, begin, end);
108
+ },
109
+ fingerprintRanges: fingerprintRanges(deps),
110
+ findLowerBound: (ownerId, begin, end, upperBound) => findLowerBound(deps)(ownerId, begin, end, upperBound),
111
+ iterate: (ownerId, begin, end, callback) => {
112
+ assertBeginEnd(begin, end);
113
+ const length = end - begin;
114
+ if (length === 0)
115
+ return;
116
+ // This is much faster than SQL limit with offset.
117
+ const first = getTimestampByIndex(deps)(ownerId, begin);
118
+ if (!callback(first, begin))
119
+ return;
120
+ if (length === 1)
121
+ return;
122
+ /**
123
+ * TODO: In rare cases, we might overfetch a lot of rows here, but we don't
124
+ * have real usage numbers yet. Fetching one row at a time would probably be
125
+ * slower in almost all cases. In the future, we should fetch in chunks
126
+ * (e.g., 1,000 rows at a time). For now, consider logging unused rows to
127
+ * gather data and calculate an average, then use that information to
128
+ * determine an optimal chunk size. Before implementing chunking, be sure to
129
+ * run performance tests (including fetching one by one).
130
+ */
131
+ const result = deps.sqlite.exec(sql `
132
+ select t
133
+ from evolu_timestamp
134
+ where ownerId = ${ownerId} and t > ${first}
135
+ order by t
136
+ limit ${length - 1};
137
+ `);
138
+ for (let i = 0; i < result.rows.length; i++) {
139
+ const index = NonNegativeInt.orThrow(begin + 1 + i);
140
+ if (!callback(result.rows[i].t, index))
153
141
  return;
154
- }
155
- for (let i = 0; i < result.value.rows.length; i++) {
156
- const index = NonNegativeInt.orThrow(begin + 1 + i);
157
- if (!callback(result.value.rows[i].t, index))
158
- return;
159
- }
160
- },
161
- deleteOwner: (ownerId) => {
162
- const result = deps.sqlite.exec(sql `
163
- delete from evolu_timestamp where ownerId = ${ownerId};
164
- `);
165
- if (!result.ok) {
166
- config.onStorageError(result.error);
167
- return false;
168
- }
169
- return true;
170
- },
171
- };
172
- };
142
+ }
143
+ },
144
+ deleteOwner: (ownerId) => {
145
+ deps.sqlite.exec(sql `
146
+ delete from evolu_timestamp where ownerId = ${ownerId};
147
+ `);
148
+ },
149
+ });
173
150
  const assertBeginEnd = (begin, end) => {
174
151
  assert(begin <= end, "invalid begin or end");
175
152
  };
@@ -233,11 +210,8 @@ export const createBaseSqliteStorageTables = (deps) => {
233
210
  strict;
234
211
  `,
235
212
  ]) {
236
- const result = deps.sqlite.exec(query);
237
- if (!result.ok)
238
- return result;
213
+ deps.sqlite.exec(query);
239
214
  }
240
- return ok();
241
215
  };
242
216
  /**
243
217
  * Determines the insertion strategy for a timestamp based on its position
@@ -772,11 +746,8 @@ const insertTimestamp = (deps) => (ownerId, timestamp, level, strategy) => {
772
746
  break;
773
747
  }
774
748
  for (const query of queries) {
775
- const result = deps.sqlite.exec(query);
776
- if (!result.ok)
777
- return result;
749
+ deps.sqlite.exec(query);
778
750
  }
779
- return ok();
780
751
  };
781
752
  export const timestampBytesToFingerprint = (timestamp) => {
782
753
  const hash = sha256(timestamp).slice(0, fingerprintSize);
@@ -870,14 +841,12 @@ const getSize = (deps) => (ownerId) => {
870
841
  select sum(c) as size
871
842
  from sc;
872
843
  `);
873
- if (!result.ok)
874
- return result;
875
- return ok(result.value.rows[0].size);
844
+ return result.rows[0].size;
876
845
  };
877
846
  const findLowerBound = (deps) => (ownerId, begin, end, upperBound) => {
878
847
  assertBeginEnd(begin, end);
879
848
  if (end === 0 || begin === end || upperBound === InfiniteUpperBound) {
880
- return ok(end);
849
+ return end;
881
850
  }
882
851
  const result = deps.sqlite.exec(sql.prepared `
883
852
  select t
@@ -886,16 +855,12 @@ const findLowerBound = (deps) => (ownerId, begin, end, upperBound) => {
886
855
  order by t
887
856
  limit 1;
888
857
  `);
889
- if (!result.ok)
890
- return result;
891
- if (result.value.rows.length === 0) {
892
- return ok(end);
858
+ if (result.rows.length === 0) {
859
+ return end;
893
860
  }
894
- const count = getTimestampCount(deps)(ownerId, result.value.rows[0].t);
895
- if (!count.ok)
896
- return count;
861
+ const count = getTimestampCount(deps)(ownerId, result.rows[0].t);
897
862
  // `decrement` converts a count to an index.
898
- return ok(NonNegativeInt.orThrow(decrement(count.value)));
863
+ return NonNegativeInt.orThrow(decrement(count));
899
864
  };
900
865
  const getTimestampCount = (deps) => (ownerId, timestamp) => {
901
866
  const result = deps.sqlite.exec(sql.prepared `
@@ -939,9 +904,7 @@ const getTimestampCount = (deps) => (ownerId, timestamp) => {
939
904
  select sum(tc) as count
940
905
  from sc;
941
906
  `);
942
- if (!result.ok)
943
- return result;
944
- return ok(result.value.rows[0].count);
907
+ return result.rows[0].count;
945
908
  };
946
909
  /**
947
910
  * TODO: We reuse {@link fingerprintRanges}, which returns upper bound, which we
@@ -950,19 +913,13 @@ const getTimestampCount = (deps) => (ownerId, timestamp) => {
950
913
  const fingerprint = (deps) => (ownerId, begin, end) => {
951
914
  // There is no need to fingerprint an empty range.
952
915
  if (end - begin === 0) {
953
- return ok(zeroFingerprint);
916
+ return zeroFingerprint;
954
917
  }
955
918
  if (begin === 0) {
956
- const result = fingerprintRanges(deps)(ownerId, [end]);
957
- if (!result.ok)
958
- return result;
959
- return ok(result.value[0].fingerprint);
919
+ return fingerprintRanges(deps)(ownerId, [end])[0].fingerprint;
960
920
  }
961
921
  // We should have a param to skip the first result.
962
- const result = fingerprintRanges(deps)(ownerId, [begin, end]);
963
- if (!result.ok)
964
- return result;
965
- return ok(result.value[1].fingerprint);
922
+ return fingerprintRanges(deps)(ownerId, [begin, end])[1].fingerprint;
966
923
  };
967
924
  /**
968
925
  * First, check this: https://logperiodic.com/rbsr.html#tree-friendly-functions
@@ -1084,9 +1041,7 @@ const fingerprintRanges = (deps) => (ownerId, buckets, upperBound = InfiniteUppe
1084
1041
  select b, cast(h1 as text) as h1, cast(h2 as text) as h2
1085
1042
  from c3;
1086
1043
  `);
1087
- if (!result.ok)
1088
- return result;
1089
- const fingerprintRanges = result.value.rows.map((row, i, arr) => ({
1044
+ const fingerprintRanges = result.rows.map((row, i, arr) => ({
1090
1045
  type: RangeType.Fingerprint,
1091
1046
  upperBound: i === arr.length - 1 ? upperBound : row.b,
1092
1047
  fingerprint: sqliteFingerprintToFingerprint([
@@ -1094,7 +1049,7 @@ const fingerprintRanges = (deps) => (ownerId, buckets, upperBound = InfiniteUppe
1094
1049
  row.h2,
1095
1050
  ]),
1096
1051
  }));
1097
- return ok(fingerprintRanges);
1052
+ return fingerprintRanges;
1098
1053
  };
1099
1054
  // XOR in SQLite
1100
1055
  const x = (a, b) => sql.raw(`(${a} | ${b}) - (${a} & ${b})`);
@@ -1170,9 +1125,7 @@ export const getTimestampByIndex = (deps) => (ownerId, index) => {
1170
1125
  from fi
1171
1126
  where ic == ${index + 1};
1172
1127
  `);
1173
- if (!result.ok)
1174
- return result;
1175
- return ok(result.value.rows[0].pt);
1128
+ return result.rows[0].pt;
1176
1129
  };
1177
1130
  /** Retrieves usage information for an owner from the evolu_usage table. */
1178
1131
  export const getOwnerUsage = (deps) => (ownerIdBytes, initialTimestamp) => {
@@ -1181,16 +1134,14 @@ export const getOwnerUsage = (deps) => (ownerIdBytes, initialTimestamp) => {
1181
1134
  from evolu_usage
1182
1135
  where ownerId = ${ownerIdBytes};
1183
1136
  `);
1184
- if (!result.ok)
1185
- return result;
1186
- if (!isNonEmptyReadonlyArray(result.value.rows)) {
1137
+ if (!isNonEmptyArray(result.rows)) {
1187
1138
  return ok({
1188
1139
  storedBytes: null,
1189
1140
  firstTimestamp: initialTimestamp,
1190
1141
  lastTimestamp: initialTimestamp,
1191
1142
  });
1192
1143
  }
1193
- const row = firstInArray(result.value.rows);
1144
+ const row = firstInArray(result.rows);
1194
1145
  assert(row.firstTimestamp, "not null");
1195
1146
  assert(row.lastTimestamp, "not null");
1196
1147
  return ok({
@@ -1206,7 +1157,7 @@ export const getOwnerUsage = (deps) => (ownerIdBytes, initialTimestamp) => {
1206
1157
  * processing messages.
1207
1158
  */
1208
1159
  export const updateOwnerUsage = (deps) => (ownerIdBytes, storedBytes, firstTimestamp, lastTimestamp) => {
1209
- const result = deps.sqlite.exec(sql `
1160
+ deps.sqlite.exec(sql `
1210
1161
  insert into evolu_usage
1211
1162
  ("ownerId", "storedBytes", "firstTimestamp", "lastTimestamp")
1212
1163
  values
@@ -1217,7 +1168,4 @@ export const updateOwnerUsage = (deps) => (ownerIdBytes, storedBytes, firstTimes
1217
1168
  firstTimestamp = ${firstTimestamp},
1218
1169
  lastTimestamp = ${lastTimestamp};
1219
1170
  `);
1220
- if (!result.ok)
1221
- return result;
1222
- return ok();
1223
1171
  };
@@ -1,8 +1,14 @@
1
- import { RandomBytesDep } from "../Crypto.js";
2
- import { Order } from "../Order.js";
3
- import { Result } from "../Result.js";
4
- import { TimeDep } from "../Time.js";
5
- import { DateIso, InferType } from "../Type.js";
1
+ /**
2
+ * Hybrid logical clock timestamps for CRDT ordering.
3
+ *
4
+ * @module
5
+ */
6
+ import type { RandomBytesDep } from "../Crypto.js";
7
+ import type { Order } from "../Order.js";
8
+ import type { Result } from "../Result.js";
9
+ import type { TimeDep } from "../Time.js";
10
+ import { Millis } from "../Time.js";
11
+ import type { DateIso, InferType, Typed } from "../Type.js";
6
12
  export interface TimestampConfig {
7
13
  /**
8
14
  * Maximum physical clock drift allowed in ms.
@@ -11,38 +17,21 @@ export interface TimestampConfig {
11
17
  */
12
18
  readonly maxDrift: number;
13
19
  }
20
+ /** Default value for {@link TimestampConfig.maxDrift}. */
21
+ export declare const defaultTimestampMaxDrift: number;
14
22
  export interface TimestampConfigDep {
15
23
  readonly timestampConfig: TimestampConfig;
16
24
  }
17
25
  export type TimestampError = TimestampDriftError | TimestampCounterOverflowError | TimestampTimeOutOfRangeError;
18
- export interface TimestampDriftError {
19
- readonly type: "TimestampDriftError";
26
+ export interface TimestampDriftError extends Typed<"TimestampDriftError"> {
20
27
  readonly next: Millis;
21
28
  readonly now: Millis;
22
29
  }
23
- export interface TimestampCounterOverflowError {
24
- readonly type: "TimestampCounterOverflowError";
30
+ export interface TimestampCounterOverflowError extends Typed<"TimestampCounterOverflowError"> {
25
31
  }
26
- export interface TimestampTimeOutOfRangeError {
27
- readonly type: "TimestampTimeOutOfRangeError";
32
+ export interface TimestampTimeOutOfRangeError extends Typed<"TimestampTimeOutOfRangeError"> {
28
33
  }
29
- /**
30
- * Millis is a timestamp in milliseconds, like `Date.now()`, but limited to the
31
- * maximum value representable in 6 bytes (281474976710655) minus 1 (reserved
32
- * for infinity). This enables more efficient binary serialization, saving 2
33
- * bytes compared to the typical 8-byte (64-bit) timestamp representation.
34
- *
35
- * This limit is enforced to prevent data corruption. If a device's clock
36
- * exceeds this range, Evolu will stop saving data until the clock is
37
- * corrected.
38
- *
39
- * `new Date(281474976710654).toString()` = Tue Aug 02 10889 07:31:49
40
- */
41
- export declare const Millis: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").IntError | import("../Type.js").NumberError>, `LessThanOrEqualTo${number}`, import("../Type.js").LessThanOrEqualToError<number>, import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError>, "Millis", import("../Type.js").BrandWithoutRefineError<"Millis", import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError | import("../Type.js").LessThanOrEqualToError<number>>, never>;
42
- export type Millis = typeof Millis.Type;
43
- export declare const minMillis: Millis;
44
- export declare const maxMillis: Millis;
45
- export declare const Counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").IntError | import("../Type.js").NumberError>, "LessThanOrEqualTo65535", import("../Type.js").LessThanOrEqualToError<65535>, import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError>, "Counter", import("../Type.js").BrandWithoutRefineError<"Counter", import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError | import("../Type.js").LessThanOrEqualToError<65535>>, never>;
34
+ export declare const Counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").NumberError | import("../Type.js").IntError>, "LessThanOrEqualTo65535", import("../Type.js").LessThanOrEqualToError<65535>, import("../Type.js").NumberError | import("../Type.js").NonNegativeError | import("../Type.js").IntError>, "Counter", import("../Type.js").BrandWithoutRefineError<"Counter", import("../Type.js").NumberError | import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").LessThanOrEqualToError<65535>>, never>;
46
35
  export type Counter = typeof Counter.Type;
47
36
  export declare const minCounter: Counter;
48
37
  export declare const maxCounter: Counter;
@@ -81,7 +70,7 @@ export declare const maxNodeId: NodeId;
81
70
  * Timestamps serve as globally unique, causally ordered identifiers for CRDT
82
71
  * messages in Evolu's sync protocol.
83
72
  *
84
- * ### Why Hybrid Logical Clocks
73
+ * ## Why Hybrid Logical Clocks
85
74
  *
86
75
  * Evolu uses Hybrid Logical Clocks (HLC), which combine physical time (millis)
87
76
  * with a logical counter. This hybrid approach preserves causality like logical
@@ -106,14 +95,14 @@ export declare const maxNodeId: NodeId;
106
95
  * configuration protects against buggy clocks and prevents problematic
107
96
  * future-dated entries from propagating through the network.
108
97
  *
109
- * ### References
98
+ * ## References
110
99
  *
111
100
  * - https://muratbuffalo.blogspot.com/2014/07/hybrid-logical-clocks.html
112
101
  * - https://sergeiturukin.com/2017/06/26/hybrid-logical-clocks.html
113
102
  * - https://jaredforsyth.com/posts/hybrid-logical-clocks/
114
103
  * - https://willowprotocol.org/more/timestamps_really/index.html
115
104
  *
116
- * ### Privacy Considerations
105
+ * ## Privacy Considerations
117
106
  *
118
107
  * Timestamps are metadata visible to relays and collaborators. While it can be
119
108
  * considered a privacy leak, let us explain why it's necessary, and how to
@@ -130,17 +119,21 @@ export declare const maxNodeId: NodeId;
130
119
  * 2. Periodically and randomly flush messages to sync tables
131
120
  *
132
121
  * **Trade-off:** It breaks real-time collaboration.
122
+ *
123
+ * Another technique is generating fake random activity (dummy messages) to mask
124
+ * real usage patterns. This preserves real-time collaboration but increases
125
+ * storage and bandwidth usage.
133
126
  */
134
127
  export declare const Timestamp: import("../Type.js").ObjectType<{
135
- millis: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").IntError | import("../Type.js").NumberError>, `LessThanOrEqualTo${number}`, import("../Type.js").LessThanOrEqualToError<number>, import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError>, "Millis", import("../Type.js").BrandWithoutRefineError<"Millis", import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError | import("../Type.js").LessThanOrEqualToError<number>>, never>;
136
- counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").IntError | import("../Type.js").NumberError>, "LessThanOrEqualTo65535", import("../Type.js").LessThanOrEqualToError<65535>, import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError>, "Counter", import("../Type.js").BrandWithoutRefineError<"Counter", import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").NumberError | import("../Type.js").LessThanOrEqualToError<65535>>, never>;
128
+ millis: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").NumberError | import("../Type.js").IntError>, "LessThan281474976710655", import("../Type.js").LessThanError<281474976710655>, import("../Type.js").NumberError | import("../Type.js").NonNegativeError | import("../Type.js").IntError>, "Millis", import("../Type.js").BrandWithoutRefineError<"Millis", import("../Type.js").NumberError | import("../Type.js").LessThanError<281474976710655> | import("../Type.js").NonNegativeError | import("../Type.js").IntError>, never>;
129
+ counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & import("../Brand.js").Brand<"Int">, import("../Type.js").NumberError | import("../Type.js").IntError>, "LessThanOrEqualTo65535", import("../Type.js").LessThanOrEqualToError<65535>, import("../Type.js").NumberError | import("../Type.js").NonNegativeError | import("../Type.js").IntError>, "Counter", import("../Type.js").BrandWithoutRefineError<"Counter", import("../Type.js").NumberError | import("../Type.js").NonNegativeError | import("../Type.js").IntError | import("../Type.js").LessThanOrEqualToError<65535>>, never>;
137
130
  nodeId: import("../Type.js").BrandType<import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "NodeId", import("../Type.js").RegexError<"NodeId">, import("../Type.js").StringError>;
138
131
  }>;
139
132
  export interface Timestamp extends InferType<typeof Timestamp> {
140
133
  }
141
134
  /** Equality function for comparing {@link Timestamp}. */
142
135
  export declare const eqTimestamp: import("../Eq.js").Eq<{
143
- readonly millis: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative"> & import("../Brand.js").Brand<`LessThanOrEqualTo${number}`> & import("../Brand.js").Brand<"Millis">;
136
+ readonly millis: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative"> & import("../Brand.js").Brand<"LessThan281474976710655"> & import("../Brand.js").Brand<"Millis">;
144
137
  readonly counter: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative"> & import("../Brand.js").Brand<"LessThanOrEqualTo65535"> & import("../Brand.js").Brand<"Counter">;
145
138
  readonly nodeId: string & import("../Brand.js").Brand<"NodeId">;
146
139
  }>;
@@ -149,7 +142,7 @@ export declare const createInitialTimestamp: (deps: RandomBytesDep) => Timestamp
149
142
  export declare const sendTimestamp: (deps: TimeDep & TimestampConfigDep) => (timestamp: Timestamp) => Result<Timestamp, TimestampDriftError | TimestampCounterOverflowError | TimestampTimeOutOfRangeError>;
150
143
  export declare const receiveTimestamp: (deps: TimeDep & TimestampConfigDep) => (local: Timestamp, remote: Timestamp) => Result<Timestamp, TimestampDriftError | TimestampCounterOverflowError | TimestampTimeOutOfRangeError>;
151
144
  /** Sortable bytes representation of {@link Timestamp}. */
152
- export declare const TimestampBytes: import("../Type.js").BrandType<import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>, "TimestampBytes", import("../Type.js").BrandWithoutRefineError<"TimestampBytes", import("../Type.js").Uint8ArrayError>, never>;
145
+ export declare const TimestampBytes: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>, "Length16", import("../Type.js").LengthError<16>, import("../Type.js").Uint8ArrayError>, "TimestampBytes", import("../Type.js").BrandWithoutRefineError<"TimestampBytes", import("../Type.js").Uint8ArrayError | import("../Type.js").LengthError<16>>, never>;
153
146
  export type TimestampBytes = typeof TimestampBytes.Type;
154
147
  export declare const timestampBytesLength: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">;
155
148
  export declare const timestampToTimestampBytes: (timestamp: Timestamp) => TimestampBytes;
@@ -1 +1 @@
1
- {"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../../src/local-first/Timestamp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAmB,MAAM,aAAa,CAAC;AACrD,OAAO,EAAW,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAEL,OAAO,EACP,SAAS,EAOV,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED,MAAM,MAAM,cAAc,GACtB,mBAAmB,GACnB,6BAA6B,GAC7B,4BAA4B,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,+BAA+B,CAAC;CAChD;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,MAAM,kwBAGlB,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAC;AAExC,eAAO,MAAM,SAAS,EAAQ,MAAM,CAAC;AACrC,eAAO,MAAM,SAAS,EAA4B,MAAM,CAAC;AAEzD,eAAO,MAAM,OAAO,8vBAGnB,CAAC;AACF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC;AAE1C,eAAO,MAAM,UAAU,EAAQ,OAAO,CAAC;AACvC,eAAO,MAAM,UAAU,EAAY,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,MAAM,wPAA4C,CAAC;AAChE,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAC;AAExC,eAAO,MAAM,SAAS,EAAyB,MAAM,CAAC;AACtD,eAAO,MAAM,SAAS,EAAyB,MAAM,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,SAAS;;;;EAIpB,CAAC;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS,CAAC,OAAO,SAAS,CAAC;CAAG;AAEjE,yDAAyD;AACzD,eAAO,MAAM,WAAW;;;;EAItB,CAAC;AAEH,eAAO,MAAM,eAAe,GAAI,+BAI7B,OAAO,CAAC,SAAS,CAAM,KAAG,SAA0C,CAAC;AAExE,eAAO,MAAM,sBAAsB,GAAI,MAAM,cAAc,KAAG,SAG7D,CAAC;AA6BF,eAAO,MAAM,aAAa,GACvB,MAAM,OAAO,GAAG,kBAAkB,MAEjC,WAAW,SAAS,KACnB,MAAM,CACP,SAAS,EACP,mBAAmB,GACnB,6BAA6B,GAC7B,4BAA4B,CAgB/B,CAAC;AAEJ,eAAO,MAAM,gBAAgB,GAC1B,MAAM,OAAO,GAAG,kBAAkB,MAEjC,OAAO,SAAS,EAChB,QAAQ,SAAS,KAChB,MAAM,CACP,SAAS,EACP,mBAAmB,GACnB,6BAA6B,GAC7B,4BAA4B,CAqB/B,CAAC;AAEJ,0DAA0D;AAC1D,eAAO,MAAM,cAAc,2WAAsC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD,eAAO,MAAM,oBAAoB,0FAA6B,CAAC;AAE/D,eAAO,MAAM,yBAAyB,GACpC,WAAW,SAAS,KACnB,cA0BF,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,WAAW,cAAc,KACxB,SAoBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,cAAc,CAAmB,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,SAAS,KAAG,OAEL,CAAC"}
1
+ {"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../../src/local-first/Timestamp.ts"],"names":[],"mappings":"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"}