cojson 0.7.0-alpha.37 → 0.7.0-alpha.39

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 (106) hide show
  1. package/.eslintrc.cjs +3 -2
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +1 -34
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +1106 -0
  6. package/CHANGELOG.md +12 -0
  7. package/README.md +3 -1
  8. package/dist/base64url.test.js +25 -0
  9. package/dist/base64url.test.js.map +1 -0
  10. package/dist/coValueCore.js +16 -15
  11. package/dist/coValueCore.js.map +1 -1
  12. package/dist/coValues/account.js +16 -15
  13. package/dist/coValues/account.js.map +1 -1
  14. package/dist/coValues/group.js +13 -14
  15. package/dist/coValues/group.js.map +1 -1
  16. package/dist/coreToCoValue.js.map +1 -1
  17. package/dist/crypto/PureJSCrypto.js +89 -0
  18. package/dist/crypto/PureJSCrypto.js.map +1 -0
  19. package/dist/crypto/WasmCrypto.js +127 -0
  20. package/dist/crypto/WasmCrypto.js.map +1 -0
  21. package/dist/crypto/crypto.js +151 -0
  22. package/dist/crypto/crypto.js.map +1 -0
  23. package/dist/ids.js +4 -2
  24. package/dist/ids.js.map +1 -1
  25. package/dist/index.js +4 -8
  26. package/dist/index.js.map +1 -1
  27. package/dist/jsonStringify.js.map +1 -1
  28. package/dist/localNode.js +24 -24
  29. package/dist/localNode.js.map +1 -1
  30. package/dist/permissions.js.map +1 -1
  31. package/dist/storage/FileSystem.js +2 -2
  32. package/dist/storage/FileSystem.js.map +1 -1
  33. package/dist/storage/chunksAndKnownStates.js +2 -2
  34. package/dist/storage/chunksAndKnownStates.js.map +1 -1
  35. package/dist/storage/index.js.map +1 -1
  36. package/dist/sync.js +6 -2
  37. package/dist/sync.js.map +1 -1
  38. package/dist/tests/account.test.js +58 -0
  39. package/dist/tests/account.test.js.map +1 -0
  40. package/dist/tests/coList.test.js +76 -0
  41. package/dist/tests/coList.test.js.map +1 -0
  42. package/dist/tests/coMap.test.js +136 -0
  43. package/dist/tests/coMap.test.js.map +1 -0
  44. package/dist/tests/coStream.test.js +172 -0
  45. package/dist/tests/coStream.test.js.map +1 -0
  46. package/dist/tests/coValueCore.test.js +114 -0
  47. package/dist/tests/coValueCore.test.js.map +1 -0
  48. package/dist/tests/crypto.test.js +118 -0
  49. package/dist/tests/crypto.test.js.map +1 -0
  50. package/dist/tests/cryptoImpl.test.js +113 -0
  51. package/dist/tests/cryptoImpl.test.js.map +1 -0
  52. package/dist/tests/group.test.js +34 -0
  53. package/dist/tests/group.test.js.map +1 -0
  54. package/dist/tests/permissions.test.js +1060 -0
  55. package/dist/tests/permissions.test.js.map +1 -0
  56. package/dist/tests/sync.test.js +816 -0
  57. package/dist/tests/sync.test.js.map +1 -0
  58. package/dist/tests/testUtils.js +10 -9
  59. package/dist/tests/testUtils.js.map +1 -1
  60. package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  61. package/dist/typeUtils/isAccountID.js.map +1 -1
  62. package/dist/typeUtils/isCoValue.js.map +1 -1
  63. package/package.json +14 -28
  64. package/src/base64url.test.ts +6 -6
  65. package/src/coValue.ts +1 -1
  66. package/src/coValueCore.ts +87 -85
  67. package/src/coValues/account.ts +26 -28
  68. package/src/coValues/coList.ts +10 -10
  69. package/src/coValues/coMap.ts +10 -10
  70. package/src/coValues/coStream.ts +17 -17
  71. package/src/coValues/group.ts +93 -109
  72. package/src/coreToCoValue.ts +5 -2
  73. package/src/crypto/PureJSCrypto.ts +200 -0
  74. package/src/crypto/WasmCrypto.ts +259 -0
  75. package/src/crypto/crypto.ts +336 -0
  76. package/src/ids.ts +8 -7
  77. package/src/index.ts +11 -19
  78. package/src/jsonStringify.ts +6 -4
  79. package/src/jsonValue.ts +2 -2
  80. package/src/localNode.ts +86 -80
  81. package/src/media.ts +3 -3
  82. package/src/permissions.ts +14 -16
  83. package/src/storage/FileSystem.ts +31 -30
  84. package/src/storage/chunksAndKnownStates.ts +24 -17
  85. package/src/storage/index.ts +41 -37
  86. package/src/streamUtils.ts +12 -12
  87. package/src/sync.ts +56 -40
  88. package/src/tests/account.test.ts +8 -12
  89. package/src/tests/coList.test.ts +19 -25
  90. package/src/tests/coMap.test.ts +25 -30
  91. package/src/tests/coStream.test.ts +28 -38
  92. package/src/tests/coValueCore.test.ts +35 -36
  93. package/src/tests/crypto.test.ts +66 -72
  94. package/src/tests/cryptoImpl.test.ts +183 -0
  95. package/src/tests/group.test.ts +16 -17
  96. package/src/tests/permissions.test.ts +237 -254
  97. package/src/tests/sync.test.ts +119 -120
  98. package/src/tests/testUtils.ts +22 -19
  99. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +1 -2
  100. package/src/typeUtils/expectGroup.ts +1 -1
  101. package/src/typeUtils/isAccountID.ts +0 -1
  102. package/src/typeUtils/isCoValue.ts +1 -2
  103. package/tsconfig.json +0 -1
  104. package/dist/crypto.js +0 -255
  105. package/dist/crypto.js.map +0 -1
  106. package/src/crypto.ts +0 -485
@@ -1,12 +1,11 @@
1
1
  import { Effect } from "effect";
2
2
  import { CoValueChunk } from "./index.js";
3
3
  import { RawCoID } from "../ids.js";
4
- import { StreamingHash } from "../crypto.js";
4
+ import { CryptoProvider, StreamingHash } from "../crypto/crypto.js";
5
5
 
6
- export type BlockFilename =
7
- `${string}-L${number}-H${number}.jsonl`;
6
+ export type BlockFilename = `${string}-L${number}-H${number}.jsonl`;
8
7
 
9
- export type BlockHeader = { id: RawCoID; start: number; length: number }[];
8
+ export type BlockHeader = { id: RawCoID; start: number; length: number }[];
10
9
 
11
10
  export type WalEntry = { id: RawCoID } & CoValueChunk;
12
11
 
@@ -18,25 +17,26 @@ export type FSErr = {
18
17
  };
19
18
 
20
19
  export interface FileSystem<WriteHandle, ReadHandle> {
20
+ crypto: CryptoProvider;
21
21
  createFile(filename: string): Effect.Effect<WriteHandle, FSErr>;
22
22
  append(handle: WriteHandle, data: Uint8Array): Effect.Effect<void, FSErr>;
23
- close(
24
- handle: ReadHandle | WriteHandle,
25
- ): Effect.Effect<void, FSErr>;
23
+ close(handle: ReadHandle | WriteHandle): Effect.Effect<void, FSErr>;
26
24
  closeAndRename(
27
25
  handle: WriteHandle,
28
- filename: BlockFilename
26
+ filename: BlockFilename,
29
27
  ): Effect.Effect<void, FSErr>;
30
28
  openToRead(
31
- filename: string
32
- ): Effect.Effect<{ handle: ReadHandle; size: number; }, FSErr>;
29
+ filename: string,
30
+ ): Effect.Effect<{ handle: ReadHandle; size: number }, FSErr>;
33
31
  read(
34
32
  handle: ReadHandle,
35
33
  offset: number,
36
- length: number
34
+ length: number,
37
35
  ): Effect.Effect<Uint8Array, FSErr>;
38
36
  listFiles(): Effect.Effect<string[], FSErr>;
39
- removeFile(filename: BlockFilename | WalFilename): Effect.Effect<void, FSErr>;
37
+ removeFile(
38
+ filename: BlockFilename | WalFilename,
39
+ ): Effect.Effect<void, FSErr>;
40
40
  }
41
41
 
42
42
  export const textEncoder = new TextEncoder();
@@ -44,12 +44,12 @@ export const textDecoder = new TextDecoder();
44
44
 
45
45
  export function readChunk<RH, FS extends FileSystem<unknown, RH>>(
46
46
  handle: RH,
47
- header: { start: number; length: number; },
48
- fs: FS
47
+ header: { start: number; length: number },
48
+ fs: FS,
49
49
  ): Effect.Effect<CoValueChunk, FSErr> {
50
50
  return Effect.gen(function* ($) {
51
51
  const chunkBytes = yield* $(
52
- fs.read(handle, header.start, header.length)
52
+ fs.read(handle, header.start, header.length),
53
53
  );
54
54
 
55
55
  const chunk = JSON.parse(textDecoder.decode(chunkBytes));
@@ -61,15 +61,13 @@ export function readHeader<RH, FS extends FileSystem<unknown, RH>>(
61
61
  filename: string,
62
62
  handle: RH,
63
63
  size: number,
64
- fs: FS
64
+ fs: FS,
65
65
  ): Effect.Effect<BlockHeader, FSErr> {
66
66
  return Effect.gen(function* ($) {
67
-
68
-
69
67
  const headerLength = Number(filename.match(/-H(\d+)\.jsonl$/)![1]!);
70
68
 
71
69
  const headerBytes = yield* $(
72
- fs.read(handle, size - headerLength, headerLength)
70
+ fs.read(handle, size - headerLength, headerLength),
73
71
  );
74
72
 
75
73
  const header = JSON.parse(textDecoder.decode(headerBytes));
@@ -80,7 +78,7 @@ export function readHeader<RH, FS extends FileSystem<unknown, RH>>(
80
78
  export function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
81
79
  chunks: Map<RawCoID, CoValueChunk>,
82
80
  level: number,
83
- fs: FS
81
+ fs: FS,
84
82
  ): Effect.Effect<void, FSErr> {
85
83
  if (chunks.size === 0) {
86
84
  return Effect.die(new Error("No chunks to write"));
@@ -94,19 +92,20 @@ export function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
94
92
  const file = yield* $(
95
93
  fs.createFile(
96
94
  "wipBlock" +
97
- Math.random().toString(36).substring(7) +
98
- ".tmp.jsonl"
99
- )
95
+ Math.random().toString(36).substring(7) +
96
+ ".tmp.jsonl",
97
+ ),
100
98
  );
101
- const hash = new StreamingHash();
99
+ const hash = new StreamingHash(fs.crypto);
102
100
 
103
- const chunksSortedById = Array.from(chunks).sort(([id1], [id2]) => id1.localeCompare(id2)
101
+ const chunksSortedById = Array.from(chunks).sort(([id1], [id2]) =>
102
+ id1.localeCompare(id2),
104
103
  );
105
104
 
106
105
  for (const [id, chunk] of chunksSortedById) {
107
106
  const encodedBytes = hash.update(chunk);
108
107
  const encodedBytesWithNewline = new Uint8Array(
109
- encodedBytes.length + 1
108
+ encodedBytes.length + 1,
110
109
  );
111
110
  encodedBytesWithNewline.set(encodedBytes);
112
111
  encodedBytesWithNewline[encodedBytes.length] = 10;
@@ -122,11 +121,13 @@ export function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
122
121
  console.log(
123
122
  "full file",
124
123
  yield* $(
125
- fs.read(file as unknown as RH, 0, offset + headerBytes.length)
126
- )
124
+ fs.read(file as unknown as RH, 0, offset + headerBytes.length),
125
+ ),
127
126
  );
128
127
 
129
- const filename: BlockFilename = `${hash.digest()}-L${level}-H${headerBytes.length}.jsonl`;
128
+ const filename: BlockFilename = `${hash.digest()}-L${level}-H${
129
+ headerBytes.length
130
+ }.jsonl`;
130
131
  console.log("renaming to" + filename);
131
132
  yield* $(fs.closeAndRename(file, filename));
132
133
 
@@ -138,7 +139,7 @@ export function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
138
139
  handle: WH,
139
140
  fs: FS,
140
141
  id: RawCoID,
141
- chunk: CoValueChunk
142
+ chunk: CoValueChunk,
142
143
  ): Effect.Effect<void, FSErr> {
143
144
  return Effect.gen(function* ($) {
144
145
  const walEntry: WalEntry = {
@@ -1,13 +1,13 @@
1
- import { Either } from 'effect';
2
- import { RawCoID, SessionID } from '../ids.js';
3
- import { MAX_RECOMMENDED_TX_SIZE } from '../index.js';
1
+ import { Either } from "effect";
2
+ import { RawCoID, SessionID } from "../ids.js";
3
+ import { MAX_RECOMMENDED_TX_SIZE } from "../index.js";
4
4
  import { CoValueKnownState, NewContentMessage } from "../sync.js";
5
5
  import { CoValueChunk } from "./index.js";
6
6
 
7
7
  export function contentSinceChunk(
8
8
  id: RawCoID,
9
9
  chunk: CoValueChunk,
10
- known?: CoValueKnownState
10
+ known?: CoValueKnownState,
11
11
  ): NewContentMessage[] {
12
12
  const newContentPieces: NewContentMessage[] = [];
13
13
 
@@ -19,7 +19,7 @@ export function contentSinceChunk(
19
19
  });
20
20
 
21
21
  for (const [sessionID, sessionsEntry] of Object.entries(
22
- chunk.sessionEntries
22
+ chunk.sessionEntries,
23
23
  )) {
24
24
  for (const entry of sessionsEntry) {
25
25
  const knownStart = known?.sessions[sessionID as SessionID] || 0;
@@ -29,13 +29,15 @@ export function contentSinceChunk(
29
29
  }
30
30
 
31
31
  const actuallyNewTransactions = entry.transactions.slice(
32
- Math.max(0, knownStart - entry.after)
32
+ Math.max(0, knownStart - entry.after),
33
33
  );
34
34
 
35
- const newAfter = entry.after +
35
+ const newAfter =
36
+ entry.after +
36
37
  (actuallyNewTransactions.length - entry.transactions.length);
37
38
 
38
- let newContentEntry = newContentPieces[0]?.new[sessionID as SessionID];
39
+ let newContentEntry =
40
+ newContentPieces[0]?.new[sessionID as SessionID];
39
41
 
40
42
  if (!newContentEntry) {
41
43
  newContentEntry = {
@@ -47,7 +49,7 @@ export function contentSinceChunk(
47
49
  newContentEntry;
48
50
  } else {
49
51
  newContentEntry.newTransactions.push(
50
- ...actuallyNewTransactions
52
+ ...actuallyNewTransactions,
51
53
  );
52
54
  newContentEntry.lastSignature = entry.lastSignature;
53
55
  }
@@ -65,7 +67,7 @@ export function chunkToKnownState(id: RawCoID, chunk: CoValueChunk) {
65
67
  };
66
68
 
67
69
  for (const [sessionID, sessionEntries] of Object.entries(
68
- chunk.sessionEntries
70
+ chunk.sessionEntries,
69
71
  )) {
70
72
  for (const entry of sessionEntries) {
71
73
  ourKnown.sessions[sessionID as SessionID] =
@@ -77,7 +79,7 @@ export function chunkToKnownState(id: RawCoID, chunk: CoValueChunk) {
77
79
 
78
80
  export function mergeChunks(
79
81
  chunkA: CoValueChunk,
80
- chunkB: CoValueChunk
82
+ chunkB: CoValueChunk,
81
83
  ): Either.Either<"nonContigous", CoValueChunk> {
82
84
  const header = chunkA.header || chunkB.header;
83
85
 
@@ -95,21 +97,26 @@ export function mergeChunks(
95
97
  const lastEntryOfA = sessionEntriesA[sessionEntriesA.length - 1]!;
96
98
  const firstEntryOfB = sessionEntriesB[0]!;
97
99
 
98
- if (lastEntryOfA.after + lastEntryOfA.transactions.length ===
99
- firstEntryOfB.after) {
100
+ if (
101
+ lastEntryOfA.after + lastEntryOfA.transactions.length ===
102
+ firstEntryOfB.after
103
+ ) {
100
104
  const newEntries = [];
101
105
  let bytesSinceLastSignature = 0;
102
106
  for (const entry of sessionEntriesA.concat(sessionEntriesB)) {
103
107
  const entryByteLength = entry.transactions.reduce(
104
- (sum, tx) => sum +
108
+ (sum, tx) =>
109
+ sum +
105
110
  (tx.privacy === "private"
106
111
  ? tx.encryptedChanges.length
107
112
  : tx.changes.length),
108
- 0
113
+ 0,
109
114
  );
110
- if (newEntries.length === 0 ||
115
+ if (
116
+ newEntries.length === 0 ||
111
117
  bytesSinceLastSignature + entryByteLength >
112
- MAX_RECOMMENDED_TX_SIZE) {
118
+ MAX_RECOMMENDED_TX_SIZE
119
+ ) {
113
120
  newEntries.push({
114
121
  after: entry.after,
115
122
  lastSignature: entry.lastSignature,
@@ -7,7 +7,7 @@ import {
7
7
  import { Effect, Either, SynchronizedRef } from "effect";
8
8
  import { RawCoID } from "../ids.js";
9
9
  import { CoValueHeader, Transaction } from "../coValueCore.js";
10
- import { Signature } from "../crypto.js";
10
+ import { Signature } from "../crypto/crypto.js";
11
11
  import {
12
12
  CoValueKnownState,
13
13
  NewContentMessage,
@@ -63,7 +63,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
63
63
  constructor(
64
64
  fs: FS,
65
65
  fromLocalNode: ReadableStream<SyncMessage>,
66
- toLocalNode: WritableStream<SyncMessage>
66
+ toLocalNode: WritableStream<SyncMessage>,
67
67
  ) {
68
68
  this.fs = fs;
69
69
  this.fromLocalNode = fromLocalNode.getReader();
@@ -76,7 +76,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
76
76
  let done = false;
77
77
  while (!done) {
78
78
  const result = yield* Effect.promise(() =>
79
- this.fromLocalNode.read()
79
+ this.fromLocalNode.read(),
80
80
  );
81
81
  done = result.done;
82
82
 
@@ -91,14 +91,14 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
91
91
  yield* this.sendNewContent(
92
92
  result.value.id,
93
93
  result.value,
94
- undefined
94
+ undefined,
95
95
  );
96
96
  }
97
97
  }
98
98
  }
99
99
 
100
100
  return;
101
- })
101
+ }),
102
102
  );
103
103
 
104
104
  setTimeout(() => this.compact(), 20000);
@@ -107,10 +107,10 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
107
107
  sendNewContent(
108
108
  id: RawCoID,
109
109
  known: CoValueKnownState | undefined,
110
- asDependencyOf: RawCoID | undefined
110
+ asDependencyOf: RawCoID | undefined,
111
111
  ): Effect.Effect<void, FSErr> {
112
112
  return SynchronizedRef.updateEffect(this.coValues, (coValues) =>
113
- this.sendNewContentInner(coValues, id, known, asDependencyOf)
113
+ this.sendNewContentInner(coValues, id, known, asDependencyOf),
114
114
  );
115
115
  }
116
116
 
@@ -118,7 +118,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
118
118
  coValues: { [id: `co_z${string}`]: CoValueChunk | undefined },
119
119
  id: RawCoID,
120
120
  known: CoValueKnownState | undefined,
121
- asDependencyOf: RawCoID | undefined
121
+ asDependencyOf: RawCoID | undefined,
122
122
  ): Effect.Effect<
123
123
  { [id: `co_z${string}`]: CoValueChunk | undefined },
124
124
  FSErr,
@@ -139,7 +139,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
139
139
  header: false,
140
140
  sessions: {},
141
141
  asDependencyOf,
142
- })
142
+ }),
143
143
  );
144
144
 
145
145
  return coValues;
@@ -153,7 +153,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
153
153
  coValues,
154
154
  coValue.header.ruleset.group,
155
155
  undefined,
156
- asDependencyOf || id
156
+ asDependencyOf || id,
157
157
  );
158
158
  } else if (
159
159
  !known?.header &&
@@ -182,7 +182,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
182
182
  coValues,
183
183
  account as CoID<RawCoValue>,
184
184
  undefined,
185
- asDependencyOf || id
185
+ asDependencyOf || id,
186
186
  );
187
187
  }
188
188
  }
@@ -190,7 +190,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
190
190
  const newContentMessages = contentSinceChunk(
191
191
  id,
192
192
  coValue,
193
- known
193
+ known,
194
194
  ).map((message) => ({ ...message, asDependencyOf }));
195
195
 
196
196
  const ourKnown: CoValueKnownState = chunkToKnownState(id, coValue);
@@ -200,7 +200,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
200
200
  action: "known",
201
201
  ...ourKnown,
202
202
  asDependencyOf,
203
- })
203
+ }),
204
204
  );
205
205
 
206
206
  for (const message of newContentMessages) {
@@ -213,7 +213,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
213
213
  }
214
214
 
215
215
  withWAL(
216
- handler: (wal: WH) => Effect.Effect<void, FSErr>
216
+ handler: (wal: WH) => Effect.Effect<void, FSErr>,
217
217
  ): Effect.Effect<void, FSErr> {
218
218
  return SynchronizedRef.updateEffect(this.currentWal, (wal) =>
219
219
  Effect.gen(this, function* () {
@@ -222,17 +222,17 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
222
222
  newWal = yield* this.fs.createFile(
223
223
  `wal-${new Date().toISOString()}-${Math.random()
224
224
  .toString(36)
225
- .slice(2)}.jsonl`
225
+ .slice(2)}.jsonl`,
226
226
  );
227
227
  }
228
228
  yield* handler(newWal);
229
229
  return newWal;
230
- })
230
+ }),
231
231
  );
232
232
  }
233
233
 
234
234
  handleNewContent(
235
- newContent: NewContentMessage
235
+ newContent: NewContentMessage,
236
236
  ): Effect.Effect<void, FSErr> {
237
237
  return SynchronizedRef.updateEffect(this.coValues, (coValues) =>
238
238
  Effect.gen(this, function* () {
@@ -253,8 +253,8 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
253
253
  newInSession.newTransactions,
254
254
  },
255
255
  ],
256
- ]
257
- )
256
+ ],
257
+ ),
258
258
  ),
259
259
  };
260
260
 
@@ -266,8 +266,8 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
266
266
  wal,
267
267
  this.fs,
268
268
  newContent.id,
269
- newContentAsChunk
270
- )
269
+ newContentAsChunk,
270
+ ),
271
271
  );
272
272
 
273
273
  return {
@@ -287,7 +287,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
287
287
  // )
288
288
  // );
289
289
  console.warn(
290
- "Incontiguous incoming update for " + newContent.id
290
+ "Incontiguous incoming update for " + newContent.id,
291
291
  );
292
292
  return coValues;
293
293
  }
@@ -295,7 +295,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
295
295
  const merged = mergeChunks(coValue, newContentAsChunk);
296
296
  if (Either.isRight(merged)) {
297
297
  yield* Effect.logWarning(
298
- "Non-contigous new content for " + newContent.id
298
+ "Non-contigous new content for " + newContent.id,
299
299
  );
300
300
 
301
301
  // yield* Effect.promise(() =>
@@ -314,27 +314,27 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
314
314
  wal,
315
315
  this.fs,
316
316
  newContent.id,
317
- newContentAsChunk
318
- )
317
+ newContentAsChunk,
318
+ ),
319
319
  );
320
320
 
321
321
  return { ...coValues, [newContent.id]: merged.left };
322
322
  }
323
323
  }
324
- })
324
+ }),
325
325
  );
326
326
  }
327
327
 
328
328
  loadCoValue<WH, RH, FS extends FileSystem<WH, RH>>(
329
329
  id: RawCoID,
330
- fs: FS
330
+ fs: FS,
331
331
  ): Effect.Effect<CoValueChunk | undefined, FSErr> {
332
332
  // return _loadChunkFromWal(id, fs);
333
333
  return Effect.gen(this, function* () {
334
334
  const files = this.fileCache || (yield* fs.listFiles());
335
335
  this.fileCache = files;
336
336
  const blockFiles = files.filter((name) =>
337
- name.startsWith("hash_")
337
+ name.startsWith("hash_"),
338
338
  ) as BlockFilename[];
339
339
 
340
340
  for (const blockFile of blockFiles) {
@@ -346,7 +346,12 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
346
346
 
347
347
  if (!cachedHeader) {
348
348
  cachedHeader = {};
349
- const header = yield* readHeader(blockFile, handle, size, fs);
349
+ const header = yield* readHeader(
350
+ blockFile,
351
+ handle,
352
+ size,
353
+ fs,
354
+ );
350
355
  for (const entry of header) {
351
356
  cachedHeader[entry.id] = {
352
357
  start: entry.start,
@@ -361,12 +366,11 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
361
366
  let result;
362
367
  if (headerEntry) {
363
368
  result = yield* readChunk(handle, headerEntry, fs);
364
-
365
369
  }
366
370
 
367
371
  yield* fs.close(handle);
368
372
 
369
- return result
373
+ return result;
370
374
  }
371
375
 
372
376
  return undefined;
@@ -379,7 +383,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
379
383
  const fileNames = yield* this.fs.listFiles();
380
384
 
381
385
  const walFiles = fileNames.filter((name) =>
382
- name.startsWith("wal-")
386
+ name.startsWith("wal-"),
383
387
  ) as WalFilename[];
384
388
  walFiles.sort();
385
389
 
@@ -394,7 +398,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
394
398
  yield* this.fs.close(wal);
395
399
  }
396
400
  return undefined;
397
- })
401
+ }),
398
402
  );
399
403
 
400
404
  for (const fileName of walFiles) {
@@ -402,7 +406,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
402
406
  yield* this.fs.openToRead(fileName);
403
407
  if (size === 0) {
404
408
  yield* this.fs.close(handle);
405
- continue
409
+ continue;
406
410
  }
407
411
  const bytes = yield* this.fs.read(handle, 0, size);
408
412
 
@@ -424,7 +428,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
424
428
  ", " +
425
429
  fileName,
426
430
  existingChunk,
427
- chunk
431
+ chunk,
428
432
  );
429
433
  } else {
430
434
  coValues.set(chunk.id, merged.left);
@@ -442,7 +446,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
442
446
  yield* this.fs.removeFile(walFile);
443
447
  }
444
448
  this.fileCache = undefined;
445
- })
449
+ }),
446
450
  );
447
451
 
448
452
  setTimeout(() => this.compact(), 5000);
@@ -464,7 +468,7 @@ export class LSMStorage<WH, RH, FS extends FileSystem<WH, RH>> {
464
468
  peer1role: "client",
465
469
  peer2role: "server",
466
470
  trace,
467
- }
471
+ },
468
472
  );
469
473
 
470
474
  new LSMStorage(fs, localNodeAsPeer.incoming, localNodeAsPeer.outgoing);
@@ -16,7 +16,7 @@ export function connectedPeers(
16
16
  trace?: boolean;
17
17
  peer1role?: Peer["role"];
18
18
  peer2role?: Peer["role"];
19
- } = {}
19
+ } = {},
20
20
  ): [Peer, Peer] {
21
21
  const [inRx1, inTx1] = newStreamPair<SyncMessage>(peer1id + "_in");
22
22
  const [outRx1, outTx1] = newStreamPair<SyncMessage>(peer1id + "_out");
@@ -29,7 +29,7 @@ export function connectedPeers(
29
29
  new TransformStream({
30
30
  transform(
31
31
  chunk: SyncMessage,
32
- controller: { enqueue: (msg: SyncMessage) => void }
32
+ controller: { enqueue: (msg: SyncMessage) => void },
33
33
  ) {
34
34
  trace &&
35
35
  console.debug(
@@ -40,12 +40,12 @@ export function connectedPeers(
40
40
  k === "changes" || k === "encryptedChanges"
41
41
  ? v.slice(0, 20) + "..."
42
42
  : v,
43
- 2
44
- )
43
+ 2,
44
+ ),
45
45
  );
46
46
  controller.enqueue(chunk);
47
47
  },
48
- })
48
+ }),
49
49
  )
50
50
  .pipeTo(inTx1);
51
51
 
@@ -54,7 +54,7 @@ export function connectedPeers(
54
54
  new TransformStream({
55
55
  transform(
56
56
  chunk: SyncMessage,
57
- controller: { enqueue: (msg: SyncMessage) => void }
57
+ controller: { enqueue: (msg: SyncMessage) => void },
58
58
  ) {
59
59
  trace &&
60
60
  console.debug(
@@ -65,12 +65,12 @@ export function connectedPeers(
65
65
  k === "changes" || k === "encryptedChanges"
66
66
  ? v.slice(0, 20) + "..."
67
67
  : v,
68
- 2
69
- )
68
+ 2,
69
+ ),
70
70
  );
71
71
  controller.enqueue(chunk);
72
72
  },
73
- })
73
+ }),
74
74
  )
75
75
  .pipeTo(inTx2);
76
76
 
@@ -92,7 +92,7 @@ export function connectedPeers(
92
92
  }
93
93
 
94
94
  export function newStreamPair<T>(
95
- pairName?: string
95
+ pairName?: string,
96
96
  ): [ReadableStream<T>, WritableStream<T>] {
97
97
  let queueLength = 0;
98
98
  let readerClosed = false;
@@ -138,13 +138,13 @@ export function newStreamPair<T>(
138
138
  new TransformStream<any, any>({
139
139
  transform(
140
140
  chunk: SyncMessage,
141
- controller: { enqueue: (msg: SyncMessage) => void }
141
+ controller: { enqueue: (msg: SyncMessage) => void },
142
142
  ) {
143
143
  queueLength -= 1;
144
144
  maybeReportQueueLength();
145
145
  controller.enqueue(chunk);
146
146
  },
147
- })
147
+ }),
148
148
  ) as ReadableStream<T>;
149
149
 
150
150
  let lastWritePromise = Promise.resolve();