Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@automerge/automerge-repo

Package Overview
Dependencies
Maintainers
4
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@automerge/automerge-repo - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

dist/network/NetworkAdapterInterface.d.ts

9

dist/DocHandle.js

@@ -204,7 +204,6 @@ import * as A from "@automerge/automerge/next";

#statePromise(awaitStates) {
if (!Array.isArray(awaitStates))
awaitStates = [awaitStates];
return Promise.any(awaitStates.map(state => waitFor(this.#machine, s => s.matches(state), {
timeout: this.#timeoutDelay * 2, // use a longer delay here so as not to race with other delays
})));
const awaitStatesArray = Array.isArray(awaitStates) ? awaitStates : [awaitStates];
return waitFor(this.#machine, s => awaitStatesArray.some((state) => s.matches(state)),
// use a longer delay here so as not to race with other delays
{ timeout: this.#timeoutDelay * 2 });
}

@@ -211,0 +210,0 @@ // PUBLIC

@@ -1,2 +0,2 @@

import { type NetworkAdapter } from "../../index.js";
import type { NetworkAdapterInterface } from "../../network/NetworkAdapterInterface.js";
/**

@@ -15,3 +15,3 @@ * Runs a series of tests against a set of three peers, each represented by one or more instantiated

export declare function runAdapterTests(_setup: SetupFn, title?: string): void;
type Network = NetworkAdapter | NetworkAdapter[];
type Network = NetworkAdapterInterface | NetworkAdapterInterface[];
export type SetupFn = () => Promise<{

@@ -18,0 +18,0 @@ adapters: [Network, Network, Network];

import assert from "assert";
import { describe, it } from "vitest";
import { describe, expect, it } from "vitest";
import { Repo } from "../../index.js";

@@ -113,2 +113,17 @@ import { eventPromise, eventPromises } from "../eventPromise.js";

});
it("emits a peer-candidate event with proper peer metadata when a peer connects", async () => {
const { adapters, teardown } = await setup();
const a = adapters[0][0];
const b = adapters[1][0];
const bPromise = eventPromise(b, "peer-candidate");
const aPeerMetadata = { storageId: "a" };
b.connect("b", { storageId: "b" });
a.connect("a", aPeerMetadata);
const peerCandidate = await bPromise;
expect(peerCandidate).toMatchObject({
peerId: "a",
peerMetadata: aPeerMetadata,
});
teardown();
});
});

@@ -115,0 +130,0 @@ }

@@ -32,4 +32,6 @@ /**

export { NetworkAdapter } from "./network/NetworkAdapter.js";
export type { NetworkAdapterInterface } from "./network/NetworkAdapterInterface.js";
export { isRepoMessage } from "./network/messages.js";
export { StorageAdapter } from "./storage/StorageAdapter.js";
export type { StorageAdapterInterface } from "./storage/StorageAdapterInterface.js";
/** @hidden **/

@@ -39,3 +41,3 @@ export * as cbor from "./helpers/cbor.js";

export type { DeleteDocumentPayload, DocumentPayload, RepoConfig, RepoEvents, SharePolicy, } from "./Repo.js";
export type { NetworkAdapterEvents, OpenPayload, PeerCandidatePayload, PeerDisconnectedPayload, PeerMetadata, } from "./network/NetworkAdapter.js";
export type { NetworkAdapterEvents, OpenPayload, PeerCandidatePayload, PeerDisconnectedPayload, PeerMetadata, } from "./network/NetworkAdapterInterface.js";
export type { DocumentUnavailableMessage, EphemeralMessage, Message, RepoMessage, RequestMessage, SyncMessage, } from "./network/messages.js";

@@ -42,0 +44,0 @@ export type { Chunk, ChunkInfo, ChunkType, StorageKey, StorageId, } from "./storage/types.js";

import { EventEmitter } from "eventemitter3";
import { NetworkAdapterEvents, PeerMetadata } from "../index.js";
import { PeerId } from "../types.js";
import { Message } from "./messages.js";
import { StorageId } from "../storage/types.js";
/**
* Describes a peer intent to the system
* storageId: the key for syncState to decide what the other peer already has
* isEphemeral: to decide if we bother recording this peer's sync state
*
*/
export interface PeerMetadata {
storageId?: StorageId;
isEphemeral?: boolean;
}
import { NetworkAdapterInterface } from "./NetworkAdapterInterface.js";
/** An interface representing some way to connect to other peers
* @deprecated use {@link NetworkAdapterInterface}
*

@@ -22,3 +14,3 @@ * @remarks

*/
export declare abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> {
export declare abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> implements NetworkAdapterInterface {
peerId?: PeerId;

@@ -40,24 +32,2 @@ peerMetadata?: PeerMetadata;

}
export interface NetworkAdapterEvents {
/** Emitted when the network is ready to be used */
ready: (payload: OpenPayload) => void;
/** Emitted when the network is closed */
close: () => void;
/** Emitted when the network adapter learns about a new peer */
"peer-candidate": (payload: PeerCandidatePayload) => void;
/** Emitted when the network adapter learns that a peer has disconnected */
"peer-disconnected": (payload: PeerDisconnectedPayload) => void;
/** Emitted when the network adapter receives a message from a peer */
message: (payload: Message) => void;
}
export interface OpenPayload {
network: NetworkAdapter;
}
export interface PeerCandidatePayload {
peerId: PeerId;
peerMetadata: PeerMetadata;
}
export interface PeerDisconnectedPayload {
peerId: PeerId;
}
//# sourceMappingURL=NetworkAdapter.d.ts.map
/* c8 ignore start */
import { EventEmitter } from "eventemitter3";
/** An interface representing some way to connect to other peers
* @deprecated use {@link NetworkAdapterInterface}
*

@@ -5,0 +6,0 @@ * @remarks

import { EventEmitter } from "eventemitter3";
import { PeerId } from "../types.js";
import type { NetworkAdapter, PeerDisconnectedPayload, PeerMetadata } from "./NetworkAdapter.js";
import type { NetworkAdapterInterface, PeerDisconnectedPayload, PeerMetadata } from "./NetworkAdapterInterface.js";
import { MessageContents, RepoMessage } from "./messages.js";

@@ -9,4 +9,4 @@ export declare class NetworkSubsystem extends EventEmitter<NetworkSubsystemEvents> {

private peerMetadata;
constructor(adapters: NetworkAdapter[], peerId: PeerId, peerMetadata: Promise<PeerMetadata>);
addNetworkAdapter(networkAdapter: NetworkAdapter): void;
constructor(adapters: NetworkAdapterInterface[], peerId: PeerId, peerMetadata: Promise<PeerMetadata>);
addNetworkAdapter(networkAdapter: NetworkAdapterInterface): void;
send(message: MessageContents): void;

@@ -13,0 +13,0 @@ isReady: () => boolean;

@@ -70,5 +70,7 @@ import debug from "debug";

});
this.peerMetadata.then(peerMetadata => {
this.peerMetadata
.then(peerMetadata => {
networkAdapter.connect(this.peerId, peerMetadata);
}).catch(err => {
})
.catch(err => {
this.#log("error connecting to network", err);

@@ -75,0 +77,0 @@ });

import { EventEmitter } from "eventemitter3";
import { DocHandle } from "./DocHandle.js";
import { NetworkAdapter, type PeerMetadata } from "./network/NetworkAdapter.js";
import { NetworkAdapterInterface, type PeerMetadata } from "./network/NetworkAdapterInterface.js";
import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
import { StorageAdapter } from "./storage/StorageAdapter.js";
import { StorageAdapterInterface } from "./storage/StorageAdapterInterface.js";
import { StorageSubsystem } from "./storage/StorageSubsystem.js";

@@ -93,5 +93,5 @@ import { StorageId } from "./storage/types.js";

/** A storage adapter can be provided, or not */
storage?: StorageAdapter;
storage?: StorageAdapterInterface;
/** One or more network adapters must be provided */
network: NetworkAdapter[];
network: NetworkAdapterInterface[];
/**

@@ -98,0 +98,0 @@ * Normal peers typically share generously with everyone (meaning we sync all our documents with

@@ -117,8 +117,6 @@ import { next as Automerge } from "@automerge/automerge";

// The network subsystem deals with sending and receiving messages to and from peers.
const myPeerMetadata = new Promise(
// eslint-disable-next-line no-async-promise-executor -- TODO: fix
async (resolve) => resolve({
const myPeerMetadata = (async () => ({
storageId: await storageSubsystem?.id(),
isEphemeral,
}));
}))();
const networkSubsystem = new NetworkSubsystem(network, peerId, myPeerMetadata);

@@ -125,0 +123,0 @@ this.networkSubsystem = networkSubsystem;

@@ -0,3 +1,5 @@

import { StorageAdapterInterface } from "./StorageAdapterInterface.js";
import { StorageKey, Chunk } from "./types.js";
/** A storage adapter represents some way of storing binary data for a {@link Repo}
* @deprecated use {@link StorageAdapterInterface}
*

@@ -8,3 +10,3 @@ * @remarks

*/
export declare abstract class StorageAdapter {
export declare abstract class StorageAdapter implements StorageAdapterInterface {
/** Load the single value corresponding to `key` */

@@ -11,0 +13,0 @@ abstract load(key: StorageKey): Promise<Uint8Array | undefined>;

/** A storage adapter represents some way of storing binary data for a {@link Repo}
* @deprecated use {@link StorageAdapterInterface}
*

@@ -3,0 +4,0 @@ * @remarks

import * as A from "@automerge/automerge/next";
import { type DocumentId } from "../types.js";
import { StorageAdapter } from "./StorageAdapter.js";
import { StorageAdapterInterface } from "./StorageAdapterInterface.js";
import { StorageId } from "./types.js";

@@ -11,3 +11,3 @@ /**

#private;
constructor(storageAdapter: StorageAdapter);
constructor(storageAdapter: StorageAdapterInterface);
id(): Promise<StorageId>;

@@ -14,0 +14,0 @@ /** Loads a value from storage. */

@@ -155,3 +155,3 @@ import * as A from "@automerge/automerge/next";

beginSync(peerIds) {
const newPeers = new Set(peerIds.filter(peerId => !this.#peers.includes(peerId)));
const noPeersWithDocument = peerIds.every((peerId) => this.#peerDocumentStatuses[peerId] in ["unavailable", "wants"]);
// At this point if we don't have anything in our storage, we need to use an empty doc to sync

@@ -166,3 +166,3 @@ // with; but we don't want to surface that state to the front end

const wasUnavailable = doc === undefined;
if (wasUnavailable && newPeers.size == 0) {
if (wasUnavailable && noPeersWithDocument) {
return;

@@ -169,0 +169,0 @@ }

{
"name": "@automerge/automerge-repo",
"version": "1.1.0",
"version": "1.1.1",
"description": "A repository object to manage a collection of automerge documents",

@@ -58,3 +58,3 @@ "repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",

},
"gitHead": "e9e7d3f27ec2ac8a2e9d122ece80598918940067"
"gitHead": "7e0681014b8c5f672e2abc2a653a954ccb6d7aba"
}

@@ -41,4 +41,4 @@ # Automerge Repo

- `create<T>()`
Creates a new, empty `Automerge.Doc` and returns a `DocHandle` for it.
- `create<T>(initialValue: T?)`
Creates a new `Automerge.Doc` and returns a `DocHandle` for it. Accepts an optional initial value for the document. Produces an empty document (potentially violating the type!) otherwise.
- `find<T>(docId: DocumentId)`

@@ -45,0 +45,0 @@ Looks up a given document either on the local machine or (if necessary) over any configured

@@ -42,3 +42,3 @@ import * as A from "@automerge/automerge/next"

#machine: DocHandleXstateMachine<T>
#timeoutDelay: number = 60_000
#timeoutDelay = 60_000
#remoteHeads: Record<StorageId, A.Heads> = {}

@@ -248,9 +248,8 @@

#statePromise(awaitStates: HandleState | HandleState[]) {
if (!Array.isArray(awaitStates)) awaitStates = [awaitStates]
return Promise.any(
awaitStates.map(state =>
waitFor(this.#machine, s => s.matches(state), {
timeout: this.#timeoutDelay * 2, // use a longer delay here so as not to race with other delays
})
)
const awaitStatesArray = Array.isArray(awaitStates) ? awaitStates : [awaitStates]
return waitFor(
this.#machine,
s => awaitStatesArray.some((state) => s.matches(state)),
// use a longer delay here so as not to race with other delays
{timeout: this.#timeoutDelay * 2}
)

@@ -257,0 +256,0 @@ }

import assert from "assert"
import { describe, it } from "vitest"
import { PeerId, Repo, type NetworkAdapter } from "../../index.js"
import { describe, expect, it } from "vitest"
import { PeerId, PeerMetadata, Repo, StorageId } from "../../index.js"
import type { NetworkAdapterInterface } from "../../network/NetworkAdapterInterface.js"
import { eventPromise, eventPromises } from "../eventPromise.js"

@@ -32,3 +33,6 @@ import { pause } from "../pause.js"

it("can sync 2 repos", async () => {
const doTest = async (a: NetworkAdapter[], b: NetworkAdapter[]) => {
const doTest = async (
a: NetworkAdapterInterface[],
b: NetworkAdapterInterface[]
) => {
const aliceRepo = new Repo({ network: a, peerId: alice })

@@ -145,2 +149,24 @@ const bobRepo = new Repo({ network: b, peerId: bob })

})
it("emits a peer-candidate event with proper peer metadata when a peer connects", async () => {
const { adapters, teardown } = await setup()
const a = adapters[0][0]
const b = adapters[1][0]
const bPromise = eventPromise(b, "peer-candidate")
const aPeerMetadata: PeerMetadata = { storageId: "a" as StorageId }
b.connect("b" as PeerId, { storageId: "b" as StorageId })
a.connect("a" as PeerId, aPeerMetadata)
const peerCandidate = await bPromise
expect(peerCandidate).toMatchObject({
peerId: "a",
peerMetadata: aPeerMetadata,
})
teardown()
})
})

@@ -151,3 +177,3 @@ }

type Network = NetworkAdapter | NetworkAdapter[]
type Network = NetworkAdapterInterface | NetworkAdapterInterface[]

@@ -154,0 +180,0 @@ export type SetupFn = () => Promise<{

@@ -37,4 +37,6 @@ /**

export { NetworkAdapter } from "./network/NetworkAdapter.js"
export type { NetworkAdapterInterface } from "./network/NetworkAdapterInterface.js"
export { isRepoMessage } from "./network/messages.js"
export { StorageAdapter } from "./storage/StorageAdapter.js"
export type { StorageAdapterInterface } from "./storage/StorageAdapterInterface.js"

@@ -72,3 +74,3 @@ /** @hidden **/

PeerMetadata,
} from "./network/NetworkAdapter.js"
} from "./network/NetworkAdapterInterface.js"

@@ -75,0 +77,0 @@ export type {

/* c8 ignore start */
import { EventEmitter } from "eventemitter3"
import { NetworkAdapterEvents, PeerMetadata } from "../index.js"
import { PeerId } from "../types.js"
import { Message } from "./messages.js"
import { StorageId } from "../storage/types.js"
import { NetworkAdapterInterface } from "./NetworkAdapterInterface.js"
/**
* Describes a peer intent to the system
* storageId: the key for syncState to decide what the other peer already has
* isEphemeral: to decide if we bother recording this peer's sync state
*
*/
export interface PeerMetadata {
storageId?: StorageId
isEphemeral?: boolean
}
/** An interface representing some way to connect to other peers
* @deprecated use {@link NetworkAdapterInterface}
*

@@ -26,3 +17,6 @@ * @remarks

*/
export abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> {
export abstract class NetworkAdapter
extends EventEmitter<NetworkAdapterEvents>
implements NetworkAdapterInterface
{
peerId?: PeerId

@@ -47,33 +41,1 @@ peerMetadata?: PeerMetadata

}
// events & payloads
export interface NetworkAdapterEvents {
/** Emitted when the network is ready to be used */
ready: (payload: OpenPayload) => void
/** Emitted when the network is closed */
close: () => void
/** Emitted when the network adapter learns about a new peer */
"peer-candidate": (payload: PeerCandidatePayload) => void
/** Emitted when the network adapter learns that a peer has disconnected */
"peer-disconnected": (payload: PeerDisconnectedPayload) => void
/** Emitted when the network adapter receives a message from a peer */
message: (payload: Message) => void
}
export interface OpenPayload {
network: NetworkAdapter
}
export interface PeerCandidatePayload {
peerId: PeerId
peerMetadata: PeerMetadata
}
export interface PeerDisconnectedPayload {
peerId: PeerId
}

@@ -5,6 +5,6 @@ import debug from "debug"

import type {
NetworkAdapter,
NetworkAdapterInterface,
PeerDisconnectedPayload,
PeerMetadata,
} from "./NetworkAdapter.js"
} from "./NetworkAdapterInterface.js"
import {

@@ -25,3 +25,3 @@ EphemeralMessage,

#log: debug.Debugger
#adaptersByPeer: Record<PeerId, NetworkAdapter> = {}
#adaptersByPeer: Record<PeerId, NetworkAdapterInterface> = {}

@@ -32,6 +32,6 @@ #count = 0

#readyAdapterCount = 0
#adapters: NetworkAdapter[] = []
#adapters: NetworkAdapterInterface[] = []
constructor(
adapters: NetworkAdapter[],
adapters: NetworkAdapterInterface[],
public peerId = randomPeerId(),

@@ -45,3 +45,3 @@ private peerMetadata: Promise<PeerMetadata>

addNetworkAdapter(networkAdapter: NetworkAdapter) {
addNetworkAdapter(networkAdapter: NetworkAdapterInterface) {
this.#adapters.push(networkAdapter)

@@ -112,7 +112,9 @@ networkAdapter.once("ready", () => {

this.peerMetadata.then(peerMetadata => {
networkAdapter.connect(this.peerId, peerMetadata)
}).catch(err => {
this.#log("error connecting to network", err)
})
this.peerMetadata
.then(peerMetadata => {
networkAdapter.connect(this.peerId, peerMetadata)
})
.catch(err => {
this.#log("error connecting to network", err)
})
}

@@ -119,0 +121,0 @@

@@ -5,5 +5,5 @@ import { next as Automerge } from "@automerge/automerge"

import {
generateAutomergeUrl,
interpretAsDocumentId,
parseAutomergeUrl,
generateAutomergeUrl,
interpretAsDocumentId,
parseAutomergeUrl,
} from "./AutomergeUrl.js"

@@ -14,6 +14,6 @@ import { DocHandle, DocHandleEncodedChangePayload } from "./DocHandle.js"

import { throttle } from "./helpers/throttle.js"
import { NetworkAdapter, type PeerMetadata } from "./network/NetworkAdapter.js"
import { NetworkAdapterInterface, type PeerMetadata } from "./network/NetworkAdapterInterface.js"
import { NetworkSubsystem } from "./network/NetworkSubsystem.js"
import { RepoMessage } from "./network/messages.js"
import { StorageAdapter } from "./storage/StorageAdapter.js"
import { StorageAdapterInterface } from "./storage/StorageAdapterInterface.js"
import { StorageSubsystem } from "./storage/StorageSubsystem.js"

@@ -160,10 +160,6 @@ import { StorageId } from "./storage/types.js"

const myPeerMetadata: Promise<PeerMetadata> = new Promise(
// eslint-disable-next-line no-async-promise-executor -- TODO: fix
async resolve =>
resolve({
storageId: await storageSubsystem?.id(),
isEphemeral,
} as PeerMetadata)
)
const myPeerMetadata: Promise<PeerMetadata> = (async () => ({
storageId: await storageSubsystem?.id(),
isEphemeral,
}))()

@@ -523,6 +519,6 @@ const networkSubsystem = new NetworkSubsystem(

/** A storage adapter can be provided, or not */
storage?: StorageAdapter
storage?: StorageAdapterInterface
/** One or more network adapters must be provided */
network: NetworkAdapter[]
network: NetworkAdapterInterface[]

@@ -529,0 +525,0 @@ /**

@@ -0,4 +1,6 @@

import { StorageAdapterInterface } from "./StorageAdapterInterface.js"
import { StorageKey, Chunk } from "./types.js"
/** A storage adapter represents some way of storing binary data for a {@link Repo}
* @deprecated use {@link StorageAdapterInterface}
*

@@ -9,3 +11,3 @@ * @remarks

*/
export abstract class StorageAdapter {
export abstract class StorageAdapter implements StorageAdapterInterface {
/** Load the single value corresponding to `key` */

@@ -12,0 +14,0 @@ abstract load(key: StorageKey): Promise<Uint8Array | undefined>

@@ -6,3 +6,3 @@ import * as A from "@automerge/automerge/next"

import { type DocumentId } from "../types.js"
import { StorageAdapter } from "./StorageAdapter.js"
import { StorageAdapterInterface } from "./StorageAdapterInterface.js"
import { ChunkInfo, StorageKey, StorageId } from "./types.js"

@@ -19,3 +19,3 @@ import { keyHash, headsHash } from "./keyHash.js"

/** The storage adapter to use for saving and loading documents */
#storageAdapter: StorageAdapter
#storageAdapter: StorageAdapterInterface

@@ -33,3 +33,3 @@ /** Record of the latest heads we've loaded or saved for each document */

constructor(storageAdapter: StorageAdapter) {
constructor(storageAdapter: StorageAdapterInterface) {
this.#storageAdapter = storageAdapter

@@ -36,0 +36,0 @@ }

@@ -230,4 +230,4 @@ import * as A from "@automerge/automerge/next"

beginSync(peerIds: PeerId[]) {
const newPeers = new Set(
peerIds.filter(peerId => !this.#peers.includes(peerId))
const noPeersWithDocument = peerIds.every(
(peerId) => this.#peerDocumentStatuses[peerId] in ["unavailable", "wants"]
)

@@ -246,3 +246,3 @@

const wasUnavailable = doc === undefined
if (wasUnavailable && newPeers.size == 0) {
if (wasUnavailable && noPeersWithDocument) {
return

@@ -249,0 +249,0 @@ }

import * as A from "@automerge/automerge/next"
import assert from "assert"
import { decode } from "cbor-x"
import { describe, it } from "vitest"
import { describe, it, vi } from "vitest"
import { generateAutomergeUrl, parseAutomergeUrl } from "../src/AutomergeUrl.js"

@@ -75,2 +75,25 @@ import { eventPromise } from "../src/helpers/eventPromise.js"

/**
* Once there's a Repo#stop API this case should be covered in accompanying
* tests and the following test removed.
*/
it("no pending timers after a document is loaded", async () => {
vi.useFakeTimers()
const timerCount = vi.getTimerCount()
const handle = new DocHandle<TestDoc>(TEST_ID)
assert.equal(handle.isReady(), false)
handle.doc()
assert(vi.getTimerCount() > timerCount)
// simulate loading from storage
handle.update(doc => docFromMockStorage(doc))
assert.equal(handle.isReady(), true)
assert.equal(vi.getTimerCount(), timerCount)
vi.useRealTimers()
})
it("should block changes until ready()", async () => {

@@ -77,0 +100,0 @@ const handle = new DocHandle<TestDoc>(TEST_ID)

@@ -1,11 +0,14 @@

import { NetworkAdapter } from "../../src/index.js"
import { pause } from "../../src/helpers/pause.js";
import { Message, NetworkAdapter, PeerId } from "../../src/index.js"
export class DummyNetworkAdapter extends NetworkAdapter {
#startReady: boolean
#sendMessage?: SendMessageFn;
constructor({ startReady = true }: Options = {}) {
constructor(opts: Options = {startReady: true}) {
super()
this.#startReady = startReady
this.#startReady = opts.startReady;
this.#sendMessage = opts.sendMessage;
}
send() {}
connect(_: string) {

@@ -16,7 +19,36 @@ if (this.#startReady) {

}
disconnect() {}
peerCandidate(peerId: PeerId) {
this.emit('peer-candidate', { peerId, peerMetadata: {} });
}
override send(message: Message) {
this.#sendMessage?.(message);
}
receive(message: Message) {
this.emit('message', message);
}
static createConnectedPair() {
const adapter1: DummyNetworkAdapter = new DummyNetworkAdapter({
startReady: true,
sendMessage: (message: Message) => pause(10).then(() => adapter2.receive(message)),
});
const adapter2: DummyNetworkAdapter = new DummyNetworkAdapter({
startReady: true,
sendMessage: (message: Message) => pause(10).then(() => adapter1.receive(message)),
});
return [adapter1, adapter2];
}
}
type SendMessageFn = (message: Message) => void;
type Options = {
startReady?: boolean
startReady?: boolean;
sendMessage?: SendMessageFn;
}

@@ -6,3 +6,3 @@ import { next as A } from "@automerge/automerge"

import { describe, expect, it } from "vitest"
import { READY } from "../src/DocHandle.js"
import { HandleState, READY } from "../src/DocHandle.js"
import { parseAutomergeUrl } from "../src/AutomergeUrl.js"

@@ -1027,2 +1027,33 @@ import {

it('peer receives a document when connection is recovered', async () => {
const alice = "alice" as PeerId;
const bob = "bob" as PeerId;
const [aliceAdapter, bobAdapter] = DummyNetworkAdapter.createConnectedPair();
const aliceRepo = new Repo({
network: [aliceAdapter],
peerId: alice
})
const bobRepo = new Repo({
network: [bobAdapter],
peerId: bob
})
const aliceDoc = aliceRepo.create();
aliceDoc.change((doc: any) => doc.text = 'Hello world');
const bobDoc = bobRepo.find(aliceDoc.url);
bobDoc.unavailable()
await bobDoc.whenReady([HandleState.UNAVAILABLE]);
aliceAdapter.peerCandidate(bob);
// Bob isn't yet connected to Alice and can't respond to her sync message
await pause(100);
bobAdapter.peerCandidate(alice);
await bobDoc.whenReady([HandleState.READY]);
assert.equal(bobDoc.isReady(), true);
});
describe("with peers (mesh network)", () => {

@@ -1029,0 +1060,0 @@ const setup = async () => {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc