import { Delta } from './merge.js'; /** * Every imperative command {@link Command} can carry, keyed by its `type` * discriminator. Each entry pairs the `input` the consumer supplies with the * `output` its result returns — the command-specific value that sits *beside* * the {@link SessionStateChanged} every result also folds (cohort changes * always ride the state, never `output`). * * This map is the single source of truth: {@link Command} and * {@link CommandOutput} both derive from it, so adding a command — or changing * its shape — is one entry here and `send` stays end-to-end typed with no edit * elsewhere. */ export type CommandRegistry = { /** * Upsert identities for the session (by `tag`). May re-anchor the `user_id`; * the new value is returned in `output.user_id` *only* when it changed. */ identify: { input: { identities: ReadonlyArray; }; output: { readonly user_id?: string; }; }; /** * Track an event. */ track: { input: { view_key?: ViewKey; name: string; properties: Properties; }; /** * In future, output will contain the enriched event following server-side * processing. */ output: void; }; }; /** The `type` discriminator of an imperative command (`keyof` the registry). */ export type CommandType = keyof CommandRegistry; /** * An imperative command: a `type` discriminator and the matching `input` for * that type. `K` is inferred from the literal `type` at the `send` call site — * `send({ type: 'identify', input })` fixes `K` to `'identify'`, which in turn * types the result (see {@link Result}). */ export type Command = { readonly type: K; readonly input: CommandRegistry[K]['input']; }; /** The command-specific output a {@link Result} of type `K` carries (beside `change`). */ export type CommandOutput = CommandRegistry[K]['output']; /** * A domain-level command failure: a numeric `code` from the session protocol's * closed registry and an optional human-readable `message`. Surfaced as the * rejection reason of a `send`/`openSession` whose command the server refused — * the session itself stays open (a refused *open* ends the connection). Branch * on `code`, never on `message`. */ export type DomainFailure = { readonly code: number; readonly message?: string; }; /** * The outcome of a {@link Command}: its command-specific `output` plus the * {@link SessionStateChanged} produced by folding the cohort state the result * carried. */ export type Result = { readonly output: CommandOutput; readonly change: SessionStateChanged; }; /** A free-form key/value bag the client ships opaquely (event/view properties). */ export type Properties = { readonly [key: string]: unknown; }; export type SessionStateChanged = { current: SessionState; previous: SessionState; delta: Delta; }; export declare function getCohorts(state: SessionState): ReadonlyArray; export declare function getActivation(state: SessionState, activationPlatform: string): ReadonlyArray; /** * A user identity to upsert by `tag`; higher `priority` wins resolution. * * TODO(toni): the deployment guide frames priority as a fixed hierarchy by * identifier *type* (authenticated first-party > device id > generated id), * but here it's a free `number` the caller supplies and the client doesn't * validate against any canonical ordering. Reconcile — should priority be * derived from `tag` rather than left to the caller? */ export type Identity = { tag: string; id: string; priority?: number; }; /** A consumer-supplied key for one view within a client (e.g. use a counter). */ type ViewKey = string; export type Context = { views: Record; }; type ViewContext = { title?: string; url?: string; }; export type SessionState = { readonly user_id: string; /** * The session's server id. Stable for the life of the session and safe to * log or display — it identifies the session for debugging. To *resume* the * session, use {@link SessionState.session_resume_token}, not this. */ readonly session_id: string; /** * The opaque token that resumes this session — pass it back as * {@link OpenSessionOptions.session_resume_token} to pick the session up * again (for example across a page reload). Minted by the server; treat it as * opaque: do not parse or construct it, only persist it verbatim and hand it * back. What it encodes is the server's concern and may change without a * client API change. */ readonly session_resume_token: string; readonly segmentation: { readonly user: CohortsAndActivations; readonly session: CohortsAndActivations; readonly views: Record; }; }; export type CohortsAndActivations = { cohorts: Record; activations: Record>; }; export {};