@evolu/common 6.0.1-preview.32 → 6.0.1-preview.34

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 (49) hide show
  1. package/README.md +2 -2
  2. package/dist/src/Array.d.ts +193 -41
  3. package/dist/src/Array.d.ts.map +1 -1
  4. package/dist/src/Array.js +155 -48
  5. package/dist/src/Crypto.d.ts +6 -8
  6. package/dist/src/Crypto.d.ts.map +1 -1
  7. package/dist/src/Crypto.js +9 -9
  8. package/dist/src/Evolu/Db.d.ts.map +1 -1
  9. package/dist/src/Evolu/Db.js +4 -4
  10. package/dist/src/Evolu/Evolu.d.ts +9 -4
  11. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  12. package/dist/src/Evolu/Evolu.js +11 -11
  13. package/dist/src/Evolu/Protocol.d.ts +24 -1
  14. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  15. package/dist/src/Evolu/Protocol.js +59 -30
  16. package/dist/src/Evolu/Query.d.ts +1 -1
  17. package/dist/src/Evolu/Query.d.ts.map +1 -1
  18. package/dist/src/Evolu/Query.js +1 -1
  19. package/dist/src/Evolu/Schema.d.ts +24 -20
  20. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  21. package/dist/src/Evolu/Schema.js +36 -27
  22. package/dist/src/Evolu/Storage.d.ts +10 -2
  23. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  24. package/dist/src/Evolu/Storage.js +18 -4
  25. package/dist/src/Evolu/Sync.d.ts +2 -1
  26. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  27. package/dist/src/Evolu/Sync.js +45 -33
  28. package/dist/src/Evolu/Timestamp.d.ts +12 -17
  29. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  30. package/dist/src/Evolu/Timestamp.js +5 -19
  31. package/dist/src/Object.d.ts +10 -4
  32. package/dist/src/Object.d.ts.map +1 -1
  33. package/dist/src/Object.js +9 -3
  34. package/dist/src/Type.d.ts +57 -11
  35. package/dist/src/Type.d.ts.map +1 -1
  36. package/dist/src/Type.js +58 -28
  37. package/package.json +2 -2
  38. package/src/Array.ts +213 -55
  39. package/src/Crypto.ts +11 -9
  40. package/src/Evolu/Db.ts +7 -7
  41. package/src/Evolu/Evolu.ts +21 -20
  42. package/src/Evolu/Protocol.ts +70 -35
  43. package/src/Evolu/Query.ts +2 -2
  44. package/src/Evolu/Schema.ts +44 -32
  45. package/src/Evolu/Storage.ts +40 -2
  46. package/src/Evolu/Sync.ts +54 -32
  47. package/src/Evolu/Timestamp.ts +7 -28
  48. package/src/Object.ts +13 -5
  49. package/src/Type.ts +58 -32
@@ -1,4 +1,6 @@
1
1
  import * as Kysely from "kysely";
2
+ import { assert } from "../Assert.js";
3
+ import { createEqArrayLike, eqString } from "../Eq.js";
2
4
  import { mapObject, objectToEntries } from "../Object.js";
3
5
  import { ok } from "../Result.js";
4
6
  import { sql, SqliteBoolean, } from "../Sqlite.js";
@@ -19,23 +21,25 @@ export const evoluSchemaToDbSchema = (schema, indexesConfig) => {
19
21
  return { tables, indexes };
20
22
  };
21
23
  /**
22
- * Default columns automatically added to all tables.
24
+ * System columns that are implicitly defined by Evolu.
23
25
  *
24
- * - `createdAt`: Set by Evolu when `insert` is called, or can be custom with
25
- * `upsert`.
26
- * - `updatedAt`: Always set by Evolu, derived from {@link CrdtMessage} timestamp.
27
- * If you defer sync to avoid leaking time activity, use a custom column to
28
- * preserve real update time.
29
- * - `isDeleted`: Soft delete flag.
26
+ * - `createdAt`: Set by Evolu on row creation, derived from {@link Timestamp}.
27
+ * - `updatedAt`: Set by Evolu on every row change, derived from {@link Timestamp}.
28
+ * - `isDeleted`: Soft delete flag created by Evolu and used by the developer to
29
+ * mark rows as deleted.
30
30
  */
31
- export const DefaultColumns = object({
31
+ export const SystemColumns = object({
32
32
  createdAt: DateIso,
33
33
  updatedAt: DateIso,
34
34
  isDeleted: nullOr(SqliteBoolean),
35
+ // TODO: ownerId
35
36
  });
37
+ export const systemColumns = ["createdAt", "updatedAt", "isDeleted"];
38
+ assert(createEqArrayLike(eqString)(objectToEntries(SystemColumns.props).map(([key]) => key), systemColumns), "SystemColumns keys must match systemColumnsKeys");
36
39
  /**
37
40
  * Type Factory to create insertable {@link Type}. It makes nullable Types
38
- * optional, omits Id, and ensures the {@link maxMutationSize}.
41
+ * optional (so they are not required), omits Id, and ensures the
42
+ * {@link maxMutationSize}.
39
43
  *
40
44
  * ### Example
41
45
  *
@@ -53,7 +57,7 @@ export const insertable = (props) => {
53
57
  };
54
58
  /**
55
59
  * Type Factory to create updateable {@link Type}. It makes everything except for
56
- * the `id` column partial (i.e. optional) and ensures the
60
+ * the `id` column optional (so they are not required) and ensures the
57
61
  * {@link maxMutationSize}.
58
62
  *
59
63
  * ### Example
@@ -76,9 +80,15 @@ export const updateable = (props) => {
76
80
  return validMutationSize(object(updateableProps));
77
81
  };
78
82
  /**
79
- * Type Factory to create upsertable Type. It makes nullable Types optional,
80
- * includes optional default columns (createdAt, isDeleted), and ensures the
81
- * {@link maxMutationSize}.
83
+ * Type Factory to create an upsertable Type. It makes nullable Types optional
84
+ * (so they are not required) and ensures the {@link maxMutationSize}.
85
+ *
86
+ * Upsert is like insert, except it requires an ID. It's useful for inserting
87
+ * rows with external ID via {@link createIdFromString}.
88
+ *
89
+ * Note that it's not possible to upsert a row with `createdAt` nor `updatedAt`,
90
+ * because they are derived from {@link CrdtMessage} timestamp. For external
91
+ * createdAt, use a different column.
82
92
  *
83
93
  * ### Example
84
94
  *
@@ -88,7 +98,6 @@ export const updateable = (props) => {
88
98
  * const todo = UpsertableTodo.from({
89
99
  * id,
90
100
  * title,
91
- * createdAt: "2023-01-01T00:00:00.000Z",
92
101
  * });
93
102
  * if (!todo.ok) return; // handle errors
94
103
  * ```
@@ -96,7 +105,6 @@ export const updateable = (props) => {
96
105
  export const upsertable = (props) => {
97
106
  const propsWithDefaults = {
98
107
  ...props,
99
- createdAt: optional(DateIso),
100
108
  isDeleted: optional(SqliteBoolean),
101
109
  };
102
110
  return validMutationSize(nullableToOptional(propsWithDefaults));
@@ -166,7 +174,7 @@ export const ensureDbSchema = (deps) => (newSchema, currentSchema, options) => {
166
174
  const currentTable = currentSchema.tables.find((t) => t.name === newTable.name);
167
175
  if (!currentTable) {
168
176
  queries.push({
169
- sql: createTableWithDefaultColumns(newTable.name, newTable.columns),
177
+ sql: createAppTableWithDefaultColumns(newTable),
170
178
  parameters: [],
171
179
  });
172
180
  }
@@ -202,20 +210,21 @@ export const ensureDbSchema = (deps) => (newSchema, currentSchema, options) => {
202
210
  }
203
211
  return ok();
204
212
  };
205
- const createTableWithDefaultColumns = (tableName, columns) => `
206
- create table ${sql.identifier(tableName).sql} (
213
+ const createAppTableWithDefaultColumns = (table) => {
214
+ return `
215
+ create table ${sql.identifier(table.name).sql} (
207
216
  "id" text primary key,
208
- ${columns
209
- // Add default columns.
210
- .concat(["createdAt", "updatedAt", "isDeleted"])
211
- .filter((c) => c !== "id")
212
- // "A column with affinity BLOB does not prefer one storage class over another
213
- // and no attempt is made to coerce data from one storage class into another."
214
- // https://www.sqlite.org/datatype3.html
215
- .map((name) => `${sql.identifier(name).sql} blob`)
216
- .join(", ")}
217
+ ${table.columns
218
+ .concat(systemColumns)
219
+ .filter((c) => c !== "id")
220
+ // "A column with affinity BLOB does not prefer one storage class over another
221
+ // and no attempt is made to coerce data from one storage class into another."
222
+ // https://www.sqlite.org/datatype3.html
223
+ .map((name) => `${sql.identifier(name).sql} blob`)
224
+ .join(", ")}
217
225
  );
218
226
  `;
227
+ };
219
228
  // https://kysely.dev/docs/recipes/splitting-query-building-and-execution
220
229
  export const kysely = new Kysely.Kysely({
221
230
  dialect: {
@@ -4,7 +4,7 @@ import { RandomDep } from "../Random.js";
4
4
  import { Result } from "../Result.js";
5
5
  import { SqliteDep, SqliteError } from "../Sqlite.js";
6
6
  import { MaybeAsync } from "../Task.js";
7
- import { NonNegativeInt, PositiveInt } from "../Type.js";
7
+ import { NonNegativeInt, PositiveInt, TypeError } from "../Type.js";
8
8
  import { BaseOwnerError, OwnerId, OwnerIdBytes, OwnerWriteKey } from "./Owner.js";
9
9
  import { Timestamp, TimestampBytes } from "./Timestamp.js";
10
10
  export interface StorageConfig {
@@ -163,6 +163,13 @@ export interface CrdtMessage {
163
163
  readonly timestamp: Timestamp;
164
164
  readonly change: DbChange;
165
165
  }
166
+ export declare const DbChangeValues: import("../Type.js").RecordType<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError, import("../Type.js").UnionType<[import("../Type.js").Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, import("../Type.js").Type<"Number", number, number, import("../Type.js").NumberError, number, import("../Type.js").NumberError>, import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>]>>;
167
+ export type DbChangeValues = typeof DbChangeValues.Type;
168
+ export declare const ValidDbChangeValues: import("../Type.js").BrandType<import("../Type.js").RecordType<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError, import("../Type.js").UnionType<[import("../Type.js").Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, import("../Type.js").Type<"Number", number, number, import("../Type.js").NumberError, number, import("../Type.js").NumberError>, import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>]>>, "ValidDbChangeValues", ValidDbChangeValuesError, import("../Type.js").RecordError<import("../Type.js").StringError, never> | import("../Type.js").RecordError<import("../Type.js").StringError, import("../Type.js").UnionError<import("../Type.js").Uint8ArrayError | import("../Type.js").NumberError | import("../Type.js").StringError | import("../Type.js").NullError>>>;
169
+ export type ValidDbChangeValues = typeof ValidDbChangeValues.Type;
170
+ export interface ValidDbChangeValuesError extends TypeError<"ValidDbChangeValues"> {
171
+ readonly invalidColumns: ReadonlyArray<string>;
172
+ }
166
173
  /**
167
174
  * A DbChange is a change to a table row. Together with a unique
168
175
  * {@link Timestamp}, it forms a {@link CrdtMessage}.
@@ -170,7 +177,8 @@ export interface CrdtMessage {
170
177
  export declare const DbChange: import("../Type.js").ObjectType<{
171
178
  table: import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>;
172
179
  id: import("../Type.js").BrandType<import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, "Id", import("../Type.js").IdError, import("../Type.js").StringError>;
173
- values: import("../Type.js").RecordType<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError, import("../Type.js").UnionType<[import("../Type.js").Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, import("../Type.js").Type<"Number", number, number, import("../Type.js").NumberError, number, import("../Type.js").NumberError>, import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>]>>;
180
+ values: import("../Type.js").BrandType<import("../Type.js").RecordType<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError, import("../Type.js").UnionType<[import("../Type.js").Type<"Null", null, null, import("../Type.js").NullError, null, import("../Type.js").NullError>, import("../Type.js").Type<"String", string, string, import("../Type.js").StringError, string, import("../Type.js").StringError>, import("../Type.js").Type<"Number", number, number, import("../Type.js").NumberError, number, import("../Type.js").NumberError>, import("../Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("../Type.js").Uint8ArrayError>]>>, "ValidDbChangeValues", ValidDbChangeValuesError, import("../Type.js").RecordError<import("../Type.js").StringError, never> | import("../Type.js").RecordError<import("../Type.js").StringError, import("../Type.js").UnionError<import("../Type.js").Uint8ArrayError | import("../Type.js").NumberError | import("../Type.js").StringError | import("../Type.js").NullError>>>;
181
+ isInsert: import("../Type.js").Type<"Boolean", boolean, boolean, import("../Type.js").BooleanError, boolean, import("../Type.js").BooleanError>;
174
182
  }>;
175
183
  export type DbChange = typeof DbChange.Type;
176
184
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Storage.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,13 @@
1
1
  import { sha256 } from "@noble/hashes/sha2.js";
2
- import { firstInArray, isNonEmptyReadonlyArray, } from "../Array.js";
2
+ import { filterArray, firstInArray, isNonEmptyReadonlyArray, } from "../Array.js";
3
3
  import { assert } from "../Assert.js";
4
4
  import { concatBytes } from "../Buffer.js";
5
5
  import { decrement } from "../Number.js";
6
- import { ok } from "../Result.js";
6
+ import { err, ok } from "../Result.js";
7
7
  import { sql, SqliteValue } from "../Sqlite.js";
8
- import { Id, NonNegativeInt, object, PositiveInt, record, String, } from "../Type.js";
8
+ import { Boolean, brand, Id, NonNegativeInt, object, PositiveInt, record, String, } from "../Type.js";
9
9
  import { orderTimestampBytes } from "./Timestamp.js";
10
+ import { systemColumns } from "./Schema.js";
10
11
  export const fingerprintSize = NonNegativeInt.orThrow(12);
11
12
  /** A fingerprint of an empty range. */
12
13
  export const zeroFingerprint = new Uint8Array(fingerprintSize);
@@ -16,6 +17,18 @@ export const RangeType = {
16
17
  Skip: 0,
17
18
  Timestamps: 2,
18
19
  };
20
+ export const DbChangeValues = record(String, SqliteValue);
21
+ const systemColumnsWithIdAndWithoutIsDeleted = filterArray(systemColumns.concat("id"), (column) => column != "isDeleted");
22
+ export const ValidDbChangeValues = brand("ValidDbChangeValues", DbChangeValues, (value) => {
23
+ const invalidColumns = systemColumnsWithIdAndWithoutIsDeleted.filter((key) => key in value);
24
+ if (invalidColumns.length > 0)
25
+ return err({
26
+ type: "ValidDbChangeValues",
27
+ value,
28
+ invalidColumns,
29
+ });
30
+ return ok(value);
31
+ });
19
32
  /**
20
33
  * A DbChange is a change to a table row. Together with a unique
21
34
  * {@link Timestamp}, it forms a {@link CrdtMessage}.
@@ -23,7 +36,8 @@ export const RangeType = {
23
36
  export const DbChange = object({
24
37
  table: String,
25
38
  id: Id,
26
- values: record(String, SqliteValue),
39
+ values: ValidDbChangeValues,
40
+ isInsert: Boolean,
27
41
  });
28
42
  /**
29
43
  * Creates a {@link BaseSqliteStorage} implementation.
@@ -6,6 +6,7 @@ import { RandomDep } from "../Random.js";
6
6
  import { Result } from "../Result.js";
7
7
  import { SqliteDep, SqliteError } from "../Sqlite.js";
8
8
  import { TimeDep } from "../Time.js";
9
+ import { DateIso } from "../Type.js";
9
10
  import { CreateWebSocketDep } from "../WebSocket.js";
10
11
  import type { PostMessageDep } from "./Db.js";
11
12
  import { AppOwner, OwnerEncryptionKey, OwnerId, OwnerIdBytes, OwnerTransport, OwnerWriteKey } from "./Owner.js";
@@ -68,7 +69,7 @@ export interface ClientStorageDep {
68
69
  readonly storage: ClientStorage;
69
70
  }
70
71
  export declare const applyLocalOnlyChange: (deps: SqliteDep & TimeDep) => (change: MutationChange) => Result<void, SqliteError>;
71
- export declare const applyMessageToTimestampAndHistoryTables: (deps: ClientStorageDep & SqliteDep) => (ownerId: OwnerIdBytes, message: CrdtMessage, strategy: StorageInsertTimestampStrategy) => Result<void, SqliteError>;
72
+ export declare const applyMessageToTimestampAndHistoryTables: (deps: ClientStorageDep & SqliteDep) => (ownerId: OwnerIdBytes, message: CrdtMessage, strategy: StorageInsertTimestampStrategy, date: DateIso) => Result<void, SqliteError>;
72
73
  /**
73
74
  * TODO: Rework for the new owners API.
74
75
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Sync.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Sync.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Sync.ts"],"names":[],"mappings":"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"}
@@ -8,11 +8,11 @@ import { createResources } from "../Resources.js";
8
8
  import { err, ok } from "../Result.js";
9
9
  import { sql } from "../Sqlite.js";
10
10
  import { createMutex } from "../Task.js";
11
- import { idBytesToId, idToIdBytes } from "../Type.js";
11
+ import { idBytesToId, idToIdBytes, } from "../Type.js";
12
12
  import { ownerIdBytesToOwnerId, ownerIdToOwnerIdBytes, } from "./Owner.js";
13
13
  import { applyProtocolMessageAsClient, createProtocolMessageForSync, createProtocolMessageForUnsubscribe, createProtocolMessageFromCrdtMessages, decryptAndDecodeDbChange, encodeAndEncryptDbChange, SubscriptionFlags, } from "./Protocol.js";
14
- import { createBaseSqliteStorage, getOwnerUsage, getTimestampInsertStrategy, updateOwnerUsage, } from "./Storage.js";
15
- import { createInitialTimestamp, receiveTimestamp, sendTimestamp, timestampBytesToTimestamp, timestampToTimestampBytes, timestampToTimestampString, } from "./Timestamp.js";
14
+ import { createBaseSqliteStorage, DbChange, getOwnerUsage, getTimestampInsertStrategy, updateOwnerUsage, } from "./Storage.js";
15
+ import { createInitialTimestamp, receiveTimestamp, sendTimestamp, timestampBytesToTimestamp, timestampToDateIso, timestampToTimestampBytes, } from "./Timestamp.js";
16
16
  export const createSync = (deps) => (config) => {
17
17
  let isDisposed = false;
18
18
  /** Returns owner data only if actively assigned to at least one transport. */
@@ -160,7 +160,10 @@ export const createSync = (deps) => (config) => {
160
160
  return nextTimestamp;
161
161
  clockTimestamp = nextTimestamp.value;
162
162
  const { ownerId = config.appOwner.id, ...dbChange } = change;
163
- const message = { timestamp: clockTimestamp, change: dbChange };
163
+ const message = {
164
+ timestamp: clockTimestamp,
165
+ change: dbChange,
166
+ };
164
167
  const messages = ownerMessages.get(ownerId);
165
168
  if (messages)
166
169
  messages.push(message);
@@ -209,9 +212,9 @@ export const createClock = (deps) => (initialTimestamp = createInitialTimestamp(
209
212
  get: () => currentTimestamp,
210
213
  save: (timestamp) => {
211
214
  currentTimestamp = timestamp;
212
- const timestampString = timestampToTimestampString(timestamp);
213
215
  const result = deps.sqlite.exec(sql.prepared `
214
- update evolu_config set "clock" = ${timestampString};
216
+ update evolu_config
217
+ set "clock" = ${timestampToTimestampBytes(timestamp)};
215
218
  `);
216
219
  if (!result.ok)
217
220
  return result;
@@ -306,18 +309,25 @@ const createClientStorage = (deps) => (config) => {
306
309
  assert(rows.length > 0, "Rows must not be empty");
307
310
  const { table, id } = rows[0];
308
311
  const values = {};
312
+ let isInsert = false;
309
313
  for (const r of rows) {
310
314
  assert(r.table === table, "All rows must have the same table");
311
315
  assert(eqArrayNumber(r.id, id), "All rows must have the same Id");
312
- values[r.column] = r.value;
316
+ if (r.column === "createdAt") {
317
+ isInsert = true;
318
+ }
319
+ else {
320
+ values[r.column] = r.value;
321
+ }
313
322
  }
314
323
  const message = {
315
324
  timestamp: timestampBytesToTimestamp(timestamp),
316
- change: {
325
+ change: DbChange.orThrow({
317
326
  table: rows[0].table,
318
327
  id: idBytesToId(rows[0].id),
319
328
  values,
320
- },
329
+ isInsert,
330
+ }),
321
331
  };
322
332
  return encodeAndEncryptDbChange(deps)(message, owner.encryptionKey);
323
333
  },
@@ -329,31 +339,26 @@ const createTransportKey = (transportConfig) => {
329
339
  return `${transportConfig.type}:${transportConfig.url}`;
330
340
  };
331
341
  export const applyLocalOnlyChange = (deps) => (change) => {
332
- const dbChange = {
333
- table: change.table,
334
- id: change.id,
335
- values: change.values,
336
- };
337
- const isDeletion = "isDeleted" in dbChange.values && dbChange.values.isDeleted === 1;
342
+ const isDeletion = "isDeleted" in change.values && change.values.isDeleted === 1;
338
343
  if (isDeletion) {
339
344
  const result = deps.sqlite.exec(sql `
340
- delete from ${sql.identifier(dbChange.table)}
341
- where id = ${dbChange.id};
345
+ delete from ${sql.identifier(change.table)}
346
+ where id = ${change.id};
342
347
  `);
343
348
  if (!result.ok)
344
349
  return result;
345
350
  }
346
351
  else {
347
- const date = new Date(deps.time.now()).toISOString();
348
- for (const [column, value] of objectToEntries(dbChange.values)) {
352
+ const now = deps.time.nowIso();
353
+ for (const [column, value] of objectToEntries(change.values)) {
349
354
  const result = deps.sqlite.exec(sql.prepared `
350
- insert into ${sql.identifier(dbChange.table)}
355
+ insert into ${sql.identifier(change.table)}
351
356
  ("id", ${sql.identifier(column)}, createdAt, updatedAt)
352
- values (${dbChange.id}, ${value}, ${date}, ${date})
357
+ values (${change.id}, ${value}, ${now}, ${now})
353
358
  on conflict ("id") do update
354
359
  set
355
360
  ${sql.identifier(column)} = ${value},
356
- updatedAt = ${date};
361
+ updatedAt = ${now};
357
362
  `);
358
363
  if (!result.ok)
359
364
  return result;
@@ -368,13 +373,14 @@ const applyMessages = (deps) => (ownerId, messages) => {
368
373
  return usageResult;
369
374
  let { firstTimestamp, lastTimestamp } = usageResult.value;
370
375
  for (const message of messages) {
371
- const result1 = applyMessageToAppTable(deps)(ownerIdBytes, message);
376
+ const date = timestampToDateIso(message.timestamp);
377
+ const result1 = applyMessageToAppTable(deps)(ownerIdBytes, message, date);
372
378
  if (!result1.ok)
373
379
  return result1;
374
380
  const timestamp = timestampToTimestampBytes(message.timestamp);
375
381
  let strategy;
376
382
  [strategy, firstTimestamp, lastTimestamp] = getTimestampInsertStrategy(timestamp, firstTimestamp, lastTimestamp);
377
- const result2 = applyMessageToTimestampAndHistoryTables(deps)(ownerIdBytes, message, strategy);
383
+ const result2 = applyMessageToTimestampAndHistoryTables(deps)(ownerIdBytes, message, strategy, date);
378
384
  if (!result2.ok)
379
385
  return result2;
380
386
  }
@@ -389,10 +395,12 @@ const applyMessages = (deps) => (ownerId, messages) => {
389
395
  return updateUsage;
390
396
  return ok();
391
397
  };
392
- const applyMessageToAppTable = (deps) => (ownerId, message) => {
393
- const timestamp = timestampToTimestampBytes(message.timestamp);
394
- const updatedAt = new Date(message.timestamp.millis).toISOString();
395
- for (const [column, value] of objectToEntries(message.change.values)) {
398
+ const applyMessageToAppTable = (deps) => (ownerId, message, date) => {
399
+ let entries = objectToEntries(message.change.values);
400
+ if (message.change.isInsert) {
401
+ entries = [...entries, ["createdAt", date]];
402
+ }
403
+ for (const [column, value] of entries) {
396
404
  const result = deps.sqlite.exec(sql.prepared `
397
405
  with
398
406
  existingTimestamp as (
@@ -403,17 +411,17 @@ const applyMessageToAppTable = (deps) => (ownerId, message) => {
403
411
  and "table" = ${message.change.table}
404
412
  and "id" = ${idToIdBytes(message.change.id)}
405
413
  and "column" = ${column}
406
- and "timestamp" >= ${timestamp}
414
+ and "timestamp" >= ${timestampToTimestampBytes(message.timestamp)}
407
415
  limit 1
408
416
  )
409
417
  insert into ${sql.identifier(message.change.table)}
410
418
  ("id", ${sql.identifier(column)}, updatedAt)
411
- select ${message.change.id}, ${value}, ${updatedAt}
419
+ select ${message.change.id}, ${value}, ${date}
412
420
  where not exists (select 1 from existingTimestamp)
413
421
  on conflict ("id") do update
414
422
  set
415
423
  ${sql.identifier(column)} = ${value},
416
- updatedAt = ${updatedAt}
424
+ updatedAt = ${date}
417
425
  where not exists (select 1 from existingTimestamp);
418
426
  `);
419
427
  if (!result.ok)
@@ -421,13 +429,17 @@ const applyMessageToAppTable = (deps) => (ownerId, message) => {
421
429
  }
422
430
  return ok();
423
431
  };
424
- export const applyMessageToTimestampAndHistoryTables = (deps) => (ownerId, message, strategy) => {
432
+ export const applyMessageToTimestampAndHistoryTables = (deps) => (ownerId, message, strategy, date) => {
425
433
  const timestamp = timestampToTimestampBytes(message.timestamp);
426
434
  const id = idToIdBytes(message.change.id);
427
435
  const result = deps.storage.insertTimestamp(ownerId, timestamp, strategy);
428
436
  if (!result.ok)
429
437
  return result;
430
- for (const [column, value] of Object.entries(message.change.values)) {
438
+ let entries = objectToEntries(message.change.values);
439
+ if (message.change.isInsert) {
440
+ entries = [...entries, ["createdAt", date]];
441
+ }
442
+ for (const [column, value] of entries) {
431
443
  const result = deps.sqlite.exec(sql.prepared `
432
444
  insert into evolu_history
433
445
  ("ownerId", "table", "id", "column", "value", "timestamp")
@@ -1,9 +1,8 @@
1
- import { Brand } from "../Brand.js";
2
1
  import { RandomBytesDep } from "../Crypto.js";
3
2
  import { Order } from "../Order.js";
4
3
  import { Result } from "../Result.js";
5
4
  import { TimeDep } from "../Time.js";
6
- import { InferType } from "../Type.js";
5
+ import { DateIso, InferType } from "../Type.js";
7
6
  export interface TimestampConfig {
8
7
  /**
9
8
  * Maximum physical clock drift allowed in ms.
@@ -39,11 +38,11 @@ export interface TimestampTimeOutOfRangeError {
39
38
  *
40
39
  * `new Date(281474976710654).toString()` = Tue Aug 02 10889 07:31:49
41
40
  */
42
- export declare const Millis: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & Brand<"Int"> & Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & 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>;
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>;
43
42
  export type Millis = typeof Millis.Type;
44
43
  export declare const minMillis: Millis;
45
44
  export declare const maxMillis: Millis;
46
- export declare const Counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & Brand<"Int"> & Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & 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>;
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>;
47
46
  export type Counter = typeof Counter.Type;
48
47
  export declare const minCounter: Counter;
49
48
  export declare const maxCounter: Counter;
@@ -128,37 +127,33 @@ export declare const maxNodeId: NodeId;
128
127
  * queue:
129
128
  *
130
129
  * 1. Write changes immediately to a local-only table
131
- * 2. Periodically/randomly flush messages to sync tables
132
- * 3. This decouples user activity from sync timing
130
+ * 2. Periodically and randomly flush messages to sync tables
133
131
  *
134
- * Tradeoff: It breaks real-time collaboration.
132
+ * **Trade-off:** It breaks real-time collaboration.
135
133
  */
136
134
  export declare const Timestamp: import("../Type.js").ObjectType<{
137
- millis: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & Brand<"Int"> & Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & 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>;
138
- counter: import("../Type.js").BrandType<import("../Type.js").BrandType<import("../Type.js").Type<"Brand", number & Brand<"Int"> & Brand<"NonNegative">, number, import("../Type.js").NonNegativeError, number & 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>;
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>;
139
137
  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>;
140
138
  }>;
141
139
  export interface Timestamp extends InferType<typeof Timestamp> {
142
140
  }
143
141
  /** Equality function for comparing {@link Timestamp}. */
144
142
  export declare const eqTimestamp: import("../Eq.js").Eq<{
145
- readonly millis: number & Brand<"Int"> & Brand<"NonNegative"> & Brand<`LessThanOrEqualTo${number}`> & Brand<"Millis">;
146
- readonly counter: number & Brand<"Int"> & Brand<"NonNegative"> & Brand<"LessThanOrEqualTo65535"> & Brand<"Counter">;
147
- readonly nodeId: string & Brand<"NodeId">;
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">;
144
+ readonly counter: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative"> & import("../Brand.js").Brand<"LessThanOrEqualTo65535"> & import("../Brand.js").Brand<"Counter">;
145
+ readonly nodeId: string & import("../Brand.js").Brand<"NodeId">;
148
146
  }>;
149
147
  export declare const createTimestamp: ({ millis, counter, nodeId, }?: Partial<Timestamp>) => Timestamp;
150
148
  export declare const createInitialTimestamp: (deps: RandomBytesDep) => Timestamp;
151
- /** Sortable string representation of {@link Timestamp}. */
152
- export type TimestampString = string & Brand<"TimestampString">;
153
- export declare const timestampToTimestampString: (t: Timestamp) => TimestampString;
154
- export declare const timestampStringToTimestamp: (timestampString: TimestampString) => Timestamp;
155
149
  export declare const sendTimestamp: (deps: TimeDep & TimestampConfigDep) => (timestamp: Timestamp) => Result<Timestamp, TimestampDriftError | TimestampCounterOverflowError | TimestampTimeOutOfRangeError>;
156
150
  export declare const receiveTimestamp: (deps: TimeDep & TimestampConfigDep) => (local: Timestamp, remote: Timestamp) => Result<Timestamp, TimestampDriftError | TimestampCounterOverflowError | TimestampTimeOutOfRangeError>;
157
151
  /** Sortable bytes representation of {@link Timestamp}. */
158
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>;
159
153
  export type TimestampBytes = typeof TimestampBytes.Type;
160
- export declare const timestampBytesLength: number & Brand<"Int"> & Brand<"NonNegative">;
154
+ export declare const timestampBytesLength: number & import("../Brand.js").Brand<"Int"> & import("../Brand.js").Brand<"NonNegative">;
161
155
  export declare const timestampToTimestampBytes: (timestamp: Timestamp) => TimestampBytes;
162
156
  export declare const timestampBytesToTimestamp: (timestamp: TimestampBytes) => Timestamp;
163
157
  export declare const orderTimestampBytes: Order<TimestampBytes>;
158
+ export declare const timestampToDateIso: (timestamp: Timestamp) => DateIso;
164
159
  //# sourceMappingURL=Timestamp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Timestamp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../../src/Evolu/Timestamp.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { assert } from "../Assert.js";
2
1
  import { bytesToHex } from "../Buffer.js";
3
2
  import { createEqObject, eqNumber, eqString } from "../Eq.js";
4
3
  import { increment } from "../Number.js";
@@ -103,10 +102,9 @@ export const maxNodeId = "ffffffffffffffff";
103
102
  * queue:
104
103
  *
105
104
  * 1. Write changes immediately to a local-only table
106
- * 2. Periodically/randomly flush messages to sync tables
107
- * 3. This decouples user activity from sync timing
105
+ * 2. Periodically and randomly flush messages to sync tables
108
106
  *
109
- * Tradeoff: It breaks real-time collaboration.
107
+ * **Trade-off:** It breaks real-time collaboration.
110
108
  */
111
109
  export const Timestamp = object({
112
110
  millis: Millis,
@@ -124,21 +122,6 @@ export const createInitialTimestamp = (deps) => {
124
122
  const nodeId = bytesToHex(deps.randomBytes.create(8));
125
123
  return createTimestamp({ nodeId });
126
124
  };
127
- export const timestampToTimestampString = (t) => [
128
- new Date(t.millis).toISOString(),
129
- t.counter.toString(16).toUpperCase().padStart(4, "0"),
130
- t.nodeId,
131
- ].join("-");
132
- export const timestampStringToTimestamp = (timestampString) => {
133
- const array = timestampString.split("-");
134
- const timestamp = {
135
- millis: Date.parse(array.slice(0, 3).join("-")).valueOf(),
136
- counter: parseInt(array[3], 16),
137
- nodeId: array[4],
138
- };
139
- assert(Timestamp.is(timestamp), "timestampString is malformed");
140
- return timestamp;
141
- };
142
125
  const getNextMillis = (deps) => (millis) => {
143
126
  const now = Millis.from(deps.time.now());
144
127
  if (!now.ok) {
@@ -236,3 +219,6 @@ export const timestampBytesToTimestamp = (timestamp) => {
236
219
  return { millis: Number(millis), counter, nodeId };
237
220
  };
238
221
  export const orderTimestampBytes = orderUint8Array;
222
+ export const timestampToDateIso = (timestamp) =>
223
+ // `as DateIso` is safe because the timestamp is always valid
224
+ new Date(timestamp.millis).toISOString();