Skip to content

bolt/page

bolt/page

Import from @norbital-ai/bolt/page

@norbital-ai/bolt/page (§3.3.10, §3.5, D9): the booted shell client, the ui edge it runs on, and optional host device. $bolt is its generated alias (.norbital/bolt.d.ts for types; the client build resolves the module itself), exporting bolt, run, fork, query, live, attach.

DeviceApi type

type DeviceApi = {
    platform?: 'ios' | 'android' | 'web' | 'desktop';
    /** A shell bound to one workspace (an app): the page offers no way to another workspace. */
    pinned?: true;
    /** Native notifications: their permission, raising one, and the path a tapped one opens. */
    notifications?: NativePermission & DeviceNotifications;
    /** Native camera permission, where the host's web view needs one. */
    camera?: NativePermission;
    geolocation?: {
        source: 'native' | 'browser';
        api: Geolocation;
        /** Native authorization, independently of whether a foreground fix is available. */
        background?: {
            status(): Promise<{
                enabled: boolean;
                always: boolean;
            }>;
            openSettings(): Promise<void>;
        };
    };
    /** This device's push endpoint (it asks the platform for it, and for permission where the platform needs to). */
    push?: {
        register(): Promise<PushRegistration>;
    };
    /** A native service holding `GET /__bolt/notices` open while the app is in the background. */
    notices?: {
        start(options: {
            url: string;
        }): Promise<void>;
        stop(): Promise<void>;
    };
    /** Opens a URL outside the workspace in the system browser. */
    navigation?: {
        openExternal(url: string): Promise<void>;
    };
};

the device a shell (the native app shell, a desktop shell) installs as window.boltDevice before the workspace bundle runs; every member is optional and feature-detected. Without one, Bolt uses the browser's own device. Availability grants no server authority.

Members

NameTypeDescription
platform?'ios' | 'android' | 'web' | 'desktop'
pinned?true

A shell bound to one workspace (an app): the page offers no way to another workspace.

notifications?NativePermission & DeviceNotifications

Native notifications: their permission, raising one, and the path a tapped one opens.

camera?NativePermission

Native camera permission, where the host's web view needs one.

geolocation?{ source: 'native' | 'browser'; api: Geolocation; /** Native authorization, independently of whether a foreground fix is available. */ background?: { status(): Promise<{ enabled: boolean; always: boolean; }>; openSettings(): Promise<void>; }; }
push?{ register(): Promise<PushRegistration>; }

This device's push endpoint (it asks the platform for it, and for permission where the platform needs to).

notices?{ start(options: { url: string; }): Promise<void>; stop(): Promise<void>; }

A native service holding GET /__bolt/notices open while the app is in the background.

navigation?{ openExternal(url: string): Promise<void>; }

Opens a URL outside the workspace in the system browser.

Source: packages/bolt/src/page/device.ts:35

LiveRead type

type LiveRead<A> = Stream.Stream<A, ReadFailed>;

Current answers from a subscribed read; consuming the Stream owns the subscription, and read failures are ReadFailed.

Source: packages/bolt/src/page/page-bolt.ts:59

PageAct type

type PageAct<O, N = string> = Effect.Effect<Committed<O, N> | PendingApproval<N>, ActRefused | ActConflict | ActUnknown>;

A caller-authorized write: committed output or a held approval proposal succeeds; refusal, conflict and uncertain settlement are typed failures.

Source: packages/bolt/src/page/page-bolt.ts:61

PageBolt interface

interface PageBolt {
    /** Dynamic declarations use the viewer's native read policies and retain any masked selected values. */
    read<C extends string>(collection: Is<C, ReadableName>, query: DeclaredQuery): Read<Page<DeclaredRow<C>>>;
    /** The record's field and operation permissions for its current revision; `null` when it is absent or not readable. */
    recordCapabilities<C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, parent?: RecordParentContext): PageCall<RecordCapabilities | null, TransportFailed | ProtocolFailed>;
    /**
     * A page of rows the caller may read: `where`, `select`, `orderBy`, a text `search`, and `limit` (or `all: true`).
     * @example
     * const open = live(() => bolt.live(bolt.read('jobs', { where: { status: { eq: 'open' } }, orderBy: { due_on: 'asc' }, limit: 50 })));
     */
    read<C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, q: {
        where?: NoInfer<Where<C>>;
        select?: S;
        orderBy?: NoInfer<OrderBy<C>>;
        search?: string;
    } & Paged): Read<Page<ListResult<C, S>>>;
    /** One record by id as the caller reads it, with an optional `select`; `null` when it is absent or not readable. */
    get<C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, select?: S): Read<ReadResult<C, S> | null>;
    /** The record as of `revision`, folded from its history (L-BOLT-181); `null` when its create was pruned…

The typed members of $bolt (§3.5); a page reads and acts as its viewer, so rows are caller rows.

Members

NameTypeDescription
read{ <C extends string>(collection: Is<C, ReadableName>, query: DeclaredQuery): Read<Page<DeclaredRow<C>>>; <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, q: { where?: NoInfer<Where<C>>; select?: S; orderBy?: NoInfer<OrderBy<C>>; search?: string; } & Paged): Read<Page<ListResult<C, S>>>; }

Dynamic declarations use the viewer's native read policies and retain any masked selected values. A page of rows the caller may read: where, select, orderBy, a text search, and limit (or all: true).

recordCapabilities<C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, parent?: RecordParentContext) => PageCall<RecordCapabilities | null, TransportFailed | ProtocolFailed>

The record's field and operation permissions for its current revision; null when it is absent or not readable.

get{ <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, select?: S): Read<ReadResult<C, S> | null>; <C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, select: undefined, options: { revision: number; }): Read<StoredRow<C> | null>; }

One record by id as the caller reads it, with an optional select; null when it is absent or not readable. The record as of revision, folded from its history (L-BOLT-181); null when its create was pruned or history is not readable.

aggregate{ <C extends string>(collection: Is<C, ReadableName>, q: Measures<C> & { by?: never; }): Read<AggRow>; <C extends string>(collection: Is<C, ReadableName>, q: Measures<C> & { by: NoInfer<Bucket<C>> | readonly NoInfer<Bucket<C>>[]; } & Paged): Read<Page<AggRow>>; }

Without by, one row over the whole scope; with by, a page of buckets (rule 9).

similar{ <C extends string, N extends SimilarityName<C>, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, search: N, input: NoInfer<In<SimilaritiesOfC<C>[N]>>, q: { where?: NoInfer<Where<C>>; select?: S; limit: number; }): Read<readonly (ListResult<C, S> & { readonly $distance: number; })[]>; <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, q: { to: str…

A named similarity search (§3.3.4): nearest first, each row with its $distance. Over search.semantic (L-BOLT-123): nearest by meaning to a text, or to a record's own embedding (the record itself left out).

history<C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, options?: { at?: { instant: Instant; } | { revision: number; } | { before: RequestId; }; }) => Read<readonly Revision<C>[]>

A record's revisions, newest first, or as of an instant, a revision or before an approval request.

query<const N extends string>(name: Is<N, QueryCallable>, input: NoInfer<QueryInput<N>>) => Read<QueryOutput<N>>

Runs a collection query ('<c>.<q>') with its typed input.

live<A>(read: Read<A>, options?: { every?: string; on?: readonly CollectionName[]; }) => LiveRead<A>

Keeps a read current: re-read when the rows it depends on change (or on those collections, or every interval).

act<const N extends string>(callable: Is<N, Callable>, input: NoInfer<ActInput<N>>, options?: { key?: string; once?: string; observed?: Readonly<Record<string, number>>; }) => PageAct<ActOutput<N>, N>

Runs a callable with its typed input; a held write is a success.

start<const A extends string>(automation: Is<A, StartableName>, input: NoInfer<StartInput<A>> | readonly NoInfer<StartInput<A>>[]) => PageStart<A>

Starts an automation now with its typed input, or once per input in one request (a bulk action over selected records); id/ids are the runs' ids before the outcome settles (a toolbar item returning it shows the runs).

upload(file: Blob & { name?: string; }, field: UploadField) => PageCall<FileRef, ActRefused | TransportFailed>

accept and max are checked before bytes are stored; a refusal is ActRefused.

fileUrl(ref: Pick<FileRef, "id">, options?: FileUrlOptions) => string

The URL a page shows or downloads a stored file from.

t(key: MessageKey, vars?: { readonly [name: string]: string | number; }) => string

A message of +messages.ts in the page's locale, {name} placeholders filled from vars.

session{ sendCode(address: string): PageCall<void, Refusal>; verify(address: string, code: string): PageCall<void, Refusal>; }

On-page sign-in (§5.11.2): sendCode texts or emails a six-digit code, verify proves it, signs the viewer in — a newcomer joins where the workspace declares signup — and reloads the page as them. A refusal is a Refusal. ui's <PhoneVerify session={bolt.session} /> is the whole control.

actorActor | null

Who the page runs as; null before a visitor page has one.

Source: packages/bolt/src/page/page-bolt.ts:91

PageCall type

type PageCall<A, E> = Effect.Effect<A, E>;

A page operation with its own typed failure channel, executed by the mounted UI runtime through run, fork or attach.

Source: packages/bolt/src/page/page-bolt.ts:73

PageStart type

type PageStart<A extends string = string> = Effect.Effect<Outcome<unknown>> & {
    /** The first run's id; `ids` holds every run's, one per input. */
    readonly id: Id<'sys_run'>;
    readonly ids: readonly Id<'sys_run'>[];
    readonly automation: A;
};

An automation's eventual outcome, carrying its run id and automation name before the caller waits for settlement.

Members

NameTypeDescription
idId<'sys_run'>

The first run's id; ids holds every run's, one per input.

idsreadonly Id<'sys_run'>[]
automationA

Source: packages/bolt/src/page/page-bolt.ts:66

Read type

type Read<A> = Effect.Effect<A, ReadFailed | TransportFailed> & {
    readonly read: WireRead;
};

Run once for an answer, or pass to live for current answers.

Members

NameTypeDescription
readWireRead

Source: packages/bolt/src/page/page-bolt.ts:57

attach function

function attach<N extends Element>(f: (node: N) => Effect.Effect<unknown, never, Scope.Scope>): Attachment<N>

{@attach attach((node) => effect)}: the effect runs scoped for the element's lifetime, interrupted when it leaves.

Parameters

NameTypeDescription
f(node: N) => Effect.Effect<unknown, never, Scope.Scope>

Source: packages/ui/src/effect/index.ts:215

bolt const

const bolt: Omit<{ options: (collection: string, fields?: readonly { name: string; label: string; kind: "text" | "number" | "bool"; optional?: boolean; }[]) => Effect<{ readonly fields: readonly { readonly label: string; readonly kind: string; readonly path: readonly ({ readonly k: "field"; readonly name: string; } | { readonly k: "is"; readonly rel: string; } | { readonly k: "arm"; readonly rel: string; readonly arm: string; } | { readonly k: "every" | "some" | "none"; readonly rel: string; } | { readonly k: "count"; readonly rel: string; } | { readonly k: "agg"; readonly rel: string; readonly fn: "min"…

The shell client typed by the workspace's names: the same rows, inputs and outcomes as ctx (§3.5).

Members

NameTypeDescription
agent{ open: (request?: AgentRequest) => void; models: () => readonly string[]; }

The agent panel: open it (optionally with a request), and the model classes the host offers.

integration(instance: string) => import("../page/integrations.ts").IntegrationClient

An integration instance's host verbs: its status, pairing, test and status stream (IntegrationSetup draws them).

decode(collection: string, view: { where?: Json; orderBy?: Json; }) => { where: Json; orderBy?: Json; dropped: { path: string; message: string; }[]; }
options(collection: string, fields?: readonly { name: string; label: string; kind: "text" | "number" | "bool"; optional?: boolean; }[]) => Effect.Effect<{ readonly fields: readonly { readonly label: string; readonly kind: string; readonly path: readonly ({ readonly k: "field"; readonly name: string; } | { readonly k: "is"; readonly rel: string; } | { readonly k: "arm"; readonly rel: string; readonly arm…
href(app: string, page?: string | undefined, record?: { collection: string; id: string; } | undefined) => string

The path of an app page, optionally opening a record: bolt.href(app, page?, record?).

localestring
restore{ preview: (collection: string, record: string, revision: number) => Effect.Effect<{ changes: { current: Json; restored: Json; field: string; approval: boolean; }[]; skipped: { current: Json; restored: Json; field: string; reason: import("@norbital-ai/ui").RestoreSkip; }[]; collection: string; record: string; revision: number; live: number; }, import("../decl/errors.ts").ActRefused | import("../d…
approvals{ process: (requestId: string, decision: { status: import("../engine/approvals/approvals.ts").DecisionStatus; reason?: string; }) => Effect.Effect<{ kind: "committed"; output: Json; records: import("../engine/contracts.ts").Written; } | { kind: "pendingApproval"; requestId: string; records: import("../engine/contracts.ts").Written; }, import("../decl/errors.ts").ActRefused | import("../decl/error…
closedstring | null
syncStream.Stream<import("../page/bolt.ts").SyncStatus, never, never>
describe?(collection: string, text: string, fields?: readonly { name: string; label: string; kind: "text" | "number" | "bool"; optional?: boolean; }[]) => Effect.Effect<{ readonly where: Schema.Json; readonly orderBy?: Schema.Json; }, import("../decl/errors.ts").ActRefused | import("../decl/errors.ts").ActConflict | import("../decl/errors.ts").ActUnknown | ProtocolFailed | import("../decl/errors.ts").Desc…
deviceDeviceApi
integrationSetup(name: string) => import("./integration/setup.ts").IntegrationSetupLoader | undefined

A definition's own setup component (integration/<name>/+integration.svelte), loaded only when its UI opens.

org{ name: string; logo: string | null; }

The page's organization: the workspace name and its brand logo (the host's first icon), or null.

runs((automation: string, options: { where?: Json; limit: number; }) => Stream.Stream<{ rows: import("../engine/index.ts").RunView[]; next: null; }, ShellError, never>) & { stop: (id: string) => Effect.Effect<import("../engine/index.ts").RunView, ShellError, never>; }
read{ <C extends string>(collection: Is<C, ReadableName>, query: DeclaredQuery): Read<Page<DeclaredRow<C>>>; <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, q: { where?: NoInfer<Where<C>>; select?: S; orderBy?: NoInfer<OrderBy<C>>; search?: string; } & Paged): Read<Page<ListResult<C, S>>>; }

Dynamic declarations use the viewer's native read policies and retain any masked selected values. A page of rows the caller may read: where, select, orderBy, a text search, and limit (or all: true).

recordCapabilities<C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, parent?: RecordParentContext) => PageCall<RecordCapabilities | null, TransportFailed | ProtocolFailed>

The record's field and operation permissions for its current revision; null when it is absent or not readable.

get{ <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, select?: S): Read<ReadResult<C, S> | null>; <C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, select: undefined, options: { revision: number; }): Read<StoredRow<C> | null>; }

One record by id as the caller reads it, with an optional select; null when it is absent or not readable. The record as of revision, folded from its history (L-BOLT-181); null when its create was pruned or history is not readable.

aggregate{ <C extends string>(collection: Is<C, ReadableName>, q: Measures<C> & { by?: never; }): Read<AggRow>; <C extends string>(collection: Is<C, ReadableName>, q: Measures<C> & { by: NoInfer<Bucket<C>> | readonly NoInfer<Bucket<C>>[]; } & Paged): Read<Page<AggRow>>; }

Without by, one row over the whole scope; with by, a page of buckets (rule 9).

similar{ <C extends string, N extends SimilarityName<C>, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, search: N, input: NoInfer<In<SimilaritiesOfC<C>[N]>>, q: { where?: NoInfer<Where<C>>; select?: S; limit: number; }): Read<readonly (ListResult<C, S> & { readonly $distance: number; })[]>; <C extends string, const S extends Select<C> = {}>(collection: Is<C, ReadableName>, q: { to: str…

A named similarity search (§3.3.4): nearest first, each row with its $distance. Over search.semantic (L-BOLT-123): nearest by meaning to a text, or to a record's own embedding (the record itself left out).

history<C extends string>(collection: Is<C, ReadableName>, id: NoInfer<Id<C>>, options?: { at?: { instant: Instant; } | { revision: number; } | { before: RequestId; }; }) => Read<readonly Revision<C>[]>

A record's revisions, newest first, or as of an instant, a revision or before an approval request.

query<const N extends string>(name: Is<N, QueryCallable>, input: NoInfer<QueryInput<N>>) => Read<QueryOutput<N>>

Runs a collection query ('<c>.<q>') with its typed input.

live<A>(read: Read<A>, options?: { every?: string; on?: readonly CollectionName[]; }) => LiveRead<A>

Keeps a read current: re-read when the rows it depends on change (or on those collections, or every interval).

act<const N extends string>(callable: Is<N, Callable>, input: NoInfer<ActInput<N>>, options?: { key?: string; once?: string; observed?: Readonly<Record<string, number>>; }) => PageAct<ActOutput<N>, N>

Runs a callable with its typed input; a held write is a success.

start<const A extends string>(automation: Is<A, StartableName>, input: NoInfer<StartInput<A>> | readonly NoInfer<StartInput<A>>[]) => PageStart<A>

Starts an automation now with its typed input, or once per input in one request (a bulk action over selected records); id/ids are the runs' ids before the outcome settles (a toolbar item returning it shows the runs).

upload(file: Blob & { name?: string; }, field: never) => PageCall<FileRef, ActRefused | TransportFailed>

accept and max are checked before bytes are stored; a refusal is ActRefused.

fileUrl(ref: Pick<FileRef, "id">, options?: FileUrlOptions) => string

The URL a page shows or downloads a stored file from.

t(key: MessageKey, vars?: { readonly [name: string]: string | number; }) => string

A message of +messages.ts in the page's locale, {name} placeholders filled from vars.

session{ sendCode(address: string): PageCall<void, Refusal>; verify(address: string, code: string): PageCall<void, Refusal>; }

On-page sign-in (§5.11.2): sendCode texts or emails a six-digit code, verify proves it, signs the viewer in — a newcomer joins where the workspace declares signup — and reloads the page as them. A refusal is a Refusal. ui's <PhoneVerify session={bolt.session} /> is the whole control.

actorActor | null

Who the page runs as; null before a visitor page has one.

Source: packages/bolt/src/page/index.ts:16

fileRef function

function fileRef(file: { readonly id: string; readonly name: string; readonly mime: string; }): FileRef

A stored-file handle from upload or a row read, as bolt's branded FileRef for writes and acts.

Parameters

NameTypeDescription
file{ readonly id: string; readonly name: string; readonly mime: string; }
  • id: string
  • name: string
  • mime: string

Source: packages/bolt/src/page/file-ref.ts:25

fork function

function fork<A>(effect: Effect.Effect<A>): void
function fork<A, E>(effect: Effect.Effect<A, E>, onFailure: (error: E) => void): void

For an event handler: runs the effect; onFailure receives its failure, and the type requires it when one can occur.

Parameters

NameTypeDescription
effectEffect.Effect<A>

Source: packages/ui/src/effect/index.ts:71

frameworkText function

function frameworkText(locale: string): { readonly [key: string]: string; }

The framework copy of a locale (none for English: the key is the text).

Parameters

NameTypeDescription
localestring

Source: packages/bolt/src/shell/i18n.ts:1018

live function

function live<A, E>(source: () => Stream.Stream<A, E> | null, options?: QueryOptions<A>): QueryState<A, E>

A live read in a component (call it while the component initializes): the stream source() names, or none for null. A change of its reactive inputs subscribes the new stream from empty; teardown interrupts the fiber.

Parameters

NameTypeDescription
source() => Stream.Stream<A, E> | null
options?QueryOptions<A>

Source: packages/ui/src/effect/index.ts:106

query function

function query<A, E>(source: () => Effect.Effect<A, E> | null, options?: QueryOptions<A>): QueryState<A, E>

A one-shot read composes into the same state and lifetime as a live query.

Parameters

NameTypeDescription
source() => Effect.Effect<A, E> | null
options?QueryOptions<A>

Source: packages/ui/src/effect/index.ts:204

resolveDevice function

function resolveDevice(host?: DeviceApi): DeviceApi

Explicit device win; otherwise read this document's own native descriptor before browser fallback.

Parameters

NameTypeDescription
host?DeviceApi

Source: packages/bolt/src/page/device.ts:119

run function

function run<A, E>(effect: Effect.Effect<A, E>): Promise<A>

For {#await run(effect)}: resolves with the success, rejects with the tagged failure for {:catch} to render.

Parameters

NameTypeDescription
effectEffect.Effect<A, E>

Source: packages/ui/src/effect/index.ts:60