@iadev93/zuno 0.0.9 → 0.0.11

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/sync/index.ts","../src/core/index.ts","../src/shared/readable.ts","../src/utils.ts"],"names":["applyIncomingEvent","universe","event","context","clientId","versions","isAuthoritative","current","store","startSSE","opts","url","syncUrl","getLastEventId","onEvent","resolveConflict","es","retryCount","applyState","queue","isFlushing","flushQueue","keyIndex","reducedQueue","idx","prev","res","data","serverState","serverVersion","nextState","localState","json","err","connect","lastId","connectUrl","e","snap","key","rec","r","delay","dispatchFn","version","startBroadcastChannel","channelName","getSnapshot","onSnapshot","channel","msg","createStore","initial","reducer","equals","state","listeners","notify","l","next","value","intent","i","listener","createUniverse","stores","cachedSnapshot","init","s","out","existing","snapshot","plain","k","createZuno","lastEventId","hydrateSnapshot","apply","sse","dispatch","bc","storeKey","pendingSyncs","batchPromise","flushBatch","syncs","coreDispatch","nextVersion","middlewareAPI","middleware","rawStore","cb","v1","v2","id","toReadable","onChange","shallowEqual","a","b","keysA","keysB"],"mappings":"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","file":"index.js","sourcesContent":["import type { Universe } from \"../core\";\n\n// --- Types ---\n\nexport type ConflictResolver<T = unknown> = (\n\tlocalState: T,\n\tserverState: T,\n\tstoreKey: string,\n) => T;\n\n/**\n * Authoritative state event.\n */\nexport type ZunoStateEvent = {\n\tstoreKey: string;\n\tstate: unknown; // Was 'any', now strictly 'unknown'\n\tintent?: { type: string; payload?: unknown };\n\tversion?: number;\n\tbaseVersion?: number;\n\torigin?: string;\n\tts?: number;\n\teventId?: number;\n};\n\n/**\n * Generic transport status.\n */\nexport type TransportStatus = {\n\tok: boolean;\n\tstatus: number;\n\t// biome-ignore lint/suspicious/noExplicitAny: generic JSON response\n\tjson: any;\n\treason?: string;\n};\n\n/**\n * Client transport interface.\n */\nexport interface ZunoTransport {\n\tdispatch(event: ZunoStateEvent): Promise<TransportStatus>;\n\tunsubscribe?(): void;\n}\n\n/**\n * Apply incoming event to the universe and local bookkeeping.\n */\nexport function applyIncomingEvent(\n\tuniverse: Universe,\n\tevent: ZunoStateEvent,\n\tcontext: {\n\t\tclientId: string;\n\t\tlocalState: Map<string, unknown>;\n\t\tversions: Map<string, number>;\n\t},\n) {\n\tconst { clientId, versions } = context;\n\n\t// 1. Determine if this event is Authoritative (from Server) or Optimistic (from Peer/Local)\n\tconst isAuthoritative =\n\t\tevent.origin === \"server\" || event.origin === \"conflict-resolution\";\n\tconst current = versions.get(event.storeKey) ?? 0;\n\n\t// 2. Version check\n\tif (typeof event.version === \"number\") {\n\t\t// If it's not authoritative, we strictly enforce incrementing versions\n\t\tif (!isAuthoritative && event.version <= current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Update version tracker\n\t\tversions.set(event.storeKey, event.version);\n\t} else if (event.origin === clientId) {\n\t\t// Suppress versionless loopback\n\t\treturn;\n\t}\n\n\t// 3. Apply to universe\n\tconst store = universe.getStore(event.storeKey, () => event.state);\n\n\t// If we have an intent, try to apply it first for side effects (but only if it's forward progress or authoritative)\n\tif (event.intent) {\n\t\t// If it's a version match/stale authoritative event, we might want to SKIP the intent\n\t\t// to avoid double-application (since we likely already did it optimistically).\n\t\t// However, snapping state (below) is always safe.\n\t\tif (\n\t\t\ttypeof event.version === \"number\" &&\n\t\t\tevent.version <= current &&\n\t\t\tisAuthoritative\n\t\t) {\n\t\t\t// Skip intent, but snap state anyway below.\n\t\t} else {\n\t\t\tstore.apply(event.intent);\n\t\t}\n\t}\n\n\t// 4. Authoritative State Snap\n\t// ALWAYS apply the state if provided and it's authoritative or has a higher version.\n\tif (event.state !== undefined) {\n\t\tif (\n\t\t\tisAuthoritative ||\n\t\t\t(typeof event.version === \"number\" && event.version > current)\n\t\t) {\n\t\t\tstore.set(event.state);\n\t\t}\n\t}\n}\n\n// --- SSE Client ---\n\nexport type SSEOptions = {\n\tuniverse: Universe;\n\turl: string;\n\tsyncUrl: string;\n\toptimistic: boolean;\n\tclientId: string;\n\tversions: Map<string, number>;\n\tgetLastEventId: () => number;\n\tonOpen?: () => void;\n\tonClose?: () => void;\n\tonEvent?: (event: ZunoStateEvent) => void;\n\tresolveConflict?: ConflictResolver;\n};\n\nexport function startSSE(opts: SSEOptions): ZunoTransport {\n\tconst {\n\t\turl,\n\t\tsyncUrl,\n\t\tuniverse,\n\t\tclientId,\n\t\tversions,\n\t\tgetLastEventId,\n\t\tonEvent,\n\t\tresolveConflict,\n\t} = opts;\n\tlet es: EventSource | null = null;\n\tlet retryCount = 0;\n\n\t// Helper to apply state changes\n\tconst applyState = (event: ZunoStateEvent) => {\n\t\tif (onEvent) {\n\t\t\tonEvent(event);\n\t\t} else {\n\t\t\t// Fallback default implementation\n\t\t\tif (typeof event.version === \"number\") {\n\t\t\t\tconst current = versions.get(event.storeKey) ?? 0;\n\t\t\t\tif (event.version <= current) return;\n\t\t\t\tversions.set(event.storeKey, event.version);\n\t\t\t}\n\t\t\tconst store = universe.getStore(event.storeKey, () => event.state);\n\t\t\tif (event.intent) {\n\t\t\t\tstore.apply(event.intent);\n\t\t\t} else {\n\t\t\t\tstore.set(event.state);\n\t\t\t}\n\t\t}\n\t};\n\n\t// --- Offline Support ---\n\tconst queue: ZunoStateEvent[] = [];\n\tlet isFlushing = false;\n\n\tasync function flushQueue() {\n\t\tif (isFlushing || queue.length === 0) return;\n\t\tif (typeof navigator !== \"undefined\" && !navigator.onLine) return;\n\n\t\tisFlushing = true;\n\n\t\t// --- Coalesce / Deduplicate Logic ---\n\t\t// 1. Map index of first occurrence of each storeKey\n\t\tconst keyIndex = new Map<string, number>();\n\t\t// 2. Reduced queue construction\n\t\tconst reducedQueue: ZunoStateEvent[] = [];\n\n\t\tfor (const event of queue) {\n\t\t\tif (keyIndex.has(event.storeKey)) {\n\t\t\t\t// We've seen this key before. We want to update the existing entry in reducedQueue.\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: key exists per has check\n\t\t\t\tconst idx = keyIndex.get(event.storeKey)!;\n\t\t\t\tconst prev = reducedQueue[idx];\n\t\t\t\t// Merge: keep original baseVersion (from the start of the chain) but use NEW state.\n\t\t\t\t// Note: We also likely want to keep the original 'ts' if strictly ordering,\n\t\t\t\t// but state is what matters.\n\t\t\t\t// The 'version' in the event is the *optimistic* version.\n\t\t\t\t// We can keep the *latest* optimistic version (e.g. v10) in the event,\n\t\t\t\t// but server will likely only verify baseVersion.\n\t\t\t\treducedQueue[idx] = { ...event, baseVersion: prev.baseVersion };\n\t\t\t} else {\n\t\t\t\tkeyIndex.set(event.storeKey, reducedQueue.length);\n\t\t\t\treducedQueue.push(event);\n\t\t\t}\n\t\t}\n\n\t\t// Replace original queue with reduced one.\n\t\t// We modify 'queue' in place or reset it.\n\t\t// Since 'queue' is const binding to array, we can't reassign variable,\n\t\t// but we can clear and push.\n\t\tqueue.length = 0;\n\t\tqueue.push(...reducedQueue);\n\n\t\ttry {\n\t\t\twhile (queue.length > 0) {\n\t\t\t\tconst event = queue[0];\n\t\t\t\ttry {\n\t\t\t\t\tconst res = await fetch(syncUrl, {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\tbody: JSON.stringify(event),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!res.ok && res.status !== 409) {\n\t\t\t\t\t\t// Keep in queue for retry if it's a transient server error?\n\t\t\t\t\t\t// For now we dequeue on non-network errors to avoid blocking.\n\t\t\t\t\t\tif (res.status >= 400 && res.status < 500) {\n\t\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// For 500, we might want to retry? Let's treat it as network-ish for now.\n\t\t\t\t\t\t// But to be safe and not block forever:\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (res.status === 409) {\n\t\t\t\t\t\tconst data = await res.json();\n\t\t\t\t\t\tif (data.current) {\n\t\t\t\t\t\t\tconst { state: serverState, version: serverVersion } =\n\t\t\t\t\t\t\t\tdata.current;\n\n\t\t\t\t\t\t\tlet nextState = serverState;\n\t\t\t\t\t\t\tif (resolveConflict) {\n\t\t\t\t\t\t\t\tconst localState = universe\n\t\t\t\t\t\t\t\t\t.getStore(event.storeKey, () => null)\n\t\t\t\t\t\t\t\t\t.get();\n\t\t\t\t\t\t\t\tnextState = resolveConflict(\n\t\t\t\t\t\t\t\t\tlocalState,\n\t\t\t\t\t\t\t\t\tserverState,\n\t\t\t\t\t\t\t\t\tevent.storeKey,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// versions.set(event.storeKey, serverVersion); // REMOVE THIS\n\n\t\t\t\t\t\t\t// 2. Apply resolved state locally\n\t\t\t\t\t\t\tapplyState({\n\t\t\t\t\t\t\t\tstoreKey: event.storeKey,\n\t\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\t\tversion: serverVersion,\n\t\t\t\t\t\t\t\torigin: \"conflict-resolution\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// 3. If resolved state differs from server, auto-sync back\n\t\t\t\t\t\t\tif (JSON.stringify(nextState) !== JSON.stringify(serverState)) {\n\t\t\t\t\t\t\t\tqueue.unshift({\n\t\t\t\t\t\t\t\t\t...event,\n\t\t\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\t\t\tbaseVersion: serverVersion,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t} else if (res.ok) {\n\t\t\t\t\t\tconst json = await res.json();\n\t\t\t\t\t\tif (json.event && typeof json.event.version === \"number\") {\n\t\t\t\t\t\t\t// Just update version map\n\t\t\t\t\t\t\tversions.set(event.storeKey, json.event.version);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[Zuno] Flush failed, retrying later\", err);\n\t\t\t\t\tbreak; // Network error, stop flushing\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tisFlushing = false;\n\t\t}\n\t}\n\tfunction connect() {\n\t\tconst lastId = getLastEventId();\n\t\tconst connectUrl = new URL(url, globalThis.location?.href);\n\t\tif (lastId > 0) connectUrl.searchParams.set(\"lastEventId\", String(lastId));\n\n\t\tes = new EventSource(connectUrl.toString());\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: EventSource data is string, rec is parsed JSON\n\t\tes.addEventListener(\"snapshot\", (e: any) => {\n\t\t\ttry {\n\t\t\t\tconst snap = JSON.parse(e.data);\n\t\t\t\tfor (const [key, rec] of Object.entries(snap)) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: rec state can be anything\n\t\t\t\t\tconst r = rec as { state: any; version: number };\n\t\t\t\t\tapplyState({\n\t\t\t\t\t\tstoreKey: key,\n\t\t\t\t\t\tstate: r.state,\n\t\t\t\t\t\tversion: r.version,\n\t\t\t\t\t\torigin: \"server\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Zuno] Failed to parse snapshot\", err);\n\t\t\t}\n\t\t});\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: EventSource event data\n\t\tes.addEventListener(\"state\", (e: any) => {\n\t\t\ttry {\n\t\t\t\tconst event = JSON.parse(e.data) as ZunoStateEvent;\n\t\t\t\t// If server didn't provide an origin (e.g. manual server-side trigger),\n\t\t\t\t// we treat it as authoritative \"server\" origin.\n\t\t\t\tif (!event.origin) {\n\t\t\t\t\tevent.origin = \"server\";\n\t\t\t\t}\n\n\t\t\t\tif (event.origin === clientId) return;\n\n\t\t\t\tapplyState(event);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Zuno] Failed to parse SSE event\", err);\n\t\t\t}\n\t\t});\n\n\t\tes.onopen = () => {\n\t\t\tretryCount = 0;\n\t\t\topts.onOpen?.();\n\t\t\tflushQueue();\n\t\t};\n\n\t\tes.onerror = () => {\n\t\t\tes?.close();\n\t\t\topts.onClose?.();\n\t\t\tconst delay = Math.min(1000 * 2 ** retryCount, 30000);\n\t\t\tretryCount++;\n\t\t\tsetTimeout(connect, delay);\n\t\t};\n\t}\n\n\tif (typeof window !== \"undefined\") {\n\t\twindow.addEventListener(\"online\", flushQueue);\n\t}\n\n\tconnect();\n\n\tconst dispatchFn = async (\n\t\tevent: ZunoStateEvent,\n\t): Promise<TransportStatus> => {\n\t\ttry {\n\t\t\t// Removed local application here. Local application is handled by coreDispatch\n\t\t\t// to avoid double-update when intents are used.\n\n\t\t\t// 1. Optimistic Local Apply\n\t\t\t// This is needed for direct transport usage (like in tests)\n\t\t\tif (opts.optimistic !== false && !event.origin) {\n\t\t\t\tapplyState(event);\n\t\t\t}\n\n\t\t\t// Check online status first\n\t\t\tif (typeof navigator !== \"undefined\" && !navigator.onLine) {\n\t\t\t\tqueue.push(event);\n\t\t\t\treturn { ok: false, status: 0, json: null, reason: \"OFFLINE_QUEUED\" };\n\t\t\t}\n\n\t\t\tconst res = await fetch(syncUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify(event),\n\t\t\t});\n\n\t\t\tif (res.status === 409) {\n\t\t\t\tconst data = await res.json();\n\t\t\t\tif (data.current) {\n\t\t\t\t\tconst { state: serverState, version: serverVersion } = data.current;\n\n\t\t\t\t\tlet nextState = serverState;\n\t\t\t\t\tif (resolveConflict) {\n\t\t\t\t\t\tconst localState = universe\n\t\t\t\t\t\t\t.getStore(event.storeKey, () => null)\n\t\t\t\t\t\t\t.get();\n\t\t\t\t\t\tnextState = resolveConflict(\n\t\t\t\t\t\t\tlocalState,\n\t\t\t\t\t\t\tserverState,\n\t\t\t\t\t\t\tevent.storeKey,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyState({\n\t\t\t\t\t\tstoreKey: event.storeKey,\n\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\tversion: serverVersion,\n\t\t\t\t\t\torigin: \"conflict-resolution\",\n\t\t\t\t\t});\n\n\t\t\t\t\tif (JSON.stringify(nextState) !== JSON.stringify(serverState)) {\n\t\t\t\t\t\treturn await dispatchFn({\n\t\t\t\t\t\t\t...event,\n\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\tbaseVersion: serverVersion,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { ok: false, status: 409, json: data, reason: \"CONFLICT\" };\n\t\t\t}\n\n\t\t\tif (!res.ok)\n\t\t\t\treturn { ok: false, status: res.status, json: await res.json() };\n\n\t\t\tconst json = await res.json();\n\t\t\tif (json.event) {\n\t\t\t\tconst { version } = json.event;\n\t\t\t\tif (typeof version === \"number\") {\n\t\t\t\t\tversions.set(event.storeKey, version);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { ok: true, status: 200, json };\n\t\t} catch (err) {\n\t\t\t// Network failure catch\n\t\t\tif (queue.length < 100) {\n\t\t\t\tqueue.push(event);\n\t\t\t\tsetTimeout(flushQueue, 1000);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tstatus: 500,\n\t\t\t\tjson: err,\n\t\t\t\treason: \"NETWORK_ERROR_QUEUED\",\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tdispatch: dispatchFn,\n\t\tunsubscribe: () => {\n\t\t\tes?.close();\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\twindow.removeEventListener(\"online\", flushQueue);\n\t\t\t}\n\t\t},\n\t};\n}\n\n// --- BroadcastChannel ---\n\nexport type BCOptions = {\n\tchannelName: string;\n\tclientId: string;\n\tonEvent: (event: ZunoStateEvent) => void;\n\tgetSnapshot: () => Record<string, { state: unknown; version: number }>;\n\tonSnapshot: (\n\t\tsnap: Record<string, { state: unknown; version: number }>,\n\t) => void;\n};\n\nexport function startBroadcastChannel(opts: BCOptions) {\n\tconst { channelName, clientId, onEvent, getSnapshot, onSnapshot } = opts;\n\tconst channel = new BroadcastChannel(channelName);\n\n\tchannel.onmessage = (e) => {\n\t\tconst msg = e.data;\n\t\tif (msg.origin === clientId) return;\n\n\t\tif (msg.type === \"event\") onEvent(msg.event);\n\t\tif (msg.type === \"hello\")\n\t\t\tchannel.postMessage({\n\t\t\t\ttype: \"snapshot\",\n\t\t\t\tsnapshot: getSnapshot(),\n\t\t\t\torigin: clientId,\n\t\t\t});\n\t\tif (msg.type === \"snapshot\") onSnapshot(msg.snapshot);\n\t};\n\n\treturn {\n\t\tpublish: (event: ZunoStateEvent) =>\n\t\t\tchannel.postMessage({ type: \"event\", event, origin: clientId }),\n\t\thello: () => channel.postMessage({ type: \"hello\", origin: clientId }),\n\t\tstop: () => channel.close(),\n\t};\n}\n","import type {\n\tConflictResolver,\n\tTransportStatus,\n\tZunoStateEvent,\n} from \"../sync\";\nimport { applyIncomingEvent, startBroadcastChannel, startSSE } from \"../sync\";\n\n// --- Types ---\n\n/**\n * Authoritative snapshot of the entire universe.\n */\nexport type ZunoSnapshot = {\n\tstate: Record<string, { state: unknown; version: number }>;\n\tlastEventId: number;\n};\n\n/**\n * A simple state container for a single keyed value.\n */\nexport interface Store<T> {\n\tget(): T;\n\tset(next: T | ((prev: T) => T)): void;\n\tapply(intent: unknown): void;\n\tsubscribe(listener: (state: T) => void): () => void;\n\tequals(val1: any, val2: any): boolean;\n}\n\n/**\n * A Universe manages many stores.\n */\nexport interface Universe {\n\tgetStore<T>(\n\t\tkey: string,\n\t\tinit: () => T,\n\t\treducer?: (prev: T, intent: any) => T,\n\t\tequals?: (v1: any, v2: any) => boolean,\n\t): Store<T>;\n\tsnapshot(): Record<string, unknown>;\n\trestore(data: Record<string, unknown>): void;\n\tdelete(key: string): void;\n\tclear(): void;\n\thydrateSnapshot(snapshot: ZunoSnapshot): void;\n}\n\n// --- Middleware Types ---\n\nexport type Dispatch = (event: ZunoStateEvent) => Promise<TransportStatus>;\n\nexport type MiddlewareAPI = {\n\tuniverse: Universe;\n\tclientId: string;\n\tversions: Map<string, number>;\n};\n\nexport type Middleware = (api: MiddlewareAPI) => (next: Dispatch) => Dispatch;\n\n/**\n * Options for creating a Zuno instance.\n */\nexport type CreateZunoOptions = {\n\t/** Optional pre-existing universe. */\n\tuniverse?: Universe;\n\t/** BroadcastChannel name for local tab sync. */\n\tchannelName?: string;\n\t/** SSE endpoint URL. */\n\tsseUrl?: string;\n\t/** Sync endpoint URL (required if sseUrl is provided). */\n\tsyncUrl?: string;\n\t/** Apply updates locally before server confirmation (default: true). */\n\toptimistic?: boolean;\n\t/** Batch multiple updates in the same microtask (default: false). */\n\tbatchSync?: boolean;\n\t/** Unique client identifier (default: random UUID). */\n\tclientId?: string;\n\t/** Middleware chain. */\n\tmiddleware?: Middleware[];\n\t/** Optional function to resolve 409 conflicts. */\n\tresolveConflict?: ConflictResolver;\n};\n\n/**\n * An extended interface for a Zuno store that includes methods for setting state\n * and a unique key identifier. This represents a store that has been \"bound\" or registered.\n */\nexport type BoundStore<T> = {\n\tkey: string;\n\tget: () => T;\n\tset: (next: T | ((prev: T) => T)) => Promise<unknown>;\n\tsubscribe: (cb: (state: T) => void) => () => void;\n\tequals: (v1: any, v2: any) => boolean;\n\traw: () => Store<T>;\n};\n\n// --- Store Implementation ---\n\n/**\n * Creates a raw ZUNO state management store.\n */\nexport const createStore = <T>(\n\tinitial: T,\n\treducer?: (prev: T, intent: any) => T,\n\tequals: (v1: any, v2: any) => boolean = Object.is,\n): Store<T> => {\n\tlet state = initial;\n\tconst listeners = new Set<(state: T) => void>();\n\n\tconst notify = () => {\n\t\tlisteners.forEach((l) => {\n\t\t\tl(state);\n\t\t});\n\t};\n\n\treturn {\n\t\tget: () => state,\n\t\tequals,\n\t\tset: (next) => {\n\t\t\tconst value =\n\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(state) : next;\n\t\t\tif (equals(value, state)) return;\n\t\t\tstate = value;\n\t\t\tnotify();\n\t\t},\n\t\tapply: (intent) => {\n\t\t\tconst i = intent as { type: string; payload?: any };\n\t\t\tif (i.type === \"SET\") {\n\t\t\t\tconst value = i.payload;\n\t\t\t\tif (equals(value, state)) return;\n\t\t\t\tstate = value;\n\t\t\t\tnotify();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!reducer) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[Zuno] apply() called for intent \"${i.type}\" on a store without a reducer. Intent ignored.`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextState = reducer(state, i);\n\t\t\tif (equals(nextState, state)) return;\n\t\t\tstate = nextState;\n\t\t\tnotify();\n\t\t},\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => listeners.delete(listener);\n\t\t},\n\t};\n};\n\n// --- Universe Implementation ---\n\n/**\n * Creates a ZUNO Universe to manage multiple stores.\n */\nexport const createUniverse = (): Universe => {\n\t// biome-ignore lint/suspicious/noExplicitAny: internal registry of heterogeneous stores\n\tconst stores = new Map<string, Store<any>>();\n\tlet cachedSnapshot: Record<string, any> | null = null;\n\n\tconst universe: Universe = {\n\t\tgetStore<T>(\n\t\t\tkey: string,\n\t\t\tinit: () => T,\n\t\t\treducer?: (prev: T, intent: any) => T,\n\t\t\tequals?: (v1: any, v2: any) => boolean,\n\t\t): Store<T> {\n\t\t\tlet s = stores.get(key);\n\t\t\tif (!s) {\n\t\t\t\ts = createStore(init(), reducer, equals);\n\t\t\t\tstores.set(key, s);\n\t\t\t\t// Invalidate cache when new store is added\n\t\t\t\tcachedSnapshot = null;\n\t\t\t\t// Subscribing to invalidate cache on changes\n\t\t\t\ts.subscribe(() => {\n\t\t\t\t\tcachedSnapshot = null;\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn s as Store<T>;\n\t\t},\n\t\tsnapshot(): Record<string, unknown> {\n\t\t\tif (cachedSnapshot) return cachedSnapshot;\n\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, store] of stores.entries()) {\n\t\t\t\tout[key] = store.get();\n\t\t\t}\n\t\t\tcachedSnapshot = out;\n\t\t\treturn out;\n\t\t},\n\t\trestore(data: Record<string, unknown>): void {\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tconst existing = stores.get(key);\n\t\t\t\tif (existing) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: external data needs to be cast to store type\n\t\t\t\t\texisting.set(value as any);\n\t\t\t\t} else {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: external data needs to be cast to store type\n\t\t\t\t\tstores.set(key, createStore(value as any));\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdelete(key: string): void {\n\t\t\tstores.delete(key);\n\t\t},\n\t\tclear(): void {\n\t\t\tstores.clear();\n\t\t},\n\t\thydrateSnapshot(snapshot: ZunoSnapshot) {\n\t\t\tconst plain: Record<string, unknown> = {};\n\t\t\tfor (const [k, rec] of Object.entries(snapshot.state)) {\n\t\t\t\tplain[k] = rec.state;\n\t\t\t}\n\t\t\tthis.restore(plain);\n\t\t},\n\t};\n\n\treturn universe;\n};\n\n// --- Main Zuno Factory ---\n\n/**\n * Creates a Zuno instance for distributed state synchronization.\n */\nexport const createZuno = (opts: CreateZunoOptions = {}) => {\n\tconst localState = new Map<string, unknown>();\n\tconst versions = new Map<string, number>();\n\tconst universe = opts.universe ?? createUniverse();\n\tconst clientId =\n\t\topts.clientId ?? globalThis.crypto?.randomUUID?.() ?? String(Math.random());\n\tlet _sseReady = false;\n\tlet lastEventId = 0;\n\n\tfunction hydrateSnapshot(snapshot: ZunoSnapshot) {\n\t\tconst plain: Record<string, unknown> = {};\n\t\tfor (const [k, rec] of Object.entries(snapshot.state)) {\n\t\t\tplain[k] = rec.state;\n\t\t\tversions.set(k, rec.version);\n\t\t}\n\t\tuniverse.restore(plain);\n\t\tlastEventId = snapshot.lastEventId;\n\t}\n\n\tconst apply = (event: ZunoStateEvent) => {\n\t\tif (typeof event.eventId === \"number\") {\n\t\t\tlastEventId = Math.max(lastEventId, event.eventId);\n\t\t}\n\t\tapplyIncomingEvent(universe, event, { clientId, localState, versions });\n\t};\n\n\tconst sse =\n\t\topts.sseUrl && opts.syncUrl\n\t\t\t? startSSE({\n\t\t\t\tuniverse,\n\t\t\t\turl: opts.sseUrl,\n\t\t\t\tsyncUrl: opts.syncUrl,\n\t\t\t\toptimistic: opts.optimistic ?? true,\n\t\t\t\tclientId,\n\t\t\t\tversions,\n\t\t\t\tgetLastEventId: () => lastEventId,\n\t\t\t\tonOpen: () => {\n\t\t\t\t\t_sseReady = true;\n\t\t\t\t},\n\t\t\t\tonClose: () => {\n\t\t\t\t\t_sseReady = false;\n\t\t\t\t},\n\t\t\t\tonEvent: (e) => dispatch(e), // Route incoming SSE events through middleware\n\t\t\t\tresolveConflict: opts.resolveConflict,\n\t\t\t})\n\t\t\t: null;\n\n\tconst bc = opts.channelName\n\t\t? startBroadcastChannel({\n\t\t\tchannelName: opts.channelName,\n\t\t\tclientId,\n\t\t\tonEvent: (e) => dispatch(e), // Route incoming BC events through middleware\n\t\t\tgetSnapshot: () => {\n\t\t\t\tconst snap = universe.snapshot();\n\t\t\t\tconst out: Record<string, { state: unknown; version: number }> = {};\n\t\t\t\tfor (const [storeKey, state] of Object.entries(snap)) {\n\t\t\t\t\tout[storeKey] = { state, version: versions.get(storeKey) ?? 0 };\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t},\n\t\t\tonSnapshot: (snap) => {\n\t\t\t\tfor (const [storeKey, rec] of Object.entries(snap)) {\n\t\t\t\t\tapply({ storeKey, state: rec.state, version: rec.version });\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\t\t: null;\n\n\tsetTimeout(() => bc?.hello(), 100);\n\n\t// --- Sync Batching ---\n\tconst pendingSyncs = new Map<string, ZunoStateEvent>();\n\tlet batchPromise: Promise<void> | null = null;\n\n\tconst flushBatch = async () => {\n\t\tconst syncs = Array.from(pendingSyncs.values());\n\t\tpendingSyncs.clear();\n\t\tbatchPromise = null;\n\n\t\tfor (const event of syncs) {\n\t\t\tif (sse) {\n\t\t\t\tsse.dispatch(event).catch((err) => {\n\t\t\t\t\tconsole.error(\"[Zuno] Batch sync failed\", err);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\tconst coreDispatch = async (\n\t\tevent: ZunoStateEvent,\n\t): Promise<TransportStatus> => {\n\t\t// 1. Incoming/Reflected Event Logic (events WITH origin)\n\t\tif (event.origin) {\n\t\t\t// Always call apply to let applyIncomingEvent handle version checks and application\n\t\t\tapply(event);\n\n\t\t\t// If it's from another client, we are done\n\t\t\tif (event.origin !== clientId) {\n\t\t\t\treturn { ok: true, status: 200, json: null };\n\t\t\t}\n\t\t\t// If it's a reflected local event, we still need to broadcast it (fall through)\n\t\t}\n\n\t\t// 2. Outgoing Event Logic (events WITHOUT origin)\n\t\tif (!event.origin) {\n\t\t\tevent.origin = clientId;\n\n\t\t\t// Resolve state if needed (e.g. from mutate)\n\t\t\tconst store = universe.getStore(event.storeKey, () => undefined);\n\n\t\t\tif (event.state === undefined && event.intent) {\n\t\t\t\t// We need the state to send to server.\n\t\t\t\t// If optimistic, we apply it. If not, we only compute if it's a simple SET.\n\t\t\t\tif (opts.optimistic !== false) {\n\t\t\t\t\tstore.apply(event.intent);\n\t\t\t\t\tevent.state = store.get();\n\t\t\t\t} else {\n\t\t\t\t\tconst i = event.intent as { type: string; payload?: any };\n\t\t\t\t\tif (i.type === \"SET\") {\n\t\t\t\t\t\tevent.state = i.payload;\n\t\t\t\t\t}\n\t\t\t\t\t// For other intents with optimistic: false, we might send undefined state\n\t\t\t\t\t// and rely on the server to compute it authoritativeley.\n\t\t\t\t}\n\t\t\t} else if (event.state !== undefined) {\n\t\t\t\tif (opts.optimistic !== false) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: generic dispatch layer\n\t\t\t\t\tstore.set(event.state as any);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Local bookkeeping and versioning\n\t\t\tif (opts.optimistic !== false) {\n\t\t\t\tconst current = versions.get(event.storeKey) ?? 0;\n\t\t\t\tconst nextVersion = current + 1;\n\t\t\t\tversions.set(event.storeKey, nextVersion);\n\t\t\t\tevent.version = nextVersion;\n\t\t\t}\n\n\t\t\t// BROADCAST IMMEDIATELY to local tabs via BC\n\t\t\t// This ensures instant sync across tabs even if SSE is slow or down.\n\t\t\tif (bc) {\n\t\t\t\tbc.publish(event);\n\t\t\t}\n\t\t}\n\n\t\t// 3. Remote Sync (SSE/HTTP) with Optional Batching\n\t\tif (sse) {\n\t\t\tif (opts.batchSync) {\n\t\t\t\t// Coalesce outgoing syncs for the same storeKey within the same microtask\n\t\t\t\tpendingSyncs.set(event.storeKey, event);\n\n\t\t\t\tif (!batchPromise) {\n\t\t\t\t\tbatchPromise = Promise.resolve().then(flushBatch);\n\t\t\t\t}\n\n\t\t\t\t// Note: Batched dispatch currently returns a \"fake\" OK immediately\n\t\t\t\t// to avoid blocking the UI. Error handling is handled via console.error in flushBatch.\n\t\t\t\t// Real conflict resolution still happens via SSE's internal queue/retry.\n\t\t\t\treturn { ok: true, status: 202, json: { batched: true } };\n\t\t\t}\n\n\t\t\treturn await sse.dispatch(event);\n\t\t}\n\n\t\treturn { ok: true, status: 200, json: null };\n\t};\n\n\t// --- Middleware Composition ---\n\tlet dispatch: Dispatch = coreDispatch;\n\n\tif (opts.middleware && opts.middleware.length > 0) {\n\t\tconst middlewareAPI: MiddlewareAPI = {\n\t\t\tuniverse,\n\t\t\tclientId,\n\t\t\tversions,\n\t\t};\n\t\tconst chain = opts.middleware.map((middleware) =>\n\t\t\tmiddleware(middlewareAPI),\n\t\t);\n\t\tdispatch = chain.reduceRight(\n\t\t\t(next, middleware) => middleware(next),\n\t\t\tcoreDispatch,\n\t\t);\n\t}\n\n\tconst store = <T>(\n\t\tstoreKey: string,\n\t\tinit: () => T,\n\t\treducer?: (prev: T, intent: any) => T,\n\t\tequals?: (v1: any, v2: any) => boolean,\n\t): BoundStore<T> => {\n\t\tconst rawStore = universe.getStore<T>(storeKey, init, reducer, equals);\n\t\treturn {\n\t\t\tkey: storeKey,\n\t\t\traw: () => rawStore,\n\t\t\tget: () => rawStore.get(),\n\t\t\tsubscribe: (cb) => rawStore.subscribe(cb),\n\t\t\tequals: (v1, v2) => rawStore.equals(v1, v2),\n\t\t\tset: (next) => {\n\t\t\t\tconst prev = rawStore.get();\n\t\t\t\tconst state =\n\t\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(prev) : next;\n\t\t\t\treturn dispatch({\n\t\t\t\t\tstoreKey,\n\t\t\t\t\tstate,\n\t\t\t\t\tintent: { type: \"SET\", payload: state },\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t};\n\n\treturn {\n\t\tuniverse,\n\t\tclientId,\n\t\tstore,\n\t\tgetStore: universe.getStore.bind(universe),\n\t\tget: <T>(key: string, init?: () => T) =>\n\t\t\tuniverse\n\t\t\t\t.getStore<T>(\n\t\t\t\t\tkey,\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: default init for convenience\n\t\t\t\t\tinit ?? (() => undefined as any),\n\t\t\t\t)\n\t\t\t\t.get(),\n\t\tset: async <T>(key: string, next: T | ((prev: T) => T), init?: () => T) => {\n\t\t\tconst s = universe.getStore<T>(\n\t\t\t\tkey,\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: default init for convenience\n\t\t\t\tinit ?? (() => undefined as any),\n\t\t\t);\n\t\t\tconst state =\n\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(s.get()) : next;\n\n\t\t\t// Don't set origin or version here, let coreDispatch handle it\n\t\t\treturn dispatch({\n\t\t\t\tstoreKey: key,\n\t\t\t\tstate,\n\t\t\t\tintent: { type: \"SET\", payload: state },\n\t\t\t});\n\t\t},\n\t\tmutate: async (\n\t\t\tkey: string,\n\t\t\tintent: { type: string; payload?: unknown },\n\t\t) => {\n\t\t\treturn dispatch({\n\t\t\t\tstoreKey: key,\n\t\t\t\t// coreDispatch will calculate state from intent\n\t\t\t\tstate: undefined as any,\n\t\t\t\tintent,\n\t\t\t});\n\t\t},\n\t\tsubscribe: <T>(key: string, init: () => T, cb: (state: T) => void) =>\n\t\t\tuniverse.getStore<T>(key, init).subscribe(cb),\n\t\tdispatch,\n\t\tstop: () => {\n\t\t\tsse?.unsubscribe?.();\n\t\t\tbc?.stop?.();\n\t\t},\n\t\thydrateSnapshot,\n\t\tgetLastEventId: () => lastEventId,\n\t\tsetLastEventId: (id: number) => {\n\t\t\tlastEventId = id;\n\t\t},\n\t};\n};\n","/** Universal UI adapter contract */\nexport type ZunoReadable<T> = {\n\t/** Read current value (sync) */\n\tgetSnapshot(): T;\n\n\t/**\n\t * Subscribe to changes.\n\t * Call `onChange()` whenever snapshot may have changed.\n\t * Return unsubscribe.\n\t */\n\tsubscribe(onChange: () => void): () => void;\n\n\t/** Optional: React SSR (server snapshot) */\n\tgetServerSnapshot?: () => T;\n};\n\n/** Minimal store shape that can be adapted into a readable */\nexport type ZunoSubscribableStore<T> = {\n\tget(): T;\n\tsubscribe(cb: (state: T) => void): () => void;\n\tequals(v1: any, v2: any): boolean;\n};\n\n/** Adapter helper: convert store => readable */\nexport function toReadable<T>(\n\tstore: ZunoSubscribableStore<T>,\n): ZunoReadable<T> {\n\treturn {\n\t\tgetSnapshot: () => store.get(),\n\t\tsubscribe: (onChange) => store.subscribe(() => onChange()),\n\t};\n}\n","/**\n * Performs a shallow equality check between two values.\n */\nexport function shallowEqual(a: any, b: any): boolean {\n\tif (Object.is(a, b)) return true;\n\n\tif (\n\t\ttypeof a !== \"object\" ||\n\t\ta === null ||\n\t\ttypeof b !== \"object\" ||\n\t\tb === null\n\t) {\n\t\treturn false;\n\t}\n\n\tconst keysA = Object.keys(a);\n\tconst keysB = Object.keys(b);\n\n\tif (keysA.length !== keysB.length) return false;\n\n\tfor (const key of keysA) {\n\t\tif (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
1
+ {"version":3,"sources":["../src/sync/index.ts","../src/core/index.ts","../src/shared/readable.ts","../src/utils.ts"],"names":["applyIncomingEvent","universe","event","context","clientId","versions","isAuthoritative","current","store","startSSE","opts","url","syncUrl","getLastEventId","onEvent","resolveConflict","es","retryCount","applyState","queue","isFlushing","flushQueue","keyIndex","reducedQueue","idx","prev","res","data","serverState","serverVersion","nextState","localState","json","err","connect","lastId","connectUrl","e","snap","key","rec","r","delay","dispatchFn","version","startBroadcastChannel","channelName","getSnapshot","onSnapshot","channel","msg","createStore","initial","reducer","equals","state","listeners","notify","l","next","value","intent","i","listener","createUniverse","stores","cachedSnapshot","trackStore","init","s","out","existing","snapshot","plain","k","createZuno","lastEventId","hydrateSnapshot","apply","sse","dispatch","bc","storeKey","pendingSyncs","batchPromise","flushBatch","syncs","coreDispatch","nextVersion","pending","middlewareAPI","middleware","rawStore","cb","v1","v2","id","toReadable","onChange","shallowEqual","a","b","keysA","keysB","objA","objB"],"mappings":"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","file":"index.js","sourcesContent":["import type { Universe } from \"../core\";\n\n// --- Types ---\n\nexport type ConflictResolver<T = unknown> = (\n\tlocalState: T,\n\tserverState: T,\n\tstoreKey: string,\n) => T;\n\n/**\n * Authoritative state event.\n */\nexport type ZunoStateEvent = {\n\tstoreKey: string;\n\tstate: unknown; // Was 'any', now strictly 'unknown'\n\tintent?: { type: string; payload?: unknown };\n\tversion?: number;\n\tbaseVersion?: number;\n\torigin?: string;\n\tts?: number;\n\teventId?: number;\n};\n\n/**\n * Generic transport status.\n */\nexport type TransportStatus = {\n\tok: boolean;\n\tstatus: number;\n\t// biome-ignore lint/suspicious/noExplicitAny: generic JSON response\n\tjson: any;\n\treason?: string;\n};\n\n/**\n * Client transport interface.\n */\nexport interface ZunoTransport {\n\tdispatch(event: ZunoStateEvent): Promise<TransportStatus>;\n\tunsubscribe?(): void;\n}\n\n/**\n * Apply incoming event to the universe and local bookkeeping.\n */\nexport function applyIncomingEvent(\n\tuniverse: Universe,\n\tevent: ZunoStateEvent,\n\tcontext: {\n\t\tclientId: string;\n\t\tlocalState: Map<string, unknown>;\n\t\tversions: Map<string, number>;\n\t},\n) {\n\tconst { clientId, versions } = context;\n\n\t// 1. Determine if this event is Authoritative (from Server) or Optimistic (from Peer/Local)\n\tconst isAuthoritative =\n\t\tevent.origin === \"server\" || event.origin === \"conflict-resolution\";\n\tconst current = versions.get(event.storeKey) ?? 0;\n\n\t// 2. Version check\n\tif (typeof event.version === \"number\") {\n\t\t// If it's not authoritative, we strictly enforce incrementing versions\n\t\tif (!isAuthoritative && event.version <= current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Update version tracker\n\t\tversions.set(event.storeKey, event.version);\n\t} else if (event.origin === clientId) {\n\t\t// Suppress versionless loopback\n\t\treturn;\n\t}\n\n\t// 3. Apply to universe\n\tconst store = universe.getStore(event.storeKey, () => event.state);\n\n\t// If we have an intent, try to apply it first for side effects (but only if it's forward progress or authoritative)\n\tif (event.intent) {\n\t\t// If it's a version match/stale authoritative event, we might want to SKIP the intent\n\t\t// to avoid double-application (since we likely already did it optimistically).\n\t\t// However, snapping state (below) is always safe.\n\t\tif (\n\t\t\ttypeof event.version === \"number\" &&\n\t\t\tevent.version <= current &&\n\t\t\tisAuthoritative\n\t\t) {\n\t\t\t// Skip intent, but snap state anyway below.\n\t\t} else {\n\t\t\tstore.apply(event.intent);\n\t\t}\n\t}\n\n\t// 4. Authoritative State Snap\n\t// ALWAYS apply the state if provided and it's authoritative or has a higher version.\n\tif (event.state !== undefined) {\n\t\tif (\n\t\t\tisAuthoritative ||\n\t\t\t(typeof event.version === \"number\" && event.version > current)\n\t\t) {\n\t\t\tstore.set(event.state);\n\t\t}\n\t}\n}\n\n// --- SSE Client ---\n\nexport type SSEOptions = {\n\tuniverse: Universe;\n\turl: string;\n\tsyncUrl: string;\n\toptimistic: boolean;\n\tclientId: string;\n\tversions: Map<string, number>;\n\tgetLastEventId: () => number;\n\tonOpen?: () => void;\n\tonClose?: () => void;\n\tonEvent?: (event: ZunoStateEvent) => void;\n\tresolveConflict?: ConflictResolver;\n};\n\nexport function startSSE(opts: SSEOptions): ZunoTransport {\n\tconst {\n\t\turl,\n\t\tsyncUrl,\n\t\tuniverse,\n\t\tclientId,\n\t\tversions,\n\t\tgetLastEventId,\n\t\tonEvent,\n\t\tresolveConflict,\n\t} = opts;\n\tlet es: EventSource | null = null;\n\tlet retryCount = 0;\n\n\t// Helper to apply state changes\n\tconst applyState = (event: ZunoStateEvent) => {\n\t\tif (onEvent) {\n\t\t\tonEvent(event);\n\t\t} else {\n\t\t\t// Fallback default implementation\n\t\t\tif (typeof event.version === \"number\") {\n\t\t\t\tconst current = versions.get(event.storeKey) ?? 0;\n\t\t\t\tif (event.version <= current) return;\n\t\t\t\tversions.set(event.storeKey, event.version);\n\t\t\t}\n\t\t\tconst store = universe.getStore(event.storeKey, () => event.state);\n\t\t\tif (event.intent) {\n\t\t\t\tstore.apply(event.intent);\n\t\t\t} else {\n\t\t\t\tstore.set(event.state);\n\t\t\t}\n\t\t}\n\t};\n\n\t// --- Offline Support ---\n\tconst queue: ZunoStateEvent[] = [];\n\tlet isFlushing = false;\n\n\tasync function flushQueue() {\n\t\tif (isFlushing || queue.length === 0) return;\n\t\tif (typeof navigator !== \"undefined\" && !navigator.onLine) return;\n\n\t\tisFlushing = true;\n\n\t\t// --- Coalesce / Deduplicate Logic ---\n\t\t// 1. Map index of first occurrence of each storeKey\n\t\tconst keyIndex = new Map<string, number>();\n\t\t// 2. Reduced queue construction\n\t\tconst reducedQueue: ZunoStateEvent[] = [];\n\n\t\tfor (const event of queue) {\n\t\t\tif (keyIndex.has(event.storeKey)) {\n\t\t\t\t// We've seen this key before. We want to update the existing entry in reducedQueue.\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: key exists per has check\n\t\t\t\tconst idx = keyIndex.get(event.storeKey)!;\n\t\t\t\tconst prev = reducedQueue[idx];\n\t\t\t\t// Merge: keep original baseVersion (from the start of the chain) but use NEW state.\n\t\t\t\t// Note: We also likely want to keep the original 'ts' if strictly ordering,\n\t\t\t\t// but state is what matters.\n\t\t\t\t// The 'version' in the event is the *optimistic* version.\n\t\t\t\t// We can keep the *latest* optimistic version (e.g. v10) in the event,\n\t\t\t\t// but server will likely only verify baseVersion.\n\t\t\t\treducedQueue[idx] = { ...event, baseVersion: prev.baseVersion };\n\t\t\t} else {\n\t\t\t\tkeyIndex.set(event.storeKey, reducedQueue.length);\n\t\t\t\treducedQueue.push(event);\n\t\t\t}\n\t\t}\n\n\t\t// Replace original queue with reduced one.\n\t\t// We modify 'queue' in place or reset it.\n\t\t// Since 'queue' is const binding to array, we can't reassign variable,\n\t\t// but we can clear and push.\n\t\tqueue.length = 0;\n\t\tqueue.push(...reducedQueue);\n\n\t\ttry {\n\t\t\twhile (queue.length > 0) {\n\t\t\t\tconst event = queue[0];\n\t\t\t\ttry {\n\t\t\t\t\tconst res = await fetch(syncUrl, {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\tbody: JSON.stringify(event),\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!res.ok && res.status !== 409) {\n\t\t\t\t\t\t// Keep in queue for retry if it's a transient server error?\n\t\t\t\t\t\t// For now we dequeue on non-network errors to avoid blocking.\n\t\t\t\t\t\tif (res.status >= 400 && res.status < 500) {\n\t\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// For 500, we might want to retry? Let's treat it as network-ish for now.\n\t\t\t\t\t\t// But to be safe and not block forever:\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (res.status === 409) {\n\t\t\t\t\t\tconst data = await res.json();\n\t\t\t\t\t\tif (data.current) {\n\t\t\t\t\t\t\tconst { state: serverState, version: serverVersion } =\n\t\t\t\t\t\t\t\tdata.current;\n\n\t\t\t\t\t\t\tlet nextState = serverState;\n\t\t\t\t\t\t\tif (resolveConflict) {\n\t\t\t\t\t\t\t\tconst localState = universe\n\t\t\t\t\t\t\t\t\t.getStore(event.storeKey, () => null)\n\t\t\t\t\t\t\t\t\t.get();\n\t\t\t\t\t\t\t\tnextState = resolveConflict(\n\t\t\t\t\t\t\t\t\tlocalState,\n\t\t\t\t\t\t\t\t\tserverState,\n\t\t\t\t\t\t\t\t\tevent.storeKey,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// versions.set(event.storeKey, serverVersion); // REMOVE THIS\n\n\t\t\t\t\t\t\t// 2. Apply resolved state locally\n\t\t\t\t\t\t\tapplyState({\n\t\t\t\t\t\t\t\tstoreKey: event.storeKey,\n\t\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\t\tversion: serverVersion,\n\t\t\t\t\t\t\t\torigin: \"conflict-resolution\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// 3. If resolved state differs from server, auto-sync back\n\t\t\t\t\t\t\tif (JSON.stringify(nextState) !== JSON.stringify(serverState)) {\n\t\t\t\t\t\t\t\tqueue.unshift({\n\t\t\t\t\t\t\t\t\t...event,\n\t\t\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\t\t\tbaseVersion: serverVersion,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t} else if (res.ok) {\n\t\t\t\t\t\tconst json = await res.json();\n\t\t\t\t\t\tif (json.event && typeof json.event.version === \"number\") {\n\t\t\t\t\t\t\t// Just update version map\n\t\t\t\t\t\t\tversions.set(event.storeKey, json.event.version);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tqueue.shift();\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"[Zuno] Flush failed, retrying later\", err);\n\t\t\t\t\tbreak; // Network error, stop flushing\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tisFlushing = false;\n\t\t}\n\t}\n\tfunction connect() {\n\t\tconst lastId = getLastEventId();\n\t\tconst connectUrl = new URL(url, globalThis.location?.href);\n\t\tif (lastId > 0) connectUrl.searchParams.set(\"lastEventId\", String(lastId));\n\n\t\tes = new EventSource(connectUrl.toString());\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: EventSource data is string, rec is parsed JSON\n\t\tes.addEventListener(\"snapshot\", (e: any) => {\n\t\t\ttry {\n\t\t\t\tconst snap = JSON.parse(e.data);\n\t\t\t\tfor (const [key, rec] of Object.entries(snap)) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: rec state can be anything\n\t\t\t\t\tconst r = rec as { state: any; version: number };\n\t\t\t\t\tapplyState({\n\t\t\t\t\t\tstoreKey: key,\n\t\t\t\t\t\tstate: r.state,\n\t\t\t\t\t\tversion: r.version,\n\t\t\t\t\t\torigin: \"server\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Zuno] Failed to parse snapshot\", err);\n\t\t\t}\n\t\t});\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: EventSource event data\n\t\tes.addEventListener(\"state\", (e: any) => {\n\t\t\ttry {\n\t\t\t\tconst event = JSON.parse(e.data) as ZunoStateEvent;\n\t\t\t\t// If server didn't provide an origin (e.g. manual server-side trigger),\n\t\t\t\t// we treat it as authoritative \"server\" origin.\n\t\t\t\tif (!event.origin) {\n\t\t\t\t\tevent.origin = \"server\";\n\t\t\t\t}\n\n\t\t\t\tif (event.origin === clientId) return;\n\n\t\t\t\tapplyState(event);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Zuno] Failed to parse SSE event\", err);\n\t\t\t}\n\t\t});\n\n\t\tes.onopen = () => {\n\t\t\tretryCount = 0;\n\t\t\topts.onOpen?.();\n\t\t\tflushQueue();\n\t\t};\n\n\t\tes.onerror = () => {\n\t\t\tes?.close();\n\t\t\topts.onClose?.();\n\t\t\tconst delay = Math.min(1000 * 2 ** retryCount, 30000);\n\t\t\tretryCount++;\n\t\t\tsetTimeout(connect, delay);\n\t\t};\n\t}\n\n\tif (typeof window !== \"undefined\") {\n\t\twindow.addEventListener(\"online\", flushQueue);\n\t}\n\n\tconnect();\n\n\tconst dispatchFn = async (\n\t\tevent: ZunoStateEvent,\n\t): Promise<TransportStatus> => {\n\t\ttry {\n\t\t\t// Removed local application here. Local application is handled by coreDispatch\n\t\t\t// to avoid double-update when intents are used.\n\n\t\t\t// 1. Optimistic Local Apply\n\t\t\t// This is needed for direct transport usage (like in tests)\n\t\t\tif (opts.optimistic !== false && !event.origin) {\n\t\t\t\tapplyState(event);\n\t\t\t}\n\n\t\t\t// Check online status first\n\t\t\tif (typeof navigator !== \"undefined\" && !navigator.onLine) {\n\t\t\t\tqueue.push(event);\n\t\t\t\treturn { ok: false, status: 0, json: null, reason: \"OFFLINE_QUEUED\" };\n\t\t\t}\n\n\t\t\tconst res = await fetch(syncUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify(event),\n\t\t\t});\n\n\t\t\tif (res.status === 409) {\n\t\t\t\tconst data = await res.json();\n\t\t\t\tif (data.current) {\n\t\t\t\t\tconst { state: serverState, version: serverVersion } = data.current;\n\n\t\t\t\t\tlet nextState = serverState;\n\t\t\t\t\tif (resolveConflict) {\n\t\t\t\t\t\tconst localState = universe\n\t\t\t\t\t\t\t.getStore(event.storeKey, () => null)\n\t\t\t\t\t\t\t.get();\n\t\t\t\t\t\tnextState = resolveConflict(\n\t\t\t\t\t\t\tlocalState,\n\t\t\t\t\t\t\tserverState,\n\t\t\t\t\t\t\tevent.storeKey,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyState({\n\t\t\t\t\t\tstoreKey: event.storeKey,\n\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\tversion: serverVersion,\n\t\t\t\t\t\torigin: \"conflict-resolution\",\n\t\t\t\t\t});\n\n\t\t\t\t\tif (JSON.stringify(nextState) !== JSON.stringify(serverState)) {\n\t\t\t\t\t\treturn await dispatchFn({\n\t\t\t\t\t\t\t...event,\n\t\t\t\t\t\t\tstate: nextState,\n\t\t\t\t\t\t\tbaseVersion: serverVersion,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { ok: false, status: 409, json: data, reason: \"CONFLICT\" };\n\t\t\t}\n\n\t\t\tif (!res.ok)\n\t\t\t\treturn { ok: false, status: res.status, json: await res.json() };\n\n\t\t\tconst json = await res.json();\n\t\t\tif (json.event) {\n\t\t\t\tconst { version } = json.event;\n\t\t\t\tif (typeof version === \"number\") {\n\t\t\t\t\tversions.set(event.storeKey, version);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { ok: true, status: 200, json };\n\t\t} catch (err) {\n\t\t\t// Network failure catch\n\t\t\tif (queue.length < 100) {\n\t\t\t\tqueue.push(event);\n\t\t\t\tsetTimeout(flushQueue, 1000);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tstatus: 500,\n\t\t\t\tjson: err,\n\t\t\t\treason: \"NETWORK_ERROR_QUEUED\",\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tdispatch: dispatchFn,\n\t\tunsubscribe: () => {\n\t\t\tes?.close();\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\twindow.removeEventListener(\"online\", flushQueue);\n\t\t\t}\n\t\t},\n\t};\n}\n\n// --- BroadcastChannel ---\n\nexport type BCOptions = {\n\tchannelName: string;\n\tclientId: string;\n\tonEvent: (event: ZunoStateEvent) => void;\n\tgetSnapshot: () => Record<string, { state: unknown; version: number }>;\n\tonSnapshot: (\n\t\tsnap: Record<string, { state: unknown; version: number }>,\n\t) => void;\n};\n\nexport function startBroadcastChannel(opts: BCOptions) {\n\tconst { channelName, clientId, onEvent, getSnapshot, onSnapshot } = opts;\n\tconst channel = new BroadcastChannel(channelName);\n\n\tchannel.onmessage = (e) => {\n\t\tconst msg = e.data;\n\t\tif (msg.origin === clientId) return;\n\n\t\tif (msg.type === \"event\") onEvent(msg.event);\n\t\tif (msg.type === \"hello\")\n\t\t\tchannel.postMessage({\n\t\t\t\ttype: \"snapshot\",\n\t\t\t\tsnapshot: getSnapshot(),\n\t\t\t\torigin: clientId,\n\t\t\t});\n\t\tif (msg.type === \"snapshot\") onSnapshot(msg.snapshot);\n\t};\n\n\treturn {\n\t\tpublish: (event: ZunoStateEvent) =>\n\t\t\tchannel.postMessage({ type: \"event\", event, origin: clientId }),\n\t\thello: () => channel.postMessage({ type: \"hello\", origin: clientId }),\n\t\tstop: () => channel.close(),\n\t};\n}\n","import type {\n\tConflictResolver,\n\tTransportStatus,\n\tZunoStateEvent,\n} from \"../sync\";\nimport { applyIncomingEvent, startBroadcastChannel, startSSE } from \"../sync\";\n\n// --- Types ---\n\n/**\n * Authoritative snapshot of the entire universe.\n */\nexport type ZunoSnapshot = {\n\tstate: Record<string, { state: unknown; version: number }>;\n\tlastEventId: number;\n};\n\n/**\n * A simple state container for a single keyed value.\n */\nexport interface Store<T> {\n\tget(): T;\n\tset(next: T | ((prev: T) => T)): void;\n\tapply(intent: unknown): void;\n\tsubscribe(listener: (state: T) => void): () => void;\n\tequals(val1: unknown, val2: unknown): boolean;\n}\n\n/**\n * A Universe manages many stores.\n */\nexport interface Universe {\n\tgetStore<T>(\n\t\tkey: string,\n\t\tinit: () => T,\n\t\treducer?: (prev: T, intent: unknown) => T,\n\t\tequals?: (v1: unknown, v2: unknown) => boolean,\n\t): Store<T>;\n\tsnapshot(): Record<string, unknown>;\n\trestore(data: Record<string, unknown>): void;\n\tdelete(key: string): void;\n\tclear(): void;\n\thydrateSnapshot(snapshot: ZunoSnapshot): void;\n}\n\n// --- Middleware Types ---\n\nexport type Dispatch = (event: ZunoStateEvent) => Promise<TransportStatus>;\n\nexport type MiddlewareAPI = {\n\tuniverse: Universe;\n\tclientId: string;\n\tversions: Map<string, number>;\n};\n\nexport type Middleware = (api: MiddlewareAPI) => (next: Dispatch) => Dispatch;\n\n/**\n * Options for creating a Zuno instance.\n */\nexport type CreateZunoOptions = {\n\t/** Optional pre-existing universe. */\n\tuniverse?: Universe;\n\t/** BroadcastChannel name for local tab sync. */\n\tchannelName?: string;\n\t/** SSE endpoint URL. */\n\tsseUrl?: string;\n\t/** Sync endpoint URL (required if sseUrl is provided). */\n\tsyncUrl?: string;\n\t/** Apply updates locally before server confirmation (default: true). */\n\toptimistic?: boolean;\n\t/** Batch multiple updates in the same microtask (default: false). */\n\tbatchSync?: boolean;\n\t/** Unique client identifier (default: random UUID). */\n\tclientId?: string;\n\t/** Middleware chain. */\n\tmiddleware?: Middleware[];\n\t/** Optional function to resolve 409 conflicts. */\n\tresolveConflict?: ConflictResolver;\n};\n\n/**\n * An extended interface for a Zuno store that includes methods for setting state\n * and a unique key identifier. This represents a store that has been \"bound\" or registered.\n */\nexport type BoundStore<T> = {\n\tkey: string;\n\tget: () => T;\n\tset: (next: T | ((prev: T) => T)) => Promise<unknown>;\n\tsubscribe: (cb: (state: T) => void) => () => void;\n\tequals: (v1: unknown, v2: unknown) => boolean;\n\traw: () => Store<T>;\n};\n\n// --- Store Implementation ---\n\n/**\n * Creates a raw ZUNO state management store.\n */\nexport const createStore = <T>(\n\tinitial: T,\n\treducer?: (prev: T, intent: unknown) => T,\n\tequals: (v1: unknown, v2: unknown) => boolean = Object.is,\n): Store<T> => {\n\tlet state = initial;\n\tconst listeners = new Set<(state: T) => void>();\n\n\tconst notify = () => {\n\t\tlisteners.forEach((l) => {\n\t\t\tl(state);\n\t\t});\n\t};\n\n\treturn {\n\t\tget: () => state,\n\t\tequals,\n\t\tset: (next) => {\n\t\t\tconst value =\n\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(state) : next;\n\t\t\tif (equals(value, state)) return;\n\t\t\tstate = value;\n\t\t\tnotify();\n\t\t},\n\t\tapply: (intent) => {\n\t\t\tconst i = intent as { type: string; payload?: unknown };\n\t\t\tif (i.type === \"SET\") {\n\t\t\t\tconst value = i.payload as T;\n\t\t\t\tif (equals(value, state)) return;\n\t\t\t\tstate = value;\n\t\t\t\tnotify();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!reducer) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[Zuno] apply() called for intent \"${i.type}\" on a store without a reducer. Intent ignored.`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextState = reducer(state, i);\n\t\t\tif (equals(nextState, state)) return;\n\t\t\tstate = nextState;\n\t\t\tnotify();\n\t\t},\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => listeners.delete(listener);\n\t\t},\n\t};\n};\n\n// --- Universe Implementation ---\n\n/**\n * Creates a ZUNO Universe to manage multiple stores.\n */\nexport const createUniverse = (): Universe => {\n\t// biome-ignore lint/suspicious/noExplicitAny: internal registry of heterogeneous stores\n\tconst stores = new Map<string, Store<any>>();\n\tlet cachedSnapshot: Record<string, unknown> | null = null;\n\tconst trackStore = <T>(store: Store<T>) => {\n\t\tstore.subscribe(() => {\n\t\t\tcachedSnapshot = null;\n\t\t});\n\t\treturn store;\n\t};\n\n\tconst universe: Universe = {\n\t\tgetStore<T>(\n\t\t\tkey: string,\n\t\t\tinit: () => T,\n\t\t\treducer?: (prev: T, intent: unknown) => T,\n\t\t\tequals?: (v1: unknown, v2: unknown) => boolean,\n\t\t): Store<T> {\n\t\t\tlet s = stores.get(key);\n\t\t\tif (!s) {\n\t\t\t\ts = trackStore(createStore(init(), reducer, equals));\n\t\t\t\tstores.set(key, s);\n\t\t\t\tcachedSnapshot = null;\n\t\t\t}\n\t\t\treturn s as Store<T>;\n\t\t},\n\t\tsnapshot(): Record<string, unknown> {\n\t\t\tif (cachedSnapshot) return cachedSnapshot;\n\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, store] of stores.entries()) {\n\t\t\t\tout[key] = store.get();\n\t\t\t}\n\t\t\tcachedSnapshot = out;\n\t\t\treturn out;\n\t\t},\n\t\trestore(data: Record<string, unknown>): void {\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tconst existing = stores.get(key);\n\t\t\t\tif (existing) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: external data needs to be cast to store type\n\t\t\t\t\texisting.set(value as any);\n\t\t\t\t} else {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: external data needs to be cast to store type\n\t\t\t\t\tstores.set(key, trackStore(createStore(value as any)));\n\t\t\t\t\tcachedSnapshot = null;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdelete(key: string): void {\n\t\t\tstores.delete(key);\n\t\t\tcachedSnapshot = null;\n\t\t},\n\t\tclear(): void {\n\t\t\tstores.clear();\n\t\t\tcachedSnapshot = null;\n\t\t},\n\t\thydrateSnapshot(snapshot: ZunoSnapshot) {\n\t\t\tconst plain: Record<string, unknown> = {};\n\t\t\tfor (const [k, rec] of Object.entries(snapshot.state)) {\n\t\t\t\tplain[k] = rec.state;\n\t\t\t}\n\t\t\tthis.restore(plain);\n\t\t},\n\t};\n\n\treturn universe;\n};\n\n// --- Main Zuno Factory ---\n\n/**\n * Creates a Zuno instance for distributed state synchronization.\n */\nexport const createZuno = (opts: CreateZunoOptions = {}) => {\n\tconst localState = new Map<string, unknown>();\n\tconst versions = new Map<string, number>();\n\tconst universe = opts.universe ?? createUniverse();\n\tconst clientId =\n\t\topts.clientId ?? globalThis.crypto?.randomUUID?.() ?? String(Math.random());\n\tlet _sseReady = false;\n\tlet lastEventId = 0;\n\n\tfunction hydrateSnapshot(snapshot: ZunoSnapshot) {\n\t\tconst plain: Record<string, unknown> = {};\n\t\tfor (const [k, rec] of Object.entries(snapshot.state)) {\n\t\t\tplain[k] = rec.state;\n\t\t\tversions.set(k, rec.version);\n\t\t}\n\t\tuniverse.restore(plain);\n\t\tlastEventId = snapshot.lastEventId;\n\t}\n\n\tconst apply = (event: ZunoStateEvent) => {\n\t\tif (typeof event.eventId === \"number\") {\n\t\t\tlastEventId = Math.max(lastEventId, event.eventId);\n\t\t}\n\t\tapplyIncomingEvent(universe, event, { clientId, localState, versions });\n\t};\n\n\tconst sse =\n\t\topts.sseUrl && opts.syncUrl\n\t\t\t? startSSE({\n\t\t\t\t\tuniverse,\n\t\t\t\t\turl: opts.sseUrl,\n\t\t\t\t\tsyncUrl: opts.syncUrl,\n\t\t\t\t\toptimistic: opts.optimistic ?? true,\n\t\t\t\t\tclientId,\n\t\t\t\t\tversions,\n\t\t\t\t\tgetLastEventId: () => lastEventId,\n\t\t\t\t\tonOpen: () => {\n\t\t\t\t\t\t_sseReady = true;\n\t\t\t\t\t},\n\t\t\t\t\tonClose: () => {\n\t\t\t\t\t\t_sseReady = false;\n\t\t\t\t\t},\n\t\t\t\t\tonEvent: (e) => dispatch(e), // Route incoming SSE events through middleware\n\t\t\t\t\tresolveConflict: opts.resolveConflict,\n\t\t\t\t})\n\t\t\t: null;\n\n\tconst bc = opts.channelName\n\t\t? startBroadcastChannel({\n\t\t\t\tchannelName: opts.channelName,\n\t\t\t\tclientId,\n\t\t\t\tonEvent: (e) => dispatch(e), // Route incoming BC events through middleware\n\t\t\t\tgetSnapshot: () => {\n\t\t\t\t\tconst snap = universe.snapshot();\n\t\t\t\t\tconst out: Record<string, { state: unknown; version: number }> = {};\n\t\t\t\t\tfor (const [storeKey, state] of Object.entries(snap)) {\n\t\t\t\t\t\tout[storeKey] = { state, version: versions.get(storeKey) ?? 0 };\n\t\t\t\t\t}\n\t\t\t\t\treturn out;\n\t\t\t\t},\n\t\t\t\tonSnapshot: (snap) => {\n\t\t\t\t\tfor (const [storeKey, rec] of Object.entries(snap)) {\n\t\t\t\t\t\tapply({ storeKey, state: rec.state, version: rec.version });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t: null;\n\n\tsetTimeout(() => bc?.hello(), 100);\n\n\t// --- Sync Batching ---\n\tconst pendingSyncs = new Map<string, ZunoStateEvent>();\n\tlet batchPromise: Promise<void> | null = null;\n\n\tconst flushBatch = async () => {\n\t\tconst syncs = Array.from(pendingSyncs.values());\n\t\tpendingSyncs.clear();\n\t\tbatchPromise = null;\n\n\t\tfor (const event of syncs) {\n\t\t\tif (sse) {\n\t\t\t\tsse.dispatch(event).catch((err) => {\n\t\t\t\t\tconsole.error(\"[Zuno] Batch sync failed\", err);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\tconst coreDispatch = async (\n\t\tevent: ZunoStateEvent,\n\t): Promise<TransportStatus> => {\n\t\t// 1. Incoming/Reflected Event Logic (events WITH origin)\n\t\tif (event.origin) {\n\t\t\t// Always call apply to let applyIncomingEvent handle version checks and application\n\t\t\tapply(event);\n\n\t\t\t// If it's from another client, we are done\n\t\t\tif (event.origin !== clientId) {\n\t\t\t\treturn { ok: true, status: 200, json: null };\n\t\t\t}\n\t\t\t// If it's a reflected local event, we still need to broadcast it (fall through)\n\t\t}\n\n\t\t// 2. Outgoing Event Logic (events WITHOUT origin)\n\t\tif (!event.origin) {\n\t\t\tevent.origin = clientId;\n\n\t\t\t// Resolve state if needed (e.g. from mutate)\n\t\t\tconst store = universe.getStore(event.storeKey, () => undefined);\n\n\t\t\tif (event.state === undefined && event.intent) {\n\t\t\t\t// We need the state to send to server.\n\t\t\t\t// If optimistic, we apply it. If not, we only compute if it's a simple SET.\n\t\t\t\tif (opts.optimistic !== false) {\n\t\t\t\t\tstore.apply(event.intent);\n\t\t\t\t\tevent.state = store.get();\n\t\t\t\t} else {\n\t\t\t\t\tconst i = event.intent as { type: string; payload?: unknown };\n\t\t\t\t\tif (i.type === \"SET\") {\n\t\t\t\t\t\tevent.state = i.payload;\n\t\t\t\t\t}\n\t\t\t\t\t// For other intents with optimistic: false, we might send undefined state\n\t\t\t\t\t// and rely on the server to compute it authoritativeley.\n\t\t\t\t}\n\t\t\t} else if (event.state !== undefined) {\n\t\t\t\tif (opts.optimistic !== false) {\n\t\t\t\t\tstore.set(event.state as never);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Always send the authoritative version this mutation was based on.\n\t\t\tconst current = versions.get(event.storeKey) ?? 0;\n\t\t\tevent.baseVersion ??= current;\n\n\t\t\t// Local bookkeeping and optimistic versioning\n\t\t\tif (opts.optimistic !== false) {\n\t\t\t\tconst nextVersion = current + 1;\n\t\t\t\tversions.set(event.storeKey, nextVersion);\n\t\t\t\tevent.version = nextVersion;\n\t\t\t}\n\n\t\t\t// BROADCAST IMMEDIATELY to local tabs via BC\n\t\t\t// This ensures instant sync across tabs even if SSE is slow or down.\n\t\t\tif (bc) {\n\t\t\t\tbc.publish(event);\n\t\t\t}\n\t\t}\n\n\t\t// 3. Remote Sync (SSE/HTTP) with Optional Batching\n\t\tif (sse) {\n\t\t\tif (opts.batchSync) {\n\t\t\t\t// Coalesce outgoing syncs for the same storeKey within the same microtask\n\t\t\t\tconst pending = pendingSyncs.get(event.storeKey);\n\t\t\t\tpendingSyncs.set(event.storeKey, {\n\t\t\t\t\t...event,\n\t\t\t\t\tbaseVersion: pending?.baseVersion ?? event.baseVersion,\n\t\t\t\t});\n\n\t\t\t\tif (!batchPromise) {\n\t\t\t\t\tbatchPromise = Promise.resolve().then(flushBatch);\n\t\t\t\t}\n\n\t\t\t\t// Note: Batched dispatch currently returns a \"fake\" OK immediately\n\t\t\t\t// to avoid blocking the UI. Error handling is handled via console.error in flushBatch.\n\t\t\t\t// Real conflict resolution still happens via SSE's internal queue/retry.\n\t\t\t\treturn { ok: true, status: 202, json: { batched: true } };\n\t\t\t}\n\n\t\t\treturn await sse.dispatch(event);\n\t\t}\n\n\t\treturn { ok: true, status: 200, json: null };\n\t};\n\n\t// --- Middleware Composition ---\n\tlet dispatch: Dispatch = coreDispatch;\n\n\tif (opts.middleware && opts.middleware.length > 0) {\n\t\tconst middlewareAPI: MiddlewareAPI = {\n\t\t\tuniverse,\n\t\t\tclientId,\n\t\t\tversions,\n\t\t};\n\t\tconst chain = opts.middleware.map((middleware) =>\n\t\t\tmiddleware(middlewareAPI),\n\t\t);\n\t\tdispatch = chain.reduceRight(\n\t\t\t(next, middleware) => middleware(next),\n\t\t\tcoreDispatch,\n\t\t);\n\t}\n\n\tconst store = <T>(\n\t\tstoreKey: string,\n\t\tinit: () => T,\n\t\treducer?: (prev: T, intent: unknown) => T,\n\t\tequals?: (v1: unknown, v2: unknown) => boolean,\n\t): BoundStore<T> => {\n\t\tconst rawStore = universe.getStore<T>(storeKey, init, reducer, equals);\n\t\treturn {\n\t\t\tkey: storeKey,\n\t\t\traw: () => rawStore,\n\t\t\tget: () => rawStore.get(),\n\t\t\tsubscribe: (cb) => rawStore.subscribe(cb),\n\t\t\tequals: (v1, v2) => rawStore.equals(v1, v2),\n\t\t\tset: (next) => {\n\t\t\t\tconst prev = rawStore.get();\n\t\t\t\tconst state =\n\t\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(prev) : next;\n\t\t\t\treturn dispatch({\n\t\t\t\t\tstoreKey,\n\t\t\t\t\tstate,\n\t\t\t\t\tintent: { type: \"SET\", payload: state },\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t};\n\n\treturn {\n\t\tuniverse,\n\t\tclientId,\n\t\tstore,\n\t\tgetStore: universe.getStore.bind(universe),\n\t\tget: <T>(key: string, init?: () => T) =>\n\t\t\tuniverse\n\t\t\t\t.getStore<T>(\n\t\t\t\t\tkey,\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: default init for convenience\n\t\t\t\t\tinit ?? (() => undefined as any),\n\t\t\t\t)\n\t\t\t\t.get(),\n\t\tset: async <T>(key: string, next: T | ((prev: T) => T), init?: () => T) => {\n\t\t\tconst s = universe.getStore<T>(\n\t\t\t\tkey,\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: default init for convenience\n\t\t\t\tinit ?? (() => undefined as any),\n\t\t\t);\n\t\t\tconst state =\n\t\t\t\ttypeof next === \"function\" ? (next as (prev: T) => T)(s.get()) : next;\n\n\t\t\t// Don't set origin or version here, let coreDispatch handle it\n\t\t\treturn dispatch({\n\t\t\t\tstoreKey: key,\n\t\t\t\tstate,\n\t\t\t\tintent: { type: \"SET\", payload: state },\n\t\t\t});\n\t\t},\n\t\tmutate: async (\n\t\t\tkey: string,\n\t\t\tintent: { type: string; payload?: unknown },\n\t\t) => {\n\t\t\treturn dispatch({\n\t\t\t\tstoreKey: key,\n\t\t\t\t// coreDispatch will calculate state from intent\n\t\t\t\tstate: undefined as unknown,\n\t\t\t\tintent,\n\t\t\t});\n\t\t},\n\t\tsubscribe: <T>(key: string, init: () => T, cb: (state: T) => void) =>\n\t\t\tuniverse.getStore<T>(key, init).subscribe(cb),\n\t\tdispatch,\n\t\tstop: () => {\n\t\t\tsse?.unsubscribe?.();\n\t\t\tbc?.stop?.();\n\t\t},\n\t\thydrateSnapshot,\n\t\tgetLastEventId: () => lastEventId,\n\t\tsetLastEventId: (id: number) => {\n\t\t\tlastEventId = id;\n\t\t},\n\t};\n};\n","/** Universal UI adapter contract */\nexport type ZunoReadable<T> = {\n\t/** Read current value (sync) */\n\tgetSnapshot(): T;\n\n\t/**\n\t * Subscribe to changes.\n\t * Call `onChange()` whenever snapshot may have changed.\n\t * Return unsubscribe.\n\t */\n\tsubscribe(onChange: () => void): () => void;\n\n\t/** Optional: React SSR (server snapshot) */\n\tgetServerSnapshot?: () => T;\n};\n\n/** Minimal store shape that can be adapted into a readable */\nexport type ZunoSubscribableStore<T> = {\n\tget(): T;\n\tsubscribe(cb: (state: T) => void): () => void;\n\tequals(v1: unknown, v2: unknown): boolean;\n};\n\n/** Adapter helper: convert store => readable */\nexport function toReadable<T>(\n\tstore: ZunoSubscribableStore<T>,\n): ZunoReadable<T> {\n\treturn {\n\t\tgetSnapshot: () => store.get(),\n\t\tsubscribe: (onChange) => store.subscribe(() => onChange()),\n\t};\n}\n","/**\n * Performs a shallow equality check between two values.\n */\nexport function shallowEqual(a: unknown, b: unknown): boolean {\n\tif (Object.is(a, b)) return true;\n\n\tif (\n\t\ttypeof a !== \"object\" ||\n\t\ta === null ||\n\t\ttypeof b !== \"object\" ||\n\t\tb === null\n\t) {\n\t\treturn false;\n\t}\n\n\tconst keysA = Object.keys(a as object);\n\tconst keysB = Object.keys(b as object);\n\n\tif (keysA.length !== keysB.length) return false;\n\n\tconst objA = a as Record<string, unknown>;\n\tconst objB = b as Record<string, unknown>;\n\n\tfor (const key of keysA) {\n\t\tif (!Object.hasOwn(objB, key) || !Object.is(objA[key], objB[key])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
@@ -1,13 +1,13 @@
1
- 'use strict';var p=new Map,S=t=>p.get(t),d=t=>{let e=p.get(t.storeKey)??{version:0},r=typeof t.version=="number"?t.version:e.version+1;p.set(t.storeKey,{state:t.state,version:r});},c=()=>Object.fromEntries(p),O=1e3,b=1,i=[],l=t=>(t.eventId=b++,i.push(t),i.length>O&&i.shift(),t),g=t=>i.filter(e=>(e?.eventId??0)>t),y=()=>i[i.length-1]?.eventId??0,u=new Set,E=t=>(u.add(t),()=>{u.delete(t);}),m=t=>{u.forEach(e=>{e(t);});};function I(t){let e=S(t.storeKey)??{state:void 0,version:0};if(typeof t.baseVersion=="number"&&t.baseVersion!==e.version)return {ok:false,reason:"VERSION_CONFLICT",current:e};let r=e.version+1,n={...t,version:r};return d(n),l(n),m(n),{ok:true,event:n}}function k(t,e){let r={state:c(),lastEventId:y()};"json"in e&&typeof e.json=="function"?e.json(r):(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(r)));}var _=(t,e,r)=>{e.writeHead(200,{"Cache-Control":"no-cache, no-transform","Content-Type":"text/event-stream; charset=utf-8",Connection:"keep-alive","X-Accel-Buffering":"no",...r}),e.flushHeaders?.();let n=t.headers["last-event-id"]||new URL(t.url||"","http://localhost").searchParams.get("lastEventId"),a=Number.parseInt(Array.isArray(n)?n[0]:n??"0",10)||0,s=[],f=true,v=o=>{e.write(`id: ${o.eventId}
1
+ 'use strict';var p=class{constructor(e={}){this.universeState=new Map;this.eventLog=[];this.listeners=new Set;this.nextEventId=1;let n=e.maxEvents??1e3,r=e.maxStateBytes??512*1024;if(!Number.isInteger(n)||n<1)throw new TypeError("maxEvents must be a positive integer");if(!Number.isInteger(r)||r<1)throw new TypeError("maxStateBytes must be a positive integer");this.maxEvents=n,this.maxStateBytes=r;}getUniverseRecord(e){return this.universeState.get(e)}updateUniverseState(e){let n=this.universeState.get(e.storeKey)??{version:0},r=typeof e.version=="number"?e.version:n.version+1;this.universeState.set(e.storeKey,{state:e.state,version:r});}getUniverseState(){return Object.fromEntries(this.universeState)}appendEvent(e){return e.eventId=this.nextEventId++,this.eventLog.push(e),this.eventLog.length>this.maxEvents&&this.eventLog.shift(),e}getEventsAfter(e){return this.eventLog.filter(n=>(n.eventId??0)>e)}getLastEventId(){return this.eventLog[this.eventLog.length-1]?.eventId??0}subscribeToStateEvents(e){return this.listeners.add(e),()=>{this.listeners.delete(e);}}publishToStateEvent(e){this.listeners.forEach(n=>{n(e);});}clear(){this.universeState.clear(),this.eventLog.length=0,this.nextEventId=1;}},S=(t={})=>new p(t),d=class{constructor(e={}){this.serverOptions=e;this.servers=new Map;}get(e){if(e.trim().length===0)throw new TypeError("namespace must be a non-empty string");let n=this.servers.get(e);return n||(n=S(this.serverOptions),this.servers.set(e,n)),n}delete(e){return this.servers.delete(e)}clear(){this.servers.clear();}},b=(t={})=>new d(t),o=S(),x=t=>o.getUniverseRecord(t),I=t=>o.updateUniverseState(t),Z=()=>o.getUniverseState(),w=t=>o.appendEvent(t),O=t=>o.getEventsAfter(t),N=()=>o.getLastEventId(),T=t=>o.subscribeToStateEvents(t),L=t=>o.publishToStateEvent(t);var f=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function E(t,e=512*1024){if(!f(t))return [{field:"event",message:"Event must be an object"}];let n=[];if((typeof t.storeKey!="string"||t.storeKey.trim().length===0||t.storeKey.length>256)&&n.push({field:"storeKey",message:"storeKey must be a non-empty string of at most 256 characters"}),!("state"in t))n.push({field:"state",message:"state is required"});else try{let r=JSON.stringify(t.state);r===void 0?n.push({field:"state",message:"state must be JSON-serializable"}):new TextEncoder().encode(r).byteLength>e&&n.push({field:"state",message:`state exceeds the ${e} byte limit`});}catch{n.push({field:"state",message:"state must be JSON-serializable"});}for(let r of ["version","baseVersion","eventId"]){let s=t[r];s!==void 0&&(!Number.isInteger(s)||s<0)&&n.push({field:r,message:`${r} must be a non-negative integer when provided`});}for(let r of ["origin"]){let s=t[r];s!==void 0&&typeof s!="string"&&n.push({field:r,message:`${r} must be a string when provided`});}return t.ts!==void 0&&!Number.isFinite(t.ts)&&n.push({field:"ts",message:"ts must be a finite number when provided"}),t.intent!==void 0&&(!f(t.intent)||typeof t.intent.type!="string"||t.intent.type.trim().length===0)&&n.push({field:"intent",message:"intent must contain a non-empty string type"}),n}function l(t,e=o){let n=E(t,e.maxStateBytes);if(n.length>0)return {ok:false,reason:"INVALID_EVENT",errors:n};let r=t,s=e.getUniverseRecord(r.storeKey)??{state:void 0,version:0};if(typeof r.baseVersion=="number"&&r.baseVersion!==s.version)return {ok:false,reason:"VERSION_CONFLICT",current:s};let a={...r,version:s.version+1};return e.updateUniverseState(a),e.appendEvent(a),e.publishToStateEvent(a),{ok:true,event:a}}function A(t,e,n=o){let r={state:n.getUniverseState(),lastEventId:n.getLastEventId()};"json"in e&&typeof e.json=="function"?e.json(r):(e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(r)));}var j=(t,e,n,r=o)=>{e.writeHead(200,{"Cache-Control":"no-cache, no-transform","Content-Type":"text/event-stream; charset=utf-8",Connection:"keep-alive","X-Accel-Buffering":"no",...n}),e.flushHeaders?.();let s=t.headers["last-event-id"]||new URL(t.url||"","http://localhost").searchParams.get("lastEventId"),a=Number.parseInt(Array.isArray(s)?s[0]:s??"0",10)||0,i=[],c=true,u=v=>{e.write(`id: ${v.eventId}
2
2
  `),e.write(`event: state
3
- `),e.write(`data: ${JSON.stringify(o)}
3
+ `),e.write(`data: ${JSON.stringify(v)}
4
4
 
5
- `);},h=E(o=>{f?s.push(o):v(o);});if(a>0){let o=g(a);for(let w of o)v(w);}else e.write(`event: snapshot
6
- `),e.write(`data: ${JSON.stringify(c())}
5
+ `);},g=r.subscribeToStateEvents(v=>{c?i.push(v):u(v);});if(a>0){let v=r.getEventsAfter(a);for(let y of v)u(y);}else e.write(`event: snapshot
6
+ `),e.write(`data: ${JSON.stringify(r.getUniverseState())}
7
7
 
8
- `);for(f=false;s.length>0;){let o=s.shift();o&&v(o);}let x=setInterval(()=>{e.write(`: ping ${Date.now()}
8
+ `);for(c=false;i.length>0;){let v=i.shift();v&&u(v);}let m=setInterval(()=>{e.write(`: ping ${Date.now()}
9
9
 
10
10
  `);},15e3);e.write(`: connected
11
11
 
12
- `),t.on("close",()=>{clearInterval(x),h(),e.end();});},N=(t,e)=>{let n="";t.on("data",a=>{n+=a.toString("utf8"),n.length>524288&&(e.writeHead(413,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"PAYLOAD_TOO_LARGE"})),t.destroy());}),t.on("end",()=>{try{let a=JSON.parse(n||"{}"),s=I(a);if(!s.ok){s.reason==="VERSION_CONFLICT"&&(e.writeHead(409,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!1,reason:"VERSION_CONFLICT",current:s.current})));return}e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!0,event:s.event}));}catch{e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"INVALID_JSON"}));}});},M=(t,e)=>N(t,e);exports.appendEvent=l;exports.applyStateEvent=I;exports.createSSEConnection=_;exports.getEventsAfter=g;exports.getLastEventId=y;exports.getUniverseRecord=S;exports.getUniverseState=c;exports.publishToStateEvent=m;exports.sendSnapshot=k;exports.setUniverseState=M;exports.subscribeToStateEvents=E;exports.syncUniverseState=N;exports.updateUniverseState=d;//# sourceMappingURL=index.cjs.map
12
+ `),t.on("close",()=>{clearInterval(m),g(),e.end();});},h=(t,e,n=o)=>{let s="";t.on("data",a=>{s+=a.toString("utf8"),s.length>524288&&(e.writeHead(413,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"PAYLOAD_TOO_LARGE"})),t.destroy());}),t.on("end",()=>{try{let a=JSON.parse(s||"{}"),i=l(a,n);if(!i.ok){i.reason==="VERSION_CONFLICT"?(e.writeHead(409,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!1,reason:"VERSION_CONFLICT",current:i.current}))):(e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!1,reason:i.reason,errors:i.errors})));return}e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:!0,event:i.event}));}catch{e.writeHead(400,{"Content-Type":"application/json"}),e.end(JSON.stringify({ok:false,reason:"INVALID_JSON"}));}});},B=(t,e,n=o)=>h(t,e,n);exports.ZunoServerRegistry=d;exports.ZunoServerState=p;exports.appendEvent=w;exports.applyStateEvent=l;exports.createSSEConnection=j;exports.createZunoServerRegistry=b;exports.createZunoServerState=S;exports.defaultZunoServerState=o;exports.getEventsAfter=O;exports.getLastEventId=N;exports.getUniverseRecord=x;exports.getUniverseState=Z;exports.publishToStateEvent=L;exports.sendSnapshot=A;exports.setUniverseState=B;exports.subscribeToStateEvents=T;exports.syncUniverseState=h;exports.updateUniverseState=I;exports.validateStateEvent=E;//# sourceMappingURL=index.cjs.map
13
13
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/core.ts","../../src/server/apply-state-event.ts","../../src/server/snapshot-handler.ts","../../src/server/sse-handler.ts"],"names":["universeState","getUniverseRecord","storeKey","updateUniverseState","event","current","nextVersion","getUniverseState","MAX_EVENTS","nextEventId","eventLog","appendEvent","getEventsAfter","lastEventId","getLastEventId","listeners","subscribeToStateEvents","listener","publishToStateEvent","applyStateEvent","incoming","sendSnapshot","_req","res","snapshot","createSSEConnection","req","headers","raw","buffer","isSyncing","writeEvent","unsubscribe","missed","heartbeat","syncUniverseState","body","chunk","result","setUniverseState"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ZunoStateEvent } from \"../sync\";\n\n// --- Types ---\n\nexport type UniverseRecord = {\n\tstate: unknown; // Was 'any'\n\tversion: number;\n};\n\nexport type ZunoStateListener = (event: ZunoStateEvent) => void;\n\n// --- State Store ---\n\nconst universeState = new Map<string, UniverseRecord>();\n\nexport const getUniverseRecord = (\n\tstoreKey: string,\n): UniverseRecord | undefined => {\n\treturn universeState.get(storeKey);\n};\n\nexport const updateUniverseState = (event: ZunoStateEvent) => {\n\tconst current = universeState.get(event.storeKey) ?? {\n\t\tstate: undefined,\n\t\tversion: 0,\n\t};\n\tconst nextVersion =\n\t\ttypeof event.version === \"number\" ? event.version : current.version + 1;\n\tuniverseState.set(event.storeKey, {\n\t\tstate: event.state,\n\t\tversion: nextVersion,\n\t});\n};\n\nexport const getUniverseState = () => {\n\treturn Object.fromEntries(universeState);\n};\n\n// --- Event Log ---\n\nconst MAX_EVENTS = 1000;\nlet nextEventId = 1;\nconst eventLog: ZunoStateEvent[] = [];\n\nexport const appendEvent = (event: ZunoStateEvent) => {\n\tevent.eventId = nextEventId++;\n\teventLog.push(event);\n\tif (eventLog.length > MAX_EVENTS) {\n\t\teventLog.shift();\n\t}\n\treturn event;\n};\n\nexport const getEventsAfter = (lastEventId: number) => {\n\treturn eventLog.filter((event) => (event?.eventId ?? 0) > lastEventId);\n};\n\nexport const getLastEventId = () => {\n\treturn eventLog[eventLog.length - 1]?.eventId ?? 0;\n};\n\n// --- State Bus (Events) ---\n\nconst listeners = new Set<ZunoStateListener>();\n\nexport const subscribeToStateEvents = (listener: ZunoStateListener) => {\n\tlisteners.add(listener);\n\treturn () => {\n\t\tlisteners.delete(listener);\n\t};\n};\n\nexport const publishToStateEvent = (event: ZunoStateEvent) => {\n\tlisteners.forEach((listener) => {\n\t\tlistener(event);\n\t});\n};\n","import type { ZunoStateEvent } from \"../sync\";\nimport {\n\tappendEvent,\n\tgetUniverseRecord,\n\tpublishToStateEvent,\n\tupdateUniverseState,\n} from \"./core\";\n\nexport type ApplyResult =\n\t| { ok: true; event: ZunoStateEvent }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"VERSION_CONFLICT\";\n\t\t\tcurrent: { state: unknown; version: number };\n\t }\n\t| { ok: false; reason: string; current?: never };\n\n/**\n * Validates and applies a state event to the server universe.\n */\nexport function applyStateEvent(incoming: ZunoStateEvent): ApplyResult {\n\tconst current = getUniverseRecord(incoming.storeKey) ?? {\n\t\tstate: undefined,\n\t\tversion: 0,\n\t};\n\n\t// Strict version check\n\tif (\n\t\ttypeof incoming.baseVersion === \"number\" &&\n\t\tincoming.baseVersion !== current.version\n\t) {\n\t\treturn { ok: false, reason: \"VERSION_CONFLICT\", current };\n\t}\n\n\t// Increment version\n\tconst nextVersion = current.version + 1;\n\tconst event = { ...incoming, version: nextVersion };\n\n\t// Persistence\n\tupdateUniverseState(event);\n\tappendEvent(event);\n\n\t// Notify SSE subscribers\n\tpublishToStateEvent(event);\n\n\treturn { ok: true, event };\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { getLastEventId, getUniverseState } from \"./core\";\n\n/**\n * Sends a snapshot of the current universe state to the response.\n * Compatible with both Express and raw Node.js http.\n */\nexport function sendSnapshot(_req: IncomingMessage, res: ServerResponse) {\n\tconst snapshot = {\n\t\tstate: getUniverseState(),\n\t\tlastEventId: getLastEventId(),\n\t};\n\n\t// Check for Express-like .json() method\n\t// biome-ignore lint/suspicious/noExplicitAny: Checking for dynamic .json() method on response object\n\tif (\"json\" in res && typeof (res as any).json === \"function\") {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Calling dynamic .json() method\n\t\t(res as any).json(snapshot);\n\t} else {\n\t\tres.writeHead(200, { \"Content-Type\": \"application/json\" });\n\t\tres.end(JSON.stringify(snapshot));\n\t}\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ZunoStateEvent } from \"../sync\";\nimport { applyStateEvent } from \"./apply-state-event\";\nimport {\n\tgetEventsAfter,\n\tgetUniverseState,\n\tsubscribeToStateEvents,\n} from \"./core\";\n\ntype IncomingHeaders = IncomingMessage[\"headers\"];\n\n/**\n * Creates a Server-Sent Events (SSE) connection for Zuno state updates.\n */\nexport const createSSEConnection = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\theaders: IncomingHeaders,\n) => {\n\tres.writeHead(200, {\n\t\t\"Cache-Control\": \"no-cache, no-transform\",\n\t\t\"Content-Type\": \"text/event-stream; charset=utf-8\",\n\t\tConnection: \"keep-alive\",\n\t\t\"X-Accel-Buffering\": \"no\",\n\t\t...headers,\n\t});\n\n\tres.flushHeaders?.();\n\n\tconst raw =\n\t\treq.headers[\"last-event-id\"] ||\n\t\tnew URL(req.url || \"\", \"http://localhost\").searchParams.get(\"lastEventId\");\n\tconst lastEventId =\n\t\tNumber.parseInt(Array.isArray(raw) ? raw[0] : (raw ?? \"0\"), 10) || 0;\n\n\t// 1. Subscribe FIRST and buffer events until snapshot/missed-events are sent\n\tconst buffer: ZunoStateEvent[] = [];\n\tlet isSyncing = true;\n\n\tconst writeEvent = (event: ZunoStateEvent) => {\n\t\tres.write(`id: ${event.eventId}\\n`);\n\t\tres.write(`event: state\\n`);\n\t\tres.write(`data: ${JSON.stringify(event)}\\n\\n`);\n\t};\n\n\tconst unsubscribe = subscribeToStateEvents((event: ZunoStateEvent) => {\n\t\tif (isSyncing) {\n\t\t\tbuffer.push(event);\n\t\t} else {\n\t\t\twriteEvent(event);\n\t\t}\n\t});\n\n\t// 2. Send missed events or snapshot\n\tif (lastEventId > 0) {\n\t\tconst missed = getEventsAfter(lastEventId);\n\t\tfor (const event of missed) {\n\t\t\twriteEvent(event);\n\t\t}\n\t} else {\n\t\tres.write(`event: snapshot\\n`);\n\t\tres.write(`data: ${JSON.stringify(getUniverseState())}\\n\\n`);\n\t}\n\n\t// 3. Flush buffer and switch to live mode\n\tisSyncing = false;\n\twhile (buffer.length > 0) {\n\t\tconst event = buffer.shift();\n\t\tif (event) writeEvent(event);\n\t}\n\n\tconst heartbeat = setInterval(() => {\n\t\tres.write(`: ping ${Date.now()}\\n\\n`);\n\t}, 15000);\n\n\tres.write(\": connected \\n\\n\");\n\n\treq.on(\"close\", () => {\n\t\tclearInterval(heartbeat);\n\t\tunsubscribe();\n\t\tres.end();\n\t});\n};\n\n/**\n * Synchronizes the Zuno universe state by applying an incoming event.\n */\nexport const syncUniverseState = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n) => {\n\tconst MAX_BODY_BYTES = 512 * 1024; // 512KB safety\n\tlet body = \"\";\n\n\treq.on(\"data\", (chunk: Buffer) => {\n\t\tbody += chunk.toString(\"utf8\");\n\t\tif (body.length > MAX_BODY_BYTES) {\n\t\t\tres.writeHead(413, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: false, reason: \"PAYLOAD_TOO_LARGE\" }));\n\t\t\treq.destroy();\n\t\t}\n\t});\n\n\treq.on(\"end\", () => {\n\t\ttry {\n\t\t\tconst incoming: ZunoStateEvent = JSON.parse(\n\t\t\t\tbody || \"{}\",\n\t\t\t) as unknown as ZunoStateEvent;\n\t\t\tconst result = applyStateEvent(incoming);\n\n\t\t\tif (!result.ok) {\n\t\t\t\tif (result.reason === \"VERSION_CONFLICT\") {\n\t\t\t\t\tres.writeHead(409, { \"Content-Type\": \"application/json\" });\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\treason: \"VERSION_CONFLICT\",\n\t\t\t\t\t\t\tcurrent: result.current,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tres.writeHead(200, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: true, event: result.event }));\n\t\t} catch {\n\t\t\tres.writeHead(400, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: false, reason: \"INVALID_JSON\" }));\n\t\t}\n\t});\n};\n\nexport const setUniverseState = (req: IncomingMessage, res: ServerResponse) => {\n\treturn syncUniverseState(req, res);\n};\n"]}
1
+ {"version":3,"sources":["../../src/server/core.ts","../../src/server/apply-state-event.ts","../../src/server/snapshot-handler.ts","../../src/server/sse-handler.ts"],"names":["ZunoServerState","options","maxEvents","maxStateBytes","storeKey","event","current","nextVersion","lastEventId","listener","createZunoServerState","ZunoServerRegistry","serverOptions","namespace","server","createZunoServerRegistry","defaultZunoServerState","getUniverseRecord","updateUniverseState","getUniverseState","appendEvent","getEventsAfter","getLastEventId","subscribeToStateEvents","publishToStateEvent","isRecord","value","validateStateEvent","input","errors","serialized","field","applyStateEvent","incoming","authoritativeEvent","sendSnapshot","_req","res","snapshot","createSSEConnection","req","headers","raw","buffer","isSyncing","writeEvent","unsubscribe","missed","heartbeat","syncUniverseState","body","chunk","result","setUniverseState"],"mappings":"aAoBO,IAAMA,CAAAA,CAAN,KAAsB,CAQ5B,WAAA,CAAYC,EAAwC,EAAC,CAAG,CALxD,IAAA,CAAiB,aAAA,CAAgB,IAAI,GAAA,CACrC,IAAA,CAAiB,SAA6B,EAAC,CAC/C,KAAiB,SAAA,CAAY,IAAI,GAAA,CACjC,IAAA,CAAQ,WAAA,CAAc,CAAA,CAGrB,IAAMC,CAAAA,CAAYD,CAAAA,CAAQ,WAAa,GAAA,CACjCE,CAAAA,CAAgBF,EAAQ,aAAA,EAAiB,GAAA,CAAM,KACrD,GAAI,CAAC,OAAO,SAAA,CAAUC,CAAS,GAAKA,CAAAA,CAAY,CAAA,CAC/C,MAAM,IAAI,SAAA,CAAU,sCAAsC,CAAA,CAE3D,GAAI,CAAC,OAAO,SAAA,CAAUC,CAAa,GAAKA,CAAAA,CAAgB,CAAA,CACvD,MAAM,IAAI,SAAA,CAAU,0CAA0C,CAAA,CAE/D,IAAA,CAAK,UAAYD,CAAAA,CACjB,IAAA,CAAK,cAAgBC,EACtB,CAEA,kBAAkBC,CAAAA,CAA8C,CAC/D,OAAO,IAAA,CAAK,aAAA,CAAc,GAAA,CAAIA,CAAQ,CACvC,CAEA,oBAAoBC,CAAAA,CAA6B,CAChD,IAAMC,CAAAA,CAAU,IAAA,CAAK,cAAc,GAAA,CAAID,CAAAA,CAAM,QAAQ,CAAA,EAAK,CAEzD,OAAA,CAAS,CACV,CAAA,CACME,CAAAA,CACL,OAAOF,CAAAA,CAAM,OAAA,EAAY,QAAA,CAAWA,EAAM,OAAA,CAAUC,CAAAA,CAAQ,QAAU,CAAA,CACvE,IAAA,CAAK,cAAc,GAAA,CAAID,CAAAA,CAAM,SAAU,CACtC,KAAA,CAAOA,EAAM,KAAA,CACb,OAAA,CAASE,CACV,CAAC,EACF,CAEA,gBAAA,EAAmD,CAClD,OAAO,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,aAAa,CAC7C,CAEA,YAAYF,CAAAA,CAAuC,CAClD,OAAAA,CAAAA,CAAM,OAAA,CAAU,KAAK,WAAA,EAAA,CACrB,IAAA,CAAK,SAAS,IAAA,CAAKA,CAAK,EACpB,IAAA,CAAK,QAAA,CAAS,OAAS,IAAA,CAAK,SAAA,EAC/B,IAAA,CAAK,QAAA,CAAS,KAAA,EAAM,CAEdA,CACR,CAEA,cAAA,CAAeG,EAAuC,CACrD,OAAO,KAAK,QAAA,CAAS,MAAA,CAAQH,IAAWA,CAAAA,CAAM,OAAA,EAAW,GAAKG,CAAW,CAC1E,CAEA,cAAA,EAAyB,CACxB,OAAO,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,CAAS,MAAA,CAAS,CAAC,GAAG,OAAA,EAAW,CAC5D,CAEA,sBAAA,CAAuBC,CAAAA,CAAyC,CAC/D,OAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAIA,CAAQ,CAAA,CACpB,IAAM,CACZ,IAAA,CAAK,SAAA,CAAU,OAAOA,CAAQ,EAC/B,CACD,CAEA,mBAAA,CAAoBJ,CAAAA,CAA6B,CAChD,IAAA,CAAK,SAAA,CAAU,QAASI,CAAAA,EAAa,CACpCA,EAASJ,CAAK,EACf,CAAC,EACF,CAEA,OAAc,CACb,IAAA,CAAK,cAAc,KAAA,EAAM,CACzB,KAAK,QAAA,CAAS,MAAA,CAAS,EACvB,IAAA,CAAK,WAAA,CAAc,EACpB,CACD,CAAA,CAEaK,CAAAA,CAAwB,CACpCT,CAAAA,CAAwC,KACpC,IAAID,CAAAA,CAAgBC,CAAO,CAAA,CAGnBU,CAAAA,CAAN,KAAyB,CAG/B,WAAA,CACkBC,EAA8C,EAAC,CAC/D,CADgB,IAAA,CAAA,aAAA,CAAAA,CAAAA,CAHlB,KAAiB,OAAA,CAAU,IAAI,IAI5B,CAEH,GAAA,CAAIC,CAAAA,CAAoC,CACvC,GAAIA,CAAAA,CAAU,MAAK,CAAE,MAAA,GAAW,EAC/B,MAAM,IAAI,UAAU,sCAAsC,CAAA,CAE3D,IAAIC,CAAAA,CAAS,IAAA,CAAK,QAAQ,GAAA,CAAID,CAAS,EACvC,OAAKC,CAAAA,GACJA,CAAAA,CAASJ,CAAAA,CAAsB,IAAA,CAAK,aAAa,EACjD,IAAA,CAAK,OAAA,CAAQ,IAAIG,CAAAA,CAAWC,CAAM,GAE5BA,CACR,CAEA,MAAA,CAAOD,CAAAA,CAA4B,CAClC,OAAO,KAAK,OAAA,CAAQ,MAAA,CAAOA,CAAS,CACrC,CAEA,OAAc,CACb,IAAA,CAAK,OAAA,CAAQ,KAAA,GACd,CACD,EAEaE,CAAAA,CAA2B,CACvCd,EAAwC,EAAC,GACrC,IAAIU,CAAAA,CAAmBV,CAAO,EAGtBe,CAAAA,CAAyBN,CAAAA,GAEzBO,CAAAA,CAAqBb,CAAAA,EACjCY,EAAuB,iBAAA,CAAkBZ,CAAQ,EACrCc,CAAAA,CAAuBb,CAAAA,EACnCW,CAAAA,CAAuB,mBAAA,CAAoBX,CAAK,CAAA,CACpCc,EAAmB,IAAMH,CAAAA,CAAuB,kBAAiB,CACjEI,CAAAA,CAAef,GAC3BW,CAAAA,CAAuB,WAAA,CAAYX,CAAK,CAAA,CAC5BgB,CAAAA,CAAkBb,GAC9BQ,CAAAA,CAAuB,cAAA,CAAeR,CAAW,CAAA,CACrCc,CAAAA,CAAiB,IAAMN,CAAAA,CAAuB,cAAA,EAAe,CAC7DO,CAAAA,CAA0Bd,CAAAA,EACtCO,CAAAA,CAAuB,uBAAuBP,CAAQ,CAAA,CAC1Ce,EAAuBnB,CAAAA,EACnCW,CAAAA,CAAuB,oBAAoBX,CAAK,ECjIjD,IAAMoB,CAAAA,CAAYC,CAAAA,EACjB,OAAOA,CAAAA,EAAU,QAAA,EAAYA,IAAU,IAAA,EAAQ,CAAC,MAAM,OAAA,CAAQA,CAAK,CAAA,CAE7D,SAASC,CAAAA,CACfC,CAAAA,CACAzB,EAAgB,GAAA,CAAM,IAAA,CACG,CACzB,GAAI,CAACsB,EAASG,CAAK,CAAA,CAClB,OAAO,CAAC,CAAE,KAAA,CAAO,QAAS,OAAA,CAAS,yBAA0B,CAAC,CAAA,CAG/D,IAAMC,EAAiC,EAAC,CAYxC,GAAA,CAVC,OAAOD,CAAAA,CAAM,QAAA,EAAa,UAC1BA,CAAAA,CAAM,QAAA,CAAS,MAAK,CAAE,MAAA,GAAW,GACjCA,CAAAA,CAAM,QAAA,CAAS,OAAS,GAAA,GAExBC,CAAAA,CAAO,KAAK,CACX,KAAA,CAAO,WACP,OAAA,CAAS,+DACV,CAAC,CAAA,CAGE,EAAE,OAAA,GAAWD,CAAAA,CAAAA,CAChBC,CAAAA,CAAO,IAAA,CAAK,CAAE,KAAA,CAAO,OAAA,CAAS,QAAS,mBAAoB,CAAC,OAE5D,GAAI,CACH,IAAMC,CAAAA,CAAa,IAAA,CAAK,UAAUF,CAAAA,CAAM,KAAK,EACzCE,CAAAA,GAAe,KAAA,CAAA,CAClBD,EAAO,IAAA,CAAK,CACX,KAAA,CAAO,OAAA,CACP,OAAA,CAAS,iCACV,CAAC,CAAA,CAED,IAAI,aAAY,CAAE,MAAA,CAAOC,CAAU,CAAA,CAAE,UAAA,CAAa3B,GAElD0B,CAAAA,CAAO,IAAA,CAAK,CACX,KAAA,CAAO,OAAA,CACP,QAAS,CAAA,kBAAA,EAAqB1B,CAAa,aAC5C,CAAC,EAEH,CAAA,KAAQ,CACP0B,CAAAA,CAAO,IAAA,CAAK,CACX,KAAA,CAAO,OAAA,CACP,QAAS,iCACV,CAAC,EACF,CAGD,IAAA,IAAWE,KAAS,CAAC,SAAA,CAAW,cAAe,SAAS,CAAA,CAAY,CACnE,IAAML,CAAAA,CAAQE,EAAMG,CAAK,CAAA,CAExBL,CAAAA,GAAU,MAAA,GACT,CAAC,MAAA,CAAO,UAAUA,CAAK,CAAA,EAAMA,EAAmB,CAAA,CAAA,EAEjDG,CAAAA,CAAO,KAAK,CACX,KAAA,CAAAE,EACA,OAAA,CAAS,CAAA,EAAGA,CAAK,CAAA,6CAAA,CAClB,CAAC,EAEH,CAEA,IAAA,IAAWA,KAAS,CAAC,QAAQ,CAAA,CAAY,CACxC,IAAML,CAAAA,CAAQE,EAAMG,CAAK,CAAA,CACrBL,IAAU,MAAA,EAAa,OAAOA,GAAU,QAAA,EAC3CG,CAAAA,CAAO,KAAK,CACX,KAAA,CAAAE,EACA,OAAA,CAAS,CAAA,EAAGA,CAAK,CAAA,+BAAA,CAClB,CAAC,EAEH,CAEA,OAAIH,CAAAA,CAAM,EAAA,GAAO,MAAA,EAAa,CAAC,OAAO,QAAA,CAASA,CAAAA,CAAM,EAAE,CAAA,EACtDC,CAAAA,CAAO,KAAK,CACX,KAAA,CAAO,KACP,OAAA,CAAS,0CACV,CAAC,CAAA,CAGED,CAAAA,CAAM,SAAW,MAAA,GAEnB,CAACH,EAASG,CAAAA,CAAM,MAAM,CAAA,EACtB,OAAOA,CAAAA,CAAM,MAAA,CAAO,MAAS,QAAA,EAC7BA,CAAAA,CAAM,OAAO,IAAA,CAAK,IAAA,GAAO,MAAA,GAAW,CAAA,CAAA,EAEpCC,CAAAA,CAAO,IAAA,CAAK,CACX,KAAA,CAAO,SACP,OAAA,CAAS,6CACV,CAAC,CAAA,CAIIA,CACR,CAGO,SAASG,CAAAA,CACfC,CAAAA,CACAnB,CAAAA,CAA0BE,CAAAA,CACZ,CACd,IAAMa,CAAAA,CAASF,CAAAA,CAAmBM,EAAUnB,CAAAA,CAAO,aAAa,EAChE,GAAIe,CAAAA,CAAO,OAAS,CAAA,CACnB,OAAO,CAAE,EAAA,CAAI,KAAA,CAAO,OAAQ,eAAA,CAAiB,MAAA,CAAAA,CAAO,CAAA,CAGrD,IAAMxB,CAAAA,CAAQ4B,CAAAA,CACR3B,CAAAA,CAAUQ,CAAAA,CAAO,kBAAkBT,CAAAA,CAAM,QAAQ,GAAK,CAC3D,KAAA,CAAO,OACP,OAAA,CAAS,CACV,EAEA,GACC,OAAOA,EAAM,WAAA,EAAgB,QAAA,EAC7BA,EAAM,WAAA,GAAgBC,CAAAA,CAAQ,QAE9B,OAAO,CAAE,EAAA,CAAI,KAAA,CAAO,MAAA,CAAQ,kBAAA,CAAoB,QAAAA,CAAQ,CAAA,CAGzD,IAAM4B,CAAAA,CAAqB,CAAE,GAAG7B,CAAAA,CAAO,OAAA,CAASC,EAAQ,OAAA,CAAU,CAAE,EACpE,OAAAQ,CAAAA,CAAO,oBAAoBoB,CAAkB,CAAA,CAC7CpB,EAAO,WAAA,CAAYoB,CAAkB,CAAA,CACrCpB,CAAAA,CAAO,mBAAA,CAAoBoB,CAAkB,EAEtC,CAAE,EAAA,CAAI,KAAM,KAAA,CAAOA,CAAmB,CAC9C,CC5IO,SAASC,CAAAA,CACfC,CAAAA,CACAC,CAAAA,CACAvB,CAAAA,CAA0BE,EACzB,CACD,IAAMsB,EAAW,CAChB,KAAA,CAAOxB,EAAO,gBAAA,EAAiB,CAC/B,WAAA,CAAaA,CAAAA,CAAO,cAAA,EACrB,EAII,MAAA,GAAUuB,CAAAA,EAAO,OAAQA,CAAAA,CAAY,IAAA,EAAS,WAEhDA,CAAAA,CAAY,IAAA,CAAKC,CAAQ,CAAA,EAE1BD,CAAAA,CAAI,UAAU,GAAA,CAAK,CAAE,eAAgB,kBAAmB,CAAC,EACzDA,CAAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAUC,CAAQ,CAAC,GAElC,CChBO,IAAMC,EAAsB,CAClCC,CAAAA,CACAH,EACAI,CAAAA,CACA3B,CAAAA,CAA0BE,IACtB,CACJqB,CAAAA,CAAI,UAAU,GAAA,CAAK,CAClB,gBAAiB,wBAAA,CACjB,cAAA,CAAgB,mCAChB,UAAA,CAAY,YAAA,CACZ,mBAAA,CAAqB,IAAA,CACrB,GAAGI,CACJ,CAAC,CAAA,CAEDJ,CAAAA,CAAI,gBAAe,CAEnB,IAAMK,EACLF,CAAAA,CAAI,OAAA,CAAQ,eAAe,CAAA,EAC3B,IAAI,IAAIA,CAAAA,CAAI,GAAA,EAAO,GAAI,kBAAkB,CAAA,CAAE,aAAa,GAAA,CAAI,aAAa,CAAA,CACpEhC,CAAAA,CACL,MAAA,CAAO,QAAA,CAAS,MAAM,OAAA,CAAQkC,CAAG,EAAIA,CAAAA,CAAI,CAAC,EAAKA,CAAAA,EAAO,GAAA,CAAM,EAAE,CAAA,EAAK,CAAA,CAG9DC,CAAAA,CAA2B,EAAC,CAC9BC,CAAAA,CAAY,KAEVC,CAAAA,CAAcxC,CAAAA,EAA0B,CAC7CgC,CAAAA,CAAI,KAAA,CAAM,CAAA,IAAA,EAAOhC,CAAAA,CAAM,OAAO;AAAA,CAAI,CAAA,CAClCgC,EAAI,KAAA,CAAM,CAAA;AAAA,CAAgB,EAC1BA,CAAAA,CAAI,KAAA,CAAM,SAAS,IAAA,CAAK,SAAA,CAAUhC,CAAK,CAAC;;AAAA,CAAM,EAC/C,CAAA,CAEMyC,CAAAA,CAAchC,CAAAA,CAAO,uBAAwBT,CAAAA,EAA0B,CACxEuC,CAAAA,CACHD,CAAAA,CAAO,KAAKtC,CAAK,CAAA,CAEjBwC,CAAAA,CAAWxC,CAAK,EAElB,CAAC,CAAA,CAGD,GAAIG,CAAAA,CAAc,EAAG,CACpB,IAAMuC,CAAAA,CAASjC,CAAAA,CAAO,eAAeN,CAAW,CAAA,CAChD,IAAA,IAAWH,CAAAA,IAAS0C,EACnBF,CAAAA,CAAWxC,CAAK,EAElB,CAAA,KACCgC,EAAI,KAAA,CAAM,CAAA;AAAA,CAAmB,CAAA,CAC7BA,EAAI,KAAA,CAAM,CAAA,MAAA,EAAS,KAAK,SAAA,CAAUvB,CAAAA,CAAO,gBAAA,EAAkB,CAAC;;AAAA,CAAM,CAAA,CAKnE,IADA8B,CAAAA,CAAY,KAAA,CACLD,CAAAA,CAAO,MAAA,CAAS,CAAA,EAAG,CACzB,IAAMtC,CAAAA,CAAQsC,CAAAA,CAAO,KAAA,EAAM,CACvBtC,CAAAA,EAAOwC,CAAAA,CAAWxC,CAAK,EAC5B,CAEA,IAAM2C,CAAAA,CAAY,WAAA,CAAY,IAAM,CACnCX,CAAAA,CAAI,KAAA,CAAM,CAAA,OAAA,EAAU,IAAA,CAAK,GAAA,EAAK;;AAAA,CAAM,EACrC,CAAA,CAAG,IAAK,CAAA,CAERA,EAAI,KAAA,CAAM,CAAA;;AAAA,CAAkB,CAAA,CAE5BG,EAAI,EAAA,CAAG,OAAA,CAAS,IAAM,CACrB,aAAA,CAAcQ,CAAS,CAAA,CACvBF,CAAAA,GACAT,CAAAA,CAAI,GAAA,GACL,CAAC,EACF,EAKaY,CAAAA,CAAoB,CAChCT,CAAAA,CACAH,CAAAA,CACAvB,CAAAA,CAA0BE,CAAAA,GACtB,CAEJ,IAAIkC,CAAAA,CAAO,GAEXV,CAAAA,CAAI,EAAA,CAAG,OAASW,CAAAA,EAAkB,CACjCD,GAAQC,CAAAA,CAAM,QAAA,CAAS,MAAM,CAAA,CACzBD,CAAAA,CAAK,OAAS,MAAA,GACjBb,CAAAA,CAAI,UAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,EAAI,GAAA,CAAI,IAAA,CAAK,UAAU,CAAE,EAAA,CAAI,MAAO,MAAA,CAAQ,mBAAoB,CAAC,CAAC,CAAA,CAClEG,EAAI,OAAA,EAAQ,EAEd,CAAC,CAAA,CAEDA,CAAAA,CAAI,GAAG,KAAA,CAAO,IAAM,CACnB,GAAI,CACH,IAAMP,EAA2B,IAAA,CAAK,KAAA,CACrCiB,GAAQ,IACT,CAAA,CACME,EAASpB,CAAAA,CAAgBC,CAAAA,CAAUnB,CAAM,CAAA,CAE/C,GAAI,CAACsC,CAAAA,CAAO,EAAA,CAAI,CACXA,CAAAA,CAAO,MAAA,GAAW,oBACrBf,CAAAA,CAAI,SAAA,CAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,IACH,IAAA,CAAK,SAAA,CAAU,CACd,EAAA,CAAI,CAAA,CAAA,CACJ,OAAQ,kBAAA,CACR,OAAA,CAASe,EAAO,OACjB,CAAC,CACF,CAAA,GAEAf,CAAAA,CAAI,UAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,EAAI,GAAA,CACH,IAAA,CAAK,UAAU,CACd,EAAA,CAAI,GACJ,MAAA,CAAQe,CAAAA,CAAO,OACf,MAAA,CAAQA,CAAAA,CAAO,MAChB,CAAC,CACF,GAED,MACD,CAEAf,EAAI,SAAA,CAAU,GAAA,CAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,EACzDA,CAAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,CAAE,GAAI,CAAA,CAAA,CAAM,KAAA,CAAOe,EAAO,KAAM,CAAC,CAAC,EAC1D,CAAA,KAAQ,CACPf,CAAAA,CAAI,SAAA,CAAU,IAAK,CAAE,cAAA,CAAgB,kBAAmB,CAAC,CAAA,CACzDA,CAAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,CAAE,EAAA,CAAI,KAAA,CAAO,OAAQ,cAAe,CAAC,CAAC,EAC9D,CACD,CAAC,EACF,CAAA,CAEagB,CAAAA,CAAmB,CAC/Bb,CAAAA,CACAH,CAAAA,CACAvB,EAA0BE,CAAAA,GAEnBiC,CAAAA,CAAkBT,CAAAA,CAAKH,CAAAA,CAAKvB,CAAM","file":"index.cjs","sourcesContent":["import type { ZunoStateEvent } from \"../sync\";\n\nexport type UniverseRecord = {\n\tstate: unknown;\n\tversion: number;\n};\n\nexport type ZunoStateListener = (event: ZunoStateEvent) => void;\n\nexport type CreateZunoServerStateOptions = {\n\t/** Maximum number of authoritative events retained for SSE replay. */\n\tmaxEvents?: number;\n\t/** Maximum serialized state size accepted per event. */\n\tmaxStateBytes?: number;\n};\n\n/**\n * Isolated authoritative state used by server adapters.\n * Create one instance per application, namespace, or tenant boundary.\n */\nexport class ZunoServerState {\n\treadonly maxEvents: number;\n\treadonly maxStateBytes: number;\n\tprivate readonly universeState = new Map<string, UniverseRecord>();\n\tprivate readonly eventLog: ZunoStateEvent[] = [];\n\tprivate readonly listeners = new Set<ZunoStateListener>();\n\tprivate nextEventId = 1;\n\n\tconstructor(options: CreateZunoServerStateOptions = {}) {\n\t\tconst maxEvents = options.maxEvents ?? 1000;\n\t\tconst maxStateBytes = options.maxStateBytes ?? 512 * 1024;\n\t\tif (!Number.isInteger(maxEvents) || maxEvents < 1) {\n\t\t\tthrow new TypeError(\"maxEvents must be a positive integer\");\n\t\t}\n\t\tif (!Number.isInteger(maxStateBytes) || maxStateBytes < 1) {\n\t\t\tthrow new TypeError(\"maxStateBytes must be a positive integer\");\n\t\t}\n\t\tthis.maxEvents = maxEvents;\n\t\tthis.maxStateBytes = maxStateBytes;\n\t}\n\n\tgetUniverseRecord(storeKey: string): UniverseRecord | undefined {\n\t\treturn this.universeState.get(storeKey);\n\t}\n\n\tupdateUniverseState(event: ZunoStateEvent): void {\n\t\tconst current = this.universeState.get(event.storeKey) ?? {\n\t\t\tstate: undefined,\n\t\t\tversion: 0,\n\t\t};\n\t\tconst nextVersion =\n\t\t\ttypeof event.version === \"number\" ? event.version : current.version + 1;\n\t\tthis.universeState.set(event.storeKey, {\n\t\t\tstate: event.state,\n\t\t\tversion: nextVersion,\n\t\t});\n\t}\n\n\tgetUniverseState(): Record<string, UniverseRecord> {\n\t\treturn Object.fromEntries(this.universeState);\n\t}\n\n\tappendEvent(event: ZunoStateEvent): ZunoStateEvent {\n\t\tevent.eventId = this.nextEventId++;\n\t\tthis.eventLog.push(event);\n\t\tif (this.eventLog.length > this.maxEvents) {\n\t\t\tthis.eventLog.shift();\n\t\t}\n\t\treturn event;\n\t}\n\n\tgetEventsAfter(lastEventId: number): ZunoStateEvent[] {\n\t\treturn this.eventLog.filter((event) => (event.eventId ?? 0) > lastEventId);\n\t}\n\n\tgetLastEventId(): number {\n\t\treturn this.eventLog[this.eventLog.length - 1]?.eventId ?? 0;\n\t}\n\n\tsubscribeToStateEvents(listener: ZunoStateListener): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\tpublishToStateEvent(event: ZunoStateEvent): void {\n\t\tthis.listeners.forEach((listener) => {\n\t\t\tlistener(event);\n\t\t});\n\t}\n\n\tclear(): void {\n\t\tthis.universeState.clear();\n\t\tthis.eventLog.length = 0;\n\t\tthis.nextEventId = 1;\n\t}\n}\n\nexport const createZunoServerState = (\n\toptions: CreateZunoServerStateOptions = {},\n) => new ZunoServerState(options);\n\n/** Lazily creates isolated server states for application namespaces or tenants. */\nexport class ZunoServerRegistry {\n\tprivate readonly servers = new Map<string, ZunoServerState>();\n\n\tconstructor(\n\t\tprivate readonly serverOptions: CreateZunoServerStateOptions = {},\n\t) {}\n\n\tget(namespace: string): ZunoServerState {\n\t\tif (namespace.trim().length === 0) {\n\t\t\tthrow new TypeError(\"namespace must be a non-empty string\");\n\t\t}\n\t\tlet server = this.servers.get(namespace);\n\t\tif (!server) {\n\t\t\tserver = createZunoServerState(this.serverOptions);\n\t\t\tthis.servers.set(namespace, server);\n\t\t}\n\t\treturn server;\n\t}\n\n\tdelete(namespace: string): boolean {\n\t\treturn this.servers.delete(namespace);\n\t}\n\n\tclear(): void {\n\t\tthis.servers.clear();\n\t}\n}\n\nexport const createZunoServerRegistry = (\n\toptions: CreateZunoServerStateOptions = {},\n) => new ZunoServerRegistry(options);\n\n/** Backward-compatible singleton used by the original module-level helpers. */\nexport const defaultZunoServerState = createZunoServerState();\n\nexport const getUniverseRecord = (storeKey: string) =>\n\tdefaultZunoServerState.getUniverseRecord(storeKey);\nexport const updateUniverseState = (event: ZunoStateEvent) =>\n\tdefaultZunoServerState.updateUniverseState(event);\nexport const getUniverseState = () => defaultZunoServerState.getUniverseState();\nexport const appendEvent = (event: ZunoStateEvent) =>\n\tdefaultZunoServerState.appendEvent(event);\nexport const getEventsAfter = (lastEventId: number) =>\n\tdefaultZunoServerState.getEventsAfter(lastEventId);\nexport const getLastEventId = () => defaultZunoServerState.getLastEventId();\nexport const subscribeToStateEvents = (listener: ZunoStateListener) =>\n\tdefaultZunoServerState.subscribeToStateEvents(listener);\nexport const publishToStateEvent = (event: ZunoStateEvent) =>\n\tdefaultZunoServerState.publishToStateEvent(event);\n","import type { ZunoStateEvent } from \"../sync\";\nimport { defaultZunoServerState, type ZunoServerState } from \"./core\";\n\nexport type EventValidationError = {\n\tfield: string;\n\tmessage: string;\n};\n\nexport type ApplyResult =\n\t| { ok: true; event: ZunoStateEvent }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"VERSION_CONFLICT\";\n\t\t\tcurrent: { state: unknown; version: number };\n\t\t\terrors?: never;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"INVALID_EVENT\";\n\t\t\terrors: EventValidationError[];\n\t\t\tcurrent?: never;\n\t };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport function validateStateEvent(\n\tinput: unknown,\n\tmaxStateBytes = 512 * 1024,\n): EventValidationError[] {\n\tif (!isRecord(input)) {\n\t\treturn [{ field: \"event\", message: \"Event must be an object\" }];\n\t}\n\n\tconst errors: EventValidationError[] = [];\n\tif (\n\t\ttypeof input.storeKey !== \"string\" ||\n\t\tinput.storeKey.trim().length === 0 ||\n\t\tinput.storeKey.length > 256\n\t) {\n\t\terrors.push({\n\t\t\tfield: \"storeKey\",\n\t\t\tmessage: \"storeKey must be a non-empty string of at most 256 characters\",\n\t\t});\n\t}\n\n\tif (!(\"state\" in input)) {\n\t\terrors.push({ field: \"state\", message: \"state is required\" });\n\t} else {\n\t\ttry {\n\t\t\tconst serialized = JSON.stringify(input.state);\n\t\t\tif (serialized === undefined) {\n\t\t\t\terrors.push({\n\t\t\t\t\tfield: \"state\",\n\t\t\t\t\tmessage: \"state must be JSON-serializable\",\n\t\t\t\t});\n\t\t\t} else if (\n\t\t\t\tnew TextEncoder().encode(serialized).byteLength > maxStateBytes\n\t\t\t) {\n\t\t\t\terrors.push({\n\t\t\t\t\tfield: \"state\",\n\t\t\t\t\tmessage: `state exceeds the ${maxStateBytes} byte limit`,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch {\n\t\t\terrors.push({\n\t\t\t\tfield: \"state\",\n\t\t\t\tmessage: \"state must be JSON-serializable\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const field of [\"version\", \"baseVersion\", \"eventId\"] as const) {\n\t\tconst value = input[field];\n\t\tif (\n\t\t\tvalue !== undefined &&\n\t\t\t(!Number.isInteger(value) || (value as number) < 0)\n\t\t) {\n\t\t\terrors.push({\n\t\t\t\tfield,\n\t\t\t\tmessage: `${field} must be a non-negative integer when provided`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const field of [\"origin\"] as const) {\n\t\tconst value = input[field];\n\t\tif (value !== undefined && typeof value !== \"string\") {\n\t\t\terrors.push({\n\t\t\t\tfield,\n\t\t\t\tmessage: `${field} must be a string when provided`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (input.ts !== undefined && !Number.isFinite(input.ts)) {\n\t\terrors.push({\n\t\t\tfield: \"ts\",\n\t\t\tmessage: \"ts must be a finite number when provided\",\n\t\t});\n\t}\n\n\tif (input.intent !== undefined) {\n\t\tif (\n\t\t\t!isRecord(input.intent) ||\n\t\t\ttypeof input.intent.type !== \"string\" ||\n\t\t\tinput.intent.type.trim().length === 0\n\t\t) {\n\t\t\terrors.push({\n\t\t\t\tfield: \"intent\",\n\t\t\t\tmessage: \"intent must contain a non-empty string type\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn errors;\n}\n\n/** Validates and applies a state event to an isolated authoritative server. */\nexport function applyStateEvent(\n\tincoming: unknown,\n\tserver: ZunoServerState = defaultZunoServerState,\n): ApplyResult {\n\tconst errors = validateStateEvent(incoming, server.maxStateBytes);\n\tif (errors.length > 0) {\n\t\treturn { ok: false, reason: \"INVALID_EVENT\", errors };\n\t}\n\n\tconst event = incoming as ZunoStateEvent;\n\tconst current = server.getUniverseRecord(event.storeKey) ?? {\n\t\tstate: undefined,\n\t\tversion: 0,\n\t};\n\n\tif (\n\t\ttypeof event.baseVersion === \"number\" &&\n\t\tevent.baseVersion !== current.version\n\t) {\n\t\treturn { ok: false, reason: \"VERSION_CONFLICT\", current };\n\t}\n\n\tconst authoritativeEvent = { ...event, version: current.version + 1 };\n\tserver.updateUniverseState(authoritativeEvent);\n\tserver.appendEvent(authoritativeEvent);\n\tserver.publishToStateEvent(authoritativeEvent);\n\n\treturn { ok: true, event: authoritativeEvent };\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { defaultZunoServerState, type ZunoServerState } from \"./core\";\n\n/**\n * Sends a snapshot of the current universe state to the response.\n * Compatible with both Express and raw Node.js http.\n */\nexport function sendSnapshot(\n\t_req: IncomingMessage,\n\tres: ServerResponse,\n\tserver: ZunoServerState = defaultZunoServerState,\n) {\n\tconst snapshot = {\n\t\tstate: server.getUniverseState(),\n\t\tlastEventId: server.getLastEventId(),\n\t};\n\n\t// Check for Express-like .json() method\n\t// biome-ignore lint/suspicious/noExplicitAny: Checking for dynamic .json() method on response object\n\tif (\"json\" in res && typeof (res as any).json === \"function\") {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Calling dynamic .json() method\n\t\t(res as any).json(snapshot);\n\t} else {\n\t\tres.writeHead(200, { \"Content-Type\": \"application/json\" });\n\t\tres.end(JSON.stringify(snapshot));\n\t}\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ZunoStateEvent } from \"../sync\";\nimport { applyStateEvent } from \"./apply-state-event\";\nimport { defaultZunoServerState, type ZunoServerState } from \"./core\";\n\ntype IncomingHeaders = IncomingMessage[\"headers\"];\n\n/**\n * Creates a Server-Sent Events (SSE) connection for Zuno state updates.\n */\nexport const createSSEConnection = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\theaders: IncomingHeaders,\n\tserver: ZunoServerState = defaultZunoServerState,\n) => {\n\tres.writeHead(200, {\n\t\t\"Cache-Control\": \"no-cache, no-transform\",\n\t\t\"Content-Type\": \"text/event-stream; charset=utf-8\",\n\t\tConnection: \"keep-alive\",\n\t\t\"X-Accel-Buffering\": \"no\",\n\t\t...headers,\n\t});\n\n\tres.flushHeaders?.();\n\n\tconst raw =\n\t\treq.headers[\"last-event-id\"] ||\n\t\tnew URL(req.url || \"\", \"http://localhost\").searchParams.get(\"lastEventId\");\n\tconst lastEventId =\n\t\tNumber.parseInt(Array.isArray(raw) ? raw[0] : (raw ?? \"0\"), 10) || 0;\n\n\t// 1. Subscribe FIRST and buffer events until snapshot/missed-events are sent\n\tconst buffer: ZunoStateEvent[] = [];\n\tlet isSyncing = true;\n\n\tconst writeEvent = (event: ZunoStateEvent) => {\n\t\tres.write(`id: ${event.eventId}\\n`);\n\t\tres.write(`event: state\\n`);\n\t\tres.write(`data: ${JSON.stringify(event)}\\n\\n`);\n\t};\n\n\tconst unsubscribe = server.subscribeToStateEvents((event: ZunoStateEvent) => {\n\t\tif (isSyncing) {\n\t\t\tbuffer.push(event);\n\t\t} else {\n\t\t\twriteEvent(event);\n\t\t}\n\t});\n\n\t// 2. Send missed events or snapshot\n\tif (lastEventId > 0) {\n\t\tconst missed = server.getEventsAfter(lastEventId);\n\t\tfor (const event of missed) {\n\t\t\twriteEvent(event);\n\t\t}\n\t} else {\n\t\tres.write(`event: snapshot\\n`);\n\t\tres.write(`data: ${JSON.stringify(server.getUniverseState())}\\n\\n`);\n\t}\n\n\t// 3. Flush buffer and switch to live mode\n\tisSyncing = false;\n\twhile (buffer.length > 0) {\n\t\tconst event = buffer.shift();\n\t\tif (event) writeEvent(event);\n\t}\n\n\tconst heartbeat = setInterval(() => {\n\t\tres.write(`: ping ${Date.now()}\\n\\n`);\n\t}, 15000);\n\n\tres.write(\": connected \\n\\n\");\n\n\treq.on(\"close\", () => {\n\t\tclearInterval(heartbeat);\n\t\tunsubscribe();\n\t\tres.end();\n\t});\n};\n\n/**\n * Synchronizes the Zuno universe state by applying an incoming event.\n */\nexport const syncUniverseState = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tserver: ZunoServerState = defaultZunoServerState,\n) => {\n\tconst MAX_BODY_BYTES = 512 * 1024; // 512KB safety\n\tlet body = \"\";\n\n\treq.on(\"data\", (chunk: Buffer) => {\n\t\tbody += chunk.toString(\"utf8\");\n\t\tif (body.length > MAX_BODY_BYTES) {\n\t\t\tres.writeHead(413, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: false, reason: \"PAYLOAD_TOO_LARGE\" }));\n\t\t\treq.destroy();\n\t\t}\n\t});\n\n\treq.on(\"end\", () => {\n\t\ttry {\n\t\t\tconst incoming: ZunoStateEvent = JSON.parse(\n\t\t\t\tbody || \"{}\",\n\t\t\t) as unknown as ZunoStateEvent;\n\t\t\tconst result = applyStateEvent(incoming, server);\n\n\t\t\tif (!result.ok) {\n\t\t\t\tif (result.reason === \"VERSION_CONFLICT\") {\n\t\t\t\t\tres.writeHead(409, { \"Content-Type\": \"application/json\" });\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\treason: \"VERSION_CONFLICT\",\n\t\t\t\t\t\t\tcurrent: result.current,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tres.writeHead(400, { \"Content-Type\": \"application/json\" });\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\treason: result.reason,\n\t\t\t\t\t\t\terrors: result.errors,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tres.writeHead(200, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: true, event: result.event }));\n\t\t} catch {\n\t\t\tres.writeHead(400, { \"Content-Type\": \"application/json\" });\n\t\t\tres.end(JSON.stringify({ ok: false, reason: \"INVALID_JSON\" }));\n\t\t}\n\t});\n};\n\nexport const setUniverseState = (\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tserver: ZunoServerState = defaultZunoServerState,\n) => {\n\treturn syncUniverseState(req, res, server);\n};\n"]}
@@ -1,6 +1,65 @@
1
- import { f as ZunoStateEvent } from '../index-BahxvhoY.cjs';
1
+ import { f as ZunoStateEvent } from '../index-BU6hvVGv.cjs';
2
2
  import { IncomingMessage, ServerResponse } from 'node:http';
3
3
 
4
+ type UniverseRecord = {
5
+ state: unknown;
6
+ version: number;
7
+ };
8
+ type ZunoStateListener = (event: ZunoStateEvent) => void;
9
+ type CreateZunoServerStateOptions = {
10
+ /** Maximum number of authoritative events retained for SSE replay. */
11
+ maxEvents?: number;
12
+ /** Maximum serialized state size accepted per event. */
13
+ maxStateBytes?: number;
14
+ };
15
+ /**
16
+ * Isolated authoritative state used by server adapters.
17
+ * Create one instance per application, namespace, or tenant boundary.
18
+ */
19
+ declare class ZunoServerState {
20
+ readonly maxEvents: number;
21
+ readonly maxStateBytes: number;
22
+ private readonly universeState;
23
+ private readonly eventLog;
24
+ private readonly listeners;
25
+ private nextEventId;
26
+ constructor(options?: CreateZunoServerStateOptions);
27
+ getUniverseRecord(storeKey: string): UniverseRecord | undefined;
28
+ updateUniverseState(event: ZunoStateEvent): void;
29
+ getUniverseState(): Record<string, UniverseRecord>;
30
+ appendEvent(event: ZunoStateEvent): ZunoStateEvent;
31
+ getEventsAfter(lastEventId: number): ZunoStateEvent[];
32
+ getLastEventId(): number;
33
+ subscribeToStateEvents(listener: ZunoStateListener): () => void;
34
+ publishToStateEvent(event: ZunoStateEvent): void;
35
+ clear(): void;
36
+ }
37
+ declare const createZunoServerState: (options?: CreateZunoServerStateOptions) => ZunoServerState;
38
+ /** Lazily creates isolated server states for application namespaces or tenants. */
39
+ declare class ZunoServerRegistry {
40
+ private readonly serverOptions;
41
+ private readonly servers;
42
+ constructor(serverOptions?: CreateZunoServerStateOptions);
43
+ get(namespace: string): ZunoServerState;
44
+ delete(namespace: string): boolean;
45
+ clear(): void;
46
+ }
47
+ declare const createZunoServerRegistry: (options?: CreateZunoServerStateOptions) => ZunoServerRegistry;
48
+ /** Backward-compatible singleton used by the original module-level helpers. */
49
+ declare const defaultZunoServerState: ZunoServerState;
50
+ declare const getUniverseRecord: (storeKey: string) => UniverseRecord | undefined;
51
+ declare const updateUniverseState: (event: ZunoStateEvent) => void;
52
+ declare const getUniverseState: () => Record<string, UniverseRecord>;
53
+ declare const appendEvent: (event: ZunoStateEvent) => ZunoStateEvent;
54
+ declare const getEventsAfter: (lastEventId: number) => ZunoStateEvent[];
55
+ declare const getLastEventId: () => number;
56
+ declare const subscribeToStateEvents: (listener: ZunoStateListener) => () => void;
57
+ declare const publishToStateEvent: (event: ZunoStateEvent) => void;
58
+
59
+ type EventValidationError = {
60
+ field: string;
61
+ message: string;
62
+ };
4
63
  type ApplyResult = {
5
64
  ok: true;
6
65
  event: ZunoStateEvent;
@@ -11,47 +70,32 @@ type ApplyResult = {
11
70
  state: unknown;
12
71
  version: number;
13
72
  };
73
+ errors?: never;
14
74
  } | {
15
75
  ok: false;
16
- reason: string;
76
+ reason: "INVALID_EVENT";
77
+ errors: EventValidationError[];
17
78
  current?: never;
18
79
  };
19
- /**
20
- * Validates and applies a state event to the server universe.
21
- */
22
- declare function applyStateEvent(incoming: ZunoStateEvent): ApplyResult;
23
-
24
- type UniverseRecord = {
25
- state: unknown;
26
- version: number;
27
- };
28
- type ZunoStateListener = (event: ZunoStateEvent) => void;
29
- declare const getUniverseRecord: (storeKey: string) => UniverseRecord | undefined;
30
- declare const updateUniverseState: (event: ZunoStateEvent) => void;
31
- declare const getUniverseState: () => {
32
- [k: string]: UniverseRecord;
33
- };
34
- declare const appendEvent: (event: ZunoStateEvent) => ZunoStateEvent;
35
- declare const getEventsAfter: (lastEventId: number) => ZunoStateEvent[];
36
- declare const getLastEventId: () => number;
37
- declare const subscribeToStateEvents: (listener: ZunoStateListener) => () => void;
38
- declare const publishToStateEvent: (event: ZunoStateEvent) => void;
80
+ declare function validateStateEvent(input: unknown, maxStateBytes?: number): EventValidationError[];
81
+ /** Validates and applies a state event to an isolated authoritative server. */
82
+ declare function applyStateEvent(incoming: unknown, server?: ZunoServerState): ApplyResult;
39
83
 
40
84
  /**
41
85
  * Sends a snapshot of the current universe state to the response.
42
86
  * Compatible with both Express and raw Node.js http.
43
87
  */
44
- declare function sendSnapshot(_req: IncomingMessage, res: ServerResponse): void;
88
+ declare function sendSnapshot(_req: IncomingMessage, res: ServerResponse, server?: ZunoServerState): void;
45
89
 
46
90
  type IncomingHeaders = IncomingMessage["headers"];
47
91
  /**
48
92
  * Creates a Server-Sent Events (SSE) connection for Zuno state updates.
49
93
  */
50
- declare const createSSEConnection: (req: IncomingMessage, res: ServerResponse, headers: IncomingHeaders) => void;
94
+ declare const createSSEConnection: (req: IncomingMessage, res: ServerResponse, headers: IncomingHeaders, server?: ZunoServerState) => void;
51
95
  /**
52
96
  * Synchronizes the Zuno universe state by applying an incoming event.
53
97
  */
54
- declare const syncUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
55
- declare const setUniverseState: (req: IncomingMessage, res: ServerResponse) => void;
98
+ declare const syncUniverseState: (req: IncomingMessage, res: ServerResponse, server?: ZunoServerState) => void;
99
+ declare const setUniverseState: (req: IncomingMessage, res: ServerResponse, server?: ZunoServerState) => void;
56
100
 
57
- export { type ApplyResult, type UniverseRecord, type ZunoStateListener, appendEvent, applyStateEvent, createSSEConnection, getEventsAfter, getLastEventId, getUniverseRecord, getUniverseState, publishToStateEvent, sendSnapshot, setUniverseState, subscribeToStateEvents, syncUniverseState, updateUniverseState };
101
+ export { type ApplyResult, type CreateZunoServerStateOptions, type EventValidationError, type UniverseRecord, ZunoServerRegistry, ZunoServerState, type ZunoStateListener, appendEvent, applyStateEvent, createSSEConnection, createZunoServerRegistry, createZunoServerState, defaultZunoServerState, getEventsAfter, getLastEventId, getUniverseRecord, getUniverseState, publishToStateEvent, sendSnapshot, setUniverseState, subscribeToStateEvents, syncUniverseState, updateUniverseState, validateStateEvent };