cojson 0.9.10 → 0.9.11

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 (101) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/CHANGELOG.md +7 -0
  3. package/dist/native/PeerState.js +2 -1
  4. package/dist/native/PeerState.js.map +1 -1
  5. package/dist/native/PriorityBasedMessageQueue.js +54 -7
  6. package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
  7. package/dist/native/base64url.js +0 -6
  8. package/dist/native/base64url.js.map +1 -1
  9. package/dist/native/coValueCore.js +4 -10
  10. package/dist/native/coValueCore.js.map +1 -1
  11. package/dist/native/coValueState.js +5 -4
  12. package/dist/native/coValueState.js.map +1 -1
  13. package/dist/native/coValues/account.js +2 -1
  14. package/dist/native/coValues/account.js.map +1 -1
  15. package/dist/native/coValues/coList.js +0 -7
  16. package/dist/native/coValues/coList.js.map +1 -1
  17. package/dist/native/coValues/coStream.js +3 -8
  18. package/dist/native/coValues/coStream.js.map +1 -1
  19. package/dist/native/coValues/group.js +3 -2
  20. package/dist/native/coValues/group.js.map +1 -1
  21. package/dist/native/crypto/PureJSCrypto.js +2 -1
  22. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  23. package/dist/native/crypto/WasmCrypto.js +2 -1
  24. package/dist/native/crypto/WasmCrypto.js.map +1 -1
  25. package/dist/native/crypto/crypto.js +2 -4
  26. package/dist/native/crypto/crypto.js.map +1 -1
  27. package/dist/native/exports.js +2 -1
  28. package/dist/native/exports.js.map +1 -1
  29. package/dist/native/localNode.js +5 -6
  30. package/dist/native/localNode.js.map +1 -1
  31. package/dist/native/logger.js +58 -0
  32. package/dist/native/logger.js.map +1 -0
  33. package/dist/native/permissions.js +3 -4
  34. package/dist/native/permissions.js.map +1 -1
  35. package/dist/native/storage/FileSystem.js +0 -10
  36. package/dist/native/storage/FileSystem.js.map +1 -1
  37. package/dist/native/storage/index.js +14 -23
  38. package/dist/native/storage/index.js.map +1 -1
  39. package/dist/native/sync.js +20 -28
  40. package/dist/native/sync.js.map +1 -1
  41. package/dist/web/PeerState.js +2 -1
  42. package/dist/web/PeerState.js.map +1 -1
  43. package/dist/web/PriorityBasedMessageQueue.js +54 -7
  44. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  45. package/dist/web/base64url.js +0 -6
  46. package/dist/web/base64url.js.map +1 -1
  47. package/dist/web/coValueCore.js +4 -10
  48. package/dist/web/coValueCore.js.map +1 -1
  49. package/dist/web/coValueState.js +5 -4
  50. package/dist/web/coValueState.js.map +1 -1
  51. package/dist/web/coValues/account.js +2 -1
  52. package/dist/web/coValues/account.js.map +1 -1
  53. package/dist/web/coValues/coList.js +0 -7
  54. package/dist/web/coValues/coList.js.map +1 -1
  55. package/dist/web/coValues/coStream.js +3 -8
  56. package/dist/web/coValues/coStream.js.map +1 -1
  57. package/dist/web/coValues/group.js +3 -2
  58. package/dist/web/coValues/group.js.map +1 -1
  59. package/dist/web/crypto/PureJSCrypto.js +2 -1
  60. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  61. package/dist/web/crypto/WasmCrypto.js +2 -1
  62. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  63. package/dist/web/crypto/crypto.js +2 -4
  64. package/dist/web/crypto/crypto.js.map +1 -1
  65. package/dist/web/exports.js +2 -1
  66. package/dist/web/exports.js.map +1 -1
  67. package/dist/web/localNode.js +5 -6
  68. package/dist/web/localNode.js.map +1 -1
  69. package/dist/web/logger.js +58 -0
  70. package/dist/web/logger.js.map +1 -0
  71. package/dist/web/permissions.js +3 -4
  72. package/dist/web/permissions.js.map +1 -1
  73. package/dist/web/storage/FileSystem.js +0 -10
  74. package/dist/web/storage/FileSystem.js.map +1 -1
  75. package/dist/web/storage/index.js +14 -23
  76. package/dist/web/storage/index.js.map +1 -1
  77. package/dist/web/sync.js +20 -28
  78. package/dist/web/sync.js.map +1 -1
  79. package/package.json +1 -1
  80. package/src/PeerState.ts +4 -3
  81. package/src/PriorityBasedMessageQueue.ts +67 -11
  82. package/src/base64url.ts +1 -6
  83. package/src/coValueCore.ts +4 -10
  84. package/src/coValueState.ts +5 -4
  85. package/src/coValues/account.ts +2 -1
  86. package/src/coValues/coList.ts +0 -7
  87. package/src/coValues/coStream.ts +3 -8
  88. package/src/coValues/group.ts +3 -2
  89. package/src/crypto/PureJSCrypto.ts +2 -1
  90. package/src/crypto/WasmCrypto.ts +2 -1
  91. package/src/crypto/crypto.ts +2 -4
  92. package/src/exports.ts +2 -0
  93. package/src/localNode.ts +5 -9
  94. package/src/logger.ts +78 -0
  95. package/src/permissions.ts +3 -5
  96. package/src/storage/FileSystem.ts +0 -12
  97. package/src/storage/index.ts +21 -37
  98. package/src/sync.ts +20 -29
  99. package/src/tests/PeerState.test.ts +0 -3
  100. package/src/tests/PriorityBasedMessageQueue.test.ts +1 -1
  101. package/src/tests/logger.test.ts +145 -0
@@ -18,11 +18,12 @@ function promiseWithResolvers<R>() {
18
18
  };
19
19
  }
20
20
 
21
- export type QueueEntry = {
22
- msg: SyncMessage;
21
+ export type QueueEntry<V> = {
22
+ msg: V;
23
23
  promise: Promise<void>;
24
24
  resolve: () => void;
25
25
  reject: (_: unknown) => void;
26
+ next: QueueEntry<V> | undefined;
26
27
  };
27
28
 
28
29
  /**
@@ -33,10 +34,68 @@ type Tuple<T, N extends number, A extends unknown[] = []> = A extends {
33
34
  }
34
35
  ? A
35
36
  : Tuple<T, N, [...A, T]>;
36
- type QueueTuple = Tuple<QueueEntry[], 8>;
37
+ type QueueTuple = Tuple<Queue<SyncMessage>, 8>;
38
+
39
+ class Queue<V> {
40
+ head: QueueEntry<V> | undefined = undefined;
41
+ tail: QueueEntry<V> | undefined = undefined;
42
+
43
+ push(msg: V) {
44
+ const { promise, resolve, reject } = promiseWithResolvers<void>();
45
+ const entry: QueueEntry<V> = {
46
+ msg,
47
+ promise,
48
+ resolve,
49
+ reject,
50
+ next: undefined,
51
+ };
52
+
53
+ if (this.head === undefined) {
54
+ this.head = entry;
55
+ } else {
56
+ if (this.tail === undefined) {
57
+ throw new Error("Tail is null but head is not");
58
+ }
59
+
60
+ this.tail.next = entry;
61
+ }
62
+
63
+ this.tail = entry;
64
+
65
+ return entry;
66
+ }
67
+
68
+ pull() {
69
+ const entry = this.head;
70
+
71
+ if (entry) {
72
+ this.head = entry.next;
73
+ }
74
+
75
+ if (this.head === undefined) {
76
+ this.tail = undefined;
77
+ }
78
+
79
+ return entry;
80
+ }
81
+
82
+ isNonEmpty() {
83
+ return this.head !== undefined;
84
+ }
85
+ }
37
86
 
38
87
  export class PriorityBasedMessageQueue {
39
- private queues: QueueTuple = [[], [], [], [], [], [], [], []];
88
+ private queues: QueueTuple = [
89
+ new Queue(),
90
+ new Queue(),
91
+ new Queue(),
92
+ new Queue(),
93
+ new Queue(),
94
+ new Queue(),
95
+ new Queue(),
96
+ new Queue(),
97
+ ];
98
+
40
99
  queueSizeCounter = metrics
41
100
  .getMeter("cojson")
42
101
  .createUpDownCounter("jazz.messagequeue.size", {
@@ -52,22 +111,19 @@ export class PriorityBasedMessageQueue {
52
111
  constructor(private defaultPriority: CoValuePriority) {}
53
112
 
54
113
  public push(msg: SyncMessage) {
55
- const { promise, resolve, reject } = promiseWithResolvers<void>();
56
- const entry: QueueEntry = { msg, promise, resolve, reject };
57
-
58
114
  const priority = "priority" in msg ? msg.priority : this.defaultPriority;
59
115
 
60
- this.getQueue(priority).push(entry);
116
+ const entry = this.getQueue(priority).push(msg);
61
117
 
62
118
  this.queueSizeCounter.add(1, {
63
119
  priority,
64
120
  });
65
121
 
66
- return promise;
122
+ return entry.promise;
67
123
  }
68
124
 
69
125
  public pull() {
70
- const priority = this.queues.findIndex((queue) => queue.length > 0);
126
+ const priority = this.queues.findIndex((queue) => queue.isNonEmpty());
71
127
 
72
128
  if (priority === -1) {
73
129
  return;
@@ -77,6 +133,6 @@ export class PriorityBasedMessageQueue {
77
133
  priority,
78
134
  });
79
135
 
80
- return this.queues[priority]?.shift();
136
+ return this.queues[priority]?.pull();
81
137
  }
82
138
  }
package/src/base64url.ts CHANGED
@@ -43,12 +43,7 @@ export function bytesToBase64url(bytes: Uint8Array) {
43
43
  let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
44
44
  if (k === 1) base64 += "==";
45
45
  if (k === 2) base64 += "=";
46
- // const after = performance.now();
47
- // console.log(
48
- // "bytesToBase64url bandwidth in MB/s for length",
49
- // (1000 * bytes.length / (after - before)) / (1024 * 1024),
50
- // bytes.length
51
- // );
46
+
52
47
  return base64;
53
48
  }
54
49
 
@@ -24,6 +24,7 @@ import {
24
24
  import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
25
25
  import { JsonObject, JsonValue } from "./jsonValue.js";
26
26
  import { LocalNode, ResolveAccountAgentError } from "./localNode.js";
27
+ import { logger } from "./logger.js";
27
28
  import {
28
29
  PermissionsDef as RulesetDef,
29
30
  determineValidTransactions,
@@ -209,16 +210,10 @@ export class CoValueCore {
209
210
  .andThen((agent) => {
210
211
  const signerID = this.crypto.getAgentSignerID(agent);
211
212
 
212
- // const beforeHash = performance.now();
213
213
  const { expectedNewHash, newStreamingHash } = this.expectedNewHashAfter(
214
214
  sessionID,
215
215
  newTransactions,
216
216
  );
217
- // const afterHash = performance.now();
218
- // console.log(
219
- // "Hashing took",
220
- // afterHash - beforeHash
221
- // );
222
217
 
223
218
  if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
224
219
  return err({
@@ -391,7 +386,6 @@ export class CoValueCore {
391
386
  streamingHash.update(transaction);
392
387
  const after = performance.now();
393
388
  if (after - before > 1) {
394
- // console.log("Hashing blocked for", after - before);
395
389
  await new Promise((resolve) => setTimeout(resolve, 0));
396
390
  before = performance.now();
397
391
  }
@@ -540,7 +534,7 @@ export class CoValueCore {
540
534
  }
541
535
 
542
536
  if (!decryptedChanges) {
543
- console.error("Failed to decrypt transaction despite having key");
537
+ logger.error("Failed to decrypt transaction despite having key");
544
538
  continue;
545
539
  }
546
540
 
@@ -685,7 +679,7 @@ export class CoValueCore {
685
679
  if (secret) {
686
680
  return secret as KeySecret;
687
681
  } else {
688
- console.error(
682
+ logger.warn(
689
683
  `Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`,
690
684
  );
691
685
  }
@@ -725,7 +719,7 @@ export class CoValueCore {
725
719
  if (secret) {
726
720
  return secret as KeySecret;
727
721
  } else {
728
- console.error(
722
+ logger.warn(
729
723
  `Encrypting parent ${parentKey.id} key didn't decrypt ${keyID}`,
730
724
  );
731
725
  }
@@ -1,6 +1,7 @@
1
1
  import { PeerState } from "./PeerState.js";
2
2
  import { CoValueCore } from "./coValueCore.js";
3
3
  import { RawCoID } from "./ids.js";
4
+ import { logger } from "./logger.js";
4
5
  import { PeerID } from "./sync.js";
5
6
 
6
7
  export const CO_VALUE_LOADING_MAX_RETRIES = 5;
@@ -282,7 +283,7 @@ async function loadCoValueFromPeers(
282
283
  ...coValueEntry.state.coValue.knownState(),
283
284
  })
284
285
  .catch((err) => {
285
- console.error(`Failed to push load message to peer ${peer.id}`, err);
286
+ logger.warn(`Failed to push load message to peer ${peer.id}`, err);
286
287
  });
287
288
  } else {
288
289
  /**
@@ -296,14 +297,14 @@ async function loadCoValueFromPeers(
296
297
  sessions: {},
297
298
  })
298
299
  .catch((err) => {
299
- console.error(`Failed to push load message to peer ${peer.id}`, err);
300
+ logger.warn(`Failed to push load message to peer ${peer.id}`, err);
300
301
  });
301
302
  }
302
303
 
303
304
  if (coValueEntry.state.type === "loading") {
304
305
  const timeout = setTimeout(() => {
305
306
  if (coValueEntry.state.type === "loading") {
306
- console.error("Failed to load coValue from peer", peer.id);
307
+ logger.warn("Failed to load coValue from peer", peer.id);
307
308
  coValueEntry.dispatch({
308
309
  type: "not-found-in-peer",
309
310
  peerId: peer.id,
@@ -356,7 +357,7 @@ function sleep(ms: number) {
356
357
  function getPeersWithoutErrors(peers: PeerState[], coValueId: RawCoID) {
357
358
  return peers.filter((p) => {
358
359
  if (p.erroredCoValues.has(coValueId)) {
359
- console.error(
360
+ logger.warn(
360
361
  `Skipping load on errored coValue ${coValueId} from peer ${p.id}`,
361
362
  );
362
363
  return false;
@@ -16,6 +16,7 @@ import {
16
16
  import { AgentID } from "../ids.js";
17
17
  import { JsonObject } from "../jsonValue.js";
18
18
  import { LocalNode } from "../localNode.js";
19
+ import { logger } from "../logger.js";
19
20
  import type { AccountRole } from "../permissions.js";
20
21
  import { RawCoMap } from "./coMap.js";
21
22
  import { InviteSecret, RawGroup } from "./group.js";
@@ -59,7 +60,7 @@ export class RawAccount<
59
60
  );
60
61
 
61
62
  if (agents.length !== 1) {
62
- console.warn("Account has " + agents.length + " agents", this.id);
63
+ logger.warn("Account has " + agents.length + " agents", this.id);
63
64
  }
64
65
 
65
66
  this._cachedCurrentAgentID = agents[0];
@@ -133,10 +133,6 @@ export class RawCoListView<
133
133
  change.before.txIndex
134
134
  ]?.[change.before.changeIdx];
135
135
  if (!beforeEntry) {
136
- // console.error(
137
- // "Insertion before missing op " +
138
- // change.before
139
- // );
140
136
  continue;
141
137
  }
142
138
  beforeEntry.predecessors.splice(0, 0, {
@@ -156,9 +152,6 @@ export class RawCoListView<
156
152
  change.after.txIndex
157
153
  ]?.[change.after.changeIdx];
158
154
  if (!afterEntry) {
159
- // console.error(
160
- // "Insertion after missing op " + change.after
161
- // );
162
155
  continue;
163
156
  }
164
157
  afterEntry.successors.push({
@@ -3,6 +3,7 @@ import { CoID, RawCoValue } from "../coValue.js";
3
3
  import { CoValueCore } from "../coValueCore.js";
4
4
  import { AgentID, SessionID, TransactionID } from "../ids.js";
5
5
  import { JsonObject, JsonValue } from "../jsonValue.js";
6
+ import { logger } from "../logger.js";
6
7
  import { CoValueKnownState } from "../sync.js";
7
8
  import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
8
9
  import { isAccountID } from "../typeUtils/isAccountID.js";
@@ -309,7 +310,7 @@ export class RawBinaryCoStreamView<
309
310
  const start = items[0];
310
311
 
311
312
  if (start?.type !== "start") {
312
- console.error("Invalid binary stream start", start);
313
+ logger.error("Invalid binary stream start", start);
313
314
  return;
314
315
  }
315
316
 
@@ -328,7 +329,7 @@ export class RawBinaryCoStreamView<
328
329
  }
329
330
 
330
331
  if (item.type !== "chunk") {
331
- console.error("Invalid binary stream chunk", item);
332
+ logger.error("Invalid binary stream chunk", item);
332
333
  return undefined;
333
334
  }
334
335
 
@@ -382,7 +383,6 @@ export class RawBinaryCoStream<
382
383
  chunk: Uint8Array,
383
384
  privacy: "private" | "trusting" = "private",
384
385
  ): void {
385
- // const before = performance.now();
386
386
  this.push(
387
387
  {
388
388
  type: "chunk",
@@ -391,11 +391,6 @@ export class RawBinaryCoStream<
391
391
  privacy,
392
392
  false,
393
393
  );
394
- // const after = performance.now();
395
- // console.log(
396
- // "pushBinaryStreamChunk bandwidth in MB/s",
397
- // (1000 * chunk.length) / (after - before) / (1024 * 1024)
398
- // );
399
394
  }
400
395
 
401
396
  endBinaryStream(privacy: "private" | "trusting" = "private") {
@@ -13,6 +13,7 @@ import {
13
13
  isParentGroupReference,
14
14
  } from "../ids.js";
15
15
  import { JsonObject } from "../jsonValue.js";
16
+ import { logger } from "../logger.js";
16
17
  import { AccountRole, Role } from "../permissions.js";
17
18
  import { expectGroup } from "../typeUtils/expectGroup.js";
18
19
  import {
@@ -153,7 +154,7 @@ export class RawGroup<
153
154
  child.state.type === "unavailable"
154
155
  ) {
155
156
  child.loadFromPeers(peers).catch(() => {
156
- console.error(`Failed to load child group ${id}`);
157
+ logger.error(`Failed to load child group ${id}`);
157
158
  });
158
159
  }
159
160
 
@@ -321,7 +322,7 @@ export class RawGroup<
321
322
  const secret = this.core.getReadKey(keyID);
322
323
 
323
324
  if (!secret) {
324
- console.error("Can't find key", keyID);
325
+ logger.error("Can't find key", keyID);
325
326
  continue;
326
327
  }
327
328
 
@@ -7,6 +7,7 @@ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
7
7
  import { RawCoID, TransactionID } from "../ids.js";
8
8
  import { Stringified, stableStringify } from "../jsonStringify.js";
9
9
  import { JsonValue } from "../jsonValue.js";
10
+ import { logger } from "../logger.js";
10
11
  import {
11
12
  CryptoProvider,
12
13
  Encrypted,
@@ -192,7 +193,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
192
193
  try {
193
194
  return JSON.parse(textDecoder.decode(plaintext));
194
195
  } catch (e) {
195
- console.error("Failed to decrypt/parse sealed message", e);
196
+ logger.error("Failed to decrypt/parse sealed message", e);
196
197
  return undefined;
197
198
  }
198
199
  }
@@ -15,6 +15,7 @@ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
15
15
  import { RawCoID, TransactionID } from "../ids.js";
16
16
  import { Stringified, stableStringify } from "../jsonStringify.js";
17
17
  import { JsonValue } from "../jsonValue.js";
18
+ import { logger } from "../logger.js";
18
19
  import {
19
20
  CryptoProvider,
20
21
  Encrypted,
@@ -240,7 +241,7 @@ export class WasmCrypto extends CryptoProvider<Uint8Array> {
240
241
  try {
241
242
  return JSON.parse(textDecoder.decode(plaintext));
242
243
  } catch (e) {
243
- console.error("Failed to decrypt/parse sealed message", e);
244
+ logger.error("Failed to decrypt/parse sealed message", e);
244
245
  return undefined;
245
246
  }
246
247
  }
@@ -4,6 +4,7 @@ import { AgentID, RawCoID, TransactionID } from "../ids.js";
4
4
  import { SessionID } from "../ids.js";
5
5
  import { Stringified, parseJSON, stableStringify } from "../jsonStringify.js";
6
6
  import { JsonValue } from "../jsonValue.js";
7
+ import { logger } from "../logger.js";
7
8
 
8
9
  export type SignerSecret = `signerSecret_z${string}`;
9
10
  export type SignerID = `signer_z${string}`;
@@ -159,7 +160,7 @@ export abstract class CryptoProvider<Blake3State = any> {
159
160
  try {
160
161
  return parseJSON(this.decryptRaw(encrypted, keySecret, nOnceMaterial));
161
162
  } catch (e) {
162
- console.error("Decryption error", e);
163
+ logger.error("Decryption error", e);
163
164
  return undefined;
164
165
  }
165
166
  }
@@ -305,10 +306,7 @@ export class StreamingHash {
305
306
 
306
307
  update(value: JsonValue): Uint8Array {
307
308
  const encoded = textEncoder.encode(stableStringify(value));
308
- // const before = performance.now();
309
309
  this.state = this.crypto.blake3IncrementalUpdate(this.state, encoded);
310
- // const after = performance.now();
311
- // console.log(`Hashing throughput in MB/s`, 1000 * (encoded.length / (after - before)) / (1024 * 1024));
312
310
  return encoded;
313
311
  }
314
312
 
package/src/exports.ts CHANGED
@@ -74,6 +74,7 @@ import {
74
74
 
75
75
  type Value = JsonValue | AnyRawCoValue;
76
76
 
77
+ import { logger } from "./logger.js";
77
78
  import { getPriorityFromHeader } from "./priority.js";
78
79
  import { FileSystem } from "./storage/FileSystem.js";
79
80
  import { BlockFilename, LSMStorage, WalFilename } from "./storage/index.js";
@@ -141,6 +142,7 @@ export {
141
142
  emptyKnownState,
142
143
  RawCoPlainText,
143
144
  stringifyOpID,
145
+ logger,
144
146
  };
145
147
 
146
148
  export type {
package/src/localNode.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  } from "./coValues/group.js";
28
28
  import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
29
29
  import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
30
+ import { logger } from "./logger.js";
30
31
  import { Peer, PeerID, SyncManager } from "./sync.js";
31
32
  import { expectGroup } from "./typeUtils/expectGroup.js";
32
33
 
@@ -230,7 +231,7 @@ export class LocalNode {
230
231
 
231
232
  return node;
232
233
  } catch (e) {
233
- console.error("Error withLoadedAccount", e);
234
+ logger.error("Error withLoadedAccount", e);
234
235
  throw e;
235
236
  }
236
237
  }
@@ -269,7 +270,7 @@ export class LocalNode {
269
270
  this.syncManager.getServerAndStoragePeers(skipLoadingFromPeer);
270
271
 
271
272
  await entry.loadFromPeers(peers).catch((e) => {
272
- console.error("Error loading from peers", id, e);
273
+ logger.error("Error loading from peers", id, e);
273
274
  });
274
275
  }
275
276
 
@@ -311,8 +312,6 @@ export class LocalNode {
311
312
  let stopped = false;
312
313
  let unsubscribe!: () => void;
313
314
 
314
- // console.log("Subscribing to " + id);
315
-
316
315
  this.load(id)
317
316
  .then((coValue) => {
318
317
  if (stopped) {
@@ -325,11 +324,10 @@ export class LocalNode {
325
324
  unsubscribe = coValue.subscribe(callback);
326
325
  })
327
326
  .catch((e) => {
328
- console.error("Error subscribing to ", id, e);
327
+ logger.error("Error subscribing to ", id, e);
329
328
  });
330
329
 
331
330
  return () => {
332
- console.log("Unsubscribing from " + id);
333
331
  stopped = true;
334
332
  unsubscribe?.();
335
333
  };
@@ -390,9 +388,7 @@ export class LocalNode {
390
388
  (existingRole === "reader" && inviteRole === "readerInvite") ||
391
389
  (existingRole && inviteRole === "writeOnlyInvite")
392
390
  ) {
393
- console.debug(
394
- "Not accepting invite that would replace or downgrade role",
395
- );
391
+ logger.debug("Not accepting invite that would replace or downgrade role");
396
392
  return;
397
393
  }
398
394
 
package/src/logger.ts ADDED
@@ -0,0 +1,78 @@
1
+ export enum LogLevel {
2
+ DEBUG = 0,
3
+ INFO = 1,
4
+ WARN = 2,
5
+ ERROR = 3,
6
+ NONE = 4,
7
+ }
8
+
9
+ export interface LogSystem {
10
+ debug(message: string, ...args: any[]): void;
11
+ info(message: string, ...args: any[]): void;
12
+ warn(message: string, ...args: any[]): void;
13
+ error(message: string, ...args: any[]): void;
14
+ }
15
+
16
+ // Default console-based logging system
17
+ export class ConsoleLogSystem implements LogSystem {
18
+ debug(message: string, ...args: any[]) {
19
+ console.debug(message, ...args);
20
+ }
21
+ info(message: string, ...args: any[]) {
22
+ console.info(message, ...args);
23
+ }
24
+ warn(message: string, ...args: any[]) {
25
+ console.warn(message, ...args);
26
+ }
27
+ error(message: string, ...args: any[]) {
28
+ console.error(message, ...args);
29
+ }
30
+ }
31
+
32
+ export class Logger {
33
+ private level: LogLevel;
34
+ private logSystem: LogSystem;
35
+
36
+ constructor(
37
+ level: LogLevel = LogLevel.INFO,
38
+ logSystem: LogSystem = new ConsoleLogSystem(),
39
+ ) {
40
+ this.level = level;
41
+ this.logSystem = logSystem;
42
+ }
43
+
44
+ setLevel(level: LogLevel) {
45
+ this.level = level;
46
+ }
47
+
48
+ setLogSystem(logSystem: LogSystem) {
49
+ this.logSystem = logSystem;
50
+ }
51
+
52
+ debug(message: string, ...args: any[]) {
53
+ if (this.level <= LogLevel.DEBUG) {
54
+ this.logSystem.debug(message, ...args);
55
+ }
56
+ }
57
+
58
+ info(message: string, ...args: any[]) {
59
+ if (this.level <= LogLevel.INFO) {
60
+ this.logSystem.info(message, ...args);
61
+ }
62
+ }
63
+
64
+ warn(message: string, ...args: any[]) {
65
+ if (this.level <= LogLevel.WARN) {
66
+ this.logSystem.warn(message, ...args);
67
+ }
68
+ }
69
+
70
+ error(message: string, ...args: any[]) {
71
+ if (this.level <= LogLevel.ERROR) {
72
+ this.logSystem.error(message, ...args);
73
+ }
74
+ }
75
+ }
76
+
77
+ // Create default logger instance
78
+ export const logger = new Logger();
@@ -14,6 +14,7 @@ import {
14
14
  } from "./ids.js";
15
15
  import { parseJSON } from "./jsonStringify.js";
16
16
  import { JsonValue } from "./jsonValue.js";
17
+ import { logger } from "./logger.js";
17
18
  import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
18
19
  import { expectGroup } from "./typeUtils/expectGroup.js";
19
20
 
@@ -46,7 +47,7 @@ function logPermissionError(...args: unknown[]) {
46
47
  return;
47
48
  }
48
49
 
49
- console.warn(...args);
50
+ logger.warn("Permission error", ...args);
50
51
  }
51
52
 
52
53
  export function determineValidTransactions(
@@ -204,7 +205,6 @@ function determineValidTransactionsForGroup(
204
205
  const writeKeys = new Set<string>();
205
206
 
206
207
  for (const { sessionID, txIndex, tx } of allTransactionsSorted) {
207
- // console.log("before", { memberState, validTransactions });
208
208
  const transactor = accountOrAgentIDfromSessionID(sessionID);
209
209
 
210
210
  if (tx.privacy === "private") {
@@ -458,8 +458,6 @@ function determineValidTransactionsForGroup(
458
458
 
459
459
  memberState[affectedMember] = change.value;
460
460
  validTransactions.push({ txID: { sessionID, txIndex }, tx });
461
-
462
- // console.log("after", { memberState, validTransactions });
463
461
  }
464
462
 
465
463
  return { validTransactions, memberState };
@@ -473,7 +471,7 @@ function agentInAccountOrMemberInGroup(
473
471
  return groupAtTime.currentAgentID().match(
474
472
  (agentID) => agentID,
475
473
  (e) => {
476
- console.error(
474
+ logger.error(
477
475
  "Error while determining current agent ID in valid transactions",
478
476
  e,
479
477
  );
@@ -87,26 +87,15 @@ export async function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
87
87
  const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
88
88
  await fs.append(file, headerBytes);
89
89
 
90
- // console.log(
91
- // "full file",
92
- // yield* $(
93
- // fs.read(file as unknown as RH, 0, offset + headerBytes.length),
94
- // ),
95
- // );
96
-
97
90
  const filename: BlockFilename = `L${level}-${(blockNumber + "").padStart(
98
91
  3,
99
92
  "0",
100
93
  )}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${
101
94
  headerBytes.length
102
95
  }.jsonl`;
103
- // console.log("renaming to" + filename);
104
96
  await fs.closeAndRename(file, filename);
105
97
 
106
98
  return filename;
107
-
108
- // console.log("Wrote block", filename, blockHeader);
109
- // console.log("IDs in block", blockHeader.map(e => e.id));
110
99
  }
111
100
 
112
101
  export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
@@ -120,6 +109,5 @@ export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
120
109
  ...chunk,
121
110
  };
122
111
  const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
123
- console.log("writing to WAL", handle, id, bytes.length);
124
112
  return fs.append(handle, bytes);
125
113
  }