@korajs/sync 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/protocol/messages.ts","../src/protocol/serializer.ts","../src/transport/websocket-transport.ts","../src/transport/http-long-polling-transport.ts","../src/transport/chaos-transport.ts","../src/engine/sync-engine.ts","../src/engine/outbound-queue.ts","../src/engine/connection-monitor.ts","../src/engine/reconnection-manager.ts"],"sourcesContent":["import type { Operation } from '@korajs/core'\n\n/**\n * Internal sync engine states. Used for state machine transitions.\n */\nexport const SYNC_STATES = [\n\t'disconnected',\n\t'connecting',\n\t'handshaking',\n\t'syncing',\n\t'streaming',\n\t'error',\n] as const\nexport type SyncState = (typeof SYNC_STATES)[number]\n\n/**\n * Developer-facing sync status. Simplified view of the internal state.\n */\nexport const SYNC_STATUSES = ['connected', 'syncing', 'synced', 'offline', 'error'] as const\nexport type SyncStatus = (typeof SYNC_STATUSES)[number]\n\n/**\n * Sync status information exposed to developers.\n */\nexport interface SyncStatusInfo {\n\t/** Current developer-facing status */\n\tstatus: SyncStatus\n\t/** Number of operations waiting to be sent */\n\tpendingOperations: number\n\t/** Timestamp of last successful sync (null if never synced) */\n\tlastSyncedAt: number | null\n}\n\n/**\n * Sync configuration provided by the developer.\n */\nexport interface SyncConfig {\n\t/** WebSocket or HTTP URL for the sync server */\n\turl: string\n\t/** Transport type to use. Defaults to 'websocket'. */\n\ttransport?: 'websocket' | 'http'\n\t/** Auth provider function. Called before each connection attempt. */\n\tauth?: () => Promise<{ token: string }>\n\t/** Sync scopes per collection. Limits which records sync to this client. */\n\tscopes?: Record<string, (ctx: SyncScopeContext) => Record<string, unknown>>\n\t/** Number of operations per batch. Defaults to 100. */\n\tbatchSize?: number\n\t/** Initial reconnection delay in ms. Defaults to 1000. */\n\treconnectInterval?: number\n\t/** Maximum reconnection delay in ms. Defaults to 30000. */\n\tmaxReconnectInterval?: number\n\t/** Schema version of this client. */\n\tschemaVersion?: number\n}\n\n/**\n * Context passed to sync scope functions.\n */\nexport interface SyncScopeContext {\n\tuserId?: string\n\t[key: string]: unknown\n}\n\n/**\n * Interface for persisting the outbound operation queue.\n * Operations must survive page refreshes and be sent when connection is re-established.\n */\nexport interface QueueStorage {\n\t/** Load all queued operations from persistent storage */\n\tload(): Promise<Operation[]>\n\t/** Persist an operation to the queue */\n\tenqueue(op: Operation): Promise<void>\n\t/** Remove acknowledged operations by their IDs */\n\tdequeue(ids: string[]): Promise<void>\n\t/** Return number of operations in storage */\n\tcount(): Promise<number>\n}\n","import type { HLCTimestamp, OperationType } from '@korajs/core'\n\nexport type WireFormat = 'json' | 'protobuf'\n\n/**\n * Wire-format operation. Plain object (no Map) for JSON serialization.\n * Maps 1:1 with Operation, but uses Record instead of Map for version vectors.\n */\nexport interface SerializedOperation {\n\tid: string\n\tnodeId: string\n\ttype: OperationType\n\tcollection: string\n\trecordId: string\n\tdata: Record<string, unknown> | null\n\tpreviousData: Record<string, unknown> | null\n\ttimestamp: HLCTimestamp\n\tsequenceNumber: number\n\tcausalDeps: string[]\n\tschemaVersion: number\n}\n\n/**\n * Handshake message sent by client to initiate sync.\n */\nexport interface HandshakeMessage {\n\ttype: 'handshake'\n\tmessageId: string\n\tnodeId: string\n\t/** Version vector as plain object (nodeId -> sequence number) */\n\tversionVector: Record<string, number>\n\tschemaVersion: number\n\tauthToken?: string\n\tsupportedWireFormats?: WireFormat[]\n}\n\n/**\n * Server response to a handshake.\n */\nexport interface HandshakeResponseMessage {\n\ttype: 'handshake-response'\n\tmessageId: string\n\tnodeId: string\n\tversionVector: Record<string, number>\n\tschemaVersion: number\n\taccepted: boolean\n\trejectReason?: string\n\tselectedWireFormat?: WireFormat\n}\n\n/**\n * Batch of operations sent during delta exchange or streaming.\n */\nexport interface OperationBatchMessage {\n\ttype: 'operation-batch'\n\tmessageId: string\n\toperations: SerializedOperation[]\n\t/** True if this is the last batch in the delta exchange phase */\n\tisFinal: boolean\n\t/** Index of this batch (0-based) for ordering */\n\tbatchIndex: number\n}\n\n/**\n * Acknowledgment of a received message.\n */\nexport interface AcknowledgmentMessage {\n\ttype: 'acknowledgment'\n\tmessageId: string\n\tacknowledgedMessageId: string\n\tlastSequenceNumber: number\n}\n\n/**\n * Error message from the server or client.\n */\nexport interface ErrorMessage {\n\ttype: 'error'\n\tmessageId: string\n\tcode: string\n\tmessage: string\n\tretriable: boolean\n}\n\n/**\n * Union of all sync protocol messages.\n */\nexport type SyncMessage =\n\t| HandshakeMessage\n\t| HandshakeResponseMessage\n\t| OperationBatchMessage\n\t| AcknowledgmentMessage\n\t| ErrorMessage\n\n// --- Type Guards ---\n\n/**\n * Check if an unknown value is a valid SyncMessage.\n */\nexport function isSyncMessage(value: unknown): value is SyncMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\tif (typeof msg.type !== 'string' || typeof msg.messageId !== 'string') return false\n\tswitch (msg.type) {\n\t\tcase 'handshake':\n\t\t\treturn isHandshakeMessage(value)\n\t\tcase 'handshake-response':\n\t\t\treturn isHandshakeResponseMessage(value)\n\t\tcase 'operation-batch':\n\t\t\treturn isOperationBatchMessage(value)\n\t\tcase 'acknowledgment':\n\t\t\treturn isAcknowledgmentMessage(value)\n\t\tcase 'error':\n\t\t\treturn isErrorMessage(value)\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n/**\n * Check if a value is a HandshakeMessage.\n */\nexport function isHandshakeMessage(value: unknown): value is HandshakeMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\treturn (\n\t\tmsg.type === 'handshake' &&\n\t\ttypeof msg.messageId === 'string' &&\n\t\ttypeof msg.nodeId === 'string' &&\n\t\ttypeof msg.versionVector === 'object' &&\n\t\tmsg.versionVector !== null &&\n\t\t!Array.isArray(msg.versionVector) &&\n\t\ttypeof msg.schemaVersion === 'number'\n\t)\n}\n\n/**\n * Check if a value is a HandshakeResponseMessage.\n */\nexport function isHandshakeResponseMessage(value: unknown): value is HandshakeResponseMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\treturn (\n\t\tmsg.type === 'handshake-response' &&\n\t\ttypeof msg.messageId === 'string' &&\n\t\ttypeof msg.nodeId === 'string' &&\n\t\ttypeof msg.versionVector === 'object' &&\n\t\tmsg.versionVector !== null &&\n\t\t!Array.isArray(msg.versionVector) &&\n\t\ttypeof msg.schemaVersion === 'number' &&\n\t\ttypeof msg.accepted === 'boolean'\n\t)\n}\n\n/**\n * Check if a value is an OperationBatchMessage.\n */\nexport function isOperationBatchMessage(value: unknown): value is OperationBatchMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\treturn (\n\t\tmsg.type === 'operation-batch' &&\n\t\ttypeof msg.messageId === 'string' &&\n\t\tArray.isArray(msg.operations) &&\n\t\ttypeof msg.isFinal === 'boolean' &&\n\t\ttypeof msg.batchIndex === 'number'\n\t)\n}\n\n/**\n * Check if a value is an AcknowledgmentMessage.\n */\nexport function isAcknowledgmentMessage(value: unknown): value is AcknowledgmentMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\treturn (\n\t\tmsg.type === 'acknowledgment' &&\n\t\ttypeof msg.messageId === 'string' &&\n\t\ttypeof msg.acknowledgedMessageId === 'string' &&\n\t\ttypeof msg.lastSequenceNumber === 'number'\n\t)\n}\n\n/**\n * Check if a value is an ErrorMessage.\n */\nexport function isErrorMessage(value: unknown): value is ErrorMessage {\n\tif (typeof value !== 'object' || value === null) return false\n\tconst msg = value as Record<string, unknown>\n\treturn (\n\t\tmsg.type === 'error' &&\n\t\ttypeof msg.messageId === 'string' &&\n\t\ttypeof msg.code === 'string' &&\n\t\ttypeof msg.message === 'string' &&\n\t\ttypeof msg.retriable === 'boolean'\n\t)\n}\n","import { SyncError } from '@korajs/core'\nimport type { Operation, VersionVector } from '@korajs/core'\nimport { Reader, Writer } from 'protobufjs/minimal'\nimport type {\n\tAcknowledgmentMessage,\n\tErrorMessage,\n\tHandshakeMessage,\n\tHandshakeResponseMessage,\n\tOperationBatchMessage,\n\tSerializedOperation,\n\tSyncMessage,\n\tWireFormat,\n} from './messages'\nimport { isSyncMessage } from './messages'\n\nexport type EncodedMessage = string | Uint8Array\n\n/**\n * Interface for encoding/decoding sync protocol messages.\n */\nexport interface MessageSerializer {\n\tencode(message: SyncMessage): EncodedMessage\n\tdecode(data: string | Uint8Array | ArrayBuffer): SyncMessage\n\tencodeOperation(op: Operation): SerializedOperation\n\tdecodeOperation(serialized: SerializedOperation): Operation\n\tsetWireFormat?(format: WireFormat): void\n\tgetWireFormat?(): WireFormat\n}\n\n/**\n * Convert a VersionVector (Map) to a plain object for wire transmission.\n */\nexport function versionVectorToWire(vector: VersionVector): Record<string, number> {\n\tconst wire: Record<string, number> = {}\n\tfor (const [nodeId, seq] of vector) {\n\t\twire[nodeId] = seq\n\t}\n\treturn wire\n}\n\n/**\n * Convert a wire-format version vector (plain object) back to a VersionVector (Map).\n */\nexport function wireToVersionVector(wire: Record<string, number>): VersionVector {\n\treturn new Map(Object.entries(wire))\n}\n\n/**\n * JSON-based message serializer.\n */\nexport class JsonMessageSerializer implements MessageSerializer {\n\tencode(message: SyncMessage): string {\n\t\treturn JSON.stringify(message)\n\t}\n\n\tdecode(data: string | Uint8Array | ArrayBuffer): SyncMessage {\n\t\tconst text = decodeTextPayload(data)\n\n\t\tlet parsed: unknown\n\t\ttry {\n\t\t\tparsed = JSON.parse(text)\n\t\t} catch {\n\t\t\tthrow new SyncError('Failed to decode sync message: invalid JSON', {\n\t\t\t\tdataLength: text.length,\n\t\t\t})\n\t\t}\n\n\t\tif (!isSyncMessage(parsed)) {\n\t\t\tthrow new SyncError('Failed to decode sync message: invalid message structure', {\n\t\t\t\treceivedType:\n\t\t\t\t\ttypeof parsed === 'object' && parsed !== null\n\t\t\t\t\t\t? (parsed as Record<string, unknown>).type\n\t\t\t\t\t\t: typeof parsed,\n\t\t\t})\n\t\t}\n\n\t\treturn parsed\n\t}\n\n\tencodeOperation(op: Operation): SerializedOperation {\n\t\treturn {\n\t\t\tid: op.id,\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data,\n\t\t\tpreviousData: op.previousData,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: op.timestamp.wallTime,\n\t\t\t\tlogical: op.timestamp.logical,\n\t\t\t\tnodeId: op.timestamp.nodeId,\n\t\t\t},\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: [...op.causalDeps],\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t}\n\t}\n\n\tdecodeOperation(serialized: SerializedOperation): Operation {\n\t\treturn {\n\t\t\tid: serialized.id,\n\t\t\tnodeId: serialized.nodeId,\n\t\t\ttype: serialized.type,\n\t\t\tcollection: serialized.collection,\n\t\t\trecordId: serialized.recordId,\n\t\t\tdata: serialized.data,\n\t\t\tpreviousData: serialized.previousData,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: serialized.timestamp.wallTime,\n\t\t\t\tlogical: serialized.timestamp.logical,\n\t\t\t\tnodeId: serialized.timestamp.nodeId,\n\t\t\t},\n\t\t\tsequenceNumber: serialized.sequenceNumber,\n\t\t\tcausalDeps: [...serialized.causalDeps],\n\t\t\tschemaVersion: serialized.schemaVersion,\n\t\t}\n\t}\n}\n\n/**\n * Protobuf-based serializer for sync messages.\n */\nexport class ProtobufMessageSerializer implements MessageSerializer {\n\tencode(message: SyncMessage): Uint8Array {\n\t\tconst envelope = toProtoEnvelope(message)\n\t\treturn encodeEnvelope(envelope)\n\t}\n\n\tdecode(data: string | Uint8Array | ArrayBuffer): SyncMessage {\n\t\tconst bytes = toBytes(data)\n\t\tconst envelope = decodeEnvelope(bytes)\n\t\treturn fromProtoEnvelope(envelope)\n\t}\n\n\tencodeOperation(op: Operation): SerializedOperation {\n\t\treturn new JsonMessageSerializer().encodeOperation(op)\n\t}\n\n\tdecodeOperation(serialized: SerializedOperation): Operation {\n\t\treturn new JsonMessageSerializer().decodeOperation(serialized)\n\t}\n}\n\n/**\n * Negotiated serializer that supports runtime wire-format switching.\n */\nexport class NegotiatedMessageSerializer implements MessageSerializer {\n\tprivate readonly json = new JsonMessageSerializer()\n\tprivate readonly protobuf = new ProtobufMessageSerializer()\n\tprivate wireFormat: WireFormat\n\n\tconstructor(initialWireFormat: WireFormat = 'json') {\n\t\tthis.wireFormat = initialWireFormat\n\t}\n\n\tencode(message: SyncMessage): EncodedMessage {\n\t\tif (this.wireFormat === 'protobuf') {\n\t\t\treturn this.protobuf.encode(message)\n\t\t}\n\n\t\treturn this.json.encode(message)\n\t}\n\n\tdecode(data: string | Uint8Array | ArrayBuffer): SyncMessage {\n\t\tif (typeof data === 'string') {\n\t\t\treturn this.json.decode(data)\n\t\t}\n\n\t\ttry {\n\t\t\treturn this.protobuf.decode(data)\n\t\t} catch {\n\t\t\treturn this.json.decode(data)\n\t\t}\n\t}\n\n\tencodeOperation(op: Operation): SerializedOperation {\n\t\treturn this.json.encodeOperation(op)\n\t}\n\n\tdecodeOperation(serialized: SerializedOperation): Operation {\n\t\treturn this.json.decodeOperation(serialized)\n\t}\n\n\tsetWireFormat(format: WireFormat): void {\n\t\tthis.wireFormat = format\n\t}\n\n\tgetWireFormat(): WireFormat {\n\t\treturn this.wireFormat\n\t}\n}\n\ninterface ProtoVectorEntry {\n\tkey: string\n\tvalue: number\n}\n\ninterface ProtoTimestamp {\n\twallTime: number\n\tlogical: number\n\tnodeId: string\n}\n\ninterface ProtoOperation {\n\tid: string\n\tnodeId: string\n\ttype: string\n\tcollection: string\n\trecordId: string\n\tdataJson: string\n\tpreviousDataJson: string\n\ttimestamp: ProtoTimestamp\n\tsequenceNumber: number\n\tcausalDeps: string[]\n\tschemaVersion: number\n\thasData: boolean\n\thasPreviousData: boolean\n}\n\ninterface ProtoEnvelope {\n\ttype: SyncMessage['type']\n\tmessageId: string\n\tnodeId?: string\n\tversionVector?: ProtoVectorEntry[]\n\tschemaVersion?: number\n\tauthToken?: string\n\tsupportedWireFormats?: string[]\n\taccepted?: boolean\n\trejectReason?: string\n\tselectedWireFormat?: string\n\toperations?: ProtoOperation[]\n\tisFinal?: boolean\n\tbatchIndex?: number\n\tacknowledgedMessageId?: string\n\tlastSequenceNumber?: number\n\terrorCode?: string\n\terrorMessage?: string\n\tretriable?: boolean\n}\n\nfunction toProtoEnvelope(message: SyncMessage): ProtoEnvelope {\n\tswitch (message.type) {\n\t\tcase 'handshake':\n\t\t\treturn {\n\t\t\t\ttype: message.type,\n\t\t\t\tmessageId: message.messageId,\n\t\t\t\tnodeId: message.nodeId,\n\t\t\t\tversionVector: Object.entries(message.versionVector).map(([key, value]) => ({ key, value })),\n\t\t\t\tschemaVersion: message.schemaVersion,\n\t\t\t\tauthToken: message.authToken,\n\t\t\t\tsupportedWireFormats: message.supportedWireFormats,\n\t\t\t}\n\t\tcase 'handshake-response':\n\t\t\treturn {\n\t\t\t\ttype: message.type,\n\t\t\t\tmessageId: message.messageId,\n\t\t\t\tnodeId: message.nodeId,\n\t\t\t\tversionVector: Object.entries(message.versionVector).map(([key, value]) => ({ key, value })),\n\t\t\t\tschemaVersion: message.schemaVersion,\n\t\t\t\taccepted: message.accepted,\n\t\t\t\trejectReason: message.rejectReason,\n\t\t\t\tselectedWireFormat: message.selectedWireFormat,\n\t\t\t}\n\t\tcase 'operation-batch':\n\t\t\treturn {\n\t\t\t\ttype: message.type,\n\t\t\t\tmessageId: message.messageId,\n\t\t\t\toperations: message.operations.map(serializeProtoOperation),\n\t\t\t\tisFinal: message.isFinal,\n\t\t\t\tbatchIndex: message.batchIndex,\n\t\t\t}\n\t\tcase 'acknowledgment':\n\t\t\treturn {\n\t\t\t\ttype: message.type,\n\t\t\t\tmessageId: message.messageId,\n\t\t\t\tacknowledgedMessageId: message.acknowledgedMessageId,\n\t\t\t\tlastSequenceNumber: message.lastSequenceNumber,\n\t\t\t}\n\t\tcase 'error':\n\t\t\treturn {\n\t\t\t\ttype: message.type,\n\t\t\t\tmessageId: message.messageId,\n\t\t\t\terrorCode: message.code,\n\t\t\t\terrorMessage: message.message,\n\t\t\t\tretriable: message.retriable,\n\t\t\t}\n\t}\n}\n\nfunction fromProtoEnvelope(envelope: ProtoEnvelope): SyncMessage {\n\tswitch (envelope.type) {\n\t\tcase 'handshake':\n\t\t\treturn {\n\t\t\t\ttype: 'handshake',\n\t\t\t\tmessageId: envelope.messageId,\n\t\t\t\tnodeId: envelope.nodeId ?? '',\n\t\t\t\tversionVector: Object.fromEntries((envelope.versionVector ?? []).map((entry) => [entry.key, entry.value])),\n\t\t\t\tschemaVersion: envelope.schemaVersion ?? 0,\n\t\t\t\tauthToken: envelope.authToken,\n\t\t\t\tsupportedWireFormats:\n\t\t\t\t\tenvelope.supportedWireFormats?.filter(\n\t\t\t\t\t\t(format): format is WireFormat => format === 'json' || format === 'protobuf',\n\t\t\t\t\t),\n\t\t\t}\n\t\tcase 'handshake-response':\n\t\t\treturn {\n\t\t\t\ttype: 'handshake-response',\n\t\t\t\tmessageId: envelope.messageId,\n\t\t\t\tnodeId: envelope.nodeId ?? '',\n\t\t\t\tversionVector: Object.fromEntries((envelope.versionVector ?? []).map((entry) => [entry.key, entry.value])),\n\t\t\t\tschemaVersion: envelope.schemaVersion ?? 0,\n\t\t\t\taccepted: envelope.accepted ?? false,\n\t\t\t\trejectReason: envelope.rejectReason,\n\t\t\t\tselectedWireFormat:\n\t\t\t\t\tenvelope.selectedWireFormat === 'json' || envelope.selectedWireFormat === 'protobuf'\n\t\t\t\t\t\t? envelope.selectedWireFormat\n\t\t\t\t\t\t: undefined,\n\t\t\t}\n\t\tcase 'operation-batch':\n\t\t\treturn {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: envelope.messageId,\n\t\t\t\toperations: (envelope.operations ?? []).map(deserializeProtoOperation),\n\t\t\t\tisFinal: envelope.isFinal ?? false,\n\t\t\t\tbatchIndex: envelope.batchIndex ?? 0,\n\t\t\t}\n\t\tcase 'acknowledgment':\n\t\t\treturn {\n\t\t\t\ttype: 'acknowledgment',\n\t\t\t\tmessageId: envelope.messageId,\n\t\t\t\tacknowledgedMessageId: envelope.acknowledgedMessageId ?? '',\n\t\t\t\tlastSequenceNumber: envelope.lastSequenceNumber ?? 0,\n\t\t\t}\n\t\tcase 'error':\n\t\t\treturn {\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: envelope.messageId,\n\t\t\t\tcode: envelope.errorCode ?? 'UNKNOWN',\n\t\t\t\tmessage: envelope.errorMessage ?? 'Unknown error',\n\t\t\t\tretriable: envelope.retriable ?? false,\n\t\t\t}\n\t\tdefault:\n\t\t\tthrow new SyncError('Failed to decode sync message: unknown protobuf type', {\n\t\t\t\ttype: envelope.type,\n\t\t\t})\n\t}\n}\n\nfunction serializeProtoOperation(operation: SerializedOperation): ProtoOperation {\n\treturn {\n\t\tid: operation.id,\n\t\tnodeId: operation.nodeId,\n\t\ttype: operation.type,\n\t\tcollection: operation.collection,\n\t\trecordId: operation.recordId,\n\t\tdataJson: operation.data === null ? '' : JSON.stringify(operation.data),\n\t\tpreviousDataJson:\n\t\t\toperation.previousData === null ? '' : JSON.stringify(operation.previousData),\n\t\ttimestamp: {\n\t\t\twallTime: operation.timestamp.wallTime,\n\t\t\tlogical: operation.timestamp.logical,\n\t\t\tnodeId: operation.timestamp.nodeId,\n\t\t},\n\t\tsequenceNumber: operation.sequenceNumber,\n\t\tcausalDeps: [...operation.causalDeps],\n\t\tschemaVersion: operation.schemaVersion,\n\t\thasData: operation.data !== null,\n\t\thasPreviousData: operation.previousData !== null,\n\t}\n}\n\nfunction deserializeProtoOperation(operation: ProtoOperation): SerializedOperation {\n\treturn {\n\t\tid: operation.id,\n\t\tnodeId: operation.nodeId,\n\t\ttype: operation.type as SerializedOperation['type'],\n\t\tcollection: operation.collection,\n\t\trecordId: operation.recordId,\n\t\tdata: operation.hasData ? (JSON.parse(operation.dataJson) as Record<string, unknown>) : null,\n\t\tpreviousData: operation.hasPreviousData\n\t\t\t? (JSON.parse(operation.previousDataJson) as Record<string, unknown>)\n\t\t\t: null,\n\t\ttimestamp: {\n\t\t\twallTime: operation.timestamp.wallTime,\n\t\t\tlogical: operation.timestamp.logical,\n\t\t\tnodeId: operation.timestamp.nodeId,\n\t\t},\n\t\tsequenceNumber: operation.sequenceNumber,\n\t\tcausalDeps: [...operation.causalDeps],\n\t\tschemaVersion: operation.schemaVersion,\n\t}\n}\n\nfunction decodeTextPayload(data: string | Uint8Array | ArrayBuffer): string {\n\tif (typeof data === 'string') return data\n\treturn new TextDecoder().decode(toBytes(data))\n}\n\nfunction toBytes(data: string | Uint8Array | ArrayBuffer): Uint8Array {\n\tif (typeof data === 'string') {\n\t\treturn new TextEncoder().encode(data)\n\t}\n\n\tif (data instanceof Uint8Array) {\n\t\treturn data\n\t}\n\n\tif (data instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(data)\n\t}\n\n\tthrow new SyncError('Unsupported sync payload type', { receivedType: typeof data })\n}\n\nfunction encodeEnvelope(envelope: ProtoEnvelope): Uint8Array {\n\tconst writer = Writer.create()\n\tif (envelope.type.length > 0) writer.uint32(10).string(envelope.type)\n\tif (envelope.messageId.length > 0) writer.uint32(18).string(envelope.messageId)\n\tif (envelope.nodeId && envelope.nodeId.length > 0) writer.uint32(26).string(envelope.nodeId)\n\tfor (const entry of envelope.versionVector ?? []) {\n\t\twriter.uint32(34).fork()\n\t\twriter.uint32(10).string(entry.key)\n\t\twriter.uint32(16).int64(entry.value)\n\t\twriter.ldelim()\n\t}\n\tif (envelope.schemaVersion !== undefined) writer.uint32(40).int32(envelope.schemaVersion)\n\tif (envelope.authToken && envelope.authToken.length > 0) writer.uint32(50).string(envelope.authToken)\n\tfor (const format of envelope.supportedWireFormats ?? []) {\n\t\twriter.uint32(58).string(format)\n\t}\n\tif (envelope.accepted !== undefined) writer.uint32(64).bool(envelope.accepted)\n\tif (envelope.rejectReason && envelope.rejectReason.length > 0) writer.uint32(74).string(envelope.rejectReason)\n\tif (envelope.selectedWireFormat && envelope.selectedWireFormat.length > 0) {\n\t\twriter.uint32(82).string(envelope.selectedWireFormat)\n\t}\n\tfor (const operation of envelope.operations ?? []) {\n\t\twriter.uint32(90).fork()\n\t\tencodeProtoOperation(writer, operation)\n\t\twriter.ldelim()\n\t}\n\tif (envelope.isFinal !== undefined) writer.uint32(96).bool(envelope.isFinal)\n\tif (envelope.batchIndex !== undefined) writer.uint32(104).uint32(envelope.batchIndex)\n\tif (envelope.acknowledgedMessageId && envelope.acknowledgedMessageId.length > 0) {\n\t\twriter.uint32(114).string(envelope.acknowledgedMessageId)\n\t}\n\tif (envelope.lastSequenceNumber !== undefined) writer.uint32(120).int64(envelope.lastSequenceNumber)\n\tif (envelope.errorCode && envelope.errorCode.length > 0) writer.uint32(130).string(envelope.errorCode)\n\tif (envelope.errorMessage && envelope.errorMessage.length > 0) {\n\t\twriter.uint32(138).string(envelope.errorMessage)\n\t}\n\tif (envelope.retriable !== undefined) writer.uint32(144).bool(envelope.retriable)\n\treturn writer.finish()\n}\n\nfunction decodeEnvelope(bytes: Uint8Array): ProtoEnvelope {\n\tconst reader = Reader.create(bytes)\n\tconst envelope: ProtoEnvelope = { type: 'error', messageId: '' }\n\n\twhile (reader.pos < reader.len) {\n\t\tconst tag = reader.uint32()\n\t\tswitch (tag >>> 3) {\n\t\t\tcase 1:\n\t\t\t\tenvelope.type = reader.string() as SyncMessage['type']\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\tenvelope.messageId = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 3:\n\t\t\t\tenvelope.nodeId = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 4:\n\t\t\t\tenvelope.versionVector = [...(envelope.versionVector ?? []), decodeVectorEntry(reader, reader.uint32())]\n\t\t\t\tbreak\n\t\t\tcase 5:\n\t\t\t\tenvelope.schemaVersion = reader.int32()\n\t\t\t\tbreak\n\t\t\tcase 6:\n\t\t\t\tenvelope.authToken = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 7:\n\t\t\t\tenvelope.supportedWireFormats = [...(envelope.supportedWireFormats ?? []), reader.string()]\n\t\t\t\tbreak\n\t\t\tcase 8:\n\t\t\t\tenvelope.accepted = reader.bool()\n\t\t\t\tbreak\n\t\t\tcase 9:\n\t\t\t\tenvelope.rejectReason = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 10:\n\t\t\t\tenvelope.selectedWireFormat = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 11:\n\t\t\t\tenvelope.operations = [...(envelope.operations ?? []), decodeProtoOperation(reader, reader.uint32())]\n\t\t\t\tbreak\n\t\t\tcase 12:\n\t\t\t\tenvelope.isFinal = reader.bool()\n\t\t\t\tbreak\n\t\t\tcase 13:\n\t\t\t\tenvelope.batchIndex = reader.uint32()\n\t\t\t\tbreak\n\t\t\tcase 14:\n\t\t\t\tenvelope.acknowledgedMessageId = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 15:\n\t\t\t\tenvelope.lastSequenceNumber = longToNumber(reader.int64())\n\t\t\t\tbreak\n\t\t\tcase 16:\n\t\t\t\tenvelope.errorCode = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 17:\n\t\t\t\tenvelope.errorMessage = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 18:\n\t\t\t\tenvelope.retriable = reader.bool()\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\treader.skipType(tag & 7)\n\t\t}\n\t}\n\n\treturn envelope\n}\n\nfunction encodeProtoOperation(writer: Writer, operation: ProtoOperation): void {\n\tif (operation.id.length > 0) writer.uint32(10).string(operation.id)\n\tif (operation.nodeId.length > 0) writer.uint32(18).string(operation.nodeId)\n\tif (operation.type.length > 0) writer.uint32(26).string(operation.type)\n\tif (operation.collection.length > 0) writer.uint32(34).string(operation.collection)\n\tif (operation.recordId.length > 0) writer.uint32(42).string(operation.recordId)\n\tif (operation.dataJson.length > 0) writer.uint32(50).string(operation.dataJson)\n\tif (operation.previousDataJson.length > 0) writer.uint32(58).string(operation.previousDataJson)\n\twriter.uint32(66).fork()\n\twriter.uint32(8).int64(operation.timestamp.wallTime)\n\twriter.uint32(16).uint32(operation.timestamp.logical)\n\twriter.uint32(26).string(operation.timestamp.nodeId)\n\twriter.ldelim()\n\twriter.uint32(72).int64(operation.sequenceNumber)\n\tfor (const dep of operation.causalDeps) {\n\t\twriter.uint32(82).string(dep)\n\t}\n\twriter.uint32(88).int32(operation.schemaVersion)\n\twriter.uint32(96).bool(operation.hasData)\n\twriter.uint32(104).bool(operation.hasPreviousData)\n}\n\nfunction decodeProtoOperation(reader: Reader, length: number): ProtoOperation {\n\tconst end = reader.pos + length\n\tconst operation: ProtoOperation = {\n\t\tid: '',\n\t\tnodeId: '',\n\t\ttype: 'insert',\n\t\tcollection: '',\n\t\trecordId: '',\n\t\tdataJson: '',\n\t\tpreviousDataJson: '',\n\t\ttimestamp: { wallTime: 0, logical: 0, nodeId: '' },\n\t\tsequenceNumber: 0,\n\t\tcausalDeps: [],\n\t\tschemaVersion: 0,\n\t\thasData: false,\n\t\thasPreviousData: false,\n\t}\n\n\twhile (reader.pos < end) {\n\t\tconst tag = reader.uint32()\n\t\tswitch (tag >>> 3) {\n\t\t\tcase 1:\n\t\t\t\toperation.id = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\toperation.nodeId = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 3:\n\t\t\t\toperation.type = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 4:\n\t\t\t\toperation.collection = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 5:\n\t\t\t\toperation.recordId = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 6:\n\t\t\t\toperation.dataJson = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 7:\n\t\t\t\toperation.previousDataJson = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 8: {\n\t\t\t\tconst timestampEnd = reader.pos + reader.uint32()\n\t\t\t\twhile (reader.pos < timestampEnd) {\n\t\t\t\t\tconst timestampTag = reader.uint32()\n\t\t\t\t\tswitch (timestampTag >>> 3) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\toperation.timestamp.wallTime = longToNumber(reader.int64())\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\toperation.timestamp.logical = reader.uint32()\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\toperation.timestamp.nodeId = reader.string()\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\treader.skipType(timestampTag & 7)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 9:\n\t\t\t\toperation.sequenceNumber = longToNumber(reader.int64())\n\t\t\t\tbreak\n\t\t\tcase 10:\n\t\t\t\toperation.causalDeps.push(reader.string())\n\t\t\t\tbreak\n\t\t\tcase 11:\n\t\t\t\toperation.schemaVersion = reader.int32()\n\t\t\t\tbreak\n\t\t\tcase 12:\n\t\t\t\toperation.hasData = reader.bool()\n\t\t\t\tbreak\n\t\t\tcase 13:\n\t\t\t\toperation.hasPreviousData = reader.bool()\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\treader.skipType(tag & 7)\n\t\t}\n\t}\n\n\treturn operation\n}\n\nfunction decodeVectorEntry(reader: Reader, length: number): ProtoVectorEntry {\n\tconst end = reader.pos + length\n\tconst entry: ProtoVectorEntry = { key: '', value: 0 }\n\twhile (reader.pos < end) {\n\t\tconst tag = reader.uint32()\n\t\tswitch (tag >>> 3) {\n\t\t\tcase 1:\n\t\t\t\tentry.key = reader.string()\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\tentry.value = longToNumber(reader.int64())\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\treader.skipType(tag & 7)\n\t\t}\n\t}\n\treturn entry\n}\n\nfunction longToNumber(value: unknown): number {\n\tif (typeof value === 'number') return value\n\tif (typeof value === 'string') return Number.parseInt(value, 10)\n\tif (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'toNumber' in value &&\n\t\ttypeof (value as { toNumber: unknown }).toNumber === 'function'\n\t) {\n\t\treturn (value as { toNumber(): number }).toNumber()\n\t}\n\n\tthrow new SyncError('Failed to decode int64 value', {\n\t\treceivedType: typeof value,\n\t})\n}\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '../protocol/messages'\nimport { JsonMessageSerializer } from '../protocol/serializer'\nimport type { MessageSerializer } from '../protocol/serializer'\nimport type {\n\tSyncTransport,\n\tTransportCloseHandler,\n\tTransportErrorHandler,\n\tTransportMessageHandler,\n\tTransportOptions,\n} from './transport'\n\n/**\n * WebSocket event interface for dependency injection.\n * Matches the subset of the browser WebSocket API that we need.\n */\nexport interface WebSocketLike {\n\treadonly readyState: number\n\tsend(data: string | Uint8Array): void\n\tclose(code?: number, reason?: string): void\n\tonopen: ((event: unknown) => void) | null\n\tonmessage: ((event: { data: unknown }) => void) | null\n\tonclose: ((event: { reason: string; code: number }) => void) | null\n\tonerror: ((event: unknown) => void) | null\n}\n\n/**\n * Constructor for WebSocket-like objects. Allows injection of mock WebSocket for testing.\n */\nexport type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike\n\n/**\n * Options for the WebSocket transport.\n */\nexport interface WebSocketTransportOptions {\n\t/** Custom serializer. Defaults to JSON. */\n\tserializer?: MessageSerializer\n\t/** Injectable WebSocket constructor for testing. Defaults to globalThis.WebSocket. */\n\tWebSocketImpl?: WebSocketConstructor\n}\n\n// WebSocket readyState constants\nconst WS_OPEN = 1\n\n/**\n * WebSocket-based sync transport implementation.\n */\nexport class WebSocketTransport implements SyncTransport {\n\tprivate ws: WebSocketLike | null = null\n\tprivate messageHandler: TransportMessageHandler | null = null\n\tprivate closeHandler: TransportCloseHandler | null = null\n\tprivate errorHandler: TransportErrorHandler | null = null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly WebSocketImpl: WebSocketConstructor\n\n\tconstructor(options?: WebSocketTransportOptions) {\n\t\tthis.serializer = options?.serializer ?? new JsonMessageSerializer()\n\n\t\tif (options?.WebSocketImpl) {\n\t\t\tthis.WebSocketImpl = options.WebSocketImpl\n\t\t} else if (typeof globalThis.WebSocket !== 'undefined') {\n\t\t\tthis.WebSocketImpl = globalThis.WebSocket as unknown as WebSocketConstructor\n\t\t} else {\n\t\t\t// Deferred — will throw on connect() if no implementation available\n\t\t\tthis.WebSocketImpl = null as unknown as WebSocketConstructor\n\t\t}\n\t}\n\n\tasync connect(url: string, options?: TransportOptions): Promise<void> {\n\t\tif (!this.WebSocketImpl) {\n\t\t\tthrow new SyncError('WebSocket is not available in this environment', {\n\t\t\t\thint: 'Provide a WebSocketImpl option or use a polyfill',\n\t\t\t})\n\t\t}\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\t// Append auth token as query param if provided\n\t\t\t\tconst connectUrl = options?.authToken\n\t\t\t\t\t? `${url}${url.includes('?') ? '&' : '?'}token=${encodeURIComponent(options.authToken)}`\n\t\t\t\t\t: url\n\n\t\t\t\tconst ws = new this.WebSocketImpl(connectUrl)\n\t\t\t\tthis.ws = ws\n\n\t\t\t\tws.onopen = () => {\n\t\t\t\t\tresolve()\n\t\t\t\t}\n\n\t\t\t\tws.onmessage = (event: { data: unknown }) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof event.data !== 'string' &&\n\t\t\t\t\t\t\t!(event.data instanceof Uint8Array) &&\n\t\t\t\t\t\t\t!(event.data instanceof ArrayBuffer)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst message = this.serializer.decode(event.data)\n\t\t\t\t\t\tthis.messageHandler?.(message)\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.errorHandler?.(new SyncError('Failed to decode incoming message'))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tws.onclose = (event: { reason: string; code: number }) => {\n\t\t\t\t\tthis.ws = null\n\t\t\t\t\tthis.closeHandler?.(event.reason || `WebSocket closed with code ${event.code}`)\n\t\t\t\t}\n\n\t\t\t\tws.onerror = (event: unknown) => {\n\t\t\t\t\tconst err = new SyncError('WebSocket error', {\n\t\t\t\t\t\turl,\n\t\t\t\t\t})\n\t\t\t\t\tthis.errorHandler?.(err)\n\t\t\t\t\t// If we haven't connected yet, reject the connect promise\n\t\t\t\t\tif (!this.isConnected()) {\n\t\t\t\t\t\tthis.ws = null\n\t\t\t\t\t\treject(err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\treject(\n\t\t\t\t\terr instanceof SyncError\n\t\t\t\t\t\t? err\n\t\t\t\t\t\t: new SyncError('Failed to create WebSocket', {\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\terror: String(err),\n\t\t\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.ws) {\n\t\t\tthis.ws.onclose = null // Prevent close handler firing for intentional disconnect\n\t\t\tthis.ws.close(1000, 'Client disconnecting')\n\t\t\tthis.ws = null\n\t\t}\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (!this.ws || this.ws.readyState !== WS_OPEN) {\n\t\t\tthrow new SyncError('Cannot send message: WebSocket is not connected', {\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\t\tconst encoded = this.serializer.encode(message)\n\t\tthis.ws.send(encoded)\n\t}\n\n\tonMessage(handler: TransportMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: TransportCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: TransportErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.ws !== null && this.ws.readyState === WS_OPEN\n\t}\n}\n","import { SyncError } from '@korajs/core'\nimport { NegotiatedMessageSerializer } from '../protocol/serializer'\nimport type { MessageSerializer } from '../protocol/serializer'\nimport { WebSocketTransport } from './websocket-transport'\nimport type { SyncTransport, TransportCloseHandler, TransportErrorHandler, TransportMessageHandler, TransportOptions } from './transport'\n\nconst DEFAULT_RETRY_DELAY_MS = 250\n\nexport interface HttpLongPollingTransportOptions {\n\tserializer?: MessageSerializer\n\tfetchImpl?: typeof fetch\n\tretryDelayMs?: number\n\tpreferWebSocket?: boolean\n\twebSocketFactory?: () => SyncTransport\n}\n\n/**\n * HTTP long-polling transport with optional WebSocket upgrade.\n */\nexport class HttpLongPollingTransport implements SyncTransport {\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly fetchImpl: typeof fetch\n\tprivate readonly retryDelayMs: number\n\tprivate readonly preferWebSocket: boolean\n\tprivate readonly webSocketFactory: () => SyncTransport\n\n\tprivate messageHandler: TransportMessageHandler | null = null\n\tprivate closeHandler: TransportCloseHandler | null = null\n\tprivate errorHandler: TransportErrorHandler | null = null\n\n\tprivate connected = false\n\tprivate polling = false\n\tprivate url: string | null = null\n\tprivate authToken: string | undefined\n\tprivate pollAbort: AbortController | null = null\n\tprivate upgradedTransport: SyncTransport | null = null\n\n\tconstructor(options?: HttpLongPollingTransportOptions) {\n\t\tthis.serializer = options?.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.fetchImpl = options?.fetchImpl ?? fetch\n\t\tthis.retryDelayMs = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS\n\t\tthis.preferWebSocket = options?.preferWebSocket ?? true\n\t\tthis.webSocketFactory = options?.webSocketFactory ?? (() => new WebSocketTransport({ serializer: this.serializer }))\n\t}\n\n\tasync connect(url: string, options?: TransportOptions): Promise<void> {\n\t\tif (this.connected) {\n\t\t\tthrow new SyncError('HTTP long-poll transport already connected', { url })\n\t\t}\n\n\t\tthis.url = normalizeHttpUrl(url)\n\t\tthis.authToken = options?.authToken\n\n\t\tif (this.preferWebSocket) {\n\t\t\tconst upgraded = await this.tryUpgradeToWebSocket(url, options)\n\t\t\tif (upgraded) {\n\t\t\t\tthis.upgradedTransport = upgraded\n\t\t\t\tthis.connected = true\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.connected = true\n\t\tthis.polling = true\n\t\tthis.pollAbort = new AbortController()\n\t\tvoid this.runPollLoop()\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.upgradedTransport) {\n\t\t\tawait this.upgradedTransport.disconnect()\n\t\t\tthis.upgradedTransport = null\n\t\t}\n\n\t\tthis.connected = false\n\t\tthis.polling = false\n\t\tthis.pollAbort?.abort()\n\t\tthis.pollAbort = null\n\t\tthis.url = null\n\t}\n\n\tsend(message: import('../protocol/messages').SyncMessage): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('Cannot send message: HTTP long-poll transport is not connected', {\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\n\t\tif (this.upgradedTransport) {\n\t\t\tthis.upgradedTransport.send(message)\n\t\t\treturn\n\t\t}\n\n\t\tvoid this.postMessage(message)\n\t}\n\n\tonMessage(handler: TransportMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t\tif (this.upgradedTransport) {\n\t\t\tthis.upgradedTransport.onMessage(handler)\n\t\t}\n\t}\n\n\tonClose(handler: TransportCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t\tif (this.upgradedTransport) {\n\t\t\tthis.upgradedTransport.onClose(handler)\n\t\t}\n\t}\n\n\tonError(handler: TransportErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t\tif (this.upgradedTransport) {\n\t\t\tthis.upgradedTransport.onError(handler)\n\t\t}\n\t}\n\n\tisConnected(): boolean {\n\t\tif (this.upgradedTransport) {\n\t\t\treturn this.upgradedTransport.isConnected()\n\t\t}\n\t\treturn this.connected\n\t}\n\n\tprivate async tryUpgradeToWebSocket(url: string, options?: TransportOptions): Promise<SyncTransport | null> {\n\t\tconst wsTransport = this.webSocketFactory()\n\n\t\tif (this.messageHandler) wsTransport.onMessage(this.messageHandler)\n\t\tif (this.closeHandler) wsTransport.onClose(this.closeHandler)\n\t\tif (this.errorHandler) wsTransport.onError(this.errorHandler)\n\n\t\ttry {\n\t\t\tawait wsTransport.connect(normalizeWebSocketUrl(url), options)\n\t\t\treturn wsTransport\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tprivate async postMessage(message: import('../protocol/messages').SyncMessage): Promise<void> {\n\t\tif (!this.url) return\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tconst headers = new Headers()\n\t\theaders.set('accept', 'application/json, application/x-protobuf')\n\t\tif (this.authToken) {\n\t\t\theaders.set('authorization', `Bearer ${this.authToken}`)\n\t\t}\n\n\t\tconst isBinary = encoded instanceof Uint8Array\n\t\theaders.set('content-type', isBinary ? 'application/x-protobuf' : 'application/json')\n\n\t\ttry {\n\t\t\tconst requestBody = isBinary ? toArrayBuffer(encoded) : encoded\n\n\t\t\tconst response = await this.fetchImpl(this.url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders,\n\t\t\t\tbody: requestBody,\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new SyncError('HTTP transport send failed', {\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\tmessageType: message.type,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t}\n\t}\n\n\tprivate async runPollLoop(): Promise<void> {\n\t\twhile (this.polling && this.connected && this.url) {\n\t\t\ttry {\n\t\t\t\tconst response = await this.fetchImpl(this.url, {\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\theaders: this.makePollHeaders(),\n\t\t\t\t\tsignal: this.pollAbort?.signal,\n\t\t\t\t})\n\n\t\t\t\tif (response.status === 204) {\n\t\t\t\t\tawait sleep(this.retryDelayMs)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new SyncError('HTTP long-poll request failed', {\n\t\t\t\t\t\tstatus: response.status,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst payload = await readResponsePayload(response)\n\t\t\t\tif (payload === null) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tconst message = this.serializer.decode(payload)\n\t\t\t\tthis.messageHandler?.(message)\n\t\t\t} catch (error) {\n\t\t\t\tif (!this.connected || !this.polling) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tif (isAbortError(error)) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t\t\tawait sleep(this.retryDelayMs)\n\t\t\t}\n\t\t}\n\n\t\tif (!this.connected) {\n\t\t\tthis.closeHandler?.('http long-polling disconnected')\n\t\t}\n\t}\n\n\tprivate makePollHeaders(): Headers {\n\t\tconst headers = new Headers()\n\t\theaders.set('accept', 'application/json, application/x-protobuf')\n\t\tif (this.authToken) {\n\t\t\theaders.set('authorization', `Bearer ${this.authToken}`)\n\t\t}\n\t\treturn headers\n\t}\n}\n\nfunction normalizeHttpUrl(url: string): string {\n\tif (url.startsWith('http://') || url.startsWith('https://')) {\n\t\treturn url\n\t}\n\n\tif (url.startsWith('ws://')) {\n\t\treturn `http://${url.slice('ws://'.length)}`\n\t}\n\n\tif (url.startsWith('wss://')) {\n\t\treturn `https://${url.slice('wss://'.length)}`\n\t}\n\n\treturn url\n}\n\nfunction normalizeWebSocketUrl(url: string): string {\n\tif (url.startsWith('ws://') || url.startsWith('wss://')) {\n\t\treturn url\n\t}\n\n\tif (url.startsWith('http://')) {\n\t\treturn `ws://${url.slice('http://'.length)}`\n\t}\n\n\tif (url.startsWith('https://')) {\n\t\treturn `wss://${url.slice('https://'.length)}`\n\t}\n\n\treturn url\n}\n\nasync function readResponsePayload(response: Response): Promise<string | Uint8Array | null> {\n\tconst contentType = response.headers.get('content-type') ?? ''\n\tif (contentType.includes('application/x-protobuf')) {\n\t\tconst buffer = await response.arrayBuffer()\n\t\tif (buffer.byteLength === 0) return null\n\t\treturn new Uint8Array(buffer)\n\t}\n\n\tconst text = await response.text()\n\tif (text.length === 0) return null\n\treturn text\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === 'object' &&\n\t\terror !== null &&\n\t\t'name' in error &&\n\t\t(error as { name?: string }).name === 'AbortError'\n\t)\n}\n\nfunction toArrayBuffer(data: Uint8Array): ArrayBuffer {\n\tconst copied = new Uint8Array(data.byteLength)\n\tcopied.set(data)\n\treturn copied.buffer\n}\n","import type { SyncMessage } from '../protocol/messages'\nimport type {\n\tSyncTransport,\n\tTransportCloseHandler,\n\tTransportErrorHandler,\n\tTransportMessageHandler,\n\tTransportOptions,\n} from './transport'\n\n/**\n * Configuration for the chaos transport.\n */\nexport interface ChaosConfig {\n\t/** Probability of dropping a message (0-1). Defaults to 0. */\n\tdropRate?: number\n\t/** Probability of duplicating a message (0-1). Defaults to 0. */\n\tduplicateRate?: number\n\t/** Probability of reordering messages (0-1). Defaults to 0. */\n\treorderRate?: number\n\t/** Maximum latency in ms for delayed messages. Defaults to 0. */\n\tmaxLatency?: number\n\t/** Injectable random source for deterministic testing. Returns value in [0, 1). */\n\trandomSource?: () => number\n}\n\n/**\n * Chaos transport that wraps another transport and injects faults.\n * Used for testing sync convergence under unreliable network conditions.\n *\n * Supports message dropping, duplication, reordering, and latency injection.\n * All random behavior is injectable for deterministic, reproducible tests.\n */\nexport class ChaosTransport implements SyncTransport {\n\tprivate readonly inner: SyncTransport\n\tprivate readonly dropRate: number\n\tprivate readonly duplicateRate: number\n\tprivate readonly reorderRate: number\n\tprivate readonly maxLatency: number\n\tprivate readonly random: () => number\n\n\tprivate messageHandler: TransportMessageHandler | null = null\n\tprivate reorderBuffer: SyncMessage[] = []\n\tprivate timers: ReturnType<typeof setTimeout>[] = []\n\n\tconstructor(inner: SyncTransport, config?: ChaosConfig) {\n\t\tthis.inner = inner\n\t\tthis.dropRate = config?.dropRate ?? 0\n\t\tthis.duplicateRate = config?.duplicateRate ?? 0\n\t\tthis.reorderRate = config?.reorderRate ?? 0\n\t\tthis.maxLatency = config?.maxLatency ?? 0\n\t\tthis.random = config?.randomSource ?? Math.random\n\t}\n\n\tasync connect(url: string, options?: TransportOptions): Promise<void> {\n\t\t// Intercept incoming messages from the inner transport\n\t\tthis.inner.onMessage((msg) => this.handleIncoming(msg))\n\t\treturn this.inner.connect(url, options)\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\t// Flush reorder buffer\n\t\tthis.flushReorderBuffer()\n\t\t// Clear pending timers\n\t\tfor (const timer of this.timers) {\n\t\t\tclearTimeout(timer)\n\t\t}\n\t\tthis.timers = []\n\t\treturn this.inner.disconnect()\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\t// Apply chaos to outgoing messages\n\t\tif (this.random() < this.dropRate) {\n\t\t\treturn // Dropped\n\t\t}\n\n\t\tif (this.random() < this.reorderRate) {\n\t\t\tthis.reorderBuffer.push(message)\n\t\t\t// Flush buffer on next non-reordered send\n\t\t\treturn\n\t\t}\n\n\t\t// Flush any buffered messages first\n\t\tthis.flushReorderBuffer()\n\n\t\tthis.inner.send(message)\n\n\t\t// Duplicate?\n\t\tif (this.random() < this.duplicateRate) {\n\t\t\tthis.inner.send(message)\n\t\t}\n\t}\n\n\tonMessage(handler: TransportMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: TransportCloseHandler): void {\n\t\tthis.inner.onClose(handler)\n\t}\n\n\tonError(handler: TransportErrorHandler): void {\n\t\tthis.inner.onError(handler)\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.inner.isConnected()\n\t}\n\n\tprivate handleIncoming(message: SyncMessage): void {\n\t\tif (!this.messageHandler) return\n\n\t\t// Apply chaos to incoming messages\n\t\tif (this.random() < this.dropRate) {\n\t\t\treturn // Dropped\n\t\t}\n\n\t\tif (this.maxLatency > 0) {\n\t\t\tconst delay = Math.floor(this.random() * this.maxLatency)\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.deliverIncoming(message)\n\t\t\t}, delay)\n\t\t\tthis.timers.push(timer)\n\t\t\treturn\n\t\t}\n\n\t\tthis.deliverIncoming(message)\n\t}\n\n\tprivate deliverIncoming(message: SyncMessage): void {\n\t\tif (!this.messageHandler) return\n\n\t\tthis.messageHandler(message)\n\n\t\t// Duplicate incoming?\n\t\tif (this.random() < this.duplicateRate) {\n\t\t\tthis.messageHandler(message)\n\t\t}\n\t}\n\n\tprivate flushReorderBuffer(): void {\n\t\t// Send buffered messages in random order\n\t\tconst buffer = [...this.reorderBuffer]\n\t\tthis.reorderBuffer = []\n\n\t\t// Fisher-Yates shuffle with injectable random\n\t\tfor (let i = buffer.length - 1; i > 0; i--) {\n\t\t\tconst j = Math.floor(this.random() * (i + 1))\n\t\t\tconst temp = buffer[i] as SyncMessage\n\t\t\tbuffer[i] = buffer[j] as SyncMessage\n\t\t\tbuffer[j] = temp\n\t\t}\n\n\t\tfor (const msg of buffer) {\n\t\t\tthis.inner.send(msg)\n\t\t}\n\t}\n}\n","import type { KoraEventEmitter, Operation, VersionVector } from '@korajs/core'\nimport { SyncError } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type {\n\tAcknowledgmentMessage,\n\tHandshakeResponseMessage,\n\tOperationBatchMessage,\n\tSyncMessage,\n\tWireFormat,\n} from '../protocol/messages'\nimport {\n\tNegotiatedMessageSerializer,\n\tversionVectorToWire,\n\twireToVersionVector,\n} from '../protocol/serializer'\nimport type { MessageSerializer } from '../protocol/serializer'\nimport type { SyncTransport } from '../transport/transport'\nimport type { SyncConfig, SyncState, SyncStatusInfo } from '../types'\nimport type { QueueStorage } from '../types'\nimport { MemoryQueueStorage } from './memory-queue-storage'\nimport type { OutboundBatch } from './outbound-queue'\nimport { OutboundQueue } from './outbound-queue'\nimport type { SyncStore } from './sync-store'\n\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\n\n/**\n * Valid state transitions for the sync engine state machine.\n */\nconst VALID_TRANSITIONS: Record<SyncState, SyncState[]> = {\n\tdisconnected: ['connecting'],\n\tconnecting: ['handshaking', 'error', 'disconnected'],\n\thandshaking: ['syncing', 'error', 'disconnected'],\n\tsyncing: ['streaming', 'error', 'disconnected'],\n\tstreaming: ['disconnected', 'error'],\n\terror: ['disconnected'],\n}\n\n/**\n * Options for creating a SyncEngine.\n */\nexport interface SyncEngineOptions {\n\t/** Transport implementation (WebSocket, memory, etc.) */\n\ttransport: SyncTransport\n\t/** Local store implementing SyncStore */\n\tstore: SyncStore\n\t/** Sync configuration */\n\tconfig: SyncConfig\n\t/** Message serializer. Defaults to JSON. */\n\tserializer?: MessageSerializer\n\t/** Event emitter for DevTools integration */\n\temitter?: KoraEventEmitter\n\t/** Queue storage for persistent outbound queue. Defaults to in-memory. */\n\tqueueStorage?: QueueStorage\n}\n\nlet nextMessageId = 0\nfunction generateMessageId(): string {\n\treturn `msg-${Date.now()}-${nextMessageId++}`\n}\n\n/**\n * Core sync orchestrator. Manages the sync lifecycle:\n * disconnected → connecting → handshaking → syncing → streaming\n *\n * Coordinates handshake, delta exchange, and real-time streaming\n * between a local store and a remote sync server.\n */\nexport class SyncEngine {\n\tprivate state: SyncState = 'disconnected'\n\tprivate readonly transport: SyncTransport\n\tprivate readonly store: SyncStore\n\tprivate readonly config: SyncConfig\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly outboundQueue: OutboundQueue\n\tprivate readonly batchSize: number\n\n\tprivate remoteVector: VersionVector = new Map()\n\tprivate lastSyncedAt: number | null = null\n\tprivate currentBatch: OutboundBatch | null = null\n\n\t// Track delta exchange state\n\tprivate deltaBatchesReceived = 0\n\tprivate deltaReceiveComplete = false\n\tprivate deltaSendComplete = false\n\n\tconstructor(options: SyncEngineOptions) {\n\t\tthis.transport = options.transport\n\t\tthis.store = options.store\n\t\tthis.config = options.config\n\t\tthis.serializer = options.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.emitter = options.emitter ?? null\n\t\tthis.batchSize = options.config.batchSize ?? DEFAULT_BATCH_SIZE\n\n\t\tconst queueStorage = options.queueStorage ?? new MemoryQueueStorage()\n\t\tthis.outboundQueue = new OutboundQueue(queueStorage)\n\t}\n\n\t/**\n\t * Start the sync engine: connect → handshake → delta exchange → streaming.\n\t */\n\tasync start(): Promise<void> {\n\t\tif (this.state !== 'disconnected') {\n\t\t\tthrow new SyncError('Cannot start sync engine: not in disconnected state', {\n\t\t\t\tcurrentState: this.state,\n\t\t\t})\n\t\t}\n\n\t\tawait this.outboundQueue.initialize()\n\n\t\t// Set up transport handlers\n\t\tthis.transport.onMessage((msg) => this.handleMessage(msg))\n\t\tthis.transport.onClose((reason) => this.handleTransportClose(reason))\n\t\tthis.transport.onError((err) => this.handleTransportError(err))\n\n\t\tthis.transitionTo('connecting')\n\n\t\ttry {\n\t\t\tconst authToken = this.config.auth ? (await this.config.auth()).token : undefined\n\n\t\t\tawait this.transport.connect(this.config.url, { authToken })\n\t\t\tthis.transitionTo('handshaking')\n\n\t\t\t// Send handshake\n\t\t\tconst localVector = this.store.getVersionVector()\n\t\t\tconst handshake: SyncMessage = {\n\t\t\t\ttype: 'handshake',\n\t\t\t\tmessageId: generateMessageId(),\n\t\t\t\tnodeId: this.store.getNodeId(),\n\t\t\t\tversionVector: versionVectorToWire(localVector),\n\t\t\t\tschemaVersion: this.config.schemaVersion ?? DEFAULT_SCHEMA_VERSION,\n\t\t\t\tauthToken,\n\t\t\t\tsupportedWireFormats: ['json', 'protobuf'],\n\t\t\t}\n\t\t\tthis.transport.send(handshake)\n\t\t} catch (err) {\n\t\t\tthis.transitionTo('error')\n\t\t\tthis.transitionTo('disconnected')\n\t\t\tthrow err\n\t\t}\n\t}\n\n\t/**\n\t * Stop the sync engine. Disconnects the transport.\n\t */\n\tasync stop(): Promise<void> {\n\t\tif (this.state === 'disconnected') return\n\n\t\t// Return any in-flight batch back to queue\n\t\tif (this.currentBatch) {\n\t\t\tthis.outboundQueue.returnBatch(this.currentBatch.batchId)\n\t\t\tthis.currentBatch = null\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.transport.disconnect()\n\t\t} finally {\n\t\t\t// The transport.disconnect() callback may have already transitioned\n\t\t\t// to 'disconnected' via handleTransportClose. Re-read the mutable field.\n\t\t\tthis.ensureDisconnected()\n\t\t}\n\t}\n\n\tprivate ensureDisconnected(): void {\n\t\tif (this.state !== 'disconnected') {\n\t\t\tthis.transitionTo('disconnected')\n\t\t}\n\t}\n\n\t/**\n\t * Push a local operation to the outbound queue.\n\t * If streaming, flushes immediately.\n\t */\n\tasync pushOperation(op: Operation): Promise<void> {\n\t\tawait this.outboundQueue.enqueue(op)\n\t\tif (this.state === 'streaming') {\n\t\t\tthis.flushQueue()\n\t\t}\n\t}\n\n\t/**\n\t * Get the current developer-facing sync status.\n\t */\n\tgetStatus(): SyncStatusInfo {\n\t\tconst pendingOperations = this.outboundQueue.totalPending\n\t\tswitch (this.state) {\n\t\t\tcase 'disconnected':\n\t\t\t\treturn { status: 'offline', pendingOperations, lastSyncedAt: this.lastSyncedAt }\n\t\t\tcase 'connecting':\n\t\t\tcase 'handshaking':\n\t\t\tcase 'syncing':\n\t\t\t\treturn { status: 'syncing', pendingOperations, lastSyncedAt: this.lastSyncedAt }\n\t\t\tcase 'streaming':\n\t\t\t\treturn {\n\t\t\t\t\tstatus: pendingOperations > 0 ? 'syncing' : 'synced',\n\t\t\t\t\tpendingOperations,\n\t\t\t\t\tlastSyncedAt: this.lastSyncedAt,\n\t\t\t\t}\n\t\t\tcase 'error':\n\t\t\t\treturn { status: 'error', pendingOperations, lastSyncedAt: this.lastSyncedAt }\n\t\t}\n\t}\n\n\t/**\n\t * Get the current internal state (for testing).\n\t */\n\tgetState(): SyncState {\n\t\treturn this.state\n\t}\n\n\t/**\n\t * Get the outbound queue (for testing).\n\t */\n\tgetOutboundQueue(): OutboundQueue {\n\t\treturn this.outboundQueue\n\t}\n\n\t// --- Private methods ---\n\n\tprivate handleMessage(message: SyncMessage): void {\n\t\tswitch (message.type) {\n\t\t\tcase 'handshake-response':\n\t\t\t\tthis.handleHandshakeResponse(message)\n\t\t\t\tbreak\n\t\t\tcase 'operation-batch':\n\t\t\t\tthis.handleOperationBatch(message)\n\t\t\t\tbreak\n\t\t\tcase 'acknowledgment':\n\t\t\t\tthis.handleAcknowledgment(message)\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.handleError(message)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate handleHandshakeResponse(msg: HandshakeResponseMessage): void {\n\t\tif (this.state !== 'handshaking') return\n\n\t\tif (!msg.accepted) {\n\t\t\tthis.transitionTo('error')\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:disconnected',\n\t\t\t\treason: msg.rejectReason ?? 'Handshake rejected',\n\t\t\t})\n\t\t\tthis.transitionTo('disconnected')\n\t\t\treturn\n\t\t}\n\n\t\tthis.remoteVector = wireToVersionVector(msg.versionVector)\n\n\t\tif (msg.selectedWireFormat) {\n\t\t\tthis.setSerializerWireFormat(msg.selectedWireFormat)\n\t\t}\n\n\t\tthis.emitter?.emit({ type: 'sync:connected', nodeId: this.store.getNodeId() })\n\n\t\tthis.transitionTo('syncing')\n\t\tthis.deltaBatchesReceived = 0\n\t\tthis.deltaReceiveComplete = false\n\t\tthis.deltaSendComplete = false\n\n\t\t// Send our delta to the server\n\t\tthis.sendDelta()\n\t}\n\n\tprivate async sendDelta(): Promise<void> {\n\t\tconst localVector = this.store.getVersionVector()\n\t\tconst missingOps = await this.collectDelta(localVector, this.remoteVector)\n\n\t\tif (missingOps.length === 0) {\n\t\t\t// No ops to send — send empty final batch\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateMessageId(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: 0,\n\t\t\t}\n\t\t\tthis.transport.send(emptyBatch)\n\t\t\tthis.deltaSendComplete = true\n\t\t\tthis.checkDeltaComplete()\n\t\t\treturn\n\t\t}\n\n\t\t// Paginate into batches\n\t\tconst sorted = topologicalSort(missingOps)\n\t\tconst totalBatches = Math.ceil(sorted.length / this.batchSize)\n\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst start = i * this.batchSize\n\t\t\tconst batchOps = sorted.slice(start, start + this.batchSize)\n\t\t\tconst serializedOps = batchOps.map((op) => this.serializer.encodeOperation(op))\n\n\t\t\tconst batchMsg: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateMessageId(),\n\t\t\t\toperations: serializedOps,\n\t\t\t\tisFinal: i === totalBatches - 1,\n\t\t\t\tbatchIndex: i,\n\t\t\t}\n\t\t\tthis.transport.send(batchMsg)\n\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: batchOps,\n\t\t\t\tbatchSize: batchOps.length,\n\t\t\t})\n\t\t}\n\n\t\tthis.deltaSendComplete = true\n\t\tthis.checkDeltaComplete()\n\t}\n\n\tprivate async collectDelta(\n\t\tlocalVector: VersionVector,\n\t\tremoteVector: VersionVector,\n\t): Promise<Operation[]> {\n\t\tconst missing: Operation[] = []\n\t\tfor (const [nodeId, localSeq] of localVector) {\n\t\t\tconst remoteSeq = remoteVector.get(nodeId) ?? 0\n\t\t\tif (localSeq > remoteSeq) {\n\t\t\t\tconst ops = await this.store.getOperationRange(nodeId, remoteSeq + 1, localSeq)\n\t\t\t\tmissing.push(...ops)\n\t\t\t}\n\t\t}\n\t\treturn missing\n\t}\n\n\tprivate async handleOperationBatch(msg: OperationBatchMessage): Promise<void> {\n\t\tconst operations = msg.operations.map((s) => this.serializer.decodeOperation(s))\n\n\t\t// Apply each operation to the local store\n\t\tfor (const op of operations) {\n\t\t\tawait this.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tif (operations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:received',\n\t\t\t\toperations,\n\t\t\t\tbatchSize: operations.length,\n\t\t\t})\n\t\t}\n\n\t\t// Send acknowledgment\n\t\tconst lastOp = operations[operations.length - 1]\n\t\tconst ack: SyncMessage = {\n\t\t\ttype: 'acknowledgment',\n\t\t\tmessageId: generateMessageId(),\n\t\t\tacknowledgedMessageId: msg.messageId,\n\t\t\tlastSequenceNumber: lastOp ? lastOp.sequenceNumber : 0,\n\t\t}\n\t\tthis.transport.send(ack)\n\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'sync:acknowledged',\n\t\t\tsequenceNumber: lastOp ? lastOp.sequenceNumber : 0,\n\t\t})\n\n\t\tif (this.state === 'syncing') {\n\t\t\tthis.deltaBatchesReceived++\n\t\t\tif (msg.isFinal) {\n\t\t\t\tthis.deltaReceiveComplete = true\n\t\t\t\tthis.checkDeltaComplete()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleAcknowledgment(msg: AcknowledgmentMessage): void {\n\t\tif (this.currentBatch) {\n\t\t\tthis.outboundQueue.acknowledge(this.currentBatch.batchId)\n\t\t\tthis.currentBatch = null\n\t\t\tthis.lastSyncedAt = Date.now()\n\t\t}\n\n\t\t// Continue flushing if more ops in queue\n\t\tif (this.state === 'streaming' && this.outboundQueue.hasOperations) {\n\t\t\tthis.flushQueue()\n\t\t}\n\t}\n\n\tprivate handleError(msg: { code: string; message: string; retriable: boolean }): void {\n\t\tthis.transitionTo('error')\n\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: msg.message })\n\t\tthis.transitionTo('disconnected')\n\t}\n\n\tprivate checkDeltaComplete(): void {\n\t\tif (this.deltaSendComplete && this.deltaReceiveComplete) {\n\t\t\tthis.lastSyncedAt = Date.now()\n\t\t\tthis.transitionTo('streaming')\n\n\t\t\t// Flush any queued operations accumulated during delta exchange\n\t\t\tif (this.outboundQueue.hasOperations) {\n\t\t\t\tthis.flushQueue()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate flushQueue(): void {\n\t\tif (this.currentBatch) return // Already have an in-flight batch\n\t\tif (!this.outboundQueue.hasOperations) return\n\n\t\tconst batch = this.outboundQueue.takeBatch(this.batchSize)\n\t\tif (!batch) return\n\n\t\tthis.currentBatch = batch\n\n\t\tconst serializedOps = batch.operations.map((op) => this.serializer.encodeOperation(op))\n\t\tconst batchMsg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateMessageId(),\n\t\t\toperations: serializedOps,\n\t\t\tisFinal: true,\n\t\t\tbatchIndex: 0,\n\t\t}\n\t\tthis.transport.send(batchMsg)\n\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'sync:sent',\n\t\t\toperations: batch.operations,\n\t\t\tbatchSize: batch.operations.length,\n\t\t})\n\t}\n\n\tprivate handleTransportClose(reason: string): void {\n\t\t// Return in-flight batch to queue\n\t\tif (this.currentBatch) {\n\t\t\tthis.outboundQueue.returnBatch(this.currentBatch.batchId)\n\t\t\tthis.currentBatch = null\n\t\t}\n\n\t\tif (this.state !== 'disconnected') {\n\t\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason })\n\t\t\tthis.transitionTo('disconnected')\n\t\t}\n\t}\n\n\tprivate handleTransportError(err: Error): void {\n\t\t// Transport errors during connecting should transition to error\n\t\tif (this.state !== 'disconnected') {\n\t\t\tthis.transitionTo('error')\n\t\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: err.message })\n\t\t\tthis.transitionTo('disconnected')\n\t\t}\n\t}\n\n\tprivate transitionTo(newState: SyncState): void {\n\t\tconst validTargets = VALID_TRANSITIONS[this.state]\n\t\tif (!validTargets.includes(newState)) {\n\t\t\tthrow new SyncError(`Invalid sync state transition: ${this.state} → ${newState}`, {\n\t\t\t\tfrom: this.state,\n\t\t\t\tto: newState,\n\t\t\t})\n\t\t}\n\t\tthis.state = newState\n\t}\n\n\tprivate setSerializerWireFormat(format: WireFormat): void {\n\t\tif (typeof this.serializer.setWireFormat === 'function') {\n\t\t\tthis.serializer.setWireFormat(format)\n\t\t}\n\t}\n}\n","import type { Operation } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type { QueueStorage } from '../types'\n\n/**\n * A batch of operations taken from the queue for sending.\n */\nexport interface OutboundBatch {\n\t/** Unique identifier for this batch */\n\tbatchId: string\n\t/** Operations in this batch, in causal order */\n\toperations: Operation[]\n}\n\n/**\n * Outbound operation queue with pluggable persistence.\n * Manages operations waiting to be sent to the sync server.\n *\n * Operations are deduplicated by ID (content-addressed) and maintained\n * in causal order via topological sort.\n */\nexport class OutboundQueue {\n\tprivate queue: Operation[] = []\n\tprivate readonly seen: Set<string> = new Set()\n\tprivate readonly inFlight: Map<string, Operation[]> = new Map()\n\tprivate nextBatchId = 0\n\tprivate initialized = false\n\n\tconstructor(private readonly storage: QueueStorage) {}\n\n\t/**\n\t * Load persisted operations from storage.\n\t * Must be called before using the queue.\n\t */\n\tasync initialize(): Promise<void> {\n\t\tconst stored = await this.storage.load()\n\t\tfor (const op of stored) {\n\t\t\tif (!this.seen.has(op.id)) {\n\t\t\t\tthis.seen.add(op.id)\n\t\t\t\tthis.queue.push(op)\n\t\t\t}\n\t\t}\n\t\t// Ensure causal order\n\t\tif (this.queue.length > 1) {\n\t\t\tthis.queue = topologicalSort(this.queue)\n\t\t}\n\t\tthis.initialized = true\n\t}\n\n\t/**\n\t * Add an operation to the outbound queue.\n\t * Deduplicates by operation ID. Persists to storage.\n\t */\n\tasync enqueue(op: Operation): Promise<void> {\n\t\tif (this.seen.has(op.id)) return\n\n\t\tthis.seen.add(op.id)\n\t\tthis.queue.push(op)\n\t\tawait this.storage.enqueue(op)\n\n\t\t// Re-sort to maintain causal order when new ops arrive\n\t\tif (this.queue.length > 1) {\n\t\t\tthis.queue = topologicalSort(this.queue)\n\t\t}\n\t}\n\n\t/**\n\t * Take a batch of operations from the front of the queue.\n\t * Moves them to in-flight status. Returns null if queue is empty.\n\t *\n\t * @param batchSize - Maximum number of operations in the batch\n\t */\n\ttakeBatch(batchSize: number): OutboundBatch | null {\n\t\tif (this.queue.length === 0) return null\n\n\t\tconst ops = this.queue.splice(0, batchSize)\n\t\tconst batchId = `batch-${this.nextBatchId++}`\n\t\tthis.inFlight.set(batchId, ops)\n\n\t\treturn { batchId, operations: ops }\n\t}\n\n\t/**\n\t * Acknowledge a batch, removing its operations permanently.\n\t */\n\tasync acknowledge(batchId: string): Promise<void> {\n\t\tconst ops = this.inFlight.get(batchId)\n\t\tif (!ops) return\n\n\t\tthis.inFlight.delete(batchId)\n\t\tconst ids = ops.map((op) => op.id)\n\t\tawait this.storage.dequeue(ids)\n\t}\n\n\t/**\n\t * Return a failed batch to the front of the queue for retry.\n\t * Prepends the operations to maintain priority.\n\t */\n\treturnBatch(batchId: string): void {\n\t\tconst ops = this.inFlight.get(batchId)\n\t\tif (!ops) return\n\n\t\tthis.inFlight.delete(batchId)\n\t\t// Prepend returned ops, then re-sort for causal order\n\t\tthis.queue.unshift(...ops)\n\t\tif (this.queue.length > 1) {\n\t\t\tthis.queue = topologicalSort(this.queue)\n\t\t}\n\t}\n\n\t/**\n\t * Number of operations waiting in the queue (not counting in-flight).\n\t */\n\tget size(): number {\n\t\treturn this.queue.length\n\t}\n\n\t/**\n\t * Total operations including in-flight.\n\t */\n\tget totalPending(): number {\n\t\tlet inFlightCount = 0\n\t\tfor (const ops of this.inFlight.values()) {\n\t\t\tinFlightCount += ops.length\n\t\t}\n\t\treturn this.queue.length + inFlightCount\n\t}\n\n\t/**\n\t * Whether the queue has any operations to send.\n\t */\n\tget hasOperations(): boolean {\n\t\treturn this.queue.length > 0\n\t}\n\n\t/**\n\t * Peek at the first `count` operations without removing them.\n\t */\n\tpeek(count: number): Operation[] {\n\t\treturn this.queue.slice(0, count)\n\t}\n\n\t/**\n\t * Whether initialize() has been called.\n\t */\n\tget isInitialized(): boolean {\n\t\treturn this.initialized\n\t}\n}\n","import type { ConnectionQuality, TimeSource } from '@korajs/core'\n\n/**\n * Configuration for the connection monitor.\n */\nexport interface ConnectionMonitorConfig {\n\t/** Number of latency samples to keep in the rolling window. Defaults to 20. */\n\twindowSize?: number\n\t/** Time in ms after which the connection is considered stale. Defaults to 30000. */\n\tstaleThreshold?: number\n\t/** Injectable time source for deterministic testing */\n\ttimeSource?: TimeSource\n}\n\n/**\n * Monitors connection quality based on RTT latency samples,\n * missed acknowledgments, and activity timestamps.\n */\nexport class ConnectionMonitor {\n\tprivate readonly windowSize: number\n\tprivate readonly staleThreshold: number\n\tprivate readonly timeSource: TimeSource\n\n\tprivate latencies: number[] = []\n\tprivate missedAcks = 0\n\tprivate lastActivityTime: number\n\n\tconstructor(config?: ConnectionMonitorConfig) {\n\t\tthis.windowSize = config?.windowSize ?? 20\n\t\tthis.staleThreshold = config?.staleThreshold ?? 30000\n\t\tthis.timeSource = config?.timeSource ?? { now: () => Date.now() }\n\t\tthis.lastActivityTime = this.timeSource.now()\n\t}\n\n\t/**\n\t * Record a round-trip time sample.\n\t */\n\trecordLatency(ms: number): void {\n\t\tthis.latencies.push(ms)\n\t\tif (this.latencies.length > this.windowSize) {\n\t\t\tthis.latencies.shift()\n\t\t}\n\t\tthis.lastActivityTime = this.timeSource.now()\n\t\t// Successful response resets missed acks\n\t\tthis.missedAcks = 0\n\t}\n\n\t/**\n\t * Record a missed acknowledgment (message sent but no response received).\n\t */\n\trecordMissedAck(): void {\n\t\tthis.missedAcks++\n\t}\n\n\t/**\n\t * Record any activity (message sent or received).\n\t */\n\trecordActivity(): void {\n\t\tthis.lastActivityTime = this.timeSource.now()\n\t}\n\n\t/**\n\t * Assess current connection quality based on collected metrics.\n\t *\n\t * Quality thresholds (average RTT):\n\t * - excellent: < 100ms, 0 missed acks\n\t * - good: < 300ms, ≤ 1 missed ack\n\t * - fair: < 1000ms, ≤ 3 missed acks\n\t * - poor: < 5000ms or > 3 missed acks\n\t * - offline: no activity for staleThreshold ms\n\t */\n\tgetQuality(): ConnectionQuality {\n\t\tconst elapsed = this.timeSource.now() - this.lastActivityTime\n\t\tif (elapsed > this.staleThreshold) return 'offline'\n\n\t\tif (this.latencies.length === 0) {\n\t\t\t// No data yet — assume good until proven otherwise\n\t\t\treturn this.missedAcks > 3 ? 'poor' : 'good'\n\t\t}\n\n\t\tconst avgLatency = this.latencies.reduce((sum, l) => sum + l, 0) / this.latencies.length\n\n\t\tif (this.missedAcks > 3) return 'poor'\n\t\tif (avgLatency < 100 && this.missedAcks === 0) return 'excellent'\n\t\tif (avgLatency < 300 && this.missedAcks <= 1) return 'good'\n\t\tif (avgLatency < 1000 && this.missedAcks <= 3) return 'fair'\n\t\treturn 'poor'\n\t}\n\n\t/**\n\t * Reset all metrics. Call on disconnect.\n\t */\n\treset(): void {\n\t\tthis.latencies = []\n\t\tthis.missedAcks = 0\n\t\tthis.lastActivityTime = this.timeSource.now()\n\t}\n\n\t/**\n\t * Get the current average latency in ms. Returns null if no samples.\n\t */\n\tgetAverageLatency(): number | null {\n\t\tif (this.latencies.length === 0) return null\n\t\treturn this.latencies.reduce((sum, l) => sum + l, 0) / this.latencies.length\n\t}\n\n\t/**\n\t * Get the number of missed acks.\n\t */\n\tgetMissedAcks(): number {\n\t\treturn this.missedAcks\n\t}\n}\n","import type { TimeSource } from '@korajs/core'\n\n/**\n * Configuration for the reconnection manager.\n */\nexport interface ReconnectionConfig {\n\t/** Initial delay in ms before first reconnection attempt. Defaults to 1000. */\n\tinitialDelay?: number\n\t/** Maximum delay in ms between attempts. Defaults to 30000. */\n\tmaxDelay?: number\n\t/** Multiplier for exponential backoff. Defaults to 2. */\n\tmultiplier?: number\n\t/** Maximum number of reconnection attempts. 0 means unlimited. Defaults to 0. */\n\tmaxAttempts?: number\n\t/** Jitter factor (0-1). Random variation applied to delay. Defaults to 0.25. */\n\tjitter?: number\n\t/** Injectable time source for deterministic testing. */\n\ttimeSource?: TimeSource\n\t/** Injectable random source for deterministic jitter. Returns value in [0, 1). */\n\trandomSource?: () => number\n}\n\n/**\n * Manages reconnection attempts with exponential backoff and jitter.\n *\n * Formula: min(initialDelay * multiplier^attempt, maxDelay) * (1 + jitter * (random - 0.5) * 2)\n */\nexport class ReconnectionManager {\n\tprivate readonly initialDelay: number\n\tprivate readonly maxDelay: number\n\tprivate readonly multiplier: number\n\tprivate readonly maxAttempts: number\n\tprivate readonly jitter: number\n\tprivate readonly random: () => number\n\n\tprivate attempt = 0\n\tprivate timer: ReturnType<typeof setTimeout> | null = null\n\tprivate stopped = false\n\tprivate waitResolve: (() => void) | null = null\n\n\tconstructor(config?: ReconnectionConfig) {\n\t\tthis.initialDelay = config?.initialDelay ?? 1000\n\t\tthis.maxDelay = config?.maxDelay ?? 30000\n\t\tthis.multiplier = config?.multiplier ?? 2\n\t\tthis.maxAttempts = config?.maxAttempts ?? 0\n\t\tthis.jitter = config?.jitter ?? 0.25\n\t\tthis.random = config?.randomSource ?? Math.random\n\t}\n\n\t/**\n\t * Start reconnection attempts. Calls `onReconnect` with exponential backoff.\n\t *\n\t * @param onReconnect - Called on each attempt. Return `true` if reconnection succeeded.\n\t * @returns Promise that resolves when reconnection succeeds or maxAttempts reached.\n\t */\n\tasync start(onReconnect: () => Promise<boolean>): Promise<boolean> {\n\t\tthis.stopped = false\n\t\tthis.attempt = 0\n\n\t\twhile (!this.stopped) {\n\t\t\tif (this.maxAttempts > 0 && this.attempt >= this.maxAttempts) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tconst delay = this.getNextDelay()\n\t\t\tthis.attempt++\n\n\t\t\tawait this.wait(delay)\n\n\t\t\tif (this.stopped) return false\n\n\t\t\ttry {\n\t\t\t\tconst success = await onReconnect()\n\t\t\t\tif (success) {\n\t\t\t\t\tthis.reset()\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Continue retrying on failure\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Stop any pending reconnection attempt.\n\t */\n\tstop(): void {\n\t\tthis.stopped = true\n\t\tif (this.timer !== null) {\n\t\t\tclearTimeout(this.timer)\n\t\t\tthis.timer = null\n\t\t}\n\t\t// Resolve the pending wait promise so start() loop can exit\n\t\tif (this.waitResolve) {\n\t\t\tthis.waitResolve()\n\t\t\tthis.waitResolve = null\n\t\t}\n\t}\n\n\t/**\n\t * Reset the attempt counter. Call after a successful manual reconnection.\n\t */\n\treset(): void {\n\t\tthis.attempt = 0\n\t\tthis.stopped = false\n\t}\n\n\t/**\n\t * Compute the next delay for the current attempt.\n\t * Exposed for testing purposes.\n\t */\n\tgetNextDelay(): number {\n\t\tconst baseDelay = Math.min(this.initialDelay * this.multiplier ** this.attempt, this.maxDelay)\n\n\t\t// Apply jitter: varies the delay by ±jitter factor\n\t\tconst jitterRange = baseDelay * this.jitter\n\t\tconst jitterOffset = (this.random() - 0.5) * 2 * jitterRange\n\t\treturn Math.max(0, Math.round(baseDelay + jitterOffset))\n\t}\n\n\t/**\n\t * Current attempt number (for testing).\n\t */\n\tgetAttemptCount(): number {\n\t\treturn this.attempt\n\t}\n\n\tprivate wait(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.waitResolve = resolve\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.timer = null\n\t\t\t\tthis.waitResolve = null\n\t\t\t\tresolve()\n\t\t\t}, ms)\n\t\t})\n\t}\n}\n"],"mappings":";;;;;AAKO,IAAM,cAAc;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAMO,IAAM,gBAAgB,CAAC,aAAa,WAAW,UAAU,WAAW,OAAO;;;ACiF3E,SAAS,cAAc,OAAsC;AACnE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,MAAI,OAAO,IAAI,SAAS,YAAY,OAAO,IAAI,cAAc,SAAU,QAAO;AAC9E,UAAQ,IAAI,MAAM;AAAA,IACjB,KAAK;AACJ,aAAO,mBAAmB,KAAK;AAAA,IAChC,KAAK;AACJ,aAAO,2BAA2B,KAAK;AAAA,IACxC,KAAK;AACJ,aAAO,wBAAwB,KAAK;AAAA,IACrC,KAAK;AACJ,aAAO,wBAAwB,KAAK;AAAA,IACrC,KAAK;AACJ,aAAO,eAAe,KAAK;AAAA,IAC5B;AACC,aAAO;AAAA,EACT;AACD;AAKO,SAAS,mBAAmB,OAA2C;AAC7E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SACC,IAAI,SAAS,eACb,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,WAAW,YACtB,OAAO,IAAI,kBAAkB,YAC7B,IAAI,kBAAkB,QACtB,CAAC,MAAM,QAAQ,IAAI,aAAa,KAChC,OAAO,IAAI,kBAAkB;AAE/B;AAKO,SAAS,2BAA2B,OAAmD;AAC7F,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SACC,IAAI,SAAS,wBACb,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,WAAW,YACtB,OAAO,IAAI,kBAAkB,YAC7B,IAAI,kBAAkB,QACtB,CAAC,MAAM,QAAQ,IAAI,aAAa,KAChC,OAAO,IAAI,kBAAkB,YAC7B,OAAO,IAAI,aAAa;AAE1B;AAKO,SAAS,wBAAwB,OAAgD;AACvF,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SACC,IAAI,SAAS,qBACb,OAAO,IAAI,cAAc,YACzB,MAAM,QAAQ,IAAI,UAAU,KAC5B,OAAO,IAAI,YAAY,aACvB,OAAO,IAAI,eAAe;AAE5B;AAKO,SAAS,wBAAwB,OAAgD;AACvF,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SACC,IAAI,SAAS,oBACb,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,0BAA0B,YACrC,OAAO,IAAI,uBAAuB;AAEpC;AAKO,SAAS,eAAe,OAAuC;AACrE,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SACC,IAAI,SAAS,WACb,OAAO,IAAI,cAAc,YACzB,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,YAAY,YACvB,OAAO,IAAI,cAAc;AAE3B;;;ACpMA,SAAS,iBAAiB;AAE1B,SAAS,QAAQ,cAAc;AA8BxB,SAAS,oBAAoB,QAA+C;AAClF,QAAM,OAA+B,CAAC;AACtC,aAAW,CAAC,QAAQ,GAAG,KAAK,QAAQ;AACnC,SAAK,MAAM,IAAI;AAAA,EAChB;AACA,SAAO;AACR;AAKO,SAAS,oBAAoB,MAA6C;AAChF,SAAO,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC;AACpC;AAKO,IAAM,wBAAN,MAAyD;AAAA,EAC/D,OAAO,SAA8B;AACpC,WAAO,KAAK,UAAU,OAAO;AAAA,EAC9B;AAAA,EAEA,OAAO,MAAsD;AAC5D,UAAM,OAAO,kBAAkB,IAAI;AAEnC,QAAI;AACJ,QAAI;AACH,eAAS,KAAK,MAAM,IAAI;AAAA,IACzB,QAAQ;AACP,YAAM,IAAI,UAAU,+CAA+C;AAAA,QAClE,YAAY,KAAK;AAAA,MAClB,CAAC;AAAA,IACF;AAEA,QAAI,CAAC,cAAc,MAAM,GAAG;AAC3B,YAAM,IAAI,UAAU,4DAA4D;AAAA,QAC/E,cACC,OAAO,WAAW,YAAY,WAAW,OACrC,OAAmC,OACpC,OAAO;AAAA,MACZ,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,gBAAgB,IAAoC;AACnD,WAAO;AAAA,MACN,IAAI,GAAG;AAAA,MACP,QAAQ,GAAG;AAAA,MACX,MAAM,GAAG;AAAA,MACT,YAAY,GAAG;AAAA,MACf,UAAU,GAAG;AAAA,MACb,MAAM,GAAG;AAAA,MACT,cAAc,GAAG;AAAA,MACjB,WAAW;AAAA,QACV,UAAU,GAAG,UAAU;AAAA,QACvB,SAAS,GAAG,UAAU;AAAA,QACtB,QAAQ,GAAG,UAAU;AAAA,MACtB;AAAA,MACA,gBAAgB,GAAG;AAAA,MACnB,YAAY,CAAC,GAAG,GAAG,UAAU;AAAA,MAC7B,eAAe,GAAG;AAAA,IACnB;AAAA,EACD;AAAA,EAEA,gBAAgB,YAA4C;AAC3D,WAAO;AAAA,MACN,IAAI,WAAW;AAAA,MACf,QAAQ,WAAW;AAAA,MACnB,MAAM,WAAW;AAAA,MACjB,YAAY,WAAW;AAAA,MACvB,UAAU,WAAW;AAAA,MACrB,MAAM,WAAW;AAAA,MACjB,cAAc,WAAW;AAAA,MACzB,WAAW;AAAA,QACV,UAAU,WAAW,UAAU;AAAA,QAC/B,SAAS,WAAW,UAAU;AAAA,QAC9B,QAAQ,WAAW,UAAU;AAAA,MAC9B;AAAA,MACA,gBAAgB,WAAW;AAAA,MAC3B,YAAY,CAAC,GAAG,WAAW,UAAU;AAAA,MACrC,eAAe,WAAW;AAAA,IAC3B;AAAA,EACD;AACD;AAKO,IAAM,4BAAN,MAA6D;AAAA,EACnE,OAAO,SAAkC;AACxC,UAAM,WAAW,gBAAgB,OAAO;AACxC,WAAO,eAAe,QAAQ;AAAA,EAC/B;AAAA,EAEA,OAAO,MAAsD;AAC5D,UAAM,QAAQ,QAAQ,IAAI;AAC1B,UAAM,WAAW,eAAe,KAAK;AACrC,WAAO,kBAAkB,QAAQ;AAAA,EAClC;AAAA,EAEA,gBAAgB,IAAoC;AACnD,WAAO,IAAI,sBAAsB,EAAE,gBAAgB,EAAE;AAAA,EACtD;AAAA,EAEA,gBAAgB,YAA4C;AAC3D,WAAO,IAAI,sBAAsB,EAAE,gBAAgB,UAAU;AAAA,EAC9D;AACD;AAKO,IAAM,8BAAN,MAA+D;AAAA,EACpD,OAAO,IAAI,sBAAsB;AAAA,EACjC,WAAW,IAAI,0BAA0B;AAAA,EAClD;AAAA,EAER,YAAY,oBAAgC,QAAQ;AACnD,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,OAAO,SAAsC;AAC5C,QAAI,KAAK,eAAe,YAAY;AACnC,aAAO,KAAK,SAAS,OAAO,OAAO;AAAA,IACpC;AAEA,WAAO,KAAK,KAAK,OAAO,OAAO;AAAA,EAChC;AAAA,EAEA,OAAO,MAAsD;AAC5D,QAAI,OAAO,SAAS,UAAU;AAC7B,aAAO,KAAK,KAAK,OAAO,IAAI;AAAA,IAC7B;AAEA,QAAI;AACH,aAAO,KAAK,SAAS,OAAO,IAAI;AAAA,IACjC,QAAQ;AACP,aAAO,KAAK,KAAK,OAAO,IAAI;AAAA,IAC7B;AAAA,EACD;AAAA,EAEA,gBAAgB,IAAoC;AACnD,WAAO,KAAK,KAAK,gBAAgB,EAAE;AAAA,EACpC;AAAA,EAEA,gBAAgB,YAA4C;AAC3D,WAAO,KAAK,KAAK,gBAAgB,UAAU;AAAA,EAC5C;AAAA,EAEA,cAAc,QAA0B;AACvC,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,gBAA4B;AAC3B,WAAO,KAAK;AAAA,EACb;AACD;AAkDA,SAAS,gBAAgB,SAAqC;AAC7D,UAAQ,QAAQ,MAAM;AAAA,IACrB,KAAK;AACJ,aAAO;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,QAAQ,QAAQ;AAAA,QAChB,eAAe,OAAO,QAAQ,QAAQ,aAAa,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE;AAAA,QAC3F,eAAe,QAAQ;AAAA,QACvB,WAAW,QAAQ;AAAA,QACnB,sBAAsB,QAAQ;AAAA,MAC/B;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,QAAQ,QAAQ;AAAA,QAChB,eAAe,OAAO,QAAQ,QAAQ,aAAa,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE;AAAA,QAC3F,eAAe,QAAQ;AAAA,QACvB,UAAU,QAAQ;AAAA,QAClB,cAAc,QAAQ;AAAA,QACtB,oBAAoB,QAAQ;AAAA,MAC7B;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,YAAY,QAAQ,WAAW,IAAI,uBAAuB;AAAA,QAC1D,SAAS,QAAQ;AAAA,QACjB,YAAY,QAAQ;AAAA,MACrB;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,uBAAuB,QAAQ;AAAA,QAC/B,oBAAoB,QAAQ;AAAA,MAC7B;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ;AAAA,MACpB;AAAA,EACF;AACD;AAEA,SAAS,kBAAkB,UAAsC;AAChE,UAAQ,SAAS,MAAM;AAAA,IACtB,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,QAAQ,SAAS,UAAU;AAAA,QAC3B,eAAe,OAAO,aAAa,SAAS,iBAAiB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,QACzG,eAAe,SAAS,iBAAiB;AAAA,QACzC,WAAW,SAAS;AAAA,QACpB,sBACC,SAAS,sBAAsB;AAAA,UAC9B,CAAC,WAAiC,WAAW,UAAU,WAAW;AAAA,QACnE;AAAA,MACF;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,QAAQ,SAAS,UAAU;AAAA,QAC3B,eAAe,OAAO,aAAa,SAAS,iBAAiB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,QACzG,eAAe,SAAS,iBAAiB;AAAA,QACzC,UAAU,SAAS,YAAY;AAAA,QAC/B,cAAc,SAAS;AAAA,QACvB,oBACC,SAAS,uBAAuB,UAAU,SAAS,uBAAuB,aACvE,SAAS,qBACT;AAAA,MACL;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,aAAa,SAAS,cAAc,CAAC,GAAG,IAAI,yBAAyB;AAAA,QACrE,SAAS,SAAS,WAAW;AAAA,QAC7B,YAAY,SAAS,cAAc;AAAA,MACpC;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,uBAAuB,SAAS,yBAAyB;AAAA,QACzD,oBAAoB,SAAS,sBAAsB;AAAA,MACpD;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,MAAM,SAAS,aAAa;AAAA,QAC5B,SAAS,SAAS,gBAAgB;AAAA,QAClC,WAAW,SAAS,aAAa;AAAA,MAClC;AAAA,IACD;AACC,YAAM,IAAI,UAAU,wDAAwD;AAAA,QAC3E,MAAM,SAAS;AAAA,MAChB,CAAC;AAAA,EACH;AACD;AAEA,SAAS,wBAAwB,WAAgD;AAChF,SAAO;AAAA,IACN,IAAI,UAAU;AAAA,IACd,QAAQ,UAAU;AAAA,IAClB,MAAM,UAAU;AAAA,IAChB,YAAY,UAAU;AAAA,IACtB,UAAU,UAAU;AAAA,IACpB,UAAU,UAAU,SAAS,OAAO,KAAK,KAAK,UAAU,UAAU,IAAI;AAAA,IACtE,kBACC,UAAU,iBAAiB,OAAO,KAAK,KAAK,UAAU,UAAU,YAAY;AAAA,IAC7E,WAAW;AAAA,MACV,UAAU,UAAU,UAAU;AAAA,MAC9B,SAAS,UAAU,UAAU;AAAA,MAC7B,QAAQ,UAAU,UAAU;AAAA,IAC7B;AAAA,IACA,gBAAgB,UAAU;AAAA,IAC1B,YAAY,CAAC,GAAG,UAAU,UAAU;AAAA,IACpC,eAAe,UAAU;AAAA,IACzB,SAAS,UAAU,SAAS;AAAA,IAC5B,iBAAiB,UAAU,iBAAiB;AAAA,EAC7C;AACD;AAEA,SAAS,0BAA0B,WAAgD;AAClF,SAAO;AAAA,IACN,IAAI,UAAU;AAAA,IACd,QAAQ,UAAU;AAAA,IAClB,MAAM,UAAU;AAAA,IAChB,YAAY,UAAU;AAAA,IACtB,UAAU,UAAU;AAAA,IACpB,MAAM,UAAU,UAAW,KAAK,MAAM,UAAU,QAAQ,IAAgC;AAAA,IACxF,cAAc,UAAU,kBACpB,KAAK,MAAM,UAAU,gBAAgB,IACtC;AAAA,IACH,WAAW;AAAA,MACV,UAAU,UAAU,UAAU;AAAA,MAC9B,SAAS,UAAU,UAAU;AAAA,MAC7B,QAAQ,UAAU,UAAU;AAAA,IAC7B;AAAA,IACA,gBAAgB,UAAU;AAAA,IAC1B,YAAY,CAAC,GAAG,UAAU,UAAU;AAAA,IACpC,eAAe,UAAU;AAAA,EAC1B;AACD;AAEA,SAAS,kBAAkB,MAAiD;AAC3E,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAO,IAAI,YAAY,EAAE,OAAO,QAAQ,IAAI,CAAC;AAC9C;AAEA,SAAS,QAAQ,MAAqD;AACrE,MAAI,OAAO,SAAS,UAAU;AAC7B,WAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,EACrC;AAEA,MAAI,gBAAgB,YAAY;AAC/B,WAAO;AAAA,EACR;AAEA,MAAI,gBAAgB,aAAa;AAChC,WAAO,IAAI,WAAW,IAAI;AAAA,EAC3B;AAEA,QAAM,IAAI,UAAU,iCAAiC,EAAE,cAAc,OAAO,KAAK,CAAC;AACnF;AAEA,SAAS,eAAe,UAAqC;AAC5D,QAAM,SAAS,OAAO,OAAO;AAC7B,MAAI,SAAS,KAAK,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,SAAS,IAAI;AACpE,MAAI,SAAS,UAAU,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,SAAS,SAAS;AAC9E,MAAI,SAAS,UAAU,SAAS,OAAO,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,SAAS,MAAM;AAC3F,aAAW,SAAS,SAAS,iBAAiB,CAAC,GAAG;AACjD,WAAO,OAAO,EAAE,EAAE,KAAK;AACvB,WAAO,OAAO,EAAE,EAAE,OAAO,MAAM,GAAG;AAClC,WAAO,OAAO,EAAE,EAAE,MAAM,MAAM,KAAK;AACnC,WAAO,OAAO;AAAA,EACf;AACA,MAAI,SAAS,kBAAkB,OAAW,QAAO,OAAO,EAAE,EAAE,MAAM,SAAS,aAAa;AACxF,MAAI,SAAS,aAAa,SAAS,UAAU,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,SAAS,SAAS;AACpG,aAAW,UAAU,SAAS,wBAAwB,CAAC,GAAG;AACzD,WAAO,OAAO,EAAE,EAAE,OAAO,MAAM;AAAA,EAChC;AACA,MAAI,SAAS,aAAa,OAAW,QAAO,OAAO,EAAE,EAAE,KAAK,SAAS,QAAQ;AAC7E,MAAI,SAAS,gBAAgB,SAAS,aAAa,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,SAAS,YAAY;AAC7G,MAAI,SAAS,sBAAsB,SAAS,mBAAmB,SAAS,GAAG;AAC1E,WAAO,OAAO,EAAE,EAAE,OAAO,SAAS,kBAAkB;AAAA,EACrD;AACA,aAAW,aAAa,SAAS,cAAc,CAAC,GAAG;AAClD,WAAO,OAAO,EAAE,EAAE,KAAK;AACvB,yBAAqB,QAAQ,SAAS;AACtC,WAAO,OAAO;AAAA,EACf;AACA,MAAI,SAAS,YAAY,OAAW,QAAO,OAAO,EAAE,EAAE,KAAK,SAAS,OAAO;AAC3E,MAAI,SAAS,eAAe,OAAW,QAAO,OAAO,GAAG,EAAE,OAAO,SAAS,UAAU;AACpF,MAAI,SAAS,yBAAyB,SAAS,sBAAsB,SAAS,GAAG;AAChF,WAAO,OAAO,GAAG,EAAE,OAAO,SAAS,qBAAqB;AAAA,EACzD;AACA,MAAI,SAAS,uBAAuB,OAAW,QAAO,OAAO,GAAG,EAAE,MAAM,SAAS,kBAAkB;AACnG,MAAI,SAAS,aAAa,SAAS,UAAU,SAAS,EAAG,QAAO,OAAO,GAAG,EAAE,OAAO,SAAS,SAAS;AACrG,MAAI,SAAS,gBAAgB,SAAS,aAAa,SAAS,GAAG;AAC9D,WAAO,OAAO,GAAG,EAAE,OAAO,SAAS,YAAY;AAAA,EAChD;AACA,MAAI,SAAS,cAAc,OAAW,QAAO,OAAO,GAAG,EAAE,KAAK,SAAS,SAAS;AAChF,SAAO,OAAO,OAAO;AACtB;AAEA,SAAS,eAAe,OAAkC;AACzD,QAAM,SAAS,OAAO,OAAO,KAAK;AAClC,QAAM,WAA0B,EAAE,MAAM,SAAS,WAAW,GAAG;AAE/D,SAAO,OAAO,MAAM,OAAO,KAAK;AAC/B,UAAM,MAAM,OAAO,OAAO;AAC1B,YAAQ,QAAQ,GAAG;AAAA,MAClB,KAAK;AACJ,iBAAS,OAAO,OAAO,OAAO;AAC9B;AAAA,MACD,KAAK;AACJ,iBAAS,YAAY,OAAO,OAAO;AACnC;AAAA,MACD,KAAK;AACJ,iBAAS,SAAS,OAAO,OAAO;AAChC;AAAA,MACD,KAAK;AACJ,iBAAS,gBAAgB,CAAC,GAAI,SAAS,iBAAiB,CAAC,GAAI,kBAAkB,QAAQ,OAAO,OAAO,CAAC,CAAC;AACvG;AAAA,MACD,KAAK;AACJ,iBAAS,gBAAgB,OAAO,MAAM;AACtC;AAAA,MACD,KAAK;AACJ,iBAAS,YAAY,OAAO,OAAO;AACnC;AAAA,MACD,KAAK;AACJ,iBAAS,uBAAuB,CAAC,GAAI,SAAS,wBAAwB,CAAC,GAAI,OAAO,OAAO,CAAC;AAC1F;AAAA,MACD,KAAK;AACJ,iBAAS,WAAW,OAAO,KAAK;AAChC;AAAA,MACD,KAAK;AACJ,iBAAS,eAAe,OAAO,OAAO;AACtC;AAAA,MACD,KAAK;AACJ,iBAAS,qBAAqB,OAAO,OAAO;AAC5C;AAAA,MACD,KAAK;AACJ,iBAAS,aAAa,CAAC,GAAI,SAAS,cAAc,CAAC,GAAI,qBAAqB,QAAQ,OAAO,OAAO,CAAC,CAAC;AACpG;AAAA,MACD,KAAK;AACJ,iBAAS,UAAU,OAAO,KAAK;AAC/B;AAAA,MACD,KAAK;AACJ,iBAAS,aAAa,OAAO,OAAO;AACpC;AAAA,MACD,KAAK;AACJ,iBAAS,wBAAwB,OAAO,OAAO;AAC/C;AAAA,MACD,KAAK;AACJ,iBAAS,qBAAqB,aAAa,OAAO,MAAM,CAAC;AACzD;AAAA,MACD,KAAK;AACJ,iBAAS,YAAY,OAAO,OAAO;AACnC;AAAA,MACD,KAAK;AACJ,iBAAS,eAAe,OAAO,OAAO;AACtC;AAAA,MACD,KAAK;AACJ,iBAAS,YAAY,OAAO,KAAK;AACjC;AAAA,MACD;AACC,eAAO,SAAS,MAAM,CAAC;AAAA,IACzB;AAAA,EACD;AAEA,SAAO;AACR;AAEA,SAAS,qBAAqB,QAAgB,WAAiC;AAC9E,MAAI,UAAU,GAAG,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,EAAE;AAClE,MAAI,UAAU,OAAO,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,MAAM;AAC1E,MAAI,UAAU,KAAK,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,IAAI;AACtE,MAAI,UAAU,WAAW,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,UAAU;AAClF,MAAI,UAAU,SAAS,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,QAAQ;AAC9E,MAAI,UAAU,SAAS,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,QAAQ;AAC9E,MAAI,UAAU,iBAAiB,SAAS,EAAG,QAAO,OAAO,EAAE,EAAE,OAAO,UAAU,gBAAgB;AAC9F,SAAO,OAAO,EAAE,EAAE,KAAK;AACvB,SAAO,OAAO,CAAC,EAAE,MAAM,UAAU,UAAU,QAAQ;AACnD,SAAO,OAAO,EAAE,EAAE,OAAO,UAAU,UAAU,OAAO;AACpD,SAAO,OAAO,EAAE,EAAE,OAAO,UAAU,UAAU,MAAM;AACnD,SAAO,OAAO;AACd,SAAO,OAAO,EAAE,EAAE,MAAM,UAAU,cAAc;AAChD,aAAW,OAAO,UAAU,YAAY;AACvC,WAAO,OAAO,EAAE,EAAE,OAAO,GAAG;AAAA,EAC7B;AACA,SAAO,OAAO,EAAE,EAAE,MAAM,UAAU,aAAa;AAC/C,SAAO,OAAO,EAAE,EAAE,KAAK,UAAU,OAAO;AACxC,SAAO,OAAO,GAAG,EAAE,KAAK,UAAU,eAAe;AAClD;AAEA,SAAS,qBAAqB,QAAgB,QAAgC;AAC7E,QAAM,MAAM,OAAO,MAAM;AACzB,QAAM,YAA4B;AAAA,IACjC,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,WAAW,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG;AAAA,IACjD,gBAAgB;AAAA,IAChB,YAAY,CAAC;AAAA,IACb,eAAe;AAAA,IACf,SAAS;AAAA,IACT,iBAAiB;AAAA,EAClB;AAEA,SAAO,OAAO,MAAM,KAAK;AACxB,UAAM,MAAM,OAAO,OAAO;AAC1B,YAAQ,QAAQ,GAAG;AAAA,MAClB,KAAK;AACJ,kBAAU,KAAK,OAAO,OAAO;AAC7B;AAAA,MACD,KAAK;AACJ,kBAAU,SAAS,OAAO,OAAO;AACjC;AAAA,MACD,KAAK;AACJ,kBAAU,OAAO,OAAO,OAAO;AAC/B;AAAA,MACD,KAAK;AACJ,kBAAU,aAAa,OAAO,OAAO;AACrC;AAAA,MACD,KAAK;AACJ,kBAAU,WAAW,OAAO,OAAO;AACnC;AAAA,MACD,KAAK;AACJ,kBAAU,WAAW,OAAO,OAAO;AACnC;AAAA,MACD,KAAK;AACJ,kBAAU,mBAAmB,OAAO,OAAO;AAC3C;AAAA,MACD,KAAK,GAAG;AACP,cAAM,eAAe,OAAO,MAAM,OAAO,OAAO;AAChD,eAAO,OAAO,MAAM,cAAc;AACjC,gBAAM,eAAe,OAAO,OAAO;AACnC,kBAAQ,iBAAiB,GAAG;AAAA,YAC3B,KAAK;AACJ,wBAAU,UAAU,WAAW,aAAa,OAAO,MAAM,CAAC;AAC1D;AAAA,YACD,KAAK;AACJ,wBAAU,UAAU,UAAU,OAAO,OAAO;AAC5C;AAAA,YACD,KAAK;AACJ,wBAAU,UAAU,SAAS,OAAO,OAAO;AAC3C;AAAA,YACD;AACC,qBAAO,SAAS,eAAe,CAAC;AAAA,UAClC;AAAA,QACD;AACA;AAAA,MACD;AAAA,MACA,KAAK;AACJ,kBAAU,iBAAiB,aAAa,OAAO,MAAM,CAAC;AACtD;AAAA,MACD,KAAK;AACJ,kBAAU,WAAW,KAAK,OAAO,OAAO,CAAC;AACzC;AAAA,MACD,KAAK;AACJ,kBAAU,gBAAgB,OAAO,MAAM;AACvC;AAAA,MACD,KAAK;AACJ,kBAAU,UAAU,OAAO,KAAK;AAChC;AAAA,MACD,KAAK;AACJ,kBAAU,kBAAkB,OAAO,KAAK;AACxC;AAAA,MACD;AACC,eAAO,SAAS,MAAM,CAAC;AAAA,IACzB;AAAA,EACD;AAEA,SAAO;AACR;AAEA,SAAS,kBAAkB,QAAgB,QAAkC;AAC5E,QAAM,MAAM,OAAO,MAAM;AACzB,QAAM,QAA0B,EAAE,KAAK,IAAI,OAAO,EAAE;AACpD,SAAO,OAAO,MAAM,KAAK;AACxB,UAAM,MAAM,OAAO,OAAO;AAC1B,YAAQ,QAAQ,GAAG;AAAA,MAClB,KAAK;AACJ,cAAM,MAAM,OAAO,OAAO;AAC1B;AAAA,MACD,KAAK;AACJ,cAAM,QAAQ,aAAa,OAAO,MAAM,CAAC;AACzC;AAAA,MACD;AACC,eAAO,SAAS,MAAM,CAAC;AAAA,IACzB;AAAA,EACD;AACA,SAAO;AACR;AAEA,SAAS,aAAa,OAAwB;AAC7C,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,SAAS,OAAO,EAAE;AAC/D,MACC,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,OAAQ,MAAgC,aAAa,YACpD;AACD,WAAQ,MAAiC,SAAS;AAAA,EACnD;AAEA,QAAM,IAAI,UAAU,gCAAgC;AAAA,IACnD,cAAc,OAAO;AAAA,EACtB,CAAC;AACF;;;ACzpBA,SAAS,aAAAA,kBAAiB;AA0C1B,IAAM,UAAU;AAKT,IAAM,qBAAN,MAAkD;AAAA,EAChD,KAA2B;AAAA,EAC3B,iBAAiD;AAAA,EACjD,eAA6C;AAAA,EAC7C,eAA6C;AAAA,EACpC;AAAA,EACA;AAAA,EAEjB,YAAY,SAAqC;AAChD,SAAK,aAAa,SAAS,cAAc,IAAI,sBAAsB;AAEnE,QAAI,SAAS,eAAe;AAC3B,WAAK,gBAAgB,QAAQ;AAAA,IAC9B,WAAW,OAAO,WAAW,cAAc,aAAa;AACvD,WAAK,gBAAgB,WAAW;AAAA,IACjC,OAAO;AAEN,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAAA,EAEA,MAAM,QAAQ,KAAa,SAA2C;AACrE,QAAI,CAAC,KAAK,eAAe;AACxB,YAAM,IAAIC,WAAU,kDAAkD;AAAA,QACrE,MAAM;AAAA,MACP,CAAC;AAAA,IACF;AAEA,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC7C,UAAI;AAEH,cAAM,aAAa,SAAS,YACzB,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,SAAS,mBAAmB,QAAQ,SAAS,CAAC,KACpF;AAEH,cAAM,KAAK,IAAI,KAAK,cAAc,UAAU;AAC5C,aAAK,KAAK;AAEV,WAAG,SAAS,MAAM;AACjB,kBAAQ;AAAA,QACT;AAEA,WAAG,YAAY,CAAC,UAA6B;AAC5C,cAAI;AACH,gBACC,OAAO,MAAM,SAAS,YACtB,EAAE,MAAM,gBAAgB,eACxB,EAAE,MAAM,gBAAgB,cACvB;AACD;AAAA,YACD;AAEA,kBAAM,UAAU,KAAK,WAAW,OAAO,MAAM,IAAI;AACjD,iBAAK,iBAAiB,OAAO;AAAA,UAC9B,QAAQ;AACP,iBAAK,eAAe,IAAIA,WAAU,mCAAmC,CAAC;AAAA,UACvE;AAAA,QACD;AAEA,WAAG,UAAU,CAAC,UAA4C;AACzD,eAAK,KAAK;AACV,eAAK,eAAe,MAAM,UAAU,8BAA8B,MAAM,IAAI,EAAE;AAAA,QAC/E;AAEA,WAAG,UAAU,CAAC,UAAmB;AAChC,gBAAM,MAAM,IAAIA,WAAU,mBAAmB;AAAA,YAC5C;AAAA,UACD,CAAC;AACD,eAAK,eAAe,GAAG;AAEvB,cAAI,CAAC,KAAK,YAAY,GAAG;AACxB,iBAAK,KAAK;AACV,mBAAO,GAAG;AAAA,UACX;AAAA,QACD;AAAA,MACD,SAAS,KAAK;AACb;AAAA,UACC,eAAeA,aACZ,MACA,IAAIA,WAAU,8BAA8B;AAAA,YAC5C;AAAA,YACA,OAAO,OAAO,GAAG;AAAA,UAClB,CAAC;AAAA,QACJ;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AACjC,QAAI,KAAK,IAAI;AACZ,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,MAAM,KAAM,sBAAsB;AAC1C,WAAK,KAAK;AAAA,IACX;AAAA,EACD;AAAA,EAEA,KAAK,SAA4B;AAChC,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,SAAS;AAC/C,YAAM,IAAIA,WAAU,mDAAmD;AAAA,QACtE,aAAa,QAAQ;AAAA,MACtB,CAAC;AAAA,IACF;AACA,UAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,SAAK,GAAG,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,UAAU,SAAwC;AACjD,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK,OAAO,QAAQ,KAAK,GAAG,eAAe;AAAA,EACnD;AACD;;;ACxKA,SAAS,aAAAC,kBAAiB;AAM1B,IAAM,yBAAyB;AAaxB,IAAM,2BAAN,MAAwD;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,iBAAiD;AAAA,EACjD,eAA6C;AAAA,EAC7C,eAA6C;AAAA,EAE7C,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,MAAqB;AAAA,EACrB;AAAA,EACA,YAAoC;AAAA,EACpC,oBAA0C;AAAA,EAElD,YAAY,SAA2C;AACtD,SAAK,aAAa,SAAS,cAAc,IAAI,4BAA4B,MAAM;AAC/E,SAAK,YAAY,SAAS,aAAa;AACvC,SAAK,eAAe,SAAS,gBAAgB;AAC7C,SAAK,kBAAkB,SAAS,mBAAmB;AACnD,SAAK,mBAAmB,SAAS,qBAAqB,MAAM,IAAI,mBAAmB,EAAE,YAAY,KAAK,WAAW,CAAC;AAAA,EACnH;AAAA,EAEA,MAAM,QAAQ,KAAa,SAA2C;AACrE,QAAI,KAAK,WAAW;AACnB,YAAM,IAAIC,WAAU,8CAA8C,EAAE,IAAI,CAAC;AAAA,IAC1E;AAEA,SAAK,MAAM,iBAAiB,GAAG;AAC/B,SAAK,YAAY,SAAS;AAE1B,QAAI,KAAK,iBAAiB;AACzB,YAAM,WAAW,MAAM,KAAK,sBAAsB,KAAK,OAAO;AAC9D,UAAI,UAAU;AACb,aAAK,oBAAoB;AACzB,aAAK,YAAY;AACjB;AAAA,MACD;AAAA,IACD;AAEA,SAAK,YAAY;AACjB,SAAK,UAAU;AACf,SAAK,YAAY,IAAI,gBAAgB;AACrC,SAAK,KAAK,YAAY;AAAA,EACvB;AAAA,EAEA,MAAM,aAA4B;AACjC,QAAI,KAAK,mBAAmB;AAC3B,YAAM,KAAK,kBAAkB,WAAW;AACxC,WAAK,oBAAoB;AAAA,IAC1B;AAEA,SAAK,YAAY;AACjB,SAAK,UAAU;AACf,SAAK,WAAW,MAAM;AACtB,SAAK,YAAY;AACjB,SAAK,MAAM;AAAA,EACZ;AAAA,EAEA,KAAK,SAA2D;AAC/D,QAAI,CAAC,KAAK,WAAW;AACpB,YAAM,IAAIA,WAAU,kEAAkE;AAAA,QACrF,aAAa,QAAQ;AAAA,MACtB,CAAC;AAAA,IACF;AAEA,QAAI,KAAK,mBAAmB;AAC3B,WAAK,kBAAkB,KAAK,OAAO;AACnC;AAAA,IACD;AAEA,SAAK,KAAK,YAAY,OAAO;AAAA,EAC9B;AAAA,EAEA,UAAU,SAAwC;AACjD,SAAK,iBAAiB;AACtB,QAAI,KAAK,mBAAmB;AAC3B,WAAK,kBAAkB,UAAU,OAAO;AAAA,IACzC;AAAA,EACD;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AACpB,QAAI,KAAK,mBAAmB;AAC3B,WAAK,kBAAkB,QAAQ,OAAO;AAAA,IACvC;AAAA,EACD;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AACpB,QAAI,KAAK,mBAAmB;AAC3B,WAAK,kBAAkB,QAAQ,OAAO;AAAA,IACvC;AAAA,EACD;AAAA,EAEA,cAAuB;AACtB,QAAI,KAAK,mBAAmB;AAC3B,aAAO,KAAK,kBAAkB,YAAY;AAAA,IAC3C;AACA,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAc,sBAAsB,KAAa,SAA2D;AAC3G,UAAM,cAAc,KAAK,iBAAiB;AAE1C,QAAI,KAAK,eAAgB,aAAY,UAAU,KAAK,cAAc;AAClE,QAAI,KAAK,aAAc,aAAY,QAAQ,KAAK,YAAY;AAC5D,QAAI,KAAK,aAAc,aAAY,QAAQ,KAAK,YAAY;AAE5D,QAAI;AACH,YAAM,YAAY,QAAQ,sBAAsB,GAAG,GAAG,OAAO;AAC7D,aAAO;AAAA,IACR,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEA,MAAc,YAAY,SAAoE;AAC7F,QAAI,CAAC,KAAK,IAAK;AAEf,UAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,UAAM,UAAU,IAAI,QAAQ;AAC5B,YAAQ,IAAI,UAAU,0CAA0C;AAChE,QAAI,KAAK,WAAW;AACnB,cAAQ,IAAI,iBAAiB,UAAU,KAAK,SAAS,EAAE;AAAA,IACxD;AAEA,UAAM,WAAW,mBAAmB;AACpC,YAAQ,IAAI,gBAAgB,WAAW,2BAA2B,kBAAkB;AAEpF,QAAI;AACH,YAAM,cAAc,WAAW,cAAc,OAAO,IAAI;AAExD,YAAM,WAAW,MAAM,KAAK,UAAU,KAAK,KAAK;AAAA,QAC/C,QAAQ;AAAA,QACR;AAAA,QACA,MAAM;AAAA,MACP,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AACjB,cAAM,IAAIA,WAAU,8BAA8B;AAAA,UACjD,QAAQ,SAAS;AAAA,UACjB,aAAa,QAAQ;AAAA,QACtB,CAAC;AAAA,MACF;AAAA,IACD,SAAS,OAAO;AACf,WAAK,eAAe,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC9E;AAAA,EACD;AAAA,EAEA,MAAc,cAA6B;AAC1C,WAAO,KAAK,WAAW,KAAK,aAAa,KAAK,KAAK;AAClD,UAAI;AACH,cAAM,WAAW,MAAM,KAAK,UAAU,KAAK,KAAK;AAAA,UAC/C,QAAQ;AAAA,UACR,SAAS,KAAK,gBAAgB;AAAA,UAC9B,QAAQ,KAAK,WAAW;AAAA,QACzB,CAAC;AAED,YAAI,SAAS,WAAW,KAAK;AAC5B,gBAAM,MAAM,KAAK,YAAY;AAC7B;AAAA,QACD;AAEA,YAAI,CAAC,SAAS,IAAI;AACjB,gBAAM,IAAIA,WAAU,iCAAiC;AAAA,YACpD,QAAQ,SAAS;AAAA,UAClB,CAAC;AAAA,QACF;AAEA,cAAM,UAAU,MAAM,oBAAoB,QAAQ;AAClD,YAAI,YAAY,MAAM;AACrB;AAAA,QACD;AAEA,cAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,aAAK,iBAAiB,OAAO;AAAA,MAC9B,SAAS,OAAO;AACf,YAAI,CAAC,KAAK,aAAa,CAAC,KAAK,SAAS;AACrC;AAAA,QACD;AAEA,YAAI,aAAa,KAAK,GAAG;AACxB;AAAA,QACD;AAEA,aAAK,eAAe,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAC7E,cAAM,MAAM,KAAK,YAAY;AAAA,MAC9B;AAAA,IACD;AAEA,QAAI,CAAC,KAAK,WAAW;AACpB,WAAK,eAAe,gCAAgC;AAAA,IACrD;AAAA,EACD;AAAA,EAEQ,kBAA2B;AAClC,UAAM,UAAU,IAAI,QAAQ;AAC5B,YAAQ,IAAI,UAAU,0CAA0C;AAChE,QAAI,KAAK,WAAW;AACnB,cAAQ,IAAI,iBAAiB,UAAU,KAAK,SAAS,EAAE;AAAA,IACxD;AACA,WAAO;AAAA,EACR;AACD;AAEA,SAAS,iBAAiB,KAAqB;AAC9C,MAAI,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU,GAAG;AAC5D,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,WAAW,OAAO,GAAG;AAC5B,WAAO,UAAU,IAAI,MAAM,QAAQ,MAAM,CAAC;AAAA,EAC3C;AAEA,MAAI,IAAI,WAAW,QAAQ,GAAG;AAC7B,WAAO,WAAW,IAAI,MAAM,SAAS,MAAM,CAAC;AAAA,EAC7C;AAEA,SAAO;AACR;AAEA,SAAS,sBAAsB,KAAqB;AACnD,MAAI,IAAI,WAAW,OAAO,KAAK,IAAI,WAAW,QAAQ,GAAG;AACxD,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,WAAW,SAAS,GAAG;AAC9B,WAAO,QAAQ,IAAI,MAAM,UAAU,MAAM,CAAC;AAAA,EAC3C;AAEA,MAAI,IAAI,WAAW,UAAU,GAAG;AAC/B,WAAO,SAAS,IAAI,MAAM,WAAW,MAAM,CAAC;AAAA,EAC7C;AAEA,SAAO;AACR;AAEA,eAAe,oBAAoB,UAAyD;AAC3F,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,MAAI,YAAY,SAAS,wBAAwB,GAAG;AACnD,UAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,QAAI,OAAO,eAAe,EAAG,QAAO;AACpC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC7B;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SAAO;AACR;AAEA,SAAS,MAAM,IAA2B;AACzC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;AAEA,SAAS,aAAa,OAAyB;AAC9C,SACC,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACT,MAA4B,SAAS;AAExC;AAEA,SAAS,cAAc,MAA+B;AACrD,QAAM,SAAS,IAAI,WAAW,KAAK,UAAU;AAC7C,SAAO,IAAI,IAAI;AACf,SAAO,OAAO;AACf;;;AClQO,IAAM,iBAAN,MAA8C;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,iBAAiD;AAAA,EACjD,gBAA+B,CAAC;AAAA,EAChC,SAA0C,CAAC;AAAA,EAEnD,YAAY,OAAsB,QAAsB;AACvD,SAAK,QAAQ;AACb,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,SAAS,QAAQ,gBAAgB,KAAK;AAAA,EAC5C;AAAA,EAEA,MAAM,QAAQ,KAAa,SAA2C;AAErE,SAAK,MAAM,UAAU,CAAC,QAAQ,KAAK,eAAe,GAAG,CAAC;AACtD,WAAO,KAAK,MAAM,QAAQ,KAAK,OAAO;AAAA,EACvC;AAAA,EAEA,MAAM,aAA4B;AAEjC,SAAK,mBAAmB;AAExB,eAAW,SAAS,KAAK,QAAQ;AAChC,mBAAa,KAAK;AAAA,IACnB;AACA,SAAK,SAAS,CAAC;AACf,WAAO,KAAK,MAAM,WAAW;AAAA,EAC9B;AAAA,EAEA,KAAK,SAA4B;AAEhC,QAAI,KAAK,OAAO,IAAI,KAAK,UAAU;AAClC;AAAA,IACD;AAEA,QAAI,KAAK,OAAO,IAAI,KAAK,aAAa;AACrC,WAAK,cAAc,KAAK,OAAO;AAE/B;AAAA,IACD;AAGA,SAAK,mBAAmB;AAExB,SAAK,MAAM,KAAK,OAAO;AAGvB,QAAI,KAAK,OAAO,IAAI,KAAK,eAAe;AACvC,WAAK,MAAM,KAAK,OAAO;AAAA,IACxB;AAAA,EACD;AAAA,EAEA,UAAU,SAAwC;AACjD,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,MAAM,QAAQ,OAAO;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,MAAM,QAAQ,OAAO;AAAA,EAC3B;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK,MAAM,YAAY;AAAA,EAC/B;AAAA,EAEQ,eAAe,SAA4B;AAClD,QAAI,CAAC,KAAK,eAAgB;AAG1B,QAAI,KAAK,OAAO,IAAI,KAAK,UAAU;AAClC;AAAA,IACD;AAEA,QAAI,KAAK,aAAa,GAAG;AACxB,YAAM,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,UAAU;AACxD,YAAM,QAAQ,WAAW,MAAM;AAC9B,aAAK,gBAAgB,OAAO;AAAA,MAC7B,GAAG,KAAK;AACR,WAAK,OAAO,KAAK,KAAK;AACtB;AAAA,IACD;AAEA,SAAK,gBAAgB,OAAO;AAAA,EAC7B;AAAA,EAEQ,gBAAgB,SAA4B;AACnD,QAAI,CAAC,KAAK,eAAgB;AAE1B,SAAK,eAAe,OAAO;AAG3B,QAAI,KAAK,OAAO,IAAI,KAAK,eAAe;AACvC,WAAK,eAAe,OAAO;AAAA,IAC5B;AAAA,EACD;AAAA,EAEQ,qBAA2B;AAElC,UAAM,SAAS,CAAC,GAAG,KAAK,aAAa;AACrC,SAAK,gBAAgB,CAAC;AAGtB,aAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC3C,YAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;AAC5C,YAAM,OAAO,OAAO,CAAC;AACrB,aAAO,CAAC,IAAI,OAAO,CAAC;AACpB,aAAO,CAAC,IAAI;AAAA,IACb;AAEA,eAAW,OAAO,QAAQ;AACzB,WAAK,MAAM,KAAK,GAAG;AAAA,IACpB;AAAA,EACD;AACD;;;AC5JA,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,mBAAAC,wBAAuB;;;ACDhC,SAAS,uBAAuB;AAoBzB,IAAM,gBAAN,MAAoB;AAAA,EAO1B,YAA6B,SAAuB;AAAvB;AAAA,EAAwB;AAAA,EAAxB;AAAA,EANrB,QAAqB,CAAC;AAAA,EACb,OAAoB,oBAAI,IAAI;AAAA,EAC5B,WAAqC,oBAAI,IAAI;AAAA,EACtD,cAAc;AAAA,EACd,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,MAAM,aAA4B;AACjC,UAAM,SAAS,MAAM,KAAK,QAAQ,KAAK;AACvC,eAAW,MAAM,QAAQ;AACxB,UAAI,CAAC,KAAK,KAAK,IAAI,GAAG,EAAE,GAAG;AAC1B,aAAK,KAAK,IAAI,GAAG,EAAE;AACnB,aAAK,MAAM,KAAK,EAAE;AAAA,MACnB;AAAA,IACD;AAEA,QAAI,KAAK,MAAM,SAAS,GAAG;AAC1B,WAAK,QAAQ,gBAAgB,KAAK,KAAK;AAAA,IACxC;AACA,SAAK,cAAc;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,IAA8B;AAC3C,QAAI,KAAK,KAAK,IAAI,GAAG,EAAE,EAAG;AAE1B,SAAK,KAAK,IAAI,GAAG,EAAE;AACnB,SAAK,MAAM,KAAK,EAAE;AAClB,UAAM,KAAK,QAAQ,QAAQ,EAAE;AAG7B,QAAI,KAAK,MAAM,SAAS,GAAG;AAC1B,WAAK,QAAQ,gBAAgB,KAAK,KAAK;AAAA,IACxC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,WAAyC;AAClD,QAAI,KAAK,MAAM,WAAW,EAAG,QAAO;AAEpC,UAAM,MAAM,KAAK,MAAM,OAAO,GAAG,SAAS;AAC1C,UAAM,UAAU,SAAS,KAAK,aAAa;AAC3C,SAAK,SAAS,IAAI,SAAS,GAAG;AAE9B,WAAO,EAAE,SAAS,YAAY,IAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAAgC;AACjD,UAAM,MAAM,KAAK,SAAS,IAAI,OAAO;AACrC,QAAI,CAAC,IAAK;AAEV,SAAK,SAAS,OAAO,OAAO;AAC5B,UAAM,MAAM,IAAI,IAAI,CAAC,OAAO,GAAG,EAAE;AACjC,UAAM,KAAK,QAAQ,QAAQ,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAAuB;AAClC,UAAM,MAAM,KAAK,SAAS,IAAI,OAAO;AACrC,QAAI,CAAC,IAAK;AAEV,SAAK,SAAS,OAAO,OAAO;AAE5B,SAAK,MAAM,QAAQ,GAAG,GAAG;AACzB,QAAI,KAAK,MAAM,SAAS,GAAG;AAC1B,WAAK,QAAQ,gBAAgB,KAAK,KAAK;AAAA,IACxC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAe;AAClB,WAAO,KAAK,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,eAAuB;AAC1B,QAAI,gBAAgB;AACpB,eAAW,OAAO,KAAK,SAAS,OAAO,GAAG;AACzC,uBAAiB,IAAI;AAAA,IACtB;AACA,WAAO,KAAK,MAAM,SAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,gBAAyB;AAC5B,WAAO,KAAK,MAAM,SAAS;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,OAA4B;AAChC,WAAO,KAAK,MAAM,MAAM,GAAG,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,gBAAyB;AAC5B,WAAO,KAAK;AAAA,EACb;AACD;;;AD5HA,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAK/B,IAAM,oBAAoD;AAAA,EACzD,cAAc,CAAC,YAAY;AAAA,EAC3B,YAAY,CAAC,eAAe,SAAS,cAAc;AAAA,EACnD,aAAa,CAAC,WAAW,SAAS,cAAc;AAAA,EAChD,SAAS,CAAC,aAAa,SAAS,cAAc;AAAA,EAC9C,WAAW,CAAC,gBAAgB,OAAO;AAAA,EACnC,OAAO,CAAC,cAAc;AACvB;AAoBA,IAAI,gBAAgB;AACpB,SAAS,oBAA4B;AACpC,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,eAAe;AAC5C;AASO,IAAM,aAAN,MAAiB;AAAA,EACf,QAAmB;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,eAA8B,oBAAI,IAAI;AAAA,EACtC,eAA8B;AAAA,EAC9B,eAAqC;AAAA;AAAA,EAGrC,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EAE5B,YAAY,SAA4B;AACvC,SAAK,YAAY,QAAQ;AACzB,SAAK,QAAQ,QAAQ;AACrB,SAAK,SAAS,QAAQ;AACtB,SAAK,aAAa,QAAQ,cAAc,IAAI,4BAA4B,MAAM;AAC9E,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,YAAY,QAAQ,OAAO,aAAa;AAE7C,UAAM,eAAe,QAAQ,gBAAgB,IAAI,mBAAmB;AACpE,SAAK,gBAAgB,IAAI,cAAc,YAAY;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC5B,QAAI,KAAK,UAAU,gBAAgB;AAClC,YAAM,IAAIC,WAAU,uDAAuD;AAAA,QAC1E,cAAc,KAAK;AAAA,MACpB,CAAC;AAAA,IACF;AAEA,UAAM,KAAK,cAAc,WAAW;AAGpC,SAAK,UAAU,UAAU,CAAC,QAAQ,KAAK,cAAc,GAAG,CAAC;AACzD,SAAK,UAAU,QAAQ,CAAC,WAAW,KAAK,qBAAqB,MAAM,CAAC;AACpE,SAAK,UAAU,QAAQ,CAAC,QAAQ,KAAK,qBAAqB,GAAG,CAAC;AAE9D,SAAK,aAAa,YAAY;AAE9B,QAAI;AACH,YAAM,YAAY,KAAK,OAAO,QAAQ,MAAM,KAAK,OAAO,KAAK,GAAG,QAAQ;AAExE,YAAM,KAAK,UAAU,QAAQ,KAAK,OAAO,KAAK,EAAE,UAAU,CAAC;AAC3D,WAAK,aAAa,aAAa;AAG/B,YAAM,cAAc,KAAK,MAAM,iBAAiB;AAChD,YAAM,YAAyB;AAAA,QAC9B,MAAM;AAAA,QACN,WAAW,kBAAkB;AAAA,QAC7B,QAAQ,KAAK,MAAM,UAAU;AAAA,QAC7B,eAAe,oBAAoB,WAAW;AAAA,QAC9C,eAAe,KAAK,OAAO,iBAAiB;AAAA,QAC5C;AAAA,QACA,sBAAsB,CAAC,QAAQ,UAAU;AAAA,MAC1C;AACA,WAAK,UAAU,KAAK,SAAS;AAAA,IAC9B,SAAS,KAAK;AACb,WAAK,aAAa,OAAO;AACzB,WAAK,aAAa,cAAc;AAChC,YAAM;AAAA,IACP;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC3B,QAAI,KAAK,UAAU,eAAgB;AAGnC,QAAI,KAAK,cAAc;AACtB,WAAK,cAAc,YAAY,KAAK,aAAa,OAAO;AACxD,WAAK,eAAe;AAAA,IACrB;AAEA,QAAI;AACH,YAAM,KAAK,UAAU,WAAW;AAAA,IACjC,UAAE;AAGD,WAAK,mBAAmB;AAAA,IACzB;AAAA,EACD;AAAA,EAEQ,qBAA2B;AAClC,QAAI,KAAK,UAAU,gBAAgB;AAClC,WAAK,aAAa,cAAc;AAAA,IACjC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,IAA8B;AACjD,UAAM,KAAK,cAAc,QAAQ,EAAE;AACnC,QAAI,KAAK,UAAU,aAAa;AAC/B,WAAK,WAAW;AAAA,IACjB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,YAA4B;AAC3B,UAAM,oBAAoB,KAAK,cAAc;AAC7C,YAAQ,KAAK,OAAO;AAAA,MACnB,KAAK;AACJ,eAAO,EAAE,QAAQ,WAAW,mBAAmB,cAAc,KAAK,aAAa;AAAA,MAChF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACJ,eAAO,EAAE,QAAQ,WAAW,mBAAmB,cAAc,KAAK,aAAa;AAAA,MAChF,KAAK;AACJ,eAAO;AAAA,UACN,QAAQ,oBAAoB,IAAI,YAAY;AAAA,UAC5C;AAAA,UACA,cAAc,KAAK;AAAA,QACpB;AAAA,MACD,KAAK;AACJ,eAAO,EAAE,QAAQ,SAAS,mBAAmB,cAAc,KAAK,aAAa;AAAA,IAC/E;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAsB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAkC;AACjC,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAIQ,cAAc,SAA4B;AACjD,YAAQ,QAAQ,MAAM;AAAA,MACrB,KAAK;AACJ,aAAK,wBAAwB,OAAO;AACpC;AAAA,MACD,KAAK;AACJ,aAAK,qBAAqB,OAAO;AACjC;AAAA,MACD,KAAK;AACJ,aAAK,qBAAqB,OAAO;AACjC;AAAA,MACD,KAAK;AACJ,aAAK,YAAY,OAAO;AACxB;AAAA,IACF;AAAA,EACD;AAAA,EAEQ,wBAAwB,KAAqC;AACpE,QAAI,KAAK,UAAU,cAAe;AAElC,QAAI,CAAC,IAAI,UAAU;AAClB,WAAK,aAAa,OAAO;AACzB,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,QAAQ,IAAI,gBAAgB;AAAA,MAC7B,CAAC;AACD,WAAK,aAAa,cAAc;AAChC;AAAA,IACD;AAEA,SAAK,eAAe,oBAAoB,IAAI,aAAa;AAEzD,QAAI,IAAI,oBAAoB;AAC3B,WAAK,wBAAwB,IAAI,kBAAkB;AAAA,IACpD;AAEA,SAAK,SAAS,KAAK,EAAE,MAAM,kBAAkB,QAAQ,KAAK,MAAM,UAAU,EAAE,CAAC;AAE7E,SAAK,aAAa,SAAS;AAC3B,SAAK,uBAAuB;AAC5B,SAAK,uBAAuB;AAC5B,SAAK,oBAAoB;AAGzB,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,MAAc,YAA2B;AACxC,UAAM,cAAc,KAAK,MAAM,iBAAiB;AAChD,UAAM,aAAa,MAAM,KAAK,aAAa,aAAa,KAAK,YAAY;AAEzE,QAAI,WAAW,WAAW,GAAG;AAE5B,YAAM,aAA0B;AAAA,QAC/B,MAAM;AAAA,QACN,WAAW,kBAAkB;AAAA,QAC7B,YAAY,CAAC;AAAA,QACb,SAAS;AAAA,QACT,YAAY;AAAA,MACb;AACA,WAAK,UAAU,KAAK,UAAU;AAC9B,WAAK,oBAAoB;AACzB,WAAK,mBAAmB;AACxB;AAAA,IACD;AAGA,UAAM,SAASC,iBAAgB,UAAU;AACzC,UAAM,eAAe,KAAK,KAAK,OAAO,SAAS,KAAK,SAAS;AAE7D,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACtC,YAAM,QAAQ,IAAI,KAAK;AACvB,YAAM,WAAW,OAAO,MAAM,OAAO,QAAQ,KAAK,SAAS;AAC3D,YAAM,gBAAgB,SAAS,IAAI,CAAC,OAAO,KAAK,WAAW,gBAAgB,EAAE,CAAC;AAE9E,YAAM,WAAwB;AAAA,QAC7B,MAAM;AAAA,QACN,WAAW,kBAAkB;AAAA,QAC7B,YAAY;AAAA,QACZ,SAAS,MAAM,eAAe;AAAA,QAC9B,YAAY;AAAA,MACb;AACA,WAAK,UAAU,KAAK,QAAQ;AAE5B,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW,SAAS;AAAA,MACrB,CAAC;AAAA,IACF;AAEA,SAAK,oBAAoB;AACzB,SAAK,mBAAmB;AAAA,EACzB;AAAA,EAEA,MAAc,aACb,aACA,cACuB;AACvB,UAAM,UAAuB,CAAC;AAC9B,eAAW,CAAC,QAAQ,QAAQ,KAAK,aAAa;AAC7C,YAAM,YAAY,aAAa,IAAI,MAAM,KAAK;AAC9C,UAAI,WAAW,WAAW;AACzB,cAAM,MAAM,MAAM,KAAK,MAAM,kBAAkB,QAAQ,YAAY,GAAG,QAAQ;AAC9E,gBAAQ,KAAK,GAAG,GAAG;AAAA,MACpB;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAc,qBAAqB,KAA2C;AAC7E,UAAM,aAAa,IAAI,WAAW,IAAI,CAAC,MAAM,KAAK,WAAW,gBAAgB,CAAC,CAAC;AAG/E,eAAW,MAAM,YAAY;AAC5B,YAAM,KAAK,MAAM,qBAAqB,EAAE;AAAA,IACzC;AAEA,QAAI,WAAW,SAAS,GAAG;AAC1B,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN;AAAA,QACA,WAAW,WAAW;AAAA,MACvB,CAAC;AAAA,IACF;AAGA,UAAM,SAAS,WAAW,WAAW,SAAS,CAAC;AAC/C,UAAM,MAAmB;AAAA,MACxB,MAAM;AAAA,MACN,WAAW,kBAAkB;AAAA,MAC7B,uBAAuB,IAAI;AAAA,MAC3B,oBAAoB,SAAS,OAAO,iBAAiB;AAAA,IACtD;AACA,SAAK,UAAU,KAAK,GAAG;AAEvB,SAAK,SAAS,KAAK;AAAA,MAClB,MAAM;AAAA,MACN,gBAAgB,SAAS,OAAO,iBAAiB;AAAA,IAClD,CAAC;AAED,QAAI,KAAK,UAAU,WAAW;AAC7B,WAAK;AACL,UAAI,IAAI,SAAS;AAChB,aAAK,uBAAuB;AAC5B,aAAK,mBAAmB;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,qBAAqB,KAAkC;AAC9D,QAAI,KAAK,cAAc;AACtB,WAAK,cAAc,YAAY,KAAK,aAAa,OAAO;AACxD,WAAK,eAAe;AACpB,WAAK,eAAe,KAAK,IAAI;AAAA,IAC9B;AAGA,QAAI,KAAK,UAAU,eAAe,KAAK,cAAc,eAAe;AACnE,WAAK,WAAW;AAAA,IACjB;AAAA,EACD;AAAA,EAEQ,YAAY,KAAkE;AACrF,SAAK,aAAa,OAAO;AACzB,SAAK,SAAS,KAAK,EAAE,MAAM,qBAAqB,QAAQ,IAAI,QAAQ,CAAC;AACrE,SAAK,aAAa,cAAc;AAAA,EACjC;AAAA,EAEQ,qBAA2B;AAClC,QAAI,KAAK,qBAAqB,KAAK,sBAAsB;AACxD,WAAK,eAAe,KAAK,IAAI;AAC7B,WAAK,aAAa,WAAW;AAG7B,UAAI,KAAK,cAAc,eAAe;AACrC,aAAK,WAAW;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,aAAmB;AAC1B,QAAI,KAAK,aAAc;AACvB,QAAI,CAAC,KAAK,cAAc,cAAe;AAEvC,UAAM,QAAQ,KAAK,cAAc,UAAU,KAAK,SAAS;AACzD,QAAI,CAAC,MAAO;AAEZ,SAAK,eAAe;AAEpB,UAAM,gBAAgB,MAAM,WAAW,IAAI,CAAC,OAAO,KAAK,WAAW,gBAAgB,EAAE,CAAC;AACtF,UAAM,WAAwB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAW,kBAAkB;AAAA,MAC7B,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,IACb;AACA,SAAK,UAAU,KAAK,QAAQ;AAE5B,SAAK,SAAS,KAAK;AAAA,MAClB,MAAM;AAAA,MACN,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM,WAAW;AAAA,IAC7B,CAAC;AAAA,EACF;AAAA,EAEQ,qBAAqB,QAAsB;AAElD,QAAI,KAAK,cAAc;AACtB,WAAK,cAAc,YAAY,KAAK,aAAa,OAAO;AACxD,WAAK,eAAe;AAAA,IACrB;AAEA,QAAI,KAAK,UAAU,gBAAgB;AAClC,WAAK,SAAS,KAAK,EAAE,MAAM,qBAAqB,OAAO,CAAC;AACxD,WAAK,aAAa,cAAc;AAAA,IACjC;AAAA,EACD;AAAA,EAEQ,qBAAqB,KAAkB;AAE9C,QAAI,KAAK,UAAU,gBAAgB;AAClC,WAAK,aAAa,OAAO;AACzB,WAAK,SAAS,KAAK,EAAE,MAAM,qBAAqB,QAAQ,IAAI,QAAQ,CAAC;AACrE,WAAK,aAAa,cAAc;AAAA,IACjC;AAAA,EACD;AAAA,EAEQ,aAAa,UAA2B;AAC/C,UAAM,eAAe,kBAAkB,KAAK,KAAK;AACjD,QAAI,CAAC,aAAa,SAAS,QAAQ,GAAG;AACrC,YAAM,IAAID,WAAU,kCAAkC,KAAK,KAAK,WAAM,QAAQ,IAAI;AAAA,QACjF,MAAM,KAAK;AAAA,QACX,IAAI;AAAA,MACL,CAAC;AAAA,IACF;AACA,SAAK,QAAQ;AAAA,EACd;AAAA,EAEQ,wBAAwB,QAA0B;AACzD,QAAI,OAAO,KAAK,WAAW,kBAAkB,YAAY;AACxD,WAAK,WAAW,cAAc,MAAM;AAAA,IACrC;AAAA,EACD;AACD;;;AEhcO,IAAM,oBAAN,MAAwB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAsB,CAAC;AAAA,EACvB,aAAa;AAAA,EACb;AAAA,EAER,YAAY,QAAkC;AAC7C,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,iBAAiB,QAAQ,kBAAkB;AAChD,SAAK,aAAa,QAAQ,cAAc,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE;AAChE,SAAK,mBAAmB,KAAK,WAAW,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,IAAkB;AAC/B,SAAK,UAAU,KAAK,EAAE;AACtB,QAAI,KAAK,UAAU,SAAS,KAAK,YAAY;AAC5C,WAAK,UAAU,MAAM;AAAA,IACtB;AACA,SAAK,mBAAmB,KAAK,WAAW,IAAI;AAE5C,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwB;AACvB,SAAK;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAuB;AACtB,SAAK,mBAAmB,KAAK,WAAW,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAgC;AAC/B,UAAM,UAAU,KAAK,WAAW,IAAI,IAAI,KAAK;AAC7C,QAAI,UAAU,KAAK,eAAgB,QAAO;AAE1C,QAAI,KAAK,UAAU,WAAW,GAAG;AAEhC,aAAO,KAAK,aAAa,IAAI,SAAS;AAAA,IACvC;AAEA,UAAM,aAAa,KAAK,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,KAAK,UAAU;AAElF,QAAI,KAAK,aAAa,EAAG,QAAO;AAChC,QAAI,aAAa,OAAO,KAAK,eAAe,EAAG,QAAO;AACtD,QAAI,aAAa,OAAO,KAAK,cAAc,EAAG,QAAO;AACrD,QAAI,aAAa,OAAQ,KAAK,cAAc,EAAG,QAAO;AACtD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,YAAY,CAAC;AAClB,SAAK,aAAa;AAClB,SAAK,mBAAmB,KAAK,WAAW,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAmC;AAClC,QAAI,KAAK,UAAU,WAAW,EAAG,QAAO;AACxC,WAAO,KAAK,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,KAAK,UAAU;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAwB;AACvB,WAAO,KAAK;AAAA,EACb;AACD;;;ACrFO,IAAM,sBAAN,MAA0B;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAU;AAAA,EACV,QAA8C;AAAA,EAC9C,UAAU;AAAA,EACV,cAAmC;AAAA,EAE3C,YAAY,QAA6B;AACxC,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,SAAS,QAAQ,gBAAgB,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAM,aAAuD;AAClE,SAAK,UAAU;AACf,SAAK,UAAU;AAEf,WAAO,CAAC,KAAK,SAAS;AACrB,UAAI,KAAK,cAAc,KAAK,KAAK,WAAW,KAAK,aAAa;AAC7D,eAAO;AAAA,MACR;AAEA,YAAM,QAAQ,KAAK,aAAa;AAChC,WAAK;AAEL,YAAM,KAAK,KAAK,KAAK;AAErB,UAAI,KAAK,QAAS,QAAO;AAEzB,UAAI;AACH,cAAM,UAAU,MAAM,YAAY;AAClC,YAAI,SAAS;AACZ,eAAK,MAAM;AACX,iBAAO;AAAA,QACR;AAAA,MACD,QAAQ;AAAA,MAER;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACZ,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,MAAM;AACxB,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACd;AAEA,QAAI,KAAK,aAAa;AACrB,WAAK,YAAY;AACjB,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,UAAU;AACf,SAAK,UAAU;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAuB;AACtB,UAAM,YAAY,KAAK,IAAI,KAAK,eAAe,KAAK,cAAc,KAAK,SAAS,KAAK,QAAQ;AAG7F,UAAM,cAAc,YAAY,KAAK;AACrC,UAAM,gBAAgB,KAAK,OAAO,IAAI,OAAO,IAAI;AACjD,WAAO,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,YAAY,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0B;AACzB,WAAO,KAAK;AAAA,EACb;AAAA,EAEQ,KAAK,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC/B,WAAK,cAAc;AACnB,WAAK,QAAQ,WAAW,MAAM;AAC7B,aAAK,QAAQ;AACb,aAAK,cAAc;AACnB,gBAAQ;AAAA,MACT,GAAG,EAAE;AAAA,IACN,CAAC;AAAA,EACF;AACD;","names":["SyncError","SyncError","SyncError","SyncError","SyncError","topologicalSort","SyncError","topologicalSort"]}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/internal.ts
21
+ var internal_exports = {};
22
+ __export(internal_exports, {
23
+ MemoryQueueStorage: () => MemoryQueueStorage,
24
+ MemoryTransport: () => MemoryTransport,
25
+ createMemoryTransportPair: () => createMemoryTransportPair
26
+ });
27
+ module.exports = __toCommonJS(internal_exports);
28
+
29
+ // src/transport/memory-transport.ts
30
+ var import_core = require("@korajs/core");
31
+ var MemoryTransport = class {
32
+ connected = false;
33
+ messageHandler = null;
34
+ closeHandler = null;
35
+ errorHandler = null;
36
+ peer = null;
37
+ sentMessages = [];
38
+ /** Link this transport to its peer (the other end of the connection) */
39
+ linkPeer(peer) {
40
+ this.peer = peer;
41
+ }
42
+ async connect(_url, _options) {
43
+ if (!this.peer) {
44
+ throw new import_core.SyncError("MemoryTransport has no linked peer", {
45
+ reason: "not-linked"
46
+ });
47
+ }
48
+ this.connected = true;
49
+ this.peer.connected = true;
50
+ }
51
+ async disconnect() {
52
+ if (!this.connected) return;
53
+ this.connected = false;
54
+ if (this.peer?.connected) {
55
+ this.peer.connected = false;
56
+ this.peer.closeHandler?.("peer disconnected");
57
+ }
58
+ }
59
+ send(message) {
60
+ if (!this.connected) {
61
+ throw new import_core.SyncError("Cannot send message: transport is not connected", {
62
+ messageType: message.type
63
+ });
64
+ }
65
+ this.sentMessages.push(message);
66
+ this.peer?.messageHandler?.(message);
67
+ }
68
+ onMessage(handler) {
69
+ this.messageHandler = handler;
70
+ }
71
+ onClose(handler) {
72
+ this.closeHandler = handler;
73
+ }
74
+ onError(handler) {
75
+ this.errorHandler = handler;
76
+ }
77
+ isConnected() {
78
+ return this.connected;
79
+ }
80
+ // --- Testing helpers ---
81
+ /**
82
+ * Simulate an incoming message (as if received from peer).
83
+ * Useful for testing without a linked peer.
84
+ */
85
+ simulateIncoming(message) {
86
+ this.messageHandler?.(message);
87
+ }
88
+ /**
89
+ * Simulate a disconnect from the remote side.
90
+ */
91
+ simulateDisconnect(reason) {
92
+ this.connected = false;
93
+ this.closeHandler?.(reason);
94
+ }
95
+ /**
96
+ * Simulate a transport error.
97
+ */
98
+ simulateError(error) {
99
+ this.errorHandler?.(error);
100
+ }
101
+ /**
102
+ * Get all messages sent through this transport.
103
+ */
104
+ getSentMessages() {
105
+ return [...this.sentMessages];
106
+ }
107
+ /**
108
+ * Clear the sent messages history.
109
+ */
110
+ clearSentMessages() {
111
+ this.sentMessages.length = 0;
112
+ }
113
+ };
114
+ function createMemoryTransportPair() {
115
+ const client = new MemoryTransport();
116
+ const server = new MemoryTransport();
117
+ client.linkPeer(server);
118
+ server.linkPeer(client);
119
+ return { client, server };
120
+ }
121
+
122
+ // src/engine/memory-queue-storage.ts
123
+ var MemoryQueueStorage = class {
124
+ operations = /* @__PURE__ */ new Map();
125
+ async load() {
126
+ return [...this.operations.values()];
127
+ }
128
+ async enqueue(op) {
129
+ this.operations.set(op.id, op);
130
+ }
131
+ async dequeue(ids) {
132
+ for (const id of ids) {
133
+ this.operations.delete(id);
134
+ }
135
+ }
136
+ async count() {
137
+ return this.operations.size;
138
+ }
139
+ };
140
+ // Annotate the CommonJS export names for ESM import in node:
141
+ 0 && (module.exports = {
142
+ MemoryQueueStorage,
143
+ MemoryTransport,
144
+ createMemoryTransportPair
145
+ });
146
+ //# sourceMappingURL=internal.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal.ts","../src/transport/memory-transport.ts","../src/engine/memory-queue-storage.ts"],"sourcesContent":["// Internal exports — shared within @kora packages but NOT part of the public API.\n// Other @kora packages can import from '@korajs/sync/internal' if needed.\n\nexport { MemoryTransport, createMemoryTransportPair } from './transport/memory-transport'\nexport { MemoryQueueStorage } from './engine/memory-queue-storage'\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '../protocol/messages'\nimport type {\n\tSyncTransport,\n\tTransportCloseHandler,\n\tTransportErrorHandler,\n\tTransportMessageHandler,\n\tTransportOptions,\n} from './transport'\n\n/**\n * In-memory transport for testing. Provides instant, synchronous message delivery\n * between a linked pair of transports (simulating client ↔ server).\n */\nexport class MemoryTransport implements SyncTransport {\n\tprivate connected = false\n\tprivate messageHandler: TransportMessageHandler | null = null\n\tprivate closeHandler: TransportCloseHandler | null = null\n\tprivate errorHandler: TransportErrorHandler | null = null\n\tprivate peer: MemoryTransport | null = null\n\tprivate readonly sentMessages: SyncMessage[] = []\n\n\t/** Link this transport to its peer (the other end of the connection) */\n\tlinkPeer(peer: MemoryTransport): void {\n\t\tthis.peer = peer\n\t}\n\n\tasync connect(_url: string, _options?: TransportOptions): Promise<void> {\n\t\tif (!this.peer) {\n\t\t\tthrow new SyncError('MemoryTransport has no linked peer', {\n\t\t\t\treason: 'not-linked',\n\t\t\t})\n\t\t}\n\t\tthis.connected = true\n\t\tthis.peer.connected = true\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (!this.connected) return\n\t\tthis.connected = false\n\t\t// Notify peer that we disconnected\n\t\tif (this.peer?.connected) {\n\t\t\tthis.peer.connected = false\n\t\t\tthis.peer.closeHandler?.('peer disconnected')\n\t\t}\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('Cannot send message: transport is not connected', {\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\t\tthis.sentMessages.push(message)\n\t\t// Deliver to peer's message handler\n\t\tthis.peer?.messageHandler?.(message)\n\t}\n\n\tonMessage(handler: TransportMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: TransportCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: TransportErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected\n\t}\n\n\t// --- Testing helpers ---\n\n\t/**\n\t * Simulate an incoming message (as if received from peer).\n\t * Useful for testing without a linked peer.\n\t */\n\tsimulateIncoming(message: SyncMessage): void {\n\t\tthis.messageHandler?.(message)\n\t}\n\n\t/**\n\t * Simulate a disconnect from the remote side.\n\t */\n\tsimulateDisconnect(reason: string): void {\n\t\tthis.connected = false\n\t\tthis.closeHandler?.(reason)\n\t}\n\n\t/**\n\t * Simulate a transport error.\n\t */\n\tsimulateError(error: Error): void {\n\t\tthis.errorHandler?.(error)\n\t}\n\n\t/**\n\t * Get all messages sent through this transport.\n\t */\n\tgetSentMessages(): SyncMessage[] {\n\t\treturn [...this.sentMessages]\n\t}\n\n\t/**\n\t * Clear the sent messages history.\n\t */\n\tclearSentMessages(): void {\n\t\tthis.sentMessages.length = 0\n\t}\n}\n\n/**\n * Create a linked pair of memory transports for testing.\n * Messages sent on `client` arrive at `server` and vice versa.\n */\nexport function createMemoryTransportPair(): { client: MemoryTransport; server: MemoryTransport } {\n\tconst client = new MemoryTransport()\n\tconst server = new MemoryTransport()\n\tclient.linkPeer(server)\n\tserver.linkPeer(client)\n\treturn { client, server }\n}\n","import type { Operation } from '@korajs/core'\nimport type { QueueStorage } from '../types'\n\n/**\n * In-memory QueueStorage implementation for testing.\n * Operations are lost on process restart — production should use\n * IndexedDB or OPFS-backed storage.\n */\nexport class MemoryQueueStorage implements QueueStorage {\n\tprivate operations: Map<string, Operation> = new Map()\n\n\tasync load(): Promise<Operation[]> {\n\t\treturn [...this.operations.values()]\n\t}\n\n\tasync enqueue(op: Operation): Promise<void> {\n\t\tthis.operations.set(op.id, op)\n\t}\n\n\tasync dequeue(ids: string[]): Promise<void> {\n\t\tfor (const id of ids) {\n\t\t\tthis.operations.delete(id)\n\t\t}\n\t}\n\n\tasync count(): Promise<number> {\n\t\treturn this.operations.size\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA0B;AAcnB,IAAM,kBAAN,MAA+C;AAAA,EAC7C,YAAY;AAAA,EACZ,iBAAiD;AAAA,EACjD,eAA6C;AAAA,EAC7C,eAA6C;AAAA,EAC7C,OAA+B;AAAA,EACtB,eAA8B,CAAC;AAAA;AAAA,EAGhD,SAAS,MAA6B;AACrC,SAAK,OAAO;AAAA,EACb;AAAA,EAEA,MAAM,QAAQ,MAAc,UAA4C;AACvE,QAAI,CAAC,KAAK,MAAM;AACf,YAAM,IAAI,sBAAU,sCAAsC;AAAA,QACzD,QAAQ;AAAA,MACT,CAAC;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,KAAK,YAAY;AAAA,EACvB;AAAA,EAEA,MAAM,aAA4B;AACjC,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,YAAY;AAEjB,QAAI,KAAK,MAAM,WAAW;AACzB,WAAK,KAAK,YAAY;AACtB,WAAK,KAAK,eAAe,mBAAmB;AAAA,IAC7C;AAAA,EACD;AAAA,EAEA,KAAK,SAA4B;AAChC,QAAI,CAAC,KAAK,WAAW;AACpB,YAAM,IAAI,sBAAU,mDAAmD;AAAA,QACtE,aAAa,QAAQ;AAAA,MACtB,CAAC;AAAA,IACF;AACA,SAAK,aAAa,KAAK,OAAO;AAE9B,SAAK,MAAM,iBAAiB,OAAO;AAAA,EACpC;AAAA,EAEA,UAAU,SAAwC;AACjD,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,QAAQ,SAAsC;AAC7C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,SAA4B;AAC5C,SAAK,iBAAiB,OAAO;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,QAAsB;AACxC,SAAK,YAAY;AACjB,SAAK,eAAe,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,OAAoB;AACjC,SAAK,eAAe,KAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAiC;AAChC,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA0B;AACzB,SAAK,aAAa,SAAS;AAAA,EAC5B;AACD;AAMO,SAAS,4BAAkF;AACjG,QAAM,SAAS,IAAI,gBAAgB;AACnC,QAAM,SAAS,IAAI,gBAAgB;AACnC,SAAO,SAAS,MAAM;AACtB,SAAO,SAAS,MAAM;AACtB,SAAO,EAAE,QAAQ,OAAO;AACzB;;;ACpHO,IAAM,qBAAN,MAAiD;AAAA,EAC/C,aAAqC,oBAAI,IAAI;AAAA,EAErD,MAAM,OAA6B;AAClC,WAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,QAAQ,IAA8B;AAC3C,SAAK,WAAW,IAAI,GAAG,IAAI,EAAE;AAAA,EAC9B;AAAA,EAEA,MAAM,QAAQ,KAA8B;AAC3C,eAAW,MAAM,KAAK;AACrB,WAAK,WAAW,OAAO,EAAE;AAAA,IAC1B;AAAA,EACD;AAAA,EAEA,MAAM,QAAyB;AAC9B,WAAO,KAAK,WAAW;AAAA,EACxB;AACD;","names":[]}
@@ -0,0 +1,68 @@
1
+ import { b as SyncTransport, T as TransportOptions, S as SyncMessage, c as TransportMessageHandler, d as TransportCloseHandler, e as TransportErrorHandler, Q as QueueStorage } from './transport-B5EFsr5F.cjs';
2
+ import { Operation } from '@korajs/core';
3
+
4
+ /**
5
+ * In-memory transport for testing. Provides instant, synchronous message delivery
6
+ * between a linked pair of transports (simulating client ↔ server).
7
+ */
8
+ declare class MemoryTransport implements SyncTransport {
9
+ private connected;
10
+ private messageHandler;
11
+ private closeHandler;
12
+ private errorHandler;
13
+ private peer;
14
+ private readonly sentMessages;
15
+ /** Link this transport to its peer (the other end of the connection) */
16
+ linkPeer(peer: MemoryTransport): void;
17
+ connect(_url: string, _options?: TransportOptions): Promise<void>;
18
+ disconnect(): Promise<void>;
19
+ send(message: SyncMessage): void;
20
+ onMessage(handler: TransportMessageHandler): void;
21
+ onClose(handler: TransportCloseHandler): void;
22
+ onError(handler: TransportErrorHandler): void;
23
+ isConnected(): boolean;
24
+ /**
25
+ * Simulate an incoming message (as if received from peer).
26
+ * Useful for testing without a linked peer.
27
+ */
28
+ simulateIncoming(message: SyncMessage): void;
29
+ /**
30
+ * Simulate a disconnect from the remote side.
31
+ */
32
+ simulateDisconnect(reason: string): void;
33
+ /**
34
+ * Simulate a transport error.
35
+ */
36
+ simulateError(error: Error): void;
37
+ /**
38
+ * Get all messages sent through this transport.
39
+ */
40
+ getSentMessages(): SyncMessage[];
41
+ /**
42
+ * Clear the sent messages history.
43
+ */
44
+ clearSentMessages(): void;
45
+ }
46
+ /**
47
+ * Create a linked pair of memory transports for testing.
48
+ * Messages sent on `client` arrive at `server` and vice versa.
49
+ */
50
+ declare function createMemoryTransportPair(): {
51
+ client: MemoryTransport;
52
+ server: MemoryTransport;
53
+ };
54
+
55
+ /**
56
+ * In-memory QueueStorage implementation for testing.
57
+ * Operations are lost on process restart — production should use
58
+ * IndexedDB or OPFS-backed storage.
59
+ */
60
+ declare class MemoryQueueStorage implements QueueStorage {
61
+ private operations;
62
+ load(): Promise<Operation[]>;
63
+ enqueue(op: Operation): Promise<void>;
64
+ dequeue(ids: string[]): Promise<void>;
65
+ count(): Promise<number>;
66
+ }
67
+
68
+ export { MemoryQueueStorage, MemoryTransport, createMemoryTransportPair };
@@ -0,0 +1,68 @@
1
+ import { b as SyncTransport, T as TransportOptions, S as SyncMessage, c as TransportMessageHandler, d as TransportCloseHandler, e as TransportErrorHandler, Q as QueueStorage } from './transport-B5EFsr5F.js';
2
+ import { Operation } from '@korajs/core';
3
+
4
+ /**
5
+ * In-memory transport for testing. Provides instant, synchronous message delivery
6
+ * between a linked pair of transports (simulating client ↔ server).
7
+ */
8
+ declare class MemoryTransport implements SyncTransport {
9
+ private connected;
10
+ private messageHandler;
11
+ private closeHandler;
12
+ private errorHandler;
13
+ private peer;
14
+ private readonly sentMessages;
15
+ /** Link this transport to its peer (the other end of the connection) */
16
+ linkPeer(peer: MemoryTransport): void;
17
+ connect(_url: string, _options?: TransportOptions): Promise<void>;
18
+ disconnect(): Promise<void>;
19
+ send(message: SyncMessage): void;
20
+ onMessage(handler: TransportMessageHandler): void;
21
+ onClose(handler: TransportCloseHandler): void;
22
+ onError(handler: TransportErrorHandler): void;
23
+ isConnected(): boolean;
24
+ /**
25
+ * Simulate an incoming message (as if received from peer).
26
+ * Useful for testing without a linked peer.
27
+ */
28
+ simulateIncoming(message: SyncMessage): void;
29
+ /**
30
+ * Simulate a disconnect from the remote side.
31
+ */
32
+ simulateDisconnect(reason: string): void;
33
+ /**
34
+ * Simulate a transport error.
35
+ */
36
+ simulateError(error: Error): void;
37
+ /**
38
+ * Get all messages sent through this transport.
39
+ */
40
+ getSentMessages(): SyncMessage[];
41
+ /**
42
+ * Clear the sent messages history.
43
+ */
44
+ clearSentMessages(): void;
45
+ }
46
+ /**
47
+ * Create a linked pair of memory transports for testing.
48
+ * Messages sent on `client` arrive at `server` and vice versa.
49
+ */
50
+ declare function createMemoryTransportPair(): {
51
+ client: MemoryTransport;
52
+ server: MemoryTransport;
53
+ };
54
+
55
+ /**
56
+ * In-memory QueueStorage implementation for testing.
57
+ * Operations are lost on process restart — production should use
58
+ * IndexedDB or OPFS-backed storage.
59
+ */
60
+ declare class MemoryQueueStorage implements QueueStorage {
61
+ private operations;
62
+ load(): Promise<Operation[]>;
63
+ enqueue(op: Operation): Promise<void>;
64
+ dequeue(ids: string[]): Promise<void>;
65
+ count(): Promise<number>;
66
+ }
67
+
68
+ export { MemoryQueueStorage, MemoryTransport, createMemoryTransportPair };