@automerge/automerge-repo 1.0.6 → 1.0.8
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/.eslintrc +1 -1
- package/dist/DocHandle.d.ts +8 -8
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +4 -8
- package/dist/DocUrl.d.ts.map +1 -1
- package/dist/Repo.d.ts +6 -3
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +20 -19
- package/dist/helpers/cbor.d.ts +2 -2
- package/dist/helpers/cbor.d.ts.map +1 -1
- package/dist/helpers/cbor.js +1 -1
- package/dist/helpers/debounce.d.ts +14 -0
- package/dist/helpers/debounce.d.ts.map +1 -0
- package/dist/helpers/debounce.js +21 -0
- package/dist/helpers/pause.d.ts.map +1 -1
- package/dist/helpers/pause.js +3 -1
- package/dist/helpers/tests/network-adapter-tests.d.ts.map +1 -1
- package/dist/helpers/tests/network-adapter-tests.js +2 -2
- package/dist/helpers/throttle.d.ts +28 -0
- package/dist/helpers/throttle.d.ts.map +1 -0
- package/dist/helpers/throttle.js +39 -0
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/network/NetworkAdapter.d.ts +3 -3
- package/dist/network/NetworkAdapter.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.d.ts +2 -2
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +30 -18
- package/dist/network/messages.d.ts +38 -68
- package/dist/network/messages.d.ts.map +1 -1
- package/dist/network/messages.js +13 -21
- package/dist/storage/StorageSubsystem.d.ts +1 -1
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +9 -9
- package/dist/synchronizer/CollectionSynchronizer.d.ts +3 -3
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +3 -3
- package/dist/synchronizer/DocSynchronizer.d.ts +4 -3
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +25 -34
- package/dist/synchronizer/Synchronizer.d.ts +2 -2
- package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/fuzz/fuzz.ts +8 -6
- package/fuzz/tsconfig.json +8 -0
- package/package.json +5 -13
- package/src/DocHandle.ts +12 -15
- package/src/DocUrl.ts +3 -1
- package/src/Repo.ts +36 -29
- package/src/helpers/cbor.ts +4 -4
- package/src/helpers/debounce.ts +25 -0
- package/src/helpers/headsAreSame.ts +1 -1
- package/src/helpers/pause.ts +7 -2
- package/src/helpers/tests/network-adapter-tests.ts +3 -3
- package/src/helpers/throttle.ts +43 -0
- package/src/helpers/withTimeout.ts +2 -2
- package/src/index.ts +36 -29
- package/src/network/NetworkAdapter.ts +7 -3
- package/src/network/NetworkSubsystem.ts +31 -23
- package/src/network/messages.ts +88 -151
- package/src/storage/StorageSubsystem.ts +12 -12
- package/src/synchronizer/CollectionSynchronizer.ts +7 -16
- package/src/synchronizer/DocSynchronizer.ts +42 -53
- package/src/synchronizer/Synchronizer.ts +2 -2
- package/src/types.ts +8 -3
- package/test/CollectionSynchronizer.test.ts +58 -53
- package/test/DocHandle.test.ts +35 -36
- package/test/DocSynchronizer.test.ts +5 -8
- package/test/Network.test.ts +1 -0
- package/test/Repo.test.ts +229 -158
- package/test/StorageSubsystem.test.ts +6 -9
- package/test/helpers/DummyNetworkAdapter.ts +9 -4
- package/test/helpers/DummyStorageAdapter.ts +4 -2
- package/test/tsconfig.json +8 -0
- package/typedoc.json +3 -3
- package/.mocharc.json +0 -5
- package/dist/EphemeralData.d.ts +0 -20
- package/dist/EphemeralData.d.ts.map +0 -1
- package/dist/EphemeralData.js +0 -1
- package/src/EphemeralData.ts +0 -17
|
@@ -1,45 +1,18 @@
|
|
|
1
|
-
import { SessionId } from "../
|
|
2
|
-
export { type SessionId } from "../EphemeralData.js";
|
|
3
|
-
import { DocumentId, PeerId } from "../types.js";
|
|
4
|
-
export declare function isValidMessage(message: NetworkAdapterMessage): message is SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
|
|
5
|
-
export declare function isDocumentUnavailableMessage(message: NetworkAdapterMessage): message is DocumentUnavailableMessage;
|
|
6
|
-
export declare function isRequestMessage(message: NetworkAdapterMessage): message is RequestMessage;
|
|
7
|
-
export declare function isSyncMessage(message: NetworkAdapterMessage): message is SyncMessage;
|
|
8
|
-
export declare function isEphemeralMessage(message: NetworkAdapterMessage | MessageContents): message is EphemeralMessage | EphemeralMessageContents;
|
|
9
|
-
export interface SyncMessageEnvelope {
|
|
10
|
-
senderId: PeerId;
|
|
11
|
-
}
|
|
12
|
-
export interface SyncMessageContents {
|
|
13
|
-
type: "sync";
|
|
14
|
-
data: Uint8Array;
|
|
15
|
-
targetId: PeerId;
|
|
16
|
-
documentId: DocumentId;
|
|
17
|
-
}
|
|
1
|
+
import { DocumentId, PeerId, SessionId } from "../types.js";
|
|
18
2
|
/**
|
|
19
3
|
* A sync message for a particular document
|
|
20
4
|
*/
|
|
21
5
|
export type SyncMessage = {
|
|
6
|
+
type: "sync";
|
|
22
7
|
/** The peer ID of the sender of this message */
|
|
23
8
|
senderId: PeerId;
|
|
24
|
-
type: "sync";
|
|
25
|
-
/** The automerge sync message */
|
|
26
|
-
data: Uint8Array;
|
|
27
9
|
/** The peer ID of the recipient of this message */
|
|
28
10
|
targetId: PeerId;
|
|
11
|
+
/** The automerge sync message */
|
|
12
|
+
data: Uint8Array;
|
|
29
13
|
/** The document ID of the document this message is for */
|
|
30
14
|
documentId: DocumentId;
|
|
31
15
|
};
|
|
32
|
-
export interface EphemeralMessageEnvelope {
|
|
33
|
-
senderId: PeerId;
|
|
34
|
-
count: number;
|
|
35
|
-
sessionId: SessionId;
|
|
36
|
-
}
|
|
37
|
-
export interface EphemeralMessageContents {
|
|
38
|
-
type: "ephemeral";
|
|
39
|
-
targetId: PeerId;
|
|
40
|
-
documentId: DocumentId;
|
|
41
|
-
data: Uint8Array;
|
|
42
|
-
}
|
|
43
16
|
/** An ephemeral message
|
|
44
17
|
*
|
|
45
18
|
* @remarks
|
|
@@ -51,41 +24,30 @@ export interface EphemeralMessageContents {
|
|
|
51
24
|
* we have already seen.
|
|
52
25
|
* */
|
|
53
26
|
export type EphemeralMessage = {
|
|
54
|
-
|
|
27
|
+
type: "ephemeral";
|
|
28
|
+
/** The peer ID of the sender of this message */
|
|
55
29
|
senderId: PeerId;
|
|
30
|
+
/** The peer ID of the recipient of this message */
|
|
31
|
+
targetId: PeerId;
|
|
56
32
|
/** A sequence number which must be incremented for each message sent by this peer */
|
|
57
33
|
count: number;
|
|
58
34
|
/** The ID of the session this message is part of. The sequence number for a given session always increases */
|
|
59
35
|
sessionId: SessionId;
|
|
60
|
-
type: "ephemeral";
|
|
61
|
-
/** The peer this message is for */
|
|
62
|
-
targetId: PeerId;
|
|
63
36
|
/** The document ID this message pertains to */
|
|
64
37
|
documentId: DocumentId;
|
|
65
38
|
/** The actual data of the message */
|
|
66
39
|
data: Uint8Array;
|
|
67
40
|
};
|
|
68
|
-
export interface DocumentUnavailableMessageContents {
|
|
69
|
-
type: "doc-unavailable";
|
|
70
|
-
documentId: DocumentId;
|
|
71
|
-
targetId: PeerId;
|
|
72
|
-
}
|
|
73
41
|
/** Sent by a {@link Repo} to indicate that it does not have the document and none of it's connected peers do either */
|
|
74
42
|
export type DocumentUnavailableMessage = {
|
|
75
|
-
/** The peer who sent this message */
|
|
76
|
-
senderId: PeerId;
|
|
77
43
|
type: "doc-unavailable";
|
|
44
|
+
/** The peer ID of the sender of this message */
|
|
45
|
+
senderId: PeerId;
|
|
46
|
+
/** The peer ID of the recipient of this message */
|
|
47
|
+
targetId: PeerId;
|
|
78
48
|
/** The document which the peer claims it doesn't have */
|
|
79
49
|
documentId: DocumentId;
|
|
80
|
-
/** The peer this message is for */
|
|
81
|
-
targetId: PeerId;
|
|
82
50
|
};
|
|
83
|
-
export interface RequestMessageContents {
|
|
84
|
-
type: "request";
|
|
85
|
-
data: Uint8Array;
|
|
86
|
-
targetId: PeerId;
|
|
87
|
-
documentId: DocumentId;
|
|
88
|
-
}
|
|
89
51
|
/** Sent by a {@link Repo} to request a document from a peer
|
|
90
52
|
*
|
|
91
53
|
* @remarks
|
|
@@ -93,40 +55,48 @@ export interface RequestMessageContents {
|
|
|
93
55
|
* as the initial sync message when asking the other peer if it has the document.
|
|
94
56
|
* */
|
|
95
57
|
export type RequestMessage = {
|
|
96
|
-
/** The peer who sent this message */
|
|
97
|
-
senderId: PeerId;
|
|
98
58
|
type: "request";
|
|
59
|
+
/** The peer ID of the sender of this message */
|
|
60
|
+
senderId: PeerId;
|
|
61
|
+
/** The peer ID of the recipient of this message */
|
|
62
|
+
targetId: PeerId;
|
|
99
63
|
/** The initial automerge sync message */
|
|
100
64
|
data: Uint8Array;
|
|
101
|
-
/** The peer this message is for */
|
|
102
|
-
targetId: PeerId;
|
|
103
65
|
/** The document ID this message requests */
|
|
104
66
|
documentId: DocumentId;
|
|
105
67
|
};
|
|
106
|
-
export type MessageContents = SyncMessageContents | EphemeralMessageContents | RequestMessageContents | DocumentUnavailableMessageContents;
|
|
107
|
-
/** The type of messages that {@link Repo} sends and receive to {@link NetworkAdapter}s */
|
|
108
|
-
export type Message = SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
|
|
109
|
-
export type SynchronizerMessage = SyncMessage | RequestMessage | DocumentUnavailableMessage | EphemeralMessage;
|
|
110
68
|
/** Notify the network that we have arrived so everyone knows our peer ID */
|
|
111
69
|
export type ArriveMessage = {
|
|
112
|
-
/** Our peer ID */
|
|
113
|
-
senderId: PeerId;
|
|
114
70
|
type: "arrive";
|
|
71
|
+
/** The peer ID of the sender of this message */
|
|
72
|
+
senderId: PeerId;
|
|
73
|
+
/** Arrive messages don't have a targetId */
|
|
74
|
+
targetId: never;
|
|
115
75
|
};
|
|
116
76
|
/** Respond to an arriving peer with our peer ID */
|
|
117
77
|
export type WelcomeMessage = {
|
|
118
|
-
|
|
78
|
+
type: "welcome";
|
|
79
|
+
/** The peer ID of the recipient sender this message */
|
|
119
80
|
senderId: PeerId;
|
|
120
|
-
/** The ID of the
|
|
81
|
+
/** The peer ID of the recipient of this message */
|
|
121
82
|
targetId: PeerId;
|
|
122
|
-
type: "welcome";
|
|
123
83
|
};
|
|
124
|
-
/**
|
|
84
|
+
/** These are message types that a {@link NetworkAdapter} surfaces to a {@link Repo}. */
|
|
85
|
+
export type RepoMessage = SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
|
|
86
|
+
/** These are all the message types that a {@link NetworkAdapter} might see.
|
|
125
87
|
*
|
|
126
88
|
* @remarks
|
|
127
|
-
* It is not _required_ that a {@link NetworkAdapter} use
|
|
128
|
-
*
|
|
129
|
-
* transport. However, this type is a useful default.
|
|
89
|
+
* It is not _required_ that a {@link NetworkAdapter} use these types: They are free to use
|
|
90
|
+
* whatever message type makes sense for their transport. However, this type is a useful default.
|
|
130
91
|
* */
|
|
131
|
-
export type
|
|
92
|
+
export type Message = RepoMessage | ArriveMessage | WelcomeMessage;
|
|
93
|
+
/**
|
|
94
|
+
* The contents of a message, without the sender ID or other properties added by the {@link NetworkSubsystem})
|
|
95
|
+
*/
|
|
96
|
+
export type MessageContents<T extends Message = Message> = T extends EphemeralMessage ? Omit<T, "senderId" | "count" | "sessionId"> : Omit<T, "senderId">;
|
|
97
|
+
export declare const isValidRepoMessage: (message: Message) => message is RepoMessage;
|
|
98
|
+
export declare const isDocumentUnavailableMessage: (msg: Message) => msg is DocumentUnavailableMessage;
|
|
99
|
+
export declare const isRequestMessage: (msg: Message) => msg is RequestMessage;
|
|
100
|
+
export declare const isSyncMessage: (msg: Message) => msg is SyncMessage;
|
|
101
|
+
export declare const isEphemeralMessage: (msg: Message) => msg is EphemeralMessage;
|
|
132
102
|
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3D;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IAEZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAEhB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAEhB,iCAAiC;IACjC,IAAI,EAAE,UAAU,CAAA;IAEhB,0DAA0D;IAC1D,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;;;;;KASK;AACL,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,WAAW,CAAA;IAEjB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAEhB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAEhB,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAA;IAEb,8GAA8G;IAC9G,SAAS,EAAE,SAAS,CAAA;IAEpB,+CAA+C;IAC/C,UAAU,EAAE,UAAU,CAAA;IAEtB,qCAAqC;IACrC,IAAI,EAAE,UAAU,CAAA;CACjB,CAAA;AAED,uHAAuH;AACvH,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,iBAAiB,CAAA;IAEvB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAEhB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAEhB,yDAAyD;IACzD,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;KAKK;AACL,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,SAAS,CAAA;IAEf,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAEhB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAEhB,yCAAyC;IACzC,IAAI,EAAE,UAAU,CAAA;IAEhB,4CAA4C;IAC5C,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,CAAA;IAEd,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAEhB,4CAA4C;IAC5C,QAAQ,EAAE,KAAK,CAAA;CAChB,CAAA;AAED,mDAAmD;AACnD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,SAAS,CAAA;IAEf,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAA;IAEhB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wFAAwF;AACxF,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,0BAA0B,CAAA;AAE9B;;;;;KAKK;AACL,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAA;AAElE;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IACrD,CAAC,SAAS,gBAAgB,GACtB,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC,GAC3C,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;AAIzB,eAAO,MAAM,kBAAkB,YAAa,OAAO,2BAOT,CAAA;AAG1C,eAAO,MAAM,4BAA4B,QAAS,OAAO,sCACzB,CAAA;AAEhC,eAAO,MAAM,gBAAgB,QAAS,OAAO,0BACrB,CAAA;AAExB,eAAO,MAAM,aAAa,QAAS,OAAO,uBACrB,CAAA;AAErB,eAAO,MAAM,kBAAkB,QAAS,OAAO,4BACrB,CAAA"}
|
package/dist/network/messages.js
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export
|
|
14
|
-
return message.type === "request";
|
|
15
|
-
}
|
|
16
|
-
export function isSyncMessage(message) {
|
|
17
|
-
return message.type === "sync";
|
|
18
|
-
}
|
|
19
|
-
export function isEphemeralMessage(message) {
|
|
20
|
-
return message.type === "ephemeral";
|
|
21
|
-
}
|
|
1
|
+
// TYPE GUARDS
|
|
2
|
+
export const isValidRepoMessage = (message) => typeof message === "object" &&
|
|
3
|
+
typeof message.type === "string" &&
|
|
4
|
+
typeof message.senderId === "string" &&
|
|
5
|
+
(isSyncMessage(message) ||
|
|
6
|
+
isEphemeralMessage(message) ||
|
|
7
|
+
isRequestMessage(message) ||
|
|
8
|
+
isDocumentUnavailableMessage(message));
|
|
9
|
+
// prettier-ignore
|
|
10
|
+
export const isDocumentUnavailableMessage = (msg) => msg.type === "doc-unavailable";
|
|
11
|
+
export const isRequestMessage = (msg) => msg.type === "request";
|
|
12
|
+
export const isSyncMessage = (msg) => msg.type === "sync";
|
|
13
|
+
export const isEphemeralMessage = (msg) => msg.type === "ephemeral";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as A from "@automerge/automerge/next";
|
|
2
|
-
import { StorageAdapter } from "./StorageAdapter.js";
|
|
3
2
|
import { type DocumentId } from "../types.js";
|
|
3
|
+
import { StorageAdapter } from "./StorageAdapter.js";
|
|
4
4
|
export type ChunkType = "snapshot" | "incremental";
|
|
5
5
|
export declare class StorageSubsystem {
|
|
6
6
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAK9C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAUhE,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;gBAQf,cAAc,EAAE,cAAc;IAuDpC,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IA0B/D,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAanE,MAAM,CAAC,UAAU,EAAE,UAAU;CAmCpC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as A from "@automerge/automerge/next";
|
|
2
|
-
import * as sha256 from "fast-sha256";
|
|
3
|
-
import { mergeArrays } from "../helpers/mergeArrays.js";
|
|
4
2
|
import debug from "debug";
|
|
3
|
+
import * as sha256 from "fast-sha256";
|
|
5
4
|
import { headsAreSame } from "../helpers/headsAreSame.js";
|
|
5
|
+
import { mergeArrays } from "../helpers/mergeArrays.js";
|
|
6
6
|
function keyHash(binary) {
|
|
7
7
|
const hash = sha256.hash(binary);
|
|
8
8
|
const hashArray = Array.from(new Uint8Array(hash)); // convert buffer to byte array
|
|
@@ -10,8 +10,8 @@ function keyHash(binary) {
|
|
|
10
10
|
return hashHex;
|
|
11
11
|
}
|
|
12
12
|
function headsHash(heads) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const encoder = new TextEncoder();
|
|
14
|
+
const headsbinary = mergeArrays(heads.map((h) => encoder.encode(h)));
|
|
15
15
|
return keyHash(headsbinary);
|
|
16
16
|
}
|
|
17
17
|
export class StorageSubsystem {
|
|
@@ -89,18 +89,18 @@ export class StorageSubsystem {
|
|
|
89
89
|
if (!this.#shouldSave(documentId, doc)) {
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
const sourceChunks = this.#chunkInfos.get(documentId) ?? [];
|
|
93
93
|
if (this.#shouldCompact(sourceChunks)) {
|
|
94
|
-
this.#saveTotal(documentId, doc, sourceChunks);
|
|
94
|
+
void this.#saveTotal(documentId, doc, sourceChunks);
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
97
|
-
this.#saveIncremental(documentId, doc);
|
|
97
|
+
void this.#saveIncremental(documentId, doc);
|
|
98
98
|
}
|
|
99
99
|
this.#storedHeads.set(documentId, A.getHeads(doc));
|
|
100
100
|
}
|
|
101
101
|
async remove(documentId) {
|
|
102
|
-
this.#storageAdapter.removeRange([documentId, "snapshot"]);
|
|
103
|
-
this.#storageAdapter.removeRange([documentId, "incremental"]);
|
|
102
|
+
void this.#storageAdapter.removeRange([documentId, "snapshot"]);
|
|
103
|
+
void this.#storageAdapter.removeRange([documentId, "incremental"]);
|
|
104
104
|
}
|
|
105
105
|
#shouldSave(documentId, doc) {
|
|
106
106
|
const oldHeads = this.#storedHeads.get(documentId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Repo } from "../Repo.js";
|
|
2
|
-
import {
|
|
2
|
+
import { RepoMessage } from "../network/messages.js";
|
|
3
|
+
import { DocumentId, PeerId } from "../types.js";
|
|
3
4
|
import { Synchronizer } from "./Synchronizer.js";
|
|
4
|
-
import { SynchronizerMessage } from "../network/messages.js";
|
|
5
5
|
/** A CollectionSynchronizer is responsible for synchronizing a DocCollection with peers. */
|
|
6
6
|
export declare class CollectionSynchronizer extends Synchronizer {
|
|
7
7
|
#private;
|
|
@@ -11,7 +11,7 @@ export declare class CollectionSynchronizer extends Synchronizer {
|
|
|
11
11
|
* When we receive a sync message for a document we haven't got in memory, we
|
|
12
12
|
* register it with the repo and start synchronizing
|
|
13
13
|
*/
|
|
14
|
-
receiveMessage(message:
|
|
14
|
+
receiveMessage(message: RepoMessage): Promise<void>;
|
|
15
15
|
/**
|
|
16
16
|
* Starts synchronizing the given document with all peers that we share it generously with.
|
|
17
17
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIhD,4FAA4F;AAC5F,qBAAa,sBAAuB,SAAQ,YAAY;;IAU1C,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAiC9B;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,WAAW;IAyBzC;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,UAAU;IAYlC,cAAc,CAAC,UAAU,EAAE,UAAU;IAIrC,2DAA2D;IAC3D,OAAO,CAAC,MAAM,EAAE,MAAM;IAgBtB,uDAAuD;IACvD,UAAU,CAAC,MAAM,EAAE,MAAM;CAQ1B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
import { stringifyAutomergeUrl } from "../DocUrl.js";
|
|
2
3
|
import { DocSynchronizer } from "./DocSynchronizer.js";
|
|
3
4
|
import { Synchronizer } from "./Synchronizer.js";
|
|
4
|
-
import debug from "debug";
|
|
5
5
|
const log = debug("automerge-repo:collectionsync");
|
|
6
6
|
/** A CollectionSynchronizer is responsible for synchronizing a DocCollection with peers. */
|
|
7
7
|
export class CollectionSynchronizer extends Synchronizer {
|
|
@@ -85,7 +85,7 @@ export class CollectionSynchronizer extends Synchronizer {
|
|
|
85
85
|
this.#peers.add(peerId);
|
|
86
86
|
for (const docSynchronizer of Object.values(this.#docSynchronizers)) {
|
|
87
87
|
const { documentId } = docSynchronizer;
|
|
88
|
-
this.repo.sharePolicy(peerId, documentId).then(okToShare => {
|
|
88
|
+
void this.repo.sharePolicy(peerId, documentId).then(okToShare => {
|
|
89
89
|
if (okToShare)
|
|
90
90
|
docSynchronizer.beginSync([peerId]);
|
|
91
91
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DocHandle } from "../DocHandle.js";
|
|
2
|
+
import { EphemeralMessage, RepoMessage, RequestMessage, SyncMessage } from "../network/messages.js";
|
|
2
3
|
import { PeerId } from "../types.js";
|
|
3
4
|
import { Synchronizer } from "./Synchronizer.js";
|
|
4
|
-
import { EphemeralMessage, RequestMessage, SynchronizerMessage, SyncMessage } from "../network/messages.js";
|
|
5
5
|
type PeerDocumentStatus = "unknown" | "has" | "unavailable" | "wants";
|
|
6
6
|
/**
|
|
7
7
|
* DocSynchronizer takes a handle to an Automerge document, and receives & dispatches sync messages
|
|
@@ -10,13 +10,14 @@ type PeerDocumentStatus = "unknown" | "has" | "unavailable" | "wants";
|
|
|
10
10
|
export declare class DocSynchronizer extends Synchronizer {
|
|
11
11
|
#private;
|
|
12
12
|
private handle;
|
|
13
|
-
|
|
13
|
+
syncDebounceRate: number;
|
|
14
|
+
constructor(handle: DocHandle<unknown>);
|
|
14
15
|
get peerStates(): Record<PeerId, PeerDocumentStatus>;
|
|
15
16
|
get documentId(): import("../types.js").DocumentId;
|
|
16
17
|
hasPeer(peerId: PeerId): boolean;
|
|
17
18
|
beginSync(peerIds: PeerId[]): void;
|
|
18
19
|
endSync(peerId: PeerId): void;
|
|
19
|
-
receiveMessage(message:
|
|
20
|
+
receiveMessage(message: RepoMessage): void;
|
|
20
21
|
receiveEphemeralMessage(message: EphemeralMessage): void;
|
|
21
22
|
receiveSyncMessage(message: SyncMessage | RequestMessage): void;
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAKV,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAEL,gBAAgB,EAEhB,WAAW,EACX,cAAc,EACd,WAAW,EAEZ,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,KAAK,kBAAkB,GAAG,SAAS,GAAG,KAAK,GAAG,aAAa,GAAG,OAAO,CAAA;AAErE;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;;IAgBnC,OAAO,CAAC,MAAM;IAd1B,gBAAgB,SAAM;gBAcF,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC;IAqB9C,IAAI,UAAU,uCAEb;IAED,IAAI,UAAU,qCAEb;IA8FD,OAAO,CAAC,MAAM,EAAE,MAAM;IAItB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE;IAqC3B,OAAO,CAAC,MAAM,EAAE,MAAM;IAKtB,cAAc,CAAC,OAAO,EAAE,WAAW;IAkBnC,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;IAuBjD,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc;CA4EzD"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as A from "@automerge/automerge/next";
|
|
2
|
-
import {
|
|
3
|
-
import { Synchronizer } from "./Synchronizer.js";
|
|
2
|
+
import { decode } from "cbor-x";
|
|
4
3
|
import debug from "debug";
|
|
4
|
+
import { READY, REQUESTING, UNAVAILABLE, } from "../DocHandle.js";
|
|
5
5
|
import { isRequestMessage, } from "../network/messages.js";
|
|
6
|
-
import {
|
|
6
|
+
import { Synchronizer } from "./Synchronizer.js";
|
|
7
|
+
import { throttle } from "../helpers/throttle.js";
|
|
7
8
|
/**
|
|
8
9
|
* DocSynchronizer takes a handle to an Automerge document, and receives & dispatches sync messages
|
|
9
10
|
* to bring it inline with all other peers' versions.
|
|
@@ -11,8 +12,7 @@ import { decode } from "cbor-x";
|
|
|
11
12
|
export class DocSynchronizer extends Synchronizer {
|
|
12
13
|
handle;
|
|
13
14
|
#log;
|
|
14
|
-
|
|
15
|
-
#opsLog;
|
|
15
|
+
syncDebounceRate = 100;
|
|
16
16
|
/** Active peers */
|
|
17
17
|
#peers = [];
|
|
18
18
|
#peerDocumentStatuses = {};
|
|
@@ -24,10 +24,8 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
24
24
|
super();
|
|
25
25
|
this.handle = handle;
|
|
26
26
|
const docId = handle.documentId.slice(0, 5);
|
|
27
|
-
this.#conciseLog = debug(`automerge-repo:concise:docsync:${docId}`); // Only logs one line per receive/send
|
|
28
27
|
this.#log = debug(`automerge-repo:docsync:${docId}`);
|
|
29
|
-
|
|
30
|
-
handle.on("change", () => this.#syncWithPeers());
|
|
28
|
+
handle.on("change", throttle(() => this.#syncWithPeers(), this.syncDebounceRate));
|
|
31
29
|
handle.on("ephemeral-message-outbound", payload => this.#broadcastToPeers(payload));
|
|
32
30
|
// Process pending sync messages immediately after the handle becomes ready.
|
|
33
31
|
void (async () => {
|
|
@@ -49,18 +47,19 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
49
47
|
return;
|
|
50
48
|
this.#peers.forEach(peerId => this.#sendSyncMessage(peerId, doc));
|
|
51
49
|
}
|
|
52
|
-
async #broadcastToPeers({ data }) {
|
|
50
|
+
async #broadcastToPeers({ data, }) {
|
|
53
51
|
this.#log(`broadcastToPeers`, this.#peers);
|
|
54
52
|
this.#peers.forEach(peerId => this.#sendEphemeralMessage(peerId, data));
|
|
55
53
|
}
|
|
56
54
|
#sendEphemeralMessage(peerId, data) {
|
|
57
55
|
this.#log(`sendEphemeralMessage ->${peerId}`);
|
|
58
|
-
|
|
56
|
+
const message = {
|
|
59
57
|
type: "ephemeral",
|
|
60
58
|
targetId: peerId,
|
|
61
59
|
documentId: this.handle.documentId,
|
|
62
60
|
data,
|
|
63
|
-
}
|
|
61
|
+
};
|
|
62
|
+
this.emit("message", message);
|
|
64
63
|
}
|
|
65
64
|
#getSyncState(peerId) {
|
|
66
65
|
if (!this.#peers.includes(peerId)) {
|
|
@@ -85,10 +84,9 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
85
84
|
const [newSyncState, message] = A.generateSyncMessage(doc, syncState);
|
|
86
85
|
this.#setSyncState(peerId, newSyncState);
|
|
87
86
|
if (message) {
|
|
88
|
-
|
|
89
|
-
const decoded = A.decodeSyncMessage(message);
|
|
87
|
+
const isNew = A.getHeads(doc).length === 0;
|
|
90
88
|
if (!this.handle.isReady() &&
|
|
91
|
-
|
|
89
|
+
isNew &&
|
|
92
90
|
newSyncState.sharedHeads.length === 0 &&
|
|
93
91
|
!Object.values(this.#peerDocumentStatuses).includes("has") &&
|
|
94
92
|
this.#peerDocumentStatuses[peerId] === "unknown") {
|
|
@@ -109,30 +107,17 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
109
107
|
});
|
|
110
108
|
}
|
|
111
109
|
// if we have sent heads, then the peer now has or will have the document
|
|
112
|
-
if (
|
|
110
|
+
if (!isNew) {
|
|
113
111
|
this.#peerDocumentStatuses[peerId] = "has";
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
114
|
}
|
|
117
|
-
#logMessage = (label, message) => {
|
|
118
|
-
// This is real expensive...
|
|
119
|
-
return;
|
|
120
|
-
const size = message.byteLength;
|
|
121
|
-
const logText = `${label} ${size}b`;
|
|
122
|
-
const decoded = A.decodeSyncMessage(message);
|
|
123
|
-
this.#conciseLog(logText);
|
|
124
|
-
this.#log(logText, decoded);
|
|
125
|
-
// expanding is expensive, so only do it if we're logging at this level
|
|
126
|
-
const expanded = this.#opsLog.enabled
|
|
127
|
-
? decoded.changes.flatMap((change) => A.decodeChange(change).ops.map((op) => JSON.stringify(op)))
|
|
128
|
-
: null;
|
|
129
|
-
this.#opsLog(logText, expanded);
|
|
130
|
-
};
|
|
131
115
|
/// PUBLIC
|
|
132
116
|
hasPeer(peerId) {
|
|
133
117
|
return this.#peers.includes(peerId);
|
|
134
118
|
}
|
|
135
119
|
beginSync(peerIds) {
|
|
120
|
+
const newPeers = new Set(peerIds.filter(peerId => !this.#peers.includes(peerId)));
|
|
136
121
|
this.#log(`beginSync: ${peerIds.join(", ")}`);
|
|
137
122
|
// HACK: if we have a sync state already, we round-trip it through the encoding system to make
|
|
138
123
|
// sure state is preserved. This prevents an infinite loop caused by failed attempts to send
|
|
@@ -149,10 +134,15 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
149
134
|
// we register out peers first, then say that sync has started
|
|
150
135
|
this.#syncStarted = true;
|
|
151
136
|
this.#checkDocUnavailable();
|
|
152
|
-
|
|
137
|
+
const wasUnavailable = doc === undefined;
|
|
138
|
+
if (wasUnavailable && newPeers.size == 0) {
|
|
153
139
|
return;
|
|
140
|
+
}
|
|
141
|
+
// If the doc is unavailable we still need a blank document to generate
|
|
142
|
+
// the sync message from
|
|
143
|
+
const theDoc = doc ?? A.init();
|
|
154
144
|
peerIds.forEach(peerId => {
|
|
155
|
-
this.#sendSyncMessage(peerId,
|
|
145
|
+
this.#sendSyncMessage(peerId, theDoc);
|
|
156
146
|
});
|
|
157
147
|
});
|
|
158
148
|
}
|
|
@@ -181,7 +171,7 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
181
171
|
if (message.documentId !== this.handle.documentId)
|
|
182
172
|
throw new Error(`channelId doesn't match documentId`);
|
|
183
173
|
const { senderId, data } = message;
|
|
184
|
-
const contents = decode(data);
|
|
174
|
+
const contents = decode(new Uint8Array(data));
|
|
185
175
|
this.handle.emit("ephemeral-message", {
|
|
186
176
|
handle: this.handle,
|
|
187
177
|
senderId,
|
|
@@ -234,11 +224,12 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
234
224
|
this.#peers
|
|
235
225
|
.filter(peerId => this.#peerDocumentStatuses[peerId] === "wants")
|
|
236
226
|
.forEach(peerId => {
|
|
237
|
-
|
|
227
|
+
const message = {
|
|
238
228
|
type: "doc-unavailable",
|
|
239
229
|
documentId: this.handle.documentId,
|
|
240
230
|
targetId: peerId,
|
|
241
|
-
}
|
|
231
|
+
};
|
|
232
|
+
this.emit("message", message);
|
|
242
233
|
});
|
|
243
234
|
this.handle.unavailable();
|
|
244
235
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "eventemitter3";
|
|
2
|
-
import {
|
|
2
|
+
import { MessageContents, RepoMessage } from "../network/messages.js";
|
|
3
3
|
export declare abstract class Synchronizer extends EventEmitter<SynchronizerEvents> {
|
|
4
|
-
abstract receiveMessage(message:
|
|
4
|
+
abstract receiveMessage(message: RepoMessage): void;
|
|
5
5
|
}
|
|
6
6
|
export interface SynchronizerEvents {
|
|
7
7
|
message: (arg: MessageContents) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAErE,8BAAsB,YAAa,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IACzE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CACpD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;CACxC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export type BinaryDocumentId = Uint8Array & {
|
|
|
20
20
|
};
|
|
21
21
|
/** A branded type for peer IDs */
|
|
22
22
|
export type PeerId = string & {
|
|
23
|
-
__peerId:
|
|
23
|
+
__peerId: true;
|
|
24
|
+
};
|
|
25
|
+
/** A randomly generated string created when the {@link Repo} starts up */
|
|
26
|
+
export type SessionId = string & {
|
|
27
|
+
__SessionId: true;
|
|
24
28
|
};
|
|
25
29
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;GACG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;GACG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,aAAa,EAAE,IAAI,CAAA;CAAE,CAAA;AAE3D;GACG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IAAE,kBAAkB,EAAE,IAAI,CAAA;CAAE,CAAA;AAExE,kCAAkC;AAClC,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAA;AAEhD,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,WAAW,EAAE,IAAI,CAAA;CAAE,CAAA"}
|
package/fuzz/fuzz.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import assert from "assert"
|
|
2
1
|
import { MessageChannelNetworkAdapter } from "@automerge/automerge-repo-network-messagechannel"
|
|
3
2
|
import * as Automerge from "@automerge/automerge/next"
|
|
4
|
-
|
|
5
|
-
import { DocHandle, DocumentId, PeerId, SharePolicy } from "../src"
|
|
3
|
+
import assert from "assert"
|
|
6
4
|
import { eventPromise } from "../src/helpers/eventPromise.js"
|
|
7
5
|
import { pause } from "../src/helpers/pause.js"
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import {
|
|
7
|
+
DocHandle,
|
|
8
|
+
DocumentId,
|
|
9
|
+
PeerId,
|
|
10
|
+
Repo,
|
|
11
|
+
SharePolicy,
|
|
12
|
+
} from "../src/index.js"
|
|
11
13
|
import { getRandomItem } from "../test/helpers/getRandomItem.js"
|
|
12
14
|
|
|
13
15
|
interface TestDoc {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "A repository object to manage a collection of automerge documents",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"watch": "npm-watch build",
|
|
13
13
|
"test:coverage": "c8 --reporter=lcov --reporter=html --reporter=text yarn test",
|
|
14
|
-
"test": "
|
|
14
|
+
"test": "vitest",
|
|
15
15
|
"test:watch": "npm-watch test",
|
|
16
16
|
"test:log": "cross-env DEBUG='automerge-repo:*' yarn test",
|
|
17
17
|
"fuzz": "ts-node --esm --experimentalSpecifierResolution=node fuzz/fuzz.ts"
|
|
@@ -20,18 +20,10 @@
|
|
|
20
20
|
"crypto": false
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"
|
|
24
|
-
"@types/debug": "^4.1.7",
|
|
25
|
-
"@types/node": "^20.4.8",
|
|
26
|
-
"@types/uuid": "^8.3.4",
|
|
27
|
-
"@types/ws": "^8.5.3",
|
|
28
|
-
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
|
29
|
-
"@typescript-eslint/parser": "^5.33.0",
|
|
30
|
-
"http-server": "^14.1.0",
|
|
31
|
-
"typescript": "^5.1.6"
|
|
23
|
+
"http-server": "^14.1.0"
|
|
32
24
|
},
|
|
33
25
|
"peerDependencies": {
|
|
34
|
-
"@automerge/automerge": "^2.1.
|
|
26
|
+
"@automerge/automerge": "^2.1.5"
|
|
35
27
|
},
|
|
36
28
|
"dependencies": {
|
|
37
29
|
"bs58check": "^3.0.1",
|
|
@@ -65,5 +57,5 @@
|
|
|
65
57
|
"publishConfig": {
|
|
66
58
|
"access": "public"
|
|
67
59
|
},
|
|
68
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "d244a36aebab52a86f91b5427bbe8ab2800bf2f4"
|
|
69
61
|
}
|