/** * Public interface for the builder package. This module exports only the types * and functions that are part of the public pattern API. * * Workspace code should import these types via `@commonfabric/builder`. */ import type { Cfc, WriteAuthorizedBy } from "./cfc.ts"; // ============================================================================ // Fabric Value Types // ============================================================================ // // Pattern-visible declarations for the fabric value type system. Canonical // implementations live in data-model submodule files (interface.ts, // fabric-primitives/FabricHash.ts, fabric-primitives/FabricEpochNsec.ts, etc.) // — these inline declarations mirror the public surface so the pattern compiler // can resolve them without relative imports. // // SYNC NOTE: These declarations must stay in sync with the canonical // definitions in the submodule files. If they drift, pattern type-checking // will diverge from runtime behavior. // // Every concrete FabricPrimitive subclass must have an instanceof-capable // declaration here (interface + constructor + declare-const with `new`). /** * Common base class for `FabricInstance` and `FabricPrimitive`. Enables a * single `instanceof` check for any fabric-system value type. */ // deno-lint-ignore no-empty-interface export interface FabricSpecialObject {} export interface FabricSpecialObjectConstructor { prototype: FabricSpecialObject; } export declare const FabricSpecialObject: & FabricSpecialObjectConstructor & (abstract new (...args: any) => FabricSpecialObject); /** * Abstract base class for values that participate in the fabric protocol. */ export interface FabricInstance extends FabricSpecialObject { shallowClone(frozen: boolean): FabricInstance; } export interface FabricInstanceConstructor { prototype: FabricInstance; } export declare const FabricInstance: & FabricInstanceConstructor & (abstract new (...args: any) => FabricInstance); /** Abstract base class for fabric primitive types. */ export interface FabricPrimitive extends FabricSpecialObject {} export interface FabricPrimitiveConstructor { prototype: FabricPrimitive; } export declare const FabricPrimitive: & FabricPrimitiveConstructor & (abstract new (...args: any) => FabricPrimitive); /** * Temporal type representing nanoseconds from the POSIX Epoch. * Wraps a `bigint` value. */ export interface FabricEpochNsec extends FabricPrimitive { readonly value: bigint; } export interface FabricEpochNsecConstructor { new (value: bigint): FabricEpochNsec; prototype: FabricEpochNsec; } export declare const FabricEpochNsec: FabricEpochNsecConstructor; /** * Temporal type representing days from the POSIX Epoch. * Wraps a `bigint` value. */ export interface FabricEpochDays extends FabricPrimitive { readonly value: bigint; } export interface FabricEpochDaysConstructor { new (value: bigint): FabricEpochDays; prototype: FabricEpochDays; } export declare const FabricEpochDays: FabricEpochDaysConstructor; /** * A content-addressed identifier: a hash digest paired with an algorithm tag. * Extends `FabricPrimitive` -- treated like a primitive in the fabric type * system (always frozen, passes through conversion unchanged). */ export interface FabricHash extends FabricPrimitive { readonly tag: string; readonly bytes: Uint8Array; readonly length: number; readonly hashString: string; toString(): string; } export interface FabricHashConstructor { new (hash: Uint8Array, tag: string): FabricHash; prototype: FabricHash; } export declare const FabricHash: FabricHashConstructor; /** * The modern, object-shaped form of a link reference, wrapping the link's * addressing payload (a `FabricPlainObject`: its addressing fields plus an optional * `schema`). Extends `FabricInstance` (not `FabricPrimitive`): the payload is an * outgoing reference (it may carry an arbitrary-`FabricValue` `schema`), so a * link is a small object graph, not a leaf. */ export interface FabricLink extends FabricInstance { readonly payload: FabricPlainObject; } export interface FabricLinkConstructor { new (payload: FabricPlainObject): FabricLink; prototype: FabricLink; } export declare const FabricLink: FabricLinkConstructor; /** * The full set of values that the fabric storage layer can represent. */ export type FabricValue = | null | boolean | number | string | bigint | FabricSpecialObject | FabricArray | FabricPlainObject | undefined; /** An array of fabric values. */ export interface FabricArray extends ArrayLike {} /** An object/record of fabric values. */ export interface FabricPlainObject extends Record {} // ============================================================================ // Runtime Constants // ============================================================================ // Runtime constants - defined by @commonfabric/runner/src/builder/types.ts // These are ambient declarations since the actual values are provided by the runtime environment export declare const ID: unique symbol; export declare const ID_FIELD: unique symbol; // Should be Symbol("UI") or so, but this makes repeat() use these when // iterating over patterns. export declare const TYPE: "$TYPE"; export declare const NAME: "$NAME"; export declare const UI: "$UI"; // UI variants (CT-1321): optional sibling renderings addressed alongside [UI]. export declare const TILE_UI: "$TILE_UI"; export declare const CHIP_UI: "$CHIP_UI"; export declare const FS: "$FS"; /** * The size/representation spectrum a piece can be rendered at (CT-1321): * `full` = the standalone [UI]; `chip` = inline; `tile` = gallery/grid card. */ export type UIVariantKind = "full" | "chip" | "tile"; /** * Render a piece at a UI variant, for render paths that aren't already * `` JSX (CT-1321 Phase B / CT-1766). Returns a `cf-render` VNode * bound to the piece — equivalent to ``. * cf-render resolves the exported variant key ([CHIP_UI] / [TILE_UI] / [UI]) when * present and otherwise fails over to the per-variant platform default, including * link resolution and click-to-navigate. */ export type UIVariantFunction = ( piece: FactoryInput, kind?: UIVariantKind, ) => VNode; // Symbol for accessing self-reference in patterns export declare const SELF: unique symbol; export type SELF = typeof SELF; // ============================================================================ // Cell Brand System // ============================================================================ /** * Brand symbol for identifying different cell types at compile-time. * Each cell variant has a unique combination of capability flags. */ export declare const CELL_BRAND: unique symbol; /** * Symbol for phantom property that enables type inference from AnyBrandedCell. * This property doesn't exist at runtime - it's purely for TypeScript's benefit: * without a concrete property mentioning T, `AnyBrandedCell` cannot * infer U (T would be a phantom parameter and inference produces `unknown`). */ export declare const CELL_INNER_TYPE: unique symbol; /** * Minimal cell type with just the brand, no methods. * Used for type-level operations like unwrapping nested cells without * creating circular dependencies. */ export type CellKind = | "cell" | "opaque" | "stream" | "comparable" | "readonly" | "writeonly" | "sqlite"; export type CellScope = "space" | "user" | "session"; export type SchemaScope = CellScope | "any"; export type LinkScope = "inherit" | CellScope; export type AsCellEntry = | CellKind | { readonly kind: CellKind; readonly scope?: SchemaScope; }; export declare const SCOPE_BRAND: unique symbol; export type Scoped = T & { readonly [SCOPE_BRAND]?: Scope; }; export type PerSpace = Scoped; export type PerUser = Scoped; export type PerSession = Scoped; export type PerAny = Scoped; type ScopedConstructorResult< Scope extends CellScope, T, > = Scope extends "space" ? PerSpace : Scope extends "user" ? PerUser : Scope extends "session" ? PerSession : never; // `string` acts as `any`, e.g. when wanting to match any kind of cell // The [CELL_INNER_TYPE] property is a phantom property that enables TypeScript // to infer T when using `AnyBrandedCell`. Without it, T is a phantom // type parameter and TypeScript produces `unknown` when trying to infer it. // The property must be non-optional so that plain types like `string[]` don't // accidentally match AnyBrandedCell. export type AnyBrandedCell = { [CELL_BRAND]: Kind; readonly [CELL_INNER_TYPE]: T; }; export type BrandedCell = AnyBrandedCell; // ============================================================================ // Cell Capability Interfaces // ============================================================================ // To constrain methods that only exists on objects export type IsThisObject = | IsThisArray | AnyBrandedCell | AnyBrandedCell>; export type IsThisArray = | AnyBrandedCell | AnyBrandedCell> | AnyBrandedCell> | AnyBrandedCell | AnyBrandedCell; // To constrain methods that only exist on number cells export type IsThisNumber = | AnyBrandedCell | AnyBrandedCell | AnyBrandedCell; /* * IAnyCell is an interface that is used by all calls and to which the runner * attaches the internal methods.. */ // deno-lint-ignore no-empty-interface export interface IAnyCell {} /** * Readable cells provide a view onto stored data. * * **Frozenness contract:** `get()` and `sample()` * return a JS Proxy over the stored value. Writes through the proxy are * rejected with a "read-only" runtime error. The underlying stored * data is additionally a deep-frozen `FabricValue` tree, so callers that * escape the proxy (e.g. via `getRaw()`) see frozen data without an * extra clone. * * Note: `Object.isFrozen(proxy)` reports `false` regardless of the * underlying state — that's a property of how JS Proxy reports * extensibility, not a statement about mutability. */ export interface IReadable { /** * Read the cell's current value as a Proxy view. See the * {@link IReadable} interface docs for the frozenness contract. */ get(options?: { traverseCells?: boolean }): Readonly>; /** * Read the cell's current value without creating a reactive dependency. * Unlike `get()`, calling `sample()` inside a lift won't cause the lift * to re-run when this cell's value changes. The same frozenness * contract from {@link IReadable} applies. */ sample(): Readonly>; } export type MetaLinkField = | "pattern" | "argument" | "result"; /** * The `pattern` field links a result cell to its pattern * The `argument` field links a result cell to its argument cell * The `internal` field contains a manifest with links to derived internal cells. * The `schema` field stores the schema for a result cell * The `result` field lets a result cell link to its parent result cell, * and also lets the argument and derived internal cells link back to the result cell. * The cfc code accesses the `cfc` field directly, but I include it here too. */ export type MetaField = | MetaLinkField | "patternIdentity" // content-addressed {identity, symbol} pattern reference | "internal" | "schema" | "slug" | "cfc"; export interface IMetaCell { getMetaRaw(metaField: MetaField, options?: unknown): FabricValue; setMetaRaw(metaField: MetaField, value: FabricValue): void; } /** * Writable cells can update their value. * * **Frozenness contract:** Values passed into `set()`, `update()`, and `push()` * flow through a write-boundary normalization step that shallowly freezes any * plain unfrozen Object/Array levels it visits. Inputs that are already * deep-frozen valid `FabricValue` trees are accepted identity-preservingly with * no further cloning. */ export interface IWritable> { /** * Set the cell's value. See the {@link IWritable} interface docs for * the frozenness contract on the input. */ set(value: T | AnyCellWrapping): C; /** * Merge a partial object value into the cell. Implemented as a * per-key `set()`, so the same frozenness contract applies. See * {@link IWritable}. */ update | AnyCellWrapping>)>( this: IsThisObject, values: V extends object ? AnyCellWrapping : never, ): C; /** * Append one or more values to an array cell. See the * {@link IWritable} interface docs for the frozenness contract on the * inputs. */ push( this: IsThisArray, ...value: T extends (infer U)[] ? (U | AnyCellWrapping)[] : never ): void; /** * Add one or more values to an array cell as a set: each value is appended * only if no existing element equals it. Mergeable — concurrent adds of * distinct elements merge and a repeated add is a no-op against durable state. */ addUnique( this: IsThisArray, ...value: T extends (infer U)[] ? (U | AnyCellWrapping)[] : never ): void; /** * Add `by` (default 1, may be negative) to a number cell. Mergeable — * concurrent increments sum against durable state rather than clobber. */ increment(this: IsThisNumber, by?: number): void; remove( this: IsThisArray, ref: T extends (infer U)[] ? (U | AnyBrandedCell) : never, ): void; /** * Remove every element equal to `ref` by stored value (a cell matches by its * link). Mergeable — resolved against durable state, so concurrent removes of * distinct entries merge instead of clobbering via a whole-array rewrite. */ removeByValue( this: IsThisArray, ref: T extends (infer U)[] ? (U | AnyBrandedCell) : never, ): void; removeAll( this: IsThisArray, ref: T extends (infer U)[] ? (U | AnyBrandedCell) : never, ): void; } /** * Streamable cells can send events. */ export interface IStreamable { send( ...args: T extends void ? [] | [AnyCellWrapping] : [AnyCellWrapping] ): void; } // Lightweight HKT, so we can pass cell types to IKeyable<>. export interface HKT { _A: unknown; type: unknown; } export type Apply = (F & { _A: A })["type"]; /** * A key-addressable, **covariant** view over a structured value `T`. * * `IKeyableCell` exposes a single method, {@link IKeyableCell.key}, which selects a * property from the (possibly branded) value `T` and returns it wrapped in a * user-provided type constructor `Wrap` (default: `Cell<…>`). The interface is * declared `out T` (covariant) and is designed so that calling `key` preserves * both type inference and variance soundness. * * @template T * The underlying (possibly branded) value type. `T` is treated **covariantly**: * `IKeyableCell` is assignable to `IKeyableCell` when `Sub` is * assignable to `Super`. * * @template Wrap extends HKT * A lightweight higher-kinded “wrapper” that determines the return container for * selected fields. For example, `AsCell` wraps as `Cell`, while other wrappers * can project to `ReadonlyCell`, `Stream`, etc. Defaults to `AsCell`. * * @template Any * The “fallback” return type used when the provided key does not match a known * key (or is widened to `any`). This should usually be `Apply`. * * @remarks * ### Variance & soundness * The `key` signature is crafted to remain **covariant in `T`**. Internally, * it guards the instantiation `K = any` with `unknown extends K ? … : …`, so * the return type becomes `Any` (independent of `T`) in that case. For real keys * (`K extends keyof UnwrapCell`), the return type is precise and fully inferred. * * ### Branded / nested cells * If a selected property is itself a branded cell (e.g., `BrandedCell`), * the return value is a wrapped branded cell, i.e. `Wrap>`. * * ### Key inference * Passing a string/number/symbol that is a literal and a member of * `keyof UnwrapCell` yields precise field types; non-literal or unknown keys * fall back to `Any` (e.g., `Cell`). * * @example * // Basic usage with the default wrapper (Cell) * declare const userCell: IKeyableCell<{ id: string; profile: { name: string } }>; * const idCell = userCell.key("id"); // Cell * const profileCell = userCell.key("profile"); // Cell<{ name: string }> * * // Unknown key falls back to Any (default: Cell) * const whatever = userCell.key(Symbol()); // Cell * * @example * // Using a custom wrapper, e.g., ReadonlyCell * interface AsReadonlyCell extends HKT { type: ReadonlyCell } * type ReadonlyUserCell = IKeyableCell<{ id: string }, AsReadonlyCell, Apply>; * declare const ro: ReadonlyUserCell; * const idRO = ro.key("id"); // ReadonlyCell * * @example * // Covariance works: * declare const sub: IKeyableCell<{ a: string }>; * const superCell: IKeyableCell = sub; // OK (out T) */ export interface IKeyable { /** * Navigate to nested properties by one or more keys. * * @example * cell.key("user") // Cell * cell.key("user", "profile") // Cell * cell.key("user", "profile", "name") // Cell */ // Overloads to avoid recursive type evaluation which causes stack overflow // Zero keys key(this: IsThisObject): Apply; // One key key(this: IsThisObject, k1: K1): Apply; // Two keys key( this: IsThisObject, k1: K1, k2: K2, ): Apply; // Three keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], >(this: IsThisObject, k1: K1, k2: K2, k3: K3): Apply; // Four keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, ): Apply; // Five keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, ): Apply; // Six keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], K6 extends keyof T[K1][K2][K3][K4][K5], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, ): Apply; // Seven keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], K6 extends keyof T[K1][K2][K3][K4][K5], K7 extends keyof T[K1][K2][K3][K4][K5][K6], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, ): Apply; // Eight keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], K6 extends keyof T[K1][K2][K3][K4][K5], K7 extends keyof T[K1][K2][K3][K4][K5][K6], K8 extends keyof T[K1][K2][K3][K4][K5][K6][K7], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, ): Apply; // Nine keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], K6 extends keyof T[K1][K2][K3][K4][K5], K7 extends keyof T[K1][K2][K3][K4][K5][K6], K8 extends keyof T[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, k9: K9, ): Apply; // Ten keys key< K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3], K5 extends keyof T[K1][K2][K3][K4], K6 extends keyof T[K1][K2][K3][K4][K5], K7 extends keyof T[K1][K2][K3][K4][K5][K6], K8 extends keyof T[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8], K10 extends keyof T[K1][K2][K3][K4][K5][K6][K7][K8][K9], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, k9: K9, k10: K10, ): Apply; // Fallback for 11+ keys or unknown keys key(...keys: PropertyKey[]): Apply; /** * A cell for the entity deterministically derived from this array and `idKey` * — the entity a keyed element is identified by. The same `idKey` always * resolves to the same entity (a content-only derivation), so a handler can * read/edit one keyed element and manage its membership with addUnique / * removeByValue, without reading the whole array. */ elementById( this: IsThisArray, idKey: string, ): Apply; } /** * Helper to wrap a type, but preserve Cell/Stream types as-is to avoid double-wrapping. * Uses non-distributive conditionals to handle union types correctly. */ export type WrapOrPreserve = [T] extends [Cell] ? T : [T] extends [Stream] ? T : [T] extends [ComparableCell] ? T : [T] extends [ReadonlyCell] ? T : [T] extends [WriteonlyCell] ? T : [T] extends [OpaqueCell] ? T : Apply; /** * Result type for key() - chains multiple key lookups. * Supports single key: cell.key("a") or multiple: cell.key("a", "b", "c") * When the final value is already a Cell/Stream type, returns it as-is. */ export type KeyResultType< T, Keys extends readonly PropertyKey[], Wrap extends HKT, > = Keys extends readonly [] ? WrapOrPreserve : Keys extends readonly [ infer First extends PropertyKey, ...infer Rest extends readonly PropertyKey[], ] ? [unknown] extends [First] ? Apply // variance guard : [0] extends [1 & T] ? Apply // keep any as-is : First extends keyof T ? KeyResultType : Apply // unknown key fallback : Apply; /** * Result type for key() on OpaqueCell - chains multiple key lookups. */ export type KeyResultTypeOpaque< T, Keys extends readonly PropertyKey[], > = Keys extends readonly [] ? OpaqueCell : Keys extends readonly [ infer First extends PropertyKey, ...infer Rest extends readonly PropertyKey[], ] ? [unknown] extends [First] ? OpaqueCell : [0] extends [1 & T] ? OpaqueCell : First extends keyof UnwrapCell ? KeyResultTypeOpaque[First], Rest> : OpaqueCell : OpaqueCell; /** * Cells that support key() for property access - OpaqueCell variant. * OpaqueCell is "sticky" and always returns OpaqueCell<>. */ export interface IKeyableOpaque { /** * Navigate to nested properties by one or more keys. */ // Overloads to avoid recursive type evaluation which causes stack overflow key(this: IsThisObject): OpaqueCell; key>( this: IsThisObject, k1: K1, ): OpaqueCell[K1]>; key, K2 extends keyof UnwrapCell[K1]>( this: IsThisObject, k1: K1, k2: K2, ): OpaqueCell[K1][K2]>; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], >(this: IsThisObject, k1: K1, k2: K2, k3: K3): OpaqueCell< UnwrapCell[K1][K2][K3] >; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], >(this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4): OpaqueCell< UnwrapCell[K1][K2][K3][K4] >; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], >(this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5): OpaqueCell< UnwrapCell[K1][K2][K3][K4][K5] >; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], K6 extends keyof UnwrapCell[K1][K2][K3][K4][K5], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, ): OpaqueCell[K1][K2][K3][K4][K5][K6]>; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], K6 extends keyof UnwrapCell[K1][K2][K3][K4][K5], K7 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, ): OpaqueCell[K1][K2][K3][K4][K5][K6][K7]>; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], K6 extends keyof UnwrapCell[K1][K2][K3][K4][K5], K7 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6], K8 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, ): OpaqueCell[K1][K2][K3][K4][K5][K6][K7][K8]>; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], K6 extends keyof UnwrapCell[K1][K2][K3][K4][K5], K7 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6], K8 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7][K8], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, k9: K9, ): OpaqueCell[K1][K2][K3][K4][K5][K6][K7][K8][K9]>; key< K1 extends keyof UnwrapCell, K2 extends keyof UnwrapCell[K1], K3 extends keyof UnwrapCell[K1][K2], K4 extends keyof UnwrapCell[K1][K2][K3], K5 extends keyof UnwrapCell[K1][K2][K3][K4], K6 extends keyof UnwrapCell[K1][K2][K3][K4][K5], K7 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6], K8 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7], K9 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7][K8], K10 extends keyof UnwrapCell[K1][K2][K3][K4][K5][K6][K7][K8][K9], >( this: IsThisObject, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: K7, k8: K8, k9: K9, k10: K10, ): OpaqueCell[K1][K2][K3][K4][K5][K6][K7][K8][K9][K10]>; key(...keys: PropertyKey[]): OpaqueCell; } /** * Cells that can be created with a cause. */ export interface ICreatable> { /** * Set a cause for this cell. Used to create a link when the cell doesn't have * one yet. * @param cause - The cause to associate with this cell * @returns This cell for method chaining */ for(cause: unknown): C; } /** * Cells that can be resolved back to a Cell. * Only available on full Cell, not on OpaqueCell or Stream. * Note: Schema-typed overload available via "commonfabric/schema" */ export interface IResolvable> { resolveAsCell(): C; getArgumentCell(schema?: JSONSchema): Cell | undefined; } /** * Comparable cells have equals() method. * Available on comparable and readable cells. */ export interface IEquatable { equals(other: AnyCell | object | undefined): boolean; equalLinks(other: AnyCell | object | undefined): boolean; } /** * Cells that allow deriving new cells from existing cells via array methods: * direct helpers mirror supported Array methods and return Reactive results. * The WithPattern variants accept pre-defined patterns for per-element * operations. */ export interface IDerivable { map( this: IsThisObject, fn: ( element: T extends Array ? Reactive : Reactive, index: Reactive, array: Reactive, ) => FactoryInput, ): Reactive; mapWithPattern( this: IsThisObject, op: PatternFactory ? U : T, S>, params: Record, ): Reactive; reduce( this: IsThisObject, fn: ( accumulator: S, element: T extends Array ? U : T, index: number, array: (T extends Array ? U : T)[], ) => S, initialValue: S, ): Reactive; findIndex( this: IsThisObject, fn: ( element: T extends Array ? U : T, index: number, array: (T extends Array ? U : T)[], ) => boolean, ): Reactive; filter( this: IsThisObject, fn: ( element: T extends Array ? Reactive : Reactive, index: Reactive, array: Reactive, ) => FactoryInput, ): Reactive<(T extends Array ? U : T)[]>; filterWithPattern( this: IsThisObject, op: PatternFactory ? U : T, S>, params: Record, ): Reactive<(T extends Array ? U : T)[]>; flatMap( this: IsThisObject, fn: ( element: T extends Array ? Reactive : Reactive, index: Reactive, array: Reactive, ) => FactoryInput, ): Reactive; flatMapWithPattern( this: IsThisObject, op: PatternFactory ? U : T, S[]>, params: Record, ): Reactive; } export interface IOpaquable { /** deprecated */ setSchema(schema: JSONSchema): void; } // ============================================================================ // Cell Constructor Interfaces // ============================================================================ /** * Generic constructor interface for cell types with static methods. */ export interface CellTypeConstructor< Wrap extends HKT, > { /** * Create a cell with an initial/default value. In a reactive context, this * value will only be set on first call. * * AST transformation adds `.for("foo")` in `const foo = new Cell(value)`. * * Internally it just merges the value into the schema as a default value. * * @param value - The initial/default value to set on the cell * @param schema - Optional JSON schema for the cell * @returns A new cell */ new (value?: T, schema?: JSONSchema): Apply; /** * Create a cell with a cause. * * Can be chained with `new ...(...)` or .set(): * * const foo = Cell.for(cause).set(value); // sets cell to latest value * * @param cause - The cause to associate with this cell * @returns A new cell */ for(cause: unknown): Apply; /** * Create a cell with an initial/default value. In a reactive context, this * value will only be set on first call. * * Can be chained with .for() to set a cause and initial value. * E.g. `const foo = Cell.for(cause).of(value)`. * * AST transformation adds `.for("foo")` in `const foo = Cell.of(value)`. * * Internally it just merges the value into the schema as a default value. * * @param value - The initial/default value to set on the cell * @param schema - Optional JSON schema for the cell * @returns A new cell */ of(value?: T, schema?: JSONSchema): Apply; /** * Scoped constructor view for space-shared cells. */ perSpace: ScopedCellTypeConstructor; /** * Scoped constructor view for per-user cells. */ perUser: ScopedCellTypeConstructor; /** * Scoped constructor view for per-session cells. */ perSession: ScopedCellTypeConstructor; /** * Compare two cells or values for equality after resolving, i.e. after * following all links in case we have cells pointing to other cells. * @param a - First cell or value to compare * @param b - Second cell or value to compare * @returns true if the values are equal */ equals( a: AnyCell | object | undefined, b: AnyCell | object | undefined, ): boolean; /** * Compare two cells or values for equality by comparing their underlying * links. No resolving. * * @param a - First cell or value to compare * @param b - Second cell or value to compare * @returns true if the values are equal */ equalLinks( a: AnyCell | object | undefined, b: AnyCell | object | undefined, ): boolean; } export interface ScopedCellTypeConstructor< Wrap extends HKT, Scope extends CellScope, > { /** * Create a scoped cell with an initial/default value. */ new ( value?: T, schema?: JSONSchema, ): ScopedConstructorResult>; /** * Create a scoped cell with an initial/default value. */ of( value?: T, schema?: JSONSchema, ): ScopedConstructorResult>; /** * Create a scoped cell with a cause. */ for(cause: unknown): ScopedConstructorResult>; } // ============================================================================ // Cell Type Definitions // ============================================================================ /** * Base type for all cell variants that has methods. Internal API augments this * interface with internal only API. Uses a second symbol brand to distinguish * from core cell brand without any methods. */ export interface AnyCell extends AnyBrandedCell, IAnyCell { } /** * Opaque cell reference - only supports keying and derivation, not direct I/O. * Has .key(), .map(), .mapWithPattern() * Does NOT have .get()/.set()/.send()/.equals()/.resolveAsCell() */ export interface AsOpaqueCell extends HKT { type: OpaqueCell; } export interface IOpaqueCell extends IAnyCell, ICreatable>, IKeyableOpaque, IDerivable, IOpaquable {} export interface OpaqueCell extends BrandedCell, IOpaqueCell {} export declare const OpaqueCell: CellTypeConstructor; /** * Full cell with read, write capabilities. * Has .get(), .set(), .update(), .push(), .equals(), .key(), .resolveAsCell() * * Note: This is an interface (not a type) to allow module augmentation by the runtime. */ export interface AsCell extends HKT { type: Cell; } export interface ICell extends IAnyCell, ICreatable>, IReadable, IWritable>, IStreamable, IEquatable, IKeyable, IDerivable, IMetaCell, IResolvable> {} export interface Cell extends BrandedCell, ICell {} export declare const Cell: CellTypeConstructor; /** * Writable is an alias for Cell that better expresses the semantic meaning. * In patterns, requesting data as Writable means "I need write access" - * all data in patterns is reactive by default, whether wrapped or not. */ export type Writable = Cell; export declare const Writable: CellTypeConstructor; /** * Stream-only cell - can only send events, not read or write. * Has .send() only * Does NOT have .key()/.equals()/.get()/.set()/.resolveAsCell() * * Note: This is an interface (not a type) to allow module augmentation by the runtime. */ export interface AsStream extends HKT { type: Stream; } export interface Stream extends BrandedCell, IAnyCell, ICreatable>, IStreamable {} export declare const Stream: CellTypeConstructor; /** * Comparable-only cell - just for equality checks and keying. * Has .equals(), .key() * Does NOT have .resolveAsCell()/.get()/.set()/.send() */ export interface AsComparableCell extends HKT { type: ComparableCell; } export interface ComparableCell extends BrandedCell, IAnyCell, ICreatable>, IEquatable, IKeyable {} export declare const ComparableCell: CellTypeConstructor; /** * Read-only cell variant. * Has .get(), .equals(), .key() * Does NOT have .resolveAsCell()/.set()/.send() */ export interface AsReadonlyCell extends HKT { type: ReadonlyCell; } export interface ReadonlyCell extends BrandedCell, IAnyCell, ICreatable>, IReadable, IEquatable, IKeyable {} export declare const ReadonlyCell: CellTypeConstructor; /** * Write-only cell variant. * Has .set(), .update(), .push(), .key() * Does NOT have .resolveAsCell()/.get()/.equals()/.send() */ export interface AsWriteonlyCell extends HKT { type: WriteonlyCell; } export interface WriteonlyCell extends BrandedCell, IAnyCell, ICreatable>, IWritable>, IKeyable {} export declare const WriteonlyCell: CellTypeConstructor; // ============================================================================ // Reactive - annotation for reactively-tracked values // ============================================================================ /** * Reactive marks a value as reactively tracked by the pattern runtime. * It is purely an annotation: at the type level it IS `T` (an identity * alias), and the transformers detect the spelling to classify reactive * positions before erasure. There is no runtime wrapper behind it. */ export type Reactive = T; /** @deprecated Use {@link Reactive}. */ export type OpaqueRef = Reactive; // Helper type for OpaqueRef's inner property/array mapping // Handles nullable types by extracting the non-null part for mapping type OpaqueRefInner = [T] extends [ArrayBuffer | ArrayBufferView | URL | Date] ? T : [T] extends [Array] ? Array> : [T] extends [AnyBrandedCell] ? T : [T] extends [object] ? { [K in keyof T]: OpaqueRef } // For nullable types (T | null | undefined), extract and map the non-null part : [NonNullable] extends [never] ? T // Handle nullable branded cells (e.g., (OpaqueRef | undefined) from .find() on proxy arrays) // Use NonNullable instead of T to avoid leaking null/undefined into the // OpaqueCell & OpaqueRefInner intersection, where TypeScript's // intersection simplification would erase them (object & undefined = never). : [NonNullable] extends [AnyBrandedCell] ? NonNullable : [NonNullable] extends [Array] ? Array> : [NonNullable] extends [object] ? { [K in keyof NonNullable]: OpaqueRef[K]> } : T; // ============================================================================ // CellLike and FactoryInput - Utility types for accepting cells // ============================================================================ /** * CellLike is a cell (AnyCell) whose nested values are valid factory inputs. * The top level must be AnyCell, but nested values can be plain or wrapped. * * Note: This is primarily used for type constraints that require a cell. */ type CellWrappedValue = AnyBrandedCell> & { [CELL_LIKE]?: unknown; }; export type CellLike = CellWrappedValue | T; type CellWrappedData = | T | AnyBrandedCell | (T extends Array ? Array> : T extends object ? { [K in keyof T]: FactoryInput } : never); export declare const CELL_LIKE: unique symbol; /** * Helper type to transform Cell to FactoryInput in pattern/lift/handler inputs. * Preserves Stream since Streams are callable interfaces (.send()), not data containers. * * INPUT-POSITION ONLY: stripping is an acceptance tool — used inside * `FactoryInput>` so callers can pass the data shape with or without * cell wrappers. It must NOT be applied to factory result types: result-type * brands are exported capabilities, and transformer-inferred result schemas * derive `asCell`/`asStream` from them (see the boundary principle on * PatternFunction). * * Implementation is non-distributive by default to preserve union types like RenderNode * that intentionally contain AnyBrandedCell as a data variant. However, for optional cell * properties like `title?: Writable` (which expand to `Writable | undefined`), * we extract the cell parts, strip them, and recombine with the non-cell parts. */ export type StripCell = // Handle optional cell properties: "SomeCell | undefined" pattern // Strip the cell part, preserve undefined only if it was present [T] extends [AnyBrandedCell | undefined] ? StripCellInner> | Extract // Non-distributive for everything else (preserves unions like RenderNode) : StripCellInner; type StripCellInner = [T] extends [Stream] ? T // Preserve Stream - it's a callable interface : [T] extends [AnyBrandedCell] ? StripCell : [T] extends [ArrayBuffer | ArrayBufferView | URL | Date] ? T : [T] extends [Array] ? StripCell[] // deno-lint-ignore ban-types : [T] extends [Function] ? T // Preserve function types : [T] extends [object] ? { [K in keyof T]: StripCell } : T; /** * Input accepted when invoking a Common Fabric factory or helper. * * FactoryInput accepts T or any cell wrapping T, recursively at any nesting * level. It also accepts cells whose stored data contains reactive values. * Used in APIs that accept inputs from developers: values can be static, * reactive, wrapped in cells, or cells containing reactive values. * * Special cases for JSX: * - FactoryInput also accepts JSXElement * - FactoryInput also accepts JSXElement (for .map() callbacks returning JSX) */ export type FactoryInput = | T // We have to list them explicitly so Typescript can unwrap them. Doesn't seem // to work if we just say AnyBrandedCell | AnyCell | AnyBrandedCell | OpaqueCell | Cell | Stream | ComparableCell | ReadonlyCell | WriteonlyCell | CellWrappedValue // Special case: When T is VNode or UIRenderable (even with null/undefined), // also accept JSXElement. Use NonNullable to handle VNode | undefined. // Combined into single check to reduce type instantiation overhead. | ([NonNullable] extends [VNode | UIRenderable] ? JSXElement : never) | (T extends Array ? Array> : T extends object ? { [K in keyof T]: FactoryInput } : T); /** * Matches any non-opaque Cell type (Cell, Stream, ComparableCell, etc.) that may be * wrapped in any number of OpaqueRef layers. Excludes OpaqueCell and AnyCell (since OpaqueCell extends AnyCell). */ /** * Recursively unwraps AnyBrandedCell types at any nesting level. * UnwrapCell>> = string * UnwrapCell }>> = { a: AnyBrandedCell } * * Special cases: * - UnwrapCell = any * - UnwrapCell = unknown (preserves unknown) */ export type UnwrapCell = // Preserve any 0 extends (1 & T) ? T // Unwrap AnyBrandedCell : T extends AnyBrandedCell ? UnwrapCell // Otherwise return as-is : T; /** * AnyCellWrapping is used for write operations (.set(), .push(), .update()). It * is a type utility that allows any part of type T to be wrapped in AnyCell<>, * and allow any part of T that is currently wrapped in AnyCell<> to be used * unwrapped. This is designed for use with cell method parameters, allowing * flexibility in how values are passed. The ID and ID_FIELD metadata symbols * allows controlling id generation and can only be passed to write operations. */ export type AnyCellWrapping = // Handle existing AnyBrandedCell<> types, allowing unwrapping T extends AnyBrandedCell ? AnyCellWrapping | AnyBrandedCell> // Handle arrays : T extends Array ? Array> | AnyBrandedCell>> // Handle objects (excluding null) : T extends object ? | { [K in keyof T]: AnyCellWrapping } & { [ID]?: AnyCellWrapping; [ID_FIELD]?: string } | AnyBrandedCell<{ [K in keyof T]: AnyCellWrapping }> // Handle primitives : T | AnyBrandedCell; // Factory types // TODO(seefeld): Subset of internal type, just enough to make it // differentiated. But this isn't part of the public API, so we need to find a // different way to handle this. export interface Pattern { argumentSchema: JSONSchema; resultSchema: JSONSchema; defaultScope?: CellScope; } export interface Module { type: "ref" | "javascript" | "pattern" | "raw" | "isolated" | "passthrough"; defaultScope?: CellScope; } export type toJSON = { toJSON(): unknown; }; export type Handler = Module & { with: (inputs: FactoryInput>) => Stream; }; export type NodeFactory = & ((inputs: FactoryInput) => OpaqueRef) & (Module | Handler | Pattern) & toJSON & { asScope(scope: CellScope): NodeFactory; }; export type PatternFactory = & ((inputs: FactoryInput) => OpaqueRef) & Pattern & toJSON & { asScope(scope: CellScope): PatternFactory; inSpace(space?: string | AnyCell): PatternFactory; }; export type ModuleFactory = & ((inputs: FactoryInput) => OpaqueRef) & Module & toJSON & { asScope(scope: CellScope): ModuleFactory; }; export type HandlerFactory = & ((inputs: FactoryInput>) => Stream) & Handler & toJSON; // JSON types export type JSONValue = | null | boolean | number | string | JSONArray | JSONObject & IDFields; export interface JSONArray extends ArrayLike {} export interface JSONObject extends Record {} // Annotations when writing data that help determine the entity id. They are // removed before sending to storage. export interface IDFields { [ID]?: unknown; [ID_FIELD]?: unknown; } /** * Recursively adds `readonly` to all properties of `T`. * * Mirrors the definition in `@commonfabric/utils/types` but is duplicated here * so that `@commonfabric/api` remains dependency-free. */ type Immutable = T extends ReadonlyArray ? ReadonlyArray> : T extends object ? ({ readonly [P in keyof T]: Immutable }) : T; /** * Deeply-readonly version of `JSONValue`. Used in `JSONSchemaObj` for fields * like `default`, `const`, `enum`, and `examples` whose values must not be * mutated after construction. */ export type ImmutableJSONValue = Immutable; // Valid values for the "type" property of a JSONSchema export type JSONSchemaTypes = | "object" | "array" | "string" | "integer" | "number" | "boolean" | "null" | "undefined" // undefined is a non-standard addition | "unknown"; // unknown is a non-standard addition // We can use a more complex asCell specifier to handle things like // `Cell>` with `{ asCell: ["cell", "cell"] }`. // We can also do an `{ asCell: ["stream"] }` or `{ asCell: ["opaque"] }`. // While this is currently tightly coupled to the CellKind type, we can restrict it // to a subset export type AsCellType = AsCellEntry; // See https://json-schema.org/draft/2020-12/json-schema-core // See https://json-schema.org/draft/2020-12/json-schema-validation // There is a lot of potential validation that is not handled, but this object // is defined to support them, so that generated schemas will still be usable. export type JSONSchema = JSONSchemaObj | boolean; export type JSONSchemaObj = { readonly $id?: string; readonly $ref?: string; readonly $defs?: Readonly>; /** @deprecated Use `$defs` for 2019-09/Draft 8 or later */ readonly definitions?: Readonly>; // Subschema logic readonly allOf?: readonly (JSONSchema)[]; // not validated readonly anyOf?: readonly (JSONSchema)[]; // not always validated readonly oneOf?: readonly (JSONSchema)[]; // not always validated readonly not?: JSONSchema; // Subschema conditionally - none applied readonly if?: JSONSchema; readonly then?: JSONSchema; readonly else?: JSONSchema; readonly dependentSchemas?: Readonly>; // Subschema for array readonly prefixItems?: readonly (JSONSchema)[]; // not always validated readonly items?: JSONSchema; readonly contains?: JSONSchema; // not validated // Subschema for object readonly properties?: Readonly>; readonly patternProperties?: Readonly>; // not validated readonly additionalProperties?: JSONSchema; readonly propertyNames?: JSONSchema; // not validated // Validation for any readonly type?: JSONSchemaTypes | readonly JSONSchemaTypes[]; readonly enum?: readonly ImmutableJSONValue[]; // not validated readonly const?: ImmutableJSONValue; // not validated // Validation for numeric - none applied readonly multipleOf?: number; readonly maximum?: number; readonly exclusiveMaximum?: number; readonly minimum?: number; readonly exclusiveMinimum?: number; // Validation for string - none applied readonly maxLength?: number; readonly minLength?: number; readonly pattern?: string; // Validation for array - none applied readonly maxItems?: number; readonly minItems?: number; readonly uniqueItems?: boolean; readonly maxContains?: number; readonly minContains?: number; // Validation for object readonly maxProperties?: number; // not validated readonly minProperties?: number; // not validated readonly required?: readonly string[]; readonly dependentRequired?: Readonly>; // not validated // Format annotations readonly format?: string; // not validated // Contents - none applied readonly contentEncoding?: string; readonly contentMediaType?: string; readonly contentSchema?: JSONSchema; // Meta-Data readonly title?: string; readonly description?: string; readonly default?: ImmutableJSONValue; readonly readOnly?: boolean; readonly writeOnly?: boolean; readonly examples?: readonly ImmutableJSONValue[]; readonly $schema?: string; readonly $comment?: string; // Common Fabric extensions readonly [ID]?: unknown; readonly [ID_FIELD]?: unknown; readonly scope?: SchemaScope; // Discovery hashtags from the doc comment (lowercased, without the leading // `#`). Populated by the schema generator; mirrors the description text. readonly tags?: readonly string[]; // makes it so that your handler gets a Cell object for that property. So you can call .set()/.update()/.push()/etc on it. readonly asCell?: readonly AsCellType[]; // temporarily used to assign labels like "confidential" readonly ifc?: { readonly confidentiality?: readonly ImmutableJSONValue[]; readonly integrity?: readonly ImmutableJSONValue[]; readonly addIntegrity?: readonly ImmutableJSONValue[]; readonly requiredIntegrity?: readonly ImmutableJSONValue[]; readonly maxConfidentiality?: readonly ImmutableJSONValue[]; readonly ownerPrincipal?: string | { readonly __ctCurrentPrincipal: true }; readonly writeAuthorizedBy?: | readonly string[] | { readonly __ctWriterIdentityOf?: { readonly bundleId?: string; readonly file?: string; readonly path?: readonly string[]; }; }; readonly exactCopyOf?: readonly string[]; readonly projection?: readonly string[]; readonly collection?: readonly string[]; readonly uiContract?: { readonly helper?: "UiAction" | "UiPromptSlot" | "UiDisclosure"; readonly action?: string; readonly surface?: string; readonly role?: string; readonly kind?: string; readonly trustedPattern?: string; readonly requiredEventIntegrity?: readonly string[]; }; }; }; /** * Recursively removes `readonly` from all properties of `T`. * * Copy of `Mutable` from `@commonfabric/utils/types`. These two definitions * should be unified; see that module for the canonical version. */ type Mutable = T extends ReadonlyArray ? Mutable[] : T extends object ? ({ -readonly [P in keyof T]: Mutable }) : T; /** * A deep-mutable variant of `JSONSchemaObj`. Recursively strips `readonly` * from all properties, making the schema safe to build up incrementally. */ export type JSONSchemaObjMutable = Mutable; /** * A `JSONSchemaObjMutable` or a boolean. JSON Schema allows `true` (accept any * value) and `false` (reject all values) as valid schemas. */ export type JSONSchemaMutable = JSONSchemaObjMutable | boolean; export type * from "./cfc.ts"; export { CFC_CANONICAL_ALIAS_NAMES } from "./cfc.ts"; export type TrustedActionWriteWithIntegrity< T, Binding, Action extends string, Pattern extends string, Integrity extends readonly [string, ...string[]], > = Cfc< WriteAuthorizedBy, { uiContract: { helper: "UiAction"; action: Action; trustedPattern: Pattern; requiredEventIntegrity: Integrity; }; } >; export type TrustedActionWrite< T, Binding, Action extends string, Pattern extends string, > = TrustedActionWriteWithIntegrity; export type TrustedActionUiContract< T, Action extends string, Pattern extends string, Integrity extends readonly [string, ...string[]] = [Pattern], > = Cfc< T, { uiContract: { helper: "UiAction"; action: Action; trustedPattern: Pattern; requiredEventIntegrity: Integrity; }; } >; /** * Selects a sub-path within a document, optionally paired with a schema * that describes the value at that path. Used by the storage/sync layer * to track which slices of a document are being observed. */ export type SchemaPathSelector = { path: readonly string[]; schema?: JSONSchema; }; // LLM types matching Vercel AI SDK structure export type BuiltInLLMTextPart = { type: "text"; text: string; }; export type BuiltInLLMImagePart = { type: "image"; image: string | Uint8Array | ArrayBuffer | URL; }; export type BuiltInLLMToolCallPart = { type: "tool-call"; toolCallId: string; toolName: string; input: Record; }; export type BuiltInLLMToolResultPart = { type: "tool-result"; toolCallId: string; toolName: string; output: { type: "text"; value: string } | { type: "json"; value: any }; }; export type BuiltInLLMContentPart = | BuiltInLLMTextPart | BuiltInLLMImagePart | BuiltInLLMToolCallPart | BuiltInLLMToolResultPart; export type BuiltInLLMContent = string | BuiltInLLMContentPart[]; export type BuiltInLLMMessage = { role: "user" | "assistant" | "system" | "tool"; content: BuiltInLLMContent; }; // Image types from UI components export interface ImageData { id: string; name: string; url: string; data: string; timestamp: number; width?: number; height?: number; size: number; type: string; exif?: { // Core metadata dateTime?: string; make?: string; model?: string; orientation?: number; // Location gpsLatitude?: number; gpsLongitude?: number; gpsAltitude?: number; // Camera settings fNumber?: number; exposureTime?: string; iso?: number; focalLength?: number; // Dimensions pixelXDimension?: number; pixelYDimension?: number; // Software software?: string; // Raw EXIF tags raw?: Record; }; } export type BuiltInLLMTool = & { description?: string } & ( | { pattern: Pattern; handler?: never; extraParams?: Record; useResultSchemaForObservation?: boolean; } | { handler: Stream | OpaqueRef; pattern?: never } ); /** * A web source surfaced by a native search/grounding tool (e.g. * `google_search`). Populated on the result state when grounding is requested. */ export interface BuiltInLLMGroundingSource { url?: string; title?: string; snippet?: string; } // Built-in types export interface BuiltInLLMParams { messages?: BuiltInLLMMessage[]; model?: string; system?: string; stop?: string; maxTokens?: number; builtinTools?: boolean; observationMaxConfidentiality?: readonly ImmutableJSONValue[]; /** * Specifies the mode of operation for the LLM. * - `"json"`: Indicates that the LLM should process and return data in JSON format. * This parameter is optional and defaults to undefined, which may result in standard behavior. */ mode?: "json"; /** * Tools that can be called by the LLM during generation. * Each tool has a description, input schema, and handler function that runs client-side. */ tools?: Record; /** * Enable Google Search grounding (shorthand for the `google_search` native * model tool). Source URLs are surfaced on the state's `groundingSources`. */ search?: boolean; /** Raw native model tool ids to request, e.g. `["google_search"]`. */ nativeModelToolIds?: readonly string[]; /** * Context cells to make available to the LLM. * These cells appear in the system prompt with their schemas and current values. */ context?: Record>; /** * When provided, injects a `presentResult` built-in tool that the LLM can call * to present a structured result matching this schema. The result is stored on the * dialog state's `result` field. Can be called multiple times (overwrites previous). */ resultSchema?: JSONSchema; /** * Optional named queue to route async operations through. */ queue?: string; } export interface BuiltInLLMState { pending: boolean; result?: BuiltInLLMContent; partial?: string; error?: unknown; cancelGeneration: Stream; /** Web sources from native search grounding, when `search`/`google_search` was requested. */ groundingSources?: readonly BuiltInLLMGroundingSource[]; } export interface BuiltInLLMGenerateObjectState { pending: boolean; result?: T; messages?: BuiltInLLMMessage[]; partial?: string; error?: unknown; cancelGeneration: Stream; // NOTE: `generateObject` accepts `search`/`nativeModelToolIds` (grounding can // improve the structured result), but does NOT surface `groundingSources` — // its JSON-mode path returns only the object, not the grounded response. Use // `generateText` when you need the source URLs. } export interface BuiltInLLMDialogState { pending: boolean; result?: any; error?: unknown; cancelGeneration: Stream; addMessage: Stream; pinCell: Stream<{ path: string; name: string }>; unpinAllCells: Stream; flattenedTools: Record; pinnedCells: Array<{ path: string; name: string }>; } export type BuiltInGenerateObjectParams = | { model?: string; prompt: BuiltInLLMContent; messages?: never; context?: Record; schema?: JSONSchema; system?: string; cache?: boolean; maxTokens?: number; observationMaxConfidentiality?: readonly ImmutableJSONValue[]; schemaSanitizePromptInjection?: boolean; metadata?: Record; tools?: Record; /** * Enable Google Search grounding (shorthand for the `google_search` * native model tool). Real, current web results inform the answer, and * the source URLs are surfaced on the result state's `groundingSources` * (generateText / llm only — generateObject does not surface them). */ search?: boolean; /** * Raw native model tool ids to request (e.g. `["google_search"]`). * `search: true` is the friendly shorthand for `["google_search"]`. */ nativeModelToolIds?: readonly string[]; queue?: string; } | { model?: string; prompt?: never; messages: BuiltInLLMMessage[]; context?: Record; schema?: JSONSchema; system?: string; cache?: boolean; maxTokens?: number; observationMaxConfidentiality?: readonly ImmutableJSONValue[]; schemaSanitizePromptInjection?: boolean; metadata?: Record; tools?: Record; /** * Enable Google Search grounding (shorthand for the `google_search` * native model tool). Real, current web results inform the answer, and * the source URLs are surfaced on the result state's `groundingSources` * (generateText / llm only — generateObject does not surface them). */ search?: boolean; /** * Raw native model tool ids to request (e.g. `["google_search"]`). * `search: true` is the friendly shorthand for `["google_search"]`. */ nativeModelToolIds?: readonly string[]; queue?: string; }; export type BuiltInGenerateTextParams = | { prompt: BuiltInLLMContent; messages?: never; context?: Record; system?: string; model?: string; maxTokens?: number; tools?: Record; /** * Enable Google Search grounding (shorthand for the `google_search` * native model tool). Real, current web results inform the answer, and * the source URLs are surfaced on the result state's `groundingSources` * (generateText / llm only — generateObject does not surface them). */ search?: boolean; /** * Raw native model tool ids to request (e.g. `["google_search"]`). * `search: true` is the friendly shorthand for `["google_search"]`. */ nativeModelToolIds?: readonly string[]; queue?: string; } | { prompt?: never; messages: BuiltInLLMMessage[]; context?: Record; system?: string; model?: string; maxTokens?: number; tools?: Record; /** * Enable Google Search grounding (shorthand for the `google_search` * native model tool). Real, current web results inform the answer, and * the source URLs are surfaced on the result state's `groundingSources` * (generateText / llm only — generateObject does not surface them). */ search?: boolean; /** * Raw native model tool ids to request (e.g. `["google_search"]`). * `search: true` is the friendly shorthand for `["google_search"]`. */ nativeModelToolIds?: readonly string[]; queue?: string; }; export interface BuiltInGenerateTextState { pending: boolean; result?: string; error?: unknown; partial?: string; requestHash?: string; /** Web sources from native search grounding, when `search`/`google_search` was requested. */ groundingSources?: readonly BuiltInLLMGroundingSource[]; } export interface BuiltInCompileAndRunParams { files: Array<{ name: string; contents: string }>; main: string; input?: T; } export interface BuiltInCompileAndRunState { pending: boolean; result?: T; error?: any; errors?: Array<{ line: number; column: number; message: string; type: string; file?: string; }>; } // Function type definitions // // Boundary principle for factory types: factories ACCEPT the stripped data // shape — `FactoryInput>` means "this data shape, wrapped however // you like" (liberal in what we accept). Factories RETURN exactly what the body // returned: `R` unstripped (faithful in what we produce). Cell/Stream brands in // a result type are exported capabilities, preserved end-to-end — the brand in // the type becomes `asCell`/`asStream` in the generated result schema, which // the runtime rematerializes as a live Cell/Stream for consumers. Stripping a // result type would not just misreport that; transformer-inferred schemas are // derived from these types, so it would silently downgrade live cells to dead // values. (`SELF` and the consumer-facing factory result deliberately use the // same unstripped `R`.) export interface PatternFunction { // Function-only overload: T and R inferred from function ( fn: ( input: OpaqueRef> & { [SELF]: OpaqueRef }, ) => FactoryInput, ): PatternFactory, R>; // Function-only overload: T explicit, R inferred ( fn: ( input: OpaqueRef> & { [SELF]: OpaqueRef }, ) => any, ): PatternFactory, ReturnType>; // Function + schema overload: T explicit, R inferred ( fn: ( input: OpaqueRef> & { [SELF]: OpaqueRef }, ) => any, argumentSchema: JSONSchema, resultSchema?: JSONSchema, ): PatternFactory, ReturnType>; // Function + schema overload: T and R explicit ( fn: ( input: OpaqueRef> & { [SELF]: OpaqueRef }, ) => FactoryInput, argumentSchema: JSONSchema, resultSchema?: JSONSchema, ): PatternFactory, R>; } /** * Result of patternTool() - an LLM tool definition with a pattern and optional pre-filled params. * This is the actual runtime return type, not a cast. */ export interface PatternToolResult> { pattern: Pattern; extraParams: E; useResultSchemaForObservation?: boolean; } export type PatternToolFunction = < T, E extends object = Record, >( // CT-1655: the first argument must be an explicit `pattern(...)`. Passing a // bare callback (and letting the runtime wrap it / a transformer auto-capture // its closure) is no longer supported — wrap it yourself: // `patternTool(pattern(fn), extraParams?)`. pattern: PatternFactory, // Validate that E (after stripping cells) is a subset of T extraParams?: StripCell extends Partial ? FactoryInput : never, ) => PatternToolResult; // Public (schema-light) surface, matching PatternFunction's index.ts shape: the // callback is the only argument and the types come from the callback itself. The // schema-bearing, type-materializing overloads (where the callback's input type // is derived FROM the supplied JSONSchema) live in `commonfabric/schema` // (api/schema.ts) so that schema and type can never contradict each other — the // same split pattern already used for pattern()/handler(). Transformer-emitted // `__cfHelpers.lift(...)` is untyped (`__cfHelpers: any`), so it does not depend // on these overloads; only authored `lift(...)` calls resolve against them. export interface LiftFunction { ( implementation: (input: T) => R, ): ModuleFactory, R>; ( implementation: (input: T) => any, ): ModuleFactory, ReturnType>; any>( implementation: T, ): ModuleFactory[0]>, ReturnType>; } // Helper type to make non-Cell and non-Stream properties readonly in handler state. // Cell/Stream/SqliteDb are passed through whole (they are handle interfaces with // methods — `.get()/.set()`, `.send()`, `.exec()/.query()` — not data containers // to map over). export type HandlerState = T extends Cell ? T : T extends Stream ? T : T extends SqliteDb ? T : T extends Array ? ReadonlyArray> : T extends object ? { readonly [K in keyof T]: HandlerState } : T; export interface HandlerFunction { // With inferred types ( eventSchema: JSONSchema, stateSchema: JSONSchema, handler: (event: E, props: HandlerState) => any, ): HandlerFactory; // Without schemas ( handler: (event: E, props: T) => any, options: { proxy: true }, ): HandlerFactory; ( handler: (event: E, props: HandlerState) => any, ): HandlerFactory; } /** * ActionFunction creates a handler that doesn't use the state parameter. * * This is to handler as computed is to lift: * - User writes: action((e) => count.set(e.data)) * - Transformer rewrites to: handler((e, { count }) => count.set(e.data))({ count }) * * The transformer extracts closures and makes them explicit, just like how * computed(() => expr) becomes a lift-applied computation with closure * extraction. */ export type ActionFunction = { // Overload 1: Zero-parameter callback returns Stream (fn: () => void): Stream; // Overload 2: Parameterized callback returns Stream (fn: (event: T) => void): Stream; }; export type ComputedFunction = (fn: () => T) => OpaqueRef; export type StrFunction = ( strings: TemplateStringsArray, ...values: any[] ) => OpaqueRef; export type IfElseFunction = ( condition: FactoryInput, ifTrue: FactoryInput, ifFalse: FactoryInput, ) => OpaqueRef; export type WhenFunction = ( condition: FactoryInput, value: FactoryInput, ) => OpaqueRef; export type UnlessFunction = ( condition: FactoryInput, fallback: FactoryInput, ) => OpaqueRef; /** @deprecated Use generateText() or generateObject() instead */ export type LLMFunction = ( params: FactoryInput, ) => OpaqueRef; export type LLMDialogFunction = ( params: FactoryInput, ) => OpaqueRef; export type GenerateObjectFunction = ( params: FactoryInput, ) => OpaqueRef>; export type GenerateTextFunction = ( params: FactoryInput, ) => OpaqueRef; export type FetchOptions = { body?: JSONValue; headers?: Record; mutexTimeoutMs?: number; cache?: | "default" | "no-store" | "reload" | "no-cache" | "force-cache" | "only-if-cached"; method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD"; redirect?: "follow" | "error" | "manual"; }; export type FetchDataFunction = ( params: FactoryInput<{ url: string; mode?: "json" | "text" | "dataUrl"; options?: FetchOptions; result?: T; }>, ) => OpaqueRef<{ pending: boolean; result: T; error?: any }>; export type FetchProgramFunction = ( params: FactoryInput<{ url: string }>, ) => OpaqueRef<{ pending: boolean; result: { files: Array<{ name: string; contents: string }>; main: string; } | undefined; error?: any; }>; export type StreamDataFunction = ( params: FactoryInput<{ url: string; options?: FetchOptions; result?: T; }>, ) => OpaqueRef<{ pending: boolean; result: T; error?: any }>; export type CompileAndRunFunction = ( params: FactoryInput>, ) => OpaqueRef>; // --- SQLite builtins (docs/specs/sqlite-builtin) --- declare const __sqliteDb: unique symbol; /** * Database handle. Empty to pattern code; a cell reference to the runtime * via the `toCell` back-pointer. Patterns only ever *forward* it (to sqliteQuery * / sqliteExecute / reactOn), never read it. */ export type SqliteDatabase = { readonly [__sqliteDb]: true }; /** Imperative write on a SqliteDb handle: records a SQLite write onto the * current transaction so it commits atomically with surrounding cell writes * (see docs/specs/sqlite-builtin/plans/sqlitedb-cell-type-exploration.md). */ export interface ISqliteExecutable { exec( sql: string, params?: ReadonlyArray | Record, ): void; } /** Reactive read on a SqliteDb handle: builds a `sqliteQuery` node. `` is * lowered by the transformer to an injected result schema. */ export interface ISqliteQueryable { query>( sql: string, options?: { params?: ReadonlyArray | Record; reactOn?: unknown; /** CFC Phase 3: declared output ceiling (see SqliteQueryParams). */ maxConfidentiality?: ReadonlyArray; /** `"fail"` (default) | `"skip"` when a row exceeds the ceiling. */ onExceed?: "fail" | "skip"; }, ): OpaqueRef<{ pending: boolean; result?: Row[]; error?: any }>; } /** * SqliteDb is a cell variant (kind `"sqlite"`) — a DB handle cell exposing ONLY * the SQLite method surface (`.exec`/`.query`), not the general value-cell * read/write API. In particular it deliberately does **not** extend * `IReadable`: `.get()`/`.sample()` are meaningless on an opaque DB handle * (the handle ref is an internal detail; pattern code reads rows via `.query`), * so omitting them keeps `db.get()` from type-checking. The handle is also not * writable (you can't `.set()` a DB handle). The runtime still reads the raw * handle internally via `getRaw()` to fold writes onto the transaction. */ export interface ISqliteDb extends IAnyCell, ISqliteExecutable, ISqliteQueryable {} export interface SqliteDb extends BrandedCell, ISqliteDb {} /** A map of table name -> one-row JSON Schema (see `table()`). */ export type SqliteTableSchemas = Record; /** Non-default database source. Cell-derived (default) needs no source; on-disk * databases are injected as a pattern input, not selected here. */ export type SqliteDatabaseSource = { vm: OpaqueRef; path: string; }; export type SqliteDatabaseFunction = { ( options?: { tables?: SqliteTableSchemas }, source?: SqliteDatabaseSource, ): OpaqueRef; /** Bind the db (and so its on-disk file) to a scope. The transformer lowers * `const db: PerUser = sqliteDatabase(...)` to `.asScope("user")`; * call it explicitly for the same effect. */ asScope(scope: CellScope): SqliteDatabaseFunction; }; export type SqliteQueryParams = { db: FactoryInput; sql: string; params?: ReadonlyArray | Record; reactOn?: unknown; /** CFC Phase 3: the declared output ceiling — the maximum confidentiality * the RESULT may carry (a consumer contract, not reader clearance). * Placeholder atoms `{__ctCurrentPrincipal: true}` (the acting user) and * `{__ctDbOwner: true}` (the db's owner) resolve at prepare time. The * typed alternative is `MaxConfidentiality` on the Row schema — * declare the ceiling once, not both ways. */ maxConfidentiality?: ReadonlyArray; /** What to do when a row's label exceeds the ceiling: `"fail"` (default — * refuse the whole query) or `"skip"` (drop the offending rows; a declared * existence release, row-returning queries only — never aggregates). */ onExceed?: "fail" | "skip"; }; export type SqliteQueryFunction = >( params: FactoryInput, ) => OpaqueRef<{ pending: boolean; result?: Row[]; error?: any }>; // Writes are the imperative SqliteDb.exec method (see ISqliteExecutable), which // folds a `sqlite` op into the caller's commit (atomic with cell writes). There // is no standalone reactive sqliteExecute builder. /** Column spec for `table()`: a shorthand SQL type string or a column schema. */ export type SqliteColumnSpec = string | JSONSchema; /** A reference to a declared column, handed to a row-label rule as `f.` * (CFC Phase 3; see `@commonfabric/memory/sqlite/row-label`). */ export type SqliteRowFieldRef = { readonly field: string }; /** A per-row CFC label rule: a pure declarative projection over the row's * columns, built from the closed helper set (match/principal/all/whenMatches/ * dbOwner/endorsedBy/…). Validated and serialized at `table()` time; * evaluated identically at the write gate, server commit, and read. */ export type SqliteRowLabelRule = ( f: Record, ) => { confidentiality?: unknown; integrity?: unknown }; export type SqliteTableFunction = ( columns: Record, rule?: SqliteRowLabelRule, ) => JSONSchema; /** * The SQLite helper namespace: one import for the table/label vocabulary — * `const { table, all, principal, match, dbOwner } = cfSqlite`. The row-label * helpers (CFC Phase 3) build the declarative per-row rule passed to * `table(columns, rule)`; each returns a serialized AST node. `any(...)` * (one authored OR-clause) errors at `table()` time until the clause-aware * label profile lands. There is deliberately no bare `when`: the builder's * control-flow `when` lowering matches by name, so the gate is the fused * `whenMatches`. */ export interface CfSqliteHelpers { table: SqliteTableFunction; cfLink: SqliteCfLinkFunction; /** Regex (forced global) over a column ⟹ ordered match list (split+clean). */ match( field: SqliteRowFieldRef, re: RegExp, opts?: { group?: number; min?: number }, ): unknown; /** `did::` per extracted value (protocol-implied normalization). */ principal(protocol: string, of: unknown): unknown; /** Conjunctive clauses — every term an independent requirement. */ all(...terms: unknown[]): unknown; /** ONE authored OR-clause (reserved: errors until OR-clause support). */ any(...terms: unknown[]): unknown; /** Integrity meet (set ∩). Integrity-only. */ intersect(...terms: unknown[]): unknown; /** Include `then` only when the regex tests true against the column. */ whenMatches(field: SqliteRowFieldRef, re: RegExp, then: unknown): unknown; /** The db's owner (fixed, from the db ref — never the acting reader). */ dbOwner(): unknown; endorsedBy(p: unknown): unknown; authoredBy(p: unknown): unknown; /** A literal atom (escape hatch). */ constant(atom: unknown): unknown; } export type SqliteCfLinkFunction = <_T = unknown>() => JSONSchema; export type WishTag = `/${string}` | `#${string}`; export type DID = `did:${string}:${string}`; export type WishParams = { query: WishTag | string; path?: string[]; context?: Record; schema?: JSONSchema; /** * Search scope for hashtag queries: "~" = favorites (home), "." = mentionables (current space), * "profile" = current user's profile elements. * Default (undefined) = favorites only for backward compatibility. */ scope?: (DID | "~" | "." | "profile")[]; /** * When true, skip the suggestion/picker UI pattern (suggestion.tsx). * Multiple candidates are returned as-is without disambiguation. * Use this for programmatic discovery where no user interaction is needed. */ headless?: boolean; }; export type WishState = { // A failed wish should have result of undefined and candidates of [] result: T | undefined; candidates: T[]; error?: any; [UI]?: VNode; }; export type NavigateToFunction = (cell: OpaqueRef) => OpaqueRef; export interface WishFunction { (target: FactoryInput): OpaqueRef>; } export type CreateNodeFactoryFunction = ( moduleSpec: Module, ) => ModuleFactory; // Symbol used to brand Default types so RequireDefaults can detect them. // This is a compile-time-only brand; at runtime Default<> is just T. export declare const DEFAULT_MARKER: unique symbol; type DefaultMarker = { readonly [DEFAULT_MARKER]: T }; // True only for the empty tuple `[]` (a length-0 tuple), false for general // arrays like `string[]` (whose `length` is the wide `number`) and non-empty // tuples. Used by Default<> to special-case `Default<[]>` (see below). type IsEmptyTuple = T extends readonly unknown[] ? number extends T["length"] ? false : T["length"] extends 0 ? true : false : false; // Default type for specifying default values in type definitions. // The DEFAULT_MARKER brand enables RequireDefaults to detect which fields // have runtime-provided defaults and make them non-optional in pattern bodies. // Detection uses conditional type inference (not keyof) for performance. // Nullish-only defaults need a standalone marker because `null & Brand` and // `undefined & Brand` collapse to `never`. // // The brand PAYLOAD carries V — the default VALUE's type — not T (matching // DeepDefault). This is load-bearing for schema generation: the alias body // never otherwise mentions V, so once the checker resolves the alias away // (which it does through every capture/projection/instantiation path), the // payload is the ONLY place the default value survives at the type level. // Schema generation reads it back from expanded types (see the brand-payload // fallback in schema-generator's union formatter); detection everywhere else // is payload-agnostic (`{ readonly [DEFAULT_MARKER]: any }`), so the payload // choice affects nothing but recoverability. Carrying T instead silently // dropped `"default"` from every schema built off a checker type. // // Empty-tuple special case (CT-1640): for `Default<[]>` we keep ONLY the branded // arm and drop the bare `| T` arm. Without this, `Default<[]>` would contribute a // bare `[]` (i.e. `never[]`) member; in the documented `T[] | Default<[]>` shape // that bare member survives `.get()`'s brand-stripping, leaving `T[] | never[]`, // and TypeScript intersects parameter-position element types across the union so // `.includes(x)`/`.indexOf(x)` collapse their parameter to `never`. Dropping the // bare arm lets the sibling `T[]` member supply the value type while the brand is // still present for RequireDefaults<> detection. (The lone `Default<[]>` form — // no sibling array — is not used in practice; the docs always pair it as // `T[] | Default<[]>`.) // // Why ONLY the empty tuple, and not all tuples: a non-empty literal-tuple default // in a union (e.g. `string[] | Default<["seed"]>`) also narrows parameter-position // methods — but to the literal element type, which is a legible error, not the // confusing `never`. More importantly, the empty tuple is the unique tuple that // can never be a legitimate *standalone* field type, so dropping its plain arm is // unconditionally safe. Generalizing to all tuples would collapse a standalone // tuple default like `Default<[string, number], ["a", 0]>` to `never` (the lone // branded arm strips away), breaking that contract. Authors who want an array // field with an empty-ish/seed default and a precise element type should use the // two-arg form `Default` (T = the array, not the tuple). export type Default = IsEmptyTuple extends true ? T & DefaultMarker : | ([T] extends [null | undefined] ? DefaultMarker : T & DefaultMarker) | T; /** * Marker for partial, recursive object defaults in `T | DeepDefault` schema * declarations. It is stripped from pattern body types by RequireDefaults; * schema generation reads `V` from the AST and applies it as object/property * defaults. */ export type DeepDefault = DefaultMarker; /** Detect if T is `any` (used to avoid false positives in brand detection). */ type IsAny = 0 extends 1 & T ? true : false; /** Returns true if T is exactly the `boolean` type (i.e. `true | false`), and false for `true`, `false`, or any other type. */ type IsBoolean = [T] extends [boolean] ? [boolean] extends [T] ? true : false : false; /** * Inner helper for HasDefaultBrand. Distributes over union members of T — * returning `true` for the branded member, `false` for the plain member, * and therefore `boolean` when T is the full `Default` union. * * IMPORTANT: uses `T extends { readonly [DEFAULT_MARKER]: any }` (T is the naked * type parameter on the LEFT of extends) so TypeScript distributes over union * members. The previous form `typeof DEFAULT_MARKER extends keyof T` was * non-distributive — for union T, `keyof T` is the intersection of member keys, * which drops DEFAULT_MARKER (it only appears in the branded member). */ type _HasDefaultBrand = T extends { readonly [DEFAULT_MARKER]: any } ? true : false; /** Returns true if T carries the DEFAULT_MARKER brand (i.e. is `Default`), false otherwise. */ type HasDefaultBrand = IsAny extends true ? false : IsBoolean<_HasDefaultBrand> extends true ? true : _HasDefaultBrand; /** * Detect whether a type T is (or wraps) a Default<>-branded value. * Handles both direct Default and Cell-wrapped Default. */ type IsDefaultField = IsAny extends true ? false : HasDefaultBrand> extends true ? true : NonNullable extends AnyBrandedCell ? IsAny extends true ? false : HasDefaultBrand extends true ? true : false : false; /** Removes the DEFAULT_MARKER branded member from a `Default` union, leaving plain `T`. */ export type StripDefaultBrand = Exclude< T, { readonly [DEFAULT_MARKER]: any } >; type RemoveRedundantUnionMembers = T extends any ? [Exclude] extends [never] ? T : T extends Exclude ? never : T : never; type StripDefaultUnion = RemoveRedundantUnionMembers>; /** * Cell-aware default stripping for pattern input normalization. The public * StripDefaultBrand intentionally stays shallow because it is used by cell * interfaces in variance-sensitive positions. */ type StripDefaultField = IsAny extends true ? T : StripDefaultFieldInner>; type StripDefaultFieldInner = T extends Cell ? Cell> : T extends OpaqueCell ? OpaqueCell> : T extends Stream ? Stream> : T extends ComparableCell ? ComparableCell> : T extends ReadonlyCell ? ReadonlyCell> : T extends WriteonlyCell ? WriteonlyCell> : T extends AnyCell ? AnyCell> : T extends AnyBrandedCell ? AnyBrandedCell, Kind> : T; /** * Maps a type T so that any fields carrying the DEFAULT_MARKER brand become required * (removing `?`) and have their brand stripped, while all other fields are left * unchanged — including preservation of their optional modifier `?`. * * Implementation note: uses an intersection of two mapped types: * 1. A homomorphic map (so TypeScript can infer `T` from the result) that strips * Default brands and preserves the original optional modifier for every key. * 2. A `-?` refinement that makes only the Default-branded keys required. * TypeScript infers `T` from the homomorphic first part; the second part is then * evaluated with the resolved `T` to enforce requiredness on Default fields. */ export type RequireDefaults = // Homomorphic: strip Default brands, preserve `?` for every key (TypeScript can infer T from this) // Use `true extends IsDefaultField` (reversed) rather than `IsDefaultField extends true` // because IsDefaultField can return `boolean` (= `true | false`) when T[K] is a union like // `Default | undefined`. In a non-distributive conditional context, `boolean extends true` // is `false`, but `true extends boolean` is `true` — correctly triggering the true branch. & { [K in keyof T]: true extends IsDefaultField ? StripDefaultField : T[K]; } // Refinement: remove `?` from keys that carry the Default brand. // Use Exclude to strip the `| undefined` that TypeScript // adds for optional fields (T[K] of `a?: X` includes `X | undefined`). // Without this, the required field's value type would still include // `| undefined`, which propagates through OpaqueRef and makes the field // possibly-undefined in the pattern body despite being required. & { [K in keyof T as true extends IsDefaultField ? K : never]-?: StripDefaultField>; }; // Internal-only way to instantiate internal modules export type ByRefFunction = (ref: string) => ModuleFactory; // Internal-only helper to create VDOM nodes export type HFunction = { // Overload for string element names - returns VNode ( name: string, props: { [key: string]: any } | null, ...children: RenderNode[] ): VNode; // Overload for function components - returns whatever the component returns ( name: (props: any) => R, props: { [key: string]: any } | null, ...children: RenderNode[] ): R; // Union overload for when type is not narrowed (used by jsx-runtime) ( name: string | ((props: any) => JSXElement), props: { [key: string]: any } | null, ...children: RenderNode[] ): JSXElement; fragment({ children }: { children: RenderNode[] }): VNode; }; // No-op alternative to `as const as JSONSchema` export type SchemaFunction = (schema: T) => T; // toSchema is a compile-time transformer that converts TypeScript types to JSONSchema // The actual implementation is done by the TypeScript transformer export type ToSchemaFunction = (options?: Partial) => JSONSchema; /** Internal compiler-emitted helper for top-level data materialization. */ export type CfDataFunction = (value: T) => T; // Pattern environment types export interface PatternEnvironment { readonly apiUrl: URL; } export type GetPatternEnvironmentFunction = () => PatternEnvironment; export type NonPrivateRandomFunction = () => number; export type SafeDateNowFunction = () => number; export type ToCompactDebugStringFunction = ( value: unknown, maxLength?: number, ) => string; export type ToIndentedDebugStringFunction = (value: unknown) => string; /** * Compare two cells or values for equality after resolving, i.e. after * following all links in case we have cells pointing to other cells. * This is a standalone export of the equals function from Cell/Writable. */ export type EqualsFunction = ( a: AnyCell | object | undefined, b: AnyCell | object | undefined, ) => boolean; /** * Multi-user pattern test descriptor (`cf test`). Export it as the test * file's default export to run each participant pattern in its own isolated * runtime (own identity) against one shared space. The optional `setup` * pattern instantiates shared state once; each participant pattern receives * its result as the `setup` input. Participants coordinate through * `{ label: "name" }` / `{ await: "name" }` entries in their `tests` arrays. * Use `{ pattern, user: "other" }` to run a second session of an existing * user's identity. */ export interface MultiUserTestDescriptor { setup?: (...args: never[]) => unknown; participants: Record< string, | ((...args: never[]) => unknown) | { pattern: (...args: never[]) => unknown; user?: string } >; } // Re-export all function types as values for destructuring imports // These will be implemented by the factory export declare const pattern: PatternFunction; export declare const patternTool: PatternToolFunction; export declare const lift: LiftFunction; export declare const handler: HandlerFunction; export declare const action: ActionFunction; export declare const computed: ComputedFunction; export declare const str: StrFunction; export declare const ifElse: IfElseFunction; export declare const when: WhenFunction; export declare const unless: UnlessFunction; export declare const uiVariant: UIVariantFunction; /** @deprecated Use generateText() or generateObject() instead */ export declare const llm: LLMFunction; export declare const llmDialog: LLMDialogFunction; export declare const generateObject: GenerateObjectFunction; export declare const generateText: GenerateTextFunction; export declare const fetchData: FetchDataFunction; export declare const fetchProgram: FetchProgramFunction; export declare const streamData: StreamDataFunction; export declare const compileAndRun: CompileAndRunFunction; export declare const sqliteDatabase: SqliteDatabaseFunction; export declare const sqliteQuery: SqliteQueryFunction; export declare const table: SqliteTableFunction; export declare const cfLink: SqliteCfLinkFunction; export declare const cfSqlite: CfSqliteHelpers; export declare const navigateTo: NavigateToFunction; export declare const wish: WishFunction; /** * Tag a multi-user test descriptor for `cf test` (identity at runtime; a * call expression keeps the descriptor's pattern factories out of the * plain-data hardening that module-level data literals receive). */ export declare const multiUserTest: ( descriptor: T, ) => T; export declare const createNodeFactory: CreateNodeFactoryFunction; /** @deprecated Use Cell.of(defaultValue?) instead */ export declare const cell: CellTypeConstructor["of"]; export declare const equals: EqualsFunction; export declare const byRef: ByRefFunction; export declare const getPatternEnvironment: GetPatternEnvironmentFunction; export declare const nonPrivateRandom: NonPrivateRandomFunction; export declare const safeDateNow: SafeDateNowFunction; export declare const toCompactDebugString: ToCompactDebugStringFunction; export declare const toIndentedDebugString: ToIndentedDebugStringFunction; export interface UiActionProps { readonly as?: string; readonly action: string; readonly children?: RenderNode; } export interface UiPromptSlotProps { readonly as?: string; readonly surface: string; readonly role: string; readonly children?: RenderNode; } export interface UiDisclosureProps { readonly as?: string; readonly kind: string; readonly children?: RenderNode; } export declare function UiAction(props: UiActionProps): JSXElement; export declare function UiPromptSlot(props: UiPromptSlotProps): JSXElement; export declare function UiDisclosure(props: UiDisclosureProps): JSXElement; /** * Get the entity ID from a cell or value, or undefined if it has none. The * concrete reference form is dispatched on the "modern cell representation" * flag: a `{ "/": "id-string" }` object with the flag off, a `FabricHash` with * it on. Useful for extracting IDs from newly created pieces for linking. */ export type GetEntityIdFunction = ( value: any, ) => { "/": string } | FabricHash | undefined; export declare const getEntityId: GetEntityIdFunction; /** * Convert an entity-id reference — as produced by {@link getEntityId} or a * cell's `entityId` — to its tagged-hash string, in whichever form the active * cell representation uses (a `{ "/": "id-string" }` object or a `FabricHash`). */ export type EntityRefToStringFunction = ( value: { "/": string } | FabricHash, ) => string; export declare const entityRefToString: EntityRefToStringFunction; export declare const schema: SchemaFunction; export declare const toSchema: ToSchemaFunction; export declare const __cf_data: CfDataFunction; export declare const __cfHelpers: any; export declare namespace __cfHelpers { export type JSONSchema = JSONSchemaObj | boolean; } /** * Dynamic properties. Can either be string type (static) or a Mustache * variable (dynamic). */ export type Props = { [key: string]: | string | number | boolean | object | Array | null | undefined | Cell | Stream; }; /** A child in a view can be one of a few things */ export type RenderNode = | InnerRenderNode | JSXElement | AnyBrandedCell< InnerRenderNode | UIRenderable | JSXElement | null | undefined > | Array; type InnerRenderNode = | VNode | string | number | boolean | undefined | null; /** An object that can be rendered via its [UI] property */ export type UIRenderable = { [UI]: VNode; }; /** * JSX element type - the result of a JSX expression. * Can be a VNode, or a cell containing something with a [UI] property. */ export type JSXElement = | VNode | AnyBrandedCell | OpaqueRef; /** A "virtual view node", e.g. a virtual DOM element */ export type VNode = { type: "vnode"; name: string; props: Props | undefined; children?: RenderNode | undefined; [UI]?: VNode; }; /** * Filesystem projection for a pattern result. Used with the [FS] symbol. * * - `type: "text/markdown"` — render as `index.md` with YAML frontmatter + * markdown body. Primitive frontmatter fields go into YAML; complex values * (arrays of entities, nested objects) become sibling directories. * - `type: "application/json"` — render as `index.json` with `content`. * - Plain object (no `type` field) — shorthand: the object itself becomes the * content of `index.json`. */ export type FsProjection = | { type: "text/markdown"; frontmatter?: Record; content: string; } | { type: "application/json"; content: Record; } | { type?: undefined; [key: string]: unknown };