Skip to content

Sharing a space

By the end of this page a second peer will have joined the app’s space, and each peer will see the other’s edits.

A space is shared by invitation. The host creates an invitation, and the guest uses it to find the host and open a secure connection. The host then gives the guest an authentication code, which the guest sends back over that connection to prove it received the invitation from the host.

Once the guest is in, both peers hold a full replica of the space’s database. Each peer reads and writes its own replica, and the replicas exchange changes whenever the peers can reach each other. A peer that goes offline keeps working, and catches up when it reconnects.

Spaces and databases explains the handshake in detail.

  1. Invite a peer. space.share starts an invitation. Its code locates you on the network, and its authentication code proves the guest received the invitation from you.

    const {
    const space: Space
    space
    } = await
    function openContacts(services?: ClientServicesProvider): Promise<{
    client: Client;
    space: Space;
    }>

    Starts a client that knows the app's types, gives it an identity, and creates the space the app keeps its records in.

    openContacts
    ();
    const
    const invitation: CancellableInvitation
    invitation
    =
    const space: Space
    space
    .
    Space.share(options?: Partial<Invitation>): CancellableInvitation
    share
    ();
    // Send this code to the guest; it locates the host and opens a secure connection.
    const
    const code: string
    code
    =
    class InvitationEncoder

    Encodes and decodes an invitation proto into/from alphanumeric chars.

    InvitationEncoder
    .
    InvitationEncoder.encode(invitation: Invitation): string
    encode
    (
    const invitation: CancellableInvitation
    invitation
    .
    MulticastObservable<Invitation>.get(): Invitation

    Get the current value of the observable.

    get
    ());
    // Pass this second factor over another channel, such as a QR code or a call.
    const
    const authCode: string | undefined
    authCode
    =
    const invitation: CancellableInvitation
    invitation
    .
    MulticastObservable<Invitation>.get(): Invitation

    Get the current value of the observable.

    get
    ().
    authCode?: string | undefined

    / Authentication code created by host (only present if auth_method is SHARED_SECRET).

    @generated ― from field: optional string auth_code = 10;

    authCode
    ;

    Send the two codes over different channels. Someone who intercepts one of them cannot join.

  2. Join from the other peer. The guest needs a client that knows the app’s types and an identity of its own. It decodes the invitation, connects, and sends the authentication code back.

    const
    const guest: Client
    guest
    = new
    new Client(options?: ClientOptions): Client

    The Client class encapsulates the core client-side API of DXOS.

    Client
    ({
    types?: AnyEntity[] | undefined

    ECHO schema.

    types
    });
    await
    const guest: Client
    guest
    .
    Client.initialize(): Promise<Client>

    Initializes internal resources in an idempotent way. Required before using the Client instance.

    initialize
    ();
    await
    const guest: Client
    guest
    .
    Client.halo: Halo

    HALO credentials.

    halo
    .
    Halo.createIdentity(options?: ProfileDocument, deviceProfile?: DeviceProfileDocument): Promise<Identity>
    createIdentity
    ();
    const
    const accepted: AuthenticatingInvitation
    accepted
    =
    const guest: Client
    guest
    .
    Client.spaces: Echo

    ECHO Spaces.

    spaces
    .
    Echo.join(invitation: Invitation | string): AuthenticatingInvitation

    Joins an existing space using the given invitation.

    join
    (
    class InvitationEncoder

    Encodes and decodes an invitation proto into/from alphanumeric chars.

    InvitationEncoder
    .
    InvitationEncoder.decode(text: string): Invitation
    decode
    (
    const code: string
    code
    ));
    await
    const accepted: AuthenticatingInvitation
    accepted
    .
    AuthenticatingInvitation.authenticate(authCode: string): Promise<void>
    authenticate
    (
    const authCode: string | undefined
    authCode
    !);
  3. Find the space. Once authentication completes, the space is among the guest’s spaces, and both peers replicate it.

    // The space appears among the guest's spaces once the invitation succeeds.
    const
    const spaces: Space[]
    spaces
    =
    const guest: Client
    guest
    .
    Client.spaces: Echo

    ECHO Spaces.

    spaces
    .
    Echo.get(): Space[] (+2 overloads)

    Returns the list of spaces.

    get
    ();

Alice created the space and Bob joined it by invitation. Edit a record on one side and watch the other follow. Switch a peer offline, edit on both sides, then switch it back on: the replicas exchange what they missed.

You can invite a peer to a space, accept the invitation from a second client, and edit one database from both.

Spaces and databases: what a space is, and how peers join one.