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

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.
package/src/Evolu/Sync.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { NonEmptyArray, NonEmptyReadonlyArray } from "../Array.js";
1
+ import {
2
+ firstInArray,
3
+ isNonEmptyReadonlyArray,
4
+ NonEmptyArray,
5
+ NonEmptyReadonlyArray,
6
+ } from "../Array.js";
2
7
  import { assert } from "../Assert.js";
3
8
  import { Brand } from "../Brand.js";
4
9
  import { ConsoleDep } from "../Console.js";
@@ -17,7 +22,7 @@ import { err, ok, Result } from "../Result.js";
17
22
  import { sql, SqliteDep, SqliteError, SqliteValue } from "../Sqlite.js";
18
23
  import { AbortError, createMutex } from "../Task.js";
19
24
  import { TimeDep } from "../Time.js";
20
- import { IdBytes, idBytesToId, idToIdBytes } from "../Type.js";
25
+ import { IdBytes, idBytesToId, idToIdBytes, PositiveInt } from "../Type.js";
21
26
  import { CreateWebSocketDep, WebSocket } from "../WebSocket.js";
22
27
  import type { PostMessageDep } from "./Db.js";
23
28
  import {
@@ -51,8 +56,12 @@ import {
51
56
  CrdtMessage,
52
57
  createBaseSqliteStorage,
53
58
  DbChange,
59
+ getOwnerUsage,
60
+ getTimestampInsertStrategy,
54
61
  Storage,
62
+ StorageInsertTimestampStrategy,
55
63
  StorageWriteError,
64
+ updateOwnerUsage,
56
65
  } from "./Storage.js";
57
66
  import {
58
67
  createInitialTimestamp,
@@ -519,11 +528,13 @@ const createClientStorage =
519
528
  clockTimestamp = nextTimestamp.value;
520
529
  }
521
530
 
522
- const applyMessagesResult = applyMessages({ ...deps, storage })(
523
- owner.id,
524
- messages,
525
- );
526
- if (!applyMessagesResult.ok) return applyMessagesResult;
531
+ if (isNonEmptyReadonlyArray(messages)) {
532
+ const applyMessagesResult = applyMessages({ ...deps, storage })(
533
+ owner.id,
534
+ messages,
535
+ );
536
+ if (!applyMessagesResult.ok) return applyMessagesResult;
537
+ }
527
538
 
528
539
  // // Apply local mutations atomically with approved messages
529
540
  // for (const change of localMutations) {
@@ -644,25 +655,56 @@ export const applyLocalOnlyChange =
644
655
  return ok();
645
656
  };
646
657
 
647
- export const applyMessages =
658
+ const applyMessages =
648
659
  (deps: ClientStorageDep & ClockDep & RandomDep & SqliteDep) =>
649
660
  (
650
661
  ownerId: OwnerId,
651
- messages: ReadonlyArray<CrdtMessage>,
662
+ messages: NonEmptyReadonlyArray<CrdtMessage>,
652
663
  ): Result<void, SqliteError> => {
653
664
  const ownerIdBytes = ownerIdToOwnerIdBytes(ownerId);
654
665
 
666
+ const usageResult = getOwnerUsage(deps)(
667
+ ownerIdBytes,
668
+ timestampToTimestampBytes(firstInArray(messages).timestamp),
669
+ );
670
+ if (!usageResult.ok) return usageResult;
671
+
672
+ let { firstTimestamp, lastTimestamp } = usageResult.value;
673
+
655
674
  for (const message of messages) {
656
675
  const result1 = applyMessageToAppTable(deps)(ownerIdBytes, message);
657
676
  if (!result1.ok) return result1;
658
677
 
678
+ const timestamp = timestampToTimestampBytes(message.timestamp);
679
+
680
+ let strategy;
681
+ [strategy, firstTimestamp, lastTimestamp] = getTimestampInsertStrategy(
682
+ timestamp,
683
+ firstTimestamp,
684
+ lastTimestamp,
685
+ );
686
+
659
687
  const result2 = applyMessageToTimestampAndHistoryTables(deps)(
660
688
  ownerIdBytes,
661
689
  message,
690
+ strategy,
662
691
  );
663
692
  if (!result2.ok) return result2;
664
693
  }
665
694
 
695
+ /**
696
+ * TODO: Implement proper storedBytes tracking for client using encrypted
697
+ * message sizes (need to figure out how to reuse received or postpone
698
+ * client...).
699
+ */
700
+ const updateUsage = updateOwnerUsage(deps)(
701
+ ownerIdBytes,
702
+ 1 as PositiveInt, // Placeholder until proper tracking implemented
703
+ firstTimestamp,
704
+ lastTimestamp,
705
+ );
706
+ if (!updateUsage.ok) return updateUsage;
707
+
666
708
  return ok();
667
709
  };
668
710
 
@@ -705,11 +747,15 @@ const applyMessageToAppTable =
705
747
 
706
748
  export const applyMessageToTimestampAndHistoryTables =
707
749
  (deps: ClientStorageDep & SqliteDep) =>
708
- (ownerId: OwnerIdBytes, message: CrdtMessage): Result<void, SqliteError> => {
750
+ (
751
+ ownerId: OwnerIdBytes,
752
+ message: CrdtMessage,
753
+ strategy: StorageInsertTimestampStrategy,
754
+ ): Result<void, SqliteError> => {
709
755
  const timestamp = timestampToTimestampBytes(message.timestamp);
710
756
  const id = idToIdBytes(message.change.id);
711
757
 
712
- const result = deps.storage.insertTimestamp(ownerId, timestamp);
758
+ const result = deps.storage.insertTimestamp(ownerId, timestamp, strategy);
713
759
  if (!result.ok) return result;
714
760
 
715
761
  for (const [column, value] of Object.entries(message.change.values)) {
package/src/Type.ts CHANGED
@@ -1641,8 +1641,9 @@ export const createId = <B extends string = never>(
1641
1641
  * });
1642
1642
  * ```
1643
1643
  *
1644
- * **Important**: This transformation is one-way. We cannot recover the original
1645
- * external string from the generated {@link Id}. If we need to preserve the
1644
+ * **Important**: This transformation uses the first 16 bytes of SHA-256 hash of
1645
+ * the string bytes, therefore it's not possible to recover the original
1646
+ * external string from the generated {@link Id}. If you need to preserve the
1646
1647
  * original external ID, store it in a separate column.
1647
1648
  *
1648
1649
  * @category String