import { Delta } from './merge.js'; import { Command, CommandRegistry, CommandType, Context, Identity, Result, SessionState, SessionStateChanged } from './model.js'; import { Transport } from './channel/transport.js'; export type PermutiveConfig = { apiKey: string; /** * The {@link Transport} sessions run on. Optional — defaults to a * {@link WebSocketTransport} connected to the production endpoint, or the * {@link Http1Transport} fallback where the runtime has no `WebSocket`. */ transport?: Transport; }; export type OpenSessionOptions = { /** * The session to attach to, taken from a prior session's * {@link SessionState.session_resume_token}. A live session is resumed * (keeping its own `user_id`); one that is no longer live recreates under the * same id. Omit to start a fresh session under a server-minted id. The token * is opaque — pass it back verbatim. */ session_resume_token?: string; /** * The client's known user, taken only when the open creates a session — a * resumed session keeps its own user. Omit (with `session_resume_token`) for * a fresh anonymous user. */ user_id?: string; /** * Identities to seed the session with at open, upserted by `tag` — the * declarative equivalent of an `identify` command sent immediately after. * May anchor the resolved `user_id`. */ identities?: ReadonlyArray; /** * The client's declared context — its set of open views. Omit to open * with no views; declare them later with {@link Session.setContext}. */ context?: Context; }; /** The configured client entry point, created by {@link permutive}. */ export interface Permutive { /** * Open a session and resolve with a live {@link Session}. Connects the * configured {@link Transport}, opens a {@link Channel} over it, and sends * the open before handing back the session. A `session_resume_token` resumes * that session (recreating it under the same id when it is no longer live); * omitting it starts a fresh session. Every option is optional — a bare * `openSession()` opens a fresh anonymous session with no views. * * The session outlives the connection it opens on: where the server refuses * to resume that connection, the client reopens the session on a fresh one * rather than ending it (see {@link Session.closed}). */ openSession(options?: OpenSessionOptions): PromiseLike; } /** * Configure the client once and get back a {@link Permutive} to open sessions * from. The `config` (api key, optional transport) is captured here, so each * {@link Permutive.openSession} call carries only its per-session options. When * no `transport` is given, a {@link WebSocketTransport} connected to the * production endpoint is used, falling back to the {@link Http1Transport} where * the runtime has no `WebSocket`. */ export declare function permutive(config: PermutiveConfig): Permutive; /** * One client of one session, resolved by {@link Permutive.openSession}. */ export interface Session { /** * The session's terminal end, as a {@link PromiseLike}: it resolves with the * reason the session ended — the reason passed to {@link Session.close} * (`undefined` for a plain close), or a connection failure the session could * not recover from. * * A connection ending is not the session ending. Where the server refuses to * resume a connection, the session reopens on a fresh one and this stays * pending; it resolves only once the client has given up — on an end that is * final (a bad api key, a protocol violation), on a reopen the server itself * refused, or on refusals in a row past the point of retrying (see * `REOPEN_LIMIT`). */ readonly closed: PromiseLike; setContext(context: Context): PromiseLike; getState(): SessionState; send(commandType: K, input: CommandRegistry[K]['input']): PromiseLike>; send(command: Command): PromiseLike>; /** Upsert identities for the user — `send('identify', input)`, dedicated. */ identify(input: CommandRegistry['identify']['input']): PromiseLike>; /** Track an event — `send('track', input)`, dedicated. */ track(input: CommandRegistry['track']['input']): PromiseLike>; /** * Observe every applied fold of session-state. Returns an unsubscribe function. * Errors are not reported here — a terminal connection failure surfaces * through {@link Session.closed}. */ onStateChange(listener: (event: SessionStateChanged) => void): () => void; /** * End the session deliberately. Resolves {@link Session.closed} with the * optional `reason` and fails any in-flight command. */ close(reason?: string): void; } /** * Encode a command as its wire tuple: `[type, payload]`, or a bare `[type]` * when the payload is absent (`ping`, and a bare open). The single client-side * command encoder; the transport carries the tuple opaquely. */ export declare function encodeCommand(type: string, payload?: unknown): ReadonlyArray; /** * A successful command result: `[1, value?, delta?]`. The `value` slot is a * `null` filler when a `delta` rides without a value; `open_session`'s value is * the full session-state. */ export type WireSuccess = readonly [ ok: 1, value?: unknown, delta?: Delta ]; /** A domain-failure result: `[0, code, message?]`. */ export type WireFailure = readonly [ok: 0, code: number, message?: string]; /** * A command's result as its wire tuple, read by index rather than decoded into * a struct. The opaque transport payload is asserted to this type once, at the * decode boundary, then narrowed on the leading `ok` discriminant. */ export type WireResult = WireSuccess | WireFailure;