cojson 0.4.7 → 0.4.13

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 (46) hide show
  1. package/dist/coValueCore.js +8 -9
  2. package/dist/coValueCore.js.map +1 -1
  3. package/dist/coValues/coList.js +3 -4
  4. package/dist/coValues/coList.js.map +1 -1
  5. package/dist/coValues/coMap.js +3 -4
  6. package/dist/coValues/coMap.js.map +1 -1
  7. package/dist/coValues/coStream.js +15 -10
  8. package/dist/coValues/coStream.js.map +1 -1
  9. package/dist/coValues/group.js +0 -11
  10. package/dist/coValues/group.js.map +1 -1
  11. package/dist/index.js +5 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/localNode.js +8 -6
  14. package/dist/localNode.js.map +1 -1
  15. package/dist/permissions.js +3 -2
  16. package/dist/permissions.js.map +1 -1
  17. package/dist/sync.js +21 -9
  18. package/dist/sync.js.map +1 -1
  19. package/dist/tests/testUtils.js +1 -1
  20. package/dist/tests/testUtils.js.map +1 -1
  21. package/dist/typeUtils/accountOrAgentIDfromSessionID.js +4 -0
  22. package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -0
  23. package/dist/typeUtils/expectGroup.js +13 -0
  24. package/dist/typeUtils/expectGroup.js.map +1 -0
  25. package/dist/typeUtils/isAccountID.js +4 -0
  26. package/dist/typeUtils/isAccountID.js.map +1 -0
  27. package/dist/typeUtils/isCoValue.js +11 -0
  28. package/dist/typeUtils/isCoValue.js.map +1 -0
  29. package/package.json +2 -2
  30. package/src/coValueCore.ts +12 -15
  31. package/src/coValues/coList.ts +4 -6
  32. package/src/coValues/coMap.ts +6 -8
  33. package/src/coValues/coStream.ts +40 -13
  34. package/src/coValues/group.ts +1 -14
  35. package/src/index.ts +4 -3
  36. package/src/localNode.ts +9 -7
  37. package/src/permissions.ts +3 -2
  38. package/src/sync.ts +26 -12
  39. package/src/tests/testUtils.ts +1 -1
  40. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +9 -0
  41. package/src/typeUtils/expectGroup.ts +15 -0
  42. package/src/typeUtils/isAccountID.ts +7 -0
  43. package/src/typeUtils/isCoValue.ts +18 -0
  44. package/dist/typeCheckers.js +0 -7
  45. package/dist/typeCheckers.js.map +0 -1
  46. package/src/typeCheckers.ts +0 -15
package/src/localNode.ts CHANGED
@@ -17,7 +17,6 @@ import {
17
17
  import {
18
18
  InviteSecret,
19
19
  Group,
20
- expectGroup,
21
20
  secretSeedFromInviteSecret,
22
21
  } from "./coValues/group.js";
23
22
  import { Peer, SyncManager } from "./sync.js";
@@ -36,6 +35,7 @@ import {
36
35
  } from "./coValues/account.js";
37
36
  import { CoMap } from "./coValues/coMap.js";
38
37
  import { CoValue } from "./index.js";
38
+ import { expectGroup } from "./typeUtils/expectGroup.js";
39
39
 
40
40
  /** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
41
41
 
@@ -199,10 +199,10 @@ export class LocalNode {
199
199
  }
200
200
 
201
201
  /** @internal */
202
- loadCoValue(id: RawCoID): Promise<CoValueCore> {
202
+ loadCoValue(id: RawCoID, onProgress?: (progress: number) => void): Promise<CoValueCore> {
203
203
  let entry = this.coValues[id];
204
204
  if (!entry) {
205
- entry = newLoadingState();
205
+ entry = newLoadingState(onProgress);
206
206
 
207
207
  this.coValues[id] = entry;
208
208
 
@@ -221,8 +221,8 @@ export class LocalNode {
221
221
  *
222
222
  * @category 3. Low-level
223
223
  */
224
- async load<T extends CoValue>(id: CoID<T>): Promise<T> {
225
- return (await this.loadCoValue(id)).getCurrentContent() as T;
224
+ async load<T extends CoValue>(id: CoID<T>, onProgress?: (progress: number) => void): Promise<T> {
225
+ return (await this.loadCoValue(id, onProgress)).getCurrentContent() as T;
226
226
  }
227
227
 
228
228
  /** @category 3. Low-level */
@@ -577,11 +577,12 @@ type CoValueState =
577
577
  state: "loading";
578
578
  done: Promise<CoValueCore>;
579
579
  resolve: (coValue: CoValueCore) => void;
580
+ onProgress?: (progress: number) => void;
580
581
  }
581
- | { state: "loaded"; coValue: CoValueCore };
582
+ | { state: "loaded"; coValue: CoValueCore; onProgress?: (progress: number) => void; };
582
583
 
583
584
  /** @internal */
584
- export function newLoadingState(): CoValueState {
585
+ export function newLoadingState(onProgress?: (progress: number) => void): CoValueState {
585
586
  let resolve: (coValue: CoValueCore) => void;
586
587
 
587
588
  const promise = new Promise<CoValueCore>((r) => {
@@ -592,5 +593,6 @@ export function newLoadingState(): CoValueState {
592
593
  state: "loading",
593
594
  done: promise,
594
595
  resolve: resolve!,
596
+ onProgress
595
597
  };
596
598
  }
@@ -5,12 +5,13 @@ import { KeyID } from "./crypto.js";
5
5
  import {
6
6
  CoValueCore,
7
7
  Transaction,
8
- accountOrAgentIDfromSessionID,
9
8
  } from "./coValueCore.js";
9
+ import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
10
10
  import { AgentID, RawCoID, SessionID, TransactionID } from "./ids.js";
11
11
  import { Account, AccountID, Profile } from "./coValues/account.js";
12
12
  import { parseJSON } from "./jsonStringify.js";
13
- import { EVERYONE, Everyone, expectGroup } from "./coValues/group.js";
13
+ import { EVERYONE, Everyone } from "./coValues/group.js";
14
+ import { expectGroup } from "./typeUtils/expectGroup.js";
14
15
 
15
16
  export type PermissionsDef =
16
17
  | { type: "group"; initialAdmin: AccountID | AgentID }
package/src/sync.ts CHANGED
@@ -225,12 +225,19 @@ export class SyncManager {
225
225
  peer.optimisticKnownStates[id] || emptyKnownState(id);
226
226
 
227
227
  const sendPieces = async () => {
228
+ let lastYield = performance.now();
228
229
  for (const [_i, piece] of newContentPieces.entries()) {
229
230
  // console.log(
230
231
  // `${id} -> ${peer.id}: Sending content piece ${i + 1}/${newContentPieces.length} header: ${!!piece.header}`,
231
232
  // // Object.values(piece.new).map((s) => s.newTransactions)
232
233
  // );
233
234
  await this.trySendToPeer(peer, piece);
235
+ if (performance.now() - lastYield > 10) {
236
+ await new Promise<void>((resolve) => {
237
+ setTimeout(resolve, 0);
238
+ });
239
+ lastYield = performance.now();
240
+ }
234
241
  }
235
242
  };
236
243
 
@@ -315,19 +322,20 @@ export class SyncManager {
315
322
 
316
323
  trySendToPeer(peer: PeerState, msg: SyncMessage) {
317
324
  return new Promise<void>((resolve) => {
318
- const timeout = setTimeout(() => {
319
- console.error(
320
- new Error(
321
- `Writing to peer ${peer.id} took >1s - this should never happen as write should resolve quickly or error`
322
- )
323
- );
324
- resolve();
325
- }, 1000);
325
+ const start = Date.now()
326
326
  peer.outgoing
327
327
  .write(msg)
328
328
  .then(() => {
329
- clearTimeout(timeout);
330
- resolve();
329
+ const end = Date.now();
330
+ if (end - start > 1000) {
331
+ console.error(
332
+ new Error(
333
+ `Writing to peer "${peer.id}" took ${Math.round((Date.now() - start)/100)/10}s - this should never happen as write should resolve quickly or error`
334
+ )
335
+ );
336
+ } else {
337
+ resolve();
338
+ }
331
339
  })
332
340
  .catch((e) => {
333
341
  console.error(
@@ -450,6 +458,7 @@ export class SyncManager {
450
458
  entry = {
451
459
  state: "loaded",
452
460
  coValue: coValue,
461
+ onProgress: entry.onProgress
453
462
  };
454
463
 
455
464
  this.local.coValues[msg.id] = entry;
@@ -509,6 +518,11 @@ export class SyncManager {
509
518
  );
510
519
  }
511
520
 
521
+ const theirTotalnTxs = Object.values(peer.optimisticKnownStates[msg.id]?.sessions || {}).reduce((sum, nTxs) => sum + nTxs, 0);
522
+ const ourTotalnTxs = Object.values(coValue.sessions).reduce((sum, session) => sum + session.transactions.length, 0);
523
+
524
+ entry.onProgress?.(ourTotalnTxs / theirTotalnTxs);
525
+
512
526
  if (!success) {
513
527
  console.error(
514
528
  "Failed to add transactions",
@@ -522,9 +536,9 @@ export class SyncManager {
522
536
  continue;
523
537
  }
524
538
 
525
- peerOptimisticKnownState.sessions[sessionID] =
539
+ peerOptimisticKnownState.sessions[sessionID] = Math.max(peerOptimisticKnownState.sessions[sessionID] || 0,
526
540
  newContentForSession.after +
527
- newContentForSession.newTransactions.length;
541
+ newContentForSession.newTransactions.length);
528
542
  }
529
543
 
530
544
  if (resolveAfterDone) {
@@ -1,7 +1,7 @@
1
1
  import { AgentSecret, createdNowUnique, getAgentID, newRandomAgentSecret } from "../crypto.js";
2
2
  import { newRandomSessionID } from "../coValueCore.js";
3
3
  import { LocalNode } from "../localNode.js";
4
- import { expectGroup } from "../coValues/group.js";
4
+ import { expectGroup } from "../typeUtils/expectGroup.js";
5
5
  import { AnonymousControlledAccount } from "../coValues/account.js";
6
6
  import { SessionID } from "../ids.js";
7
7
  // @ts-ignore
@@ -0,0 +1,9 @@
1
+ import { AgentID, SessionID } from "../ids.js";
2
+ import { AccountID } from "../coValues/account.js";
3
+
4
+
5
+ export function accountOrAgentIDfromSessionID(
6
+ sessionID: SessionID
7
+ ): AccountID | AgentID {
8
+ return sessionID.split("_session")[0] as AccountID | AgentID;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { expectMap, type CoValue } from "../coValue.js";
2
+ import { Group } from "../coValues/group.js";
3
+
4
+ export function expectGroup(content: CoValue): Group {
5
+ const map = expectMap(content);
6
+ if (map.core.header.ruleset.type !== "group") {
7
+ throw new Error("Expected group ruleset in group");
8
+ }
9
+
10
+ if (!(map instanceof Group)) {
11
+ throw new Error("Expected group");
12
+ }
13
+
14
+ return map;
15
+ }
@@ -0,0 +1,7 @@
1
+ import type { AccountID } from "../coValues/account.js";
2
+ import type { AgentID } from "../ids.js";
3
+
4
+
5
+ export function isAccountID(id: AccountID | AgentID): id is AccountID {
6
+ return id.startsWith("co_");
7
+ }
@@ -0,0 +1,18 @@
1
+ import { type CoValue } from "../coValue.js";
2
+ import type { JsonValue } from "../jsonValue.js";
3
+ import { CoMap } from "../coValues/coMap.js";
4
+ import { CoList } from "../coValues/coList.js";
5
+ import { CoStream } from "../coValues/coStream.js";
6
+ import { BinaryCoStream } from "../coValues/coStream.js";
7
+
8
+
9
+ export function isCoValue(
10
+ value: JsonValue | CoValue | undefined
11
+ ): value is CoValue {
12
+ return (
13
+ value instanceof CoMap ||
14
+ value instanceof CoList ||
15
+ value instanceof CoStream ||
16
+ value instanceof BinaryCoStream
17
+ );
18
+ }
@@ -1,7 +0,0 @@
1
- export function isCoValue(value) {
2
- return (typeof value === "object" && !!value && "id" in value && "headerMeta" in value && "core" in value);
3
- }
4
- export function isAccountID(id) {
5
- return id.startsWith("co_");
6
- }
7
- //# sourceMappingURL=typeCheckers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"typeCheckers.js","sourceRoot":"","sources":["../src/typeCheckers.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,SAAS,CACrB,KAAsC;IAEtC,OAAO,CACH,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,YAAY,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,CACpG,CAAC;AACN,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAuB;IAC/C,OAAO,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}
@@ -1,15 +0,0 @@
1
- import type { CoValue } from "./coValue.js";
2
- import type { AccountID, AgentID, JsonValue } from "./index.js";
3
-
4
-
5
- export function isCoValue(
6
- value: JsonValue | CoValue | undefined
7
- ): value is CoValue {
8
- return (
9
- typeof value === "object" && !!value && "id" in value && "headerMeta" in value && "core" in value
10
- );
11
- }
12
-
13
- export function isAccountID(id: AccountID | AgentID): id is AccountID {
14
- return id.startsWith("co_");
15
- }