@datafn/client 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/events/filter.ts","../src/events/bus.ts","../src/errors.ts","../src/tables/table.ts","../src/tables/registry.ts","../src/remote/unwrap.ts","../src/offline/query.ts","../src/plugins/run-hooks.ts","../src/query.ts","../src/offline/mutate.ts","../src/mutate.ts","../src/transact.ts","../src/signals/querySignal.ts","../src/sync/apply.ts","../src/sync.ts","../src/adapters/memoryStorage.ts","../src/adapters/indexedDbStorage.ts"],"sourcesContent":["/**\n * DataFn client factory\n */\n\nimport type { DatafnSchema, DatafnPlugin } from \"@datafn/core\";\nimport { validateSchema } from \"@datafn/core\";\nimport { EventBus, type EventHandler } from \"./events/bus.js\";\nimport type { EventFilter } from \"./events/filter.js\";\nimport { createClientError } from \"./errors.js\";\nimport { TableRegistry } from \"./tables/registry.js\";\nimport type { DatafnTable } from \"./tables/table.js\";\nimport { executeQuery } from \"./query.js\";\nimport { executeMutation } from \"./mutate.js\";\nimport { executeTransact } from \"./transact.js\";\nimport { SignalRegistry } from \"./signals/querySignal.js\";\nimport { createSyncFacade, type SyncFacade } from \"./sync.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\n\nexport interface DatafnRemoteAdapter {\n query(q: unknown): Promise<unknown>;\n mutation(m: unknown): Promise<unknown>;\n transact(t: unknown): Promise<unknown>;\n seed(payload: unknown): Promise<unknown>;\n clone(payload: unknown): Promise<unknown>;\n pull(payload: unknown): Promise<unknown>;\n push(payload: unknown): Promise<unknown>;\n}\n\nexport interface DatafnClientConfig {\n schema: DatafnSchema;\n remote: DatafnRemoteAdapter;\n /**\n * Optional plugins for client-side hook execution\n */\n plugins?: DatafnPlugin[];\n /**\n * Stable client/device identifier used for idempotency and offline change logs.\n * Required when `storage` is provided.\n */\n clientId?: string;\n /**\n * Local persistence adapter. When provided, sync results are applied to local storage.\n */\n storage?: DatafnStorageAdapter;\n getTimestamp?: () => number; // For testing with fake clock\n}\n\nexport interface DatafnClient {\n table<TRecord = unknown>(name: string): DatafnTable<TRecord>;\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(mutation: unknown | unknown[]): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n sync: SyncFacade;\n}\n\n/**\n * Create a DataFn client\n */\nexport function createDatafnClient(config: DatafnClientConfig): DatafnClient {\n // Validate schema at client creation (CLIENT-API-001)\n const validationResult = validateSchema(config.schema);\n if (!validationResult.ok) {\n createClientError(\n validationResult.error.code,\n validationResult.error.message,\n validationResult.error.details as {\n path: string;\n [key: string]: unknown;\n },\n );\n }\n\n const schema = validationResult.result;\n const eventBus = new EventBus();\n const getTimestamp = config.getTimestamp || (() => Date.now());\n\n // Reserved keys that should not trigger table lookup (CLIENT-REG-002)\n const RESERVED_KEYS = new Set([\"then\", \"toJSON\", \"inspect\"]);\n\n // Create the client object first (will add table() method after registry is created)\n const client: DatafnClient = {\n table: null as any, // Will be set below\n\n /**\n * Execute a query (CLIENT-QUERY-001, CLIENT-OFFLINE-QUERY-001)\n */\n async query(q: unknown | unknown[]) {\n return executeQuery(\n config.remote,\n q,\n config.storage,\n config.plugins || [],\n schema,\n );\n },\n\n /**\n * Sync facade (CLIENT-SYNC-001, CLIENT-SYNC-APPLY-001)\n */\n sync: createSyncFacade(config.remote, config.storage),\n\n /**\n * Execute a transaction (CLIENT-TX-001)\n */\n async transact(payload: unknown) {\n return executeTransact(config.remote, payload);\n },\n\n /**\n * Execute a mutation (CLIENT-MUT-001, CLIENT-OFFLINE-MUT-001)\n */\n async mutate(mutation: unknown | unknown[]) {\n return executeMutation(\n config.remote,\n eventBus,\n getTimestamp,\n mutation,\n config.storage,\n config.plugins || [],\n schema,\n );\n },\n\n /**\n * Subscribe to events\n */\n subscribe(handler: EventHandler, filter?: EventFilter) {\n return eventBus.subscribe(handler, filter);\n },\n };\n\n // Create signal registry (CLIENT-SIGNAL-001)\n const signalRegistry = new SignalRegistry(client, eventBus);\n\n // Create table registry with client and signal registry (CLIENT-REG-001)\n const registry = new TableRegistry(schema, client, signalRegistry);\n\n // Set table method now that registry exists\n client.table = (name: string) => registry.getTable(name);\n\n // Wrap client in Proxy for table property access (CLIENT-REG-001, CLIENT-REG-002)\n return new Proxy(client, {\n get(target, prop) {\n // Handle reserved keys - return undefined without throwing\n if (typeof prop === \"string\" && RESERVED_KEYS.has(prop)) {\n return undefined;\n }\n\n // If property exists on target, return it\n if (prop in target) {\n return target[prop as keyof typeof target];\n }\n\n // Check if it's a table name\n if (typeof prop === \"string\") {\n return registry.getTable(prop);\n }\n\n return undefined;\n },\n });\n}\n","/**\n * Event filtering logic\n */\n\nimport type { DatafnEvent } from \"@datafn/core\";\n\nexport interface EventFilter {\n type?: string | string[];\n resource?: string | string[];\n ids?: string | string[];\n mutationId?: string | string[];\n action?: string | string[]; // CLIENT-FILTER-001\n fields?: string | string[]; // CLIENT-FILTER-001\n contextKeys?: string[]; // CLIENT-FILTER-001\n}\n\n/**\n * Check if an event matches the filter\n */\nexport function matchesFilter(\n event: DatafnEvent,\n filter?: EventFilter,\n): boolean {\n if (!filter) return true;\n\n // Match type\n if (filter.type !== undefined) {\n if (Array.isArray(filter.type)) {\n if (!filter.type.includes(event.type)) return false;\n } else {\n if (event.type !== filter.type) return false;\n }\n }\n\n // Match resource\n if (filter.resource !== undefined && event.resource) {\n if (Array.isArray(filter.resource)) {\n if (!filter.resource.includes(event.resource)) return false;\n } else {\n if (event.resource !== filter.resource) return false;\n }\n }\n\n // Match ids (any of the event ids must match)\n if (filter.ids !== undefined && event.ids) {\n const filterIds = Array.isArray(filter.ids) ? filter.ids : [filter.ids];\n const eventIds = Array.isArray(event.ids) ? event.ids : [event.ids];\n const hasMatch = eventIds.some((id) => filterIds.includes(id));\n if (!hasMatch) return false;\n }\n\n // Match mutationId\n if (filter.mutationId !== undefined && event.mutationId) {\n if (Array.isArray(filter.mutationId)) {\n if (!filter.mutationId.includes(event.mutationId)) return false;\n } else {\n if (event.mutationId !== filter.mutationId) return false;\n }\n }\n\n // Match action (CLIENT-FILTER-001)\n if (filter.action !== undefined && event.action) {\n if (Array.isArray(filter.action)) {\n if (!filter.action.includes(event.action)) return false;\n } else {\n if (event.action !== filter.action) return false;\n }\n }\n\n // Match fields - non-empty intersection (CLIENT-FILTER-001)\n if (filter.fields !== undefined && event.fields) {\n const filterFields = Array.isArray(filter.fields)\n ? filter.fields\n : [filter.fields];\n const eventFields = Array.isArray(event.fields)\n ? event.fields\n : [event.fields];\n\n // Check for non-empty intersection\n const hasIntersection = filterFields.some((f) => eventFields.includes(f));\n if (!hasIntersection) return false;\n }\n\n // Match contextKeys - all must exist (CLIENT-FILTER-001)\n if (filter.contextKeys !== undefined && filter.contextKeys.length > 0) {\n if (!event.context || typeof event.context !== \"object\") {\n return false;\n }\n\n const ctx = event.context as Record<string, unknown>;\n const allExist = filter.contextKeys.every((key) => key in ctx);\n if (!allExist) return false;\n }\n\n return true;\n}\n","/**\n * In-process event bus\n */\n\nimport type { DatafnEvent } from \"@datafn/core\";\nimport { matchesFilter, type EventFilter } from \"./filter.js\";\n\nexport type EventHandler = (event: DatafnEvent) => void;\n\ninterface Subscription {\n id: number;\n handler: EventHandler;\n filter?: EventFilter;\n}\n\n/**\n * Simple in-process event bus\n */\nexport class EventBus {\n private subscriptions: Subscription[] = [];\n private nextId = 1;\n\n /**\n * Subscribe to events with optional filtering\n */\n subscribe(handler: EventHandler, filter?: EventFilter): () => void {\n const subscription: Subscription = {\n id: this.nextId++,\n handler,\n filter,\n };\n\n this.subscriptions.push(subscription);\n\n // Return unsubscribe function\n return () => {\n this.subscriptions = this.subscriptions.filter(\n (s) => s.id !== subscription.id\n );\n };\n }\n\n /**\n * Emit an event to all matching subscribers\n */\n emit(event: DatafnEvent): void {\n for (const subscription of this.subscriptions) {\n if (matchesFilter(event, subscription.filter)) {\n subscription.handler(event);\n }\n }\n }\n}\n","/**\n * DataFn Client Error Types\n */\n\nimport type { DatafnErrorCode } from \"@datafn/core\";\n\nexport type DatafnClientError = {\n code: DatafnErrorCode | \"TRANSPORT_ERROR\";\n message: string;\n details: { path: string; [key: string]: unknown };\n};\n\n/**\n * Create a DataFnClientError and throw it\n */\nexport function createClientError(\n code: DatafnClientError[\"code\"],\n message: string,\n details: { path: string; [key: string]: unknown },\n): never {\n const error: DatafnClientError = {\n code,\n message,\n details,\n };\n throw error;\n}\n/**\n * Check if an error is a transport/retriable error.\n * Returns true for network errors, timeouts, or explicit TRANSPORT_ERROR code.\n * Returns false for logic errors (validation, auth, missing resource, etc).\n */\nexport function isTransportError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n\n const err = error as any;\n\n // Explicit DataFn code\n if (err.code === \"TRANSPORT_ERROR\") return true;\n\n // Network/Fetch errors match common patterns\n // 1. fetch() throws TypeError on network failure\n // 2. AbortError on timeout\n if (err.name === \"TypeError\" && err.message.includes(\"fetch\")) return true;\n if (err.name === \"AbortError\") return true; // Timeout\n\n // Check failure status if available (e.g. 503, 504)\n // Note: DataFnRemoteAdapter usually unwraps to DataFnError, so status might not be here directly\n // unless wrapped.\n\n return false;\n}\n","/**\n * DataFn Table Handle\n *\n * Represents a table/resource from the schema with methods for query, mutation, signals, and subscriptions.\n */\n\nimport type { DatafnSignal } from \"@datafn/core\";\nimport type { EventHandler } from \"../events/bus.js\";\nimport type { EventFilter } from \"../events/filter.js\";\nimport type { SignalRegistry } from \"../signals/querySignal.js\";\n\nexport interface DatafnTable<TRecord = unknown> {\n name: string;\n version: number;\n\n query(q: unknown): Promise<unknown>;\n mutate(m: unknown): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n signal(q: unknown): DatafnSignal<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n}\n\n// Forward declaration for client interface\ninterface ClientWithQuery {\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(m: unknown | unknown[]): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n}\n\n/**\n * Create a table handle (internal factory)\n */\nexport function createTable(\n name: string,\n version: number,\n client: ClientWithQuery,\n signalRegistry: SignalRegistry\n): DatafnTable {\n return {\n name,\n version,\n\n /**\n * Execute a query with resource/version merged (CLIENT-QUERY-001)\n */\n async query(q: unknown): Promise<unknown> {\n // Merge query fragment with table resource/version\n const fragment = (typeof q === \"object\" && q !== null ? q : {}) as Record<\n string,\n unknown\n >;\n\n // Remove resource/version from fragment if present (table is authoritative)\n const { resource: _r, version: _v, ...rest } = fragment;\n\n // Build full query\n const fullQuery = {\n resource: name,\n version,\n ...rest,\n };\n\n // Delegate to client.query and return single result\n return client.query(fullQuery);\n },\n\n /**\n * Execute a mutation with resource/version merged (CLIENT-MUT-001)\n */\n async mutate(m: unknown): Promise<unknown> {\n // Merge mutation fragment with table resource/version\n const fragment = (typeof m === \"object\" && m !== null ? m : {}) as Record<\n string,\n unknown\n >;\n\n // Remove resource/version from fragment if present (table is authoritative)\n const { resource: _r, version: _v, ...rest } = fragment;\n\n // Build full mutation\n const fullMutation = {\n resource: name,\n version,\n ...rest,\n };\n\n // Delegate to client.mutate and return single result\n return client.mutate(fullMutation);\n },\n\n /**\n * Execute a transaction (CLIENT-TX-001)\n */\n async transact(payload: unknown): Promise<unknown> {\n // Delegate directly to client.transact without modification\n return client.transact(payload);\n },\n\n /**\n * Create reactive query signal (CLIENT-SIGNAL-001)\n */\n signal(q: unknown): DatafnSignal<unknown> {\n // Merge query fragment with table resource/version\n const fragment = (typeof q === \"object\" && q !== null ? q : {}) as Record<\n string,\n unknown\n >;\n\n // Remove resource/version from fragment if present (table is authoritative)\n const { resource: _r, version: _v, ...rest } = fragment;\n\n // Build full query\n const fullQuery = {\n resource: name,\n version,\n ...rest,\n };\n\n // Get or create signal from registry (ensures caching by dfqlKey)\n return signalRegistry.getSignal(fullQuery);\n },\n\n /**\n * Subscribe to events for this table's resource (CLIENT-SUB-001)\n */\n subscribe(handler: EventHandler, filter?: EventFilter): () => void {\n // Inject resource filter (table is authoritative)\n const tableFilter: EventFilter = {\n ...filter,\n resource: name, // Always use table's resource, ignore user-provided\n };\n\n return client.subscribe(handler, tableFilter);\n },\n };\n}\n","/**\n * Table Registry\n *\n * Manages table handles with object identity caching.\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport { createClientError } from \"../errors.js\";\nimport { createTable, type DatafnTable } from \"./table.js\";\nimport type { SignalRegistry } from \"../signals/querySignal.js\";\n\n// Forward declaration for client interface\ninterface ClientWithQuery {\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(m: unknown | unknown[]): Promise<unknown>;\n subscribe(handler: any, filter?: any): () => void;\n}\n\nexport class TableRegistry {\n private schema: DatafnSchema;\n private tables: Map<string, DatafnTable>;\n private client: ClientWithQuery;\n private signalRegistry: SignalRegistry;\n\n constructor(\n schema: DatafnSchema,\n client: ClientWithQuery,\n signalRegistry: SignalRegistry\n ) {\n this.schema = schema;\n this.tables = new Map();\n this.client = client;\n this.signalRegistry = signalRegistry;\n }\n\n /**\n * Get a table handle by name.\n * Caches table instances for object identity.\n * Throws DFQL_UNKNOWN_RESOURCE for unknown tables.\n */\n getTable(name: string): DatafnTable {\n // Check cache first\n const cached = this.tables.get(name);\n if (cached) {\n return cached;\n }\n\n // Find resource in schema\n const resource = this.schema.resources.find((r) => r.name === name);\n if (!resource) {\n createClientError(\"DFQL_UNKNOWN_RESOURCE\", `Unknown resource: ${name}`, {\n path: \"resource\",\n resource: name,\n });\n }\n\n // Create and cache table\n const table = createTable(\n resource.name,\n resource.version,\n this.client,\n this.signalRegistry\n );\n this.tables.set(name, table);\n return table;\n }\n\n /**\n * Get all declared table names from schema\n */\n getTableNames(): string[] {\n return this.schema.resources.map((r) => r.name);\n }\n}\n","/**\n * Remote Response Unwrapping Utilities\n *\n * Handles both wrapped (DatafnEnvelope) and unwrapped server responses.\n */\n\nimport { createClientError } from \"../errors.js\";\n\n/**\n * Unwrap a remote response that may be wrapped in DatafnEnvelope or unwrapped.\n *\n * - If wrapped success `{ ok: true, result }`, return `result`\n * - If wrapped error `{ ok: false, error }`, throw DatafnClientError\n * - If unwrapped query result `{ data, nextCursor }`, return as-is\n * - If unwrapped aggregate result `{ groups, nextCursor }`, return as-is\n * - Otherwise throw TRANSPORT_ERROR\n */\nexport function unwrapRemoteSuccess<T>(response: unknown): T {\n if (typeof response !== \"object\" || response === null) {\n createClientError(\n \"TRANSPORT_ERROR\",\n \"Transport error: unexpected response shape\",\n { path: \"$\" }\n );\n }\n\n const resp = response as Record<string, unknown>;\n\n // Check for wrapped envelope\n if (\"ok\" in resp) {\n if (resp.ok === true && \"result\" in resp) {\n // Wrapped success\n return resp.result as T;\n } else if (resp.ok === false && \"error\" in resp) {\n // Wrapped error\n const error = resp.error as {\n code?: string;\n message?: string;\n details?: { path?: string; [key: string]: unknown };\n };\n\n createClientError(\n (error.code as any) || \"INTERNAL\",\n error.message || \"Unknown error\",\n (error.details as any) || { path: \"$\" }\n );\n }\n }\n\n // Check for unwrapped query result\n if (\"data\" in resp && \"nextCursor\" in resp) {\n return response as T;\n }\n\n // Check for unwrapped aggregate result\n if (\"groups\" in resp && \"nextCursor\" in resp) {\n return response as T;\n }\n\n // Unknown shape\n createClientError(\n \"TRANSPORT_ERROR\",\n \"Transport error: unexpected response shape\",\n { path: \"$\" }\n );\n}\n","/**\n * Offline Query Execution\n *\n * Execute queries locally against storage adapter for tables in 'ready' hydration state.\n * Supports: filters (operators), sort, pagination, selection.\n */\n\nimport type { DatafnStorageAdapter } from \"../storage.js\";\n\n/**\n * Query result shape matching DFQL protocol\n */\nexport type QueryResult = {\n data: Array<Record<string, unknown>>;\n nextCursor: null | string;\n};\n\n/**\n * Execute a query locally against storage.\n *\n * Implements robust DFQL subset for local-first apps.\n */\nexport async function executeLocalQuery(\n storage: DatafnStorageAdapter,\n query: Record<string, unknown>,\n): Promise<QueryResult> {\n const resource = query.resource as string;\n const select = (query.select as string[]) || [];\n const filters = (query.filters as Record<string, unknown>) || {};\n const sort =\n (query.sort as Array<{ field: string; dir: \"asc\" | \"desc\" }>) || [];\n const limit = typeof query.limit === \"number\" ? query.limit : undefined;\n const offset = typeof query.offset === \"number\" ? query.offset : 0;\n\n // 1. Fetch all records\n // Adapters ensure deterministic id sorting by default\n let records = await storage.listRecords(resource);\n\n // 2. Apply Filters\n if (Object.keys(filters).length > 0) {\n records = records.filter((record) => matchesFilters(record, filters));\n }\n\n // 3. Apply Sort\n if (sort.length > 0) {\n records.sort(createComparator(sort));\n }\n\n // 4. Pagination\n if (offset > 0) {\n records = records.slice(offset);\n }\n\n if (limit !== undefined) {\n records = records.slice(0, limit);\n }\n\n // 5. Selection\n const data = records.map((record) => projectFields(record, select));\n\n return {\n data,\n nextCursor: null, // Local cursor logic omitted for MVP (id-based or offset based)\n };\n}\n\n/**\n * Check if a record matches filters\n */\nfunction matchesFilters(\n record: Record<string, unknown>,\n filters: Record<string, unknown>,\n): boolean {\n for (const [key, filterValue] of Object.entries(filters)) {\n const recordValue = getDotPath(record, key);\n\n // Operator Logic\n if (typeof filterValue === \"object\" && filterValue !== null) {\n if (\n !evaluateOperators(recordValue, filterValue as Record<string, unknown>)\n ) {\n return false;\n }\n } else {\n // Implicit Equality\n if (recordValue !== filterValue) {\n return false;\n }\n }\n }\n return true;\n}\n\n/**\n * Evaluate DFQL operators\n */\nfunction evaluateOperators(\n value: unknown,\n operators: Record<string, unknown>,\n): boolean {\n for (const [op, target] of Object.entries(operators)) {\n switch (op) {\n case \"$eq\":\n case \"eq\":\n if (value !== target) return false;\n break;\n case \"$neq\":\n case \"neq\":\n if (value === target) return false;\n break;\n case \"$in\":\n case \"in\":\n if (Array.isArray(target) && !target.includes(value)) return false;\n break;\n case \"$gt\":\n case \"gt\":\n if (!((value as any) > (target as any))) return false;\n break;\n case \"$lt\":\n case \"lt\":\n if (!((value as any) < (target as any))) return false;\n break;\n case \"$gte\":\n case \"gte\":\n if (!((value as any) >= (target as any))) return false;\n break;\n case \"$lte\":\n case \"lte\":\n if (!((value as any) <= (target as any))) return false;\n break;\n case \"$contains\":\n case \"contains\":\n if (typeof value === \"string\" && typeof target === \"string\") {\n if (!value.includes(target)) return false;\n } else if (Array.isArray(value)) {\n if (!value.includes(target)) return false;\n } else {\n return false;\n }\n break;\n }\n }\n return true;\n}\n\n/**\n * Create a comparator function for multi-field sorting\n */\nfunction createComparator(\n sortRules: Array<{ field: string; dir: \"asc\" | \"desc\" }>,\n) {\n return (a: Record<string, unknown>, b: Record<string, unknown>) => {\n for (const rule of sortRules) {\n const valA = getDotPath(a, rule.field);\n const valB = getDotPath(b, rule.field);\n\n if (valA === valB) continue;\n\n const comparison = valA < valB ? -1 : 1;\n return rule.dir === \"asc\" ? comparison : -comparison;\n }\n // Deterministic tie-breaker: id\n const idA = a.id as string;\n const idB = b.id as string;\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n };\n}\n\n/**\n * Get value from object by dot path\n */\nfunction getDotPath(obj: any, path: string): any {\n return path.split(\".\").reduce((curr, part) => curr?.[part], obj);\n}\n\n/**\n * Project selected fields\n */\nfunction projectFields(\n record: Record<string, unknown>,\n select: string[],\n): Record<string, unknown> {\n if (!select || select.length === 0) {\n return { ...record }; // Shallow copy\n }\n\n const projected: Record<string, unknown> = { id: record.id };\n for (const field of select) {\n // Handle simple top-level fields for MVP\n // Nested projection would require recursive logic\n if (field in record) {\n projected[field] = record[field];\n }\n }\n return projected;\n}\n","/**\n * Plugin hook runner for client-side plugins\n * Implements CLIENT-PLUG-001: registration order, runsOn enforcement, fail semantics\n */\n\nimport type {\n DatafnPlugin,\n DatafnHookContext,\n DatafnSchema,\n} from \"@datafn/core\";\n\n/**\n * Filter plugins to only those that run on client\n */\nexport function getClientPlugins(plugins: DatafnPlugin[]): DatafnPlugin[] {\n return plugins.filter((p) => p.runsOn && p.runsOn.includes(\"client\"));\n}\n\n/**\n * Run beforeQuery hooks (fail-closed)\n * Throws deterministic error if any hook fails\n */\nexport async function runBeforeQuery(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n query: unknown,\n): Promise<unknown> {\n let transformed = query;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.beforeQuery) {\n try {\n const result = await plugin.beforeQuery(ctx, transformed);\n if (result !== undefined) {\n transformed = result;\n }\n } catch (error: any) {\n // Fail-closed: throw with deterministic path\n throw {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Plugin error\",\n details: {\n path: `plugins.${plugin.name}.beforeQuery`,\n ...(error.details || {}),\n },\n };\n }\n }\n }\n\n return transformed;\n}\n\n/**\n * Run afterQuery hooks (fail-open)\n * Logs errors but continues execution\n */\nexport async function runAfterQuery(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n query: unknown,\n result: unknown,\n): Promise<unknown> {\n let transformed = result;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.afterQuery) {\n try {\n const pluginResult = await plugin.afterQuery(ctx, query, transformed);\n if (pluginResult !== undefined) {\n transformed = pluginResult;\n }\n } catch (error) {\n // Fail-open: log but continue\n console.error(`Plugin ${plugin.name}.afterQuery failed:`, error);\n }\n }\n }\n\n return transformed;\n}\n\n/**\n * Run beforeMutation hooks (fail-closed)\n */\nexport async function runBeforeMutation(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n mutation: unknown,\n): Promise<unknown> {\n let transformed = mutation;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.beforeMutation) {\n try {\n const result = await plugin.beforeMutation(ctx, transformed);\n if (result !== undefined) {\n transformed = result;\n }\n } catch (error: any) {\n throw {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Plugin error\",\n details: {\n path: `plugins.${plugin.name}.beforeMutation`,\n ...(error.details || {}),\n },\n };\n }\n }\n }\n\n return transformed;\n}\n\n/**\n * Run afterMutation hooks (fail-open)\n */\nexport async function runAfterMutation(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n mutation: unknown,\n result: unknown,\n): Promise<unknown> {\n let transformed = result;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.afterMutation) {\n try {\n await plugin.afterMutation(ctx, mutation, transformed);\n // afterMutation returns void, no transformation\n } catch (error) {\n console.error(`Plugin ${plugin.name}.afterMutation failed:`, error);\n }\n }\n }\n\n return transformed;\n}\n\n/**\n * Run beforeSync hooks (fail-closed)\n */\nexport async function runBeforeSync(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n phase: \"seed\" | \"clone\" | \"pull\" | \"push\",\n payload: unknown,\n): Promise<unknown> {\n let transformed = payload;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.beforeSync) {\n try {\n const result = await plugin.beforeSync(ctx, phase, transformed);\n if (result !== undefined) {\n transformed = result;\n }\n } catch (error: any) {\n throw {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Plugin error\",\n details: {\n path: `plugins.${plugin.name}.beforeSync`,\n ...(error.details || {}),\n },\n };\n }\n }\n }\n\n return transformed;\n}\n\n/**\n * Run afterSync hooks (fail-open)\n */\nexport async function runAfterSync(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n phase: \"seed\" | \"clone\" | \"pull\" | \"push\",\n payload: unknown,\n result: unknown,\n): Promise<unknown> {\n let transformed = result;\n const ctx: DatafnHookContext = { env: \"client\", schema };\n\n for (const plugin of getClientPlugins(plugins)) {\n if (plugin.afterSync) {\n try {\n await plugin.afterSync(ctx, phase, payload, transformed);\n // afterSync returns void, no transformation\n } catch (error) {\n console.error(`Plugin ${plugin.name}.afterSync failed:`, error);\n }\n }\n }\n\n return transformed;\n}\n","/**\n * Query Execution Utilities\n *\n * Handles query execution via remote adapter or local storage based on hydration state.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport type { DatafnPlugin, DatafnSchema } from \"@datafn/core\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { executeLocalQuery } from \"./offline/query.js\";\nimport { runBeforeQuery, runAfterQuery } from \"./plugins/run-hooks.js\";\n\n/**\n * Execute a query (single or batch) via the remote adapter or local storage.\n *\n * When storage is configured and table hydration state is 'ready', queries execute locally.\n * Otherwise, queries use remote fallback.\n *\n * @param remote - Remote adapter for server queries\n * @param q - Query or array of queries\n * @param storage - Optional storage adapter for local-first execution\n * @param plugins - Optional plugins for hook execution\n * @returns Query result(s)\n */\nexport async function executeQuery<T = unknown>(\n remote: DatafnRemoteAdapter,\n q: unknown | unknown[],\n storage?: DatafnStorageAdapter,\n plugins: DatafnPlugin[] = [],\n schema?: DatafnSchema,\n): Promise<T | T[]> {\n // Run beforeQuery hooks (fail-closed)\n const transformedQuery = schema\n ? await runBeforeQuery(plugins, schema, q)\n : q;\n\n // If no storage configured, always use remote (backward compatible)\n if (!storage) {\n const response = await remote.query(transformedQuery);\n const result = unwrapRemoteSuccess<T | T[]>(response);\n // Run afterQuery hooks (fail-open)\n return schema\n ? (runAfterQuery(plugins, schema, transformedQuery, result) as Promise<\n T | T[]\n >)\n : result;\n }\n\n // For batch queries, always use remote fallback (simplification for Phase 20)\n if (Array.isArray(transformedQuery)) {\n const response = await remote.query(transformedQuery);\n const result = unwrapRemoteSuccess<T | T[]>(response);\n return schema\n ? (runAfterQuery(plugins, schema, transformedQuery, result) as Promise<\n T | T[]\n >)\n : result;\n }\n\n // Single query: check hydration state for local-first routing\n const query = transformedQuery as Record<string, unknown>;\n const resource = query.resource as string;\n\n if (resource) {\n const hydrationState = await storage.getHydrationState(resource);\n\n // Local-first: execute against storage when table is ready\n if (hydrationState === \"ready\") {\n const result = (await executeLocalQuery(storage, query)) as T;\n return schema\n ? (runAfterQuery(plugins, schema, query, result) as Promise<T>)\n : result;\n }\n }\n\n // Remote fallback for: notStarted, hydrating, or missing resource\n const response = await remote.query(transformedQuery);\n const result = unwrapRemoteSuccess<T>(response);\n return schema\n ? (runAfterQuery(plugins, schema, transformedQuery, result) as Promise<T>)\n : result;\n}\n","/**\n * Offline Mutation Logic\n *\n * Handles offline mutations by:\n * 1. Appending to offline changelog\n * 2. Performing optimistic local write to storage\n */\n\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport { createClientError } from \"../errors.js\";\n\n/**\n * Handle a mutation when remote is unavailable.\n *\n * @param storage Storage adapter\n * @param mutation The full mutation object (including resource, version, clientId, mutationId)\n * @param timestampMs Client timestamp\n * @returns Optimistic mutation result\n */\nexport async function handleOfflineMutation(\n storage: DatafnStorageAdapter,\n mutation: Record<string, unknown>,\n timestampMs: number,\n): Promise<any> {\n // 1. Append to changelog (handling dedupe)\n // CLIENT-CHANGELOG-001, CLIENT-OFFLINE-MUT-001\n const clientId = mutation.clientId as string;\n const mutationId = mutation.mutationId as string;\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n\n try {\n await storage.changelogAppend({\n clientId,\n mutationId,\n mutation,\n timestampMs,\n });\n } catch (err) {\n // If changelog fails, the whole offline mutation fails\n // Throw as is or wrap (CLIENT-OFFLINE-MUT-002)\n throw err;\n }\n\n // 2. Optimistic local apply\n // Deterministic implementation\n const operation = mutation.operation as string;\n const record = (mutation.record || {}) as Record<string, unknown>;\n\n if (operation === \"delete\") {\n await storage.deleteRecord(resource, id);\n } else if (operation === \"merge\") {\n // Merge: Read -> Patch -> Write\n const existing = await storage.getRecord(resource, id);\n const merged = existing\n ? { ...existing, ...record } // Patch existing\n : { ...record, id }; // Create new if missing (upsert semantics)\n\n // Ensure id is present\n merged.id = id;\n\n await storage.upsertRecord(resource, merged);\n } else if (operation === \"insert\" || operation === \"replace\") {\n // Insert/Replace: Overwrite (simple upsert)\n // Ensure id matches mutation target\n const toWrite = { ...record, id };\n await storage.upsertRecord(resource, toWrite);\n }\n\n // 3. Return optimistic success result\n return {\n ok: true,\n mutationId,\n affectedIds: [id],\n deduped: false, // local apply is fresh\n };\n}\n","/**\n * Mutation Execution Utilities\n *\n * Handles mutation execution via remote adapter with event emission.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport type { EventBus } from \"./events/bus.js\";\nimport type { DatafnPlugin, DatafnSchema } from \"@datafn/core\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { isTransportError } from \"./errors.js\";\nimport { handleOfflineMutation } from \"./offline/mutate.js\";\nimport { runBeforeMutation, runAfterMutation } from \"./plugins/run-hooks.js\";\n\n/**\n * Execute a mutation (single or batch) via the remote adapter.\n * Unwraps responses, emits events, and returns mutation result(s).\n */\nexport async function executeMutation(\n remote: DatafnRemoteAdapter,\n eventBus: EventBus,\n getTimestamp: () => number,\n m: unknown | unknown[],\n storage?: DatafnStorageAdapter,\n plugins: DatafnPlugin[] = [],\n schema?: DatafnSchema,\n): Promise<unknown> {\n // Run beforeMutation hooks (fail-closed)\n const transformedMutation = schema\n ? await runBeforeMutation(plugins, schema, m)\n : m;\n\n let result: unknown;\n let fromOfflineFallback = false;\n\n try {\n const response = await remote.mutation(transformedMutation);\n result = unwrapRemoteSuccess(response);\n // Run afterMutation hooks (fail-open)\n result = schema\n ? await runAfterMutation(plugins, schema, transformedMutation, result)\n : result;\n } catch (err: unknown) {\n // CLIENT-EVENT-001: Emit mutation_rejected for thrown errors\n if (!Array.isArray(transformedMutation)) {\n emitRejectionForError(\n eventBus,\n getTimestamp,\n transformedMutation as any,\n err,\n );\n } else {\n // For batch mutations, emit rejection for each\n for (const mut of transformedMutation as any[]) {\n emitRejectionForError(eventBus, getTimestamp, mut, err);\n }\n }\n\n // Check if we can failover to offline handling\n // We only failover if:\n // 1. Storage is configured\n // 2. It's a single mutation (batch offline fallback not scope of P21)\n // 3. Error IS A TRANSPORT ERROR (logic errors should fail)\n if (storage && !Array.isArray(m) && isTransportError(err)) {\n try {\n result = await handleOfflineMutation(\n storage,\n m as Record<string, unknown>,\n getTimestamp(),\n );\n fromOfflineFallback = true;\n } catch (offlineErr) {\n // If offline fallback also fails (e.g. storage error), rethrow original error?\n // Actually vectors CLIENT-OFFLINE-MUT-002 expect storage error to be thrown if changelog fails\n throw offlineErr;\n }\n } else {\n // No fallback possible, rethrow\n throw err;\n }\n }\n\n // Handle single mutation result\n if (!Array.isArray(m)) {\n emitMutationEvents(eventBus, getTimestamp, m as any, result as any);\n return result;\n }\n\n // Handle batch mutation results\n const mutations = m as any[];\n const results = result as any[];\n\n for (let i = 0; i < mutations.length; i++) {\n emitMutationEvents(eventBus, getTimestamp, mutations[i], results[i]);\n }\n\n return results;\n}\n\n/**\n * Emit mutation events based on result\n * CLIENT-EVENT-001: Include action and fields metadata\n */\nfunction emitMutationEvents(\n eventBus: EventBus,\n getTimestamp: () => number,\n mutation: any,\n result: any,\n): void {\n // Derive action from mutation.operation (CLIENT-EVENT-001)\n const action = mutation.operation;\n\n // Derive fields from mutation.record keys, excluding 'id' (CLIENT-EVENT-001)\n let fields: string[] | undefined;\n if (mutation.operation !== \"delete\" && mutation.record) {\n fields = Object.keys(mutation.record)\n .filter((k) => k !== \"id\")\n .sort(); // deterministic order\n }\n\n const baseEvent = {\n resource: mutation.resource,\n ids: Array.isArray(mutation.id) ? mutation.id : [mutation.id],\n mutationId: mutation.mutationId,\n clientId: mutation.clientId,\n timestampMs: getTimestamp(),\n action, // NEW: CLIENT-EVENT-001\n fields, // NEW: CLIENT-EVENT-001\n };\n\n if (result.ok) {\n // Successful mutation - emit mutation_applied\n eventBus.emit({\n type: \"mutation_applied\",\n ...baseEvent,\n });\n } else {\n // Failed mutation - emit mutation_rejected with error context\n const errorContext = result.errors?.[0] || {\n code: \"UNKNOWN\",\n message: \"Mutation failed\",\n path: \"$\",\n };\n\n eventBus.emit({\n type: \"mutation_rejected\",\n ...baseEvent,\n context: errorContext,\n } as any);\n }\n}\n\n/**\n * Emit mutation_rejected for thrown errors (CLIENT-EVENT-001)\n */\nfunction emitRejectionForError(\n eventBus: EventBus,\n getTimestamp: () => number,\n mutation: any,\n error: any,\n): void {\n // Derive action and fields same as above\n const action = mutation.operation;\n let fields: string[] | undefined;\n if (mutation.operation !== \"delete\" && mutation.record) {\n fields = Object.keys(mutation.record)\n .filter((k) => k !== \"id\")\n .sort();\n }\n\n const errorContext = {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Remote error\",\n path: error.path || \"$\",\n };\n\n eventBus.emit({\n type: \"mutation_rejected\",\n resource: mutation.resource,\n ids: Array.isArray(mutation.id) ? mutation.id : [mutation.id],\n mutationId: mutation.mutationId,\n clientId: mutation.clientId,\n timestampMs: getTimestamp(),\n action,\n fields,\n context: errorContext,\n } as any);\n}\n","/**\n * Transaction Execution Utilities\n *\n * Handles transaction execution via remote adapter with response unwrapping.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\n\n/**\n * Execute a transaction via the remote adapter.\n * Unwraps response and returns transaction result.\n */\nexport async function executeTransact(\n remote: DatafnRemoteAdapter,\n payload: unknown\n): Promise<unknown> {\n const response = await remote.transact(payload);\n return unwrapRemoteSuccess(response);\n}\n","/**\n * Query Signal Implementation\n *\n * Reactive query signals with caching, lazy fetch, and auto-refresh on mutations.\n */\n\nimport type { DatafnSignal } from \"@datafn/core\";\nimport { dfqlKey } from \"@datafn/core\";\nimport type { EventBus } from \"../events/bus.js\";\n\n/**\n * Signal registry for caching signals by dfqlKey\n */\nexport class SignalRegistry {\n private signals = new Map<string, DatafnSignal<any>>();\n private client: any;\n private eventBus: EventBus;\n\n constructor(client: any, eventBus: EventBus) {\n this.client = client;\n this.eventBus = eventBus;\n }\n\n getSignal<T>(fullQuery: unknown): DatafnSignal<T> {\n const key = dfqlKey(fullQuery);\n\n // Return cached signal if exists\n if (this.signals.has(key)) {\n return this.signals.get(key) as DatafnSignal<T>;\n }\n\n // Create new signal\n const signal = createQuerySignal<T>(this.client, this.eventBus, fullQuery);\n this.signals.set(key, signal);\n return signal;\n }\n}\n\n/**\n * Create a reactive query signal\n */\nfunction createQuerySignal<T>(\n client: any,\n eventBus: EventBus,\n fullQuery: any,\n): DatafnSignal<T> {\n let currentValue: T | undefined;\n let status: \"idle\" | \"loading\" | \"error\" = \"idle\";\n const subscribers = new Set<(value: T) => void>();\n let inFlight = false;\n let queuedRefresh = false;\n const resource = fullQuery.resource;\n\n const fetchQuery = async (isRefresh = false): Promise<void> => {\n if (inFlight) {\n // Queue a refresh to happen after current fetch completes\n if (isRefresh) {\n queuedRefresh = true;\n }\n return;\n }\n\n inFlight = true;\n queuedRefresh = false;\n\n try {\n const result = await client.query(fullQuery);\n currentValue = result as T;\n status = \"idle\";\n\n // Only notify subscribers if this is not a silent refresh or it succeeded\n if (!isRefresh || currentValue !== undefined) {\n subscribers.forEach((fn) => fn(currentValue as T));\n }\n } catch (error) {\n // On refresh error, swallow and keep last value (don't notify)\n if (!isRefresh) {\n status = \"error\";\n throw error;\n }\n // Refresh errors are silent - keep old value, don't notify\n } finally {\n inFlight = false;\n\n // If a refresh was queued, execute it now\n if (queuedRefresh) {\n queuedRefresh = false;\n fetchQuery(true);\n }\n }\n };\n\n // Listen for mutation_applied events for auto-refresh\n eventBus.subscribe((event) => {\n if (event.type === \"mutation_applied\" && event.resource === resource) {\n // Trigger refresh\n fetchQuery(true);\n }\n });\n\n return {\n subscribe(fn: (value: T) => void): () => void {\n subscribers.add(fn);\n\n // Lazy fetch on first subscribe\n if (\n subscribers.size === 1 &&\n status === \"idle\" &&\n currentValue === undefined\n ) {\n fetchQuery(false).catch(() => {\n // Initial fetch errors are handled internally\n });\n } else if (currentValue !== undefined) {\n // Immediately deliver current value to new subscriber\n fn(currentValue);\n }\n\n // Return unsubscribe function\n return () => {\n subscribers.delete(fn);\n };\n },\n\n get(): T {\n // Return current value or undefined as T (signals can have undefined state)\n return currentValue as T;\n },\n };\n}\n","/**\n * Sync Apply Logic\n *\n * Apply clone/pull results into local storage with hydration state management.\n */\n\nimport type { DatafnStorageAdapter, DatafnHydrationState } from \"../storage.js\";\n\n/**\n * Clone result shape from remote\n */\nexport type CloneResult = {\n ok: boolean;\n data: Record<string, Array<Record<string, unknown>>>;\n cursors: Record<string, string>;\n};\n\n/**\n * Pull result shape from remote\n */\nexport type PullResult = {\n ok: boolean;\n records: Record<string, Array<Record<string, unknown>>>;\n deleted: Record<string, string[]>;\n cursors: Record<string, string>;\n};\n\n/**\n * Apply clone result to local storage.\n * Transitions hydration state: notStarted → hydrating → ready\n */\nexport async function applyCloneResult(\n storage: DatafnStorageAdapter,\n result: CloneResult,\n): Promise<void> {\n if (!result.ok) {\n return; // Don't apply failed results\n }\n\n const { data, cursors } = result;\n\n // Process each table\n for (const [resource, records] of Object.entries(data)) {\n // Transition to hydrating state before applying\n await storage.setHydrationState(resource, \"hydrating\");\n\n // Upsert all records by id\n for (const record of records) {\n await storage.upsertRecord(resource, record);\n }\n\n // Set cursor\n const cursor = cursors[resource];\n if (cursor !== undefined) {\n await storage.setCursor(resource, cursor);\n }\n\n // Transition to ready after applying\n await storage.setHydrationState(resource, \"ready\");\n }\n}\n\n/**\n * Apply pull result to local storage.\n * Updates records, deletes removed records, and updates cursors monotonically.\n */\nexport async function applyPullResult(\n storage: DatafnStorageAdapter,\n result: PullResult,\n): Promise<void> {\n if (!result.ok) {\n return; // Don't apply failed results\n }\n\n const { records, deleted, cursors } = result;\n\n // Process record updates\n for (const [resource, resourceRecords] of Object.entries(records)) {\n for (const record of resourceRecords) {\n await storage.upsertRecord(resource, record);\n }\n }\n\n // Process deletions\n for (const [resource, deletedIds] of Object.entries(deleted)) {\n for (const id of deletedIds) {\n await storage.deleteRecord(resource, id);\n }\n }\n\n // Update cursors monotonically (only forward)\n for (const [resource, newCursor] of Object.entries(cursors)) {\n await setCursorMonotonically(storage, resource, newCursor);\n }\n}\n\n/**\n * Set cursor only if new cursor is greater than existing cursor.\n * Cursors are base-10 integer strings representing serverSeq.\n */\nasync function setCursorMonotonically(\n storage: DatafnStorageAdapter,\n resource: string,\n newCursor: string,\n): Promise<void> {\n const existingCursor = await storage.getCursor(resource);\n\n // If no existing cursor, set the new one\n if (existingCursor === null) {\n await storage.setCursor(resource, newCursor);\n return;\n }\n\n // Parse as integers for comparison\n const existingSeq = parseInt(existingCursor, 10);\n const newSeq = parseInt(newCursor, 10);\n\n // Only update if new cursor is greater (monotonic)\n if (newSeq > existingSeq) {\n await storage.setCursor(resource, newCursor);\n }\n}\n","/**\n * Sync Facade\n *\n * Client-side sync methods that delegate to remote adapter.\n * When storage is configured, clone/pull results are applied to local storage.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { createClientError } from \"./errors.js\";\nimport { applyCloneResult, applyPullResult } from \"./sync/apply.js\";\nimport type { CloneResult, PullResult } from \"./sync/apply.js\";\n\nexport interface SyncFacade {\n seed(payload: unknown): Promise<unknown>;\n clone(payload: unknown): Promise<unknown>;\n pull(payload: unknown): Promise<unknown>;\n push(payload: unknown): Promise<unknown>;\n}\n\n/**\n * Create sync facade that delegates to remote adapter\n */\nexport function createSyncFacade(\n remote: DatafnRemoteAdapter,\n storage?: DatafnStorageAdapter,\n): SyncFacade {\n const callSyncMethod = async (\n methodName: keyof DatafnRemoteAdapter,\n payload: unknown,\n ): Promise<unknown> => {\n const method = remote[methodName];\n\n // Check if method exists\n if (typeof method !== \"function\") {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n `Transport error: remote method missing: ${methodName}`,\n { path: `sync.${methodName}` },\n );\n }\n\n // Call remote method and unwrap\n const response = await method.call(remote, payload);\n return unwrapRemoteSuccess(response);\n };\n\n return {\n async seed(payload: unknown) {\n return callSyncMethod(\"seed\", payload);\n },\n\n async clone(payload: unknown) {\n const result = await callSyncMethod(\"clone\", payload);\n\n // Apply to storage if configured (CLIENT-SYNC-APPLY-001, CLIENT-HYDRATION-001)\n if (storage) {\n await applyCloneResult(storage, result as CloneResult);\n }\n\n return result;\n },\n\n async pull(payload: unknown) {\n const result = await callSyncMethod(\"pull\", payload);\n\n // Apply to storage if configured (CLIENT-SYNC-APPLY-001)\n if (storage) {\n await applyPullResult(storage, result as PullResult);\n }\n\n return result;\n },\n\n async push(payload: unknown) {\n return callSyncMethod(\"push\", payload);\n },\n };\n}\n","/**\n * In-memory storage adapter for testing and development.\n * Implements deterministic ordering and changelog deduplication.\n */\n\nimport type {\n DatafnStorageAdapter,\n DatafnHydrationState,\n DatafnChangelogEntry,\n} from \"../storage.js\";\n\nexport class MemoryStorageAdapter implements DatafnStorageAdapter {\n private records = new Map<string, Map<string, Record<string, unknown>>>();\n private joinRows = new Map<string, Map<string, Record<string, unknown>>>();\n private cursors = new Map<string, string>();\n private hydration = new Map<string, DatafnHydrationState>();\n private changelog: DatafnChangelogEntry[] = [];\n private changelogSeq = 1;\n\n constructor() {}\n\n // --- Records ---\n\n async getRecord(\n resource: string,\n id: string,\n ): Promise<Record<string, unknown> | null> {\n const table = this.records.get(resource);\n return table?.get(id) || null;\n }\n\n async listRecords(resource: string): Promise<Record<string, unknown>[]> {\n const table = this.records.get(resource);\n if (!table) return [];\n\n // STORAGE-MEM-001: Deterministic ordering by id:asc\n return Array.from(table.values()).sort((a, b) => {\n const idA = (a.id as string) || \"\";\n const idB = (b.id as string) || \"\";\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n });\n }\n\n async upsertRecord(\n resource: string,\n record: Record<string, unknown>,\n ): Promise<void> {\n if (!this.records.has(resource)) {\n this.records.set(resource, new Map());\n }\n const id = record.id as string;\n if (!id) throw new Error(\"Record missing id\");\n this.records.get(resource)!.set(id, record);\n }\n\n async deleteRecord(resource: string, id: string): Promise<void> {\n const table = this.records.get(resource);\n if (table) {\n table.delete(id);\n }\n }\n\n // --- Join Rows ---\n\n async listJoinRows(\n relationKey: string,\n ): Promise<Array<Record<string, unknown>>> {\n const table = this.joinRows.get(relationKey);\n if (!table) return [];\n\n // Deterministic sort by from, to\n return Array.from(table.values()).sort((a, b) => {\n const keyA = `${a.from}:${a.to}`;\n const keyB = `${b.from}:${b.to}`;\n return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;\n });\n }\n\n async upsertJoinRow(\n relationKey: string,\n row: Record<string, unknown>,\n ): Promise<void> {\n if (!this.joinRows.has(relationKey)) {\n this.joinRows.set(relationKey, new Map());\n }\n // Composite key for storage\n const key = `${row.from}:${row.to}`;\n this.joinRows.get(relationKey)!.set(key, row);\n }\n\n async deleteJoinRow(\n relationKey: string,\n from: string,\n to: string,\n ): Promise<void> {\n const table = this.joinRows.get(relationKey);\n if (table) {\n table.delete(`${from}:${to}`);\n }\n }\n\n // --- Sync State ---\n\n async getCursor(resource: string): Promise<string | null> {\n return this.cursors.get(resource) || null;\n }\n\n async setCursor(resource: string, cursor: string): Promise<void> {\n this.cursors.set(resource, cursor);\n }\n\n async getHydrationState(resource: string): Promise<DatafnHydrationState> {\n return this.hydration.get(resource) || \"notStarted\";\n }\n\n async setHydrationState(\n resource: string,\n state: DatafnHydrationState,\n ): Promise<void> {\n this.hydration.set(resource, state);\n }\n\n // --- Changelog ---\n\n async changelogAppend(\n entry: Omit<DatafnChangelogEntry, \"seq\">,\n ): Promise<DatafnChangelogEntry> {\n // CLIENT-CHANGELOG-001: Deduplicate by (clientId, mutationId)\n const existing = this.changelog.find(\n (e) => e.clientId === entry.clientId && e.mutationId === entry.mutationId,\n );\n if (existing) {\n return existing;\n }\n\n const newEntry: DatafnChangelogEntry = {\n ...entry,\n seq: this.changelogSeq++,\n };\n this.changelog.push(newEntry);\n return newEntry;\n }\n\n async changelogList(\n options: { limit?: number } = {},\n ): Promise<DatafnChangelogEntry[]> {\n const limit = options.limit || 100;\n return this.changelog.slice(0, limit); // Already sorted by insertion/seq\n }\n\n async changelogAck(options: { throughSeq: number }): Promise<void> {\n // Remove acked entries\n this.changelog = this.changelog.filter((e) => e.seq > options.throughSeq);\n }\n\n // Test helper to clear state\n clear() {\n this.records.clear();\n this.joinRows.clear();\n this.cursors.clear();\n this.hydration.clear();\n this.changelog = [];\n this.changelogSeq = 1;\n }\n}\n","/**\n * IndexedDB storage adapter for persistent client storage.\n * Implements deterministic ordering and changelog deduplication.\n */\n\nimport type {\n DatafnStorageAdapter,\n DatafnHydrationState,\n DatafnChangelogEntry,\n} from \"../storage\";\n\nconst DB_NAME = \"datafn_client_db\";\nconst DB_VERSION = 1;\n\nexport class IndexedDbStorageAdapter implements DatafnStorageAdapter {\n private dbPromise: Promise<IDBDatabase>;\n\n constructor(dbName: string = DB_NAME) {\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(dbName, DB_VERSION);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n\n request.onupgradeneeded = (event) => {\n const db = request.result;\n\n // Records store: Key [resource, id]\n // This effectively groups by resource and allows range queries\n if (!db.objectStoreNames.contains(\"records\")) {\n const store = db.createObjectStore(\"records\", {\n keyPath: [\"resource\", \"id\"],\n });\n store.createIndex(\"by_resource\", \"resource\", { unique: false });\n }\n\n // Join rows store: Key [relationKey, from, to]\n if (!db.objectStoreNames.contains(\"join_rows\")) {\n const store = db.createObjectStore(\"join_rows\", {\n keyPath: [\"relationKey\", \"from\", \"to\"],\n });\n store.createIndex(\"by_relation\", \"relationKey\", { unique: false });\n }\n\n // Meta store: Key [type, key] (e.g. [\"cursor\", \"task\"], [\"hydration\", \"task\"])\n if (!db.objectStoreNames.contains(\"meta\")) {\n db.createObjectStore(\"meta\", { keyPath: [\"type\", \"key\"] });\n }\n\n // Changelog store: Key seq (autoIncrement)\n if (!db.objectStoreNames.contains(\"changelog\")) {\n const store = db.createObjectStore(\"changelog\", {\n keyPath: \"seq\",\n autoIncrement: true,\n });\n // Unique index for deduplication\n store.createIndex(\"by_client_mutation\", [\"clientId\", \"mutationId\"], {\n unique: true,\n });\n }\n };\n });\n }\n\n private async getStore(\n storeName: string,\n mode: IDBTransactionMode,\n ): Promise<IDBObjectStore> {\n const db = await this.dbPromise;\n return db.transaction(storeName, mode).objectStore(storeName);\n }\n\n // --- Records ---\n\n async getRecord(\n resource: string,\n id: string,\n ): Promise<Record<string, unknown> | null> {\n const store = await this.getStore(\"records\", \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get([resource, id]);\n request.onsuccess = () => resolve(request.result || null);\n request.onerror = () => reject(request.error);\n });\n }\n\n async listRecords(resource: string): Promise<Record<string, unknown>[]> {\n const store = await this.getStore(\"records\", \"readonly\");\n const index = store.index(\"by_resource\");\n return new Promise((resolve, reject) => {\n // Get all records for resource\n // Since keyPath is [resource, id], the natural index order for \"by_resource\" might not guarantee id sort?\n // Actually, if we use the primary key range on the store itself:\n // IDB sorts by key path. [resource, id] sorts by resource, then id.\n // So retrieving a range matching [resource, -Infinity] to [resource, Infinity]\n // from the object store directly will return them sorted by id!\n\n const range = IDBKeyRange.bound([resource, \"\"], [resource, \"\\uffff\"]);\n\n const request = store.getAll(range);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async upsertRecord(\n resource: string,\n record: Record<string, unknown>,\n ): Promise<void> {\n const store = await this.getStore(\"records\", \"readwrite\");\n return new Promise((resolve, reject) => {\n // Ensure resource is set in record for storage (though it might be redundant with key)\n // The keyPath requires 'resource' and 'id' properties on the object.\n const recordWithKey = { ...record, resource };\n const request = store.put(recordWithKey);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async deleteRecord(resource: string, id: string): Promise<void> {\n const store = await this.getStore(\"records\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.delete([resource, id]);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Join Rows ---\n\n async listJoinRows(\n relationKey: string,\n ): Promise<Array<Record<string, unknown>>> {\n const store = await this.getStore(\"join_rows\", \"readonly\");\n\n // Similarly, keyPath [relationKey, from, to] guarantees sorting by from, then to.\n const range = IDBKeyRange.bound(\n [relationKey, \"\", \"\"],\n [relationKey, \"\\uffff\", \"\\uffff\"],\n );\n\n return new Promise((resolve, reject) => {\n const request = store.getAll(range);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async upsertJoinRow(\n relationKey: string,\n row: Record<string, unknown>,\n ): Promise<void> {\n const store = await this.getStore(\"join_rows\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const rowWithKey = { ...row, relationKey };\n const request = store.put(rowWithKey);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async deleteJoinRow(\n relationKey: string,\n from: string,\n to: string,\n ): Promise<void> {\n const store = await this.getStore(\"join_rows\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.delete([relationKey, from, to]);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Sync State ---\n\n async getCursor(resource: string): Promise<string | null> {\n const store = await this.getStore(\"meta\", \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get([\"cursor\", resource]);\n request.onsuccess = () => resolve(request.result?.value || null);\n request.onerror = () => reject(request.error);\n });\n }\n\n async setCursor(resource: string, cursor: string): Promise<void> {\n const store = await this.getStore(\"meta\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.put({\n type: \"cursor\",\n key: resource,\n value: cursor,\n });\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async getHydrationState(resource: string): Promise<DatafnHydrationState> {\n const store = await this.getStore(\"meta\", \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get([\"hydration\", resource]);\n request.onsuccess = () => resolve(request.result?.value || \"notStarted\");\n request.onerror = () => reject(request.error);\n });\n }\n\n async setHydrationState(\n resource: string,\n state: DatafnHydrationState,\n ): Promise<void> {\n const store = await this.getStore(\"meta\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.put({\n type: \"hydration\",\n key: resource,\n value: state,\n });\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Changelog ---\n\n async changelogAppend(\n entry: Omit<DatafnChangelogEntry, \"seq\">,\n ): Promise<DatafnChangelogEntry> {\n const store = await this.getStore(\"changelog\", \"readwrite\");\n const index = store.index(\"by_client_mutation\");\n\n // Check for duplicate\n const existing = await new Promise<DatafnChangelogEntry | undefined>(\n (resolve, reject) => {\n const request = index.get([entry.clientId, entry.mutationId]);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n },\n );\n\n if (existing) {\n return existing;\n }\n\n // Insert new\n return new Promise((resolve, reject) => {\n // Don't pass seq, let autoIncrement handle it\n const request = store.add(entry);\n request.onsuccess = () => {\n const seq = request.result as number;\n resolve({ ...entry, seq });\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n async changelogList(\n options: { limit?: number } = {},\n ): Promise<DatafnChangelogEntry[]> {\n const store = await this.getStore(\"changelog\", \"readonly\");\n return new Promise((resolve, reject) => {\n const limit = options.limit || 100;\n // getAll allows limit\n const request = store.getAll(null, limit);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async changelogAck(options: { throughSeq: number }): Promise<void> {\n const store = await this.getStore(\"changelog\", \"readwrite\");\n\n // Delete range <= throughSeq\n const range = IDBKeyRange.upperBound(options.throughSeq);\n\n return new Promise((resolve, reject) => {\n const request = store.delete(range);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n}\n"],"mappings":"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","names":["response","result"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/events/filter.ts","../src/events/bus.ts","../src/errors.ts","../src/tables/table.ts","../src/remote/unwrap.ts","../src/offline/mutate.ts","../src/capability-fields.ts","../src/plugins/run-hooks.ts","../src/codecs/date.ts","../src/mutate.ts","../src/offline/query.ts","../src/offline/relations.ts","../src/offline/aggregate.ts","../src/query.ts","../src/tables/registry.ts","../src/transact.ts","../src/signals/querySignal.ts","../src/signals/liveSignal.ts","../src/sync/apply.ts","../src/sync/cloneUp.ts","../src/sync/cloneUp/hash.ts","../src/sync/cloneUp/order.ts","../src/sync/cloneUp/batch.ts","../src/sync.ts","../src/transport/http.ts","../src/sync/engine.ts","../src/kv.ts","../src/extension/subscriptionManager.ts","../src/debounce.ts","../src/export.ts","../src/crossTab.ts","../src/index.ts","../src/adapters/memoryStorage.ts","../src/adapters/shared.ts","../src/adapters/indexedDbStorage.ts"],"sourcesContent":["/**\n * DataFn client factory\n */\n\nimport type { DatafnSchema, DatafnPlugin, SearchProvider } from \"@datafn/core\";\nimport { validateSchema, buildSchemaIndex, evaluateFilter as coreEvaluateFilter } from \"@datafn/core\";\nimport { EventBus, type EventHandler } from \"./events/bus.js\";\nimport type { EventFilter } from \"./events/filter.js\";\nimport { createClientError } from \"./errors.js\";\nimport { TableRegistry } from \"./tables/registry.js\";\nimport type { DatafnTable } from \"./tables/table.js\";\nimport { executeQuery } from \"./query.js\";\nimport { executeMutation } from \"./mutate.js\";\nimport { executeTransact } from \"./transact.js\";\nimport { SignalRegistry } from \"./signals/querySignal.js\";\nimport { LiveSignalRegistry } from \"./signals/liveSignal.js\";\nimport { createSyncFacade, type SyncFacade } from \"./sync.js\";\nimport type { DatafnStorageAdapter, DatafnStorageFactory } from \"./storage.js\";\nimport { DefaultHttpTransport } from \"./transport/http.js\";\nimport { SyncEngine } from \"./sync/engine.js\";\nimport { createKvApi, type DatafnKvApi, KV_RESOURCE_NAME } from \"./kv.js\";\nimport { ensureBuiltinKv } from \"@datafn/core\";\nimport { ExtensionSubscriptionManager } from \"./extension/subscriptionManager.js\";\nimport { DebouncerMap } from \"./debounce.js\";\nimport { exportData, importData, type DatafnExportPayload, type DatafnImportResult } from \"./export.js\";\nimport { CrossTabRelay } from \"./crossTab.js\";\n\n// Helper type to extract resource names from schema\nexport type ResourceNames<S extends DatafnSchema> =\n S[\"resources\"][number][\"name\"];\n\nexport interface DatafnRemoteAdapter {\n query(q: unknown): Promise<unknown>;\n mutation(m: unknown): Promise<unknown>;\n transact(t: unknown): Promise<unknown>;\n seed(payload: unknown): Promise<unknown>;\n clone(payload: unknown): Promise<unknown>;\n pull(payload: unknown): Promise<unknown>;\n push(payload: unknown): Promise<unknown>;\n reconcile(payload: unknown): Promise<unknown>; // Required for SYNC-007\n search?(payload: unknown): Promise<unknown>;\n}\n\nexport interface DatafnSyncConfig {\n /**\n * Enable offline support. Requires `storage` adapter.\n */\n offlinability?: boolean;\n\n /**\n * Remote server URL used by the default HTTP transport and for deriving wsUrl.\n * Optional when `remoteAdapter` is provided.\n */\n remote?: string;\n\n /**\n * Optional injected adapter used instead of DefaultHttpTransport.\n * Required for extension environments.\n */\n remoteAdapter?: DatafnRemoteAdapter;\n\n /**\n * Enable WebSocket updates.\n */\n ws?: boolean;\n\n /**\n * WebSocket URL. If not provided, derived from `remote` when `ws` is enabled.\n */\n wsUrl?: string;\n\n /**\n * Batch push interval in milliseconds.\n * Must be a positive integer.\n */\n pushInterval?: number;\n\n /**\n * Batch push page size.\n * Must be a positive integer. Default 100.\n */\n pushBatchSize?: number;\n\n /**\n * Max retries for push.\n * Must be a non-negative integer. Default 3.\n */\n pushMaxRetries?: number;\n\n /**\n * Hydration plan for large datasets.\n */\n hydration?: {\n /**\n * Resources that MUST be cloned to `ready` before the app can consider itself hydrated.\n */\n bootResources?: string[];\n /**\n * Resources that MAY hydrate in the background after boot.\n */\n backgroundResources?: string[];\n /**\n * Per-resource clone page size limits used by paginated clone.\n */\n clonePageSize?: number | Record<string, number>;\n };\n\n /**\n * Explicit mode selection.\n * - \"sync\": requires remote or remoteAdapter.\n * - \"local-only\": remote is not required; all local tables start as `ready`.\n */\n mode?: \"sync\" | \"local-only\";\n\n /**\n * WebSocket reconnection configuration with exponential backoff and jitter.\n * Default: enabled with baseDelayMs=1000, multiplier=2, maxDelayMs=60000, jitterMs=500.\n */\n wsReconnect?: {\n enabled?: boolean;\n baseDelayMs?: number;\n maxDelayMs?: number;\n multiplier?: number;\n jitterMs?: number;\n };\n\n /**\n * Push retry exponential backoff configuration.\n * Default: baseDelayMs=1000, multiplier=2, maxDelayMs=60000, jitterMs=500.\n */\n pushRetryBackoff?: {\n baseDelayMs?: number;\n maxDelayMs?: number;\n multiplier?: number;\n jitterMs?: number;\n };\n\n /**\n * Push interval exponential backoff configuration when push keeps failing.\n * When a push round exhausts all retries and fails, the next round is delayed\n * using exponential backoff: pushInterval * multiplier^consecutiveFailures.\n * On first success after failures, backoff is reset to configured pushInterval.\n * Default: baseMultiplier=2, maxDelayMs=300000 (5 minutes), jitterMs=1000.\n */\n pushIntervalBackoff?: {\n baseMultiplier?: number;\n maxDelayMs?: number;\n jitterMs?: number;\n };\n\n /**\n * Pull batch size limit per request.\n * Must be a positive integer between 10 and 10000.\n * Default: 200.\n */\n pullBatchSize?: number;\n\n /**\n * Maximum number of catch-up pull iterations per sync cycle (CLIENT-PULL-003).\n * Prevents infinite loops if the server continuously returns hasMore=true.\n * Default: 50.\n */\n maxPullIterations?: number;\n\n /**\n * Enable cross-tab coordination via BroadcastChannel.\n * When enabled, mutation events are relayed to other same-origin tabs for near-instant reactivity.\n * Default: false (opt-in).\n */\n crossTab?: boolean;\n\n /**\n * Defer search indexing for initial clone and rebuild asynchronously after clone completion.\n */\n skipCloneIndexing?: boolean;\n}\n\nexport interface DatafnClientConfig<S extends DatafnSchema> {\n schema: S;\n /**\n * Sync configuration.\n */\n sync?: DatafnSyncConfig;\n /**\n * Optional plugins for client-side hook execution\n */\n plugins?: DatafnPlugin[];\n /**\n * Stable client/device identifier used for idempotency and offline change logs.\n * Required when `storage` is provided.\n */\n clientId: string;\n /**\n * Local persistence adapter. Can be:\n * - A direct `DatafnStorageAdapter` instance\n * - A factory function `(namespace: string) => DatafnStorageAdapter` for multi-user isolation\n *\n * When using a factory function, `namespace` must also be provided.\n */\n storage?: DatafnStorageAdapter | DatafnStorageFactory;\n /**\n * Namespace for client-side data isolation.\n * Used to construct isolated storage (IndexedDB database names, BroadcastChannel names).\n * Required when `storage` is a factory function.\n */\n namespace?: string;\n getTimestamp?: () => number; // For testing with fake clock\n /**\n * Resource-aware ID generator function for insert operations.\n * If not provided, defaults to crypto.randomUUID() with resource prefix.\n * Allows users to use custom ID strategies (UUID v7, ULID, etc.)\n * without adding dependencies to @datafn/client.\n */\n generateId?: (params: { resource: string; idPrefix?: string }) => string;\n\n /**\n * Optional search provider for client-side search query routing.\n */\n searchProvider?: SearchProvider;\n}\n\n/**\n * Override options for switchContext.\n * Only the provided fields are changed; everything else is inherited from the current config.\n */\nexport type SwitchContextOverride = {\n /** New namespace (replaces current) */\n namespace?: string;\n /** New sync configuration (replaces current, not merged) */\n sync?: DatafnSyncConfig;\n /** New storage adapter or factory (replaces current) */\n storage?: DatafnStorageAdapter | DatafnStorageFactory;\n};\n\nexport type DatafnClient<S extends DatafnSchema> = {\n table<Name extends ResourceNames<S>>(name: Name): DatafnTable<S, Name>;\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(mutation: unknown | unknown[]): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n sync: SyncFacade & {\n start(): Promise<void>;\n stop(): void;\n pullNow(): Promise<void>;\n cloneNow(): Promise<void>;\n reconcileNow(): Promise<void>;\n };\n kv: DatafnKvApi;\n /** Tear down client: stop sync, close connections, unsubscribe all, release resources. */\n destroy(): Promise<void>;\n /** Wipe all local data (IndexedDB stores, cursors, changelog, hydration state). */\n clear(): Promise<void>;\n /** Flush a specific debounced mutation immediately. */\n flush(key?: string): Promise<void>;\n /** Flush all pending debounced mutations immediately. */\n flushAll(): Promise<void>;\n /** Export all local records as structured JSON. */\n exportData(options?: { resources?: string[] }): Promise<unknown>;\n /** Import records from a structured JSON payload. */\n importData(data: unknown, options?: { triggerCloneUp?: boolean }): Promise<unknown>;\n /** Check storage health and verify hydration state consistency. */\n checkHealth(): Promise<{ ok: boolean; issues: string[]; action?: \"none\" | \"reclone\" }>;\n /** Perform a cross-resource search using the configured search provider. */\n search(params: unknown): Promise<unknown>;\n /**\n * Switch to a different configuration context (auth, sync mode, or storage).\n * Destroys the current underlying client and recreates it with merged config.\n * Concurrent calls are serialized. Auto-starts sync when sync.mode is \"sync\".\n */\n switchContext(override: SwitchContextOverride): Promise<void>;\n /** Get the current resolved namespace, or undefined if not configured. */\n currentNamespace(): string | undefined;\n /**\n * Subscribe to client lifecycle changes.\n * The callback fires immediately with the stable proxy reference,\n * and again after every switchContext() completes.\n * Returns an unsubscribe function.\n */\n subscribeClient(fn: (client: DatafnClient<S>) => void): () => void;\n} & {\n [Name in ResourceNames<S>]: DatafnTable<S, Name>;\n};\n\n/**\n * Internal: creates a one-shot DataFn client without switching capability.\n * Used by createDatafnClient (the public API that adds switchContext).\n */\nfunction _buildRawClient<S extends DatafnSchema>(\n config: DatafnClientConfig<S>,\n): DatafnClient<S> {\n // Validate schema at client creation (CLIENT-API-001)\n const validationResult = validateSchema(config.schema);\n if (!validationResult.ok) {\n createClientError(\n validationResult.error.code,\n validationResult.error.message,\n validationResult.error.details as {\n path: string;\n [key: string]: unknown;\n },\n );\n }\n\n // Validate Sync Config (CFG-001, CFG-002)\n // Note: We validate offlinability requires storage after resolving storage below\n if (config.sync) {\n // Determine sync mode (default to \"sync\")\n const syncMode = config.sync.mode || \"sync\";\n\n // CFG-001: In sync mode, require remote or remoteAdapter\n if (syncMode === \"sync\") {\n if (!config.sync.remote && !config.sync.remoteAdapter) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: remote or remoteAdapter is required in sync mode\",\n { path: \"sync\" },\n );\n }\n }\n\n // CFG-002: In local-only mode, forbid ws without remote/wsUrl\n if (syncMode === \"local-only\") {\n if (\n config.sync.ws === true &&\n !config.sync.remote &&\n !config.sync.wsUrl\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: WebSocket requires remote or wsUrl in local-only mode\",\n { path: \"sync.ws\" },\n );\n }\n }\n\n if (\n config.sync.pushBatchSize !== undefined &&\n (!Number.isInteger(config.sync.pushBatchSize) ||\n config.sync.pushBatchSize <= 0)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: pushBatchSize must be a positive integer\",\n { path: \"sync.pushBatchSize\" },\n );\n }\n if (\n config.sync.pushInterval !== undefined &&\n (!Number.isInteger(config.sync.pushInterval) ||\n config.sync.pushInterval <= 0)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: pushInterval must be a positive integer\",\n { path: \"sync.pushInterval\" },\n );\n }\n if (\n config.sync.pushMaxRetries !== undefined &&\n (!Number.isInteger(config.sync.pushMaxRetries) ||\n config.sync.pushMaxRetries < 0)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: pushMaxRetries must be a non-negative integer\",\n { path: \"sync.pushMaxRetries\" },\n );\n }\n // CFG-001: Validate pullBatchSize\n if (\n config.sync.pullBatchSize !== undefined &&\n (!Number.isInteger(config.sync.pullBatchSize) ||\n config.sync.pullBatchSize < 10 ||\n config.sync.pullBatchSize > 10000)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: pullBatchSize must be a positive integer between 10 and 10000\",\n { path: \"sync.pullBatchSize\" },\n );\n }\n }\n\n // Ensure built-in KV resource exists in schema (KV-001)\n const schema = ensureBuiltinKv(validationResult.result);\n // Optional plugin-level schema validation hook\n for (const plugin of config.plugins || []) {\n const validatePluginSchema = (plugin as unknown as Record<string, unknown>)\n .validateSchema;\n if (typeof validatePluginSchema === \"function\") {\n (validatePluginSchema as (schema: DatafnSchema) => void)(schema);\n }\n }\n // Build O(1) schema index for offline query path (IDX-003)\n const schemaIndex = buildSchemaIndex(schema);\n const eventBus = new EventBus();\n const getTimestamp = config.getTimestamp || (() => Date.now());\n\n // Create ID generator with built-in default strategy (API-001)\n const generateId =\n config.generateId ||\n (({ resource, idPrefix }: { resource: string; idPrefix?: string }) => {\n // Generate a random ID component\n let randomId: string;\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n randomId = crypto.randomUUID();\n } else {\n randomId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n }\n\n // Use idPrefix if provided, otherwise default to resource:\n const prefix = idPrefix || resource;\n return `${prefix}:${randomId}`;\n });\n\n // Validate empty namespace (NS-022)\n if (config.namespace !== undefined && config.namespace === \"\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: namespace must be a non-empty string\",\n { path: \"namespace\" },\n );\n }\n\n // Resolve storage adapter (may be a factory function requiring namespace)\n let resolvedStorage: DatafnStorageAdapter | undefined;\n let resolvedNamespace: string | undefined = config.namespace;\n if (config.storage) {\n if (typeof config.storage === \"function\") {\n // Storage is a factory function — requires namespace\n if (config.namespace) {\n resolvedStorage = config.storage(config.namespace);\n } else {\n throw createClientError(\n \"DFQL_INVALID\",\n \"namespace is required when storage is a factory function\",\n { path: \"namespace\" },\n );\n }\n } else {\n // Direct storage adapter\n resolvedStorage = config.storage;\n }\n }\n\n // Validate offlinability requires resolved storage\n if (config.sync?.offlinability && !resolvedStorage) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid client config: storage is required when offlinability is true\",\n { path: \"storage\" },\n );\n }\n\n // STORAGE-INIT-001: Validate storage has all required resource stores.\n // Probes each resource with a lightweight getRecord call. If a store is\n // missing (e.g. schema was not passed to IndexedDbStorageAdapter), this\n // throws a clear error on the first query/mutation instead of a cryptic\n // \"Store not found\" deep in the stack.\n // Defined before localOnlyInitPromise so that it can be awaited first.\n const storageValidationPromise = resolvedStorage\n ? (async () => {\n for (const resource of schema.resources) {\n if (resource.isRemoteOnly) continue;\n try {\n await resolvedStorage.getRecord(resource.name, \"__storage_probe__\");\n } catch (err: any) {\n if (\n typeof err?.message === \"string\" &&\n err.message.includes(\"Store not found\")\n ) {\n createClientError(\n \"DFQL_INVALID\",\n `Storage is missing object store for resource \"${resource.name}\". ` +\n `Pass schema when creating IndexedDbStorageAdapter: ` +\n `IndexedDbStorageAdapter.create({ dbName, schema })`,\n { path: \"storage\", resource: resource.name },\n );\n }\n throw err;\n }\n }\n })()\n : Promise.resolve();\n\n // Suppress unhandled rejection — the error is re-thrown when awaited in mutate/query.\n storageValidationPromise.catch(() => {});\n\n // For local-only mode, we'll lazily initialize hydration state on first query/mutation (CFG-002)\n // Must await storageValidationPromise first to avoid using a broken storage.\n const needsLocalOnlyInit =\n config.sync?.mode === \"local-only\" && resolvedStorage;\n const localOnlyInitPromise =\n needsLocalOnlyInit && resolvedStorage\n ? (async () => {\n await storageValidationPromise;\n // Mark all non-remote-only resources as ready\n // Must follow valid transitions: notStarted -> hydrating -> ready\n for (const resource of schema.resources) {\n if (!resource.isRemoteOnly) {\n await resolvedStorage.setHydrationState(\n resource.name,\n \"hydrating\",\n );\n await resolvedStorage.setHydrationState(resource.name, \"ready\");\n }\n }\n })()\n : Promise.resolve();\n\n // Suppress unhandled rejection — the error is re-thrown when awaited in mutate/query.\n localOnlyInitPromise.catch(() => {});\n\n // PROV-008: Initialize search provider at client startup when configured.\n // This promise is awaited by query/mutate/search so init failures surface deterministically.\n const searchProviderInitPromise = (async () => {\n if (!config.searchProvider?.initialize) return;\n const resources = schema.resources\n .map((resource) => ({\n name: resource.name,\n searchFields: Array.isArray(resource.indices) ? [] : (resource.indices?.search ?? []),\n }))\n .filter((resource) => resource.searchFields.length > 0);\n await config.searchProvider.initialize({ resources });\n })();\n searchProviderInitPromise.catch(() => {});\n\n // Resolve remote adapter (CFG-001)\n let remote: DatafnRemoteAdapter;\n let extensionSubscriptionManager: ExtensionSubscriptionManager | undefined;\n\n if (config.sync?.remoteAdapter) {\n // Precedence 1: Use provided remoteAdapter\n remote = config.sync.remoteAdapter;\n\n // EXT-001: Wire inbound remote events if extension adapter supports it\n // Check if the adapter has onEvent capability (extension adapter)\n if (\"onEvent\" in remote && typeof remote.onEvent === \"function\") {\n const extAdapter = remote as any; // Has onEvent, subscribeRemote, unsubscribeRemote methods\n\n // Wire inbound remote events into local event bus\n extAdapter.onEvent((delivery: { subscriptionId: string; event: any }) => {\n // Emit the remote event into local event bus\n // The event is already in DatafnEvent format from background\n eventBus.emit(delivery.event);\n });\n\n // Create subscription manager for lifecycle management\n if (\"subscribeRemote\" in extAdapter && \"unsubscribeRemote\" in extAdapter) {\n extensionSubscriptionManager = new ExtensionSubscriptionManager({\n subscribeRemote: extAdapter.subscribeRemote.bind(extAdapter),\n unsubscribeRemote: extAdapter.unsubscribeRemote.bind(extAdapter),\n });\n }\n }\n } else if (config.sync?.remote) {\n // Precedence 2: Create DefaultHttpTransport from remote URL\n remote = new DefaultHttpTransport(config.sync.remote);\n } else {\n // Precedence 3: Create throwing adapter for local-only mode\n // This adapter should only be called if code violates routing invariants\n remote = {\n query: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n mutation: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n transact: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n seed: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n clone: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n pull: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n push: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n reconcile: async () => {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n \"No remote adapter configured\",\n { path: \"sync\" },\n );\n },\n };\n }\n\n // Create SyncEngine (for offline push)\n let syncEngine: SyncEngine | undefined;\n if (config.sync?.offlinability && resolvedStorage) {\n syncEngine = new SyncEngine(\n resolvedStorage,\n remote,\n eventBus,\n config.clientId,\n schema,\n config.sync,\n config.plugins || [],\n getTimestamp,\n config.searchProvider,\n );\n }\n\n // Create base sync facade\n const baseSync = createSyncFacade(\n remote,\n resolvedStorage,\n {\n schema: schema as DatafnSchema,\n storage: resolvedStorage,\n remote: config.sync?.remote ? remote : undefined,\n clientId: config.clientId,\n syncConfig: config.sync,\n eventBus,\n getTimestamp,\n },\n config.plugins || [],\n schema,\n eventBus,\n getTimestamp,\n );\n\n // Enhanced sync facade with start/stop/pullNow/cloneNow/reconcileNow\n const sync = {\n ...baseSync,\n async start() {\n if (syncEngine) {\n await syncEngine.start();\n }\n },\n stop() {\n if (syncEngine) {\n syncEngine.stop();\n }\n },\n async pullNow() {\n if (syncEngine) {\n await syncEngine.pullNow();\n }\n },\n async cloneNow() {\n if (syncEngine) {\n await syncEngine.cloneNow();\n }\n },\n async reconcileNow() {\n if (syncEngine) {\n await syncEngine.reconcileNow();\n }\n },\n };\n\n // Reserved keys that should not trigger table lookup (CLIENT-REG-002)\n const RESERVED_KEYS = new Set([\"then\", \"toJSON\", \"inspect\"]);\n\n // Client lifecycle state (CLN-001)\n let destroyed = false;\n \n /**\n * Guard method to ensure client is not destroyed\n */\n const guardDestroyed = () => {\n if (destroyed) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Client has been destroyed\",\n { path: \"client\", context: \"client lifecycle\" }\n );\n }\n };\n\n const assertSearchNotAborted = (signal?: AbortSignal) => {\n if (signal?.aborted) {\n throw createClientError(\n \"DFQL_ABORTED\",\n \"Search request aborted\",\n { path: \"signal\" },\n );\n }\n };\n\n const applySearchSelect = (\n record: Record<string, unknown>,\n select?: string[],\n ): Record<string, unknown> => {\n if (!select || select.length === 0) return record;\n const out: Record<string, unknown> = {};\n for (const field of select) {\n if (field in record) out[field] = record[field];\n }\n return out;\n };\n\n // Create debouncer for mutation debouncing (DEB-001)\n const debouncerMap = new DebouncerMap();\n\n // Create cross-tab relay if enabled (TAB-001)\n let crossTabRelay: CrossTabRelay | undefined;\n if (config.sync?.crossTab === true) {\n // Use clientId as namespace for the BroadcastChannel\n crossTabRelay = new CrossTabRelay(config.clientId, eventBus);\n\n // Subscribe to mutation_applied events and relay them to other tabs\n // Exclude: silent mutations (they don't emit events) and fromRemoteTab events (prevent echo)\n eventBus.subscribe((event) => {\n if (\n event.type === \"mutation_applied\" &&\n !(event as any).fromRemoteTab // Don't relay events from other tabs\n ) {\n crossTabRelay!.broadcast(event);\n }\n });\n }\n\n // Create the client object first (will add table() method after registry is created)\n // We cast to any initially because the mapped types are handled by Proxy\n const client: any = {\n table: null as any, // Will be set below\n\n /**\n * Execute a query (CLIENT-QUERY-001, CLIENT-OFFLINE-QUERY-001)\n */\n async query(q: unknown | unknown[]) {\n guardDestroyed();\n await searchProviderInitPromise;\n await storageValidationPromise; // STORAGE-INIT-001: fail fast if stores are missing\n await localOnlyInitPromise; // Ensure hydration state is ready in local-only mode\n return executeQuery(\n remote,\n q,\n resolvedStorage,\n config.plugins || [],\n schema,\n schemaIndex,\n );\n },\n\n /**\n * Sync facade (CLIENT-SYNC-001, CLIENT-SYNC-APPLY-001)\n */\n sync,\n\n /**\n * Execute a transaction (CLIENT-TX-001)\n */\n async transact(payload: unknown) {\n guardDestroyed();\n return executeTransact(remote, payload);\n },\n\n /**\n * Execute a mutation (CLIENT-MUT-001, CLIENT-OFFLINE-MUT-001)\n */\n async mutate(mutation: unknown | unknown[]) {\n guardDestroyed();\n await searchProviderInitPromise;\n await storageValidationPromise; // STORAGE-INIT-001: fail fast if stores are missing\n await localOnlyInitPromise; // Ensure hydration state is ready in local-only mode\n return executeMutation(\n remote,\n eventBus,\n getTimestamp,\n mutation,\n resolvedStorage,\n config.plugins || [],\n schema,\n syncEngine,\n config.sync?.offlinability,\n config.clientId,\n debouncerMap,\n config.searchProvider,\n );\n },\n\n /**\n * Subscribe to events\n */\n subscribe(handler: EventHandler, filter?: EventFilter) {\n guardDestroyed();\n const localUnsub = eventBus.subscribe(handler, filter);\n\n // EXT-001: If using extension adapter with subscription manager, register with remote\n if (extensionSubscriptionManager) {\n let remoteUnsub: (() => Promise<void>) | undefined;\n\n // Register with remote subscription manager (async)\n extensionSubscriptionManager\n .registerSubscriber(filter)\n .then((unsub) => {\n remoteUnsub = unsub;\n })\n .catch((err) => {\n console.error(\"Failed to register remote subscription:\", err);\n });\n\n // Return combined unsubscribe that cleans up both local and remote\n return () => {\n localUnsub();\n if (remoteUnsub) {\n remoteUnsub().catch((err) => {\n console.error(\"Failed to unsubscribe from remote:\", err);\n });\n }\n };\n }\n\n return localUnsub;\n },\n\n /**\n * Tear down client: stop sync, close connections, unsubscribe all, release resources (CLN-001)\n */\n async destroy() {\n if (destroyed) return;\n \n // 1. Flush all pending debounced mutations (DEB-001)\n await debouncerMap.flushAll();\n \n // 2. Stop sync engine\n if (syncEngine) {\n syncEngine.stop();\n }\n \n // 3. Dispose all signals\n signalRegistry.disposeAll();\n \n // 4. Close cross-tab relay (TAB-001)\n if (crossTabRelay) {\n crossTabRelay.close();\n }\n \n // 5. Clear event bus\n eventBus.clear();\n \n // 6. Close storage\n if (resolvedStorage) {\n await resolvedStorage.close();\n }\n\n // 7. Dispose search provider (best-effort)\n if (config.searchProvider?.dispose) {\n try {\n await config.searchProvider.dispose();\n } catch {\n // Best-effort cleanup: do not block destroy()\n }\n }\n \n // 8. Set destroyed flag\n destroyed = true;\n },\n\n /**\n * Wipe all local data (CLN-002)\n */\n async clear() {\n guardDestroyed();\n \n if (resolvedStorage) {\n // 1. Clear all data\n await resolvedStorage.clearAll();\n \n // 2. Reset hydration states\n // clearAll() already cleared the hydration state metadata, so all resources\n // are implicitly back to \"notStarted\" (the default)\n // No need to explicitly set them\n }\n },\n\n /**\n * Flush a specific debounced mutation immediately (DEB-001)\n */\n async flush(key?: string) {\n guardDestroyed();\n if (key !== undefined) {\n await debouncerMap.flush(key);\n }\n },\n\n /**\n * Flush all pending debounced mutations immediately (DEB-001)\n */\n async flushAll() {\n guardDestroyed();\n await debouncerMap.flushAll();\n },\n\n /**\n * Export all local records as structured JSON (EXP-001)\n */\n async exportData(options?: { resources?: string[] }): Promise<DatafnExportPayload> {\n guardDestroyed();\n \n if (!resolvedStorage) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Export requires storage adapter\",\n { path: \"exportData\", context: \"exportData\" }\n );\n }\n \n return exportData(resolvedStorage, schema, options);\n },\n\n /**\n * Import records from a structured JSON payload (EXP-002)\n */\n async importData(\n data: DatafnExportPayload, \n options?: { triggerCloneUp?: boolean }\n ): Promise<DatafnImportResult> {\n guardDestroyed();\n \n if (!resolvedStorage) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Import requires storage adapter\",\n { path: \"importData\", context: \"importData\" }\n );\n }\n \n return importData(resolvedStorage, schema, sync, data, options);\n },\n\n async search(params: unknown): Promise<unknown> {\n guardDestroyed();\n await searchProviderInitPromise;\n\n if (typeof params !== \"object\" || params === null || Array.isArray(params)) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Search query must not be empty\",\n { path: \"query\" },\n );\n }\n\n const raw = params as Record<string, unknown>;\n if (typeof raw.query !== \"string\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Search query must not be empty\",\n { path: \"query\" },\n );\n }\n const query = raw.query.trim();\n if (query === \"\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Search query must not be empty\",\n { path: \"query\" },\n );\n }\n if (query.length > 1000) {\n throw createClientError(\n \"LIMIT_EXCEEDED\",\n \"Search query exceeds maximum length\",\n { path: \"query\" },\n );\n }\n\n if (raw.resources !== undefined) {\n if (!Array.isArray(raw.resources)) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: resources must be an array\",\n { path: \"resources\" },\n );\n }\n if (raw.resources.length > 50) {\n throw createClientError(\n \"LIMIT_EXCEEDED\",\n \"Too many resources in search request\",\n { path: \"resources\" },\n );\n }\n }\n\n if (raw.filters !== undefined && (typeof raw.filters !== \"object\" || raw.filters === null || Array.isArray(raw.filters))) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: filters must be an object\",\n { path: \"filters\" },\n );\n }\n\n if (\n raw.limit !== undefined &&\n (typeof raw.limit !== \"number\" || !Number.isFinite(raw.limit) || raw.limit < 1)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: limit must be a positive number\",\n { path: \"limit\" },\n );\n }\n if (\n raw.limitPerResource !== undefined &&\n (typeof raw.limitPerResource !== \"number\" || !Number.isFinite(raw.limitPerResource) || raw.limitPerResource < 1)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: limitPerResource must be a positive number\",\n { path: \"limitPerResource\" },\n );\n }\n\n if (raw.prefix !== undefined && typeof raw.prefix !== \"boolean\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: prefix must be boolean\",\n { path: \"prefix\" },\n );\n }\n if (\n raw.fuzzy !== undefined &&\n typeof raw.fuzzy !== \"boolean\" &&\n (typeof raw.fuzzy !== \"number\" || !Number.isFinite(raw.fuzzy) || raw.fuzzy < 0)\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: fuzzy must be boolean or a non-negative number\",\n { path: \"fuzzy\" },\n );\n }\n if (raw.fieldBoosts !== undefined) {\n const fieldBoostsValue = raw.fieldBoosts;\n const isPlainObject =\n typeof fieldBoostsValue === \"object\" &&\n fieldBoostsValue !== null &&\n !Array.isArray(fieldBoostsValue) &&\n (Object.getPrototypeOf(fieldBoostsValue) === Object.prototype ||\n Object.getPrototypeOf(fieldBoostsValue) === null);\n if (!isPlainObject) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: fieldBoosts must be an object\",\n { path: \"fieldBoosts\" },\n );\n }\n const entries = Object.entries(fieldBoostsValue as Record<string, unknown>);\n if (entries.length > 100) {\n throw createClientError(\n \"LIMIT_EXCEEDED\",\n \"Too many fieldBoosts entries in search request\",\n { path: \"fieldBoosts\" },\n );\n }\n for (const [field, value] of entries) {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: fieldBoosts values must be finite positive numbers\",\n { path: `fieldBoosts.${field}` },\n );\n }\n }\n }\n\n if (\n raw.source !== undefined &&\n raw.source !== \"auto\" &&\n raw.source !== \"local\" &&\n raw.source !== \"remote\"\n ) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid request: source must be one of auto, local, remote\",\n { path: \"source\" },\n );\n }\n\n const limit = Math.min(\n typeof raw.limit === \"number\" ? raw.limit : 50,\n 10_000,\n );\n const limitPerResource = Math.min(\n typeof raw.limitPerResource === \"number\" ? raw.limitPerResource : limit,\n 1_000,\n );\n const resources = Array.isArray(raw.resources) ? (raw.resources as string[]) : undefined;\n const fields = Array.isArray(raw.fields) ? (raw.fields as string[]) : undefined;\n const prefix = raw.prefix as boolean | undefined;\n const fuzzy = raw.fuzzy as boolean | number | undefined;\n const fieldBoosts = raw.fieldBoosts as Record<string, number> | undefined;\n const source = (raw.source ?? \"auto\") as \"auto\" | \"local\" | \"remote\";\n const signal = raw.signal as AbortSignal | undefined;\n assertSearchNotAborted(signal);\n\n const hasRemote = !!(config.sync?.remote || config.sync?.remoteAdapter);\n const isOffline = typeof navigator !== \"undefined\" && navigator.onLine === false;\n const hasLocalSearch = typeof config.searchProvider?.searchAll === \"function\";\n\n const runRemoteSearch = async (): Promise<unknown> => {\n if (typeof (remote as any).search === \"function\") {\n return (remote as any).search({\n ...raw,\n query,\n limit,\n limitPerResource,\n signal,\n });\n }\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"Remote adapter does not support search\",\n { path: \"search\" },\n );\n };\n\n const runLocalSearch = async (): Promise<{ results: Array<{ id: string; resource: string; score: number; data: Record<string, unknown> }> }> => {\n const searchAll = config.searchProvider?.searchAll;\n if (!searchAll) {\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"Local search unavailable\",\n { path: \"source\" },\n );\n }\n await storageValidationPromise;\n await localOnlyInitPromise;\n const candidates = await (searchAll as any)({\n query,\n resources,\n fields,\n limit,\n limitPerResource,\n prefix,\n fuzzy,\n fieldBoosts,\n signal,\n });\n assertSearchNotAborted(signal);\n\n const filters =\n typeof raw.filters === \"object\" && raw.filters !== null && !Array.isArray(raw.filters)\n ? (raw.filters as Record<string, Record<string, unknown>>)\n : undefined;\n const select = Array.isArray(raw.select) ? (raw.select as string[]) : undefined;\n const results: Array<{ id: string; resource: string; score: number; data: Record<string, unknown> }> = [];\n\n for (const candidate of candidates) {\n assertSearchNotAborted(signal);\n const resource = String(candidate.resource);\n const id = String(candidate.id);\n let row: Record<string, unknown> | null = null;\n if (resolvedStorage) {\n row = await resolvedStorage.getRecord(resource, id);\n if (!row) continue;\n const resourceFilter = filters?.[resource];\n if (resourceFilter && !coreEvaluateFilter(row, resourceFilter)) {\n continue;\n }\n }\n results.push({\n id,\n resource,\n score: candidate.score,\n data: row ? applySearchSelect(row, select) : {},\n });\n }\n\n results.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n if (a.resource !== b.resource) return a.resource < b.resource ? -1 : 1;\n return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;\n });\n\n return { results: results.slice(0, limit) };\n };\n\n if (source === \"local\") {\n if (!hasLocalSearch) {\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"Local search unavailable\",\n { path: \"source\" },\n );\n }\n return runLocalSearch();\n }\n\n if (source === \"remote\") {\n if (!hasRemote || isOffline || typeof (remote as any).search !== \"function\") {\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"Remote search unavailable\",\n { path: \"source\" },\n );\n }\n return runRemoteSearch();\n }\n\n if (hasLocalSearch) {\n return runLocalSearch();\n }\n if (hasRemote && !isOffline) {\n return runRemoteSearch();\n }\n\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"Search unavailable offline without search provider\",\n { path: \"search\" },\n );\n },\n\n /**\n * Check storage health and verify hydration state consistency (HEAL-001)\n */\n async checkHealth(): Promise<{ ok: boolean; issues: string[]; action?: \"none\" | \"reclone\" }> {\n guardDestroyed();\n \n // Wait for local-only init to complete\n await localOnlyInitPromise;\n \n if (!resolvedStorage) {\n return { ok: true, issues: [], action: \"none\" };\n }\n\n // 1. Check storage health\n const storageHealth = await resolvedStorage.healthCheck();\n const issues = [...storageHealth.issues];\n\n // 2. Check hydration state consistency\n for (const resource of schema.resources) {\n if (resource.isRemoteOnly) continue;\n \n const state = await resolvedStorage.getHydrationState(resource.name);\n \n // Detect stuck hydrating state\n // Note: We don't have a reliable way to check if sync is actively cloning,\n // so we detect this as a potential issue but not a hard failure.\n // In production, this would need coordination with SyncEngine state.\n if (state === \"hydrating\") {\n issues.push(`Resource ${resource.name} is in hydrating state (may be stuck)`);\n }\n }\n\n const action = issues.length > 0 ? \"reclone\" : \"none\";\n return { ok: issues.length === 0, issues, action };\n },\n };\n\n // Create signal registry (CLIENT-SIGNAL-001, SIG-002)\n const signalRegistry = new SignalRegistry(client, eventBus, schema);\n\n // Create table registry with client and signal registry (CLIENT-REG-001)\n const registry = new TableRegistry<S>(\n schema as S,\n client as any,\n signalRegistry,\n generateId,\n );\n\n // Set table method now that registry exists\n (client as any).table = (name: string) => registry.getTable(name);\n\n // Create KV API (KV-002)\n const kvTable = registry.getTable(KV_RESOURCE_NAME);\n const kvApi = createKvApi({\n storage: resolvedStorage,\n kvTable,\n eventBus,\n clientId: config.clientId,\n debouncerMap,\n });\n (client as any).kv = kvApi;\n\n // Wrap client in Proxy for table property access (CLIENT-REG-001, CLIENT-REG-002)\n return new Proxy(client, {\n get(target, prop) {\n // Handle reserved keys - return undefined without throwing\n if (typeof prop === \"string\" && RESERVED_KEYS.has(prop)) {\n return undefined;\n }\n\n // If property exists on target, return it\n if (prop in target) {\n return target[prop as keyof typeof target];\n }\n\n // Check if it's a table name\n if (typeof prop === \"string\") {\n return registry.getTable(prop);\n }\n\n return undefined;\n },\n }) as DatafnClient<S>;\n}\n\n/**\n * Create a DataFn client with built-in context switching.\n *\n * The returned client is a stable Proxy reference that always delegates to the\n * current underlying client. Use `switchContext()` to switch auth, sync mode,\n * or storage without replacing the reference. Use `subscribeClient()` to react\n * to switches (e.g. to recreate signals in framework adapters).\n */\nexport function createDatafnClient<S extends DatafnSchema>(\n config: DatafnClientConfig<S>,\n): DatafnClient<S> {\n let realClient = _buildRawClient(config);\n let currentConfig = config;\n let isDestroyed = false;\n let switchInProgress = false;\n let switchQueue: Array<() => Promise<void>> = [];\n const subscribers = new Set<(c: DatafnClient<S>) => void>();\n\n const liveRegistry = new LiveSignalRegistry();\n\n // Cache of wrapped table handles, keyed by table name.\n // Ensures `client.table(\"task\") === client.task` (identity preserved across calls).\n const wrappedTableCache = new Map<string, DatafnTable<S, any>>();\n // Cached wrapped KV handle (singleton per client proxy).\n let wrappedKv: DatafnKvApi | null = null;\n\n // Return a cached wrapped table handle for `tableName`.\n // The handle intercepts .signal() to return LiveSignals; all other props delegate\n // dynamically to the current realClient's raw table (so they remain correct after\n // performSwitch reassigns realClient).\n //\n // CRITICAL: factory closures capture `realClient` by reference (the `let` variable).\n // After performSwitch reassigns realClient, re-calling factory() uses the new client.\n // Do NOT destructure or snapshot realClient into a local const inside the factory.\n function getOrCreateWrappedTable(tableName: string): DatafnTable<S, any> {\n const cached = wrappedTableCache.get(tableName);\n if (cached) return cached;\n\n // Validate the table name upfront — throws DFQL_UNKNOWN_RESOURCE if not in schema.\n // This preserves the same eager-throw behavior as direct realClient.table() calls.\n realClient.table(tableName);\n\n const wrapped = new Proxy(Object.create(null), {\n get(_proxyTarget, prop) {\n if (prop === \"signal\") {\n return (query: unknown, options?: { disableOptimistic?: boolean }) => {\n const currentRawTable = realClient.table(tableName);\n const version = (currentRawTable as any).version as number;\n const factory = () => realClient.table(tableName).signal(query as any, options);\n return liveRegistry.getOrCreateTableSignal(tableName, version, query, options, factory);\n };\n }\n // Delegate all other property accesses to the current realClient's raw table.\n // This ensures non-signal methods (mutate, query, subscribe) are always bound\n // to the current underlying client, not a stale snapshot.\n return (realClient.table(tableName) as any)[prop];\n },\n }) as DatafnTable<S, any>;\n\n wrappedTableCache.set(tableName, wrapped);\n return wrapped;\n }\n\n function getOrCreateWrappedKv(): DatafnKvApi {\n if (!wrappedKv) {\n wrappedKv = new Proxy(Object.create(null), {\n get(_proxyTarget, prop) {\n if (prop === \"signal\") {\n return (key: string, options?: { defaultValue?: unknown }) => {\n const factory = () => realClient.kv.signal(key, options);\n return liveRegistry.getOrCreateKvSignal(key, factory);\n };\n }\n return (realClient.kv as any)[prop];\n },\n }) as DatafnKvApi;\n }\n return wrappedKv;\n }\n\n function isTableLike(val: unknown): val is DatafnTable<S, any> {\n return (\n val !== null &&\n typeof val === \"object\" &&\n typeof (val as any).signal === \"function\" &&\n typeof (val as any).query === \"function\" &&\n typeof (val as any).name === \"string\" &&\n typeof (val as any).version === \"number\"\n );\n }\n\n // outer is declared with let so closures can reference it before assignment\n let outer: DatafnClient<S>;\n\n async function performSwitch(overrides: SwitchContextOverride): Promise<void> {\n await realClient.destroy();\n\n // Build new config by applying overrides\n const newConfig: DatafnClientConfig<S> = {\n ...currentConfig,\n ...(overrides.namespace !== undefined ? { namespace: overrides.namespace } : {}),\n ...(overrides.sync !== undefined ? { sync: overrides.sync } : {}),\n ...(overrides.storage !== undefined ? { storage: overrides.storage } : {}),\n };\n currentConfig = newConfig;\n realClient = _buildRawClient(newConfig);\n\n // Rebind all LiveSignals to the new realClient BEFORE notifying subscribers (PROXY-006).\n // Ordering is critical: factories use the updated realClient, and subscribers see rebound signals.\n liveRegistry.rebindAll();\n\n // Notify subscribers with the stable outer proxy\n for (const fn of subscribers) {\n fn(outer);\n }\n\n // Auto-start sync when switching into sync mode\n if (newConfig.sync?.mode === \"sync\") {\n await realClient.sync.start();\n }\n }\n\n async function switchContextFn(overrides: SwitchContextOverride): Promise<void> {\n if (isDestroyed) {\n throw createClientError(\"DFQL_INVALID\", \"Cannot switch context on a destroyed client\", { path: \"client\" });\n }\n\n if (switchInProgress) {\n return new Promise<void>((resolve, reject) => {\n switchQueue.push(async () => {\n try { await performSwitch(overrides); resolve(); }\n catch (err) { reject(err); }\n });\n });\n }\n\n switchInProgress = true;\n try {\n await performSwitch(overrides);\n while (switchQueue.length > 0) {\n const next = switchQueue.shift();\n if (next) await next();\n }\n } finally {\n switchInProgress = false;\n }\n }\n\n function currentNamespaceFn(): string | undefined {\n return currentConfig.namespace;\n }\n\n function subscribeClientFn(fn: (c: DatafnClient<S>) => void): () => void {\n subscribers.add(fn);\n fn(outer); // Fire immediately with current (stable) proxy\n return () => subscribers.delete(fn);\n }\n\n async function destroyFn(): Promise<void> {\n // Wait for any in-progress switch to complete\n while (switchInProgress) {\n await new Promise<void>(r => setTimeout(r, 10));\n }\n switchQueue = [];\n isDestroyed = true;\n subscribers.clear();\n liveRegistry.disposeAll(); // PROXY-007: dispose all LiveSignals before destroying underlying client\n return realClient.destroy();\n }\n\n outer = new Proxy(function () {} as unknown as DatafnClient<S>, {\n get(_target, prop) {\n if (prop === \"switchContext\") return switchContextFn;\n if (prop === \"currentNamespace\") return currentNamespaceFn;\n if (prop === \"subscribeClient\") return subscribeClientFn;\n if (prop === \"destroy\") return destroyFn;\n\n if (prop === \"table\") {\n return (name: string) => getOrCreateWrappedTable(name);\n }\n\n if (prop === \"kv\") {\n return getOrCreateWrappedKv();\n }\n\n const val = (realClient as any)[prop];\n\n if (isTableLike(val)) {\n return getOrCreateWrappedTable((val as any).name);\n }\n\n // Bind functions to realClient so 'this' is correct if ever needed\n if (typeof val === \"function\") return val.bind(realClient);\n return val;\n },\n has(_target, prop) {\n return (\n prop === \"switchContext\" ||\n prop === \"currentNamespace\" ||\n prop === \"subscribeClient\" ||\n prop in realClient\n );\n },\n ownKeys(_target) {\n return [...Reflect.ownKeys(realClient), \"switchContext\", \"currentNamespace\", \"subscribeClient\"];\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (prop === \"switchContext\" || prop === \"currentNamespace\" || prop === \"subscribeClient\") {\n return { configurable: true, enumerable: true, writable: true, value: undefined };\n }\n return Object.getOwnPropertyDescriptor(realClient, prop);\n },\n }) as DatafnClient<S>;\n\n return outer;\n}\n","/**\n * Event filtering logic\n */\n\nimport type { DatafnEvent } from \"@datafn/core\";\n\nexport interface EventFilter {\n type?: string | string[];\n resource?: string | string[];\n ids?: string | string[];\n mutationId?: string | string[];\n action?: string | string[]; // CLIENT-FILTER-001\n fields?: string | string[]; // CLIENT-FILTER-001\n contextKeys?: string[]; // CLIENT-FILTER-001\n context?: Record<string, unknown>; // EVT-002: shallow equality matching\n}\n\n/**\n * Normalize a filter to a canonical form for deterministic comparison\n */\nexport function normalizeFilter(filter: EventFilter): EventFilter {\n const normalized: EventFilter = {};\n\n // Normalize arrays and sort them\n if (filter.type !== undefined) {\n normalized.type = Array.isArray(filter.type)\n ? [...filter.type].sort()\n : filter.type;\n }\n if (filter.resource !== undefined) {\n normalized.resource = Array.isArray(filter.resource)\n ? [...filter.resource].sort()\n : filter.resource;\n }\n if (filter.ids !== undefined) {\n normalized.ids = Array.isArray(filter.ids)\n ? [...filter.ids].sort()\n : filter.ids;\n }\n if (filter.mutationId !== undefined) {\n normalized.mutationId = Array.isArray(filter.mutationId)\n ? [...filter.mutationId].sort()\n : filter.mutationId;\n }\n if (filter.action !== undefined) {\n normalized.action = Array.isArray(filter.action)\n ? [...filter.action].sort()\n : filter.action;\n }\n if (filter.fields !== undefined) {\n normalized.fields = Array.isArray(filter.fields)\n ? [...filter.fields].sort()\n : filter.fields;\n }\n if (filter.contextKeys !== undefined) {\n normalized.contextKeys = [...filter.contextKeys].sort();\n }\n if (filter.context !== undefined) {\n // Sort context keys for deterministic serialization\n normalized.context = filter.context;\n }\n\n return normalized;\n}\n\n/**\n * Check if an event matches the filter\n */\nexport function matchesFilter(\n event: DatafnEvent,\n filter?: EventFilter,\n): boolean {\n if (!filter) return true;\n\n // Match type\n if (filter.type !== undefined) {\n if (Array.isArray(filter.type)) {\n if (!filter.type.includes(event.type)) return false;\n } else {\n if (event.type !== filter.type) return false;\n }\n }\n\n // Match resource\n if (filter.resource !== undefined && event.resource) {\n if (Array.isArray(filter.resource)) {\n if (!filter.resource.includes(event.resource)) return false;\n } else {\n if (event.resource !== filter.resource) return false;\n }\n }\n\n // Match ids (any of the event ids must match)\n if (filter.ids !== undefined && event.ids) {\n const filterIds = Array.isArray(filter.ids) ? filter.ids : [filter.ids];\n const eventIds = Array.isArray(event.ids) ? event.ids : [event.ids];\n const hasMatch = eventIds.some((id) => filterIds.includes(id));\n if (!hasMatch) return false;\n }\n\n // Match mutationId\n if (filter.mutationId !== undefined && event.mutationId) {\n if (Array.isArray(filter.mutationId)) {\n if (!filter.mutationId.includes(event.mutationId)) return false;\n } else {\n if (event.mutationId !== filter.mutationId) return false;\n }\n }\n\n // Match action (CLIENT-FILTER-001)\n if (filter.action !== undefined && event.action) {\n if (Array.isArray(filter.action)) {\n if (!filter.action.includes(event.action)) return false;\n } else {\n if (event.action !== filter.action) return false;\n }\n }\n\n // Match fields - non-empty intersection (CLIENT-FILTER-001)\n if (filter.fields !== undefined && event.fields) {\n const filterFields = Array.isArray(filter.fields)\n ? filter.fields\n : [filter.fields];\n const eventFields = Array.isArray(event.fields)\n ? event.fields\n : [event.fields];\n\n // Check for non-empty intersection\n const hasIntersection = filterFields.some((f) => eventFields.includes(f));\n if (!hasIntersection) return false;\n }\n\n // Match contextKeys - all must exist (CLIENT-FILTER-001)\n if (filter.contextKeys !== undefined && filter.contextKeys.length > 0) {\n if (!event.context || typeof event.context !== \"object\") {\n return false;\n }\n\n const ctx = event.context as Record<string, unknown>;\n const allExist = filter.contextKeys.every((key) => key in ctx);\n if (!allExist) return false;\n }\n\n // Match context - shallow equality (EVT-002)\n if (filter.context !== undefined) {\n if (!event.context || typeof event.context !== \"object\") {\n return false;\n }\n\n const ctx = event.context as Record<string, unknown>;\n // Check that all key/value pairs in filter.context match event.context\n for (const [key, value] of Object.entries(filter.context)) {\n if (ctx[key] !== value) {\n return false;\n }\n }\n }\n\n return true;\n}\n","/**\n * In-process event bus\n */\n\nimport type { DatafnEvent } from \"@datafn/core\";\nimport { matchesFilter, type EventFilter } from \"./filter.js\";\n\nexport type EventHandler = (event: DatafnEvent) => void;\n\ninterface Subscription {\n id: number;\n handler: EventHandler;\n filter?: EventFilter;\n}\n\nexport interface EventBusOptions {\n /**\n * Error handler called when a subscriber throws an error.\n * Default: logs to console.error\n */\n onError?: (error: unknown, event: DatafnEvent) => void;\n}\n\n/**\n * Simple in-process event bus with fault-tolerant delivery\n */\nexport class EventBus {\n private subscriptions: Subscription[] = [];\n private nextId = 1;\n private onError: (error: unknown, event: DatafnEvent) => void;\n\n constructor(options?: EventBusOptions) {\n this.onError =\n options?.onError ||\n ((error: unknown, event: DatafnEvent) => {\n console.error(\"[datafn] Event handler error:\", error, \"event:\", event);\n });\n }\n\n /**\n * Subscribe to events with optional filtering\n */\n subscribe(handler: EventHandler, filter?: EventFilter): () => void {\n const subscription: Subscription = {\n id: this.nextId++,\n handler,\n filter,\n };\n\n this.subscriptions.push(subscription);\n\n // Return unsubscribe function\n return () => {\n this.subscriptions = this.subscriptions.filter(\n (s) => s.id !== subscription.id\n );\n };\n }\n\n /**\n * Emit an event to all matching subscribers.\n * Errors in handlers are isolated - a throwing handler will not prevent delivery to other handlers.\n */\n emit(event: DatafnEvent): void {\n // CLI-005: Copy before iteration so unsubscribes during emit don't skip/crash handlers\n const subs = [...this.subscriptions];\n for (const subscription of subs) {\n if (matchesFilter(event, subscription.filter)) {\n try {\n subscription.handler(event);\n } catch (error) {\n this.onError(error, event);\n }\n }\n }\n }\n\n /**\n * Remove all subscriptions\n */\n clear(): void {\n this.subscriptions = [];\n }\n}\n","/**\n * DataFn Client Error Types\n */\n\nimport type { DatafnErrorCode } from \"@datafn/core\";\n\nexport type DatafnClientError = {\n code: DatafnErrorCode | \"TRANSPORT_ERROR\";\n message: string;\n details: { path: string; [key: string]: unknown };\n};\n\n/**\n * Build and throw a DatafnClientError.\n */\nexport function throwClientError(\n code: DatafnClientError[\"code\"],\n message: string,\n details: { path: string; [key: string]: unknown },\n): never {\n const error: DatafnClientError = {\n code,\n message,\n details,\n };\n throw error;\n}\n\n/**\n * Alias for `throwClientError`.\n */\nexport const createClientError: typeof throwClientError = throwClientError;\n/**\n * Check if an error is a transport/retriable error.\n * Returns true for network errors, timeouts, or explicit TRANSPORT_ERROR code.\n * Returns false for logic errors (validation, auth, missing resource, etc).\n */\nexport function isTransportError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n\n const err = error as any;\n\n // Explicit DataFn code\n if (err.code === \"TRANSPORT_ERROR\") return true;\n\n // Network/Fetch errors match common patterns\n // 1. fetch() throws TypeError on network failure\n // 2. AbortError on timeout\n if (err.name === \"TypeError\" && err.message.includes(\"fetch\")) return true;\n if (err.name === \"AbortError\") return true; // Timeout\n\n // Check failure status if available (e.g. 503, 504)\n // Note: DataFnRemoteAdapter usually unwraps to DataFnError, so status might not be here directly\n // unless wrapped.\n\n return false;\n}\n","/**\n * DataFn Table Handle\n *\n * Represents a table/resource from the schema with methods for query, mutation, signals, and subscriptions.\n */\n\nimport type {\n DatafnSchema,\n DatafnSignal,\n DfqlQueryFragment,\n DfqlMutationFragment,\n DfqlTransact,\n} from \"@datafn/core\";\nimport { resolveCapabilities } from \"@datafn/core\";\nimport { createClientError } from \"../errors.js\";\nimport type { EventHandler } from \"../events/bus.js\";\nimport type { EventFilter } from \"../events/filter.js\";\nimport type { SignalRegistry } from \"../signals/querySignal.js\";\nimport {\n buildTableOperationMutation,\n buildShareMutation,\n buildUnshareMutation,\n buildPrincipalShareMutation,\n buildPrincipalUnshareMutation,\n type PrincipalShareMutationInput,\n type PrincipalUnshareMutationInput,\n type TableOperation,\n} from \"../mutate.js\";\nimport {\n buildGetPermissionsQuery,\n type PermissionEntry,\n} from \"../query.js\";\n\ntype QueryMetadata = {\n includeTrashed?: boolean;\n includeArchived?: boolean;\n};\n\nconst DFQL_PRINCIPAL_INVALID_CODE = \"DFQL_PRINCIPAL_INVALID\" as any;\nconst DFQL_SHARE_SCOPE_INVALID_CODE = \"DFQL_SHARE_SCOPE_INVALID\" as any;\nconst LEGACY_SHARE_WARNING =\n \"Deprecated shareWith.userId is accepted for compatibility; use shareWith.principalId\";\n\nexport interface DatafnTable<\n S extends DatafnSchema = DatafnSchema,\n Name extends string = string,\n TRecord = unknown,\n> {\n name: Name;\n version: number;\n\n query(q: DfqlQueryFragment & { metadata?: QueryMetadata }): Promise<unknown>;\n mutate(m: DfqlMutationFragment | DfqlMutationFragment[]): Promise<unknown>;\n delete(id: string): Promise<unknown>;\n trash?: (id: string) => Promise<unknown>;\n restore?: (id: string) => Promise<unknown>;\n archive?: (id: string) => Promise<unknown>;\n unarchive?: (id: string) => Promise<unknown>;\n share?: {\n (id: string, userId: string, level: string): Promise<unknown>;\n (input: PrincipalShareMutationInput): Promise<unknown>;\n };\n unshare?: {\n (id: string, userId: string): Promise<unknown>;\n (input: PrincipalUnshareMutationInput): Promise<unknown>;\n };\n getPermissions?: (id: string) => Promise<PermissionEntry[]>;\n transact(payload: DfqlTransact): Promise<unknown>;\n signal(q: DfqlQueryFragment, options?: { disableOptimistic?: boolean }): DatafnSignal<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n}\n\n// Forward declaration for client interface\ninterface ClientWithQuery {\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(m: unknown | unknown[]): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n subscribe(handler: EventHandler, filter?: EventFilter): () => void;\n}\n\n/**\n * Create a table handle (internal factory)\n */\nexport function createTable<S extends DatafnSchema>(\n name: string,\n version: number,\n client: ClientWithQuery,\n signalRegistry: SignalRegistry,\n generateId: (params: { resource: string; idPrefix?: string }) => string,\n schema: S,\n): DatafnTable<S, string> {\n const resource = schema.resources.find((r) => r.name === name);\n const resolvedCapabilities = resource\n ? resolveCapabilities(\n schema.capabilities as any,\n resource.capabilities as any,\n )\n : [];\n\n const executeOperation = async (\n operation: TableOperation,\n id: string,\n ): Promise<unknown> =>\n client.mutate(buildTableOperationMutation(name, version, operation, id));\n\n const table: DatafnTable<S, string> = {\n name,\n version,\n\n /**\n * Execute a query with resource/version merged (CLIENT-QUERY-001)\n */\n async query(\n q: DfqlQueryFragment & { metadata?: QueryMetadata },\n ): Promise<unknown> {\n // Merge query fragment with table resource/version\n const fragment = (typeof q === \"object\" && q !== null ? q : {}) as Record<\n string,\n unknown\n >;\n\n // Remove resource/version from fragment if present (table is authoritative)\n const { resource: _r, version: _v, ...rest } = fragment;\n\n // Build full query\n const fullQuery = {\n resource: name,\n version,\n ...rest,\n };\n\n // Delegate to client.query and return single result\n return client.query(fullQuery);\n },\n\n /**\n * Execute a mutation with resource/version merged (CLIENT-MUT-001)\n */\n async mutate(\n m: DfqlMutationFragment | DfqlMutationFragment[],\n ): Promise<unknown> {\n // Normalize to array for processing if needed, but here we just pass through\n // Since executeMutation handles single or array, we just need to preserve that structure\n // But we need to inject resource/version into each item if it's an array, or the item itself\n\n const mutations = Array.isArray(m) ? m : [m];\n\n const fullMutations = mutations.map((fragment) => {\n const {\n resource: _r,\n version: _v,\n ...rest\n } = fragment as Record<string, unknown>;\n const mutation = {\n resource: name,\n version,\n ...rest,\n } as Record<string, unknown>;\n\n // Auto-generate ID for insert operations if not provided (API-001)\n if (mutation.operation === \"insert\" && !mutation.id) {\n // Find resource in schema to get idPrefix\n const resource = schema.resources.find((r) => r.name === name);\n const idPrefix = resource?.idPrefix;\n\n // Generate ID with resource and idPrefix\n const generatedId = generateId({ resource: name, idPrefix });\n\n // Validate prefix (API-001)\n const expectedPrefix = idPrefix || name;\n if (!generatedId.startsWith(`${expectedPrefix}:`)) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid id: does not match required prefix\",\n { path: \"id\" },\n );\n }\n\n mutation.id = generatedId;\n }\n\n return mutation;\n });\n\n // Delegate to client.mutate and return single result (or array if input was array)\n const result = await client.mutate(\n Array.isArray(m) ? fullMutations : fullMutations[0],\n );\n return result;\n },\n\n async delete(id: string): Promise<unknown> {\n return executeOperation(\"delete\", id);\n },\n\n /**\n * Execute a transaction (CLIENT-TX-001)\n */\n async transact(payload: DfqlTransact): Promise<unknown> {\n // Delegate directly to client.transact without modification\n // Note: client.transact expects unknown but at runtime/logic level it handles it.\n // Ideally client.transact should also be typed; cast here to keep table API ergonomic.\n return client.transact(payload as any);\n },\n\n /**\n * Create reactive query signal (CLIENT-SIGNAL-001, SIG-003)\n */\n signal(q: DfqlQueryFragment, options?: { disableOptimistic?: boolean }): DatafnSignal<unknown> {\n // Merge query fragment with table resource/version\n const fragment = (typeof q === \"object\" && q !== null ? q : {}) as Record<\n string,\n unknown\n >;\n\n // Remove resource/version from fragment if present (table is authoritative)\n const { resource: _r, version: _v, ...rest } = fragment;\n\n // Build full query\n const fullQuery = {\n resource: name,\n version,\n ...rest,\n };\n\n // Get or create signal from registry (ensures caching by dfqlKey)\n return signalRegistry.getSignal(fullQuery, options);\n },\n\n /**\n * Subscribe to events for this table's resource (CLIENT-SUB-001)\n */\n subscribe(handler: EventHandler, filter?: EventFilter): () => void {\n // Inject resource filter (table is authoritative)\n const tableFilter: EventFilter = {\n ...filter,\n resource: name, // Always use table's resource, ignore user-provided\n };\n\n return client.subscribe(handler, tableFilter);\n },\n };\n\n if (resolvedCapabilities.some((capability) => capability === \"trash\")) {\n table.trash = async (id: string): Promise<unknown> =>\n executeOperation(\"trash\", id);\n table.restore = async (id: string): Promise<unknown> =>\n executeOperation(\"restore\", id);\n }\n\n if (resolvedCapabilities.some((capability) => capability === \"archivable\")) {\n table.archive = async (id: string): Promise<unknown> =>\n executeOperation(\"archive\", id);\n table.unarchive = async (id: string): Promise<unknown> =>\n executeOperation(\"unarchive\", id);\n }\n\n const hasShareableCapability = resolvedCapabilities.some(\n (capability) =>\n typeof capability === \"object\" &&\n capability !== null &&\n \"shareable\" in (capability as Record<string, unknown>),\n );\n if (hasShareableCapability) {\n table.share = (async (...args: unknown[]): Promise<unknown> => {\n if (\n args.length === 3 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\" &&\n typeof args[2] === \"string\"\n ) {\n console.warn(LEGACY_SHARE_WARNING, {\n code: \"DFQL_LEGACY_API_DEPRECATED\",\n operation: \"share\",\n path: \"shareWith.userId\",\n replacement: \"shareWith.principalId\",\n });\n return client.mutate(\n buildShareMutation(name, version, args[0], args[1], args[2]),\n );\n }\n\n const input = args[0] as PrincipalShareMutationInput | undefined;\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n throw createClientError(\"DFQL_INVALID\", \"Invalid share arguments\", {\n path: \"shareWith\",\n });\n }\n if (typeof input.principalId !== \"string\" || input.principalId.trim().length === 0) {\n throw createClientError(DFQL_PRINCIPAL_INVALID_CODE, \"principalId must be non-empty string\", {\n path: \"shareWith.principalId\",\n });\n }\n if (typeof input.level !== \"string\") {\n throw createClientError(\"DFQL_INVALID\", \"Invalid DFQL: shareWith.level must be string\", {\n path: \"shareWith.level\",\n });\n }\n const scope = input.scope ?? \"record\";\n if (scope !== \"record\" && scope !== \"resource\") {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"scope must be either record or resource\", {\n path: \"scope\",\n });\n }\n if (scope === \"record\") {\n if (typeof input.id !== \"string\" || input.id.length === 0) {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"record scope share must include id\", {\n path: \"id\",\n });\n }\n } else if (input.id !== undefined) {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"resource scope share must omit id\", {\n path: \"id\",\n });\n }\n\n return client.mutate(\n buildPrincipalShareMutation(name, version, {\n id: input.id,\n scope,\n principalId: input.principalId,\n level: input.level,\n }),\n );\n }) as DatafnTable<S, string>[\"share\"];\n table.unshare = (async (...args: unknown[]): Promise<unknown> => {\n if (\n args.length === 2 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\"\n ) {\n console.warn(LEGACY_SHARE_WARNING, {\n code: \"DFQL_LEGACY_API_DEPRECATED\",\n operation: \"unshare\",\n path: \"shareWith.userId\",\n replacement: \"shareWith.principalId\",\n });\n return client.mutate(buildUnshareMutation(name, version, args[0], args[1]));\n }\n\n const input = args[0] as PrincipalUnshareMutationInput | undefined;\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n throw createClientError(\"DFQL_INVALID\", \"Invalid unshare arguments\", {\n path: \"shareWith\",\n });\n }\n if (typeof input.principalId !== \"string\" || input.principalId.trim().length === 0) {\n throw createClientError(DFQL_PRINCIPAL_INVALID_CODE, \"principalId must be non-empty string\", {\n path: \"shareWith.principalId\",\n });\n }\n const scope = input.scope ?? \"record\";\n if (scope !== \"record\" && scope !== \"resource\") {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"scope must be either record or resource\", {\n path: \"scope\",\n });\n }\n if (scope === \"record\") {\n if (typeof input.id !== \"string\" || input.id.length === 0) {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"record scope share must include id\", {\n path: \"id\",\n });\n }\n } else if (input.id !== undefined) {\n throw createClientError(DFQL_SHARE_SCOPE_INVALID_CODE, \"resource scope share must omit id\", {\n path: \"id\",\n });\n }\n\n return client.mutate(\n buildPrincipalUnshareMutation(name, version, {\n id: input.id,\n scope,\n principalId: input.principalId,\n }),\n );\n }) as DatafnTable<S, string>[\"unshare\"];\n table.getPermissions = async (id: string): Promise<PermissionEntry[]> =>\n client.query(buildGetPermissionsQuery(name, version, id)) as Promise<PermissionEntry[]>;\n }\n\n return table;\n}\n","/**\n * Remote Response Unwrapping Utilities\n *\n * Handles both wrapped (DatafnEnvelope) and unwrapped server responses.\n */\n\nimport { createClientError } from \"../errors.js\";\n\n/**\n * Unwrap a remote response that may be wrapped in DatafnEnvelope or unwrapped.\n *\n * - If wrapped success `{ ok: true, result }`, return `result`\n * - If wrapped error `{ ok: false, error }`, throw DatafnClientError\n * - If unwrapped query result `{ data, nextCursor }`, return as-is\n * - If unwrapped aggregate result `{ groups, nextCursor }`, return as-is\n * - Otherwise throw TRANSPORT_ERROR\n */\nexport function unwrapRemoteSuccess<T>(response: unknown): T {\n if (typeof response !== \"object\" || response === null) {\n createClientError(\n \"TRANSPORT_ERROR\",\n \"Transport error: unexpected response shape\",\n { path: \"$\" }\n );\n }\n\n const resp = response as Record<string, unknown>;\n\n // Check for wrapped envelope\n if (\"ok\" in resp) {\n if (resp.ok === true && \"result\" in resp) {\n // Wrapped success\n return resp.result as T;\n } else if (resp.ok === false && \"error\" in resp) {\n // Wrapped error\n const error = resp.error as {\n code?: string;\n message?: string;\n details?: { path?: string; [key: string]: unknown };\n };\n\n createClientError(\n (error.code as any) || \"INTERNAL\",\n error.message || \"Unknown error\",\n (error.details as any) || { path: \"$\" }\n );\n }\n }\n\n // Check for unwrapped query result\n if (\"data\" in resp && \"nextCursor\" in resp) {\n return response as T;\n }\n\n // Check for unwrapped aggregate result\n if (\"groups\" in resp && \"nextCursor\" in resp) {\n return response as T;\n }\n\n // Unknown shape\n createClientError(\n \"TRANSPORT_ERROR\",\n \"Transport error: unexpected response shape\",\n { path: \"$\" }\n );\n}\n","/**\n * Offline Mutation Logic\n *\n * Handles offline mutations by:\n * 1. Appending to offline changelog\n * 2. Performing optimistic local write to storage\n * 3. Supporting relation mutations (relate, modifyRelation, unrelate)\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport { createClientError } from \"../errors.js\";\nimport { getJoinStoreKey, normalizeRelationPayload, findRelationBidirectional } from \"@datafn/core\";\nimport {\n injectCapabilityFieldsForOptimisticRecord,\n sanitizeCapabilityReadonlyFields,\n} from \"../capability-fields.js\";\n\n/**\n * Handle a mutation when remote is unavailable.\n *\n * @param storage Storage adapter\n * @param schema Schema definition (required for relation operations)\n * @param mutation The full mutation object (including resource, version, clientId, mutationId)\n * @param timestampMs Client timestamp\n * @returns Optimistic mutation result\n */\nexport async function handleOfflineMutation(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n timestampMs: number,\n): Promise<any> {\n // Validate required fields\n if (!mutation.clientId) {\n throw new Error(\"Missing clientId in mutation - mutation must be enriched before calling handleOfflineMutation\");\n }\n if (!mutation.mutationId) {\n throw new Error(\"Missing mutationId in mutation - mutation must be enriched before calling handleOfflineMutation\");\n }\n\n // 1. Append to changelog (handling dedupe)\n // CLIENT-CHANGELOG-001, CLIENT-OFFLINE-MUT-001\n const clientId = mutation.clientId as string;\n const mutationId = mutation.mutationId as string;\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const operation = mutation.operation as string;\n const sanitizedMutation = sanitizeCapabilityReadonlyFields(schema, mutation);\n const record = ((sanitizedMutation.record || {}) as Record<string, unknown>);\n\n // 2. Validate mutation (no side effects, can throw)\n // This prevents invalid mutations from being added to changelog\n if (operation === \"relate\" || operation === \"modifyRelation\" || operation === \"unrelate\") {\n await validateRelationMutation(storage, schema, sanitizedMutation);\n }\n\n // 3. Append to changelog (after validation, before apply)\n // AUD-001: Enrich with timestamp\n try {\n await storage.changelogAppend({\n clientId,\n mutationId,\n mutation: sanitizedMutation,\n timestampMs,\n timestamp: new Date().toISOString(),\n });\n } catch (err) {\n // If changelog fails, the whole offline mutation fails\n // Throw as is or wrap (CLIENT-OFFLINE-MUT-002)\n throw err;\n }\n\n // 4. Optimistic local apply\n // Deterministic implementation\n\n if (operation === \"delete\") {\n await storage.deleteRecord(resource, id);\n } else if (operation === \"trash\") {\n await storage.mergeRecord(resource, id, {\n trashedAt: timestampMs,\n trashedBy: null,\n });\n } else if (operation === \"restore\") {\n await storage.mergeRecord(resource, id, {\n trashedAt: null,\n trashedBy: null,\n });\n } else if (operation === \"archive\") {\n await storage.mergeRecord(resource, id, {\n isArchived: true,\n });\n } else if (operation === \"unarchive\") {\n await storage.mergeRecord(resource, id, {\n isArchived: false,\n });\n } else if (operation === \"merge\") {\n // Merge: Use atomic mergeRecord with one-level-deep merge\n const optimisticRecord = injectCapabilityFieldsForOptimisticRecord(\n schema,\n sanitizedMutation,\n {\n timestampMs,\n actorId: clientId,\n },\n );\n await storage.mergeRecord(resource, id, optimisticRecord);\n } else if (operation === \"insert\" || operation === \"replace\") {\n // Insert/Replace: Overwrite (simple upsert)\n // Ensure id matches mutation target\n const existing =\n operation === \"replace\" ? await storage.getRecord(resource, id) : null;\n const optimisticRecord = injectCapabilityFieldsForOptimisticRecord(\n schema,\n sanitizedMutation,\n {\n timestampMs,\n actorId: clientId,\n existingRecord: existing,\n },\n );\n const toWrite = { ...optimisticRecord, id };\n await storage.upsertRecord(resource, toWrite);\n } else if (operation === \"relate\") {\n // Handle relation mutations\n await applyRelate(storage, schema, sanitizedMutation);\n } else if (operation === \"modifyRelation\") {\n await applyModifyRelation(storage, schema, sanitizedMutation);\n } else if (operation === \"unrelate\") {\n await applyUnrelate(storage, schema, sanitizedMutation);\n }\n\n // 5. Return optimistic success result\n return {\n ok: true,\n mutationId,\n affectedIds: [id],\n deduped: false, // local apply is fresh\n };\n}\n\n/**\n * Validate relation mutation (no side effects)\n * Throws if validation fails\n */\nasync function validateRelationMutation(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n): Promise<void> {\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const operation = mutation.operation as string;\n const relations = mutation.relations as Record<string, unknown>;\n\n if (!relations) return;\n\n for (const [relationName, payload] of Object.entries(relations)) {\n const relation = findRelationBidirectional(schema, resource, relationName);\n if (!relation) {\n throw createClientError(\n \"DFQL_UNKNOWN_RELATION\",\n `Unknown relation: ${relationName}`,\n { path: `relations.${relationName}` },\n );\n }\n\n // Validate payload structure\n const items = normalizeRelationPayload(payload);\n\n // For modifyRelation, check that join rows exist\n if (operation === \"modifyRelation\") {\n if (relation.type !== \"many-many\") {\n throw createClientError(\n \"DFQL_UNSUPPORTED\",\n \"modifyRelation only supported for many-many relations\",\n { path: `relations.${relationName}` },\n );\n }\n\n const fromResource = resource;\n const toResources = Array.isArray(relation.to)\n ? relation.to\n : [relation.to];\n\n for (const item of items) {\n const toResource =\n toResources.length === 1\n ? toResources[0]\n : toResources.find((r) => item.toId.startsWith(`${r}:`)) ||\n toResources[0];\n\n const joinStore = getJoinStoreKey(\n fromResource,\n relationName,\n toResource,\n );\n\n // Check if join row exists\n const existingRows = await storage.getJoinRows(joinStore, id);\n const existingRow = existingRows.find((r) => r.to === item.toId);\n\n if (!existingRow) {\n throw createClientError(\n \"NOT_FOUND\",\n `Relation not found between ${id} and ${item.toId}`,\n { path: `relations.${relationName}` },\n );\n }\n }\n }\n\n // For relate with many-one, validate single target\n if (operation === \"relate\" && relation.type === \"many-one\") {\n if (items.length !== 1) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"many-one relation expects single target\",\n { path: `relations.${relationName}` },\n );\n }\n }\n }\n}\n\n/**\n * Apply relate operation offline\n */\nasync function applyRelate(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n): Promise<void> {\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const relations = mutation.relations as Record<string, unknown>;\n\n if (!relations) return;\n\n for (const [relationName, payload] of Object.entries(relations)) {\n const relation = findRelationBidirectional(schema, resource, relationName);\n if (!relation) continue; // Already validated\n\n const items = normalizeRelationPayload(payload);\n\n // Apply based on relation type\n if (relation.type === \"many-one\") {\n // Update FK on source record\n const fkField = relation.fkField || `${relationName}Id`;\n const existing = await storage.getRecord(resource, id);\n if (existing) {\n await storage.upsertRecord(resource, {\n ...existing,\n [fkField]: items[0].toId,\n });\n }\n } else if (relation.type === \"one-many\") {\n // Update FK on target records\n const fkField =\n relation.fkField || relation.inverse || `${resource}Id`;\n const targetResource =\n typeof relation.to === \"string\" ? relation.to : relation.to[0];\n\n for (const item of items) {\n const targetRecord = await storage.getRecord(\n targetResource,\n item.toId,\n );\n if (targetRecord) {\n await storage.upsertRecord(targetResource, {\n ...targetRecord,\n [fkField]: id,\n });\n }\n }\n } else if (relation.type === \"many-many\") {\n // Upsert join rows\n const fromResource = resource;\n const toResources = Array.isArray(relation.to)\n ? relation.to\n : [relation.to];\n\n for (const item of items) {\n // Determine target resource from toId prefix (or use first if single)\n const toResource =\n toResources.length === 1\n ? toResources[0]\n : toResources.find((r) => item.toId.startsWith(`${r}:`)) ||\n toResources[0];\n\n const joinStore = getJoinStoreKey(\n fromResource,\n relationName,\n toResource,\n );\n\n // Upsert join row (merge metadata if exists)\n const existingRows = await storage.getJoinRows(joinStore, id);\n const existingRow = existingRows.find((r) => r.to === item.toId);\n\n if (existingRow) {\n // Update metadata if provided\n if (Object.keys(item.metadata).length > 0) {\n await storage.upsertJoinRow(joinStore, {\n from: id,\n to: item.toId,\n ...existingRow,\n ...item.metadata,\n });\n }\n } else {\n // Create new join row\n await storage.upsertJoinRow(joinStore, {\n from: id,\n to: item.toId,\n ...item.metadata,\n });\n }\n }\n }\n }\n}\n\n/**\n * Apply modifyRelation operation offline\n */\nasync function applyModifyRelation(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n): Promise<void> {\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const relations = mutation.relations as Record<string, unknown>;\n\n if (!relations) return;\n\n for (const [relationName, payload] of Object.entries(relations)) {\n const relation = findRelationBidirectional(schema, resource, relationName);\n if (!relation) continue; // Already validated\n\n const items = normalizeRelationPayload(payload);\n const fromResource = resource;\n const toResources = Array.isArray(relation.to)\n ? relation.to\n : [relation.to];\n\n for (const item of items) {\n // Determine target resource\n const toResource =\n toResources.length === 1\n ? toResources[0]\n : toResources.find((r) => item.toId.startsWith(`${r}:`)) ||\n toResources[0];\n\n const joinStore = getJoinStoreKey(fromResource, relationName, toResource);\n\n // Find existing join row (already validated to exist)\n const existingRows = await storage.getJoinRows(joinStore, id);\n const existingRow = existingRows.find((r) => r.to === item.toId);\n\n // Update metadata (existingRow is guaranteed to exist due to validation)\n await storage.upsertJoinRow(joinStore, {\n from: id,\n to: item.toId,\n ...existingRow,\n ...item.metadata,\n });\n }\n }\n}\n\n/**\n * Apply unrelate operation offline\n */\nasync function applyUnrelate(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n): Promise<void> {\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const relations = mutation.relations as Record<string, unknown>;\n\n if (!relations) return;\n\n for (const [relationName, payload] of Object.entries(relations)) {\n const relation = findRelationBidirectional(schema, resource, relationName);\n if (!relation) continue; // Already validated\n\n const items = normalizeRelationPayload(payload);\n\n if (relation.type === \"many-one\") {\n // Clear FK on source record\n const fkField = relation.fkField || `${relationName}Id`;\n const existing = await storage.getRecord(resource, id);\n if (existing) {\n await storage.upsertRecord(resource, {\n ...existing,\n [fkField]: null,\n });\n }\n } else if (relation.type === \"one-many\") {\n // Clear FK on target records\n const fkField =\n relation.fkField || relation.inverse || `${resource}Id`;\n const targetResource =\n typeof relation.to === \"string\" ? relation.to : relation.to[0];\n\n for (const item of items) {\n const targetRecord = await storage.getRecord(\n targetResource,\n item.toId,\n );\n if (targetRecord) {\n await storage.upsertRecord(targetResource, {\n ...targetRecord,\n [fkField]: null,\n });\n }\n }\n } else if (relation.type === \"many-many\") {\n // Delete join rows\n const fromResource = resource;\n const toResources = Array.isArray(relation.to)\n ? relation.to\n : [relation.to];\n\n for (const item of items) {\n // Determine target resource\n const toResource =\n toResources.length === 1\n ? toResources[0]\n : toResources.find((r) => item.toId.startsWith(`${r}:`)) ||\n toResources[0];\n\n const joinStore = getJoinStoreKey(\n fromResource,\n relationName,\n toResource,\n );\n\n await storage.deleteJoinRow(joinStore, id, item.toId);\n }\n }\n }\n}\n","import { resolveCapabilities, type DatafnSchema } from \"@datafn/core\";\n\ntype CapabilityMutationOp = \"insert\" | \"merge\" | \"replace\";\n\ntype CapabilityContext = {\n hasTimestamps: boolean;\n hasAudit: boolean;\n hasTrash: boolean;\n};\n\nfunction resolveCapabilityContext(\n schema: DatafnSchema,\n resourceName: string,\n): CapabilityContext | null {\n const resource = schema.resources.find((r) => r.name === resourceName);\n if (!resource) return null;\n\n const resolved = resolveCapabilities(\n schema.capabilities as any,\n resource.capabilities as any,\n );\n\n return {\n hasTimestamps: resolved.some((entry) => entry === \"timestamps\"),\n hasAudit: resolved.some((entry) => entry === \"audit\"),\n hasTrash: resolved.some((entry) => entry === \"trash\"),\n };\n}\n\nfunction stripReadonlyCapabilityFields(\n record: Record<string, unknown>,\n context: CapabilityContext,\n): Record<string, unknown> {\n const next = { ...record };\n\n if (context.hasTimestamps) {\n delete next.createdAt;\n delete next.updatedAt;\n }\n if (context.hasAudit) {\n delete next.createdBy;\n delete next.updatedBy;\n }\n if (context.hasTrash) {\n delete next.trashedAt;\n delete next.trashedBy;\n }\n\n return next;\n}\n\nfunction isRecordOperation(operation: unknown): operation is CapabilityMutationOp {\n return operation === \"insert\" || operation === \"merge\" || operation === \"replace\";\n}\n\nexport function sanitizeCapabilityReadonlyFields(\n schema: DatafnSchema | undefined,\n mutation: Record<string, unknown>,\n): Record<string, unknown> {\n if (!schema) return mutation;\n\n const operation = mutation.operation;\n if (!isRecordOperation(operation)) return mutation;\n\n if (typeof mutation.record !== \"object\" || mutation.record === null || Array.isArray(mutation.record)) {\n return mutation;\n }\n\n const resourceName = mutation.resource;\n if (typeof resourceName !== \"string\") return mutation;\n\n const context = resolveCapabilityContext(schema, resourceName);\n if (!context) return mutation;\n\n return {\n ...mutation,\n record: stripReadonlyCapabilityFields(\n mutation.record as Record<string, unknown>,\n context,\n ),\n };\n}\n\nexport function injectCapabilityFieldsForOptimisticRecord(\n schema: DatafnSchema,\n mutation: Record<string, unknown>,\n opts: {\n timestampMs: number;\n actorId?: string;\n existingRecord?: Record<string, unknown> | null;\n },\n): Record<string, unknown> {\n const operation = mutation.operation;\n if (!isRecordOperation(operation)) {\n return (mutation.record || {}) as Record<string, unknown>;\n }\n\n const resourceName = mutation.resource;\n if (typeof resourceName !== \"string\") {\n return (mutation.record || {}) as Record<string, unknown>;\n }\n\n const context = resolveCapabilityContext(schema, resourceName);\n if (!context) {\n return (mutation.record || {}) as Record<string, unknown>;\n }\n\n const base = stripReadonlyCapabilityFields(\n ((mutation.record || {}) as Record<string, unknown>),\n context,\n );\n const next = { ...base };\n\n if (operation === \"insert\") {\n if (context.hasTimestamps) {\n next.createdAt = opts.timestampMs;\n next.updatedAt = opts.timestampMs;\n }\n if (context.hasAudit) {\n next.createdBy = opts.actorId ?? null;\n next.updatedBy = opts.actorId ?? null;\n }\n return next;\n }\n\n if (operation === \"merge\") {\n if (context.hasTimestamps) {\n next.updatedAt = opts.timestampMs;\n }\n if (context.hasAudit) {\n next.updatedBy = opts.actorId ?? null;\n }\n return next;\n }\n\n // replace\n const existing = opts.existingRecord || null;\n if (context.hasTimestamps) {\n if (existing && existing.createdAt !== undefined) {\n next.createdAt = existing.createdAt;\n }\n next.updatedAt = opts.timestampMs;\n }\n if (context.hasAudit) {\n if (existing && existing.createdBy !== undefined) {\n next.createdBy = existing.createdBy;\n }\n next.updatedBy = opts.actorId ?? null;\n }\n return next;\n}\n","/**\n * Plugin hook runner for client-side plugins\n * Delegates to shared @datafn/core hook runner with env: \"client\"\n */\n\nimport type { DatafnPlugin, DatafnHookContext, DatafnSchema } from \"@datafn/core\";\nimport { runBeforeHook, runAfterHook } from \"@datafn/core\";\n\nexport async function runBeforeQuery(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n query: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n const result = await runBeforeHook(plugins, \"client\", \"beforeQuery\", ctx, query);\n if (!result.ok) throw result.error;\n return result.value;\n}\n\nexport async function runAfterQuery(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n query: unknown,\n queryResult: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n await runAfterHook(plugins, \"client\", \"afterQuery\", ctx, query, queryResult);\n return queryResult;\n}\n\nexport async function runBeforeMutation(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n mutation: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n const result = await runBeforeHook(plugins, \"client\", \"beforeMutation\", ctx, mutation);\n if (!result.ok) throw result.error;\n return result.value;\n}\n\nexport async function runAfterMutation(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n mutation: unknown,\n mutationResult: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n await runAfterHook(plugins, \"client\", \"afterMutation\", ctx, mutation, mutationResult);\n return mutationResult;\n}\n\nexport async function runBeforeSync(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n phase: \"seed\" | \"clone\" | \"pull\" | \"push\" | \"cloneUp\" | \"reconcile\",\n payload: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n // beforeSync signature: (ctx, phase, payload) — phase is a pre-arg\n const result = await runBeforeHook(plugins, \"client\", \"beforeSync\", ctx, payload, [phase]);\n if (!result.ok) throw result.error;\n return result.value;\n}\n\nexport async function runAfterSync(\n plugins: DatafnPlugin[],\n schema: DatafnSchema,\n phase: \"seed\" | \"clone\" | \"pull\" | \"push\" | \"cloneUp\" | \"reconcile\",\n payload: unknown,\n syncResult: unknown,\n): Promise<unknown> {\n const ctx: DatafnHookContext = { env: \"client\", schema };\n // afterSync signature: (ctx, phase, payload, result) — phase is a pre-arg\n await runAfterHook(plugins, \"client\", \"afterSync\", ctx, payload, syncResult, [phase]);\n return syncResult;\n}\n","/**\n * Date Codec (CODEC-001)\n *\n * Provides schema-driven date serialization and parsing:\n * - Outbound (mutation): Date objects → epoch milliseconds (number)\n * - Inbound (query result): epoch milliseconds or ISO strings → Date objects for schema date fields\n * - Deterministic error behavior for invalid dates\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport { toEpochMs, fromEpochMs } from \"@datafn/core\";\n\n/**\n * Serialize Date fields in mutation records to epoch milliseconds (CODEC-001 outbound)\n *\n * @param schema Schema definition\n * @param resource Resource name\n * @param record Record to serialize\n * @returns Serialized record with Date → epoch milliseconds (number)\n * @throws DFQL_INVALID if a date field contains a non-Date value\n */\nexport function serializeDateFields(\n schema: DatafnSchema,\n resource: string,\n record: Record<string, unknown>,\n): Record<string, unknown> {\n const resourceDef = schema.resources.find((r) => r.name === resource);\n if (!resourceDef || !resourceDef.fields) {\n return record;\n }\n\n const dateFields = resourceDef.fields.filter((f) => f.type === \"date\");\n if (dateFields.length === 0) {\n return record;\n }\n\n const serialized = { ...record };\n\n for (const field of dateFields) {\n const value = serialized[field.name];\n if (value === undefined || value === null) continue;\n\n // Client strictly requires Date objects for outbound serialization\n if (!(value instanceof Date)) {\n throw {\n code: \"DFQL_INVALID\",\n message: \"Invalid date value: expected Date object\",\n details: { path: `record.${field.name}` },\n };\n }\n try {\n serialized[field.name] = toEpochMs(value);\n } catch {\n throw {\n code: \"DFQL_INVALID\",\n message: \"Invalid date value\",\n details: { path: `record.${field.name}` },\n };\n }\n }\n\n return serialized;\n}\n\n/**\n * Parse date fields in query results from epoch milliseconds or ISO strings to Date objects (CODEC-001 inbound)\n *\n * @param schema Schema definition\n * @param resource Resource name\n * @param record Record to parse\n * @returns Parsed record with epoch milliseconds or ISO string → Date\n * @throws DFQL_INVALID if a date field contains an invalid value\n */\nexport function parseDateFields(\n schema: DatafnSchema,\n resource: string,\n record: Record<string, unknown>,\n): Record<string, unknown> {\n const resourceDef = schema.resources.find((r) => r.name === resource);\n if (!resourceDef || !resourceDef.fields) {\n return record;\n }\n\n const dateFields = resourceDef.fields.filter((f) => f.type === \"date\");\n if (dateFields.length === 0) {\n return record;\n }\n\n const parsed = { ...record };\n\n for (const field of dateFields) {\n const value = parsed[field.name];\n if (value === undefined || value === null) continue;\n\n try {\n parsed[field.name] = fromEpochMs(value);\n } catch {\n throw {\n code: \"DFQL_INVALID\",\n message: \"Invalid date value\",\n details: { path: `data[].${field.name}` },\n };\n }\n }\n\n return parsed;\n}\n\n/**\n * Parse date fields in a query result payload\n * Handles both non-aggregate (data array) and aggregate (groups array) results\n *\n * @param schema Schema definition\n * @param resource Resource name\n * @param result Query result payload\n * @returns Result with parsed Date fields\n */\nexport function parseQueryResultDates(\n schema: DatafnSchema,\n resource: string,\n result: any,\n): any {\n if (!result) {\n return result;\n }\n\n // Non-aggregate query: { data: [...], nextCursor? }\n if (Array.isArray(result.data)) {\n return {\n ...result,\n data: result.data.map((record: any) =>\n parseDateFields(schema, resource, record),\n ),\n };\n }\n\n // Aggregate query: { groups: [...], nextCursor? }\n // Note: aggregate results don't have record fields, so no date parsing needed\n // But for completeness, we handle this gracefully\n if (Array.isArray(result.groups)) {\n return result;\n }\n\n // Unknown result shape - passthrough\n return result;\n}\n","/**\n * Mutation Execution Utilities\n *\n * Handles mutation execution via remote adapter with event emission.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport type { EventBus } from \"./events/bus.js\";\nimport type { DatafnPlugin, DatafnSchema, SearchProvider } from \"@datafn/core\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { isTransportError } from \"./errors.js\";\nimport { handleOfflineMutation } from \"./offline/mutate.js\";\nimport { runBeforeMutation, runAfterMutation } from \"./plugins/run-hooks.js\";\nimport { serializeDateFields } from \"./codecs/date.js\";\nimport {\n injectCapabilityFieldsForOptimisticRecord,\n sanitizeCapabilityReadonlyFields,\n} from \"./capability-fields.js\";\n\nimport type { SyncEngine } from \"./sync/engine.js\";\nimport type { DebouncerMap } from \"./debounce.js\";\n\nexport type TableOperation =\n | \"delete\"\n | \"trash\"\n | \"restore\"\n | \"archive\"\n | \"unarchive\";\n\nexport type ShareScope = \"record\" | \"resource\";\n\nexport type PrincipalShareMutationInput = {\n principalId: string;\n level: string;\n scope?: ShareScope;\n id?: string;\n};\n\nexport type PrincipalUnshareMutationInput = {\n principalId: string;\n scope?: ShareScope;\n id?: string;\n};\n\n/**\n * Build a table-scoped mutation payload for operation convenience methods.\n */\nexport function buildTableOperationMutation(\n resource: string,\n version: number,\n operation: TableOperation,\n id: string,\n): Record<string, unknown> {\n return {\n resource,\n version,\n operation,\n id,\n };\n}\n\nexport function buildShareMutation(\n resource: string,\n version: number,\n id: string,\n userId: string,\n level: string,\n): Record<string, unknown> {\n return {\n resource,\n version,\n operation: \"share\",\n id,\n shareWith: { userId, level },\n };\n}\n\nexport function buildUnshareMutation(\n resource: string,\n version: number,\n id: string,\n userId: string,\n): Record<string, unknown> {\n return {\n resource,\n version,\n operation: \"unshare\",\n id,\n shareWith: { userId },\n };\n}\n\nexport function buildPrincipalShareMutation(\n resource: string,\n version: number,\n input: PrincipalShareMutationInput,\n): Record<string, unknown> {\n const scope = input.scope ?? \"record\";\n const payload: Record<string, unknown> = {\n resource,\n version,\n operation: \"share\",\n scope,\n shareWith: {\n principalId: input.principalId,\n level: input.level,\n },\n };\n\n if (scope === \"record\") {\n payload.id = input.id;\n }\n\n return payload;\n}\n\nexport function buildPrincipalUnshareMutation(\n resource: string,\n version: number,\n input: PrincipalUnshareMutationInput,\n): Record<string, unknown> {\n const scope = input.scope ?? \"record\";\n const payload: Record<string, unknown> = {\n resource,\n version,\n operation: \"unshare\",\n scope,\n shareWith: {\n principalId: input.principalId,\n },\n };\n\n if (scope === \"record\") {\n payload.id = input.id;\n }\n\n return payload;\n}\n\n/**\n * Generate a unique mutation ID\n */\nfunction generateMutationId(): string {\n return `mut-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * Apply outbound date codec to mutation record (CODEC-001)\n */\nfunction applyDateCodecToMutation(\n schema: DatafnSchema | undefined,\n mutation: Record<string, unknown>,\n): Record<string, unknown> {\n if (!schema || !mutation.record) {\n return mutation;\n }\n\n const resource = mutation.resource as string;\n if (!resource) {\n return mutation;\n }\n\n try {\n const serializedRecord = serializeDateFields(\n schema,\n resource,\n mutation.record as Record<string, unknown>,\n );\n return {\n ...mutation,\n record: serializedRecord,\n };\n } catch (err) {\n // Propagate codec errors\n throw err;\n }\n}\n\nfunction sanitizeCapabilityFieldsInMutationPayload(\n schema: DatafnSchema | undefined,\n payload: unknown | unknown[],\n): unknown | unknown[] {\n if (!schema) return payload;\n if (Array.isArray(payload)) {\n return payload.map((entry) =>\n sanitizeCapabilityReadonlyFields(schema, entry as Record<string, unknown>),\n );\n }\n return sanitizeCapabilityReadonlyFields(\n schema,\n payload as Record<string, unknown>,\n );\n}\n\nconst SEARCH_INDEX_UPSERT_OPS = new Set([\n \"insert\",\n \"merge\",\n \"replace\",\n \"trash\",\n \"restore\",\n \"archive\",\n \"unarchive\",\n]);\n\nfunction resolveSearchIndexOperation(\n operation: unknown,\n): \"upsert\" | \"delete\" | undefined {\n if (operation === \"delete\") return \"delete\";\n if (typeof operation === \"string\" && SEARCH_INDEX_UPSERT_OPS.has(operation)) {\n return \"upsert\";\n }\n return undefined;\n}\n\nasync function tryUpdateSearchIndex(\n searchProvider: SearchProvider | undefined,\n storage: DatafnStorageAdapter | undefined,\n mutation: Record<string, unknown>,\n resolvedRecord?: Record<string, unknown>,\n): Promise<void> {\n if (!searchProvider) return;\n\n const resource = mutation.resource;\n const id = mutation.id;\n const searchOp = resolveSearchIndexOperation(mutation.operation);\n if (typeof resource !== \"string\" || typeof id !== \"string\" || !searchOp) return;\n\n try {\n if (searchOp === \"delete\") {\n await searchProvider.updateIndices({\n resource,\n records: [{ id }],\n operation: \"delete\",\n });\n return;\n }\n\n const fromStorage = storage ? await storage.getRecord(resource, id) : null;\n const fallbackRecord =\n typeof mutation.record === \"object\" &&\n mutation.record !== null &&\n !Array.isArray(mutation.record)\n ? (mutation.record as Record<string, unknown>)\n : {};\n const finalRecord = {\n id,\n ...(resolvedRecord ?? (fromStorage as Record<string, unknown> | null) ?? fallbackRecord),\n };\n await searchProvider.updateIndices({\n resource,\n records: [finalRecord],\n operation: \"upsert\",\n });\n } catch (error) {\n // Search indexing is non-fatal for mutation durability.\n console.warn(\"Search index update failed (non-fatal)\", {\n operation: \"search-index-update\",\n resource,\n error: String(error),\n });\n }\n}\n\n/**\n * Execute a mutation (single or batch) via the remote adapter.\n * Unwraps responses, emits events, and returns mutation result(s).\n */\nexport async function executeMutation(\n remote: DatafnRemoteAdapter,\n eventBus: EventBus,\n getTimestamp: () => number,\n m: unknown | unknown[],\n storage?: DatafnStorageAdapter,\n plugins: DatafnPlugin[] = [],\n schema?: DatafnSchema,\n syncEngine?: SyncEngine,\n offlinability?: boolean,\n clientId?: string,\n debouncerMap?: DebouncerMap,\n searchProvider?: SearchProvider,\n): Promise<unknown> {\n // Validate clientId is provided when offline functionality is needed\n if ((offlinability || storage) && !clientId) {\n throw new Error(\n \"clientId is required when offlinability or storage is enabled\",\n );\n }\n\n // Validate context is JSON-serializable (API-002)\n const mutationsToValidate = Array.isArray(m) ? m : [m];\n for (const mut of mutationsToValidate) {\n const mutation = mut as any;\n if (mutation.context !== undefined) {\n try {\n // Test JSON serializability\n JSON.stringify(mutation.context);\n // Check for non-serializable types\n if (\n typeof mutation.context === \"function\" ||\n typeof mutation.context === \"symbol\" ||\n typeof mutation.context === \"bigint\"\n ) {\n throw new Error(\n \"Invalid mutation: context must be JSON-serializable\",\n );\n }\n } catch (err) {\n throw {\n code: \"DFQL_INVALID\",\n message: \"Invalid mutation: context must be JSON-serializable\",\n details: { path: \"context\" },\n };\n }\n }\n }\n\n // Check for debounced mutations (DEB-001)\n // Only single merge mutations with debounceKey are debounced\n if (\n !Array.isArray(m) &&\n debouncerMap &&\n storage &&\n offlinability &&\n clientId\n ) {\n const mutation = m as any;\n const debounceKey = mutation.debounceKey as string | undefined;\n const debounceMs = (mutation.debounceMs as number | undefined) || 1500;\n\n if (debounceKey) {\n // If operation is NOT merge, execute immediately (no debounce for insert/delete/replace)\n if (mutation.operation !== \"merge\") {\n // Fall through to normal execution below\n } else {\n // This is a debounced merge mutation\n const mutationId = mutation.mutationId || generateMutationId();\n const sanitizedMutation = schema\n ? sanitizeCapabilityReadonlyFields(schema, mutation as Record<string, unknown>)\n : mutation;\n const enrichedMutation = {\n ...sanitizedMutation,\n clientId,\n mutationId,\n };\n\n // Check hydration state - only proceed if ready\n const state = await storage.getHydrationState(mutation.resource);\n if (state === \"ready\") {\n // Apply to local storage immediately (optimistic) - inline merge logic\n const resource = mutation.resource as string;\n const id = mutation.id as string;\n const existing = await storage.getRecord(resource, id);\n const optimisticRecord = schema\n ? injectCapabilityFieldsForOptimisticRecord(\n schema,\n enrichedMutation as Record<string, unknown>,\n {\n timestampMs: getTimestamp(),\n actorId: clientId,\n existingRecord: existing,\n },\n )\n : (((enrichedMutation as any).record || {}) as Record<string, unknown>);\n\n const merged = existing\n ? { ...existing, ...optimisticRecord }\n : { ...optimisticRecord, id };\n merged.id = id;\n await storage.upsertRecord(resource, merged);\n await tryUpdateSearchIndex(\n searchProvider,\n storage,\n enrichedMutation as Record<string, unknown>,\n merged,\n );\n\n // Add to debouncer for delayed changelog append + event emission\n debouncerMap.set(\n debounceKey,\n enrichedMutation,\n debounceMs,\n async (debouncedMutation) => {\n // This executor runs after the debounce delay\n // The mutation is already in local storage (coalesced from all calls)\n // Now we need to:\n // 1. Append to changelog with the coalesced mutation\n // 2. Emit mutation_applied event\n // 3. Schedule push\n\n try {\n // Append to changelog (AUD-001: with timestamp enrichment)\n await storage.changelogAppend({\n clientId: debouncedMutation.clientId as string,\n mutationId: debouncedMutation.mutationId as string,\n mutation: debouncedMutation,\n timestampMs: getTimestamp(),\n timestamp: new Date().toISOString(),\n });\n\n // Emit mutation_applied event\n emitMutationEvents(\n eventBus,\n getTimestamp,\n debouncedMutation,\n { ok: true, mutationId: debouncedMutation.mutationId },\n );\n\n // Schedule push if syncEngine exists\n if (syncEngine) {\n syncEngine.schedulePush();\n }\n } catch (err) {\n // If changelog append fails, emit rejection event\n const errorContext = {\n code: \"INTERNAL\",\n message: \"Failed to append to changelog\",\n path: \"$\",\n };\n eventBus.emit({\n type: \"mutation_rejected\",\n resource: debouncedMutation.resource as string,\n ids: [debouncedMutation.id as string],\n mutationId: debouncedMutation.mutationId as string,\n clientId: debouncedMutation.clientId as string,\n timestampMs: getTimestamp(),\n action: debouncedMutation.operation as string,\n context: errorContext,\n } as any);\n // Don't re-throw - we've emitted the rejection event\n // and the debouncer promise will be rejected anyway\n }\n },\n );\n\n // Return immediately (optimistic result)\n // The mutation is in local storage and will be synced after debounce\n return {\n ok: true,\n mutationId,\n affectedIds: [mutation.id],\n deduped: false,\n };\n }\n }\n }\n }\n\n // Run beforeMutation hooks (fail-closed)\n const transformedMutation = schema\n ? await runBeforeMutation(plugins, schema, m)\n : m;\n\n // Apply outbound date codec (CODEC-001)\n // Serialize Date fields to ISO strings before any processing\n let codecAppliedMutation = transformedMutation;\n if (schema) {\n if (Array.isArray(transformedMutation)) {\n codecAppliedMutation = transformedMutation.map((mut) =>\n applyDateCodecToMutation(schema, mut as Record<string, unknown>),\n );\n } else {\n codecAppliedMutation = applyDateCodecToMutation(\n schema,\n transformedMutation as Record<string, unknown>,\n );\n }\n }\n\n const capabilitySanitizedMutation = sanitizeCapabilityFieldsInMutationPayload(\n schema,\n codecAppliedMutation,\n );\n\n // Local-first path (SYNC-MUT-001)\n // Only use local-first when hydration is ready to avoid data integrity issues\n // (e.g., editing a record that exists on remote but not yet synced locally)\n if (offlinability && storage && syncEngine) {\n const mutations = Array.isArray(capabilitySanitizedMutation)\n ? capabilitySanitizedMutation\n : [capabilitySanitizedMutation];\n\n // Check hydration state for all mutations\n let allReady = true;\n for (const mut of mutations) {\n const resource = (mut as any).resource;\n if (!resource) continue;\n const state = await storage.getHydrationState(resource);\n if (state !== \"ready\") {\n allReady = false;\n break;\n }\n }\n\n if (allReady) {\n // Enrich mutations with clientId and mutationId\n const enrichedMutations = mutations.map((mut) => {\n const mutation = mut as Record<string, unknown>;\n return {\n ...mutation,\n clientId: clientId!, // clientId is validated above\n mutationId: mutation.mutationId || generateMutationId(),\n };\n });\n\n const results: unknown[] = [];\n for (const mut of enrichedMutations) {\n const mutationRecord = mut as Record<string, unknown>;\n let result = await handleOfflineMutation(\n storage,\n schema!,\n mutationRecord,\n getTimestamp(),\n );\n\n // Run afterMutation hooks\n result = schema\n ? await runAfterMutation(plugins, schema, mut, result)\n : result;\n await tryUpdateSearchIndex(\n searchProvider,\n storage,\n mutationRecord,\n );\n\n results.push(result);\n emitMutationEvents(eventBus, getTimestamp, mut, result);\n }\n\n // Schedule push\n syncEngine.schedulePush();\n\n return Array.isArray(m) ? results : results[0];\n }\n }\n\n let result: unknown;\n let usedOfflinePath = false;\n\n // If storage is available, enrich mutations before remote call\n // so they're ready for offline handling if remote fails.\n let mutationForRemote = capabilitySanitizedMutation;\n if (storage && clientId) {\n const mutations = Array.isArray(codecAppliedMutation)\n ? codecAppliedMutation\n : [codecAppliedMutation];\n const enriched = mutations.map((mut) => {\n const mutation = mut as Record<string, unknown>;\n return {\n ...mutation,\n clientId: clientId,\n mutationId: mutation.mutationId || generateMutationId(),\n };\n });\n mutationForRemote = Array.isArray(codecAppliedMutation)\n ? enriched\n : enriched[0];\n }\n\n // Extract retryIndividual option from first mutation if batch\n let retryIndividualBatch = false;\n if (Array.isArray(mutationForRemote) && mutationForRemote.length > 0) {\n const firstMut = mutationForRemote[0] as any;\n retryIndividualBatch = firstMut.retryIndividual === true;\n }\n\n try {\n const response = await remote.mutation(mutationForRemote);\n result = unwrapRemoteSuccess(response);\n // Run afterMutation hooks (fail-open)\n result = schema\n ? await runAfterMutation(plugins, schema, mutationForRemote, result)\n : result;\n } catch (err: unknown) {\n // BULK-001: If batch fails and retryIndividual is true, retry each individually\n if (retryIndividualBatch && Array.isArray(mutationForRemote) && clientId) {\n const results: any[] = [];\n for (const mutation of mutationForRemote) {\n try {\n // Retry this mutation individually via remote.mutation\n const singleMutationResponse = await remote.mutation(mutation);\n const singleResult = unwrapRemoteSuccess(singleMutationResponse);\n results.push({\n mutationId: (mutation as any).mutationId,\n ok: true,\n result: singleResult,\n });\n } catch (mutErr) {\n results.push({\n mutationId: (mutation as any).mutationId,\n ok: false,\n error: mutErr,\n });\n }\n }\n\n // Aggregate results: ok only if ALL succeeded\n const allSucceeded = results.every((r) => r.ok);\n const errors = results.filter((r) => !r.ok).map((r) => r.error);\n\n result = {\n ok: allSucceeded,\n results,\n errors: allSucceeded ? [] : errors,\n };\n\n // Emit events for each mutation based on result\n for (let i = 0; i < mutationForRemote.length; i++) {\n if (results[i].ok) {\n emitMutationEvents(\n eventBus,\n getTimestamp,\n mutationForRemote[i],\n { ok: true, mutationId: (mutationForRemote[i] as any).mutationId },\n );\n } else {\n emitRejectionForError(\n eventBus,\n getTimestamp,\n mutationForRemote[i],\n results[i].error,\n );\n }\n }\n\n return result;\n }\n\n // REL-012: Do NOT emit rejection here if we are about to attempt offline handling.\n // Rejection is emitted only when no offline path is available (else branch below)\n // or when offline handling itself fails.\n\n // Check if we can failover to offline handling\n // OFF-001: Batch offline handling\n if (storage && schema && isTransportError(err)) {\n try {\n if (Array.isArray(mutationForRemote)) {\n // Batch offline handling: iterate through each mutation\n const results: any[] = [];\n for (const mutation of mutationForRemote) {\n const mutationRecord = mutation as Record<string, unknown>;\n try {\n const mutResult = await handleOfflineMutation(\n storage,\n schema,\n mutationRecord,\n getTimestamp(),\n );\n await tryUpdateSearchIndex(\n searchProvider,\n storage,\n mutationRecord,\n );\n // Emit mutation_applied event (unless silent)\n emitMutationEvents(eventBus, getTimestamp, mutation, mutResult);\n results.push({ ok: true, ...mutResult });\n } catch (mutErr) {\n results.push({ ok: false, error: mutErr });\n }\n }\n // Return aggregated batch results\n result = results;\n usedOfflinePath = true;\n } else {\n // Single mutation offline handling\n const mutationToUse = mutationForRemote as Record<string, unknown>;\n result = await handleOfflineMutation(\n storage,\n schema,\n mutationToUse,\n getTimestamp(),\n );\n await tryUpdateSearchIndex(\n searchProvider,\n storage,\n mutationToUse,\n );\n // REL-012: Emit applied here so only one event fires (no double-emit with final path)\n emitMutationEvents(eventBus, getTimestamp, mutationToUse, result);\n usedOfflinePath = true;\n }\n } catch (offlineErr) {\n // REL-012: Offline path also failed — emit rejection now and rethrow\n if (!Array.isArray(mutationForRemote)) {\n emitRejectionForError(eventBus, getTimestamp, mutationForRemote as any, offlineErr);\n } else {\n for (const mut of mutationForRemote as any[]) {\n emitRejectionForError(eventBus, getTimestamp, mut, offlineErr);\n }\n }\n throw offlineErr;\n }\n } else {\n // REL-012: No offline path available — emit rejection now and rethrow\n // CLIENT-EVENT-001: Emit mutation_rejected for thrown errors\n if (!Array.isArray(mutationForRemote)) {\n emitRejectionForError(\n eventBus,\n getTimestamp,\n mutationForRemote as any,\n err,\n );\n } else {\n // For batch mutations, emit rejection for each\n for (const mut of mutationForRemote as any[]) {\n emitRejectionForError(eventBus, getTimestamp, mut, err);\n }\n }\n throw err;\n }\n }\n\n // Handle single mutation result\n // REL-012: Skip final emit for offline path — events already emitted inside offline handling\n if (!Array.isArray(m)) {\n if (!usedOfflinePath) {\n emitMutationEvents(eventBus, getTimestamp, m as any, result as any);\n }\n return result;\n }\n\n // Handle batch mutation results\n // REL-012: Skip final emit for offline path — events already emitted inside the offline loop\n const mutations = m as any[];\n const results = result as any[];\n\n if (!usedOfflinePath) {\n for (let i = 0; i < mutations.length; i++) {\n emitMutationEvents(eventBus, getTimestamp, mutations[i], results[i]);\n }\n }\n\n return results;\n}\n\n/**\n * Emit mutation events based on result\n * CLIENT-EVENT-001: Include action and fields metadata\n * MUT-001: Skip emission if silent: true\n * MUT-002: Include system flag in event payload\n */\nfunction emitMutationEvents(\n eventBus: EventBus,\n getTimestamp: () => number,\n mutation: any,\n result: any,\n): void {\n // MUT-001: If silent: true, suppress event emission entirely\n if (mutation.silent === true) {\n return;\n }\n\n // Derive action from mutation.operation (CLIENT-EVENT-001)\n const action = mutation.operation;\n\n // Derive fields from mutation.record keys, excluding 'id' (CLIENT-EVENT-001)\n let fields: string[] | undefined;\n if (mutation.operation !== \"delete\" && mutation.record) {\n fields = Object.keys(mutation.record)\n .filter((k) => k !== \"id\")\n .sort(); // deterministic order\n }\n\n const baseEvent = {\n resource: mutation.resource,\n ids: Array.isArray(mutation.id) ? mutation.id : [mutation.id],\n mutationId: mutation.mutationId,\n clientId: mutation.clientId,\n timestampMs: getTimestamp(),\n action, // NEW: CLIENT-EVENT-001\n fields, // NEW: CLIENT-EVENT-001\n ...(mutation.record && { record: mutation.record }), // SIG-003: include record for optimistic patching\n ...(mutation.context !== undefined && { context: mutation.context }), // API-002: propagate context\n ...(mutation.system === true && { system: true }), // MUT-002: propagate system flag\n };\n\n if (result.ok) {\n // Successful mutation - emit mutation_applied\n eventBus.emit({\n type: \"mutation_applied\",\n ...baseEvent,\n });\n } else {\n // Failed mutation - emit mutation_rejected with error context\n const errorContext = result.errors?.[0] || {\n code: \"UNKNOWN\",\n message: \"Mutation failed\",\n path: \"$\",\n };\n\n eventBus.emit({\n type: \"mutation_rejected\",\n ...baseEvent,\n context: errorContext,\n } as any);\n }\n}\n\n/**\n * Emit mutation_rejected for thrown errors (CLIENT-EVENT-001)\n * MUT-001: Skip emission if silent: true\n * MUT-002: Include system flag in event payload\n */\nfunction emitRejectionForError(\n eventBus: EventBus,\n getTimestamp: () => number,\n mutation: any,\n error: any,\n): void {\n // MUT-001: If silent: true, suppress event emission entirely\n if (mutation.silent === true) {\n return;\n }\n\n // Derive action and fields same as above\n const action = mutation.operation;\n let fields: string[] | undefined;\n if (mutation.operation !== \"delete\" && mutation.record) {\n fields = Object.keys(mutation.record)\n .filter((k) => k !== \"id\")\n .sort();\n }\n\n const errorContext = {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Remote error\",\n path: error.path || \"$\",\n };\n\n eventBus.emit({\n type: \"mutation_rejected\",\n resource: mutation.resource,\n ids: Array.isArray(mutation.id) ? mutation.id : [mutation.id],\n mutationId: mutation.mutationId,\n clientId: mutation.clientId,\n timestampMs: getTimestamp(),\n action,\n fields,\n context: errorContext,\n ...(mutation.system === true && { system: true }), // MUT-002: propagate system flag\n } as any);\n}\n","/**\n * Offline query executor\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport {\n evaluateFilter as coreEvaluateFilter,\n parseSortTerms,\n sortRecords,\n type SchemaIndex,\n normalizeFilterOps,\n} from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport { materializeSelect } from \"./relations.js\";\nimport { executeAggregateQuery } from \"./aggregate.js\";\n\n/**\n * Execute a local query with index-aware routing (OFFQ-001)\n */\nexport async function executeLocalQuery(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n query: Record<string, unknown>,\n _schemaIndex?: SchemaIndex,\n): Promise<{ data?: any[]; groups?: any[]; nextCursor?: any }> {\n // Check for aggregation\n if (query.groupBy) {\n return executeAggregateQuery(storage, schema, query);\n }\n\n const resource = query.resource as string;\n let records: Record<string, unknown>[] = [];\n let usedIndexedPath = false;\n // CLI-012: tracks whether the index fetch fully satisfied all filter conditions\n let filterFullySatisfied = false;\n\n // Planning step: detect index-aware routing opportunities (OFFQ-001)\n if (query.filters) {\n const filters = query.filters as Record<string, unknown>;\n \n // Case 1: id eq → use getRecord\n if (filters.id && typeof filters.id === \"object\") {\n const idFilter = filters.id as Record<string, unknown>;\n if (idFilter.eq !== undefined) {\n const record = await storage.getRecord(resource, idFilter.eq as string);\n records = record ? [record] : [];\n usedIndexedPath = true;\n // Filter fully satisfied only when id eq is the sole filter condition\n if (Object.keys(filters).length === 1) {\n filterFullySatisfied = true;\n }\n }\n }\n \n // Case 2: single-field indexed eq → use findRecords\n if (!usedIndexedPath) {\n const singleFieldEq = detectSingleFieldEq(filters);\n if (singleFieldEq) {\n const { field, value } = singleFieldEq;\n // findRecords will use index if available, else fall back to scan\n records = await storage.findRecords(resource, field, value);\n usedIndexedPath = true;\n // detectSingleFieldEq guarantees exactly one key — fully satisfied\n filterFullySatisfied = true;\n }\n }\n }\n\n // Scan path with deterministic ordering\n if (!usedIndexedPath) {\n records = await storage.listRecords(resource);\n }\n\n // Apply filters only when not fully satisfied by the indexed path (CLI-012)\n if (query.filters && !filterFullySatisfied) {\n const normalized = normalizeFilterOps(query.filters as Record<string, unknown>);\n records = records.filter((r) => applyFilter(r, normalized));\n }\n\n // Sort using shared core utilities\n if (query.sort) {\n const terms = parseSortTerms(query.sort as string[]);\n records = sortRecords(records, terms);\n } else if (!usedIndexedPath) {\n // Deterministic ordering: stable sort by id:asc when scan path is used\n records = sortRecords(records, [{ field: \"id\", direction: \"asc\" }]);\n }\n\n // Pagination\n if (query.limit || query.offset) {\n const offset = (query.offset as number) || 0;\n const limit = (query.limit as number) || records.length;\n records = records.slice(offset, offset + limit);\n }\n\n // Select / Expansion\n if (query.select) {\n records = await materializeSelect(\n storage,\n schema,\n resource,\n records,\n query.select as string[],\n );\n }\n\n return {\n data: records,\n nextCursor: null,\n };\n}\n\n/** Wrap core evaluateFilter to add field-path context to error messages. */\nfunction applyFilter(\n record: Record<string, unknown>,\n filters: Record<string, unknown>,\n path = \"filters\",\n): boolean {\n for (const [key, value] of Object.entries(filters)) {\n const fieldPath = `${path}.${key}`;\n try {\n if (key === \"$and\" && Array.isArray(value)) {\n for (const sub of value as Record<string, unknown>[]) {\n if (!applyFilter(record, sub, path)) return false;\n }\n continue;\n }\n if (key === \"$or\" && Array.isArray(value)) {\n let matched = false;\n for (const sub of value as Record<string, unknown>[]) {\n try {\n if (applyFilter(record, sub, path)) { matched = true; break; }\n } catch { /* continue */ }\n }\n if (!matched) {\n // Re-run to surface errors from all branches\n for (const sub of value as Record<string, unknown>[]) {\n applyFilter(record, sub, path);\n }\n return false;\n }\n continue;\n }\n if (!coreEvaluateFilter(record, { [key]: value })) return false;\n } catch (err: any) {\n if (err && (err.code === \"DFQL_UNSUPPORTED\" || err.code === \"DFQL_INVALID\")) {\n throw { ...err, message: `${err.message}: ${fieldPath}` };\n }\n throw err;\n }\n }\n return true;\n}\n\n// normalizeFilterOps is imported from @datafn/core above.\n\n/**\n * Detect if filters contain a single-field eq that could use an index.\n * Returns null if not applicable, or { field, value } if applicable.\n */\nfunction detectSingleFieldEq(\n filters: Record<string, unknown>,\n): { field: string; value: unknown } | null {\n const keys = Object.keys(filters);\n \n // Only consider if exactly one field and it's not a logical operator\n if (keys.length !== 1) return null;\n const key = keys[0];\n if (key.startsWith(\"$\")) return null;\n \n const val = filters[key];\n \n // Check for { field: { eq: value } } or { field: { $eq: value } }\n if (typeof val === \"object\" && val !== null && !Array.isArray(val)) {\n const ops = val as Record<string, unknown>;\n if (ops.eq !== undefined && Object.keys(ops).length === 1) {\n return { field: key, value: ops.eq };\n }\n if (ops.$eq !== undefined && Object.keys(ops).length === 1) {\n return { field: key, value: ops.$eq };\n }\n }\n \n return null;\n}\n","/**\n * Offline Relation Operations\n * \n * Handles relation expansion and mutation operations in offline mode.\n */\nimport type { DatafnSchema, DatafnRelationSchema } from \"@datafn/core\";\nimport { getJoinStoreKey } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"../storage.js\";\n\n// NormalizedRelation, normalizeRelationPayload, and findRelationBidirectional\n// are canonical in @datafn/core and are re-exported here for convenience.\nexport type { NormalizedRelation } from \"@datafn/core\";\nexport { normalizeRelationPayload } from \"@datafn/core\";\n\n/**\n * Expand a relation for a record with sub-selection\n */\nexport async function expandRelation(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n resource: string,\n record: Record<string, unknown>,\n relationName: string,\n subSelect: string[],\n): Promise<unknown> {\n const relation = schema.relations?.find(\n (r) =>\n (r.from === resource && r.relation === relationName) ||\n (r.to === resource && r.inverse === relationName),\n );\n\n if (!relation) {\n return null;\n }\n\n // Determine direction\n const isForward =\n relation.from === resource && relation.relation === relationName;\n const targetResource = isForward\n ? (relation.to as string)\n : (relation.from as string);\n\n // Check for metadata request (# or *#)\n const wantsMetadata = subSelect.some(\n (s) => s === \"#\" || s === \"*#\" || s === \"#*\",\n );\n const wantsExpansion = subSelect.length > 0;\n\n // 1. Fetch related IDs or Join Rows\n let targetIds: string[] = [];\n let joinRows: Record<string, unknown>[] = [];\n\n if (relation.type === \"many-one\") {\n if (isForward) {\n const fk = relation.fkField || `${relationName}Id`;\n const val = record[fk] as string;\n if (val) targetIds.push(val);\n } else {\n // Inverse many-one is one-many behavior\n // fk is on target table.\n const fk = relation.fkField || relation.inverse || `${resource}Id`;\n const records = await storage.findRecords(targetResource, fk, record.id);\n targetIds = records.map((r) => r.id as string);\n }\n } else if (relation.type === \"one-many\") {\n const fk = relation.fkField || relation.inverse || `${resource}Id`;\n const records = await storage.findRecords(targetResource, fk, record.id);\n targetIds = records.map((r) => r.id as string);\n } else if (relation.type === \"many-many\") {\n const relationName = relation.relation || \"rel\";\n const fromResources = Array.isArray(relation.from)\n ? relation.from\n : [relation.from];\n const toResources = Array.isArray(relation.to)\n ? relation.to\n : [relation.to];\n\n // Determine stores to query based on direction\n const storesToQuery: string[] = [];\n\n if (isForward) {\n // Forward: We are 'from' (resource). Query all 'to' targets.\n for (const t of toResources) {\n storesToQuery.push(getJoinStoreKey(resource, relationName, t));\n }\n } else {\n // Inverse: We are 'to' (resource). Query all 'from' sources.\n for (const f of fromResources) {\n storesToQuery.push(getJoinStoreKey(f, relationName, resource));\n }\n }\n\n const allRows: Record<string, unknown>[] = [];\n for (const storeName of storesToQuery) {\n try {\n const rows = isForward\n ? await storage.getJoinRows(storeName, record.id as string)\n : await storage.getJoinRowsInverse(storeName, record.id as string);\n allRows.push(...rows);\n } catch (err) {\n // Store might not exist if lazy created or invalid schema combo\n // Ignore or log? Safe to ignore if we assume consistent schema.\n }\n }\n\n joinRows = allRows;\n targetIds = allRows.map((r) =>\n isForward ? (r.to as string) : (r.from as string),\n );\n }\n\n // 2. Return based on request type\n if (!wantsExpansion && relation.type !== \"many-many\") {\n // Just IDs for many-one?\n // \"rel\" -> ID or IDs.\n if (relation.type === \"many-one\" && isForward) return targetIds[0] || null;\n return targetIds;\n }\n\n if (relation.type === \"many-many\") {\n if (wantsMetadata && !subSelect.some((s) => s !== \"#\")) {\n // Only metadata (#)\n return joinRows;\n }\n // If we want expansion, we need to fetch records\n }\n\n // 3. Fetch records\n const targets = [];\n for (const id of targetIds) {\n const r = await storage.getRecord(targetResource, id);\n if (r) targets.push(r);\n }\n\n // 4. Attach metadata if needed (many-many *#)\n if (relation.type === \"many-many\" && wantsMetadata) {\n // Merge metadata\n const merged = targets.map((target) => {\n // Find matching join row\n const match = joinRows.find((row) =>\n isForward ? row.to === target.id : row.from === target.id,\n );\n return { ...target, ...(match || {}) };\n });\n return materializeSelect(\n storage,\n schema,\n targetResource,\n merged,\n subSelect,\n );\n }\n\n // 5. Materialize\n const result = await materializeSelect(\n storage,\n schema,\n targetResource,\n targets,\n subSelect,\n );\n\n if (relation.type === \"many-one\" && isForward) {\n return result[0] || null;\n }\n return result;\n}\n\n/**\n * Materialize selection for a list of records\n * Handles nested expansion\n */\nexport async function materializeSelect(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n resource: string,\n records: Record<string, unknown>[],\n select: string[],\n): Promise<Record<string, unknown>[]> {\n // Group tokens\n const expansions = new Map<string, string[]>();\n const baseFields = new Set<string>();\n\n for (const token of select) {\n if (token === \"*\" || token === \"#\" || token === \"*#\" || token === \"#*\") {\n baseFields.add(\"*\"); // Keep all fields\n // # implies metadata, which is already merged if we are here?\n // Yes, expandRelation merges it.\n continue;\n }\n\n if (token.includes(\".\")) {\n const [base, ...rest] = token.split(\".\");\n if (!expansions.has(base)) expansions.set(base, []);\n expansions.get(base)!.push(rest.join(\".\"));\n } else {\n // Check if it's a relation (ids only request)\n // We will handle it in expansions with empty subSelect if it is relation.\n // But we need to know if it is a relation or field.\n // We can defer check.\n baseFields.add(token);\n }\n }\n\n const results = [];\n for (const record of records) {\n const result: Record<string, unknown> = {};\n\n // Copy fields\n if (baseFields.has(\"*\")) {\n Object.assign(result, record);\n } else {\n result.id = record.id;\n for (const key of baseFields) {\n // Check if relation\n const relation = schema.relations?.find(\n (r) =>\n (r.from === resource && r.relation === key) ||\n (r.to === resource && r.inverse === key),\n );\n if (relation) {\n // Expand as IDs\n result[key] = await expandRelation(\n storage,\n schema,\n resource,\n record,\n key,\n [],\n );\n } else if (key in record) {\n result[key] = record[key];\n }\n }\n }\n\n // Process expansions\n for (const [key, subSelect] of expansions.entries()) {\n result[key] = await expandRelation(\n storage,\n schema,\n resource,\n record,\n key,\n subSelect,\n );\n }\n\n results.push(result);\n }\n\n return results;\n}\n","/**\n * Offline aggregation logic\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport { evaluateFilter as coreEvaluateFilter, calculateAggregation } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport { expandRelation } from \"./relations.js\";\n\n/**\n * Execute aggregate query locally\n */\nexport async function executeAggregateQuery(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n query: Record<string, unknown>,\n): Promise<{ groups: Record<string, unknown>[]; nextCursor: null }> {\n // 1. Fetch all records\n // We assume filter is already applied? No, query executor applies filters.\n // But query executor calls THIS function instead of normal flow?\n // Yes, spec says: \"Check if query has groupBy: If yes: call executeAggregateQuery\".\n // So we need to fetch and filter here.\n // But filtering logic is in `client/src/offline/query.ts` (implied, not yet existing).\n // Actually, standard `executeLocalQuery` logic does filtering.\n // We should reuse filter logic.\n // Let's assume caller passes filtered records?\n // Or we fetch all and filter.\n // Reusing filter logic is better.\n // I will accept `records` as argument?\n // Spec says: \"executeAggregateQuery(storage, schema, query)\".\n // \"Fetch all records... Apply filters...\".\n // So I need to implement filtering here or import it.\n \n // To avoid duplication, `offline/query.ts` should handle fetching and filtering, then pass `records` to `executeAggregateQuery`?\n // Spec: \"If yes: call executeAggregateQuery\".\n // \"executeAggregateQuery\" steps include \"Fetch all records... Apply filters\".\n // Okay, I will import `filterRecords` helper from query module if available, or duplicate simple filter logic.\n // Client filters are usually simple (sift).\n \n const resource = query.resource as string;\n let records = await storage.listRecords(resource);\n \n // Apply filters\n if (query.filters) {\n // Need filter logic.\n // I'll define a simple evaluator or import if possible.\n // `sift` is common but I should use custom logic matching server?\n // \"OFFLINE-001: Local DFQL expansion\" implies matching semantics.\n // server uses `evaluateFilter`.\n // Can I share `evaluateFilter` code? It's in `server/src`. Client cannot import server code.\n // I need a client-side `evaluateFilter`.\n // For now, I will implement a basic one here or stub it.\n // Spec requirement \"OFFLINE-002\" says \"support groupBy... filtering grouped rows deterministically\".\n // It doesn't explicitly demand full filter parity but implied.\n // I will assume `evaluateFilter` is available or implement a basic one.\n \n records = records.filter(r => coreEvaluateFilter(r, query.filters as Record<string, unknown>));\n }\n\n // 2. Group By\n const groupBy = query.groupBy as string[];\n const groups = new Map<string, Record<string, unknown>[]>();\n \n for (const record of records) {\n // Resolve group key\n const keyParts = [];\n for (const field of groupBy) {\n // Handle dot paths?\n // Simple field access for now.\n keyParts.push(String(record[field]));\n }\n const groupKey = JSON.stringify(keyParts); // Collision-safe key (DUP-10)\n \n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(record);\n }\n\n // 3. Aggregations\n const results = [];\n const aggregations = query.aggregations as Record<string, Record<string, unknown>>;\n \n for (const [, rows] of groups.entries()) {\n const result: Record<string, unknown> = {};\n \n // LOW-022: group key is JSON.stringify(keyParts) — splitting with \"::\" is not\n // meaningful. Restore typed group-key values directly from the first row's fields.\n groupBy.forEach((field) => {\n result[field] = rows[0][field];\n });\n \n // Compute aggregations using shared core implementation\n if (aggregations) {\n for (const [alias, def] of Object.entries(aggregations)) {\n const op = def.op as string;\n const field = def.field as string;\n result[alias] = calculateAggregation(op, field, rows);\n }\n }\n \n results.push(result);\n }\n\n // 4. Having\n if (query.having) {\n // Filter results\n const having = query.having as Record<string, unknown>;\n // Reuse evaluateFilter\n const filteredResults = results.filter(r => coreEvaluateFilter(r, having));\n // Reassign\n results.length = 0;\n results.push(...filteredResults);\n }\n\n // 5. Sort (Deterministic)\n // Default sort by group keys\n results.sort((a, b) => {\n for (const field of groupBy) {\n const va = a[field] as any;\n const vb = b[field] as any;\n if (va < vb) return -1;\n if (va > vb) return 1;\n }\n return 0;\n });\n\n return {\n groups: results,\n nextCursor: null, // Pagination not fully implemented for local aggregation in this phase\n };\n}\n\n\n","/**\n * Query Execution Utilities\n *\n * Handles query execution via remote adapter or local storage based on hydration state.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport type { DatafnPlugin, DatafnSchema, SchemaIndex } from \"@datafn/core\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { executeLocalQuery } from \"./offline/query.js\";\nimport { runBeforeQuery, runAfterQuery } from \"./plugins/run-hooks.js\";\nimport { parseQueryResultDates } from \"./codecs/date.js\";\n\ntype QueryMetadata = {\n includeTrashed?: boolean;\n includeArchived?: boolean;\n};\n\nexport type PermissionEntry = {\n userId: string;\n level: string;\n grantedBy: string;\n grantedAt: number;\n};\n\nexport function buildGetPermissionsQuery(\n resource: string,\n version: number,\n id: string,\n): Record<string, unknown> {\n return {\n resource,\n version,\n operation: \"getPermissions\",\n id,\n };\n}\n\nfunction normalizeQueryMetadata(\n query: Record<string, unknown>,\n): Record<string, unknown> {\n if (\n !query.metadata ||\n typeof query.metadata !== \"object\" ||\n Array.isArray(query.metadata)\n ) {\n return query;\n }\n\n const metadata = query.metadata as Record<string, unknown>;\n const normalizedMetadata: QueryMetadata = {\n ...(metadata.includeTrashed === true ? { includeTrashed: true } : {}),\n ...(metadata.includeArchived === true ? { includeArchived: true } : {}),\n };\n\n return {\n ...query,\n metadata: normalizedMetadata,\n };\n}\n\n/**\n * Execute a query (single or batch) via the remote adapter or local storage.\n *\n * When storage is configured and table hydration state is 'ready', queries execute locally.\n * Otherwise, queries execute via the remote adapter.\n *\n * @param remote - Remote adapter for server queries\n * @param q - Query or array of queries\n * @param storage - Optional storage adapter for local-first execution\n * @param plugins - Optional plugins for hook execution\n * @returns Query result(s)\n */\nexport async function executeQuery<T = unknown>(\n remote: DatafnRemoteAdapter,\n q: unknown | unknown[],\n storage?: DatafnStorageAdapter,\n plugins: DatafnPlugin[] = [],\n schema?: DatafnSchema,\n schemaIndex?: SchemaIndex,\n): Promise<T | T[]> {\n // Run beforeQuery hooks (fail-closed)\n const transformedQuery = schema\n ? await runBeforeQuery(plugins, schema, q)\n : q;\n const normalizedQuery = Array.isArray(transformedQuery)\n ? transformedQuery.map((entry) =>\n typeof entry === \"object\" && entry !== null\n ? normalizeQueryMetadata(entry as Record<string, unknown>)\n : entry,\n )\n : typeof transformedQuery === \"object\" && transformedQuery !== null\n ? normalizeQueryMetadata(transformedQuery as Record<string, unknown>)\n : transformedQuery;\n\n // If no storage is configured, always use remote execution.\n if (!storage) {\n const response = await remote.query(normalizedQuery);\n let result = unwrapRemoteSuccess<T | T[]>(response);\n\n if (schema && Array.isArray(normalizedQuery)) {\n // REL-013: Apply inbound date codec per-query for batch queries (no-storage path)\n if (Array.isArray(result)) {\n result = (result as any[]).map((queryResult, i) => {\n const query = (normalizedQuery as any[])[i] as Record<string, unknown>;\n const resource = query?.resource as string;\n if (resource) {\n return parseQueryResultDates(schema, resource, queryResult);\n }\n return queryResult;\n }) as any;\n }\n } else if (schema && !Array.isArray(normalizedQuery)) {\n // Apply inbound date codec (CODEC-001)\n const query = normalizedQuery as Record<string, unknown>;\n const resource = query.resource as string;\n if (resource) {\n result = parseQueryResultDates(schema, resource, result) as T | T[];\n }\n }\n\n // Run afterQuery hooks (fail-open)\n return schema\n ? (runAfterQuery(plugins, schema, normalizedQuery, result) as Promise<\n T | T[]\n >)\n : result;\n }\n\n // For batch queries, always use remote execution.\n if (Array.isArray(normalizedQuery)) {\n const response = await remote.query(normalizedQuery);\n let result = unwrapRemoteSuccess<T | T[]>(response);\n\n // REL-013: Apply inbound date codec per-query in batch path\n if (schema && Array.isArray(result)) {\n result = (result as any[]).map((queryResult, i) => {\n const query = (normalizedQuery as any[])[i] as Record<string, unknown>;\n const resource = query?.resource as string;\n if (resource) {\n return parseQueryResultDates(schema, resource, queryResult);\n }\n return queryResult;\n }) as any;\n }\n\n return schema\n ? (runAfterQuery(plugins, schema, normalizedQuery, result) as Promise<\n T | T[]\n >)\n : result;\n }\n\n // Single query: check hydration state for local-first routing\n const query = normalizedQuery as Record<string, unknown>;\n const resource = query.resource as string;\n\n if (resource) {\n // Check if table is remote-only\n const resourceDef = schema?.resources.find((r) => r.name === resource);\n if (resourceDef?.isRemoteOnly) {\n // Force remote execution for remote-only tables (SYNC-003)\n const response = await remote.query(normalizedQuery);\n let result = unwrapRemoteSuccess<T>(response);\n \n // Apply inbound date codec (CODEC-001)\n if (schema) {\n result = parseQueryResultDates(schema, resource, result) as T;\n }\n \n return schema\n ? (runAfterQuery(\n plugins,\n schema,\n normalizedQuery,\n result,\n ) as Promise<T>)\n : result;\n }\n\n const hydrationState = await storage.getHydrationState(resource);\n\n // Local-first: execute against storage when table is ready\n if (hydrationState === \"ready\" && schema) {\n let result = (await executeLocalQuery(storage, schema, query, schemaIndex)) as T;\n \n // Apply inbound date codec for local query results (CODEC-001)\n result = parseQueryResultDates(schema, resource, result) as T;\n \n return schema\n ? (runAfterQuery(plugins, schema, query, result) as Promise<T>)\n : result;\n }\n \n // If table is hydrating, route to remote when available (SYNC-002, TV-SYNC-002N)\n // In local-only mode (no remote), we'd use local even if hydrating\n // But since storage is present and we're here, we have a remote, so use it\n if (hydrationState === \"hydrating\") {\n const response = await remote.query(normalizedQuery);\n let result = unwrapRemoteSuccess<T>(response);\n \n // Apply inbound date codec (CODEC-001)\n if (schema) {\n result = parseQueryResultDates(schema, resource, result) as T;\n }\n \n return schema\n ? (runAfterQuery(plugins, schema, normalizedQuery, result) as Promise<T>)\n : result;\n }\n }\n\n // Remote execution for: notStarted or missing resource\n const response = await remote.query(normalizedQuery);\n let result = unwrapRemoteSuccess<T>(response);\n \n // Apply inbound date codec (CODEC-001)\n if (schema && !Array.isArray(normalizedQuery)) {\n const query = normalizedQuery as Record<string, unknown>;\n const resource = query.resource as string;\n if (resource) {\n result = parseQueryResultDates(schema, resource, result) as T;\n }\n }\n \n return schema\n ? (runAfterQuery(plugins, schema, normalizedQuery, result) as Promise<T>)\n : result;\n}\n","/**\n * Table Registry\n *\n * Manages table handles with object identity caching.\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport { createClientError } from \"../errors.js\";\nimport { createTable, type DatafnTable } from \"./table.js\";\nimport type { SignalRegistry } from \"../signals/querySignal.js\";\n\n// Forward declaration for client interface\ninterface ClientWithQuery {\n query(q: unknown | unknown[]): Promise<unknown>;\n mutate(m: unknown | unknown[]): Promise<unknown>;\n transact(payload: unknown): Promise<unknown>;\n subscribe(handler: any, filter?: any): () => void;\n}\n\nexport class TableRegistry<S extends DatafnSchema = DatafnSchema> {\n private schema: S;\n private tables: Map<string, DatafnTable<S, string>>;\n private client: ClientWithQuery;\n private signalRegistry: SignalRegistry;\n private generateId: (params: {\n resource: string;\n idPrefix?: string;\n }) => string;\n\n constructor(\n schema: S,\n client: ClientWithQuery,\n signalRegistry: SignalRegistry,\n generateId: (params: { resource: string; idPrefix?: string }) => string,\n ) {\n this.schema = schema;\n this.tables = new Map();\n this.client = client;\n this.signalRegistry = signalRegistry;\n this.generateId = generateId;\n }\n\n /**\n * Get a table handle by name.\n * Caches table instances for object identity.\n * Throws DFQL_UNKNOWN_RESOURCE for unknown tables.\n */\n getTable(name: string): DatafnTable<S, string> {\n // Check cache first\n const cached = this.tables.get(name);\n if (cached) {\n return cached;\n }\n\n // Find resource in schema\n const resource = this.schema.resources.find((r) => r.name === name);\n if (!resource) {\n createClientError(\"DFQL_UNKNOWN_RESOURCE\", `Unknown resource: ${name}`, {\n path: \"resource\",\n resource: name,\n });\n }\n\n // Create and cache table\n const table = createTable<S>(\n resource.name,\n resource.version,\n this.client,\n this.signalRegistry,\n this.generateId,\n this.schema,\n );\n this.tables.set(name, table);\n return table;\n }\n\n /**\n * Get all declared table names from schema\n */\n getTableNames(): string[] {\n return this.schema.resources.map((r) => r.name);\n }\n}\n","/**\n * Transaction Execution Utilities\n *\n * Handles transaction execution via remote adapter with response unwrapping.\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\n\n/**\n * Execute a transaction via the remote adapter.\n * Unwraps response and returns transaction result.\n */\nexport async function executeTransact(\n remote: DatafnRemoteAdapter,\n payload: unknown\n): Promise<unknown> {\n const response = await remote.transact(payload);\n return unwrapRemoteSuccess(response);\n}\n","/**\n * Query Signal Implementation\n *\n * Reactive query signals with caching, lazy fetch, and auto-refresh on mutations.\n */\n\nimport type { DatafnSignal, DatafnError, DatafnSchema } from \"@datafn/core\";\nimport { dfqlKey } from \"@datafn/core\";\nimport type { EventBus } from \"../events/bus.js\";\n\n/**\n * Signal registry for caching signals by dfqlKey\n */\nexport class SignalRegistry {\n private signals = new Map<string, DatafnSignal<any>>();\n private client: any;\n private eventBus: EventBus;\n private schema: DatafnSchema;\n\n constructor(client: any, eventBus: EventBus, schema: DatafnSchema) {\n this.client = client;\n this.eventBus = eventBus;\n this.schema = schema;\n }\n\n getSignal<T>(fullQuery: unknown, options?: { disableOptimistic?: boolean }): DatafnSignal<T> {\n const key = dfqlKey(fullQuery);\n\n // Return cached signal if exists\n if (this.signals.has(key)) {\n return this.signals.get(key) as DatafnSignal<T>;\n }\n\n // Create new signal\n const signal = createQuerySignal<T>(\n this.client,\n this.eventBus,\n this.schema,\n fullQuery,\n key,\n () => this.removeSignal(key),\n options,\n );\n this.signals.set(key, signal);\n return signal;\n }\n\n /**\n * Remove a signal from the registry (called by signal.dispose())\n */\n private removeSignal(key: string): void {\n this.signals.delete(key);\n }\n\n /**\n * Dispose all signals in the registry\n */\n disposeAll(): void {\n // Create array copy to avoid iterator invalidation\n const signalsToDispose = Array.from(this.signals.values());\n signalsToDispose.forEach((signal) => signal.dispose());\n // signals.clear() not needed - dispose() removes each signal\n }\n}\n\n/**\n * Derive the footprint (set of resources) that affect a query signal (SIG-002)\n *\n * Footprint includes:\n * - Primary resource from query\n * - Resources referenced by relation expansion tokens in select array (via schema lookup)\n *\n * Relation expansion tokens are parsed for patterns like:\n * - \"relationName.*\" (expand all fields)\n * - \"relationName.field\" (expand specific field)\n */\nfunction deriveQueryFootprint(query: any, schema: DatafnSchema): Set<string> {\n const footprint = new Set<string>();\n\n // Add primary resource\n if (query.resource) {\n footprint.add(query.resource);\n }\n\n // Parse select array for relation expansion tokens\n if (Array.isArray(query.select) && schema.relations) {\n for (const token of query.select) {\n if (typeof token === \"string\" && token.includes(\".\")) {\n // Extract the relation name (first segment before dot)\n const relationName = token.split(\".\")[0];\n \n // Look up the relation in schema to find the target resource\n for (const relation of schema.relations) {\n // Check if this relation matches (by relation field name or inverse)\n const matchesRelation = relation.relation === relationName;\n const matchesInverse = relation.inverse === relationName;\n \n if (matchesRelation || matchesInverse) {\n // Add the target resource (to) for forward relations\n // Add the source resource (from) for inverse relations\n const targetResource = matchesRelation \n ? (Array.isArray(relation.to) ? relation.to[0] : relation.to)\n : (Array.isArray(relation.from) ? relation.from[0] : relation.from);\n \n if (targetResource && targetResource !== query.resource) {\n footprint.add(targetResource);\n }\n break;\n }\n }\n }\n }\n }\n\n return footprint;\n}\n\n/**\n * Extract record IDs from a query result (SIG-002)\n */\nfunction extractRecordIds(result: any): Set<string> | null {\n const ids = new Set<string>();\n \n // Handle result with data array (standard query result)\n if (result && Array.isArray(result.data)) {\n for (const record of result.data) {\n if (record && typeof record.id === \"string\") {\n ids.add(record.id);\n }\n }\n return ids.size > 0 ? ids : null;\n }\n \n // Handle direct array result (some queries may return arrays directly)\n if (Array.isArray(result)) {\n for (const record of result) {\n if (record && typeof record.id === \"string\") {\n ids.add(record.id);\n }\n }\n return ids.size > 0 ? ids : null;\n }\n \n // Single record result\n if (result && typeof result.id === \"string\") {\n ids.add(result.id);\n return ids;\n }\n \n return null;\n}\n\n/**\n * Apply optimistic patch to signal cache (SIG-003)\n * \n * Attempts to patch cached records with mutation data without re-fetching.\n * Returns the patched value if successful, null if patching is not possible.\n */\nfunction applyOptimisticPatch(currentValue: any, event: any): any | null {\n // Only handle merge operations with record data\n if (event.action !== \"merge\" || !event.record) {\n return null;\n }\n \n // Extract mutation IDs\n const mutationIds = event.ids;\n if (!mutationIds || !Array.isArray(mutationIds) || mutationIds.length === 0) {\n return null;\n }\n \n // Handle result with data array (standard query result format)\n if (currentValue && Array.isArray(currentValue.data)) {\n let patched = false;\n const patchedData = currentValue.data.map((record: any) => {\n if (record && typeof record.id === \"string\" && mutationIds.includes(record.id)) {\n patched = true;\n // Shallow merge: spread existing record, then apply mutation fields\n return { ...record, ...event.record };\n }\n return record;\n });\n \n if (!patched) {\n // No records were patched (IDs not found in cache)\n return null;\n }\n \n // Return new result object with patched data\n return {\n ...currentValue,\n data: patchedData,\n };\n }\n \n // Handle direct array result\n if (Array.isArray(currentValue)) {\n let patched = false;\n const patchedArray = currentValue.map((record: any) => {\n if (record && typeof record.id === \"string\" && mutationIds.includes(record.id)) {\n patched = true;\n return { ...record, ...event.record };\n }\n return record;\n });\n \n if (!patched) {\n return null;\n }\n \n return patchedArray;\n }\n \n // Handle single record result\n if (currentValue && typeof currentValue.id === \"string\" && mutationIds.includes(currentValue.id)) {\n return { ...currentValue, ...event.record };\n }\n \n // Unknown format or no match\n return null;\n}\n\n/**\n * Create a reactive query signal\n */\nfunction createQuerySignal<T>(\n client: any,\n eventBus: EventBus,\n schema: DatafnSchema,\n fullQuery: any,\n signalKey: string,\n removeFromRegistry: () => void,\n options?: { disableOptimistic?: boolean },\n): DatafnSignal<T> {\n let currentValue: T | undefined;\n let currentCursor: string | null = null;\n const subscribers = new Set<(value: T) => void>();\n let inFlight = false;\n let isRefresh = false;\n let queuedRefresh = false;\n let currentError: DatafnError | null = null;\n const resource = fullQuery.resource;\n let disposed = false;\n let unsubscribeFn: (() => void) | null = null;\n\n // Track cached record IDs for fine-grained invalidation (SIG-002)\n let cachedIds: Set<string> | null = null;\n\n // Optimistic update option (SIG-003)\n const disableOptimistic = options?.disableOptimistic ?? false;\n\n // Helper to notify all subscribers (notify on any state change, not just value change)\n const notifySubscribers = () => {\n subscribers.forEach((fn) => fn(currentValue as T));\n };\n\n const fetchQuery = async (refresh = false): Promise<void> => {\n if (inFlight) {\n // Queue a refresh to happen after current fetch completes\n if (refresh) {\n queuedRefresh = true;\n }\n return;\n }\n\n inFlight = true;\n isRefresh = refresh;\n queuedRefresh = false;\n // Clear error when starting a new fetch\n if (!refresh) {\n currentError = null;\n }\n\n try {\n const result = await client.query(fullQuery);\n // Unwrap pagination envelope: emit the record array directly\n const queryResult = result as { data?: any[]; nextCursor?: string | null };\n currentValue = (queryResult.data ?? result) as T;\n currentCursor = queryResult.nextCursor ?? null;\n currentError = null;\n\n // Extract and cache record IDs from result (SIG-002)\n cachedIds = extractRecordIds(currentValue);\n\n // Clear flight flags BEFORE notifying so loading/refreshing read correctly\n inFlight = false;\n isRefresh = false;\n\n notifySubscribers();\n } catch (error: any) {\n // Convert error to DatafnError format\n const dfError: DatafnError = {\n code: error?.code || \"INTERNAL\",\n message: error?.message || \"Query failed\",\n details: error?.details,\n };\n\n if (!refresh) {\n // Initial load error - store and notify\n currentError = dfError;\n // Clear flight flags BEFORE notifying so loading reads correctly\n inFlight = false;\n isRefresh = false;\n notifySubscribers();\n // Preserve throw behavior for initial-load failures\n throw error;\n } else {\n // Refresh error - store but don't notify with error updates\n currentError = dfError;\n // Don't notify subscribers of refresh errors to avoid UI disruption\n }\n } finally {\n inFlight = false;\n isRefresh = false;\n\n // If a refresh was queued, execute it now\n if (queuedRefresh) {\n queuedRefresh = false;\n fetchQuery(true);\n }\n }\n };\n\n // Derive footprint from query with schema lookup (SIG-002)\n const footprint = deriveQueryFootprint(fullQuery, schema);\n\n // Debouncing state for batching refreshes (SIG-002)\n let pendingRefresh = false;\n\n const scheduleRefresh = () => {\n if (pendingRefresh) {\n return; // Already scheduled\n }\n pendingRefresh = true;\n\n // Microtask debounce (0ms via Promise.resolve)\n Promise.resolve().then(() => {\n pendingRefresh = false;\n fetchQuery(true);\n });\n };\n\n // Listen for mutation_applied and sync_applied events for auto-refresh (SIG-002, SIG-003)\n // Store unsubscribe function for disposal\n unsubscribeFn = eventBus.subscribe((event) => {\n // Check disposed flag to prevent refresh after dispose\n if (disposed) {\n return;\n }\n\n // Refresh after sync operations (clone/pull) that may have updated local storage\n if (event.type === \"sync_applied\") {\n const ctx = (event as any).context;\n const phase = ctx?.phase;\n if (phase === \"clone\" || phase === \"pull\") {\n const affectedResources: string[] = ctx?.resources ?? [];\n // Only refresh when specific resources that overlap with this signal's footprint\n // changed. Removing the \"length === 0\" broadcast avoids refreshing all signals\n // (including KV) on every pull that returns no records (RC-3 / issue 2026-03-02-k7m4x9r8).\n if (affectedResources.some(r => footprint.has(r))) {\n scheduleRefresh();\n }\n }\n return;\n }\n\n if (event.type === \"mutation_applied\" && event.resource) {\n // Check if event.resource is in signal footprint\n if (!footprint.has(event.resource)) {\n return; // Not relevant to this signal\n }\n \n // If mutation is on a related resource (not the primary query resource),\n // always refresh since we can't easily match IDs across relations\n if (event.resource !== resource) {\n scheduleRefresh();\n return;\n }\n \n // Fine-grained invalidation logic (SIG-002) for primary resource mutations\n const action = event.action;\n \n if (action === \"insert\" || action === \"delete\" || action === \"replace\") {\n // Always full re-fetch for insert/delete/replace (no safe patching)\n scheduleRefresh();\n return;\n }\n \n if (action === \"merge\") {\n // Optimistic signal update (SIG-003) for merge operations\n \n // Skip optimistic patch if disabled or no cached value yet\n if (disableOptimistic || currentValue === undefined) {\n scheduleRefresh();\n return;\n }\n \n // Conservative: if no cached IDs, always refresh\n if (!cachedIds || cachedIds.size === 0) {\n scheduleRefresh();\n return;\n }\n \n // Check if mutation affects any cached record\n if (!event.ids || !Array.isArray(event.ids)) {\n // No ids in event, be conservative and refresh\n scheduleRefresh();\n return;\n }\n \n const affectsCachedRecord = event.ids.some(id => cachedIds!.has(id));\n \n if (!affectsCachedRecord) {\n // Mutation doesn't affect cached records, skip refresh\n return;\n }\n \n // Attempt optimistic patch\n const patchedValue = applyOptimisticPatch(currentValue, event);\n \n if (patchedValue !== null) {\n // Successfully patched - emit immediately\n currentValue = patchedValue as T;\n notifySubscribers();\n \n // Schedule background re-fetch for eventual consistency\n scheduleRefresh();\n } else {\n // Patch failed, fall back to refresh\n scheduleRefresh();\n }\n \n return;\n }\n \n // Unknown action, be conservative\n scheduleRefresh();\n }\n });\n\n return {\n subscribe(fn: (value: T) => void): () => void {\n subscribers.add(fn);\n\n // Lazy fetch on first subscribe\n if (subscribers.size === 1 && currentValue === undefined && !inFlight) {\n fetchQuery(false).catch(() => {\n // Initial fetch errors are handled internally\n });\n } else if (currentValue !== undefined) {\n // Immediately deliver current value to new subscriber\n fn(currentValue);\n }\n\n // Return unsubscribe function\n return () => {\n subscribers.delete(fn);\n };\n },\n\n get(): T {\n // Return current value or undefined as T (signals can have undefined state)\n // Disposed signal returns last cached value (no re-fetch)\n return currentValue as T;\n },\n\n get loading(): boolean {\n return inFlight && !isRefresh;\n },\n\n get error(): DatafnError | null {\n return currentError;\n },\n\n get refreshing(): boolean {\n return inFlight && isRefresh;\n },\n\n get nextCursor(): string | null {\n return currentCursor;\n },\n\n dispose(): void {\n // Guard against double-dispose\n if (disposed) {\n return;\n }\n\n // Mark as disposed\n disposed = true;\n\n // Unsubscribe from event bus\n if (unsubscribeFn) {\n unsubscribeFn();\n unsubscribeFn = null;\n }\n\n // Remove from registry\n removeFromRegistry();\n\n // Note: We keep currentValue intact so get() returns last cached value\n },\n };\n}\n","/**\n * LiveSignal — lifecycle-aware signal wrapper that survives switchContext().\n *\n * A LiveSignal holds a factory closure that creates raw signals.\n * When rebind() is called (by LiveSignalRegistry after a context switch),\n * the factory is re-invoked to produce a new raw signal bound to the new\n * realClient, and existing subscribers continue receiving updates.\n */\n\nimport type { DatafnSignal, DatafnError } from \"@datafn/core\";\nimport { dfqlKey } from \"@datafn/core\";\n\ntype SignalFactory<T> = () => DatafnSignal<T>;\ntype UnsubscribeFn = () => void;\n\nexport class LiveSignal<T> implements DatafnSignal<T> {\n private raw: DatafnSignal<T> | null = null;\n private rawUnsub: UnsubscribeFn | null = null;\n private disposed = false;\n private lastValue: T | undefined = undefined;\n private currentError: DatafnError | null = null;\n private subscribers = new Set<(value: T) => void>();\n\n /**\n * Set by the Proxy layer (Phase 2) to unsubscribe from the client lifecycle.\n * null until wired in.\n */\n lifecycleUnsub: UnsubscribeFn | null = null;\n\n constructor(\n private factory: SignalFactory<T>,\n private removeFromRegistry: () => void,\n ) {\n this.bindRaw();\n }\n\n private bindRaw(): void {\n try {\n this.raw = this.factory();\n this.rawUnsub = this.raw.subscribe((value) => {\n this.lastValue = value;\n this.subscribers.forEach((fn) => fn(value));\n });\n } catch (err: any) {\n this.currentError = {\n code: \"INTERNAL\",\n message: err?.message ?? \"Signal factory failed\",\n details: err,\n };\n this.raw = null;\n this.rawUnsub = null;\n }\n }\n\n private unbindRaw(): void {\n this.rawUnsub?.();\n this.rawUnsub = null;\n try {\n this.raw?.dispose();\n } catch {\n // Raw signal may already be disposed by realClient.destroy() — ignore\n }\n this.raw = null;\n }\n\n /**\n * Rebind to a new raw signal from the factory.\n * Called by LiveSignalRegistry.rebindAll() after a context switch.\n */\n rebind(): void {\n if (this.disposed) return;\n this.unbindRaw();\n this.currentError = null;\n this.bindRaw();\n // If the new raw signal already has a value (e.g. cached), emit to subscribers.\n // Note: bindRaw's internal handler also emits when raw.subscribe() delivers synchronously.\n if (this.raw !== null) {\n const current = this.raw.get();\n if (current !== undefined) {\n this.lastValue = current;\n this.subscribers.forEach((fn) => fn(current));\n }\n }\n }\n\n get(): T {\n return (this.raw?.get() ?? this.lastValue) as T;\n }\n\n subscribe(handler: (value: T) => void): () => void {\n if (this.disposed) return () => {};\n this.subscribers.add(handler);\n if (this.lastValue !== undefined) {\n handler(this.lastValue);\n }\n return () => {\n this.subscribers.delete(handler);\n };\n }\n\n get loading(): boolean {\n return this.raw?.loading ?? false;\n }\n\n get error(): DatafnError | null {\n return this.currentError ?? this.raw?.error ?? null;\n }\n\n get refreshing(): boolean {\n return this.raw?.refreshing ?? false;\n }\n\n get nextCursor(): string | null {\n return (this.raw as any)?.nextCursor ?? null;\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.unbindRaw();\n this.lifecycleUnsub?.();\n this.lifecycleUnsub = null;\n this.removeFromRegistry();\n this.subscribers.clear();\n }\n}\n\nexport class LiveSignalRegistry {\n private signals = new Map<string, LiveSignal<any>>();\n\n getOrCreateTableSignal<T>(\n name: string,\n version: number,\n query: unknown,\n options: { disableOptimistic?: boolean } | undefined,\n factory: SignalFactory<T>,\n ): DatafnSignal<T> {\n const key = dfqlKey({ resource: name, version, ...(query as object) });\n if (this.signals.has(key)) {\n return this.signals.get(key) as DatafnSignal<T>;\n }\n const signal = new LiveSignal<T>(factory, () => this.signals.delete(key));\n this.signals.set(key, signal);\n return signal;\n }\n\n getOrCreateKvSignal<T>(\n key: string,\n factory: SignalFactory<T>,\n ): DatafnSignal<T> {\n const registryKey = `kv:${key}`;\n if (this.signals.has(registryKey)) {\n return this.signals.get(registryKey) as DatafnSignal<T>;\n }\n const signal = new LiveSignal<T>(factory, () => this.signals.delete(registryKey));\n this.signals.set(registryKey, signal);\n return signal;\n }\n\n rebindAll(): void {\n const signals = Array.from(this.signals.values());\n for (const signal of signals) {\n try {\n signal.rebind();\n } catch {\n // One failure must not prevent others from rebinding\n }\n }\n }\n\n disposeAll(): void {\n const signals = Array.from(this.signals.values());\n for (const signal of signals) {\n signal.dispose();\n }\n this.signals.clear();\n }\n}\n","/**\n * Sync Apply Logic\n *\n * Apply clone/pull results into local storage with hydration state management.\n */\n\nimport type { DatafnStorageAdapter } from \"../storage.js\";\n\nexport const GLOBAL_CURSOR_KEY = \"__global_cursor__\";\n\n/**\n * Clone result shape from remote\n */\nexport type CloneResult = {\n ok: boolean;\n data: Record<string, Array<Record<string, unknown>>>;\n cursors: Record<string, string>;\n joins?: Record<string, Array<Record<string, unknown>>>;\n next?: Record<string, string | null>;\n};\n\n/**\n * Global-cursor pull result shape\n */\nexport type PullResultGlobalCursor = {\n ok: boolean;\n changes: Array<{\n serverSeq: number;\n resource: string;\n id: string;\n op: \"insert\" | \"merge\" | \"replace\" | \"upsert\" | \"delete\";\n record: Record<string, unknown> | null;\n reason?: \"revoked\" | \"grant_backfill\";\n }>;\n nextCursor: string | null;\n actorFeed?: Array<Record<string, unknown>>;\n};\n\n/**\n * Canonical per-table cursor pull result shape (PHASE_05)\n */\nexport type PullResultCanonical = {\n ok: boolean;\n records: Record<string, Array<Record<string, unknown>>>;\n merged?: Record<string, Array<Record<string, unknown>>>; // partial records to apply via mergeRecord (FIX-A)\n deleted: Record<string, string[]>;\n joins?: Record<string, {\n upsert: Array<Record<string, unknown>>;\n delete: Array<{ from: string; to: string }>;\n }>;\n cursors: Record<string, string>;\n actorFeed?: Array<Record<string, unknown>>;\n hasMore?: boolean; // CLIENT-PULL-001: true when more changes remain on server\n};\n\nexport type PullResult = PullResultGlobalCursor | PullResultCanonical;\n\n/**\n * Apply clone result to local storage.\n * Transitions hydration state: notStarted → hydrating → ready\n */\nexport async function applyCloneResult(\n storage: DatafnStorageAdapter,\n result: CloneResult,\n): Promise<void> {\n if (!result.ok) {\n return; // Don't apply failed results\n }\n\n const { data, cursors, joins } = result;\n\n // Process each table\n for (const [resource, records] of Object.entries(data)) {\n // Transition to hydrating state before applying\n await storage.setHydrationState(resource, \"hydrating\");\n\n // Upsert all records by id\n for (const record of records) {\n await storage.upsertRecord(resource, record);\n }\n\n // Set cursor per resource\n const cursor = cursors[resource];\n if (cursor !== undefined) {\n await storage.setCursor(resource, cursor);\n }\n\n // Transition to ready after applying\n await storage.setHydrationState(resource, \"ready\");\n }\n\n // Apply join rows if present (TV-SYNC-006, TV-REL-002)\n if (joins) {\n for (const [joinStoreKey, rows] of Object.entries(joins)) {\n for (const row of rows) {\n try {\n await storage.upsertJoinRow(joinStoreKey, row);\n } catch (error) {\n // If join store doesn't exist, this is a deterministic error (TV-REL-002N)\n console.error(`Failed to apply join row to ${joinStoreKey}:`, error);\n throw new Error(\n `INTERNAL: Store not found: ${joinStoreKey}`,\n );\n }\n }\n }\n }\n\n // Calculate and set global cursor\n let maxSeq = 0;\n for (const cursor of Object.values(cursors)) {\n const seq = parseInt(cursor, 10);\n if (!isNaN(seq) && seq > maxSeq) {\n maxSeq = seq;\n }\n }\n await setCursorMonotonically(storage, GLOBAL_CURSOR_KEY, String(maxSeq));\n}\n\n/**\n * Detect if pull result is global-cursor format\n */\nfunction isGlobalCursorPullResult(result: PullResult): result is PullResultGlobalCursor {\n return \"changes\" in result && Array.isArray((result as any).changes);\n}\n\n/**\n * Apply pull result to local storage.\n * Supports both global-cursor and canonical per-table cursor formats.\n */\nexport async function applyPullResult(\n storage: DatafnStorageAdapter,\n result: PullResult,\n): Promise<void> {\n if (!result.ok) {\n return; // Don't apply failed results\n }\n\n if (isGlobalCursorPullResult(result)) {\n await applyPullResultGlobalCursor(storage, result);\n } else {\n await applyPullResultCanonical(storage, result as PullResultCanonical);\n }\n}\n\n/**\n * Apply global-cursor pull result\n */\nasync function applyPullResultGlobalCursor(\n storage: DatafnStorageAdapter,\n result: PullResultGlobalCursor,\n): Promise<void> {\n const { changes, nextCursor } = result;\n\n if (nextCursor !== null) {\n await assertCursorNonRegressing(storage, GLOBAL_CURSOR_KEY, nextCursor, \"nextCursor\");\n }\n\n // Process changes in order\n for (const change of changes) {\n const { resource, id, op, record } = change;\n\n if (op === \"delete\") {\n await storage.deleteRecord(resource, id);\n } else if (record) {\n await storage.upsertRecord(resource, record);\n }\n }\n\n // Update global cursor monotonically\n if (nextCursor !== null) {\n await setCursorMonotonically(storage, GLOBAL_CURSOR_KEY, nextCursor);\n }\n}\n\n/**\n * Apply canonical per-table cursor pull result (PHASE_05)\n */\nasync function applyPullResultCanonical(\n storage: DatafnStorageAdapter,\n result: PullResultCanonical,\n): Promise<void> {\n const { records, merged, deleted, joins, cursors } = result;\n\n // Reject cursor regressions before mutating local state.\n for (const [resource, cursor] of Object.entries(cursors)) {\n await assertCursorNonRegressing(storage, resource, cursor, `cursors.${resource}`);\n }\n\n // Apply record upserts (insert/replace/upsert ops — full record replacement)\n for (const [resource, resourceRecords] of Object.entries(records)) {\n for (const record of resourceRecords) {\n await storage.upsertRecord(resource, record);\n }\n }\n\n // Apply merge deltas (merge op — partial record, must not overwrite unset fields) (FIX-A)\n if (merged) {\n for (const [resource, mergedRecords] of Object.entries(merged)) {\n for (const record of mergedRecords) {\n const id = record.id as string;\n await storage.mergeRecord(resource, id, record);\n }\n }\n }\n\n // Apply record deletes\n for (const [resource, ids] of Object.entries(deleted)) {\n for (const id of ids) {\n await storage.deleteRecord(resource, id);\n }\n }\n\n // Apply join deltas if present (TV-SYNC-006, TV-REL-002)\n if (joins) {\n for (const [joinStoreKey, delta] of Object.entries(joins)) {\n // Apply upserts\n for (const row of delta.upsert) {\n try {\n await storage.upsertJoinRow(joinStoreKey, row);\n } catch (error) {\n // If join store doesn't exist, this is a deterministic error (TV-REL-002N)\n console.error(`Failed to apply join upsert to ${joinStoreKey}:`, error);\n throw new Error(\n `INTERNAL: Store not found: ${joinStoreKey}`,\n );\n }\n }\n\n // Apply deletes\n for (const edge of delta.delete) {\n try {\n await storage.deleteJoinRow(joinStoreKey, edge.from, edge.to);\n } catch (error) {\n console.error(`Failed to apply join delete to ${joinStoreKey}:`, error);\n throw new Error(\n `INTERNAL: Store not found: ${joinStoreKey}`,\n );\n }\n }\n }\n }\n\n // Update per-table cursors monotonically\n for (const [resource, cursor] of Object.entries(cursors)) {\n await setCursorMonotonically(storage, resource, cursor);\n }\n\n // Calculate and update global cursor (derived optimization)\n let maxSeq = 0;\n for (const cursor of Object.values(cursors)) {\n const seq = parseInt(cursor, 10);\n if (!isNaN(seq) && seq > maxSeq) {\n maxSeq = seq;\n }\n }\n if (maxSeq > 0) {\n await setCursorMonotonically(storage, GLOBAL_CURSOR_KEY, String(maxSeq));\n }\n}\n\n/**\n * Set cursor only if new cursor is greater than existing cursor.\n * Cursors are base-10 integer strings representing serverSeq.\n */\nexport async function setCursorMonotonically(\n storage: DatafnStorageAdapter,\n resource: string,\n newCursor: string,\n): Promise<void> {\n const existingCursor = await storage.getCursor(resource);\n\n // If no existing cursor, set the new one\n if (existingCursor === null) {\n await storage.setCursor(resource, newCursor);\n return;\n }\n\n // Parse as integers for comparison\n const existingSeq = parseInt(existingCursor, 10);\n const newSeq = parseInt(newCursor, 10);\n\n // Only update if new cursor is greater (monotonic)\n if (newSeq > existingSeq) {\n await storage.setCursor(resource, newCursor);\n }\n}\n\nasync function assertCursorNonRegressing(\n storage: DatafnStorageAdapter,\n resource: string,\n newCursor: string,\n path: string,\n): Promise<void> {\n const existingCursor = await storage.getCursor(resource);\n if (existingCursor === null) {\n return;\n }\n\n const existingSeq = parseInt(existingCursor, 10);\n const newSeq = parseInt(newCursor, 10);\n\n if (Number.isNaN(existingSeq) || Number.isNaN(newSeq)) {\n return;\n }\n\n if (newSeq < existingSeq) {\n const error = new Error(\"Non-monotonic cursor\") as Error & {\n code: string;\n details: Record<string, unknown>;\n };\n error.code = \"CONFLICT\";\n error.details = { path };\n throw error;\n }\n}\n","import type { DatafnSchema, DatafnResourceSchema, DatafnRelationSchema } from \"@datafn/core\";\nimport { getJoinStoreKey } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport type { DatafnRemoteAdapter } from \"../client.js\";\nimport type { EventBus } from \"../events/bus.js\";\nimport { createClientError, isTransportError } from \"../errors.js\";\nimport { computeMutationHash } from \"./cloneUp/hash.js\";\nimport { sortRecordsById, sortJoinRows } from \"./cloneUp/order.js\";\nimport { batchMutations } from \"./cloneUp/batch.js\";\n\nexport type CloneUpOptions = {\n resources?: string[];\n includeManyMany?: boolean;\n recordOperation?: \"merge\" | \"replace\" | \"insert\";\n batchSize?: number;\n maxRetries?: number;\n failFast?: boolean;\n clearChangelogOnSuccess?: boolean;\n setGlobalCursorOnSuccess?: boolean;\n pullAfter?: boolean;\n mutationIdPrefix?: string;\n};\n\nexport type CloneUpResult = {\n ok: boolean;\n cursor: string;\n stats: {\n resources: Record<string, { records: number; mutations: number }>;\n joinStores: Record<string, { rows: number; mutations: number }>;\n batches: number;\n };\n errors: Array<{\n mutationId: string;\n code: string;\n message: string;\n path: string;\n }>;\n /** Optional total count of uploaded records (for event context) */\n uploadedCount?: number;\n};\n\nexport type CloneUpDeps = {\n schema: DatafnSchema;\n storage: DatafnStorageAdapter | undefined;\n remote: DatafnRemoteAdapter | undefined;\n clientId: string;\n syncConfig: { pushBatchSize?: number; pushMaxRetries?: number } | undefined;\n eventBus: EventBus;\n getTimestamp: () => number;\n};\n\nexport async function cloneUp(\n deps: CloneUpDeps,\n options?: CloneUpOptions,\n): Promise<CloneUpResult> {\n const storage = deps.storage;\n const remote = deps.remote;\n const schema = deps.schema;\n\n if (!storage) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: storage is required\",\n { path: \"storage\" },\n );\n }\n\n if (!remote) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: sync.remote is required\",\n { path: \"sync.remote\" },\n );\n }\n\n if (!schema) {\n throw createClientError(\n \"INTERNAL\",\n \"Invalid cloneUp: schema is not available\",\n { path: \"schema\" },\n );\n }\n\n const batchSize = options?.batchSize ?? deps.syncConfig?.pushBatchSize ?? 100;\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: batchSize must be a positive integer\",\n { path: \"batchSize\" },\n );\n }\n\n const maxRetries = options?.maxRetries ?? deps.syncConfig?.pushMaxRetries ?? 3;\n if (!Number.isInteger(maxRetries) || maxRetries < 0) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: maxRetries must be a non-negative integer\",\n { path: \"maxRetries\" },\n );\n }\n\n const recordOperation = options?.recordOperation ?? \"merge\";\n const prefix = options?.mutationIdPrefix ?? \"cloneup\";\n const failFast = options?.failFast ?? true;\n const includeManyMany = options?.includeManyMany ?? true;\n\n const resolvedResources = resolveResourceScope(schema, options?.resources);\n\n const resourceSchemaMap = new Map<string, DatafnResourceSchema>();\n for (const r of schema.resources) {\n resourceSchemaMap.set(r.name, r);\n }\n\n const result: CloneUpResult = {\n ok: true,\n cursor: \"0\",\n stats: {\n resources: {},\n joinStores: {},\n batches: 0,\n },\n errors: [],\n };\n\n let highestCursor = \"0\";\n let hasErrors = false;\n\n // --- Stage A: Upload records ---\n for (const resourceName of resolvedResources) {\n const resourceSchema = resourceSchemaMap.get(resourceName)!;\n const fieldNames = new Set(resourceSchema.fields.map((f) => f.name));\n\n const rawRecords = await storage.listRecords(resourceName);\n const sortedRecords = sortRecordsById(rawRecords);\n\n const mutations: Record<string, unknown>[] = [];\n let recordIndex = 0;\n\n for (const record of sortedRecords) {\n if (typeof record.id !== \"string\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: record id must be a string\",\n { path: `records[${recordIndex}].id` },\n );\n }\n\n const filteredRecord: Record<string, unknown> = {};\n for (const key of Object.keys(record)) {\n if (key !== \"id\" && fieldNames.has(key)) {\n filteredRecord[key] = record[key];\n }\n }\n\n const hashInput = {\n kind: \"rec\",\n resource: resourceName,\n operation: recordOperation,\n id: record.id,\n record: filteredRecord,\n };\n const hash = computeMutationHash(hashInput);\n const mutationId = `${prefix}:rec:${resourceName}:${record.id}:${hash}`;\n\n mutations.push({\n resource: resourceName,\n version: resourceSchema.version,\n operation: recordOperation,\n id: record.id,\n record: filteredRecord,\n clientId: deps.clientId,\n mutationId,\n });\n\n recordIndex++;\n }\n\n // Only include resources in stats if they have records\n if (sortedRecords.length > 0) {\n result.stats.resources[resourceName] = {\n records: sortedRecords.length,\n mutations: mutations.length,\n };\n }\n\n const batches = batchMutations(mutations, batchSize);\n for (const batch of batches) {\n const pushResult = await pushBatchWithRetry(\n remote,\n deps.clientId,\n batch,\n maxRetries,\n );\n\n result.stats.batches += pushResult.attempts;\n\n if (pushResult.cursor) {\n highestCursor = maxCursorStr(highestCursor, pushResult.cursor);\n }\n\n if (pushResult.errors.length > 0) {\n result.errors.push(...pushResult.errors);\n hasErrors = true;\n if (failFast) {\n result.ok = false;\n result.cursor = highestCursor;\n deps.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: deps.getTimestamp(),\n context: { phase: \"cloneup\", error: { errors: result.errors } },\n });\n return result;\n }\n }\n }\n }\n\n // --- Stage B: Many-many join rows ---\n if (includeManyMany && schema.relations) {\n const resolvedResourceSet = new Set(resolvedResources);\n const joinStoreEntries = enumerateJoinStores(schema.relations, resolvedResourceSet);\n const sortedJoinStoreNames = joinStoreEntries.map((e) => e.storeName).sort();\n\n for (const storeName of sortedJoinStoreNames) {\n const entry = joinStoreEntries.find((e) => e.storeName === storeName)!;\n const { fromResource, relationName, relation } = entry;\n const fromSchema = resourceSchemaMap.get(fromResource)!;\n const metaFieldNames = new Set(\n (relation.metadata ?? []).map((m) => m.name),\n );\n\n let rawJoinRows: Record<string, unknown>[];\n try {\n rawJoinRows = await storage.listJoinRows(storeName);\n } catch {\n rawJoinRows = [];\n }\n\n let rowIndex = 0;\n for (const row of rawJoinRows) {\n if (typeof row.from !== \"string\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: join row from/to must be a string\",\n { path: `joinRows[${rowIndex}].from` },\n );\n }\n if (typeof row.to !== \"string\") {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: join row from/to must be a string\",\n { path: `joinRows[${rowIndex}].to` },\n );\n }\n\n for (const key of Object.keys(row)) {\n if (key === \"from\" || key === \"to\") continue;\n if (!metaFieldNames.has(key)) {\n throw createClientError(\n \"DFQL_UNKNOWN_FIELD\",\n \"Invalid cloneUp: unknown join metadata field\",\n { path: `joinRows[${rowIndex}].${key}` },\n );\n }\n }\n rowIndex++;\n }\n\n const sortedRows = sortJoinRows(rawJoinRows);\n\n const mutations: Record<string, unknown>[] = [];\n for (const row of sortedRows) {\n const metaFiltered: Record<string, unknown> = {};\n for (const key of Object.keys(row)) {\n if (key !== \"from\" && key !== \"to\" && metaFieldNames.has(key)) {\n metaFiltered[key] = row[key];\n }\n }\n\n const hashInput = {\n kind: \"rel\",\n joinStore: storeName,\n resource: fromResource,\n relation: relationName,\n from: row.from,\n to: row.to,\n metadata: metaFiltered,\n };\n const hash = computeMutationHash(hashInput);\n const mutationId = `${prefix}:rel:${storeName}:${row.from}:${row.to}:${hash}`;\n\n mutations.push({\n resource: fromResource,\n version: fromSchema.version,\n operation: \"relate\",\n id: row.from,\n relations: { [relationName]: { $ref: row.to, ...metaFiltered } },\n clientId: deps.clientId,\n mutationId,\n });\n }\n\n result.stats.joinStores[storeName] = {\n rows: rawJoinRows.length,\n mutations: mutations.length,\n };\n\n const batches = batchMutations(mutations, batchSize);\n for (const batch of batches) {\n const pushResult = await pushBatchWithRetry(\n remote,\n deps.clientId,\n batch,\n maxRetries,\n );\n\n result.stats.batches += pushResult.attempts;\n\n if (pushResult.cursor) {\n highestCursor = maxCursorStr(highestCursor, pushResult.cursor);\n }\n\n if (pushResult.errors.length > 0) {\n result.errors.push(...pushResult.errors);\n hasErrors = true;\n if (failFast) {\n result.ok = false;\n result.cursor = highestCursor;\n deps.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: deps.getTimestamp(),\n context: { phase: \"cloneup\", error: { errors: result.errors } },\n });\n return result;\n }\n }\n }\n }\n }\n\n if (hasErrors) {\n result.ok = false;\n }\n\n result.cursor = highestCursor;\n\n if (hasErrors) {\n deps.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: deps.getTimestamp(),\n context: { phase: \"cloneup\", error: { errors: result.errors } },\n });\n return result;\n }\n\n // --- Finalization ---\n const startingCursor = (await storage.getCursor(\"__global_cursor__\")) ?? \"0\";\n\n // pullAfter: catch-up loop from startingCursor\n if (options?.pullAfter !== false) {\n let pullCursor = startingCursor;\n let caughtUp = false;\n\n while (!caughtUp) {\n let pullResponse: any;\n try {\n pullResponse = await remote.pull({\n clientId: deps.clientId,\n cursor: pullCursor,\n limit: 100,\n });\n } catch (err) {\n if (isTransportError(err)) {\n throw err;\n }\n throw err;\n }\n\n const pullResult = pullResponse?.result ?? pullResponse;\n const changes: any[] = pullResult?.changes ?? [];\n const nextCursor: string | null = pullResult?.nextCursor ?? null;\n\n for (const change of changes) {\n if (change.op === \"upsert\" && change.record) {\n await storage.upsertRecord(change.resource, change.record);\n } else if (change.op === \"delete\") {\n await storage.deleteRecord(change.resource, change.id);\n }\n }\n\n if (nextCursor !== null) {\n await setCursorMonotonically(storage, nextCursor);\n pullCursor = nextCursor;\n } else if (changes.length > 0) {\n const lastSeq = String(changes[changes.length - 1].serverSeq);\n await setCursorMonotonically(storage, lastSeq);\n pullCursor = lastSeq;\n caughtUp = true;\n } else {\n caughtUp = true;\n }\n\n if (nextCursor === null) {\n caughtUp = true;\n }\n }\n }\n\n // setGlobalCursorOnSuccess: monotonic set to max push cursor\n if (options?.setGlobalCursorOnSuccess !== false) {\n await setCursorMonotonically(storage, highestCursor);\n }\n\n // clearChangelogOnSuccess: drain changelog\n if (options?.clearChangelogOnSuccess !== false) {\n let draining = true;\n while (draining) {\n const pending = await storage.changelogList({ limit: 1000 });\n if (pending.length === 0) {\n draining = false;\n } else {\n await storage.changelogAck({ throughSeq: pending[pending.length - 1].seq });\n }\n }\n }\n\n deps.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: deps.getTimestamp(),\n context: { phase: \"cloneup\", cursor: result.cursor, stats: result.stats },\n });\n\n return result;\n}\n\nasync function setCursorMonotonically(\n storage: DatafnStorageAdapter,\n newCursor: string,\n): Promise<void> {\n const existing = await storage.getCursor(\"__global_cursor__\");\n const existingNum = parseInt(existing ?? \"0\", 10) || 0;\n const newNum = parseInt(newCursor, 10) || 0;\n if (newNum > existingNum) {\n await storage.setCursor(\"__global_cursor__\", newCursor);\n }\n}\n\nfunction resolveResourceScope(\n schema: DatafnSchema,\n requestedResources?: string[],\n): string[] {\n if (requestedResources) {\n const schemaResourceMap = new Map<string, DatafnResourceSchema>();\n for (const r of schema.resources) {\n schemaResourceMap.set(r.name, r);\n }\n\n for (let i = 0; i < requestedResources.length; i++) {\n const name = requestedResources[i];\n const res = schemaResourceMap.get(name);\n\n if (!res) {\n throw createClientError(\n \"DFQL_UNKNOWN_RESOURCE\",\n \"Invalid cloneUp: unknown resource\",\n { path: `resources[${i}]` },\n );\n }\n\n if (res.isRemoteOnly) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Invalid cloneUp: remote-only resources are not allowed\",\n { path: `resources[${i}]` },\n );\n }\n }\n\n return requestedResources;\n }\n\n return schema.resources\n .filter((r) => !r.isRemoteOnly)\n .map((r) => r.name);\n}\n\ntype JoinStoreEntry = {\n storeName: string;\n fromResource: string;\n relationName: string;\n relation: DatafnRelationSchema;\n};\n\nfunction enumerateJoinStores(\n relations: DatafnRelationSchema[],\n resolvedResourceSet: Set<string>,\n): JoinStoreEntry[] {\n const entries: JoinStoreEntry[] = [];\n\n for (const rel of relations) {\n if (rel.type !== \"many-many\") continue;\n\n const fromResources = Array.isArray(rel.from) ? rel.from : [rel.from];\n const toResources = Array.isArray(rel.to) ? rel.to : [rel.to];\n const relName = rel.relation ?? \"rel\";\n\n for (const f of fromResources) {\n if (!resolvedResourceSet.has(f)) continue;\n for (const t of toResources) {\n entries.push({\n storeName: getJoinStoreKey(f, relName, t),\n fromResource: f,\n relationName: relName,\n relation: rel,\n });\n }\n }\n }\n\n return entries;\n}\n\ntype PushBatchResult = {\n cursor: string | null;\n errors: Array<{ mutationId: string; code: string; message: string; path: string }>;\n attempts: number;\n};\n\nasync function pushBatchWithRetry(\n remote: DatafnRemoteAdapter,\n clientId: string,\n mutations: Record<string, unknown>[],\n maxRetries: number,\n): Promise<PushBatchResult> {\n let attempts = 0;\n\n while (true) {\n attempts++;\n try {\n const response = (await remote.push({\n clientId,\n mutations,\n })) as any;\n\n const pushResult = response?.result ?? response;\n\n return {\n cursor: pushResult?.cursor ?? null,\n errors: pushResult?.errors ?? [],\n attempts,\n };\n } catch (err) {\n if (isTransportError(err) && attempts <= maxRetries) {\n // CLI-010: Exponential backoff between retries\n const backoffMs = 1000 * Math.pow(2, attempts - 1);\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n continue;\n }\n throw err;\n }\n }\n}\n\nfunction maxCursorStr(a: string, b: string): string {\n const an = parseInt(a, 10) || 0;\n const bn = parseInt(b, 10) || 0;\n return an >= bn ? a : b;\n}\n","import { normalizeDfql } from \"@datafn/core\";\n\nconst FNV_OFFSET_BASIS = 0x811c9dc5;\nconst FNV_PRIME = 0x01000193;\n\nexport function fnv1a32(data: Uint8Array): number {\n let hash = FNV_OFFSET_BASIS;\n for (let i = 0; i < data.length; i++) {\n hash ^= data[i];\n hash = Math.imul(hash, FNV_PRIME) >>> 0;\n }\n return hash >>> 0;\n}\n\nconst encoder = new TextEncoder();\n\nexport function computeMutationHash(hashInput: Record<string, unknown>): string {\n const normalized = normalizeDfql(hashInput);\n const json = JSON.stringify(normalized);\n const bytes = encoder.encode(json);\n const hash = fnv1a32(bytes);\n return (hash >>> 0).toString(36);\n}\n","import { dfqlKey } from \"@datafn/core\";\n\nexport function sortRecordsById(\n records: Record<string, unknown>[]\n): Record<string, unknown>[] {\n return [...records].sort((a, b) =>\n String(a.id).localeCompare(String(b.id))\n );\n}\n\nexport function sortJoinRows(\n rows: Record<string, unknown>[]\n): Record<string, unknown>[] {\n return [...rows].sort((a, b) => {\n const fromCmp = String(a.from).localeCompare(String(b.from));\n if (fromCmp !== 0) return fromCmp;\n\n const toCmp = String(a.to).localeCompare(String(b.to));\n if (toCmp !== 0) return toCmp;\n\n const aMeta = extractMeta(a);\n const bMeta = extractMeta(b);\n return dfqlKey(aMeta).localeCompare(dfqlKey(bMeta));\n });\n}\n\nfunction extractMeta(\n row: Record<string, unknown>\n): Record<string, unknown> {\n const { from, to, ...meta } = row;\n return meta;\n}\n","export function batchMutations<T>(mutations: T[], batchSize: number): T[][] {\n if (mutations.length === 0) return [];\n\n const batches: T[][] = [];\n for (let i = 0; i < mutations.length; i += batchSize) {\n batches.push(mutations.slice(i, i + batchSize));\n }\n return batches;\n}\n","/**\n * Sync Facade\n *\n * Client-side sync methods that delegate to remote adapter.\n * When storage is configured, clone/pull results are applied to local storage.\n * Implements HOOK-001 and EVT-003: beforeSync/afterSync hooks and sync lifecycle events\n */\n\nimport type { DatafnRemoteAdapter } from \"./client.js\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nimport { createClientError } from \"./errors.js\";\nimport { applyCloneResult, applyPullResult } from \"./sync/apply.js\";\nimport type { CloneResult, PullResult } from \"./sync/apply.js\";\nimport { cloneUp as executeCloneUp } from \"./sync/cloneUp.js\";\nimport type { CloneUpOptions, CloneUpResult, CloneUpDeps } from \"./sync/cloneUp.js\";\nimport type { DatafnPlugin, DatafnSchema } from \"@datafn/core\";\nimport type { EventBus } from \"./events/bus.js\";\nimport { runBeforeSync, runAfterSync } from \"./plugins/run-hooks.js\";\n\nexport interface SyncFacade {\n seed(payload: unknown): Promise<unknown>;\n clone(payload: unknown): Promise<unknown>;\n pull(payload: unknown): Promise<unknown>;\n push(payload: unknown): Promise<unknown>;\n cloneUp(options?: CloneUpOptions): Promise<CloneUpResult>;\n}\n\n/**\n * Create sync facade that delegates to remote adapter\n * Wraps all sync phases with beforeSync/afterSync hooks (HOOK-001)\n * Emits sync_applied/sync_failed events (EVT-003)\n */\nexport function createSyncFacade(\n remote: DatafnRemoteAdapter,\n storage?: DatafnStorageAdapter,\n cloneUpDeps?: CloneUpDeps,\n plugins: DatafnPlugin[] = [],\n schema?: DatafnSchema,\n eventBus?: EventBus,\n getTimestamp?: () => number,\n): SyncFacade {\n // Helper to get current timestamp\n const timestamp = getTimestamp || (() => Date.now());\n\n /**\n * Wraps a sync method with hooks and event emission\n * Phase-specific logic for each sync method\n */\n const wrapSyncMethod = async <T>(\n phase: \"seed\" | \"clone\" | \"pull\" | \"push\" | \"cloneUp\" | \"reconcile\",\n methodName: keyof DatafnRemoteAdapter,\n payload: unknown,\n applyFn?: (result: T) => Promise<void>,\n ): Promise<T> => {\n try {\n // Run beforeSync hooks (fail-closed) (HOOK-001)\n const transformedPayload = schema\n ? await runBeforeSync(plugins, schema, phase, payload)\n : payload;\n\n // Check if method exists\n const method = remote[methodName];\n if (typeof method !== \"function\") {\n throw createClientError(\n \"TRANSPORT_ERROR\",\n `Transport error: remote method missing: ${methodName}`,\n { path: `sync.${methodName}` },\n );\n }\n\n // Call remote method and unwrap\n const response = await method.call(remote, transformedPayload);\n const result = unwrapRemoteSuccess(response) as T;\n\n // Apply to storage if configured\n if (applyFn) {\n await applyFn(result);\n }\n\n // Run afterSync hooks (fail-open) (HOOK-001)\n if (schema) {\n await runAfterSync(plugins, schema, phase, transformedPayload, result);\n }\n\n // Emit sync_applied event (EVT-003)\n if (eventBus) {\n eventBus.emit({\n type: \"sync_applied\",\n timestampMs: timestamp(),\n context: createSyncEventContext(phase, result),\n });\n }\n\n return result;\n } catch (error: any) {\n // Emit sync_failed event (EVT-003)\n if (eventBus) {\n eventBus.emit({\n type: \"sync_failed\",\n timestampMs: timestamp(),\n context: {\n phase,\n error: {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Sync failed\",\n },\n },\n });\n }\n\n throw error;\n }\n };\n\n /**\n * Create deterministic sync event context (EVT-003)\n * Ensures stable key ordering\n */\n const createSyncEventContext = (phase: string, result: any): Record<string, unknown> => {\n const context: Record<string, unknown> = { phase };\n\n // Add phase-specific context with stable key ordering\n if (phase === \"clone\" && result) {\n if (result.cursors) {\n context.cursors = result.cursors;\n }\n if (result.data) {\n const resources = Object.keys(result.data).sort();\n context.resources = resources;\n }\n }\n\n if (phase === \"pull\" && result) {\n if (result.cursors) {\n context.cursors = result.cursors;\n }\n if (result.records) {\n const resources = Object.keys(result.records).sort();\n context.resources = resources;\n }\n // Calculate cursor delta (difference between new and old cursors)\n if (result.cursors) {\n const cursorDeltas: Record<string, number> = {};\n for (const [resource, newCursor] of Object.entries(result.cursors as Record<string, string>)) {\n cursorDeltas[resource] = parseInt(newCursor, 10);\n }\n context.cursorDelta = cursorDeltas;\n }\n }\n\n if (phase === \"push\" && result) {\n if (result.cursor) {\n context.cursor = result.cursor;\n }\n if (result.applied) {\n context.appliedCount = (result.applied as unknown[]).length;\n }\n }\n\n if (phase === \"reconcile\" && result) {\n if (result.reclonedResources) {\n context.reclonedResources = result.reclonedResources;\n }\n }\n\n if (phase === \"cloneUp\" && result) {\n if ((result as CloneUpResult).uploadedCount !== undefined) {\n context.uploadedCount = (result as CloneUpResult).uploadedCount;\n }\n }\n\n return context;\n };\n\n return {\n async seed(payload: unknown) {\n return wrapSyncMethod(\"seed\", \"seed\", payload);\n },\n\n async clone(payload: unknown) {\n return wrapSyncMethod(\"clone\", \"clone\", payload, async (result) => {\n if (storage) {\n await applyCloneResult(storage, result as CloneResult);\n }\n });\n },\n\n async pull(payload: unknown) {\n return wrapSyncMethod(\"pull\", \"pull\", payload, async (result) => {\n if (storage) {\n await applyPullResult(storage, result as PullResult);\n }\n });\n },\n\n async push(payload: unknown) {\n return wrapSyncMethod(\"push\", \"push\", payload);\n },\n\n async cloneUp(options?: CloneUpOptions): Promise<CloneUpResult> {\n if (!cloneUpDeps) {\n throw createClientError(\n \"INTERNAL\",\n \"Invalid cloneUp: dependencies not configured\",\n { path: \"sync.cloneUp\" },\n );\n }\n\n try {\n // Run beforeSync hooks (fail-closed) (HOOK-001)\n const transformedOptions = schema\n ? await runBeforeSync(plugins, schema, \"cloneUp\", options || {})\n : options;\n\n // Execute cloneUp (note: cloneUp emits its own sync_applied/sync_failed events)\n const result = await executeCloneUp(cloneUpDeps, transformedOptions as CloneUpOptions);\n\n // Run afterSync hooks (fail-open) (HOOK-001)\n if (schema) {\n await runAfterSync(plugins, schema, \"cloneUp\", transformedOptions, result);\n }\n\n // Note: Do NOT emit sync_applied here - executeCloneUp already emits\n // sync_applied (on success) or sync_failed (on errors)\n\n return result;\n } catch (error: any) {\n // Emit sync_failed event only for exceptions (EVT-003)\n // Note: Normal error cases (result.ok = false) are handled by executeCloneUp\n if (eventBus) {\n eventBus.emit({\n type: \"sync_failed\",\n timestampMs: timestamp(),\n context: {\n phase: \"cloneUp\",\n error: {\n code: error.code || \"INTERNAL\",\n message: error.message || \"CloneUp failed\",\n },\n },\n });\n }\n\n throw error;\n }\n },\n };\n}\n","import type { DatafnRemoteAdapter } from \"../client.js\";\n\n/**\n * Default HTTP Transport for DataFn\n * Uses global fetch() to communicate with a remote DataFn server.\n */\nexport class DefaultHttpTransport implements DatafnRemoteAdapter {\n private customFetch: typeof fetch;\n\n constructor(\n private readonly baseUrl: string,\n options?: { fetch?: typeof fetch },\n ) {\n if (baseUrl.endsWith(\"/\")) {\n this.baseUrl = baseUrl.slice(0, -1);\n }\n this.customFetch = options?.fetch || globalThis.fetch.bind(globalThis);\n }\n\n async query(q: unknown): Promise<unknown> {\n // QRY-001: Extract signal from query if present\n let signal: AbortSignal | undefined;\n if (typeof q === \"object\" && q !== null && \"signal\" in q) {\n signal = (q as any).signal;\n }\n return this.post(\"query\", q, signal);\n }\n\n async mutation(m: unknown): Promise<unknown> {\n return this.post(\"mutation\", m);\n }\n\n async transact(t: unknown): Promise<unknown> {\n return this.post(\"transact\", t);\n }\n\n async seed(payload: unknown): Promise<unknown> {\n return this.post(\"seed\", payload);\n }\n\n async clone(payload: unknown): Promise<unknown> {\n return this.post(\"clone\", payload);\n }\n\n async pull(payload: unknown): Promise<unknown> {\n return this.post(\"pull\", payload);\n }\n\n async push(payload: unknown): Promise<unknown> {\n return this.post(\"push\", payload);\n }\n\n async reconcile(payload: unknown): Promise<unknown> {\n return this.post(\"reconcile\", payload);\n }\n\n async search(payload: unknown): Promise<unknown> {\n let signal: AbortSignal | undefined;\n if (typeof payload === \"object\" && payload !== null && \"signal\" in payload) {\n signal = (payload as any).signal;\n }\n return this.post(\"search\", payload, signal);\n }\n\n private async post(endpoint: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n try {\n const response = await this.customFetch(`${this.baseUrl}/${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal, // QRY-001: Pass signal to fetch\n });\n\n if (!response.ok) {\n // Try to parse error envelope if available\n try {\n const errorBody = await response.json();\n // If it looks like a DataFn envelope, return it (it will be unwrapped/checked by caller)\n if (\n errorBody &&\n typeof errorBody === \"object\" &&\n (errorBody.error || errorBody.ok === false)\n ) {\n return errorBody;\n }\n } catch {\n // ignore JSON parse error\n }\n throw new Error(`HTTP Error ${response.status}: ${response.statusText}`);\n }\n\n return response.json();\n } catch (err: any) {\n // QRY-001: Convert AbortError to DFQL_ABORTED\n if (err.name === \"AbortError\") {\n return {\n ok: false,\n error: {\n code: \"DFQL_ABORTED\",\n message: endpoint === \"search\" ? \"Search request aborted\" : \"Query aborted\",\n details: { path: \"signal\" },\n },\n };\n }\n throw err;\n }\n }\n}\n","/**\n * Sync Engine\n *\n * Handles background synchronization tasks:\n * - Push engine (reading changelog -> pushing to remote)\n * - Pull engine (polling/cursor-based updates)\n * - Retries and error handling\n * - Sync event emission\n * Implements HOOK-001 and EVT-003: beforeSync/afterSync hooks and sync lifecycle events\n */\n\nimport type { DatafnStorageAdapter } from \"../storage.js\";\nimport type { DatafnRemoteAdapter, DatafnSyncConfig } from \"../client.js\";\nimport type { EventBus } from \"../events/bus.js\";\nimport type { DatafnSchema, DatafnPlugin, SearchProvider } from \"@datafn/core\";\nimport { enumerateJoinStoreKeys, getJoinStoreKey } from \"@datafn/core\";\nimport {\n applyCloneResult,\n applyPullResult,\n setCursorMonotonically,\n GLOBAL_CURSOR_KEY,\n type CloneResult,\n type PullResult,\n} from \"./apply.js\";\nimport { runBeforeSync, runAfterSync } from \"../plugins/run-hooks.js\";\n// CLI-008: buildEvent import removed (was unused)\n\nconst ACTOR_FEED_CURSOR_KEY = \"__datafn_actor_feed__\";\n\n/**\n * Helper: Sleep for a given number of milliseconds (PHASE_08)\n */\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\n/**\n * Helper: Compute exponential backoff delay with jitter (PHASE_08)\n */\nfunction computeBackoffDelay(\n attempt: number,\n config: { baseDelayMs: number; multiplier: number; maxDelayMs: number; jitterMs: number }\n): number {\n const exponentialDelay = config.baseDelayMs * Math.pow(config.multiplier, attempt);\n const jitter = Math.random() * config.jitterMs;\n return Math.min(exponentialDelay + jitter, config.maxDelayMs);\n}\n\nexport class SyncEngine {\n private static readonly SEARCH_REBUILD_BATCH_SIZE = 1000;\n private inFlight = false;\n private pullInFlight = false;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private pushBatchSize = 100;\n private pushMaxRetries = 3;\n private pushInterval: number | undefined;\n private boundOnVisibilityChange: () => void;\n private boundOnWindowFocus: () => void;\n private boundOnOnline: () => void;\n private boundOnOffline: () => void;\n private isOnline = typeof navigator !== \"undefined\" ? (navigator.onLine ?? true) : true;\n private pushPausedForOffline = false;\n private ws: WebSocket | null = null;\n private wsUrl: string | undefined;\n private hydrationPlan?: {\n bootResources?: string[];\n backgroundResources?: string[];\n clonePageSize?: number | Record<string, number>;\n };\n private plugins: DatafnPlugin[] = [];\n private getTimestamp: () => number;\n private searchProvider?: SearchProvider;\n private wsReconnectAttempt = 0;\n private wsReconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private wsReconnectEnabled = true;\n private config?: DatafnSyncConfig;\n private pushConsecutiveFailures = 0;\n private pushIntervalBackoffActive = false;\n private searchRebuildState: \"idle\" | \"pending\" | \"running\" | \"failed\" | \"completed\" = \"idle\";\n\n constructor(\n private storage: DatafnStorageAdapter,\n private remote: DatafnRemoteAdapter,\n private eventBus: EventBus,\n private clientId: string,\n private schema: DatafnSchema,\n config?: DatafnSyncConfig,\n plugins?: DatafnPlugin[],\n getTimestamp?: () => number,\n searchProvider?: SearchProvider,\n ) {\n this.config = config;\n this.pushBatchSize = config?.pushBatchSize ?? 100;\n this.pushMaxRetries = config?.pushMaxRetries ?? 3;\n this.pushInterval = config?.pushInterval;\n this.boundOnVisibilityChange = this.onVisibilityChange.bind(this);\n this.boundOnWindowFocus = this.onWindowFocus.bind(this);\n this.boundOnOnline = this.onOnline.bind(this);\n this.boundOnOffline = this.onOffline.bind(this);\n this.hydrationPlan = config?.hydration;\n this.plugins = plugins || [];\n this.getTimestamp = getTimestamp || (() => Date.now());\n this.searchProvider = searchProvider;\n\n if (config?.ws && config?.remote) {\n const remote = config.remote;\n const wsProtocol = remote.startsWith(\"https\") ? \"wss\" : \"ws\";\n // Replace protocol (handles http/https)\n const base = remote.replace(/^http(s)?:\\/\\//, \"\");\n this.wsUrl = `${wsProtocol}://${base}/ws`;\n }\n }\n\n /**\n * Start the sync loop (if interval is configured)\n */\n async start() {\n // REL-005: Guard against duplicate push timers — if start() is called twice, skip\n if (this.timer) return;\n\n // 1. Initial sync\n await this.initializeSync();\n\n // 2. Start push loop\n if (this.pushInterval) {\n this.timer = setInterval(() => this.processPush(), this.pushInterval);\n }\n\n // 3. Register visibility listener, focus listener, and online/offline listeners\n if (typeof document !== \"undefined\" && document.addEventListener) {\n document.addEventListener(\n \"visibilitychange\",\n this.boundOnVisibilityChange,\n );\n }\n if (typeof window !== \"undefined\" && window.addEventListener) {\n window.addEventListener(\"focus\", this.boundOnWindowFocus);\n // Read current connectivity state\n this.isOnline = typeof navigator !== \"undefined\" ? (navigator.onLine ?? true) : true;\n window.addEventListener(\"online\", this.boundOnOnline);\n window.addEventListener(\"offline\", this.boundOnOffline);\n }\n\n // 4. Connect WebSocket\n if (this.wsUrl) {\n this.connectWs();\n }\n }\n\n /**\n * Stop the sync loop\n */\n stop() {\n // Disable reconnection\n this.wsReconnectEnabled = false;\n \n // Clear reconnection timer\n if (this.wsReconnectTimer) {\n clearTimeout(this.wsReconnectTimer);\n this.wsReconnectTimer = null;\n }\n \n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (typeof document !== \"undefined\" && document.removeEventListener) {\n document.removeEventListener(\n \"visibilitychange\",\n this.boundOnVisibilityChange,\n );\n }\n if (typeof window !== \"undefined\" && window.removeEventListener) {\n window.removeEventListener(\"focus\", this.boundOnWindowFocus);\n window.removeEventListener(\"online\", this.boundOnOnline);\n window.removeEventListener(\"offline\", this.boundOnOffline);\n }\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n /**\n * Connect WebSocket for real-time updates\n */\n private connectWs() {\n if (typeof WebSocket === \"undefined\" || !this.wsUrl) return;\n\n try {\n this.ws = new WebSocket(this.wsUrl);\n\n this.ws.onopen = async () => {\n // Reset reconnection attempt counter on successful connection\n this.wsReconnectAttempt = 0;\n\n const cursors = await this.buildPullCursors();\n \n // Send hello with current cursors\n this.ws?.send(\n JSON.stringify({\n type: \"hello\",\n clientId: this.clientId,\n cursors,\n }),\n );\n \n // Emit ws_connected event\n this.eventBus.emit({\n type: \"ws_connected\",\n timestampMs: this.getTimestamp(),\n });\n };\n\n this.ws.onmessage = async (event) => {\n try {\n const msg = JSON.parse(event.data);\n if (msg.type === \"cursor\" && msg.cursor) {\n const stored =\n (await this.storage.getCursor(GLOBAL_CURSOR_KEY)) || \"0\";\n const serverSeq = parseInt(msg.cursor, 10);\n const storedSeq = parseInt(stored, 10);\n\n if (serverSeq > storedSeq) {\n // REL-015: use .catch() to prevent unhandled promise rejection in WS message handler\n this.pullNow().catch((err) =>\n console.warn(\"[datafn] pullNow error in WS message handler:\", err)\n );\n }\n }\n } catch (e) {\n // Ignore invalid messages\n }\n };\n\n this.ws.onerror = (e) => {\n console.error(\"WebSocket error:\", e);\n };\n\n this.ws.onclose = () => {\n this.ws = null;\n \n // Emit ws_disconnected event\n this.eventBus.emit({\n type: \"ws_disconnected\",\n timestampMs: this.getTimestamp(),\n });\n \n // Schedule reconnection if enabled\n if (this.wsReconnectEnabled && this.config?.wsReconnect?.enabled !== false) {\n this.scheduleReconnect();\n }\n };\n } catch (e) {\n console.error(\"Failed to connect WebSocket:\", e);\n }\n }\n\n /**\n * Schedule WebSocket reconnection with exponential backoff and jitter\n */\n private scheduleReconnect() {\n const { \n baseDelayMs = 1000, \n multiplier = 2, \n maxDelayMs = 60000, \n jitterMs = 500 \n } = this.config?.wsReconnect ?? {};\n \n // Calculate delay with exponential backoff: baseDelayMs * multiplier^attempt\n const exponentialDelay = baseDelayMs * Math.pow(multiplier, this.wsReconnectAttempt);\n \n // Add random jitter to prevent thundering herd\n const jitter = Math.random() * jitterMs;\n \n // Cap at maxDelayMs\n const delay = Math.min(exponentialDelay + jitter, maxDelayMs);\n \n this.wsReconnectTimer = setTimeout(() => {\n this.wsReconnectAttempt++;\n this.connectWs();\n }, delay);\n }\n\n /**\n * Visibility change handler (TV-PULL-002)\n */\n private onVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n this.pullNow();\n }\n }\n\n /**\n * Window focus handler — triggers pull when user returns to the app window.\n * Mirrors the Nucleus `onAppear` pattern (`<svelte:window on:focus={onAppear} />`).\n * pullNow() has an in-flight guard so rapid focus events won't cause duplicate pulls.\n */\n private onWindowFocus() {\n this.pullNow();\n }\n\n /**\n * Online handler — emits connectivity_changed, resumes push loop, triggers immediate sync.\n */\n private onOnline() {\n this.isOnline = true;\n this.eventBus.emit({\n type: \"connectivity_changed\",\n timestampMs: this.getTimestamp(),\n context: { isOnline: true },\n });\n\n // Resume push interval if it was paused for offline\n if (this.pushPausedForOffline && this.pushInterval) {\n this.pushPausedForOffline = false;\n this.timer = setInterval(() => this.processPush(), this.pushInterval);\n }\n\n // Trigger immediate sync\n this.pullNow();\n setTimeout(() => this.processPush(), 0);\n }\n\n /**\n * Offline handler — emits connectivity_changed and pauses the push interval.\n */\n private onOffline() {\n this.isOnline = false;\n this.eventBus.emit({\n type: \"connectivity_changed\",\n timestampMs: this.getTimestamp(),\n context: { isOnline: false },\n });\n\n // Pause the regular push interval to save battery (skip backoff timer — it will expire on its own)\n if (this.timer && this.pushInterval && !this.pushIntervalBackoffActive) {\n clearInterval(this.timer);\n this.timer = null;\n this.pushPausedForOffline = true;\n }\n }\n\n private async buildPullCursors(): Promise<Record<string, string>> {\n const cursors: Record<string, string> = {};\n\n for (const res of this.schema.resources) {\n if (res.isRemoteOnly) continue;\n const cursor = await this.storage.getCursor(res.name) || \"0\";\n cursors[res.name] = cursor;\n }\n\n if (this.schema.relations) {\n for (const joinStoreKey of enumerateJoinStoreKeys(this.schema.relations)) {\n cursors[joinStoreKey] = await this.storage.getCursor(joinStoreKey) || \"0\";\n }\n }\n\n cursors[ACTOR_FEED_CURSOR_KEY] =\n await this.storage.getCursor(ACTOR_FEED_CURSOR_KEY) || \"0\";\n\n return cursors;\n }\n\n /**\n * Initialize sync: Clone if fresh, Pull if hydrated (SYNC-PULL-001)\n * Supports hydration plan: clone bootResources first, then backgroundResources (SYNC-002)\n */\n async initializeSync() {\n // If hydration plan is provided, use it\n if (this.hydrationPlan?.bootResources || this.hydrationPlan?.backgroundResources) {\n await this.initializeWithHydrationPlan();\n return;\n }\n\n // Default behavior: check if all tables need clone\n let needsClone = false;\n\n for (const res of this.schema.resources) {\n if (res.isRemoteOnly) continue;\n const state = await this.storage.getHydrationState(res.name);\n if (state !== \"ready\") {\n needsClone = true;\n break;\n }\n }\n\n if (needsClone) {\n await this.cloneNow();\n } else {\n await this.pullNow();\n }\n }\n\n /**\n * Initialize with hydration plan (SYNC-002)\n * Only clones resources that are not yet in \"ready\" state; pulls for the rest.\n */\n private async initializeWithHydrationPlan() {\n const { bootResources = [], backgroundResources = [] } = this.hydrationPlan!;\n\n // Auto-include schema resources not listed in any plan bucket and not remote-only.\n // Framework-injected resources (e.g. \"kv\") are never added to user hydration plans,\n // so they would otherwise stay at \"notStarted\" forever, causing every query to fall\n // back to the remote server (RC-1 / issue 2026-03-02-k7m4x9r8).\n const plannedResources = new Set([...bootResources, ...backgroundResources]);\n const unplannedResources = this.schema.resources\n .filter((r) => !r.isRemoteOnly && !plannedResources.has(r.name))\n .map((r) => r.name);\n\n // Merge unplanned resources into boot (they are typically small — kv is tiny)\n const effectiveBootResources = [...bootResources, ...unplannedResources];\n\n // Partition boot resources into those needing clone vs already ready\n const bootNeedingClone: string[] = [];\n for (const table of effectiveBootResources) {\n const state = await this.storage.getHydrationState(table);\n if (state !== \"ready\") {\n bootNeedingClone.push(table);\n }\n }\n\n if (bootNeedingClone.length > 0) {\n await this.cloneResources(bootNeedingClone);\n }\n\n // If all boot resources were already ready, do a pull to catch up on missed changes\n if (bootNeedingClone.length === 0 && effectiveBootResources.length > 0) {\n await this.pullNow();\n }\n\n // Partition background resources the same way\n const bgNeedingClone: string[] = [];\n for (const table of backgroundResources) {\n const state = await this.storage.getHydrationState(table);\n if (state !== \"ready\") {\n bgNeedingClone.push(table);\n }\n }\n\n if (bgNeedingClone.length > 0) {\n this.cloneResourcesInBackground(bgNeedingClone);\n }\n }\n\n private emitSearchRebuildProgress(\n stage: \"pending\" | \"running\" | \"failed\" | \"completed\",\n indexedRecords: number,\n totalRecords: number,\n error?: { code: string; message: string },\n ) {\n const percent = totalRecords === 0 ? 100 : Math.min(100, Math.floor((indexedRecords / totalRecords) * 100));\n if (stage === \"failed\") {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"search-rebuild\",\n stage,\n indexedRecords,\n totalRecords,\n percent,\n error,\n },\n });\n return;\n }\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"search-rebuild\",\n stage,\n indexedRecords,\n totalRecords,\n percent,\n },\n });\n }\n\n private scheduleSearchRebuild(resources: string[], attempt = 0) {\n if (!this.searchProvider || resources.length === 0) return;\n this.searchRebuildState = \"pending\";\n this.emitSearchRebuildProgress(\"pending\", 0, 0);\n setTimeout(() => {\n this.rebuildSearchIndices(resources, attempt).catch(() => {\n // Failures are emitted in rebuildSearchIndices.\n });\n }, 0);\n }\n\n private async rebuildSearchIndices(resources: string[], attempt = 0): Promise<void> {\n if (!this.searchProvider) return;\n\n let totalRecords = 0;\n for (const resource of resources) {\n const records = await this.storage.listRecords(resource);\n totalRecords += records.length;\n }\n\n this.searchRebuildState = \"running\";\n this.emitSearchRebuildProgress(\"running\", 0, totalRecords);\n\n let indexedRecords = 0;\n try {\n for (const resource of resources) {\n const records = await this.storage.listRecords(resource);\n for (\n let offset = 0;\n offset < records.length;\n offset += SyncEngine.SEARCH_REBUILD_BATCH_SIZE\n ) {\n const batch = records.slice(offset, offset + SyncEngine.SEARCH_REBUILD_BATCH_SIZE);\n if (batch.length === 0) continue;\n await this.searchProvider.updateIndices({\n resource,\n records: batch,\n operation: \"upsert\",\n });\n indexedRecords += batch.length;\n this.emitSearchRebuildProgress(\"running\", indexedRecords, totalRecords);\n }\n }\n this.searchRebuildState = \"completed\";\n this.emitSearchRebuildProgress(\"completed\", totalRecords, totalRecords);\n } catch (error: any) {\n this.searchRebuildState = \"failed\";\n this.emitSearchRebuildProgress(\"failed\", indexedRecords, totalRecords, {\n code: error?.code || \"INTERNAL\",\n message: error?.message || \"Search rebuild failed\",\n });\n // Allow retry without data loss: retry once asynchronously.\n if (attempt < 1) {\n this.scheduleSearchRebuild(resources, attempt + 1);\n }\n }\n }\n\n /**\n * Clone specific resources and wait for completion\n * Implements HOOK-001 and EVT-003\n */\n private async cloneResources(tables: string[]) {\n try {\n // Mark tables as hydrating\n for (const table of tables) {\n await this.storage.setHydrationState(table, \"hydrating\");\n }\n\n // Prepare payload for hooks\n const payload = {\n clientId: this.clientId,\n tables,\n includeJoins: true,\n };\n\n // Run beforeSync hooks (fail-closed) (HOOK-001)\n const transformedPayload = await runBeforeSync(\n this.plugins,\n this.schema,\n \"clone\",\n payload,\n );\n\n // Clone with pagination if configured\n const pageSize = this.getClonePageSize(tables[0]); // Use first table for now\n const skipCloneIndexing = this.config?.skipCloneIndexing === true;\n let result: CloneResult;\n \n if (pageSize && pageSize < 1000) {\n // Use pagination\n for (const table of tables) {\n await this.cloneTablePaginated(table, pageSize, !skipCloneIndexing);\n }\n // Create a synthetic result for event emission\n result = { ok: true, data: {}, cursors: {}, next: {} };\n if (this.searchProvider && skipCloneIndexing) {\n this.scheduleSearchRebuild(tables);\n }\n } else {\n // Clone all at once\n const response: any = await this.remote.clone(transformedPayload);\n\n if (response.ok && response.result?.ok) {\n result = response.result as CloneResult;\n await applyCloneResult(this.storage, result);\n if (this.searchProvider) {\n if (skipCloneIndexing) {\n this.scheduleSearchRebuild(tables);\n } else {\n for (const [resource, records] of Object.entries(result.data)) {\n if (records.length > 0) {\n try {\n await this.searchProvider.updateIndices({ resource, records, operation: \"upsert\" });\n } catch (e) {\n // fail-soft\n }\n }\n }\n }\n }\n } else {\n throw new Error(response.error?.message || \"Clone rejected by server\");\n }\n }\n\n // Ensure every requested table reaches \"ready\" even if the server returned no\n // records for it (RC-4 / issue 2026-03-02-k7m4x9r8). applyCloneResult only\n // marks a resource \"ready\" when it appears in the response data object, so a\n // resource with zero records would be left stuck at \"hydrating\".\n for (const table of tables) {\n const state = await this.storage.getHydrationState(table);\n if (state !== \"ready\") {\n await this.storage.setHydrationState(table, \"ready\");\n }\n }\n\n // Run afterSync hooks (fail-open) (HOOK-001)\n await runAfterSync(\n this.plugins,\n this.schema,\n \"clone\",\n transformedPayload,\n result,\n );\n\n // Emit sync_applied event (EVT-003)\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"clone\",\n resources: tables.sort(), // Stable sort for determinism\n cursors: result.cursors || {},\n },\n });\n } catch (err: any) {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"clone\",\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Clone failed\",\n },\n },\n });\n throw err;\n }\n }\n\n /**\n * Clone resources in the background (non-blocking)\n */\n private cloneResourcesInBackground(tables: string[]) {\n // REL-006: Schedule async clone with error handling\n setTimeout(async () => {\n try {\n await this.cloneResources(tables);\n } catch (error: any) {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"clone\",\n operation: \"background\",\n error: {\n code: error.code || \"INTERNAL\",\n message: error.message || \"Background clone failed\",\n },\n tables,\n },\n });\n // Mark tables as failed, not stuck in hydrating\n for (const table of tables) {\n try {\n await this.storage.setHydrationState(table, \"notStarted\");\n } catch {\n // Best-effort state update\n }\n }\n }\n }, 0);\n }\n\n /**\n * Clone a single table with pagination\n */\n private async cloneTablePaginated(table: string, pageSize: number, indexAfterPage: boolean) {\n let afterId: string | null = null;\n let hasMore = true;\n\n while (hasMore) {\n const response: any = await this.remote.clone({\n clientId: this.clientId,\n tables: [table],\n page: {\n table,\n afterId,\n limit: pageSize,\n },\n includeJoins: true,\n });\n\n if (response.ok && response.result?.ok) {\n const cloneResult = response.result as CloneResult;\n await applyCloneResult(this.storage, cloneResult);\n if (indexAfterPage && this.searchProvider) {\n const records = cloneResult.data?.[table] ?? [];\n if (records.length > 0) {\n try {\n await this.searchProvider.updateIndices({\n resource: table,\n records,\n operation: \"upsert\",\n });\n } catch {\n // fail-soft\n }\n }\n }\n \n // Check if there are more pages\n const nextMarker = response.result.next?.[table];\n if (nextMarker === null || nextMarker === undefined) {\n hasMore = false;\n } else {\n afterId = nextMarker;\n }\n } else {\n throw new Error(response.error?.message || \"Clone rejected by server\");\n }\n }\n }\n\n /**\n * Get clone page size for a specific table\n */\n private getClonePageSize(table: string): number {\n const config = this.hydrationPlan?.clonePageSize;\n \n if (typeof config === \"number\") {\n return config;\n }\n \n if (typeof config === \"object\" && config[table]) {\n return config[table];\n }\n \n return 1000; // Default\n }\n\n /**\n * Perform a full clone\n * Implements HOOK-001 and EVT-003\n */\n async cloneNow() {\n const tables = this.schema.resources\n .filter((r) => !r.isRemoteOnly)\n .map((r) => r.name);\n\n if (tables.length === 0) {\n // No tables to clone, emit success event\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: { phase: \"clone\", resources: [] },\n });\n return;\n }\n\n // Delegate to cloneResources which handles hooks and events\n await this.cloneResources(tables);\n }\n\n /**\n * Perform an incremental pull (SYNC-PULL-003)\n * Uses per-table cursors when storage is enabled (PHASE_05)\n * Implements HOOK-001 and EVT-003\n */\n async pullNow() {\n if (this.pullInFlight) return;\n this.pullInFlight = true;\n\n try {\n const cursors = await this.buildPullCursors();\n\n // Use canonical per-table cursor pull if we have cursors\n if (Object.keys(cursors).length > 0) {\n await this.pullWithPerTableCursors(cursors);\n } else {\n // No resources to pull, emit success event\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: { phase: \"pull\", resources: [] },\n });\n }\n } catch (err: any) {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"pull\",\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Pull failed\",\n },\n },\n });\n } finally {\n this.pullInFlight = false;\n }\n }\n\n /**\n * Pull using per-table cursors (canonical protocol, PHASE_05)\n * Implements catch-up loop (CLIENT-PULL-002, CLIENT-PULL-003, CLIENT-PULL-004)\n * and HOOK-001/EVT-003 once across all iterations.\n */\n private async pullWithPerTableCursors(cursors: Record<string, string>) {\n try {\n // Prepare payload for hooks\n // CFG-001: Use configurable pullBatchSize, default to 200\n const payload = {\n clientId: this.clientId,\n cursors,\n limit: this.config?.pullBatchSize ?? 200,\n includeJoins: true,\n };\n\n // Run beforeSync hooks once before the loop (CLIENT-PULL-004, HOOK-001)\n const transformedPayload = await runBeforeSync(\n this.plugins,\n this.schema,\n \"pull\",\n payload,\n );\n\n // Catch-up loop (CLIENT-PULL-002, CLIENT-PULL-003)\n const maxIterations = this.config?.maxPullIterations ?? 50;\n let iterationCursors: Record<string, string> = { ...(transformedPayload as any).cursors };\n let hasMore = true;\n let iterations = 0;\n let lastResult: any = null;\n\n while (hasMore && iterations < maxIterations) {\n iterations++;\n\n const iterPayload = { ...(transformedPayload as object), cursors: iterationCursors };\n const response: any = await this.remote.pull(iterPayload);\n\n if (response.ok && response.result?.ok) {\n lastResult = response.result;\n await applyPullResult(this.storage, lastResult);\n if (this.searchProvider && lastResult) {\n try {\n if (lastResult.records) {\n for (const [resource, records] of Object.entries(lastResult.records as Record<string, unknown[]>)) {\n if ((records as unknown[]).length > 0) {\n await this.searchProvider.updateIndices({ resource, records: records as Record<string, unknown>[], operation: \"upsert\" });\n }\n }\n }\n if (lastResult.deleted) {\n for (const [resource, ids] of Object.entries(lastResult.deleted as Record<string, string[]>)) {\n for (const id of ids as string[]) {\n await this.searchProvider.updateIndices({ resource, records: [{ id }], operation: \"delete\" });\n }\n }\n }\n } catch (e) {\n // fail-soft\n }\n }\n\n hasMore = lastResult.hasMore === true;\n if (hasMore && lastResult.cursors) {\n // Advance cursors for the next iteration (monotonic)\n iterationCursors = { ...iterationCursors, ...lastResult.cursors };\n }\n } else {\n throw new Error(response.error?.message || \"Pull rejected by server\");\n }\n }\n\n // CLIENT-PULL-003: warn if max iterations reached while hasMore is still true\n if (iterations >= maxIterations && hasMore) {\n console.warn(\n `[datafn] Pull catch-up reached max iterations (${maxIterations}), stopping. Will resume on next sync cycle.`,\n );\n }\n\n if (!lastResult) {\n return;\n }\n\n // Run afterSync hooks once after loop exits (CLIENT-PULL-004, HOOK-001)\n await runAfterSync(\n this.plugins,\n this.schema,\n \"pull\",\n transformedPayload,\n lastResult,\n );\n\n // Calculate aggregated cursor delta (initial cursors vs final cursors)\n const cursorDelta: Record<string, number> = {};\n if (lastResult.cursors) {\n for (const [resource, newCursor] of Object.entries(lastResult.cursors)) {\n const oldCursor = cursors[resource] || \"0\";\n const delta =\n parseInt(newCursor as string, 10) - parseInt(oldCursor, 10);\n if (delta > 0) {\n cursorDelta[resource] = delta;\n }\n }\n }\n\n // Emit sync_applied once after all iterations (CLIENT-PULL-004, EVT-003)\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"pull\",\n cursors: lastResult.cursors || {},\n cursorDelta,\n resources: lastResult.records\n ? Object.keys(lastResult.records).sort()\n : [],\n },\n });\n } catch (err: any) {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"pull\",\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Pull failed\",\n },\n },\n });\n throw err;\n }\n }\n\n /**\n * Perform reconcile to detect and repair drift (SYNC-007)\n * Compares local counts with server counts and triggers re-clone for mismatches\n * Implements HOOK-001 and EVT-003\n */\n async reconcileNow() {\n try {\n // Run beforeSync hooks (fail-closed) (HOOK-001)\n const payload = {\n clientId: this.clientId,\n resources: this.schema.resources\n .filter((r) => !r.isRemoteOnly)\n .map((r) => r.name),\n includeJoins: true,\n };\n\n const transformedPayload = await runBeforeSync(\n this.plugins,\n this.schema,\n \"reconcile\",\n payload,\n );\n\n // Check if remote adapter supports reconcile\n if (!this.remote.reconcile) {\n throw new Error(\"Remote adapter does not support reconcile\");\n }\n\n // Call server reconcile endpoint\n const response: any = await this.remote.reconcile(transformedPayload);\n\n if (!response.ok || !response.result?.ok) {\n throw new Error(response.error?.message || \"Reconcile rejected by server\");\n }\n\n const result = response.result;\n const serverCounts = result.counts || {};\n const serverJoinCounts = result.joinCounts || {};\n\n // Compare local counts with server counts\n const mismatchedResources: string[] = [];\n const resources = (transformedPayload as any).resources;\n\n for (const resource of resources) {\n const localCount = await this.storage.countRecords(resource);\n const serverCount = serverCounts[resource] || 0;\n\n if (localCount !== serverCount) {\n mismatchedResources.push(resource);\n }\n }\n\n // Check join counts if includeJoins was requested\n if (this.schema.relations) {\n for (const relation of this.schema.relations) {\n if (relation.type !== \"many-many\") continue;\n\n // DI-004: from/to may be string[] — enumerate all join store key combinations\n const fromArr = Array.isArray(relation.from)\n ? relation.from as string[]\n : [relation.from as string];\n const toArr = Array.isArray(relation.to)\n ? relation.to as string[]\n : [relation.to as string];\n\n for (const fromTable of fromArr) {\n for (const toTable of toArr) {\n const joinStoreKey = getJoinStoreKey(fromTable, relation.relation!, toTable);\n const localJoinCount = await this.storage.countJoinRows(joinStoreKey);\n const serverJoinCount = serverJoinCounts[joinStoreKey] || 0;\n\n if (localJoinCount !== serverJoinCount) {\n if (!mismatchedResources.includes(fromTable)) {\n mismatchedResources.push(fromTable);\n }\n if (!mismatchedResources.includes(toTable)) {\n mismatchedResources.push(toTable);\n }\n }\n }\n }\n }\n }\n\n // Trigger re-clone for mismatched resources\n if (mismatchedResources.length > 0) {\n await this.cloneResources(mismatchedResources);\n }\n\n // Prepare result for hooks and events\n const reconcileResult = {\n ...result,\n reclonedResources: mismatchedResources,\n };\n\n // Run afterSync hooks (fail-open) (HOOK-001)\n await runAfterSync(\n this.plugins,\n this.schema,\n \"reconcile\",\n transformedPayload,\n reconcileResult,\n );\n\n // Emit sync_applied event (EVT-003)\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"reconcile\",\n reclonedResources: mismatchedResources.sort(), // Stable sort for determinism\n },\n });\n } catch (err: any) {\n // Emit sync_failed event (EVT-003)\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"reconcile\",\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Reconcile failed\",\n },\n },\n });\n throw err;\n }\n }\n\n /**\n * Schedule a push attempt.\n * If interval is set, this is a no-op (loop handles it).\n * If no interval, schedules immediate execution.\n */\n schedulePush() {\n if (!this.pushInterval) {\n // Schedule on next tick\n setTimeout(() => this.processPush(), 0);\n }\n }\n\n /**\n * Compute interval backoff delay when push keeps failing\n */\n private computePushIntervalBackoff(): number {\n if (!this.pushInterval || this.pushConsecutiveFailures === 0) {\n return this.pushInterval || 0;\n }\n\n const backoffConfig = {\n baseMultiplier: this.config?.pushIntervalBackoff?.baseMultiplier ?? 2,\n maxDelayMs: this.config?.pushIntervalBackoff?.maxDelayMs ?? 300000, // 5 minutes\n jitterMs: this.config?.pushIntervalBackoff?.jitterMs ?? 1000,\n };\n\n // Exponential backoff: pushInterval * multiplier^consecutiveFailures\n const exponentialDelay =\n this.pushInterval *\n Math.pow(backoffConfig.baseMultiplier, this.pushConsecutiveFailures);\n\n // Add jitter\n const jitter = Math.random() * backoffConfig.jitterMs;\n\n // Cap at maxDelayMs\n return Math.min(exponentialDelay + jitter, backoffConfig.maxDelayMs);\n }\n\n /**\n * Process pending changelog entries\n */\n async processPush() {\n if (this.inFlight) return;\n // Fast-fail: skip push when browser reports offline — saves battery and avoids doomed requests.\n // The existing retry-with-backoff logic remains authoritative for transport failures.\n if (!this.isOnline) return;\n this.inFlight = true;\n\n try {\n // 1. Read pending changelog\n const pending = await this.storage.changelogList({\n limit: this.pushBatchSize,\n });\n\n if (pending.length === 0) {\n this.inFlight = false;\n return;\n }\n\n const mutations = pending.map((p) => p.mutation);\n const throughSeq = pending[pending.length - 1].seq;\n\n // 2. Push with retries\n const pushResult = await this.pushWithRetries(mutations);\n\n if (pushResult) {\n // Success: reset consecutive failures\n this.pushConsecutiveFailures = 0;\n\n // If we were in backoff mode, re-establish the regular interval\n if (this.pushIntervalBackoffActive && this.pushInterval) {\n this.pushIntervalBackoffActive = false;\n // Clear any pending backoff timer\n if (this.timer) {\n clearTimeout(this.timer);\n }\n // Re-establish the regular interval\n this.timer = setInterval(() => this.processPush(), this.pushInterval);\n }\n\n // 3. Ack on success\n await this.storage.changelogAck({ throughSeq });\n\n // 3a. Advance per-table cursors from push response (FIX-B)\n // This prevents the client from re-fetching its own changes on the next pull.\n if (pushResult.cursors) {\n for (const [resource, cursor] of Object.entries(pushResult.cursors)) {\n await setCursorMonotonically(this.storage, resource, cursor);\n }\n }\n\n // Trigger pull if foreign changes exist since last sync (SYNC-PULL-002)\n if (pushResult.cursor) {\n const stored =\n (await this.storage.getCursor(GLOBAL_CURSOR_KEY)) || \"0\";\n const storedSeq = parseInt(stored, 10);\n\n if (pushResult.cursorBefore !== undefined) {\n // cursorBefore = global seq before this push allocated any sequences.\n // If cursorBefore == storedSeq, no other client wrote changes since our last\n // pull — advance the global cursor locally and skip the redundant pull.\n // If cursorBefore != storedSeq, foreign changes exist — pull to fetch them.\n const beforeSeq = parseInt(pushResult.cursorBefore, 10);\n if (beforeSeq === storedSeq) {\n // No foreign changes — advance cursor locally (global) and skip pull\n await setCursorMonotonically(this.storage, GLOBAL_CURSOR_KEY, pushResult.cursor);\n } else {\n // Foreign changes exist — pull to fetch them\n setTimeout(() => this.pullNow(), 0);\n }\n } else {\n // Server did not return cursorBefore; use cursor comparison.\n const serverSeq = parseInt(pushResult.cursor, 10);\n if (serverSeq > storedSeq) {\n setTimeout(() => this.pullNow(), 0);\n }\n }\n }\n\n // If we filled the batch, there might be more\n if (pending.length === this.pushBatchSize) {\n // Schedule next batch immediately\n setTimeout(() => this.processPush(), 0);\n }\n } else {\n // Failure: increment consecutive failures and apply interval backoff\n this.pushConsecutiveFailures++;\n\n if (this.pushInterval) {\n // Clear the regular interval and switch to backoff mode\n if (this.timer && !this.pushIntervalBackoffActive) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.pushIntervalBackoffActive = true;\n\n // Compute backoff delay\n const backoffDelay = this.computePushIntervalBackoff();\n\n // Schedule next push with backoff delay\n this.timer = setTimeout(() => {\n this.processPush();\n }, backoffDelay);\n }\n }\n } catch (err) {\n console.error(\"Sync engine internal error\", err);\n } finally {\n this.inFlight = false;\n }\n }\n\n /**\n * Push mutations with retry policy\n * Returns result if successful, null if exhausted retries\n * Implements HOOK-001, EVT-003, and RET-001 (exponential backoff)\n */\n private async pushWithRetries(\n mutations: any[],\n ): Promise<{ ok: boolean; cursor?: string; cursorBefore?: string; cursors?: Record<string, string> } | null> {\n let attempt = 0;\n // Initial attempt (0) + retries\n const maxAttempts = 1 + this.pushMaxRetries;\n\n // Get backoff configuration (PHASE_08: RET-001)\n const backoffConfig = {\n baseDelayMs: this.config?.pushRetryBackoff?.baseDelayMs ?? 1000,\n multiplier: this.config?.pushRetryBackoff?.multiplier ?? 2,\n maxDelayMs: this.config?.pushRetryBackoff?.maxDelayMs ?? 60000,\n jitterMs: this.config?.pushRetryBackoff?.jitterMs ?? 500,\n };\n\n // Prepare payload for hooks\n const payload = {\n clientId: this.clientId,\n mutations,\n };\n\n // Run beforeSync hooks (fail-closed) (HOOK-001)\n let transformedPayload: any;\n try {\n transformedPayload = await runBeforeSync(\n this.plugins,\n this.schema,\n \"push\",\n payload,\n );\n } catch (err: any) {\n // beforeSync failed, emit sync_failed and return\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"push\",\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Push beforeSync hook failed\",\n },\n },\n });\n return null;\n }\n\n while (attempt < maxAttempts) {\n attempt++;\n try {\n const response: any = await this.remote.push(transformedPayload);\n\n if (response.ok && response.result?.ok) {\n const result = response.result;\n\n // Run afterSync hooks (fail-open) (HOOK-001)\n await runAfterSync(\n this.plugins,\n this.schema,\n \"push\",\n transformedPayload,\n result,\n );\n\n // Emit sync_applied event (EVT-003)\n this.eventBus.emit({\n type: \"sync_applied\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"push\",\n cursor: result.cursor || null,\n appliedCount: result.applied ? result.applied.length : 0,\n },\n });\n\n // Success (backoff resets on next call)\n return result;\n } else {\n // Protocol error (e.g. invalid clientId) or server rejection\n throw new Error(response.error?.message || \"Push rejected by server\");\n }\n } catch (err: any) {\n // If this was the last attempt\n if (attempt === maxAttempts) {\n this.eventBus.emit({\n type: \"sync_failed\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"push\",\n attempts: attempt,\n error: {\n code: err.code || \"INTERNAL\",\n message: err.message || \"Push failed\",\n },\n },\n });\n return null;\n }\n \n // Compute backoff delay (PHASE_08: RET-001)\n // Note: attempt is 1-indexed (first attempt is 1), so use attempt-1 for backoff calculation\n const delay = computeBackoffDelay(attempt - 1, backoffConfig);\n \n // Emit sync_retry event (PHASE_08: RET-001)\n this.eventBus.emit({\n type: \"sync_retry\",\n timestampMs: this.getTimestamp(),\n context: {\n phase: \"push\",\n attempt,\n delayMs: delay,\n },\n });\n \n // Wait before next retry\n await sleep(delay);\n // Loop to retry\n }\n }\n\n return null;\n }\n}\n","/**\n * KV API implementation for datafn\n * Provides a first-class key-value store that works with signals and events.\n */\n\nimport { kvId, KV_RESOURCE_NAME, type DatafnSignal } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport { EventBus } from \"./events/bus.js\";\nimport type { DatafnTable } from \"./tables/table.js\";\nimport { DebouncerMap } from \"./debounce.js\";\n\n// Re-export for convenience\nexport { kvId, KV_RESOURCE_NAME } from \"@datafn/core\";\n\nexport interface DatafnKvApi {\n get<T = unknown>(key: string): Promise<T | null>;\n set<T = unknown>(\n key: string,\n value: T,\n params?: { context?: Record<string, unknown>; debounceMs?: number },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }>;\n merge(\n key: string,\n patch: Record<string, unknown>,\n params?: { context?: Record<string, unknown>; debounceMs?: number },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }>;\n delete(\n key: string,\n params?: { context?: Record<string, unknown> },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }>;\n getOrSeed<T = unknown>(key: string, defaults: T): Promise<T>;\n flush(key?: string): Promise<void>;\n signal<T = unknown>(\n key: string,\n options?: { defaultValue?: T },\n ): DatafnSignal<T>;\n}\n\nexport interface KvApiDeps {\n storage?: DatafnStorageAdapter;\n kvTable: DatafnTable;\n eventBus: EventBus;\n clientId: string;\n debouncerMap: DebouncerMap;\n}\n\n/**\n * Create the KV API facade.\n */\nexport function createKvApi(deps: KvApiDeps): DatafnKvApi {\n const { storage, kvTable, eventBus, clientId, debouncerMap } = deps;\n\n // CLI-007: Per-key serialization for merge to prevent read-modify-write races.\n // Concurrent merges on the same key are chained so they execute sequentially.\n const mergeLocks = new Map<string, Promise<unknown>>();\n function withMergeLock<T>(\n key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n const prev = mergeLocks.get(key) ?? Promise.resolve();\n const next = prev.then(fn, (_) => fn()); // run fn even if prev failed\n const cleanup = next.then(\n () => { if (mergeLocks.get(key) === next) mergeLocks.delete(key); },\n () => { if (mergeLocks.get(key) === next) mergeLocks.delete(key); },\n );\n void cleanup;\n mergeLocks.set(key, next);\n return next;\n }\n\n return {\n async get<T = unknown>(key: string): Promise<T | null> {\n if (typeof key !== \"string\") {\n throw new Error(\"Invalid KV key: must be string\");\n }\n\n const id = kvId(key);\n\n // Try storage first (offline-first)\n if (storage) {\n const record = await storage.getRecord(KV_RESOURCE_NAME, id);\n if (record) {\n return (record.value as T) ?? null;\n }\n }\n\n // Query path (remote or local)\n const result = (await kvTable.query({\n resource: KV_RESOURCE_NAME,\n version: 1,\n filters: { id: { eq: id } },\n select: [\"id\", \"value\"],\n } as any)) as any;\n\n if (!result || !(\"data\" in result) || !Array.isArray(result.data)) {\n return null;\n }\n\n const records = result.data;\n if (records.length === 0) {\n return null;\n }\n\n return (records[0].value as T) ?? null;\n },\n\n async set<T = unknown>(\n key: string,\n value: T,\n params?: { context?: Record<string, unknown>; debounceMs?: number },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }> {\n if (typeof key !== \"string\") {\n return {\n ok: false as const,\n error: {\n code: \"DFQL_INVALID\",\n message: \"Invalid KV key: must be string\",\n details: { path: \"key\" },\n },\n };\n }\n\n const id = kvId(key);\n\n const executeMutation = async () => {\n // Use merge operation for upsert semantics (create-or-update)\n const result = (await kvTable.mutate({\n resource: KV_RESOURCE_NAME,\n version: 1,\n operation: \"merge\",\n id,\n record: { value },\n clientId,\n mutationId: `kv-set-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n context: params?.context,\n } as any)) as any;\n\n if (!result || typeof result !== \"object\" || !(\"ok\" in result)) {\n return { ok: false as const, error: result };\n }\n\n if (!result.ok) {\n return { ok: false as const, error: result };\n }\n\n return { ok: true as const, key };\n };\n\n try {\n // If debounceMs is provided, use the DebouncerMap\n if (params?.debounceMs !== undefined && params.debounceMs > 0) {\n const debounceKey = `kv:${key}`;\n await debouncerMap.set(\n debounceKey,\n {\n resource: KV_RESOURCE_NAME,\n operation: \"merge\",\n id,\n record: { value },\n clientId,\n mutationId: `kv-set-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n context: params?.context,\n },\n params.debounceMs,\n async (mutation) => {\n // Execute the mutation directly through kvTable\n const result = (await kvTable.mutate(mutation as any)) as any;\n if (!result || typeof result !== \"object\" || !(\"ok\" in result)) {\n throw result;\n }\n if (!result.ok) {\n throw result;\n }\n },\n );\n return { ok: true as const, key };\n }\n\n // Without debounce, execute immediately\n return await executeMutation();\n } catch (error) {\n return { ok: false as const, error };\n }\n },\n\n async merge(\n key: string,\n patch: Record<string, unknown>,\n params?: { context?: Record<string, unknown>; debounceMs?: number },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }> {\n if (typeof key !== \"string\") {\n return {\n ok: false as const,\n error: {\n code: \"DFQL_INVALID\",\n message: \"Invalid KV key: must be string\",\n details: { path: \"key\" },\n },\n };\n }\n\n if (\n typeof patch !== \"object\" ||\n patch === null ||\n Array.isArray(patch)\n ) {\n return {\n ok: false as const,\n error: {\n code: \"DFQL_INVALID\",\n message: \"Invalid KV merge: patch must be a plain object\",\n details: { path: \"patch\" },\n },\n };\n }\n\n const id = kvId(key);\n\n const executeMutation = async () => {\n // Get existing value\n const existing = await this.get<Record<string, unknown>>(key);\n\n // Validate existing value is an object\n if (\n existing !== null &&\n (typeof existing !== \"object\" ||\n Array.isArray(existing))\n ) {\n return {\n ok: false as const,\n error: {\n code: \"DFQL_INVALID\",\n message:\n \"Invalid KV merge: existing value is not an object\",\n details: { path: \"value\" },\n },\n };\n }\n\n // Send patch as { value: patch } and let the deep merge logic handle it\n // The storage adapter's mergeRecord will do one-level deep merge:\n // existing: { id: \"kv:k\", value: { a: 1, b: 2 } }\n // patch: { value: { a: 10 } }\n // result: { id: \"kv:k\", value: { a: 10, b: 2 } }\n const result = (await kvTable.mutate({\n resource: KV_RESOURCE_NAME,\n version: 1,\n operation: \"merge\",\n id,\n record: { value: patch }, // Send patch, not merged value\n clientId,\n mutationId: `kv-merge-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n context: params?.context,\n } as any)) as any;\n\n if (!result || typeof result !== \"object\" || !(\"ok\" in result)) {\n return { ok: false as const, error: result };\n }\n\n if (!result.ok) {\n return { ok: false as const, error: result };\n }\n\n return { ok: true as const, key };\n };\n\n try {\n // If debounceMs is provided, use the DebouncerMap\n if (params?.debounceMs !== undefined && params.debounceMs > 0) {\n const debounceKey = `kv:${key}`;\n // Store patch fields at the top level of record so they merge correctly\n await debouncerMap.set(\n debounceKey,\n {\n resource: KV_RESOURCE_NAME,\n operation: \"merge\",\n id,\n record: patch, // Store patch fields directly (not nested under 'value')\n clientId,\n mutationId: `kv-merge-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n context: params?.context,\n },\n params.debounceMs,\n async (mutation) => {\n // Validate existing value is an object (before mutation)\n const existing = await this.get<Record<string, unknown>>(key);\n \n if (\n existing !== null &&\n (typeof existing !== \"object\" || Array.isArray(existing))\n ) {\n throw {\n code: \"DFQL_INVALID\",\n message: \"Invalid KV merge: existing value is not an object\",\n details: { path: \"value\" },\n };\n }\n \n // mutation.record now contains the accumulated patch fields\n // Wrap it in { value: patch } and let deep merge handle it\n const patchValue = mutation.record as Record<string, unknown>;\n \n // Execute the mutation with patch wrapped in value field\n const result = (await kvTable.mutate({\n ...mutation,\n record: { value: patchValue },\n } as any)) as any;\n \n if (!result || typeof result !== \"object\" || !(\"ok\" in result)) {\n throw result;\n }\n if (!result.ok) {\n throw result;\n }\n },\n );\n return { ok: true as const, key };\n }\n\n // Without debounce, execute immediately with per-key lock (CLI-007)\n return await withMergeLock(key, executeMutation);\n } catch (error) {\n return { ok: false as const, error };\n }\n },\n\n async delete(\n key: string,\n params?: { context?: Record<string, unknown> },\n ): Promise<{ ok: true; key: string } | { ok: false; error: unknown }> {\n if (typeof key !== \"string\") {\n return {\n ok: false as const,\n error: {\n code: \"DFQL_INVALID\",\n message: \"Invalid KV key: must be string\",\n details: { path: \"key\" },\n },\n };\n }\n\n const id = kvId(key);\n\n try {\n const result = (await kvTable.mutate({\n resource: KV_RESOURCE_NAME,\n version: 1,\n operation: \"delete\",\n id,\n clientId,\n mutationId: `kv-delete-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n context: params?.context,\n } as any)) as any;\n\n if (!result || typeof result !== \"object\" || !(\"ok\" in result)) {\n return { ok: false as const, error: result };\n }\n\n if (!result.ok) {\n return { ok: false as const, error: result };\n }\n\n return { ok: true as const, key };\n } catch (error) {\n return { ok: false as const, error };\n }\n },\n\n async getOrSeed<T = unknown>(key: string, defaults: T): Promise<T> {\n if (typeof key !== \"string\") {\n throw new Error(\"Invalid KV key: must be string\");\n }\n\n const id = kvId(key);\n\n // Check if the record exists in storage\n if (storage) {\n const record = await storage.getRecord(KV_RESOURCE_NAME, id);\n if (record !== null) {\n // Record exists, return its value (even if null)\n return (record.value as T) ?? null as T;\n }\n } else {\n // No storage, query to check existence\n const result = (await kvTable.query({\n resource: KV_RESOURCE_NAME,\n version: 1,\n filters: { id: { eq: id } },\n select: [\"id\", \"value\"],\n } as any)) as any;\n\n if (result && \"data\" in result && Array.isArray(result.data) && result.data.length > 0) {\n // Record exists, return its value (even if null)\n return (result.data[0].value as T) ?? null as T;\n }\n }\n\n // Record doesn't exist, seed with defaults\n await this.set(key, defaults);\n return defaults;\n },\n\n async flush(key?: string): Promise<void> {\n if (key !== undefined) {\n // Flush specific key\n const debounceKey = `kv:${key}`;\n await debouncerMap.flush(debounceKey);\n } else {\n // Flush all KV debounced mutations\n await debouncerMap.flushAll();\n }\n },\n\n signal<T = unknown>(\n key: string,\n options?: { defaultValue?: T },\n ): DatafnSignal<T> {\n if (typeof key !== \"string\") {\n throw new Error(\"Invalid KV key: must be string\");\n }\n\n const id = kvId(key);\n\n // Create a signal scoped to this specific KV id\n const baseSignal = kvTable.signal({\n resource: KV_RESOURCE_NAME,\n version: 1,\n filters: { id: { eq: id } },\n select: [\"id\", \"value\"],\n } as any);\n\n // Transform the signal to extract the value field.\n // After the query signal unwrap, baseSignal emits the record array directly.\n const transformedSignal: DatafnSignal<T> = {\n subscribe: (handler: (value: T) => void) => {\n return baseSignal.subscribe((records: any) => {\n if (Array.isArray(records) && records.length > 0) {\n handler(records[0].value as T);\n } else {\n handler(options?.defaultValue ?? (null as T));\n }\n });\n },\n get: () => {\n const records = baseSignal.get() as any;\n if (Array.isArray(records) && records.length > 0) {\n return records[0].value as T;\n }\n return options?.defaultValue ?? (null as T);\n },\n get loading() { return baseSignal.loading; },\n get error() { return baseSignal.error; },\n get refreshing() { return baseSignal.refreshing; },\n get nextCursor() { return baseSignal.nextCursor; },\n dispose: () => baseSignal.dispose(),\n };\n\n return transformedSignal;\n },\n };\n}\n","/**\n * Extension Subscription Manager\n *\n * Manages remote subscription lifecycle for extension contexts:\n * - Opens remote subscription when first local subscriber with a filter registers\n * - Closes remote subscription when last local subscriber unsubscribes\n * - Provides deterministic filter -> remote subscription key mapping\n */\n\nimport type { EventFilter } from \"../events/filter.js\";\nimport { normalizeFilter } from \"../events/filter.js\";\n\nexport interface RemoteSubscriptionAdapter {\n subscribeRemote(filter?: unknown): Promise<string>;\n unsubscribeRemote(subscriptionId: string): Promise<void>;\n}\n\ninterface RemoteSubscription {\n subscriptionId: string;\n filter: EventFilter | undefined;\n localSubscriberCount: number;\n}\n\n/**\n * Generates a deterministic key from an event filter for deduplication\n */\nfunction filterToKey(filter: EventFilter | undefined): string {\n if (!filter) return \"__all__\";\n // Create a stable JSON representation by sorting keys\n const normalized = normalizeFilter(filter);\n return JSON.stringify(normalized, Object.keys(normalized).sort());\n}\n\n/**\n * Manages remote subscriptions for extension context\n */\nexport class ExtensionSubscriptionManager {\n private remoteSubscriptions = new Map<string, RemoteSubscription>();\n\n constructor(private adapter: RemoteSubscriptionAdapter) {}\n\n /**\n * Register a local subscriber. Opens remote subscription if needed.\n * Returns a cleanup function to decrement the ref count.\n */\n async registerSubscriber(\n filter: EventFilter | undefined,\n ): Promise<() => Promise<void>> {\n const key = filterToKey(filter);\n let remoteSub = this.remoteSubscriptions.get(key);\n\n if (!remoteSub) {\n // First subscriber with this filter - open remote subscription\n const subscriptionId = await this.adapter.subscribeRemote(filter);\n remoteSub = {\n subscriptionId,\n filter,\n localSubscriberCount: 1,\n };\n this.remoteSubscriptions.set(key, remoteSub);\n } else {\n // Existing remote subscription - increment ref count\n remoteSub.localSubscriberCount++;\n }\n\n // Return cleanup function\n return async () => {\n const sub = this.remoteSubscriptions.get(key);\n if (!sub) return; // Already cleaned up\n\n sub.localSubscriberCount--;\n\n if (sub.localSubscriberCount === 0) {\n // Last subscriber removed - close remote subscription\n await this.adapter.unsubscribeRemote(sub.subscriptionId);\n this.remoteSubscriptions.delete(key);\n }\n };\n }\n\n /**\n * Close all remote subscriptions (for cleanup)\n */\n async closeAll(): Promise<void> {\n const subs = Array.from(this.remoteSubscriptions.values());\n this.remoteSubscriptions.clear();\n\n await Promise.all(\n subs.map((sub) => this.adapter.unsubscribeRemote(sub.subscriptionId)),\n );\n }\n}\n","/**\n * DebouncerMap for per-record-key mutation debouncing (DEB-001)\n *\n * Coalesces rapid mutations with the same debounceKey within a debounce window.\n * Only applies to merge operations; other operations execute immediately.\n */\n\nexport interface DfqlMutation {\n resource: string;\n operation: string;\n id: string;\n record?: Record<string, unknown>;\n mutationId?: string;\n clientId?: string;\n debounceKey?: string;\n debounceMs?: number;\n [key: string]: unknown;\n}\n\ninterface PendingMutation {\n timer: ReturnType<typeof setTimeout>;\n mutation: DfqlMutation;\n executor: (m: DfqlMutation) => Promise<void>;\n resolve: (value: void) => void;\n reject: (error: unknown) => void;\n}\n\nexport class DebouncerMap {\n private pending = new Map<string, PendingMutation>();\n\n /**\n * Set a debounced mutation.\n * If a mutation with the same key is already pending, merge the records and reset the timer.\n *\n * @param key - Debounce key (typically record ID)\n * @param mutation - The mutation to debounce\n * @param delayMs - Debounce delay in milliseconds\n * @param executor - Async function to execute the mutation after debounce\n * @returns Promise that resolves when the mutation is executed\n */\n set(\n key: string,\n mutation: DfqlMutation,\n delayMs: number,\n executor: (m: DfqlMutation) => Promise<void>,\n ): Promise<void> {\n // If key already pending, clear existing timer and merge records\n const existing = this.pending.get(key);\n if (existing) {\n clearTimeout(existing.timer);\n\n // REL-004: Resolve the old caller's Promise before replacing.\n // Data was merged into the new mutation, so the original caller's mutation is not lost.\n existing.resolve();\n\n // Merge the new mutation's record fields into the existing mutation's record\n if (mutation.record && existing.mutation.record) {\n existing.mutation.record = {\n ...existing.mutation.record,\n ...mutation.record,\n };\n } else if (mutation.record) {\n existing.mutation.record = mutation.record;\n }\n\n // Update other mutation fields that might have changed\n // (keep existing mutationId, but update other fields)\n existing.mutation = {\n ...existing.mutation,\n ...mutation,\n // Preserve the merged record\n record: existing.mutation.record,\n // Keep the original mutationId for tracking\n mutationId: existing.mutation.mutationId,\n };\n }\n\n return new Promise<void>((resolve, reject) => {\n const mutationToExecute = existing?.mutation || mutation;\n const executorToUse = executor;\n \n const timer = setTimeout(async () => {\n this.pending.delete(key);\n try {\n await executorToUse(mutationToExecute);\n resolve();\n } catch (err) {\n reject(err);\n }\n }, delayMs);\n\n if (existing) {\n // Update the existing entry with new timer, executor, and resolve/reject\n existing.timer = timer;\n existing.executor = executorToUse;\n existing.resolve = resolve;\n existing.reject = reject;\n } else {\n // Create new entry\n this.pending.set(key, {\n timer,\n mutation: mutationToExecute,\n executor: executorToUse,\n resolve,\n reject,\n });\n }\n });\n }\n\n /**\n * Flush a specific debounced mutation immediately.\n *\n * @param key - The debounce key to flush. If undefined, does nothing.\n * @returns Promise that resolves when the flushed mutation completes\n */\n async flush(key?: string): Promise<void> {\n if (key === undefined) {\n return;\n }\n \n const pending = this.pending.get(key);\n if (!pending) {\n return; // Nothing to flush\n }\n \n // Clear the timer and remove from pending\n clearTimeout(pending.timer);\n this.pending.delete(key);\n \n // Execute immediately\n try {\n await pending.executor(pending.mutation);\n pending.resolve();\n } catch (err) {\n pending.reject(err);\n throw err; // Re-throw so caller knows it failed\n }\n }\n\n /**\n * Flush all pending debounced mutations immediately.\n *\n * @returns Promise that resolves when all mutations complete\n */\n async flushAll(): Promise<void> {\n const entries = Array.from(this.pending.entries());\n this.pending.clear();\n \n // Clear all timers first\n for (const [, pending] of entries) {\n clearTimeout(pending.timer);\n }\n \n // Execute all mutations in parallel\n await Promise.allSettled(\n entries.map(async ([, pending]) => {\n try {\n await pending.executor(pending.mutation);\n pending.resolve();\n } catch (err) {\n pending.reject(err);\n // Don't re-throw - the promise is already rejected via pending.reject\n }\n }),\n );\n }\n\n /**\n * Destroy the debouncer, clearing all timers without executing.\n * Used for cleanup when the client is torn down abruptly.\n */\n destroy(): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timer);\n }\n this.pending.clear();\n }\n}\n","/**\n * Data export and import for backup and restore\n */\n\nimport type { DatafnSchema } from \"@datafn/core\";\nimport { getJoinStoreKey } from \"@datafn/core\";\nimport type { DatafnStorageAdapter } from \"./storage.js\";\nimport { createClientError } from \"./errors.js\";\nimport type { SyncFacade } from \"./sync.js\";\n\n/**\n * Export payload format version 1\n */\nexport interface DatafnExportPayload {\n version: 1;\n exportedAt: string; // ISO 8601\n schema: Array<{ name: string; version: number }>;\n resources: Record<string, Array<Record<string, unknown>>>;\n joins?: Record<string, Array<Record<string, unknown>>>;\n}\n\n/**\n * Import result with per-resource stats\n */\nexport interface DatafnImportResult {\n ok: boolean;\n stats: {\n resources: Record<string, { imported: number; skipped: number }>;\n joins: Record<string, { imported: number; skipped: number }>;\n };\n errors: Array<{ resource: string; id: string; code: string; message: string }>;\n}\n\n/**\n * Options for data export\n */\nexport interface DatafnExportOptions {\n /** Filter export to specific resources. If omitted, exports all non-remote-only resources. */\n resources?: string[];\n}\n\n/**\n * Options for data import\n */\nexport interface DatafnImportOptions {\n /** When true, trigger cloneUp after import to sync changes to server. Default: false. */\n triggerCloneUp?: boolean;\n}\n\n/**\n * Resolve the set of resources to export based on schema and filter options\n */\nfunction resolveExportScope(\n schema: DatafnSchema,\n resourceNames?: string[],\n): Array<{ name: string; version: number }> {\n const allExportable = schema.resources.filter(r => !r.isRemoteOnly);\n \n if (!resourceNames || resourceNames.length === 0) {\n // Export all non-remote-only resources\n return allExportable.map(r => ({ name: r.name, version: r.version }));\n }\n \n // Filter to specified resources\n const result: Array<{ name: string; version: number }> = [];\n for (const name of resourceNames) {\n const resource = allExportable.find(r => r.name === name);\n if (resource) {\n result.push({ name: resource.name, version: resource.version });\n }\n }\n \n return result;\n}\n\n/**\n * Export all local records and join rows as structured JSON\n */\nexport async function exportData(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n options?: DatafnExportOptions,\n): Promise<DatafnExportPayload> {\n const resources = resolveExportScope(schema, options?.resources);\n \n const payload: DatafnExportPayload = {\n version: 1,\n exportedAt: new Date().toISOString(),\n schema: resources.map(r => ({ name: r.name, version: r.version })),\n resources: {},\n joins: {},\n };\n \n // Export records for each resource\n for (const resource of resources) {\n payload.resources[resource.name] = await storage.listRecords(resource.name);\n }\n \n // Export join rows for many-many relations (handle multi-resource from/to arrays)\n for (const relation of schema.relations ?? []) {\n if (relation.type !== \"many-many\") continue;\n const froms = Array.isArray(relation.from) ? relation.from : [relation.from];\n const tos = Array.isArray(relation.to) ? relation.to : [relation.to];\n const relName = relation.relation ?? \"rel\";\n for (const f of froms) {\n for (const t of tos) {\n const storeName = getJoinStoreKey(f, relName, t);\n try {\n payload.joins![storeName] = await storage.listJoinRows(storeName);\n } catch (err) {\n // Join store may not exist if no relations have been created\n // Continue without error\n }\n }\n }\n }\n \n return payload;\n}\n\n/**\n * Import records and join rows from a structured JSON payload\n */\nexport async function importData(\n storage: DatafnStorageAdapter,\n schema: DatafnSchema,\n sync: SyncFacade,\n data: DatafnExportPayload,\n options?: DatafnImportOptions,\n): Promise<DatafnImportResult> {\n // Validate version\n if (data.version !== 1) {\n throw createClientError(\n \"DFQL_INVALID\",\n \"Unsupported export version\",\n { path: \"version\", version: data.version },\n );\n }\n \n const result: DatafnImportResult = {\n ok: true,\n stats: {\n resources: {},\n joins: {},\n },\n errors: [],\n };\n \n // Import records\n for (const [resourceName, records] of Object.entries(data.resources)) {\n const resourceSchema = schema.resources.find(r => r.name === resourceName);\n if (!resourceSchema) {\n // Skip unknown resources (not an error)\n continue;\n }\n \n let imported = 0;\n let skipped = 0;\n \n for (const record of records) {\n try {\n await storage.upsertRecord(resourceName, record);\n imported++;\n } catch (err) {\n skipped++;\n result.errors.push({\n resource: resourceName,\n id: String(record.id),\n code: \"IMPORT_FAILED\",\n message: String(err),\n });\n }\n }\n \n result.stats.resources[resourceName] = { imported, skipped };\n }\n \n // Import join rows\n for (const [storeName, rows] of Object.entries(data.joins ?? {})) {\n let imported = 0;\n let skipped = 0;\n \n for (const row of rows) {\n try {\n await storage.upsertJoinRow(storeName, row);\n imported++;\n } catch (err) {\n skipped++;\n // Join row errors are not added to errors array (less critical)\n }\n }\n \n result.stats.joins[storeName] = { imported, skipped };\n }\n \n // Trigger cloneUp if requested\n if (options?.triggerCloneUp && sync.cloneUp) {\n await sync.cloneUp();\n }\n \n // Mark result as not ok if there were any errors\n if (result.errors.length > 0) {\n result.ok = false;\n }\n \n return result;\n}\n","/**\n * Cross-Tab Coordination via BroadcastChannel\n *\n * Enables event relay between browser tabs for near-instant cross-tab reactivity.\n * Opt-in via `crossTab: true` config.\n */\n\nimport type { EventBus } from \"./events/bus.js\";\nimport type { DatafnEvent } from \"@datafn/core\";\n\n/**\n * Sanitized event payload for cross-tab broadcast.\n * Strips full record data, keeping only metadata.\n */\ninterface RelayEvent {\n sourceTabId: string;\n event: Omit<DatafnEvent, \"context\"> & {\n // Only metadata fields - no full record data\n type: DatafnEvent[\"type\"];\n resource?: string;\n ids?: string[];\n mutationId?: string;\n clientId?: string;\n timestampMs: number;\n action?: string;\n fields?: string[];\n system?: boolean;\n };\n}\n\n/**\n * Known valid relay event type values (SEC-012)\n */\nconst KNOWN_EVENT_TYPES: ReadonlySet<string> = new Set([\n \"mutation_applied\",\n \"mutation_rejected\",\n \"sync_applied\",\n \"sync_failed\",\n \"sync_retry\",\n \"connectivity_changed\",\n \"ws_connected\",\n \"ws_disconnected\",\n]);\n\n/**\n * SEC-012: Runtime type guard for RelayEvent.\n * Validates that incoming cross-tab message has expected shape before processing.\n */\nfunction isValidRelayEvent(data: unknown): data is RelayEvent {\n if (typeof data !== \"object\" || data === null) return false;\n const d = data as Record<string, unknown>;\n // Must have sourceTabId string\n if (typeof d.sourceTabId !== \"string\") return false;\n // Must have event object with a valid type\n if (typeof d.event !== \"object\" || d.event === null) return false;\n const event = d.event as Record<string, unknown>;\n if (typeof event.type !== \"string\" || !KNOWN_EVENT_TYPES.has(event.type)) return false;\n return true;\n}\n\n/**\n * Strip full record data from event, keeping only metadata for relay.\n */\nfunction sanitizeForRelay(event: DatafnEvent): RelayEvent[\"event\"] {\n return {\n type: event.type,\n resource: event.resource,\n ids: event.ids,\n mutationId: event.mutationId,\n clientId: event.clientId,\n timestampMs: event.timestampMs,\n action: event.action,\n fields: event.fields,\n system: event.system,\n };\n}\n\n/**\n * CrossTabRelay - relays mutation events between browser tabs via BroadcastChannel\n */\nexport class CrossTabRelay {\n private channel: BroadcastChannel | null = null;\n private tabId: string;\n private eventBus: EventBus;\n\n constructor(namespace: string, eventBus: EventBus) {\n this.tabId = crypto.randomUUID();\n this.eventBus = eventBus;\n\n // Check if BroadcastChannel is available (not available in all environments)\n if (typeof BroadcastChannel !== \"undefined\") {\n this.channel = new BroadcastChannel(`datafn:${namespace}`);\n this.channel.onmessage = (messageEvent) => {\n // SEC-012: Validate message shape before casting to RelayEvent\n const data = messageEvent.data;\n if (!isValidRelayEvent(data)) {\n // Silently discard invalid messages (rogue extension / XSS injection)\n return;\n }\n const relayEvent = data as RelayEvent;\n\n // Echo prevention: ignore messages from this tab\n if (relayEvent.sourceTabId === this.tabId) return;\n\n // Emit the event on local event bus with fromRemoteTab flag\n this.eventBus.emit({\n ...relayEvent.event,\n fromRemoteTab: true,\n } as DatafnEvent & { fromRemoteTab: true });\n };\n }\n }\n\n /**\n * Broadcast an event to other tabs.\n * Should only be called for non-silent, non-fromRemoteTab mutations.\n */\n broadcast(event: DatafnEvent): void {\n if (!this.channel) return;\n\n const relayEvent: RelayEvent = {\n sourceTabId: this.tabId,\n event: sanitizeForRelay(event),\n };\n\n this.channel.postMessage(relayEvent);\n }\n\n /**\n * Close the broadcast channel and release resources.\n */\n close(): void {\n if (this.channel) {\n this.channel.close();\n this.channel = null;\n }\n }\n}\n","/**\n * @datafn/client public API\n */\n\nexport {\n createDatafnClient,\n type DatafnClient,\n type DatafnClientConfig,\n type DatafnRemoteAdapter,\n type SwitchContextOverride,\n} from \"./client.js\";\n\nexport { EventBus, type EventHandler } from \"./events/bus.js\";\nexport { matchesFilter, type EventFilter } from \"./events/filter.js\";\nexport {\n type DatafnClientError,\n throwClientError,\n /** Alias for throwClientError */\n createClientError,\n} from \"./errors.js\";\nexport { unwrapRemoteSuccess } from \"./remote/unwrap.js\";\nexport { type DatafnTable } from \"./tables/table.js\";\nexport { type PermissionEntry } from \"./query.js\";\nexport {\n type DatafnStorageAdapter,\n type DatafnStorageFactory,\n type DatafnHydrationState,\n type DatafnChangelogEntry,\n} from \"./storage.js\";\n\n// Re-export namespace helper from core\nexport { ns } from \"@datafn/core\";\n\n// CloneUp types\nexport type { CloneUpOptions, CloneUpResult } from \"./sync/cloneUp.js\";\n\n// Storage Adapters\nexport { MemoryStorageAdapter } from \"./adapters/memoryStorage.js\";\nexport { IndexedDbStorageAdapter } from \"./adapters/indexedDbStorage.js\";\n\n// KV API\nexport type { DatafnKvApi } from \"./kv.js\";\nexport { kvId, KV_RESOURCE_NAME } from \"./kv.js\";\n\n// Date Codec (CODEC-001)\nexport {\n serializeDateFields,\n parseDateFields,\n parseQueryResultDates,\n} from \"./codecs/date.js\";\n","/**\n * In-memory storage adapter for testing and development.\n * Implements deterministic ordering and changelog deduplication.\n */\n\nimport type {\n DatafnStorageAdapter,\n DatafnHydrationState,\n DatafnChangelogEntry,\n} from \"../storage.js\";\nimport { KV_RESOURCE_NAME } from \"@datafn/core\";\nimport {\n validateHydrationState,\n validateTransition,\n validateCursor,\n} from \"./shared.js\";\n\nfunction validateMutation(mutation: any): void {\n if (!mutation.clientId) throw new Error(\"Missing clientId in mutation\");\n if (!mutation.mutationId) throw new Error(\"Missing mutationId in mutation\");\n}\n\nexport class MemoryStorageAdapter implements DatafnStorageAdapter {\n private records = new Map<string, Map<string, Record<string, unknown>>>();\n private joinRows = new Map<string, Map<string, Record<string, unknown>>>();\n private cursors = new Map<string, string>();\n private hydration = new Map<string, DatafnHydrationState>();\n private changelog: DatafnChangelogEntry[] = [];\n private changelogSeq = 1;\n // PER-006: O(1) dedup index keyed by \"clientId:mutationId\"\n private changelogIndex = new Map<string, DatafnChangelogEntry>();\n private validResources?: Set<string>;\n\n constructor(resources?: string[]) {\n if (resources) {\n this.validResources = new Set(resources);\n // Ensure built-in KV resource is always valid (KV-001)\n this.validResources.add(KV_RESOURCE_NAME);\n }\n // Always create KV store (KV-001)\n this.records.set(\"kv\", new Map());\n }\n\n private validateTableName(table: string) {\n if (this.validResources && !this.validResources.has(table)) {\n throw new Error(`Unknown table: ${table}`);\n }\n }\n\n // --- Records ---\n\n async getRecord(\n resource: string,\n id: string,\n ): Promise<Record<string, unknown> | null> {\n this.validateTableName(resource);\n const table = this.records.get(resource);\n return table?.get(id) || null;\n }\n\n async listRecords(resource: string): Promise<Record<string, unknown>[]> {\n this.validateTableName(resource);\n const table = this.records.get(resource);\n if (!table) return [];\n\n // STORAGE-MEM-001: Deterministic ordering by id:asc\n return Array.from(table.values()).sort((a, b) => {\n const idA = (a.id as string) || \"\";\n const idB = (b.id as string) || \"\";\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n });\n }\n\n async upsertRecord(\n resource: string,\n record: Record<string, unknown>,\n ): Promise<void> {\n this.validateTableName(resource);\n if (!this.records.has(resource)) {\n this.records.set(resource, new Map());\n }\n const id = record.id as string;\n if (!id) throw new Error(\"Record missing id\");\n this.records.get(resource)!.set(id, record);\n }\n\n async deleteRecord(resource: string, id: string): Promise<void> {\n this.validateTableName(resource);\n const table = this.records.get(resource);\n if (table) {\n table.delete(id);\n }\n }\n\n /**\n * Atomic read-modify-write merge using one-level-deep merge.\n */\n async mergeRecord(\n resource: string,\n id: string,\n partial: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n this.validateTableName(resource);\n const existing = await this.getRecord(resource, id);\n \n // One-level deep merge\n const merged = existing\n ? this.deepMergeOneLevel(existing, partial)\n : { ...partial, id };\n \n merged.id = id;\n await this.upsertRecord(resource, merged);\n return merged;\n }\n\n private deepMergeOneLevel(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): Record<string, unknown> {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n const sv = source[key];\n const tv = target[key];\n if (\n sv !== null &&\n typeof sv === \"object\" &&\n !Array.isArray(sv) &&\n tv !== null &&\n typeof tv === \"object\" &&\n !Array.isArray(tv)\n ) {\n // One-level deep merge for objects\n result[key] = { ...tv, ...sv };\n } else {\n // Overwrite for everything else\n result[key] = sv;\n }\n }\n return result;\n }\n\n // --- Join Rows ---\n\n async listJoinRows(\n relationKey: string,\n ): Promise<Array<Record<string, unknown>>> {\n // Validate relationKey? It is \"Resource.relation\".\n // We could validate the resource part if we parse it.\n // But requirement says \"validate table names\". Join tables are internal?\n // Let's skip strict validation for relationKey for now unless we enforce schema awareness for relations too.\n const table = this.joinRows.get(relationKey);\n if (!table) return [];\n\n // Deterministic sort by from, to\n return Array.from(table.values()).sort((a, b) => {\n const keyA = `${a.from}:${a.to}`;\n const keyB = `${b.from}:${b.to}`;\n return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;\n });\n }\n\n async getJoinRows(\n relationKey: string,\n fromId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const table = this.joinRows.get(relationKey);\n if (!table) return [];\n\n // Filter by fromId and sort by to\n return Array.from(table.values())\n .filter((row) => row.from === fromId)\n .sort((a, b) => {\n const idA = (a.to as string) || \"\";\n const idB = (b.to as string) || \"\";\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n });\n }\n\n async getJoinRowsInverse(\n relationKey: string,\n toId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const table = this.joinRows.get(relationKey);\n if (!table) return [];\n\n // Filter by toId and sort by from\n return Array.from(table.values())\n .filter((row) => row.to === toId)\n .sort((a, b) => {\n const idA = (a.from as string) || \"\";\n const idB = (b.from as string) || \"\";\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n });\n }\n\n async upsertJoinRow(\n relationKey: string,\n row: Record<string, unknown>,\n ): Promise<void> {\n if (!this.joinRows.has(relationKey)) {\n this.joinRows.set(relationKey, new Map());\n }\n // Composite key for storage\n const key = `${row.from}:${row.to}`;\n this.joinRows.get(relationKey)!.set(key, row);\n }\n\n async setJoinRows(\n relationKey: string,\n rows: Array<Record<string, unknown>>,\n ): Promise<void> {\n if (!this.joinRows.has(relationKey)) {\n this.joinRows.set(relationKey, new Map());\n }\n const table = this.joinRows.get(relationKey)!;\n // This is \"set\" (replace for these rows? or replace all? \"stores join rows\")\n // Usually used for syncing/bulk update.\n // Assuming upsert semantics for the provided rows.\n for (const row of rows) {\n const key = `${row.from}:${row.to}`;\n table.set(key, row);\n }\n }\n\n async deleteJoinRow(\n relationKey: string,\n from: string,\n to: string,\n ): Promise<void> {\n const table = this.joinRows.get(relationKey);\n if (table) {\n table.delete(`${from}:${to}`);\n }\n }\n\n async findRecords(\n resource: string,\n field: string,\n value: unknown,\n ): Promise<Record<string, unknown>[]> {\n this.validateTableName(resource);\n const table = this.records.get(resource);\n if (!table) return [];\n\n return Array.from(table.values())\n .filter((r) => r[field] === value)\n .sort((a, b) => {\n const idA = (a.id as string) || \"\";\n const idB = (b.id as string) || \"\";\n return idA < idB ? -1 : idA > idB ? 1 : 0;\n });\n }\n\n // --- Sync State ---\n\n async getCursor(resource: string): Promise<string | null> {\n // Skip validation for internal cursor keys (SYNC-CURSOR-001)\n if (resource !== \"__global_cursor__\") {\n this.validateTableName(resource);\n }\n return this.cursors.get(resource) || null;\n }\n\n async setCursor(resource: string, cursor: string | null): Promise<void> {\n // Skip validation for internal cursor keys (SYNC-CURSOR-001)\n if (resource !== \"__global_cursor__\") {\n this.validateTableName(resource);\n }\n validateCursor(cursor);\n if (cursor === null) {\n this.cursors.delete(resource);\n } else {\n this.cursors.set(resource, cursor);\n }\n }\n\n async getHydrationState(resource: string): Promise<DatafnHydrationState> {\n this.validateTableName(resource);\n return this.hydration.get(resource) || \"notStarted\";\n }\n\n async setHydrationState(\n resource: string,\n state: DatafnHydrationState,\n ): Promise<void> {\n this.validateTableName(resource);\n validateHydrationState(state);\n const current = this.hydration.get(resource) || \"notStarted\";\n validateTransition(current, state);\n this.hydration.set(resource, state);\n }\n\n // --- Changelog ---\n\n async changelogAppend(\n entry: Omit<DatafnChangelogEntry, \"seq\">,\n ): Promise<DatafnChangelogEntry> {\n validateMutation(entry);\n // CLIENT-CHANGELOG-001: Deduplicate by (clientId, mutationId)\n // PER-006: O(1) lookup via Map index instead of O(n) .find()\n const dedupeKey = `${entry.clientId}:${entry.mutationId}`;\n const existing = this.changelogIndex.get(dedupeKey);\n if (existing) {\n return existing;\n }\n\n const newEntry: DatafnChangelogEntry = {\n ...entry,\n seq: this.changelogSeq++,\n };\n this.changelog.push(newEntry);\n this.changelogIndex.set(dedupeKey, newEntry);\n return newEntry;\n }\n\n async changelogList(\n options: { limit?: number } = {},\n ): Promise<DatafnChangelogEntry[]> {\n const limit = options.limit || 100;\n return this.changelog.slice(0, limit); // Already sorted by insertion/seq\n }\n\n async changelogAck(options: { throughSeq: number }): Promise<void> {\n // Remove acked entries from both array and index\n const removed = this.changelog.filter((e) => e.seq <= options.throughSeq);\n for (const entry of removed) {\n this.changelogIndex.delete(`${entry.clientId}:${entry.mutationId}`);\n }\n this.changelog = this.changelog.filter((e) => e.seq > options.throughSeq);\n }\n\n // --- Counts for reconcile (SYNC-007) ---\n\n async countRecords(resource: string): Promise<number> {\n this.validateTableName(resource);\n const table = this.records.get(resource);\n return table ? table.size : 0;\n }\n\n async countJoinRows(relationKey: string): Promise<number> {\n const table = this.joinRows.get(relationKey);\n return table ? table.size : 0;\n }\n\n // --- Lifecycle (CLN-001, CLN-002) ---\n\n async close(): Promise<void> {\n // Memory adapter has no connections to close\n return Promise.resolve();\n }\n\n async clearAll(): Promise<void> {\n this.records.clear();\n this.joinRows.clear();\n this.cursors.clear();\n this.hydration.clear();\n this.changelog = [];\n this.changelogSeq = 1;\n this.changelogIndex.clear();\n // Always recreate KV store (KV-001)\n this.records.set(\"kv\", new Map());\n }\n\n // --- Health Check (HEAL-001) ---\n\n async healthCheck(): Promise<{ ok: boolean; issues: string[] }> {\n // Memory adapter is always healthy (no external dependencies)\n return { ok: true, issues: [] };\n }\n}\n","/**\n * Shared storage adapter validation utilities (STR-001)\n */\n\nimport type { DatafnHydrationState } from \"../storage.js\";\n\nexport function validateHydrationState(state: string): DatafnHydrationState {\n if (state !== \"notStarted\" && state !== \"hydrating\" && state !== \"ready\") {\n throw new Error(`Invalid hydration state: ${state}`);\n }\n return state as DatafnHydrationState;\n}\n\nexport function validateTransition(\n from: DatafnHydrationState,\n to: DatafnHydrationState,\n): void {\n if (from === to) return;\n if (from === \"notStarted\" && to === \"hydrating\") return;\n if (from === \"hydrating\" && to === \"ready\") return;\n if (from === \"ready\" && to === \"hydrating\") return;\n throw new Error(`Invalid hydration state transition: ${from} -> ${to}`);\n}\n\nexport function validateCursor(cursor: unknown): void {\n if (cursor !== null && typeof cursor !== \"string\") {\n throw new Error(\"Invalid cursor format\");\n }\n}\n","/**\n * IndexedDB storage adapter for persistent client storage.\n * Implements deterministic ordering and changelog deduplication.\n */\n\nimport type {\n DatafnStorageAdapter,\n DatafnHydrationState,\n DatafnChangelogEntry,\n} from \"../storage.js\";\nimport type { DatafnSchema, DatafnRelationSchema } from \"@datafn/core\";\nimport { KV_RESOURCE_NAME, getJoinStoreKey, enumerateJoinStoreKeys } from \"@datafn/core\";\nimport {\n validateHydrationState,\n validateTransition,\n validateCursor,\n} from \"./shared.js\";\n\nconst DB_NAME = \"datafn_client_db\";\nconst DB_VERSION = 2;\n/** CLI-013: Maximum IDB version before database recreation */\nconst MAX_IDB_VERSION = 1000;\n\nfunction validateMutation(mutation: any): void {\n if (!mutation.clientId) throw new Error(\"Missing clientId in mutation\");\n if (!mutation.mutationId) throw new Error(\"Missing mutationId in mutation\");\n}\n\n/**\n * Deep merge helper\n * - Top-level scalar fields: overwrite\n * - Top-level object fields: shallow-merge the nested object\n * - Arrays: overwrite (no array merging)\n */\nfunction deepMergeOneLevel(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n const sv = source[key];\n const tv = target[key];\n if (\n sv !== null &&\n typeof sv === \"object\" &&\n !Array.isArray(sv) &&\n tv !== null &&\n typeof tv === \"object\" &&\n !Array.isArray(tv)\n ) {\n // One-level deep merge for objects\n result[key] = { ...tv, ...sv };\n } else {\n // Overwrite for everything else (scalars, arrays, null)\n result[key] = sv;\n }\n }\n return result;\n}\n\nexport class IndexedDbStorageAdapter implements DatafnStorageAdapter {\n private dbPromise: Promise<IDBDatabase>;\n private validResources?: Set<string>;\n private schema?: DatafnSchema;\n readonly dbName: string;\n\n /**\n * Create an IndexedDB storage adapter with schema-aware store creation.\n * This is the **recommended** way to create the adapter — schema is required,\n * ensuring all resource object stores and join tables are created in IndexedDB.\n *\n * If the database already exists but is missing stores (stale DB), the adapter\n * automatically bumps the version and creates the missing stores.\n *\n * @param options.dbName - Database name (e.g., \"my-app-db\")\n * @param options.schema - DataFn schema (required — used to create object stores)\n *\n * @example\n * ```typescript\n * const storage = IndexedDbStorageAdapter.create({\n * dbName: \"my-app-db\",\n * schema,\n * });\n * ```\n */\n static create(options: {\n dbName: string;\n schema: DatafnSchema;\n }): IndexedDbStorageAdapter {\n const resources = options.schema.resources.map((r) => r.name);\n // Ensure built-in KV resource is always valid (KV-001)\n if (!resources.includes(KV_RESOURCE_NAME)) {\n resources.push(KV_RESOURCE_NAME);\n }\n // Register join store keys for many-many relations\n if (options.schema.relations) {\n for (const key of enumerateJoinStoreKeys(options.schema.relations)) {\n if (!resources.includes(key)) {\n resources.push(key);\n }\n }\n }\n return new IndexedDbStorageAdapter(options.dbName, resources, options.schema);\n }\n\n /**\n * Create a storage adapter with a namespace-derived database name.\n * The namespace string has `:` replaced with `_` for the IDB database name.\n *\n * @example\n * ```typescript\n * const storage = IndexedDbStorageAdapter.createForNamespace(\"my-app\", \"org:user-1\");\n * // IDB database name: \"my-app_org_user-1\"\n * ```\n */\n static createForNamespace(\n baseDbName: string,\n namespace: string,\n resources?: string[],\n schema?: DatafnSchema,\n ): IndexedDbStorageAdapter {\n const sanitized = namespace.replace(/:/g, \"_\");\n const dbName = `${baseDbName}_${sanitized}`;\n\n let finalResources = resources;\n if (!finalResources && schema) {\n finalResources = schema.resources.map((r) => r.name);\n }\n if (finalResources && !finalResources.includes(KV_RESOURCE_NAME)) {\n finalResources = [...finalResources, KV_RESOURCE_NAME];\n }\n if (finalResources && schema?.relations) {\n for (const key of enumerateJoinStoreKeys(schema.relations)) {\n if (!finalResources.includes(key)) {\n finalResources.push(key);\n }\n }\n }\n\n return new IndexedDbStorageAdapter(dbName, finalResources, schema);\n }\n\n constructor(\n dbName: string = DB_NAME,\n resources?: string[],\n schema?: DatafnSchema,\n ) {\n this.dbName = dbName;\n if (resources) {\n this.validResources = new Set(resources);\n // Ensure built-in KV resource is always valid (KV-001)\n this.validResources.add(KV_RESOURCE_NAME);\n }\n this.schema = schema;\n\n // Open the database, then verify all expected stores exist.\n // If stores are missing (stale DB from prior version without schema),\n // close and reopen with a bumped version to trigger onupgradeneeded.\n this.dbPromise = this.openDatabase(DB_VERSION).then((db) =>\n this.ensureStores(db),\n );\n }\n\n /**\n * Open (or upgrade) the IndexedDB database at the given version.\n * All object store creation happens inside `onupgradeneeded`.\n */\n private openDatabase(version: number): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, version);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n\n request.onupgradeneeded = (event) => {\n const db = request.result;\n const txn = request.transaction!;\n\n // --- Migration from v1 (IDB-001: Two-phase migration approach) ---\n // Phase 1: Detect and log old version for migration tracking\n if (event.oldVersion < 2 && event.oldVersion > 0) {\n console.log(`IndexedDB migration: Detected v${event.oldVersion}, upgrading to v${version}`);\n \n // Store migration metadata in __datafn_meta for tracking\n if (!db.objectStoreNames.contains(\"__datafn_meta\")) {\n db.createObjectStore(\"__datafn_meta\", { keyPath: \"key\" });\n }\n \n // Mark migration as in-progress (for potential recovery detection)\n const metaStore = txn.objectStore(\"__datafn_meta\");\n metaStore.put({\n key: \"migration_v1_to_v2\",\n status: \"in_progress\",\n startedAt: new Date().toISOString(),\n oldVersion: event.oldVersion,\n });\n\n // Log but don't fail on migration issues - preserve old data\n // Actual async migration will happen after DB opens (Phase 2)\n try {\n // For v1 -> v2: We're changing from monolithic stores to per-resource stores\n // Synchronous schema changes only - data migration happens post-open\n console.log(\"IndexedDB migration: Schema changes applied. Data migration deferred to post-open phase.\");\n } catch (migrationError) {\n console.error(\"IndexedDB migration warning:\", migrationError);\n // Don't throw - allow schema to be created, old data preserved\n }\n }\n\n // --- Create/Update Stores based on Schema ---\n if (this.schema) {\n // 1. Resource Stores\n for (const resource of this.schema.resources) {\n if (!db.objectStoreNames.contains(resource.name)) {\n const store = db.createObjectStore(resource.name, {\n keyPath: \"id\",\n });\n \n // Base indices from schema\n if (resource.indices) {\n const indices = Array.isArray(resource.indices)\n ? resource.indices\n : resource.indices.base || [];\n\n for (const field of indices) {\n store.createIndex(`by_${field}`, field, { unique: false });\n }\n }\n\n // FK indices (inferred from relations)\n if (this.schema.relations) {\n for (const rel of this.schema.relations) {\n if (rel.type === \"many-one\" && rel.from === resource.name) {\n const fk = rel.fkField || `${rel.relation}Id`;\n if (!store.indexNames.contains(`by_${fk}`)) {\n store.createIndex(`by_${fk}`, fk, { unique: false });\n }\n } else if (rel.type === \"one-many\" && rel.to === resource.name) {\n // For one-many, 'to' has the FK back to 'from'\n const fk = rel.fkField || rel.inverse || `${rel.from}Id`;\n if (!store.indexNames.contains(`by_${fk}`)) {\n store.createIndex(`by_${fk}`, fk, { unique: false });\n }\n }\n }\n }\n }\n }\n\n // 2. Join Stores (Many-Many)\n if (this.schema.relations) {\n for (const rel of this.schema.relations) {\n if (rel.type === \"many-many\") {\n const froms = Array.isArray(rel.from) ? rel.from : [rel.from];\n const tos = Array.isArray(rel.to) ? rel.to : [rel.to];\n \n for (const f of froms) {\n for (const t of tos) {\n const storeName = getJoinStoreKey(f, rel.relation || \"rel\", t);\n if (!db.objectStoreNames.contains(storeName)) {\n const store = db.createObjectStore(storeName, {\n keyPath: [\"from\", \"to\"],\n });\n store.createIndex(\"by_from\", \"from\", { unique: false });\n store.createIndex(\"by_to\", \"to\", { unique: false });\n }\n }\n }\n }\n }\n }\n }\n\n // --- Built-in KV Store (KV-001) ---\n // Always create KV object store with index on id\n if (!db.objectStoreNames.contains(\"kv\")) {\n const kvStore = db.createObjectStore(\"kv\", { keyPath: \"id\" });\n kvStore.createIndex(\"by_id\", \"id\", { unique: true });\n }\n\n // --- Meta Stores (Preserve/Create) ---\n if (!db.objectStoreNames.contains(\"meta\")) {\n db.createObjectStore(\"meta\", { keyPath: [\"type\", \"key\"] });\n }\n\n if (!db.objectStoreNames.contains(\"changelog\")) {\n const store = db.createObjectStore(\"changelog\", {\n keyPath: \"seq\",\n autoIncrement: true,\n });\n store.createIndex(\"by_client_mutation\", [\"clientId\", \"mutationId\"], {\n unique: true,\n });\n }\n \n // IDB-001: Preserve old stores for recovery\n // DO NOT delete old stores (\"records\", \"join_rows\") immediately\n // They are preserved in case migration fails and manual recovery is needed\n // The new adapter only uses per-resource stores going forward\n if (event.oldVersion < 2 && event.oldVersion > 0) {\n console.log(\"IndexedDB migration: Old v1 stores preserved for recovery if needed\");\n // Migration completion will be marked by healthCheck() after successful operation\n }\n };\n });\n }\n\n /**\n * Verify all expected stores exist after initial open.\n * If stores are missing (stale DB opened without schema previously),\n * close the database and reopen with a bumped version to trigger\n * `onupgradeneeded`, which will create the missing stores.\n */\n private async ensureStores(db: IDBDatabase): Promise<IDBDatabase> {\n if (!this.schema) return db;\n\n const missing: string[] = [];\n\n // Check resource stores\n for (const resource of this.schema.resources) {\n if (!db.objectStoreNames.contains(resource.name)) {\n missing.push(resource.name);\n }\n }\n\n // Check join stores (many-many)\n if (this.schema.relations) {\n for (const rel of this.schema.relations) {\n if (rel.type === \"many-many\") {\n const froms = Array.isArray(rel.from) ? rel.from : [rel.from];\n const tos = Array.isArray(rel.to) ? rel.to : [rel.to];\n for (const f of froms) {\n for (const t of tos) {\n const storeName = getJoinStoreKey(f, rel.relation || \"rel\", t);\n if (!db.objectStoreNames.contains(storeName)) {\n missing.push(storeName);\n }\n }\n }\n }\n }\n }\n\n if (missing.length === 0) return db;\n\n const nextVersion = db.version + 1;\n db.close();\n\n // CLI-013: If version exceeds max, recreate the database from scratch\n if (nextVersion > MAX_IDB_VERSION) {\n console.warn(\n `[datafn] IndexedDB version ${nextVersion} exceeds MAX_IDB_VERSION (${MAX_IDB_VERSION}). Recreating database.`,\n );\n await new Promise<void>((resolve, reject) => {\n const req = indexedDB.deleteDatabase(this.dbName);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n req.onblocked = () => resolve(); // proceed even if blocked\n });\n return this.openDatabase(DB_VERSION);\n }\n\n return this.openDatabase(nextVersion);\n }\n\n private validateTableName(table: string) {\n // CLI-006: Skip validation for internal health-check probe keys\n if (table === \"__health_check__\" || table.startsWith(\"__datafn_\")) return;\n if (this.validResources && !this.validResources.has(table)) {\n throw new Error(`Unknown table: ${table}`);\n }\n }\n\n private async getStore(\n storeName: string,\n mode: IDBTransactionMode,\n ): Promise<IDBObjectStore> {\n const db = await this.dbPromise;\n if (!db.objectStoreNames.contains(storeName)) {\n throw new Error(`Store not found: ${storeName}`);\n }\n return db.transaction(storeName, mode).objectStore(storeName);\n }\n\n // --- Records ---\n\n async getRecord(\n resource: string,\n id: string,\n ): Promise<Record<string, unknown> | null> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get(id);\n request.onsuccess = () => resolve(request.result || null);\n request.onerror = () => reject(request.error);\n });\n }\n\n async listRecords(resource: string): Promise<Record<string, unknown>[]> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.getAll();\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async upsertRecord(\n resource: string,\n record: Record<string, unknown>,\n ): Promise<void> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readwrite\");\n return new Promise((resolve, reject) => {\n // In new design, record is just the object. Key is 'id'.\n const request = store.put(record);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async deleteRecord(resource: string, id: string): Promise<void> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.delete(id);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Atomic read-modify-write merge using a single transaction.\n * Uses one-level-deep merge for object-type fields.\n */\n async mergeRecord(\n resource: string,\n id: string,\n partial: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n this.validateTableName(resource);\n const db = await this.dbPromise;\n \n return new Promise((resolve, reject) => {\n const tx = db.transaction(resource, \"readwrite\");\n const store = tx.objectStore(resource);\n \n // Read existing record\n const getRequest = store.get(id);\n \n getRequest.onsuccess = () => {\n const existing = getRequest.result;\n // Merge with deep merge logic\n const merged = existing\n ? deepMergeOneLevel(existing, partial)\n : { ...partial, id };\n \n // Ensure id is present\n merged.id = id;\n \n // Write merged record\n const putRequest = store.put(merged);\n \n putRequest.onsuccess = () => {\n resolve(merged);\n };\n putRequest.onerror = () => {\n reject(putRequest.error);\n };\n };\n \n getRequest.onerror = () => {\n reject(getRequest.error);\n };\n \n tx.onerror = () => {\n reject(tx.error);\n };\n });\n }\n\n // --- Join Rows ---\n\n async listJoinRows(\n storeName: string,\n ): Promise<Array<Record<string, unknown>>> {\n const store = await this.getStore(storeName, \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.getAll();\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async getJoinRows(\n storeName: string,\n fromId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const store = await this.getStore(storeName, \"readonly\");\n const index = store.index(\"by_from\");\n return new Promise((resolve, reject) => {\n const request = index.getAll(fromId);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n \n async getJoinRowsInverse(\n storeName: string,\n toId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const store = await this.getStore(storeName, \"readonly\");\n const index = store.index(\"by_to\");\n return new Promise((resolve, reject) => {\n const request = index.getAll(toId);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async upsertJoinRow(\n storeName: string,\n row: Record<string, unknown>,\n ): Promise<void> {\n const store = await this.getStore(storeName, \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.put(row);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async setJoinRows(\n storeName: string,\n rows: Array<Record<string, unknown>>,\n ): Promise<void> {\n const store = await this.getStore(storeName, \"readwrite\");\n return new Promise((resolve, reject) => {\n let count = 0;\n if (rows.length === 0) {\n resolve();\n return;\n }\n const checkDone = () => {\n count++;\n if (count === rows.length) resolve();\n };\n\n for (const row of rows) {\n const req = store.put(row);\n req.onsuccess = checkDone;\n req.onerror = () => reject(req.error);\n }\n });\n }\n\n async deleteJoinRow(\n storeName: string,\n from: string,\n to: string,\n ): Promise<void> {\n const store = await this.getStore(storeName, \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.delete([from, to]);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n async findRecords(\n resource: string,\n field: string,\n value: unknown,\n ): Promise<Record<string, unknown>[]> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readonly\");\n\n // Check if index exists\n if (store.indexNames.contains(`by_${field}`)) {\n const index = store.index(`by_${field}`);\n return new Promise((resolve, reject) => {\n const request = index.getAll(value as IDBValidKey);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n // Index-miss path: list all and filter (strictly scoped to resource)\n const all = await this.listRecords(resource);\n return all.filter((r) => r[field] === value);\n }\n\n // --- Sync State ---\n\n async getCursor(resource: string): Promise<string | null> {\n // Skip validation for internal cursor keys (SYNC-CURSOR-001)\n if (resource !== \"__global_cursor__\") {\n this.validateTableName(resource);\n }\n const store = await this.getStore(\"meta\", \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get([\"cursor\", resource]);\n request.onsuccess = () => resolve(request.result?.value || null);\n request.onerror = () => reject(request.error);\n });\n }\n\n async setCursor(resource: string, cursor: string | null): Promise<void> {\n // Skip validation for internal cursor keys (SYNC-CURSOR-001)\n if (resource !== \"__global_cursor__\") {\n this.validateTableName(resource);\n }\n validateCursor(cursor);\n const store = await this.getStore(\"meta\", \"readwrite\");\n return new Promise((resolve, reject) => {\n if (cursor === null) {\n const request = store.delete([\"cursor\", resource]);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n } else {\n const request = store.put({\n type: \"cursor\",\n key: resource,\n value: cursor,\n });\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n }\n });\n }\n\n async getHydrationState(resource: string): Promise<DatafnHydrationState> {\n this.validateTableName(resource);\n const store = await this.getStore(\"meta\", \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.get([\"hydration\", resource]);\n request.onsuccess = () => resolve(request.result?.value || \"notStarted\");\n request.onerror = () => reject(request.error);\n });\n }\n\n async setHydrationState(\n resource: string,\n state: DatafnHydrationState,\n ): Promise<void> {\n this.validateTableName(resource);\n validateHydrationState(state);\n const current = await this.getHydrationState(resource);\n validateTransition(current, state);\n\n const store = await this.getStore(\"meta\", \"readwrite\");\n return new Promise((resolve, reject) => {\n const request = store.put({\n type: \"hydration\",\n key: resource,\n value: state,\n });\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Changelog ---\n\n async changelogAppend(\n entry: Omit<DatafnChangelogEntry, \"seq\">,\n ): Promise<DatafnChangelogEntry> {\n validateMutation(entry);\n const store = await this.getStore(\"changelog\", \"readwrite\");\n const index = store.index(\"by_client_mutation\");\n\n // Check for duplicate\n const existing = await new Promise<DatafnChangelogEntry | undefined>(\n (resolve, reject) => {\n const request = index.get([entry.clientId, entry.mutationId]);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n },\n );\n\n if (existing) {\n return existing;\n }\n\n // Insert new\n return new Promise((resolve, reject) => {\n // Don't pass seq, let autoIncrement handle it\n const request = store.add(entry);\n request.onsuccess = () => {\n const seq = request.result as number;\n resolve({ ...entry, seq });\n };\n request.onerror = () => reject(request.error);\n });\n }\n\n async changelogList(\n options: { limit?: number } = {},\n ): Promise<DatafnChangelogEntry[]> {\n const store = await this.getStore(\"changelog\", \"readonly\");\n return new Promise((resolve, reject) => {\n const limit = options.limit || 100;\n // getAll allows limit\n const request = store.getAll(null, limit);\n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => reject(request.error);\n });\n }\n\n async changelogAck(options: { throughSeq: number }): Promise<void> {\n const store = await this.getStore(\"changelog\", \"readwrite\");\n\n // Delete range <= throughSeq\n const range = IDBKeyRange.upperBound(options.throughSeq);\n\n return new Promise((resolve, reject) => {\n const request = store.delete(range);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Counts for reconcile (SYNC-007) ---\n\n async countRecords(resource: string): Promise<number> {\n this.validateTableName(resource);\n const store = await this.getStore(resource, \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async countJoinRows(relationKey: string): Promise<number> {\n const store = await this.getStore(relationKey, \"readonly\");\n return new Promise((resolve, reject) => {\n const request = store.count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n // --- Lifecycle (CLN-001, CLN-002) ---\n\n async close(): Promise<void> {\n const db = await this.dbPromise;\n db.close();\n }\n\n async clearAll(): Promise<void> {\n const db = await this.dbPromise;\n const storeNames = Array.from(db.objectStoreNames);\n \n // Delete all data from all stores\n const transaction = db.transaction(storeNames, \"readwrite\");\n \n return new Promise((resolve, reject) => {\n const clearPromises: Promise<void>[] = [];\n \n for (const storeName of storeNames) {\n const store = transaction.objectStore(storeName);\n clearPromises.push(\n new Promise((resolveStore, rejectStore) => {\n const request = store.clear();\n request.onsuccess = () => resolveStore();\n request.onerror = () => rejectStore(request.error);\n })\n );\n }\n \n transaction.oncomplete = () => {\n Promise.all(clearPromises).then(() => resolve()).catch(reject);\n };\n transaction.onerror = () => reject(transaction.error);\n });\n }\n\n // --- Health Check (HEAL-001, IDB-001) ---\n\n async healthCheck(): Promise<{ ok: boolean; issues: string[] }> {\n const issues: string[] = [];\n \n try {\n // Verify database is accessible\n const db = await this.dbPromise;\n if (!db) {\n issues.push(\"Database not initialized\");\n return { ok: false, issues };\n }\n\n // Verify expected object stores exist\n const storeNames = Array.from(db.objectStoreNames);\n \n // Check meta stores\n const requiredStores = [\"meta\", \"changelog\"];\n for (const storeName of requiredStores) {\n if (!storeNames.includes(storeName)) {\n issues.push(`Missing object store: ${storeName}`);\n }\n }\n\n // Check resource stores if we have a schema\n if (this.schema) {\n for (const resource of this.schema.resources) {\n if (!storeNames.includes(resource.name)) {\n issues.push(`Missing object store: ${resource.name}`);\n }\n }\n }\n\n // Verify cursor store is readable (use a health check key that won't conflict)\n if (storeNames.includes(\"meta\")) {\n try {\n await this.getCursor(\"__health_check__\");\n } catch (err) {\n issues.push(`Cursor store is not readable: ${String(err)}`);\n }\n }\n\n // IDB-001: Check for stuck migrations\n if (storeNames.includes(\"__datafn_meta\")) {\n try {\n const metaStore = await this.getStore(\"__datafn_meta\", \"readonly\");\n const migrationStatus = await new Promise<any>((resolve, reject) => {\n const request = metaStore.get(\"migration_v1_to_v2\");\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n\n if (migrationStatus && migrationStatus.status === \"in_progress\") {\n issues.push(`Migration stuck: v${migrationStatus.oldVersion} to v${DB_VERSION} started at ${migrationStatus.startedAt}`);\n }\n } catch (err) {\n // Migration metadata read failed - not critical\n console.warn(\"Could not check migration status:\", err);\n }\n }\n } catch (err) {\n issues.push(`Storage access error: ${String(err)}`);\n }\n\n return { ok: issues.length === 0, issues };\n }\n}\n"],"mappings":"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","names":["coreEvaluateFilter","resolveCapabilities","mutations","results","result","coreEvaluateFilter","getJoinStoreKey","normalizeRelationPayload","relationName","coreEvaluateFilter","response","result","query","resource","resolveCapabilities","resource","dfqlKey","getJoinStoreKey","dfqlKey","setCursorMonotonically","getJoinStoreKey","getJoinStoreKey","remote","getJoinStoreKey","kvId","KV_RESOURCE_NAME","executeMutation","getJoinStoreKey","getJoinStoreKey","coreEvaluateFilter","KV_RESOURCE_NAME","KV_RESOURCE_NAME","KV_RESOURCE_NAME","KV_RESOURCE_NAME","getJoinStoreKey","enumerateJoinStoreKeys","validateMutation","KV_RESOURCE_NAME","enumerateJoinStoreKeys","getJoinStoreKey"]}