Skip to content

React

import { HaloProvider, useIdentity } from '@dxos/halo-react';

@dxos/halo-react reads HALO from React components. Each hook follows one @dxos/halo stream and re-renders when it emits, so a component shows the current identity, devices or members without subscribing itself.

HaloProvider takes the HALO services as an Effect Context. Build it from a Client with the adapter’s makeIdentityService and makeSpaceService, and wrap the part of the app that uses the hooks.

import * as
import Context
Context
from 'effect/Context';
import {
import Identity
Identity
,
import Space
Space
} from '@dxos/halo';
import {
const makeIdentityService: (client: Client) => Context.Service.Shape<typeof Identity.Service>

Builds the

HaloIdentity.Service

implementation over a client's halo proxy.

makeIdentityService
,
const makeSpaceService: (client: Client) => Context.Service.Shape<typeof Space.Service>

Builds the

HaloSpace.Service

implementation over a client's spaces proxy.

makeSpaceService
} from '@dxos/halo-adapter-client';
import {
const HaloProvider: ({ services, children }: HaloProviderProps) => React.JSX.Element

Provides the HALO services to the hook library. Wrap the application (or the subtree that uses the hooks) in this provider. Replaces ClientProvider for HALO concerns.

HaloProvider
} from '@dxos/halo-react';
const
const services: Context.Context<Identity.Service | Space.Service>
services
=
import Context
Context
.
const empty: () => Context.Context<never>

Returns an empty Context.

Example (Creating an empty context)

import { Context } from "effect"
Context.empty().mapUnsafe.size // => 0

@stability ― stable

@category ― constructors

@since ― 2.0.0

empty
().
Pipeable.pipe<Context.Context<never>, Context.Context<Identity.Service>, Context.Context<Identity.Service | Space.Service>>(this: Context.Context<never>, ab: (_: Context.Context<never>) => Context.Context<Identity.Service>, bc: (_: Context.Context<Identity.Service>) => Context.Context<Identity.Service | Space.Service>): Context.Context<Identity.Service | Space.Service> (+21 overloads)
pipe
(
import Context
Context
.
const add: <Identity.Service, Identity.ServiceApi>(key: Context.Key<Identity.Service, Identity.ServiceApi>, service: Identity.ServiceApi) => <Services>(self: Context.Context<Services>) => Context.Context<Identity.Service | Services> (+1 overload)

Adds a service to a given Context.

When to use

Use when you need to store a known service value in a Context.

Details

If the context already contains the same service key, the new service replaces the previous one.

Example (Adding a service to a context)

import { Context, pipe } from "effect"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const someContext = Context.make(Port, { PORT: 8080 })
const context = pipe(
someContext,
Context.add(Timeout, { TIMEOUT: 5000 })
)
const values = [Context.get(context, Port).PORT, Context.get(context, Timeout).TIMEOUT]
values // => [8080, 5000]

@see ― addOrOmit for adding or removing a service from an Option

@stability ― stable

@category ― combining

@since ― 2.0.0

add
(
import Identity
Identity
.
class Service
Service
,
function makeIdentityService(client: Client): Context.Service.Shape<typeof Identity.Service>

Builds the

HaloIdentity.Service

implementation over a client's halo proxy.

makeIdentityService
(
const client: Client
client
)),
import Context
Context
.
const add: <Space.Service, Space.ServiceApi>(key: Context.Key<Space.Service, Space.ServiceApi>, service: Space.ServiceApi) => <Services>(self: Context.Context<Services>) => Context.Context<Space.Service | Services> (+1 overload)

Adds a service to a given Context.

When to use

Use when you need to store a known service value in a Context.

Details

If the context already contains the same service key, the new service replaces the previous one.

Example (Adding a service to a context)

import { Context, pipe } from "effect"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const someContext = Context.make(Port, { PORT: 8080 })
const context = pipe(
someContext,
Context.add(Timeout, { TIMEOUT: 5000 })
)
const values = [Context.get(context, Port).PORT, Context.get(context, Timeout).TIMEOUT]
values // => [8080, 5000]

@see ― addOrOmit for adding or removing a service from an Option

@stability ― stable

@category ― combining

@since ― 2.0.0

add
(
import Space
Space
.
class Service
Service
,
function makeSpaceService(client: Client): Context.Service.Shape<typeof Space.Service>

Builds the

HaloSpace.Service

implementation over a client's spaces proxy.

makeSpaceService
(
const client: Client
client
)),
);
export const
const App: () => React.JSX.Element
App
= () => (
<
const HaloProvider: ({ services, children }: HaloProviderProps) => React.JSX.Element

Provides the HALO services to the hook library. Wrap the application (or the subtree that uses the hooks) in this provider. Replaces ClientProvider for HALO concerns.

HaloProvider
services: Context.Context<HaloServices>

The HALO services context. Build it from a concrete backing — e.g. the client adapter's makeIdentityService / makeSpaceService from @dxos/halo-adapter-client — and pass it here.

services
={
const services: Context.Context<Identity.Service | Space.Service>
services
}>
<
const Profile: () => React.JSX.Element
Profile
/>
</
const HaloProvider: ({ services, children }: HaloProviderProps) => React.JSX.Element

Provides the HALO services to the hook library. Wrap the application (or the subtree that uses the hooks) in this provider. Replaces ClientProvider for HALO concerns.

HaloProvider
>
);

useIdentity returns the identity, or undefined before one exists. It has the current value on the first render. useDevices and useCredentials return the identity’s devices and credentials.

import {
const useCredentials: () => readonly Identity.Credential[]

Returns the local identity's HALO credentials. Reactive: re-renders when credentials are written. Replaces @dxos/react-client's useCredentials.

useCredentials
,
const useDevices: () => readonly Identity.DeviceInfo[]

Returns the devices belonging to the local identity. Reactive. Replaces @dxos/react-client's useDevices.

useDevices
,
const useIdentity: () => Identity.Info | undefined

Returns the local identity, or undefined if none exists. Reactive: re-renders when the identity is created or its profile changes. Replaces @dxos/react-client's useIdentity.

useIdentity
} from '@dxos/halo-react';
export const
const Profile: () => React.JSX.Element
Profile
= () => {
const
const identity: {
readonly did: IdentityDid;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
} | undefined
identity
=
function useIdentity(): Identity.Info | undefined

Returns the local identity, or undefined if none exists. Reactive: re-renders when the identity is created or its profile changes. Replaces @dxos/react-client's useIdentity.

useIdentity
();
const
const devices: readonly {
readonly key: string;
readonly current: boolean;
readonly kind?: "unknown" | "browser" | "native" | "mobile" | "agent" | "agent-managed" | undefined;
readonly label?: string | undefined;
readonly os?: string | undefined;
readonly platform?: string | undefined;
readonly presence?: "online" | "offline" | "removed" | undefined;
}[]
devices
=
function useDevices(): readonly Identity.DeviceInfo[]

Returns the devices belonging to the local identity. Reactive. Replaces @dxos/react-client's useDevices.

useDevices
();
const
const credentials: readonly {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[]
credentials
=
function useCredentials(): readonly Identity.Credential[]

Returns the local identity's HALO credentials. Reactive: re-renders when credentials are written. Replaces @dxos/react-client's useCredentials.

useCredentials
();
if (!
const identity: {
readonly did: IdentityDid;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
} | undefined
identity
) {
return <
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>No identity yet.</
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>;
}
const
const recovery: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[]
recovery
=
const credentials: readonly {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[]
credentials
.
ReadonlyArray<{ readonly type: string; readonly id?: string | undefined; readonly issuanceDate?: Date | undefined; readonly recovery?: { readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth"; readonly revoked: boolean; readonly label?: string | undefined; readonly lookupKey?: string | undefined; } | undefined; }>.filter(predicate: (value: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}, index: number, array: readonly {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[]) => unknown, thisArg?: any): {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[] (+1 overload)

Returns the elements of an array that meet the condition specified in a callback function.

@param ― predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.

filter
((
c: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}
c
) =>
c: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}
c
.
recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined
recovery
&& !
c: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}
c
.
recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
}
recovery
.
revoked: boolean

Whether an IdentityRecoveryRevoked assertion cancels this credential.

revoked
);
return (
<
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
{
const identity: {
readonly did: IdentityDid;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}
identity
.
displayName?: string | undefined
displayName
} on {
const devices: readonly {
readonly key: string;
readonly current: boolean;
readonly kind?: "unknown" | "browser" | "native" | "mobile" | "agent" | "agent-managed" | undefined;
readonly label?: string | undefined;
readonly os?: string | undefined;
readonly platform?: string | undefined;
readonly presence?: "online" | "offline" | "removed" | undefined;
}[]
devices
.
ReadonlyArray<{ readonly key: string; readonly current: boolean; readonly kind?: "unknown" | "browser" | "native" | "mobile" | "agent" | "agent-managed" | undefined; readonly label?: string | undefined; readonly os?: string | undefined; readonly platform?: string | undefined; readonly presence?: "online" | ... 2 more ... | undefined; }>.length: number

Gets the length of the array. This is a number one higher than the highest element defined in an array.

length
} devices, with {
const recovery: {
readonly type: string;
readonly id?: string | undefined;
readonly issuanceDate?: Date | undefined;
readonly recovery?: {
readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth";
readonly revoked: boolean;
readonly label?: string | undefined;
readonly lookupKey?: string | undefined;
} | undefined;
}[]
recovery
.
Array<{ readonly type: string; readonly id?: string | undefined; readonly issuanceDate?: Date | undefined; readonly recovery?: { readonly kind: "unknown" | "passkey" | "recovery-code" | "oauth"; readonly revoked: boolean; readonly label?: string | undefined; readonly lookupKey?: string | undefined; } | undefined; }>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
}{' '}
recovery credentials.
</
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
);
};

useSpaces returns the spaces that are ready; pass { all: true } for every space. useSpace finds one by id, and useMembers returns a space’s members.

import {
const useMembers: (spaceId?: SpaceId) => readonly Space.Member[]

Returns the membership of a space. Reactive: re-renders on join/leave/role/presence changes. Replaces @dxos/react-client's useMembers (which took a PublicKey; this takes a

SpaceId

).

useMembers
,
const useSpace: (spaceId?: SpaceId) => Space.Info | undefined

Resolves a single space by id, or undefined. Reactive. Replaces useSpace. Unlike the legacy hook this takes a

SpaceId

only (no PublicKey).

useSpace
,
const useSpaces: ({ all }?: UseSpacesOptions) => readonly Space.Info[]

Returns the spaces known to the local identity. By default only ready spaces are returned; pass { all: true } for every space. Reactive. Replaces @dxos/react-client's useSpaces.

useSpaces
} from '@dxos/halo-react';
import { type
type SpaceId = string & {
__SpaceId: true;
}
const SpaceId: Codec<SpaceId, string, never, never> & {
byteLength: number;
encode: (value: Uint8Array) => SpaceId;
decode: (value: SpaceId) => Uint8Array;
isValid: (value: unknown) => value is SpaceId;
make: (value: string) => SpaceId;
random: () => SpaceId;
}

A unique identifier for a space. Space keys are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).

@example BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE

SpaceId
} from '@dxos/keys';
export const
const SpaceList: () => React.JSX.Element
SpaceList
= () => {
const
const spaces: readonly {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}[]
spaces
=
function useSpaces({ all }?: UseSpacesOptions): readonly Space.Info[]

Returns the spaces known to the local identity. By default only ready spaces are returned; pass { all: true } for every space. Reactive. Replaces @dxos/react-client's useSpaces.

useSpaces
();
return (
<
React.JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>
ul
>
{
const spaces: readonly {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}[]
spaces
.
ReadonlyArray<{ readonly id: SpaceId; readonly state: "inactive" | "closed" | "ready"; readonly name?: string | undefined; }>.map<React.JSX.Element>(callbackfn: (value: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}, index: number, array: readonly {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
space: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}
space
) => (
<
React.JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>
li
React.Attributes.key?: React.Key | null | undefined
key
={
space: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}
space
.
id: SpaceId
id
}>
<
const Members: ({ spaceId }: {
spaceId: SpaceId;
}) => React.JSX.Element
Members
spaceId: SpaceId
spaceId
={
space: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
}
space
.
id: SpaceId
id
} />
</
React.JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>
li
>
))}
</
React.JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>
ul
>
);
};
export const
const Members: ({ spaceId }: {
spaceId: SpaceId;
}) => React.JSX.Element
Members
= ({
spaceId: SpaceId
spaceId
}: {
spaceId: SpaceId
spaceId
:
type SpaceId = string & {
__SpaceId: true;
}

A unique identifier for a space. Space keys are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).

@example BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE

SpaceId
}) => {
const
const space: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
} | undefined
space
=
function useSpace(spaceId?: SpaceId): Space.Info | undefined

Resolves a single space by id, or undefined. Reactive. Replaces useSpace. Unlike the legacy hook this takes a

SpaceId

only (no PublicKey).

useSpace
(
spaceId: SpaceId
spaceId
);
const
const members: readonly {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}[]
members
=
function useMembers(spaceId?: SpaceId): readonly Space.Member[]

Returns the membership of a space. Reactive: re-renders on join/leave/role/presence changes. Replaces @dxos/react-client's useMembers (which took a PublicKey; this takes a

SpaceId

).

useMembers
(
spaceId: SpaceId
spaceId
);
return (
<>
{
const space: {
readonly id: SpaceId;
readonly state: "inactive" | "closed" | "ready";
readonly name?: string | undefined;
} | undefined
space
?.
name?: string | undefined
name
}:{' '}
{
const members: readonly {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}[]
members
.
ReadonlyArray<{ readonly role: "pull" | "read" | "edit" | "admin"; readonly online: boolean; readonly did?: IdentityDid | undefined; readonly identityKey?: string | undefined; readonly displayName?: string | undefined; readonly data?: { ...; } | undefined; }>.map<string | undefined>(callbackfn: (value: {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}, index: number, array: readonly {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}[]) => string | undefined, thisArg?: any): (string | undefined)[]

Calls a defined callback function on each element of an array, and returns an array that contains the results.

@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.

@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.

map
((
member: {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}
member
) =>
member: {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}
member
.
displayName?: string | undefined
displayName
??
member: {
readonly role: "pull" | "read" | "edit" | "admin";
readonly online: boolean;
readonly did?: IdentityDid | undefined;
readonly identityKey?: string | undefined;
readonly displayName?: string | undefined;
readonly data?: {
readonly [x: string]: any;
} | undefined;
}
member
.
did?: IdentityDid | undefined

DID of the member identity, when known.

did
).
Array<string | undefined>.join(separator?: string): string

Adds all the elements of an array into a string, separated by the specified separator string.

@param ― separator A string used to separate one element of the array from the next in the resulting string. If omitted, the array elements are separated with a comma.

join
(', ')}
</>
);
};

Start a flow with Space.share or Identity.share, run as an Effect with the same services. useInvitationFlow follows the flow: its latest event and its code. It needs no provider, since a flow carries what it needs. useSpaceInvitations and useHaloInvitations list the flows this device has open.

import * as
import Effect
Effect
from 'effect/Effect';
import {
function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)

Returns a stateful value, and a function to update it.

@version ― 16.8.0

@see ― https://react.dev/reference/react/useState

useState
} from 'react';
import {
import Invitation
Invitation
,
import Space
Space
} from '@dxos/halo';
import {
const useHaloInvitations: () => readonly Invitation.Flow[]

Returns the active device-invitation flows for the local identity. Reactive. Replaces useHaloInvitations.

useHaloInvitations
,
const useInvitationFlow: (flow?: Invitation.Flow) => InvitationFlowState

Tracks one

Invitation.Flow

for rendering, re-rendering on each lifecycle event. Needs no HaloProvider: a flow's streams and effects carry no service requirement.

useInvitationFlow
,
const useSpaceInvitations: (spaceId?: SpaceId) => readonly Invitation.Flow[]

Returns the active (host-created) invitation flows for a space. Reactive. Replaces @dxos/react-client's useSpaceInvitations. Drive an individual flow through the Invitation verbs (events / authenticate / cancel / code).

useSpaceInvitations
} from '@dxos/halo-react';
import { type
type SpaceId = string & {
__SpaceId: true;
}
const SpaceId: Codec<SpaceId, string, never, never> & {
byteLength: number;
encode: (value: Uint8Array) => SpaceId;
decode: (value: SpaceId) => Uint8Array;
isValid: (value: unknown) => value is SpaceId;
make: (value: string) => SpaceId;
random: () => SpaceId;
}

A unique identifier for a space. Space keys are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).

@example BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE

SpaceId
} from '@dxos/keys';
export const
const Invite: ({ spaceId }: {
spaceId: SpaceId;
}) => React.JSX.Element
Invite
= ({
spaceId: SpaceId
spaceId
}: {
spaceId: SpaceId
spaceId
:
type SpaceId = string & {
__SpaceId: true;
}

A unique identifier for a space. Space keys are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).

@example BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE

SpaceId
}) => {
const [
const flow: Invitation.Flow | undefined
flow
,
const setFlow: React.Dispatch<React.SetStateAction<Invitation.Flow | undefined>>
setFlow
] =
useState<Invitation.Flow>(): [Invitation.Flow | undefined, React.Dispatch<React.SetStateAction<Invitation.Flow | undefined>>] (+1 overload)

Returns a stateful value, and a function to update it.

@version ― 16.8.0

@see ― https://react.dev/reference/react/useState

useState
<
import Invitation
Invitation
.
interface Flow

An in-flight invitation, host or guest side. Produced by

Identity.share

/join and

Space.share

/join; its lifecycle is then driven through this handle and the

Service

.

Flow
>();
const {
const event: Invitation.Event | undefined
event
,
const code: string | undefined
code
} =
function useInvitationFlow(flow?: Invitation.Flow): InvitationFlowState

Tracks one

Invitation.Flow

for rendering, re-rendering on each lifecycle event. Needs no HaloProvider: a flow's streams and effects carry no service requirement.

useInvitationFlow
(
const flow: Invitation.Flow | undefined
flow
);
const
const share: () => Promise<void>
share
= () =>
import Effect
Effect
.
const runPromise: <Invitation.Flow, SpaceError>(effect: Effect.Effect<Invitation.Flow, SpaceError, never>, options?: Effect.RunOptions | undefined) => Promise<Invitation.Flow>

Executes an effect and returns the result as a Promise.

When to use

Use when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

Example (Running a successful effect as a Promise)

import { Effect } from "effect"
await Effect.runPromise(Effect.succeed(1)) // => 1

Example (Running effects as promises)

//Example: Handling a Failing Effect as a Rejected Promise
import { Effect } from "effect"
const output: Array<unknown> = []
await Effect.runPromise(Effect.fail("my error")).catch(() => {
void output.push("rejected")
})
output // => ["rejected"]

@see ― runPromiseExit for a version that returns an Exit type instead of rejecting.

@stability ― stable

@category ― running

@since ― 2.0.0

runPromise
(
import Space
Space
.
const share: (id: SpaceId, options?: Invitation.ShareOptions) => Effect.Effect<Invitation.Flow, SpaceError, Space.Service>

Initiate a space invitation (requires

Service

).

share
(
spaceId: SpaceId
spaceId
, {
authMethod?: Invitation.AuthMethod | undefined
authMethod
: 'shared-secret' }).
Pipeable.pipe<Effect.Effect<Invitation.Flow, SpaceError, Space.Service>, Effect.Effect<Invitation.Flow, SpaceError, never>>(this: Effect.Effect<Invitation.Flow, SpaceError, Space.Service>, ab: (_: Effect.Effect<Invitation.Flow, SpaceError, Space.Service>) => Effect.Effect<Invitation.Flow, SpaceError, never>): Effect.Effect<Invitation.Flow, SpaceError, never> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <Space.Service | Identity.Service>(context: Context.Context<Space.Service | Identity.Service>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Space.Service | Identity.Service>> (+5 overloads)

Provides dependencies to an effect using layers or a context. Use options.local to build the layer every time; by default, layers are shared between provide calls.

Example (Providing dependencies with a layer)

import { Context, Effect, Layer } from "effect"
interface Database {
readonly query: (sql: string) => Effect.Effect<string>
}
const Database = Context.Service<Database>("Database")
const DatabaseLayer = Layer.succeed(Database)({
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result for: ${sql}`))
})
const program = Effect.gen(function*() {
const db = yield* Database
return yield* db.query("SELECT * FROM users")
})
const provided = Effect.provide(program, DatabaseLayer)
await Effect.runPromise(provided) // => "Result for: SELECT * FROM users"

@stability ― stable

@category ― providing services

@since ― 2.0.0

provide
(
const services: Context.Context<Space.Service | Identity.Service>
services
),
),
).
Promise<Flow>.then<void, never>(onfulfilled?: ((value: Invitation.Flow) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@param ― onfulfilled The callback to execute when the Promise is resolved.

@param ― onrejected The callback to execute when the Promise is rejected.

@returns ― A Promise for the completion of which ever callback is executed.

then
(
const setFlow: React.Dispatch<React.SetStateAction<Invitation.Flow | undefined>>
setFlow
);
if (!
const flow: Invitation.Flow | undefined
flow
) {
return <
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={
const share: () => Promise<void>
share
}>Invite</
React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>;
}
return (
<
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
Code: {
const code: string | undefined
code
}
{
const event: Invitation.Event | undefined
event
?.
_tag: "connecting" | "connected" | "readyForAuthentication" | "authenticating" | "success" | "cancelled" | "error" | undefined
_tag
=== 'readyForAuthentication' && ` Auth: ${
const event: {
readonly _tag: "readyForAuthentication";
readonly authCode?: string;
}
event
.
authCode?: string | undefined
authCode
}`}
</
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
);
};
// Every flow this device has open, for a space or for the identity.
export const
const OpenInvitations: ({ spaceId }: {
spaceId: SpaceId;
}) => React.JSX.Element
OpenInvitations
= ({
spaceId: SpaceId
spaceId
}: {
spaceId: SpaceId
spaceId
:
type SpaceId = string & {
__SpaceId: true;
}

A unique identifier for a space. Space keys are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).

@example BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE

SpaceId
}) => {
const
const forSpace: readonly Invitation.Flow[]
forSpace
=
function useSpaceInvitations(spaceId?: SpaceId): readonly Invitation.Flow[]

Returns the active (host-created) invitation flows for a space. Reactive. Replaces @dxos/react-client's useSpaceInvitations. Drive an individual flow through the Invitation verbs (events / authenticate / cancel / code).

useSpaceInvitations
(
spaceId: SpaceId
spaceId
);
const
const forDevices: readonly Invitation.Flow[]
forDevices
=
function useHaloInvitations(): readonly Invitation.Flow[]

Returns the active device-invitation flows for the local identity. Reactive. Replaces useHaloInvitations.

useHaloInvitations
();
return (
<
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
{
const forSpace: readonly Invitation.Flow[]
forSpace
.
ReadonlyArray<Flow>.length: number

Gets the length of the array. This is a number one higher than the highest element defined in an array.

length
} space and {
const forDevices: readonly Invitation.Flow[]
forDevices
.
ReadonlyArray<Flow>.length: number

Gets the length of the array. This is a number one higher than the highest element defined in an array.

length
} device invitations open.
</
React.JSX.IntrinsicElements.p: React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
);
};
Hook Returns
useIdentity The identity, or undefined
useDevices useCredentials The identity’s devices and credentials
useSpaces useSpace Spaces, and one space by id
useMembers A space’s members
useContacts Everyone you share a space with, once each
useSpaceInvitations useHaloInvitations Open space and device invitations
useInvitationFlow One flow’s latest event and code