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
| Name | Type | Description |
|---|---|---|
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 |
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
| Name | Type | Description |
|---|---|---|
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: |
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; |
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 |
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 |
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 |
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 ( |
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 |
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); |
upload | (file: Blob & { name?: string; }, field: UploadField) => PageCall<FileRef, ActRefused | TransportFailed> |
|
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 |
session | { sendCode(address: string): PageCall<void, Refusal>; verify(address: string, code: string): PageCall<void, Refusal>; } | On-page sign-in (§5.11.2): |
actor | Actor | null | Who the page runs as; |
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
| Name | Type | Description |
|---|---|---|
id | Id<'sys_run'> | The first run's id; |
ids | readonly Id<'sys_run'>[] | |
automation | A |
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
| Name | Type | Description |
|---|---|---|
read | WireRead |
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
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
agent | { open: (request?: AgentRequest) => void; models: () => readonly string[]; } | The agent panel: |
integration | (instance: string) => import("../page/integrations.ts").IntegrationClient | An integration instance's host verbs: its status, pairing, test and status stream ( |
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: |
locale | string | |
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… | |
closed | string | null | |
sync | Stream.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… | |
device | DeviceApi | |
integrationSetup | (name: string) => import("./integration/setup.ts").IntegrationSetupLoader | undefined | A definition's own setup component ( |
org | { name: string; logo: string | null; } | The page's organization: the workspace name and its brand logo (the host's first icon), or |
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: |
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; |
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 |
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 |
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 |
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 ( |
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 |
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); |
upload | (file: Blob & { name?: string; }, field: never) => PageCall<FileRef, ActRefused | TransportFailed> |
|
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 |
session | { sendCode(address: string): PageCall<void, Refusal>; verify(address: string, code: string): PageCall<void, Refusal>; } | On-page sign-in (§5.11.2): |
actor | Actor | null | Who the page runs as; |
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
| Name | Type | Description |
|---|---|---|
file | { readonly id: string; readonly name: string; readonly 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
| Name | Type | Description |
|---|---|---|
effect | Effect.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
| Name | Type | Description |
|---|---|---|
locale | string |
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
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
effect | Effect.Effect<A, E> |