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.
Set up the provider
Section titled “Set up the provider”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
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]
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]
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>);
The identity
Section titled “The identity”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.
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> );};
Spaces and members
Section titled “Spaces and members”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).
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.
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).
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.
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.
join(', ')} </> );};
Invitations
Section titled “Invitations”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.
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).
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).
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.
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 Promiseimport { Effect } from "effect"const output: Array<unknown> = []
await Effect.runPromise(Effect.fail("my error")).catch(() => { void output.push("rejected")})output // => ["rejected"]
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"
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.
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).
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> );};
Hooks at a glance
Section titled “Hooks at a glance”| 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 |
Related
Section titled “Related”- Identity, Space and Invitation
- The contact book in the learning path is built on
HaloProviderand these hooks.