@sqlite-sync/core 0.1.1 → 0.2.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.
- package/dist/{chunk-UGF5IU53.js → chunk-NHT3ELMN.js} +34 -6
- package/dist/chunk-NHT3ELMN.js.map +1 -0
- package/dist/{chunk-627DSM2Q.js → chunk-O4WYEB4H.js} +565 -176
- package/dist/chunk-O4WYEB4H.js.map +1 -0
- package/dist/{crdt-sync-remote-source-idoIjMcs.d.ts → crdt-sync-remote-source-Na9Uicu6.d.ts} +130 -45
- package/dist/index.d.ts +66 -34
- package/dist/index.js +154 -94
- package/dist/index.js.map +1 -1
- package/dist/{crdt-schema-DQ1cYsFE.d.ts → reset-state-WqgHBSA4.d.ts} +20 -2
- package/dist/server.d.ts +7 -2
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +11 -3
- package/dist/worker.js +119 -89
- package/dist/worker.js.map +1 -1
- package/package.json +7 -3
- package/dist/chunk-627DSM2Q.js.map +0 -1
- package/dist/chunk-UGF5IU53.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dummy-kysely.ts","../src/hlc.ts","../src/introspection.ts","../src/logger.ts","../src/sqlite-db-wrapper.ts","../src/migrations/migrator.ts","../src/sqlite-crdt/stored-value.ts","../src/sqlite-kv-store.ts","../src/migrations/system-schema.ts","../src/sqlite-crdt/apply-crdt-event.ts","../src/sqlite-crdt/crdt-storage.ts","../src/sqlite-crdt/crdt-sync-producer.ts","../src/sqlite-crdt/crdt-sync-remote-source.ts","../src/sqlite-crdt/events-batch-filters.ts","../src/worker-db/worker-common.ts"],"sourcesContent":["import { DummyDriver, Kysely, SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from \"kysely\";\n\nexport const dummyKysely: Kysely<any> = new Kysely({\n dialect: {\n createAdapter: () => new SqliteAdapter(),\n createDriver: () => new DummyDriver(),\n createQueryCompiler: () => new SqliteQueryCompiler(),\n createIntrospector: (db) => new SqliteIntrospector(db),\n },\n});\n","export interface HLC {\n timestamp: number;\n counter: number;\n nodeId: string;\n}\n\nconst MAX_COUNTER = 36 ** 5 - 1; // 60,466,175 — max value that fits in 5-char base36\nconst DEFAULT_MAX_DRIFT_MS = 6 * 60 * 60 * 1000; // 6 hours\n\nexport class HLCCounter {\n private timestamp: number;\n private counter: number;\n private nodeId: string;\n\n private readonly getTimestamp: () => number;\n private readonly maxDrift: number;\n\n constructor(nodeId: string, getTimestamp: () => number, maxDrift: number = DEFAULT_MAX_DRIFT_MS) {\n this.timestamp = getTimestamp();\n this.counter = 0;\n this.nodeId = nodeId;\n this.getTimestamp = getTimestamp;\n this.maxDrift = maxDrift;\n }\n\n getCurrentHLC(): HLC {\n return {\n timestamp: this.timestamp,\n counter: this.counter,\n nodeId: this.nodeId,\n };\n }\n\n getNextHLC(): HLC {\n const now = this.getTimestamp();\n\n if (now > this.timestamp) {\n this.timestamp = now;\n this.counter = 0;\n return this.getCurrentHLC();\n }\n\n this.counter++;\n if (this.counter > MAX_COUNTER) {\n throw new Error(`HLC counter overflow: exceeded max value ${MAX_COUNTER}`);\n }\n return this.getCurrentHLC();\n }\n\n mergeHLC(hlc: HLC) {\n const now = this.getTimestamp();\n if (hlc.timestamp - now > this.maxDrift) {\n console.warn(\n `HLC: ignoring far-future timestamp (remote=${hlc.timestamp}, local=${now}, drift=${hlc.timestamp - now}ms)`,\n );\n return;\n }\n\n if (this.timestamp === hlc.timestamp) {\n this.counter = Math.max(this.counter, hlc.counter) + 1;\n } else if (this.timestamp > hlc.timestamp) {\n this.counter++;\n } else {\n this.timestamp = hlc.timestamp;\n this.counter = hlc.counter + 1;\n }\n if (this.counter > MAX_COUNTER) {\n throw new Error(`HLC counter overflow: exceeded max value ${MAX_COUNTER}`);\n }\n }\n}\n\nexport function serializeHLC(hlc: HLC) {\n return `${hlc.timestamp.toString().padStart(15, \"0\")}:${hlc.counter.toString(36).padStart(5, \"0\")}:${hlc.nodeId}`;\n}\n\nexport function deserializeHLC(serialized: string): HLC {\n const parts = serialized.split(\":\");\n if (parts.length < 3) {\n throw new Error(`Invalid HLC format: expected at least 3 colon-separated segments, got ${parts.length}`);\n }\n\n const timestamp = parseInt(parts[0], 10);\n const counter = parseInt(parts[1], 36);\n\n if (Number.isNaN(timestamp) || Number.isNaN(counter)) {\n throw new Error(`Invalid HLC values: timestamp=${parts[0]}, counter=${parts[1]}`);\n }\n\n return {\n timestamp,\n counter,\n nodeId: parts.slice(2).join(\":\"),\n };\n}\n\nexport function compareHLC(one: HLC, two: HLC) {\n if (one.timestamp === two.timestamp) {\n if (one.counter === two.counter) {\n if (one.nodeId === two.nodeId) {\n return 0;\n }\n return one.nodeId < two.nodeId ? -1 : 1;\n }\n return one.counter - two.counter;\n }\n return one.timestamp - two.timestamp;\n}\n","import type { Kysely, QueryCreator } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SQLiteDbWrapper } from \"./sqlite-db-wrapper\";\n\ninterface SqliteSystemDatabase {\n // https://www.sqlite.org/schematab.html#alternative_names\n sqlite_master: SQliteMasterTable;\n}\n\n// https://www.sqlite.org/schematab.html#interpretation_of_the_schema_table\ninterface SQliteMasterTable {\n name: string;\n rootpage: number | null;\n sql: string;\n tbl_name: string;\n type: \"index\" | \"table\" | \"trigger\" | \"view\";\n}\n\n// https://www.sqlite.org/pragma.html#pragma_table_info\ninterface PragmaTableInfo {\n cid: number;\n dflt_value: unknown;\n name: string;\n notnull: 0 | 1;\n pk: number;\n type: string;\n}\n\nfunction tablesQuery(qb: QueryCreator<SqliteSystemDatabase> | Kysely<SqliteSystemDatabase>) {\n return qb\n .selectFrom(\"sqlite_master\")\n .where(\"type\", \"in\", [\"table\", \"view\"])\n .where(\"name\", \"not like\", \"sqlite_%\")\n .select([\"name\", \"sql\", \"type\"])\n .orderBy(\"name\");\n}\n\nexport type TableMetadata = {\n name: string;\n isView: boolean;\n columns: ColumnMetadata[];\n};\n\nexport type DatabaseIntrospection = Record<string, TableMetadata>;\n\ntype ColumnMetadata = {\n name: string;\n dataType: string;\n isNullable: boolean;\n isAutoIncrementing: boolean;\n hasDefaultValue: boolean;\n comment: undefined;\n};\n\nexport function introspectDb<BaseDatabase>(_db: SQLiteDbWrapper<BaseDatabase>): DatabaseIntrospection {\n const db = _db as unknown as SQLiteDbWrapper<SqliteSystemDatabase>;\n const tables = db.executeKysely((db) => tablesQuery(db as unknown as Kysely<SqliteSystemDatabase>), {\n loggerLevel: \"system\",\n }).rows;\n\n const tablesMetadata = db.executeKysely(\n (db) =>\n db\n .with(\"table_list\", (qb) => tablesQuery(qb as unknown as Kysely<SqliteSystemDatabase>))\n .selectFrom([\"table_list as tl\", sql<PragmaTableInfo>`pragma_table_info(tl.name)`.as(\"p\")])\n .select([\"tl.name as table\", \"p.cid\", \"p.name\", \"p.type\", \"p.notnull\", \"p.dflt_value\", \"p.pk\"])\n .orderBy(\"tl.name\")\n .orderBy(\"p.cid\"),\n { loggerLevel: \"system\" },\n ).rows;\n\n const columnsByTable: Record<string, typeof tablesMetadata> = {};\n for (const row of tablesMetadata) {\n columnsByTable[row.table] ??= [];\n columnsByTable[row.table].push(row);\n }\n\n return Object.fromEntries(\n tables.map(({ name, sql, type }) => {\n // // Try to find the name of the column that has `autoincrement` 🤦\n let autoIncrementCol = sql\n ?.split(/[(),]/)\n ?.find((it) => it.toLowerCase().includes(\"autoincrement\"))\n ?.trimStart()\n ?.split(/\\s+/)?.[0]\n ?.replace(/[\"`]/g, \"\");\n\n const columns = columnsByTable[name] ?? [];\n\n // Otherwise, check for an INTEGER PRIMARY KEY\n // https://www.sqlite.org/autoinc.html\n if (!autoIncrementCol) {\n const pkCols = columns.filter((r) => r.pk > 0);\n if (pkCols.length === 1 && pkCols[0].type.toLowerCase() === \"integer\") {\n autoIncrementCol = pkCols[0].name;\n }\n }\n\n return [\n name,\n {\n name: name,\n isView: type === \"view\",\n columns: columns.map((col) => ({\n name: col.name,\n dataType: col.type,\n isNullable: !col.notnull,\n isAutoIncrementing: col.name === autoIncrementCol,\n hasDefaultValue: col.dflt_value != null,\n comment: undefined,\n })),\n },\n ];\n }),\n );\n}\n","export type LogLevel = \"info\" | \"warning\" | \"error\" | \"trace\" | \"system\";\n\nexport type Logger = (type: string, message: string, level?: LogLevel) => void;\n\nexport const startPerformanceLogger = (logger: Logger) => {\n let startTime = performance.now();\n\n return {\n restart: () => {\n startTime = performance.now();\n },\n logEnd: (type: string, message: string, level: LogLevel = \"info\") => {\n const elapsed = performance.now() - startTime;\n\n logger(type, `${elapsed.toFixed(2)}ms - ${message}`, level);\n },\n };\n};\n","import type {\n BindableValue,\n FunctionOptions,\n Database as SQLiteDatabase,\n Sqlite3Static,\n SqlValue,\n} from \"@sqlite.org/sqlite-wasm\";\nimport type { Compilable, CompiledQuery, Kysely } from \"kysely\";\nimport { dummyKysely } from \"./dummy-kysely\";\nimport { type DatabaseIntrospection, introspectDb } from \"./introspection\";\nimport { type Logger, startPerformanceLogger } from \"./logger\";\n\nexport type ExecuteParams = {\n sql: string;\n parameters: readonly unknown[];\n};\n\nexport type ExecuteResult<T> = {\n rows: T[];\n};\n\nexport type PreparedStatement<TParams extends SqlValue[], TResult> = {\n execute: (parameters: TParams) => TResult[];\n finalize: () => void;\n isFinalized: boolean;\n};\n\ntype ScalarFunctionOptions<TArgs extends readonly SqlValue[], TResult extends SqlValue | undefined> = {\n name: string;\n callback: (...args: TArgs) => TResult;\n} & Pick<FunctionOptions, \"deterministic\" | \"directOnly\" | \"innocuous\">;\n\ntype SqliteWrapperOptions = {\n logger?: Logger;\n loggerPrefix?: string;\n sqlite3: Sqlite3Static;\n db: () => SQLiteDatabase;\n};\n\nexport type SQLiteTransactionWrapper<TDatabase = unknown> = Pick<\n SQLiteDbWrapper<TDatabase>,\n \"execute\" | \"sql\" | \"executeKysely\" | \"prepare\" | \"executePrepared\" | \"prepareKysely\"\n>;\n\ntype QueryMetaOpts = {\n loggerLevel?: \"info\" | \"system\";\n};\n\nexport class SQLiteDbWrapper<TDatabase = unknown> {\n private db: SQLiteDatabase | null = null;\n private sqlite3: Sqlite3Static;\n private logger?: Logger;\n private loggerPrefix?: string;\n\n private loadedDbSchema: DatabaseIntrospection | null = null;\n\n private readonly dataPointers = [] as number[];\n\n private preparedStatements: PreparedStatement<SqlValue[], unknown>[] = [];\n private preparedStatementsMap = new Map<string, TypedStatement<Record<string, unknown>, unknown>>();\n private preparedRawStatementsMap = new Map<string, PreparedStatement<SqlValue[], unknown>>();\n\n constructor(opts: SqliteWrapperOptions) {\n this.db = opts.db();\n this.sqlite3 = opts.sqlite3;\n this.logger = opts.logger;\n this.loggerPrefix = opts.loggerPrefix;\n }\n\n get ensureDb() {\n if (!this.db) {\n throw new Error(\"Database is already closed\");\n }\n return this.db;\n }\n\n get dbSchema() {\n if (!this.loadedDbSchema) {\n this.loadedDbSchema = introspectDb(this);\n }\n return this.loadedDbSchema;\n }\n\n execute<T = unknown>(opts: ExecuteParams | string | CompiledQuery<T>, meta?: QueryMetaOpts): ExecuteResult<T> {\n const sql = typeof opts === \"string\" ? opts : opts.sql;\n const bind = typeof opts === \"string\" ? undefined : opts.parameters;\n\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const rows = this.ensureDb.exec({\n sql,\n bind: bind as BindableValue[],\n returnValue: \"resultRows\",\n rowMode: \"object\",\n });\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:query`, sql, meta?.loggerLevel);\n\n return { rows: rows as T[] };\n }\n\n executeTransaction<T>(callback: (db: SQLiteTransactionWrapper<TDatabase>) => T): T {\n const transaction = this.beginTransaction();\n try {\n const result = callback(this);\n transaction.commit();\n return result;\n } catch (error) {\n transaction.rollback();\n throw error;\n }\n }\n\n isInTransaction() {\n // TODO: Awaiting upstream fix: https://github.com/sqlite/sqlite-wasm/pull/143\n return (this.sqlite3.capi as any).sqlite3_get_autocommit(this.ensureDb) === 0;\n }\n\n beginTransaction() {\n this.executePreparedRaw({\n key: \"$begin-transaction\",\n sql: \"begin\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n\n return {\n commit: () => {\n this.executePreparedRaw({\n key: \"$commit-transaction\",\n sql: \"commit\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n rollback: () => {\n this.executePreparedRaw({\n key: \"$rollback-transaction\",\n sql: \"rollback\",\n meta: {\n loggerLevel: \"system\",\n },\n });\n },\n };\n }\n\n prepare<TParams extends SqlValue[], TResult>(sql: string, opts?: QueryMetaOpts) {\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const stmt = this.ensureDb.prepare(sql);\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:prepare`, sql, opts?.loggerLevel);\n\n let isFinalized = false;\n\n const execute = (params: TParams) => {\n if (isFinalized) {\n throw new Error(\"Statement is finalized\");\n }\n\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n if (params.length > 0) {\n stmt.bind(params);\n }\n const results = [] as TResult[];\n while (stmt.step()) {\n results.push(stmt.get({}) as TResult);\n }\n stmt.reset(true);\n perf?.logEnd(`${this.loggerPrefix ?? \"\"}:prepare-execute`, sql, opts?.loggerLevel);\n return results;\n };\n\n const finalize = () => {\n isFinalized = true;\n stmt.finalize();\n };\n\n const preparedStatement: PreparedStatement<TParams, TResult> = {\n execute,\n finalize,\n get isFinalized() {\n return isFinalized;\n },\n };\n\n this.preparedStatements.push(preparedStatement as PreparedStatement<SqlValue[], unknown>);\n\n return preparedStatement;\n }\n\n prepareKysely<TParams extends Record<string, unknown>>(opts?: QueryMetaOpts) {\n return <TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n ): TypedStatement<TParams, TResult> => {\n const query = factory(dummyKysely, (key) => key as any).compile();\n const statement = this.prepare<SqlValue[], TResult>(query.sql, opts);\n\n return {\n execute: (parameters) => {\n const params = query.parameters.map((param) => parameters[param as keyof TParams]);\n const result = statement.execute(params as SqlValue[]);\n return result;\n },\n };\n };\n }\n\n executeKysely<TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>>(\n factory: KyselyQueryFactory<TDatabase, TQuery, TResult>,\n meta?: QueryMetaOpts,\n ) {\n const query = factory(dummyKysely).compile();\n return this.execute(query, meta);\n }\n\n executePrepared<\n TParams extends Record<string, unknown>,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n >(\n key: string,\n params: TParams,\n factory: KyselyStatementFactory<TParams, TDatabase, TQuery, TResult>,\n meta?: QueryMetaOpts,\n ) {\n let statement = this.preparedStatementsMap.get(key) as TypedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepareKysely<TParams>(meta)(factory);\n this.preparedStatementsMap.set(key, statement as TypedStatement<Record<string, unknown>, unknown>);\n }\n\n return statement.execute(params);\n }\n\n executePreparedRaw<TParams extends SqlValue[], TResult>({\n key,\n sql,\n params,\n meta,\n }: {\n key: string;\n sql: string;\n params?: TParams;\n meta?: QueryMetaOpts;\n }) {\n let statement = this.preparedRawStatementsMap.get(key) as PreparedStatement<TParams, TResult> | undefined;\n if (!statement) {\n statement = this.prepare(sql, meta);\n this.preparedRawStatementsMap.set(key, statement as PreparedStatement<any[], unknown>);\n }\n\n return statement.execute((params ?? []) as TParams);\n }\n\n sql<T = unknown>(templateOrString: TemplateStringsArray | string, ...parameters: unknown[]) {\n if (typeof templateOrString === \"string\") {\n return this.execute<T>({\n sql: templateOrString,\n parameters,\n });\n }\n return this.execute<T>({\n sql: templateOrString.join(\"?\"),\n parameters,\n });\n }\n\n createScalarFunction<TArgs extends SqlValue[], TResult extends SqlValue | undefined>({\n name,\n callback,\n deterministic,\n directOnly,\n innocuous,\n }: ScalarFunctionOptions<TArgs, TResult>) {\n return this.ensureDb.createFunction({\n name,\n xFunc: (_, ...args) => {\n const result = callback(...(args as TArgs)) as SqlValue;\n return result;\n },\n arity: callback.length,\n deterministic,\n directOnly,\n innocuous,\n });\n }\n\n useSnapshot(snapshot: Uint8Array<ArrayBufferLike>) {\n const perf = this.logger ? startPerformanceLogger(this.logger) : undefined;\n const dataPointer = this.sqlite3.wasm.allocFromTypedArray(snapshot);\n this.dataPointers.push(dataPointer);\n\n const resultCode = this.sqlite3.capi.sqlite3_deserialize(\n this.ensureDb,\n \"main\",\n dataPointer,\n snapshot.byteLength,\n snapshot.byteLength,\n this.sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE | this.sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE,\n );\n\n this.ensureDb.checkRc(resultCode);\n\n this.invalidateDbSchema();\n\n perf?.logEnd(\"useSnapshot\", \"success\", \"system\");\n }\n\n createSnapshot() {\n return this.sqlite3.capi.sqlite3_js_db_export(this.ensureDb);\n }\n\n invalidateDbSchema() {\n this.loadedDbSchema = null;\n }\n\n cleanup() {\n this.preparedStatements.forEach((stmt) => {\n stmt.finalize();\n });\n this.preparedStatements.splice(0);\n this.preparedStatementsMap.clear();\n this.preparedRawStatementsMap.clear();\n }\n\n close() {\n this.cleanup();\n\n this.db?.close();\n this.db = null;\n }\n}\n\nexport type QueryBuilderOutput<QB> = QB extends Compilable<infer O> ? O : never;\ntype ParamsGetter<TParams> = <TKey extends keyof TParams>(key: TKey) => TParams[TKey];\n\ntype TypedStatement<TParams extends Record<string, unknown>, TResult> = {\n execute: (parameters: TParams) => TResult[];\n};\ntype KyselyStatementFactory<\n TParams extends Record<string, unknown>,\n TDatabase,\n TQuery extends Compilable<TResult>,\n TResult = QueryBuilderOutput<TQuery>,\n> = (kysely: Kysely<TDatabase>, params: ParamsGetter<TParams>) => TQuery;\nexport type KyselyQueryFactory<TDatabase, TQuery extends Compilable<TResult>, TResult = QueryBuilderOutput<TQuery>> = (\n kysely: Kysely<TDatabase>,\n) => TQuery;\n","import type {\n ColumnDataType,\n ColumnDefinitionBuilderCallback,\n Compilable,\n CreateIndexBuilder,\n CreateTableBuilder,\n Expression,\n Kysely,\n} from \"kysely\";\nimport { dummyKysely } from \"../dummy-kysely\";\nimport type { CrdtEventType } from \"../sqlite-crdt/crdt-table-schema\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\n\ntype CrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: Record<string, unknown>;\n};\n\nexport type MigratableEvent = {\n schema_version: number;\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: string;\n};\n\ntype CrdtEventTransformer = (event: CrdtEvent) => CrdtEvent | null;\n\ntype MigrationStepSql =\n | {\n sql: string;\n parameters?: readonly unknown[];\n }\n | Compilable\n | ((db: Kysely<unknown>) => Compilable);\n\ntype TableRename = { oldTable: string; newTable: string };\n\ntype MigrationStep = {\n sql: MigrationStepSql | MigrationStepSql[];\n eventTransformer?: MigrationEventTransformers;\n tableRenames?: TableRename[];\n tableDrops?: string[];\n};\n\ntype RawMigrationStep = {\n sql: MigrationSql[];\n eventTransformer?: CompiledMigrationEventTransformer;\n tableRenames?: TableRename[];\n tableDrops?: string[];\n};\n\ntype MigrationSql = { sql: string; parameters: readonly unknown[] };\n\ntype DataTypeExpression = ColumnDataType | Expression<any>;\n\nconst protectedColumns = [\"id\", \"tombstone\"];\n\nfunction assertColumnNotProtected(column: string, operation: string) {\n if (protectedColumns.includes(column)) {\n throw new Error(`Cannot ${operation} protected column \"${column}\"`);\n }\n}\n\nconst migrationSteps = {\n createTable: (table: string, build: (table: CreateTableBuilder<string, never>) => Compilable): MigrationStep => ({\n sql: (db) => build(db.schema.createTable(table)),\n }),\n\n dropTable: (table: string): MigrationStep => ({\n sql: (db) => db.schema.dropTable(table),\n eventTransformer: {\n [table]: () => null,\n },\n tableDrops: [table],\n }),\n\n createIndex: (indexName: string, build: (index: CreateIndexBuilder) => Compilable): MigrationStep => ({\n sql: (db) => build(db.schema.createIndex(indexName)),\n }),\n\n dropIndex: (indexName: string): MigrationStep => ({\n sql: (db) => db.schema.dropIndex(indexName),\n }),\n\n renameTable: ({ oldTable, newTable }: { oldTable: string; newTable: string }): MigrationStep => ({\n sql: (db) => db.schema.alterTable(oldTable).renameTo(newTable),\n eventTransformer: {\n [oldTable]: (event) => {\n event.dataset = newTable;\n return event;\n },\n },\n tableRenames: [{ oldTable, newTable }],\n }),\n\n renameColumn: ({\n table,\n oldColumn,\n newColumn,\n }: {\n table: string;\n oldColumn: string;\n newColumn: string;\n }): MigrationStep => {\n assertColumnNotProtected(oldColumn, \"rename\");\n assertColumnNotProtected(newColumn, \"rename to\");\n return {\n sql: (db) => db.schema.alterTable(table).renameColumn(oldColumn, newColumn),\n eventTransformer: {\n [table]: (event) => {\n if ((event.type !== \"item-updated\" && event.type !== \"item-created\") || !(oldColumn in event.payload)) {\n return event;\n }\n\n const oldVal = event.payload[oldColumn];\n delete event.payload[oldColumn];\n event.payload[newColumn] = oldVal;\n\n return event;\n },\n },\n };\n },\n\n addColumn: ({\n table,\n column,\n type,\n defaultValue,\n build = (e) => e,\n }: {\n table: string;\n column: string;\n type: DataTypeExpression;\n defaultValue: number | boolean | string | null;\n build?: ColumnDefinitionBuilderCallback;\n }): MigrationStep => ({\n sql: (db) => db.schema.alterTable(table).addColumn(column, type, (x) => build(x).defaultTo(defaultValue)),\n eventTransformer: {\n [table]: (event) => {\n if (event.type !== \"item-created\") {\n return event;\n }\n\n event.payload[column] = defaultValue;\n\n return event;\n },\n },\n }),\n\n dropColumn: ({ table, column }: { table: string; column: string }): MigrationStep => {\n assertColumnNotProtected(column, \"drop\");\n return {\n sql: (db) => db.schema.alterTable(table).dropColumn(column),\n eventTransformer: {\n [table]: (event) => {\n if (!(column in event.payload)) {\n return event;\n }\n\n delete event.payload[column];\n\n if (event.type === \"item-updated\" && Object.keys(event.payload).length === 0) {\n return null;\n }\n\n return event;\n },\n },\n };\n },\n};\n\ntype MigrationEventTransformers = Record<string, CrdtEventTransformer>;\ntype CompiledMigrationEventTransformer = (event: CrdtEvent) => CrdtEvent | null;\n\nfunction buildMigrationSql(steps: MigrationStep[]): MigrationSql[] {\n return steps\n .flatMap((step) => (Array.isArray(step.sql) ? step.sql : [step.sql]))\n .map((sql): MigrationSql => {\n if (typeof sql === \"string\") {\n return { sql, parameters: [] };\n }\n\n if (typeof sql === \"function\") {\n const query = sql(dummyKysely).compile();\n return { sql: query.sql, parameters: query.parameters };\n }\n\n if (\"compile\" in sql) {\n const query = sql.compile();\n return { sql: query.sql, parameters: query.parameters };\n }\n\n return {\n sql: sql.sql,\n parameters: sql.parameters ?? [],\n };\n });\n}\n\nfunction buildMigrationEventTransformer(steps: MigrationStep[]): CompiledMigrationEventTransformer | undefined {\n const transformers: Array<[string, CrdtEventTransformer]> = [];\n\n for (const step of steps) {\n if (step.eventTransformer) {\n transformers.push(...Object.entries(step.eventTransformer));\n }\n }\n\n if (transformers.length === 0) {\n return undefined;\n }\n\n return (event: CrdtEvent) => {\n let transformedEvent: CrdtEvent | null = event;\n\n for (const [table, transformer] of transformers) {\n if (transformedEvent === null) {\n return null;\n }\n if (transformedEvent.dataset !== table) {\n continue;\n }\n transformedEvent = transformer(transformedEvent);\n if (transformedEvent === null) {\n return null;\n }\n }\n\n return transformedEvent;\n };\n}\n\nexport function createMigrations(buildMigrations: (builder: typeof migrationSteps) => Record<number, MigrationStep[]>) {\n const migrations: Record<number, RawMigrationStep> = Object.fromEntries(\n Object.entries(buildMigrations(migrationSteps)).map(([version, steps]) => {\n const versionNumber = Number(version);\n\n if (Number.isNaN(versionNumber)) {\n throw new Error(`Invalid migration version: ${version}`);\n }\n\n if (versionNumber < 0) {\n throw new Error(`Migration version cannot be negative: ${version}`);\n }\n\n const tableRenames = steps.flatMap((s) => s.tableRenames ?? []);\n const tableDrops = steps.flatMap((s) => s.tableDrops ?? []);\n\n return [\n version,\n {\n sql: buildMigrationSql(steps),\n eventTransformer: buildMigrationEventTransformer(steps),\n ...(tableRenames.length > 0 && { tableRenames }),\n ...(tableDrops.length > 0 && { tableDrops }),\n },\n ];\n }),\n );\n\n return migrations;\n}\n\nexport type Migrations = ReturnType<typeof createMigrations>;\n\nexport type MigrationsDb = {\n startTransaction: (callback: (tx: MigrationsTransaction) => void) => void;\n};\n\ntype MigrationsTransaction = {\n execute: (sql: string, parameters: readonly unknown[]) => void;\n};\n\nexport function createMigrator({\n migrations,\n schemaVersion,\n updateLogTableName,\n}: {\n migrations: Migrations;\n schemaVersion: StoredValue<number>;\n updateLogTableName?: string;\n}) {\n const latestSchemaVersion = Math.max(...Object.keys(migrations).map(Number));\n\n // Pre-sort migrations once for efficient range lookups\n const sortedMigrations = Object.entries(migrations)\n .map(([v, m]) => [Number(v), m] as const)\n .sort((a, b) => a[0] - b[0]);\n\n const applyMigration = (db: MigrationsDb, version: number, migration: RawMigrationStep) => {\n if (version <= schemaVersion.current) {\n throw new Error(`Cannot apply migration ${version} to schema version ${schemaVersion.current}`);\n }\n\n db.startTransaction((tx) => {\n for (const statement of migration.sql) {\n tx.execute(statement.sql, statement.parameters);\n }\n if (updateLogTableName) {\n if (migration.tableRenames) {\n for (const { oldTable, newTable } of migration.tableRenames) {\n tx.execute(`UPDATE ${updateLogTableName} SET \"dataset\" = ? WHERE \"dataset\" = ?`, [newTable, oldTable]);\n }\n }\n if (migration.tableDrops) {\n for (const table of migration.tableDrops) {\n tx.execute(`DELETE FROM ${updateLogTableName} WHERE \"dataset\" = ?`, [table]);\n }\n }\n }\n schemaVersion.current = version;\n });\n };\n\n const migrateEvent = <Event extends MigratableEvent>(event: Event, targetVersion?: number): Event | null => {\n targetVersion ??= latestSchemaVersion;\n if (targetVersion > schemaVersion.current) {\n throw new Error(\n `Target schema version ${targetVersion} is greater than current schema version ${schemaVersion.current}`,\n );\n }\n\n if (event.schema_version >= targetVersion) {\n return event;\n }\n\n const fromVersion = event.schema_version;\n\n let crdtEvent: CrdtEvent | null = {\n dataset: event.dataset,\n item_id: event.item_id,\n type: event.type,\n payload: JSON.parse(event.payload),\n };\n\n for (let i = 0; i < sortedMigrations.length; i++) {\n const [version, migration] = sortedMigrations[i];\n if (version <= fromVersion) continue;\n if (version > targetVersion) break;\n\n const transformer = migration.eventTransformer;\n if (transformer) {\n crdtEvent = transformer(crdtEvent);\n if (crdtEvent === null) return null;\n }\n }\n\n if (crdtEvent === null) {\n return null;\n }\n\n event.schema_version = targetVersion;\n event.dataset = crdtEvent.dataset;\n event.item_id = crdtEvent.item_id;\n event.type = crdtEvent.type;\n event.payload = JSON.stringify(crdtEvent.payload);\n\n return event;\n };\n\n const migrateEvents = <Event extends MigratableEvent>(events: Event[], targetVersion?: number): Event[] => {\n return events\n .map((event) => migrateEvent(event, targetVersion ?? latestSchemaVersion))\n .filter((event): event is NonNullable<typeof event> => event !== null);\n };\n\n return {\n latestSchemaVersion,\n get currentSchemaVersion() {\n return schemaVersion.current;\n },\n migrateDbToLatest: (db: MigrationsDb) => {\n const currentSchemaVersion = schemaVersion.current;\n\n if (currentSchemaVersion >= latestSchemaVersion) {\n return;\n }\n\n for (let i = 0; i < sortedMigrations.length; i++) {\n const [version, migration] = sortedMigrations[i];\n if (version <= currentSchemaVersion) continue;\n applyMigration(db, version, migration);\n }\n },\n migrateEvent,\n migrateEvents,\n };\n}\n\nexport type SyncDbMigrator = ReturnType<typeof createMigrator>;\n","export type StoredValue<T> = {\n get current(): T;\n set current(newValue: T);\n};\n\nexport function createStoredValue<T>({\n initialValue,\n saveToStorage,\n}: {\n initialValue: T;\n saveToStorage?: (value: T) => void;\n}): StoredValue<T> {\n let currentValue = initialValue;\n\n return {\n get current() {\n return currentValue;\n },\n set current(newValue: T) {\n saveToStorage?.(newValue);\n currentValue = newValue;\n },\n };\n}\n","import type { SchemaModule } from \"kysely\";\nimport { createStoredValue } from \"./sqlite-crdt/stored-value\";\nimport type { SQLiteTransactionWrapper } from \"./sqlite-db-wrapper\";\n\nexport type KvStoreItem = {\n key: string;\n value: string;\n};\n\nexport function createKvStoreTableQuery(schema: SchemaModule, tableName: string) {\n return schema\n .createTable(tableName)\n .ifNotExists()\n .addColumn(\"key\", \"text\", (col) => col.notNull().primaryKey())\n .addColumn(\"value\", \"text\", (col) => col.notNull());\n}\n\nexport function createSQLiteKvStore({\n db,\n metaTableName,\n}: {\n db: SQLiteTransactionWrapper<any>;\n metaTableName: string;\n}) {\n const metaDb = db as SQLiteTransactionWrapper<{\n meta: KvStoreItem;\n }>;\n\n const get = (key: string): string | null => {\n const [result] = metaDb.executePrepared(\n \"get-meta-value\",\n { key },\n (db, params) =>\n db\n .selectFrom(metaTableName as \"meta\")\n .where(\"key\", \"=\", params(\"key\"))\n .select(\"value\")\n .limit((eb) => eb.lit(1)),\n { loggerLevel: \"system\" },\n );\n\n return result?.value ?? null;\n };\n\n const set = (key: string, value: string) => {\n metaDb.executePrepared(\n \"set-meta-value\",\n { key, value },\n (db, params) =>\n db\n .insertInto(metaTableName as \"meta\")\n .values({ key: params(\"key\"), value: params(\"value\") })\n .onConflict((oc) => oc.doUpdateSet({ value: params(\"value\") })),\n { loggerLevel: \"system\" },\n );\n };\n\n const remove = (key: string) => {\n metaDb.executePrepared(\n \"remove-meta-value\",\n { key },\n (db, params) => db.deleteFrom(metaTableName as \"meta\").where(\"key\", \"=\", params(\"key\")),\n { loggerLevel: \"system\" },\n );\n };\n\n const getNumberOrDefault = <T>(key: string, defaultValue: T): T | number => {\n const value = get(key);\n if (!value) return defaultValue;\n const parsedValue = Number.parseInt(value, 10);\n return Number.isNaN(parsedValue) ? defaultValue : parsedValue;\n };\n\n return {\n get,\n set,\n remove,\n createStringStoredValue: (key: string, defaultValue: string) =>\n createStoredValue<string>({\n initialValue: get(key) ?? defaultValue,\n saveToStorage: (val) => set(key, val),\n }),\n createNumberStoredValue: (key: string, defaultValue: number) =>\n createStoredValue<number>({\n initialValue: getNumberOrDefault(key, defaultValue),\n saveToStorage: (val) => set(key, val.toString()),\n }),\n };\n}\n\nexport type KvStore = ReturnType<typeof createSQLiteKvStore>;\n","import type { CrdtUpdateLogItem, PersistedCrdtEvent } from \"../sqlite-crdt/crdt-table-schema\";\nimport type { StoredValue } from \"../sqlite-crdt/stored-value\";\nimport type { SQLiteDbWrapper } from \"../sqlite-db-wrapper\";\nimport { createKvStoreTableQuery, createSQLiteKvStore, type KvStoreItem } from \"../sqlite-kv-store\";\n\nexport type WorkerDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n \"worker.kv\": KvStoreItem;\n \"worker.crdt_events\": PersistedCrdtEvent;\n};\n\nexport type MemoryDbSchema = {\n crdt_update_log: CrdtUpdateLogItem;\n persisted_crdt_events: PersistedCrdtEvent;\n};\n\nexport type SystemMigrationContext = {\n eventsTableName: string;\n updateLogTableName: string;\n execute: (sql: string) => void;\n};\n\nexport type SystemMigration = {\n version: number;\n up: (ctx: SystemMigrationContext) => void;\n};\n\nexport const baseSystemMigrations: SystemMigration[] = [\n {\n version: 0,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.eventsTableName} (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n )`);\n ctx.execute(`CREATE TABLE IF NOT EXISTS ${ctx.updateLogTableName} (\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL,\n PRIMARY KEY (\"item_id\", \"dataset\")\n )`);\n },\n },\n {\n version: 1,\n up: (ctx: SystemMigrationContext) => {\n ctx.execute(`ALTER TABLE ${ctx.eventsTableName} ADD COLUMN \"source_node_id\" TEXT NOT NULL DEFAULT ''`);\n },\n },\n];\n\nexport function runSystemMigrations(opts: {\n version: StoredValue<number>;\n migrations: SystemMigration[];\n eventsTableName: string;\n updateLogTableName: string;\n execute: (sql: string) => void;\n transaction: (callback: () => void) => void;\n}): void {\n const ctx: SystemMigrationContext = {\n eventsTableName: opts.eventsTableName,\n updateLogTableName: opts.updateLogTableName,\n execute: opts.execute,\n };\n for (const migration of opts.migrations) {\n if (migration.version > opts.version.current) {\n opts.transaction(() => {\n migration.up(ctx);\n opts.version.current = migration.version;\n });\n }\n }\n}\n\nexport function applyWorkerDbSchema(db: SQLiteDbWrapper<any>) {\n // KV table stays separate — needed before system migrations for version tracking\n db.executeKysely((kysely) => createKvStoreTableQuery(kysely.schema, \"worker.kv\"), { loggerLevel: \"system\" });\n\n // System schema migrations (each in its own transaction)\n const kvStore = createSQLiteKvStore({ db, metaTableName: \"worker.kv\" });\n runSystemMigrations({\n migrations: baseSystemMigrations,\n version: kvStore.createNumberStoredValue(\"internal-schema-version\", -1),\n eventsTableName: '\"worker\".\"crdt_events\"',\n updateLogTableName: '\"crdt_update_log\"',\n execute: (sql) => db.execute(sql, { loggerLevel: \"system\" }),\n transaction: (callback) => db.executeTransaction(callback),\n });\n}\n\nexport function applyMemoryDbSchema(db: SQLiteDbWrapper<any>) {\n db.execute(\n `CREATE TABLE \"persisted_crdt_events\" (\n \"sync_id\" integer NOT NULL PRIMARY KEY,\n \"schema_version\" integer NOT NULL,\n \"status\" text NOT NULL,\n \"type\" text NOT NULL,\n \"timestamp\" text NOT NULL,\n \"origin\" text NOT NULL,\n \"source_node_id\" text NOT NULL DEFAULT '',\n \"dataset\" text NOT NULL,\n \"item_id\" text NOT NULL,\n \"payload\" text NOT NULL\n)`,\n { loggerLevel: \"system\" },\n );\n}\n","import type { Kysely } from \"kysely\";\nimport type { SQLiteTransactionWrapper } from \"../sqlite-db-wrapper\";\nimport { quoteId } from \"../utils\";\nimport type { CrdtEventType, CrdtUpdateLogItem, CrdtUpdateLogPayload } from \"./crdt-table-schema\";\n\nexport type PendingCrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n timestamp: string;\n payload: string;\n};\n\nexport const createSQLiteCrdtApplyFunction = ({\n db,\n updateLogTableName,\n}: {\n db: SQLiteTransactionWrapper<any>;\n updateLogTableName: string;\n}) => {\n const applyCrdtEvent = createCrdtApplyFunction({\n getCrdtUpdateLog(opts) {\n const [metaRow] = db.executePrepared(\n \"get-item-crdt-meta\",\n {\n item_id: opts.itemId,\n dataset: opts.dataset,\n },\n (db, params) => {\n return (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>)\n .selectFrom(updateLogTableName as \"table\")\n .select(\"payload\")\n .where(\"item_id\", \"=\", params(\"item_id\"))\n .where(\"dataset\", \"=\", params(\"dataset\"));\n },\n { loggerLevel: \"system\" },\n );\n const meta = metaRow ? (JSON.parse(metaRow.payload) as CrdtUpdateLogPayload) : null;\n return meta;\n },\n insertCrdtUpdateLog(opts) {\n db.executePrepared(\n \"insert-crdt-update-log\",\n {\n item_id: opts.itemId,\n dataset: opts.dataset,\n payload: opts.payload,\n },\n (db, params) =>\n (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>).insertInto(updateLogTableName as \"table\").values({\n item_id: params(\"item_id\"),\n dataset: params(\"dataset\"),\n payload: params(\"payload\"),\n }),\n { loggerLevel: \"system\" },\n );\n },\n updateCrdtUpdateLog(opts) {\n db.executePrepared(\n \"update-crdt-update-log\",\n {\n item_id: opts.itemId,\n dataset: opts.dataset,\n payload: opts.payload,\n },\n (db, params) =>\n (db as unknown as Kysely<{ table: CrdtUpdateLogItem }>)\n .updateTable(updateLogTableName as \"table\")\n .set({\n payload: params(\"payload\"),\n })\n .where(\"item_id\", \"=\", params(\"item_id\"))\n .where(\"dataset\", \"=\", params(\"dataset\")),\n { loggerLevel: \"system\" },\n );\n },\n insertItem(opts) {\n const insertPayload = {} as Record<string, unknown>;\n for (const key of Object.keys(opts.payload)) {\n insertPayload[key] = key;\n }\n db.executePrepared(\n `crdt-insert-item-${opts.dataset}`,\n opts.payload,\n (db) => db.insertInto(opts.dataset).values(insertPayload),\n { loggerLevel: \"system\" },\n );\n },\n updateItem(opts) {\n const keys = Array.from(Object.keys(opts.payload));\n db.execute(\n {\n sql: `update ${quoteId(opts.dataset)} set ${keys.map((key) => `${quoteId(key)} = ?`).join(\",\")} where id = ?`,\n parameters: [...keys.map((key) => opts.payload[key]), opts.itemId],\n },\n { loggerLevel: \"system\" },\n );\n },\n });\n\n return applyCrdtEvent;\n};\n\ntype CreateCrdtApplyOpts = {\n getCrdtUpdateLog: (opts: { itemId: string; dataset: string }) => CrdtUpdateLogPayload | null;\n insertItem: (opts: { dataset: string; payload: Record<string, unknown> }) => void;\n insertCrdtUpdateLog: (opts: { dataset: string; itemId: string; payload: string }) => void;\n updateItem: (opts: { dataset: string; itemId: string; payload: Record<string, unknown> }) => void;\n updateCrdtUpdateLog: (opts: { dataset: string; itemId: string; payload: string }) => void;\n};\n\nexport function createCrdtApplyFunction({\n getCrdtUpdateLog,\n insertItem,\n insertCrdtUpdateLog,\n updateItem,\n updateCrdtUpdateLog,\n}: CreateCrdtApplyOpts) {\n type ItemCreatedOpts = {\n event: PendingCrdtEvent;\n meta: CrdtUpdateLogPayload | null;\n };\n const applyItemCreated = ({ event, meta }: ItemCreatedOpts) => {\n if (meta) {\n // Item already exists\n applyItemUpdated({ event, meta });\n return;\n }\n\n const eventPayload = JSON.parse(event.payload);\n\n eventPayload.tombstone = false;\n insertItem({ dataset: event.dataset, payload: eventPayload });\n\n const newUpdateLog = {} as Record<string, string>;\n for (const key of Object.keys(eventPayload)) {\n newUpdateLog[key] = event.timestamp;\n }\n\n insertCrdtUpdateLog({\n dataset: event.dataset,\n itemId: event.item_id,\n payload: JSON.stringify(newUpdateLog),\n });\n };\n\n type ItemUpdatedOpts = {\n event: PendingCrdtEvent;\n meta: CrdtUpdateLogPayload;\n };\n const applyItemUpdated = ({ event, meta }: ItemUpdatedOpts) => {\n if (!meta) {\n throw new Error(`Item ${event.item_id} in dataset ${event.dataset} not found`);\n }\n const eventPayload = JSON.parse(event.payload);\n\n const updatePayload = {} as Record<string, unknown>;\n let hasUpdates = false;\n\n for (const [key, value] of Object.entries(eventPayload)) {\n const lastUpdateTimestamp = meta[key];\n const currentUpdateTimestamp = event.timestamp;\n\n if (!lastUpdateTimestamp || !currentUpdateTimestamp || currentUpdateTimestamp > lastUpdateTimestamp) {\n updatePayload[key] = value;\n meta[key] = currentUpdateTimestamp;\n hasUpdates = true;\n }\n }\n\n if (!hasUpdates) {\n return;\n }\n\n updateItem({\n dataset: event.dataset,\n itemId: event.item_id,\n payload: updatePayload,\n });\n updateCrdtUpdateLog({\n dataset: event.dataset,\n itemId: event.item_id,\n payload: JSON.stringify(meta),\n });\n };\n\n return (event: PendingCrdtEvent) => {\n const meta = getCrdtUpdateLog({\n itemId: event.item_id,\n dataset: event.dataset,\n });\n\n // TODO Check primary key / unique constraints\n\n switch (event.type) {\n case \"item-created\": {\n applyItemCreated({\n event,\n meta,\n });\n break;\n }\n case \"item-updated\": {\n if (!meta) {\n throw new Error(`Item ${event.item_id} in dataset ${event.dataset} not found`);\n }\n\n applyItemUpdated({\n event,\n meta,\n });\n break;\n }\n default:\n event.type satisfies never;\n }\n };\n}\n","import { deserializeHLC, type HLCCounter, serializeHLC } from \"../hlc\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { createTypedEventTarget, ensureSingletonExecution } from \"../utils\";\nimport type { CrdtEventOrigin, CrdtEventStatus, CrdtEventType, PersistedCrdtEvent } from \"./crdt-table-schema\";\nimport type { StoredValue } from \"./stored-value\";\n\ntype LocalCrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: string;\n timestamp: string;\n schema_version: number;\n};\n\nexport type OwnCrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: string;\n timestamp?: undefined;\n schema_version?: undefined;\n};\n\ntype RemoteCrdtEvent = {\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: string;\n timestamp: string;\n schema_version: number;\n};\n\ntype EnqueuedCrdtEvent = LocalCrdtEvent | OwnCrdtEvent | RemoteCrdtEvent;\n\nexport type GetEventsOptions = {\n afterSyncId?: number;\n status?: CrdtEventStatus;\n excludeOrigin?: string;\n excludeNodeId?: string;\n limit?: number;\n};\n\nexport type GetEventsBatch = {\n events: PersistedCrdtEvent[];\n hasMore: boolean;\n nextSyncId: number;\n};\n\nexport type EventUpdate = {\n status: CrdtEventStatus;\n schema_version: number;\n type: CrdtEventType;\n dataset: string;\n item_id: string;\n payload: string;\n};\n\ntype StorageHLC = Pick<HLCCounter, \"getNextHLC\" | \"mergeHLC\">;\n\ntype DbSyncerStorage = {\n nodeId: string;\n syncId: StoredValue<number>;\n migrator: SyncDbMigrator;\n persistEvent: (events: PersistedCrdtEvent) => void;\n getEventsBatch: (options: GetEventsOptions) => PersistedCrdtEvent[];\n updateEvent: (syncId: number, update: EventUpdate) => void;\n handleCrdtEventApply: (event: PersistedCrdtEvent) => void;\n hlc: StorageHLC;\n transaction?: (callback: () => void) => void;\n};\n\nexport type CrdtStorage = ReturnType<typeof createCrdtStorage>;\n\nexport const crdtEventOrigin = {\n local: \"local\",\n own: \"own\",\n remote: \"remote\",\n};\n\ntype EventsAppliedPayload = {\n syncId: number;\n};\n\nexport function createCrdtStorage(storage: DbSyncerStorage) {\n const transaction = storage.transaction ?? ((callback) => callback());\n const eventTarget = createTypedEventTarget<{\n \"events-applied\": EventsAppliedPayload;\n }>();\n\n const enqueueEvents = (origin: CrdtEventOrigin, sourceNodeId: string, events: EnqueuedCrdtEvent[]) => {\n if (events.length === 0) {\n return;\n }\n\n transaction(() => {\n for (const event of events) {\n storage.persistEvent({\n schema_version: event.schema_version ?? storage.migrator.currentSchemaVersion,\n timestamp: event.timestamp ?? serializeHLC(storage.hlc.getNextHLC()),\n type: event.type,\n dataset: event.dataset,\n item_id: event.item_id,\n origin: origin,\n source_node_id: sourceNodeId,\n payload: event.payload,\n sync_id: ++storage.syncId.current,\n status: \"pending\",\n });\n }\n });\n\n processEnqueuedEvents();\n };\n\n const enqueueLocalEvents = (events: LocalCrdtEvent[], sourceNodeId: string) => {\n enqueueEvents(\"local\", sourceNodeId, events);\n };\n\n const enqueueOwnEvents = (events: OwnCrdtEvent[]) => {\n enqueueEvents(\"own\", storage.nodeId, events);\n };\n\n const enqueueRemoteEvents = (events: RemoteCrdtEvent[]) => {\n enqueueEvents(\"remote\", \"\", events);\n };\n\n const applyOwnEvent = (event: OwnCrdtEvent, { wrapInTransaction }: { wrapInTransaction?: boolean } = {}) => {\n const persistedEvent: PersistedCrdtEvent = {\n schema_version: storage.migrator.currentSchemaVersion,\n timestamp: serializeHLC(storage.hlc.getNextHLC()),\n type: event.type,\n dataset: event.dataset,\n item_id: event.item_id,\n origin: \"own\",\n source_node_id: storage.nodeId,\n payload: event.payload,\n sync_id: ++storage.syncId.current,\n status: \"pending\",\n };\n\n if (wrapInTransaction) {\n transaction(() => {\n storage.persistEvent(persistedEvent);\n processPersistedEvent(persistedEvent);\n });\n } else {\n storage.persistEvent(persistedEvent);\n processPersistedEvent(persistedEvent);\n }\n };\n\n const dispatchEventsApplied = () => {\n eventTarget.dispatchEvent(\"events-applied\", {\n syncId: storage.syncId.current,\n });\n };\n\n const getEventsBatch = (options: GetEventsOptions): GetEventsBatch => {\n const limit = options.limit ?? 50;\n const events = storage.getEventsBatch({\n ...options,\n limit: limit + 1,\n });\n const hasMore = events.length > limit;\n if (hasMore) {\n events.pop();\n }\n return {\n events,\n hasMore,\n nextSyncId: events[events.length - 1]?.sync_id ?? options.afterSyncId ?? 0,\n };\n };\n\n const processPersistedEvent = (event: PersistedCrdtEvent) => {\n if (event.status !== \"pending\") {\n throw new Error(`Event ${event.sync_id} is not pending`);\n }\n\n try {\n // Always advance HLC, even for skipped events, to maintain monotonic ordering\n if (event.origin === \"local\" || event.origin === \"remote\") {\n storage.hlc.mergeHLC(deserializeHLC(event.timestamp));\n }\n\n // Migrate event to latest schema version\n const migratedEvent = storage.migrator.migrateEvent(event, storage.migrator.latestSchemaVersion);\n\n if (migratedEvent === null) {\n // Event was dropped during migration (e.g., table was deleted)\n event.status = \"skipped\";\n event.schema_version = storage.migrator.latestSchemaVersion;\n return event;\n }\n\n // Update event with migrated values\n event.schema_version = migratedEvent.schema_version;\n event.type = migratedEvent.type;\n event.dataset = migratedEvent.dataset;\n event.item_id = migratedEvent.item_id;\n event.payload = migratedEvent.payload;\n\n storage.handleCrdtEventApply(event);\n event.status = \"applied\";\n } catch (error) {\n console.error(\"Error applying enqueued CRDT event\", error);\n event.status = \"failed\";\n } finally {\n storage.updateEvent(event.sync_id, {\n status: event.status,\n schema_version: event.schema_version,\n type: event.type,\n dataset: event.dataset,\n item_id: event.item_id,\n payload: event.payload,\n });\n }\n };\n\n const processEnqueuedEvents = ensureSingletonExecution(async () => {\n let hasMore = true;\n while (hasMore) {\n await Promise.resolve();\n\n const batch = getEventsBatch({ status: \"pending\", limit: 100 });\n const events = batch.events;\n hasMore = batch.hasMore;\n\n if (events.length === 0) {\n break;\n }\n\n for (const event of events) {\n transaction(() => {\n processPersistedEvent(event);\n });\n }\n\n dispatchEventsApplied();\n }\n });\n\n return {\n getEventsBatch,\n enqueueLocalEvents,\n enqueueOwnEvents,\n enqueueRemoteEvents,\n applyOwnEvent,\n dispatchEventsApplied,\n\n addEventListener: eventTarget.addEventListener,\n removeEventListener: eventTarget.removeEventListener,\n };\n}\n","import type { CrdtStorage } from \"./crdt-storage\";\n\ntype CrdtSyncProducer = {\n storage: CrdtStorage;\n broadcastEvents: (request: { newSyncId: number }) => void;\n};\n\nexport const createCrdtSyncProducer = ({ storage, broadcastEvents }: CrdtSyncProducer) => {\n storage.addEventListener(\"events-applied\", (event) => {\n broadcastEvents({ newSyncId: event.payload.syncId });\n });\n};\n","import retryAsPromised from \"retry-as-promised\";\nimport type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { createTypedEventTarget, ensureSingletonExecution, tryCatchAsync } from \"../utils\";\nimport type { EventsPullResponse } from \"../worker-db/worker-common\";\nimport type { PendingCrdtEvent } from \"./apply-crdt-event\";\nimport type { CrdtStorage } from \"./crdt-storage\";\nimport type { StoredValue } from \"./stored-value\";\n\ntype CrdtSyncRemoteSourceConfig = {\n bufferSize: number;\n storage: CrdtStorage;\n migrator: SyncDbMigrator;\n pullSyncId: StoredValue<number>;\n pushSyncId: StoredValue<number>;\n nodeId: string;\n remoteFactory?: CreateRemoteSourceFactory;\n};\n\nexport type EventsPullRequest = {\n afterSyncId: number;\n excludeNodeId?: string;\n};\n\nexport type EventsPushRequest = {\n nodeId: string;\n events: (PendingCrdtEvent & { schema_version: number })[];\n};\nexport type EventsPushResponse = {\n ok: boolean;\n};\n\nexport type CrdtSyncRemoteSource = ReturnType<typeof createCrdtSyncRemoteSource>;\n\nexport type CreateRemoteSourceFactory = (opts: {\n onEventsAvailable: (newSyncId: number) => void;\n}) => RemoteSource | Promise<RemoteSource>;\n\ntype RemoteSource = {\n pullEvents: (request: EventsPullRequest) => Promise<EventsPullResponse>;\n pushEvents: (request: EventsPushRequest) => Promise<EventsPushResponse>;\n disconnect?: () => void | Promise<void>;\n};\n\ntype RemoteSourceState =\n | {\n type: \"pending\";\n }\n | {\n type: \"offline\";\n reason: OfflineReason;\n }\n | {\n type: \"online\";\n source: RemoteSource;\n };\n\nexport type OfflineReason =\n | \"NOT_INITIALIZED\"\n | \"INITIALIZATION_FAILED\"\n | \"REMOTE_PUSH_ERROR\"\n | \"REMOTE_PULL_ERROR\"\n | \"DISCONNECTED\";\n\nexport const createCrdtSyncRemoteSource = ({\n bufferSize,\n storage,\n migrator,\n pullSyncId,\n pushSyncId,\n nodeId,\n remoteFactory,\n}: CrdtSyncRemoteSourceConfig) => {\n const eventTarget = createTypedEventTarget<{\n \"state-changed\": RemoteSourceState[\"type\"];\n }>();\n\n let remoteState: RemoteSourceState = { type: \"offline\", reason: \"NOT_INITIALIZED\" };\n\n const setRemoteState = (state: RemoteSourceState) => {\n remoteState = state;\n eventTarget.dispatchEvent(\"state-changed\", state.type);\n };\n\n const initRemote = ensureSingletonExecution(\n async () => {\n if (remoteState.type !== \"offline\") {\n throw new Error(\"Remote source is not offline\");\n }\n\n if (!remoteFactory) {\n console.warn(\"Remote source factory not provided. Going offline.\");\n setRemoteState({ type: \"offline\", reason: \"NOT_INITIALIZED\" });\n return;\n }\n\n setRemoteState({ type: \"pending\" });\n\n const factoryResult = await tryCatchAsync(async () => {\n return await remoteFactory?.({\n onEventsAvailable: (newSyncId) => {\n pullEvents({ remoteSyncId: newSyncId, includeSelf: false });\n },\n });\n });\n\n if (!factoryResult.success) {\n setRemoteState({ type: \"offline\", reason: \"INITIALIZATION_FAILED\" });\n console.warn(\"Failed to create remote source\", factoryResult.error);\n return;\n }\n\n setRemoteState({\n type: \"online\",\n source: factoryResult.data,\n });\n },\n { queueReExecution: false },\n );\n\n const syncWithRemote = ensureSingletonExecution(\n async () => {\n if (remoteState.type !== \"online\") {\n return;\n }\n\n await pullEvents();\n await startPushingEvents();\n },\n { queueReExecution: false },\n );\n\n const goOffline = ensureSingletonExecution(\n async (reason: OfflineReason) => {\n if (remoteState.type !== \"online\") {\n return;\n }\n const source = remoteState.source;\n\n setRemoteState({ type: \"pending\" });\n\n const disconnectResult = await tryCatchAsync(async () => {\n return await source.disconnect?.();\n });\n\n if (!disconnectResult.success) {\n console.warn(\"Error while disconnecting from remote source\", disconnectResult.error);\n }\n\n setRemoteState({ type: \"offline\", reason });\n },\n { queueReExecution: false },\n );\n\n const goOnline = async () => {\n if (remoteState.type !== \"online\") {\n await initRemote();\n }\n\n if (remoteState.type === \"online\") {\n await syncWithRemote();\n }\n };\n\n let requestedPullSyncId: number | null = null;\n let pullPromise: Promise<void> | null = null;\n const pullEvents = (request?: { remoteSyncId?: number; includeSelf?: boolean }) => {\n if (remoteState.type !== \"online\") {\n return Promise.resolve();\n }\n\n const remoteSyncId = request?.remoteSyncId;\n\n if (remoteSyncId !== undefined && remoteSyncId <= pullSyncId.current) {\n return Promise.resolve();\n }\n\n if (pullPromise) {\n if (remoteSyncId !== undefined && (!requestedPullSyncId || requestedPullSyncId < remoteSyncId)) {\n requestedPullSyncId = remoteSyncId;\n }\n return pullPromise;\n }\n\n pullPromise = pullAllEvents({\n afterSyncId: pullSyncId.current,\n excludeNodeId: request?.includeSelf ? undefined : nodeId,\n })\n .catch((error) => {\n console.error(\"Error pulling events. Going offline.\", error);\n goOffline(\"REMOTE_PULL_ERROR\");\n })\n .finally(() => {\n pullPromise = null;\n\n const nextTarget = requestedPullSyncId;\n requestedPullSyncId = null;\n\n if (nextTarget && nextTarget > pullSyncId.current) {\n pullEvents({ remoteSyncId: nextTarget });\n }\n });\n return pullPromise;\n };\n\n const pullAllEvents = async (opts: EventsPullRequest) => {\n let hasMore = true;\n let afterSyncId = opts.afterSyncId;\n while (hasMore) {\n if (remoteState.type !== \"online\") {\n return;\n }\n const source = remoteState.source;\n\n const response = await retryAsPromised(\n () =>\n source.pullEvents({\n ...opts,\n afterSyncId,\n }),\n {\n max: 3,\n backoffBase: 100,\n backoffExponent: 1.5,\n backoffJitter: 150,\n timeout: 10000,\n },\n );\n hasMore = response.hasMore;\n afterSyncId = response.nextSyncId;\n\n if (response.events) {\n storage.enqueueRemoteEvents(\n response.events.map((x) => {\n if (x.schema_version > migrator.currentSchemaVersion) {\n throw new Error(\n `Event schema version ${x.schema_version} is greater than current schema version ${migrator.currentSchemaVersion}`,\n );\n }\n return x;\n }),\n );\n }\n if (response.nextSyncId <= pullSyncId.current) {\n break;\n }\n if (response.nextSyncId > pullSyncId.current) {\n pullSyncId.current = response.nextSyncId;\n }\n }\n };\n\n const startPushingEvents = ensureSingletonExecution(async () => {\n while (true) {\n const eventsBatch = storage.getEventsBatch({\n status: \"applied\",\n afterSyncId: pushSyncId.current,\n excludeOrigin: \"remote\",\n limit: bufferSize,\n });\n if (eventsBatch.events.length === 0) {\n break;\n }\n\n if (remoteState.type !== \"online\") {\n break;\n }\n const source = remoteState.source;\n\n const migratedEvents = migrator.migrateEvents(eventsBatch.events);\n\n if (migratedEvents.length > 0) {\n try {\n await retryAsPromised(\n () =>\n source.pushEvents({\n nodeId,\n events: migratedEvents,\n }),\n {\n max: 3,\n backoffBase: 100,\n backoffExponent: 1.5,\n backoffJitter: 150,\n timeout: 10000,\n },\n );\n } catch (error) {\n console.error(\"Error pushing events. Going offline.\", error);\n goOffline(\"REMOTE_PUSH_ERROR\");\n return;\n }\n }\n\n pushSyncId.current = eventsBatch.nextSyncId;\n if (!eventsBatch.hasMore) {\n break;\n }\n }\n });\n\n const onEventsApplied = () => {\n startPushingEvents();\n };\n storage.addEventListener(\"events-applied\", onEventsApplied);\n\n const getState = (): \"pending\" | \"offline\" | \"online\" => remoteState.type;\n\n const dispose = async () => {\n await goOffline(\"DISCONNECTED\");\n storage.removeEventListener(\"events-applied\", onEventsApplied);\n };\n\n return {\n goOnline,\n goOffline,\n syncWithRemote,\n getState,\n dispose,\n addEventListener: eventTarget.addEventListener,\n removeEventListener: eventTarget.removeEventListener,\n };\n};\n","import type { SelectQueryBuilder } from \"kysely\";\nimport type { GetEventsOptions } from \"./crdt-storage\";\nimport type { PersistedCrdtEvent } from \"./crdt-table-schema\";\n\nexport function applyKyselyEventsBatchFilters(\n query: SelectQueryBuilder<any, any, PersistedCrdtEvent>,\n opts: GetEventsOptions,\n) {\n if (opts.afterSyncId) {\n query = query.where(\"sync_id\", \">\", opts.afterSyncId);\n }\n if (opts.status) {\n query = query.where(\"status\", \"=\", opts.status);\n }\n if (opts.excludeOrigin) {\n query = query.where(\"origin\", \"!=\", opts.excludeOrigin);\n }\n if (opts.excludeNodeId) {\n query = query.where(\"source_node_id\", \"!=\", opts.excludeNodeId);\n }\n\n return query.limit(opts.limit ?? 50).orderBy(\"sync_id\", \"asc\");\n}\n","import type { EventsPullRequest, EventsPushRequest, EventsPushResponse } from \"../sqlite-crdt/crdt-sync-remote-source\";\nimport type { CrdtEventType } from \"../sqlite-crdt/crdt-table-schema\";\nimport type { ExecuteParams, ExecuteResult } from \"../sqlite-db-wrapper\";\nimport { TypedBroadcastChannel } from \"../utils\";\n\nexport const syncDbWorkerLockName = \"sync-db-worker-lock\";\nexport const syncDbClientLockName = \"sync-db-client-lock\";\n\nexport type WorkerNotificationMessage =\n | {\n notificationType: \"new-event-chunk-applied\";\n newSyncId: number;\n }\n | {\n notificationType: \"state-changed\";\n state: WorkerState;\n };\n\nexport type WorkerState = {\n remoteState: \"online\" | \"offline\" | \"pending\";\n};\n\nexport type GetSnapshotResponse = {\n file: Uint8Array<ArrayBufferLike>;\n syncId: number;\n schemaVersion: number;\n};\n\nexport type EventsPullResponse = {\n events: {\n schema_version: number;\n type: CrdtEventType;\n timestamp: string;\n dataset: string;\n item_id: string;\n payload: string;\n }[];\n hasMore: boolean;\n nextSyncId: number;\n};\n\nexport interface WorkerRpc {\n getSnapshot: () => GetSnapshotResponse;\n pushTabEvents: (request: EventsPushRequest) => EventsPushResponse;\n execute: (query: ExecuteParams) => ExecuteResult<unknown>;\n pullEvents: (params: EventsPullRequest) => EventsPullResponse;\n postState: () => void;\n goOnline: () => Promise<void>;\n goOffline: () => void;\n}\n\nexport type WorkerRequestMethod = keyof WorkerRpc;\n\nexport type WorkerRequestMessage<TMethod extends WorkerRequestMethod = WorkerRequestMethod> = {\n type: \"request\";\n requestId: string;\n method: TMethod;\n args: Parameters<WorkerRpc[TMethod]>;\n};\n\nexport type WorkerResponseMessage<TMethod extends WorkerRequestMethod = WorkerRequestMethod> = {\n type: \"response\";\n requestId: string;\n data: ReturnType<WorkerRpc[TMethod]>;\n};\n\nexport type WorkerErrorResponseMessage = {\n type: \"error-response\";\n requestId: string;\n error: string;\n};\n\nexport type AsyncRpc<T> = {\n [K in keyof T]: T[K] extends (...args: infer U) => infer V ? (...args: U) => Promise<Awaited<V>> : never;\n};\n\nexport const broadcastChannelNames = {\n requests: \"sync-db-worker-requests\",\n responses: \"sync-db-worker-responses\",\n} as const;\n\nexport type WorkerBroadcastChannels = {\n requests: TypedBroadcastChannel<WorkerRequestMessage>;\n responses: TypedBroadcastChannel<WorkerResponseMessage | WorkerErrorResponseMessage | WorkerNotificationMessage>;\n};\n\nexport const createBroadcastChannels = (prefix: string): WorkerBroadcastChannels => {\n return {\n requests: new TypedBroadcastChannel(`${prefix}-${broadcastChannelNames.requests}`),\n responses: new TypedBroadcastChannel(`${prefix}-${broadcastChannelNames.responses}`),\n };\n};\n\nexport type WorkerConfig<Props = any> = {\n dbId: string;\n clientId: string;\n clearOnInit?: boolean;\n props: Props;\n};\n\nexport type WorkerInitMessage = {\n type: \"init\";\n config: WorkerConfig;\n};\n\nexport function isWorkerInitMessage(message: unknown): message is WorkerInitMessage {\n return typeof message === \"object\" && message !== null && \"type\" in message && message.type === \"init\";\n}\n\nexport function isWorkerRequestMessage(message: unknown): message is WorkerRequestMessage {\n return typeof message === \"object\" && message !== null && \"type\" in message && message.type === \"request\";\n}\n\nexport function isWorkerResponseMessage(message: unknown): message is WorkerResponseMessage {\n return (\n typeof message === \"object\" && message !== null && \"type\" in message && \"requestId\" in message && \"data\" in message\n );\n}\n\nexport function isWorkerErrorResponseMessage(message: unknown): message is WorkerErrorResponseMessage {\n return typeof message === \"object\" && message !== null && \"type\" in message && message.type === \"error-response\";\n}\n\nexport function isWorkerNotificationMessage(message: unknown): message is WorkerNotificationMessage {\n return typeof message === \"object\" && message !== null && \"notificationType\" in message && !!message.notificationType;\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,aAAa,QAAQ,eAAe,oBAAoB,2BAA2B;AAErF,IAAM,cAA2B,IAAI,OAAO;AAAA,EACjD,SAAS;AAAA,IACP,eAAe,MAAM,IAAI,cAAc;AAAA,IACvC,cAAc,MAAM,IAAI,YAAY;AAAA,IACpC,qBAAqB,MAAM,IAAI,oBAAoB;AAAA,IACnD,oBAAoB,CAAC,OAAO,IAAI,mBAAmB,EAAE;AAAA,EACvD;AACF,CAAC;;;ACHD,IAAM,cAAc,MAAM,IAAI;AAC9B,IAAM,uBAAuB,IAAI,KAAK,KAAK;AAEpC,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EAES;AAAA,EACA;AAAA,EAEjB,YAAY,QAAgB,cAA4B,WAAmB,sBAAsB;AAC/F,SAAK,YAAY,aAAa;AAC9B,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,eAAe;AACpB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,gBAAqB;AACnB,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,aAAkB;AAChB,UAAM,MAAM,KAAK,aAAa;AAE9B,QAAI,MAAM,KAAK,WAAW;AACxB,WAAK,YAAY;AACjB,WAAK,UAAU;AACf,aAAO,KAAK,cAAc;AAAA,IAC5B;AAEA,SAAK;AACL,QAAI,KAAK,UAAU,aAAa;AAC9B,YAAM,IAAI,MAAM,4CAA4C,WAAW,EAAE;AAAA,IAC3E;AACA,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,SAAS,KAAU;AACjB,UAAM,MAAM,KAAK,aAAa;AAC9B,QAAI,IAAI,YAAY,MAAM,KAAK,UAAU;AACvC,cAAQ;AAAA,QACN,8CAA8C,IAAI,SAAS,WAAW,GAAG,WAAW,IAAI,YAAY,GAAG;AAAA,MACzG;AACA;AAAA,IACF;AAEA,QAAI,KAAK,cAAc,IAAI,WAAW;AACpC,WAAK,UAAU,KAAK,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI;AAAA,IACvD,WAAW,KAAK,YAAY,IAAI,WAAW;AACzC,WAAK;AAAA,IACP,OAAO;AACL,WAAK,YAAY,IAAI;AACrB,WAAK,UAAU,IAAI,UAAU;AAAA,IAC/B;AACA,QAAI,KAAK,UAAU,aAAa;AAC9B,YAAM,IAAI,MAAM,4CAA4C,WAAW,EAAE;AAAA,IAC3E;AAAA,EACF;AACF;AAEO,SAAS,aAAa,KAAU;AACrC,SAAO,GAAG,IAAI,UAAU,SAAS,EAAE,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,QAAQ,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,IAAI,MAAM;AACjH;AAEO,SAAS,eAAe,YAAyB;AACtD,QAAM,QAAQ,WAAW,MAAM,GAAG;AAClC,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,IAAI,MAAM,yEAAyE,MAAM,MAAM,EAAE;AAAA,EACzG;AAEA,QAAM,YAAY,SAAS,MAAM,CAAC,GAAG,EAAE;AACvC,QAAM,UAAU,SAAS,MAAM,CAAC,GAAG,EAAE;AAErC,MAAI,OAAO,MAAM,SAAS,KAAK,OAAO,MAAM,OAAO,GAAG;AACpD,UAAM,IAAI,MAAM,iCAAiC,MAAM,CAAC,CAAC,aAAa,MAAM,CAAC,CAAC,EAAE;AAAA,EAClF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,EACjC;AACF;AAEO,SAAS,WAAW,KAAU,KAAU;AAC7C,MAAI,IAAI,cAAc,IAAI,WAAW;AACnC,QAAI,IAAI,YAAY,IAAI,SAAS;AAC/B,UAAI,IAAI,WAAW,IAAI,QAAQ;AAC7B,eAAO;AAAA,MACT;AACA,aAAO,IAAI,SAAS,IAAI,SAAS,KAAK;AAAA,IACxC;AACA,WAAO,IAAI,UAAU,IAAI;AAAA,EAC3B;AACA,SAAO,IAAI,YAAY,IAAI;AAC7B;;;AC1GA,SAAS,WAAW;AA2BpB,SAAS,YAAY,IAAuE;AAC1F,SAAO,GACJ,WAAW,eAAe,EAC1B,MAAM,QAAQ,MAAM,CAAC,SAAS,MAAM,CAAC,EACrC,MAAM,QAAQ,YAAY,UAAU,EACpC,OAAO,CAAC,QAAQ,OAAO,MAAM,CAAC,EAC9B,QAAQ,MAAM;AACnB;AAmBO,SAAS,aAA2B,KAA2D;AACpG,QAAM,KAAK;AACX,QAAM,SAAS,GAAG,cAAc,CAACA,QAAO,YAAYA,GAA6C,GAAG;AAAA,IAClG,aAAa;AAAA,EACf,CAAC,EAAE;AAEH,QAAM,iBAAiB,GAAG;AAAA,IACxB,CAACA,QACCA,IACG,KAAK,cAAc,CAAC,OAAO,YAAY,EAA6C,CAAC,EACrF,WAAW,CAAC,oBAAoB,gCAAiD,GAAG,GAAG,CAAC,CAAC,EACzF,OAAO,CAAC,oBAAoB,SAAS,UAAU,UAAU,aAAa,gBAAgB,MAAM,CAAC,EAC7F,QAAQ,SAAS,EACjB,QAAQ,OAAO;AAAA,IACpB,EAAE,aAAa,SAAS;AAAA,EAC1B,EAAE;AAEF,QAAM,iBAAwD,CAAC;AAC/D,aAAW,OAAO,gBAAgB;AAChC,mBAAe,IAAI,KAAK,MAAM,CAAC;AAC/B,mBAAe,IAAI,KAAK,EAAE,KAAK,GAAG;AAAA,EACpC;AAEA,SAAO,OAAO;AAAA,IACZ,OAAO,IAAI,CAAC,EAAE,MAAM,KAAAC,MAAK,KAAK,MAAM;AAElC,UAAI,mBAAmBA,MACnB,MAAM,OAAO,GACb,KAAK,CAAC,OAAO,GAAG,YAAY,EAAE,SAAS,eAAe,CAAC,GACvD,UAAU,GACV,MAAM,KAAK,IAAI,CAAC,GAChB,QAAQ,SAAS,EAAE;AAEvB,YAAM,UAAU,eAAe,IAAI,KAAK,CAAC;AAIzC,UAAI,CAAC,kBAAkB;AACrB,cAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;AAC7C,YAAI,OAAO,WAAW,KAAK,OAAO,CAAC,EAAE,KAAK,YAAY,MAAM,WAAW;AACrE,6BAAmB,OAAO,CAAC,EAAE;AAAA,QAC/B;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,UACE;AAAA,UACA,QAAQ,SAAS;AAAA,UACjB,SAAS,QAAQ,IAAI,CAAC,SAAS;AAAA,YAC7B,MAAM,IAAI;AAAA,YACV,UAAU,IAAI;AAAA,YACd,YAAY,CAAC,IAAI;AAAA,YACjB,oBAAoB,IAAI,SAAS;AAAA,YACjC,iBAAiB,IAAI,cAAc;AAAA,YACnC,SAAS;AAAA,UACX,EAAE;AAAA,QACJ;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC/GO,IAAM,yBAAyB,CAAC,WAAmB;AACxD,MAAI,YAAY,YAAY,IAAI;AAEhC,SAAO;AAAA,IACL,SAAS,MAAM;AACb,kBAAY,YAAY,IAAI;AAAA,IAC9B;AAAA,IACA,QAAQ,CAAC,MAAc,SAAiB,QAAkB,WAAW;AACnE,YAAM,UAAU,YAAY,IAAI,IAAI;AAEpC,aAAO,MAAM,GAAG,QAAQ,QAAQ,CAAC,CAAC,QAAQ,OAAO,IAAI,KAAK;AAAA,IAC5D;AAAA,EACF;AACF;;;AC+BO,IAAM,kBAAN,MAA2C;AAAA,EACxC,KAA4B;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EAEA,iBAA+C;AAAA,EAEtC,eAAe,CAAC;AAAA,EAEzB,qBAA+D,CAAC;AAAA,EAChE,wBAAwB,oBAAI,IAA8D;AAAA,EAC1F,2BAA2B,oBAAI,IAAoD;AAAA,EAE3F,YAAY,MAA4B;AACtC,SAAK,KAAK,KAAK,GAAG;AAClB,SAAK,UAAU,KAAK;AACpB,SAAK,SAAS,KAAK;AACnB,SAAK,eAAe,KAAK;AAAA,EAC3B;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,IAAI;AACZ,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,gBAAgB;AACxB,WAAK,iBAAiB,aAAa,IAAI;AAAA,IACzC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAqB,MAAiD,MAAwC;AAC5G,UAAMC,OAAM,OAAO,SAAS,WAAW,OAAO,KAAK;AACnD,UAAM,OAAO,OAAO,SAAS,WAAW,SAAY,KAAK;AAEzD,UAAM,OAAO,KAAK,SAAS,uBAAuB,KAAK,MAAM,IAAI;AACjE,UAAM,OAAO,KAAK,SAAS,KAAK;AAAA,MAC9B,KAAAA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AACD,UAAM,OAAO,GAAG,KAAK,gBAAgB,EAAE,UAAUA,MAAK,MAAM,WAAW;AAEvE,WAAO,EAAE,KAAkB;AAAA,EAC7B;AAAA,EAEA,mBAAsB,UAA6D;AACjF,UAAM,cAAc,KAAK,iBAAiB;AAC1C,QAAI;AACF,YAAM,SAAS,SAAS,IAAI;AAC5B,kBAAY,OAAO;AACnB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,kBAAY,SAAS;AACrB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,kBAAkB;AAEhB,WAAQ,KAAK,QAAQ,KAAa,uBAAuB,KAAK,QAAQ,MAAM;AAAA,EAC9E;AAAA,EAEA,mBAAmB;AACjB,SAAK,mBAAmB;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,QACJ,aAAa;AAAA,MACf;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,MAAM;AACZ,aAAK,mBAAmB;AAAA,UACtB,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,YACJ,aAAa;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA,UAAU,MAAM;AACd,aAAK,mBAAmB;AAAA,UACtB,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,YACJ,aAAa;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAA6CA,MAAa,MAAsB;AAC9E,UAAM,OAAO,KAAK,SAAS,uBAAuB,KAAK,MAAM,IAAI;AACjE,UAAM,OAAO,KAAK,SAAS,QAAQA,IAAG;AACtC,UAAM,OAAO,GAAG,KAAK,gBAAgB,EAAE,YAAYA,MAAK,MAAM,WAAW;AAEzE,QAAI,cAAc;AAElB,UAAM,UAAU,CAAC,WAAoB;AACnC,UAAI,aAAa;AACf,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,YAAMC,QAAO,KAAK,SAAS,uBAAuB,KAAK,MAAM,IAAI;AACjE,UAAI,OAAO,SAAS,GAAG;AACrB,aAAK,KAAK,MAAM;AAAA,MAClB;AACA,YAAM,UAAU,CAAC;AACjB,aAAO,KAAK,KAAK,GAAG;AAClB,gBAAQ,KAAK,KAAK,IAAI,CAAC,CAAC,CAAY;AAAA,MACtC;AACA,WAAK,MAAM,IAAI;AACf,MAAAA,OAAM,OAAO,GAAG,KAAK,gBAAgB,EAAE,oBAAoBD,MAAK,MAAM,WAAW;AACjF,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM;AACrB,oBAAc;AACd,WAAK,SAAS;AAAA,IAChB;AAEA,UAAM,oBAAyD;AAAA,MAC7D;AAAA,MACA;AAAA,MACA,IAAI,cAAc;AAChB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,SAAK,mBAAmB,KAAK,iBAA2D;AAExF,WAAO;AAAA,EACT;AAAA,EAEA,cAAuD,MAAsB;AAC3E,WAAO,CACL,YACqC;AACrC,YAAM,QAAQ,QAAQ,aAAa,CAAC,QAAQ,GAAU,EAAE,QAAQ;AAChE,YAAM,YAAY,KAAK,QAA6B,MAAM,KAAK,IAAI;AAEnE,aAAO;AAAA,QACL,SAAS,CAAC,eAAe;AACvB,gBAAM,SAAS,MAAM,WAAW,IAAI,CAAC,UAAU,WAAW,KAAsB,CAAC;AACjF,gBAAM,SAAS,UAAU,QAAQ,MAAoB;AACrD,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cACE,SACA,MACA;AACA,UAAM,QAAQ,QAAQ,WAAW,EAAE,QAAQ;AAC3C,WAAO,KAAK,QAAQ,OAAO,IAAI;AAAA,EACjC;AAAA,EAEA,gBAKE,KACA,QACA,SACA,MACA;AACA,QAAI,YAAY,KAAK,sBAAsB,IAAI,GAAG;AAClD,QAAI,CAAC,WAAW;AACd,kBAAY,KAAK,cAAuB,IAAI,EAAE,OAAO;AACrD,WAAK,sBAAsB,IAAI,KAAK,SAA6D;AAAA,IACnG;AAEA,WAAO,UAAU,QAAQ,MAAM;AAAA,EACjC;AAAA,EAEA,mBAAwD;AAAA,IACtD;AAAA,IACA,KAAAA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAKG;AACD,QAAI,YAAY,KAAK,yBAAyB,IAAI,GAAG;AACrD,QAAI,CAAC,WAAW;AACd,kBAAY,KAAK,QAAQA,MAAK,IAAI;AAClC,WAAK,yBAAyB,IAAI,KAAK,SAA8C;AAAA,IACvF;AAEA,WAAO,UAAU,QAAS,UAAU,CAAC,CAAa;AAAA,EACpD;AAAA,EAEA,IAAiB,qBAAoD,YAAuB;AAC1F,QAAI,OAAO,qBAAqB,UAAU;AACxC,aAAO,KAAK,QAAW;AAAA,QACrB,KAAK;AAAA,QACL;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO,KAAK,QAAW;AAAA,MACrB,KAAK,iBAAiB,KAAK,GAAG;AAAA,MAC9B;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,qBAAqF;AAAA,IACnF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA0C;AACxC,WAAO,KAAK,SAAS,eAAe;AAAA,MAClC;AAAA,MACA,OAAO,CAAC,MAAM,SAAS;AACrB,cAAM,SAAS,SAAS,GAAI,IAAc;AAC1C,eAAO;AAAA,MACT;AAAA,MACA,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,UAAuC;AACjD,UAAM,OAAO,KAAK,SAAS,uBAAuB,KAAK,MAAM,IAAI;AACjE,UAAM,cAAc,KAAK,QAAQ,KAAK,oBAAoB,QAAQ;AAClE,SAAK,aAAa,KAAK,WAAW;AAElC,UAAM,aAAa,KAAK,QAAQ,KAAK;AAAA,MACnC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT,KAAK,QAAQ,KAAK,iCAAiC,KAAK,QAAQ,KAAK;AAAA,IACvE;AAEA,SAAK,SAAS,QAAQ,UAAU;AAEhC,SAAK,mBAAmB;AAExB,UAAM,OAAO,eAAe,WAAW,QAAQ;AAAA,EACjD;AAAA,EAEA,iBAAiB;AACf,WAAO,KAAK,QAAQ,KAAK,qBAAqB,KAAK,QAAQ;AAAA,EAC7D;AAAA,EAEA,qBAAqB;AACnB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,UAAU;AACR,SAAK,mBAAmB,QAAQ,CAAC,SAAS;AACxC,WAAK,SAAS;AAAA,IAChB,CAAC;AACD,SAAK,mBAAmB,OAAO,CAAC;AAChC,SAAK,sBAAsB,MAAM;AACjC,SAAK,yBAAyB,MAAM;AAAA,EACtC;AAAA,EAEA,QAAQ;AACN,SAAK,QAAQ;AAEb,SAAK,IAAI,MAAM;AACf,SAAK,KAAK;AAAA,EACZ;AACF;;;ACjRA,IAAM,mBAAmB,CAAC,MAAM,WAAW;AAE3C,SAAS,yBAAyB,QAAgB,WAAmB;AACnE,MAAI,iBAAiB,SAAS,MAAM,GAAG;AACrC,UAAM,IAAI,MAAM,UAAU,SAAS,sBAAsB,MAAM,GAAG;AAAA,EACpE;AACF;AAEA,IAAM,iBAAiB;AAAA,EACrB,aAAa,CAAC,OAAe,WAAoF;AAAA,IAC/G,KAAK,CAAC,OAAO,MAAM,GAAG,OAAO,YAAY,KAAK,CAAC;AAAA,EACjD;AAAA,EAEA,WAAW,CAAC,WAAkC;AAAA,IAC5C,KAAK,CAAC,OAAO,GAAG,OAAO,UAAU,KAAK;AAAA,IACtC,kBAAkB;AAAA,MAChB,CAAC,KAAK,GAAG,MAAM;AAAA,IACjB;AAAA,IACA,YAAY,CAAC,KAAK;AAAA,EACpB;AAAA,EAEA,aAAa,CAAC,WAAmB,WAAqE;AAAA,IACpG,KAAK,CAAC,OAAO,MAAM,GAAG,OAAO,YAAY,SAAS,CAAC;AAAA,EACrD;AAAA,EAEA,WAAW,CAAC,eAAsC;AAAA,IAChD,KAAK,CAAC,OAAO,GAAG,OAAO,UAAU,SAAS;AAAA,EAC5C;AAAA,EAEA,aAAa,CAAC,EAAE,UAAU,SAAS,OAA8D;AAAA,IAC/F,KAAK,CAAC,OAAO,GAAG,OAAO,WAAW,QAAQ,EAAE,SAAS,QAAQ;AAAA,IAC7D,kBAAkB;AAAA,MAChB,CAAC,QAAQ,GAAG,CAAC,UAAU;AACrB,cAAM,UAAU;AAChB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,cAAc,CAAC,EAAE,UAAU,SAAS,CAAC;AAAA,EACvC;AAAA,EAEA,cAAc,CAAC;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAIqB;AACnB,6BAAyB,WAAW,QAAQ;AAC5C,6BAAyB,WAAW,WAAW;AAC/C,WAAO;AAAA,MACL,KAAK,CAAC,OAAO,GAAG,OAAO,WAAW,KAAK,EAAE,aAAa,WAAW,SAAS;AAAA,MAC1E,kBAAkB;AAAA,QAChB,CAAC,KAAK,GAAG,CAAC,UAAU;AAClB,cAAK,MAAM,SAAS,kBAAkB,MAAM,SAAS,kBAAmB,EAAE,aAAa,MAAM,UAAU;AACrG,mBAAO;AAAA,UACT;AAEA,gBAAM,SAAS,MAAM,QAAQ,SAAS;AACtC,iBAAO,MAAM,QAAQ,SAAS;AAC9B,gBAAM,QAAQ,SAAS,IAAI;AAE3B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,CAAC;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC,MAAM;AAAA,EACjB,OAMsB;AAAA,IACpB,KAAK,CAAC,OAAO,GAAG,OAAO,WAAW,KAAK,EAAE,UAAU,QAAQ,MAAM,CAAC,MAAM,MAAM,CAAC,EAAE,UAAU,YAAY,CAAC;AAAA,IACxG,kBAAkB;AAAA,MAChB,CAAC,KAAK,GAAG,CAAC,UAAU;AAClB,YAAI,MAAM,SAAS,gBAAgB;AACjC,iBAAO;AAAA,QACT;AAEA,cAAM,QAAQ,MAAM,IAAI;AAExB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,CAAC,EAAE,OAAO,OAAO,MAAwD;AACnF,6BAAyB,QAAQ,MAAM;AACvC,WAAO;AAAA,MACL,KAAK,CAAC,OAAO,GAAG,OAAO,WAAW,KAAK,EAAE,WAAW,MAAM;AAAA,MAC1D,kBAAkB;AAAA,QAChB,CAAC,KAAK,GAAG,CAAC,UAAU;AAClB,cAAI,EAAE,UAAU,MAAM,UAAU;AAC9B,mBAAO;AAAA,UACT;AAEA,iBAAO,MAAM,QAAQ,MAAM;AAE3B,cAAI,MAAM,SAAS,kBAAkB,OAAO,KAAK,MAAM,OAAO,EAAE,WAAW,GAAG;AAC5E,mBAAO;AAAA,UACT;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,kBAAkB,OAAwC;AACjE,SAAO,MACJ,QAAQ,CAAC,SAAU,MAAM,QAAQ,KAAK,GAAG,IAAI,KAAK,MAAM,CAAC,KAAK,GAAG,CAAE,EACnE,IAAI,CAACE,SAAsB;AAC1B,QAAI,OAAOA,SAAQ,UAAU;AAC3B,aAAO,EAAE,KAAAA,MAAK,YAAY,CAAC,EAAE;AAAA,IAC/B;AAEA,QAAI,OAAOA,SAAQ,YAAY;AAC7B,YAAM,QAAQA,KAAI,WAAW,EAAE,QAAQ;AACvC,aAAO,EAAE,KAAK,MAAM,KAAK,YAAY,MAAM,WAAW;AAAA,IACxD;AAEA,QAAI,aAAaA,MAAK;AACpB,YAAM,QAAQA,KAAI,QAAQ;AAC1B,aAAO,EAAE,KAAK,MAAM,KAAK,YAAY,MAAM,WAAW;AAAA,IACxD;AAEA,WAAO;AAAA,MACL,KAAKA,KAAI;AAAA,MACT,YAAYA,KAAI,cAAc,CAAC;AAAA,IACjC;AAAA,EACF,CAAC;AACL;AAEA,SAAS,+BAA+B,OAAuE;AAC7G,QAAM,eAAsD,CAAC;AAE7D,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,kBAAkB;AACzB,mBAAa,KAAK,GAAG,OAAO,QAAQ,KAAK,gBAAgB,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,UAAqB;AAC3B,QAAI,mBAAqC;AAEzC,eAAW,CAAC,OAAO,WAAW,KAAK,cAAc;AAC/C,UAAI,qBAAqB,MAAM;AAC7B,eAAO;AAAA,MACT;AACA,UAAI,iBAAiB,YAAY,OAAO;AACtC;AAAA,MACF;AACA,yBAAmB,YAAY,gBAAgB;AAC/C,UAAI,qBAAqB,MAAM;AAC7B,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,iBAAiB,iBAAsF;AACrH,QAAM,aAA+C,OAAO;AAAA,IAC1D,OAAO,QAAQ,gBAAgB,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM;AACxE,YAAM,gBAAgB,OAAO,OAAO;AAEpC,UAAI,OAAO,MAAM,aAAa,GAAG;AAC/B,cAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,MACzD;AAEA,UAAI,gBAAgB,GAAG;AACrB,cAAM,IAAI,MAAM,yCAAyC,OAAO,EAAE;AAAA,MACpE;AAEA,YAAM,eAAe,MAAM,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAC9D,YAAM,aAAa,MAAM,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE1D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,UACE,KAAK,kBAAkB,KAAK;AAAA,UAC5B,kBAAkB,+BAA+B,KAAK;AAAA,UACtD,GAAI,aAAa,SAAS,KAAK,EAAE,aAAa;AAAA,UAC9C,GAAI,WAAW,SAAS,KAAK,EAAE,WAAW;AAAA,QAC5C;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAYO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,sBAAsB,KAAK,IAAI,GAAG,OAAO,KAAK,UAAU,EAAE,IAAI,MAAM,CAAC;AAG3E,QAAM,mBAAmB,OAAO,QAAQ,UAAU,EAC/C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAU,EACvC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAE7B,QAAM,iBAAiB,CAAC,IAAkB,SAAiB,cAAgC;AACzF,QAAI,WAAW,cAAc,SAAS;AACpC,YAAM,IAAI,MAAM,0BAA0B,OAAO,sBAAsB,cAAc,OAAO,EAAE;AAAA,IAChG;AAEA,OAAG,iBAAiB,CAAC,OAAO;AAC1B,iBAAW,aAAa,UAAU,KAAK;AACrC,WAAG,QAAQ,UAAU,KAAK,UAAU,UAAU;AAAA,MAChD;AACA,UAAI,oBAAoB;AACtB,YAAI,UAAU,cAAc;AAC1B,qBAAW,EAAE,UAAU,SAAS,KAAK,UAAU,cAAc;AAC3D,eAAG,QAAQ,UAAU,kBAAkB,0CAA0C,CAAC,UAAU,QAAQ,CAAC;AAAA,UACvG;AAAA,QACF;AACA,YAAI,UAAU,YAAY;AACxB,qBAAW,SAAS,UAAU,YAAY;AACxC,eAAG,QAAQ,eAAe,kBAAkB,wBAAwB,CAAC,KAAK,CAAC;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AACA,oBAAc,UAAU;AAAA,IAC1B,CAAC;AAAA,EACH;AAEA,QAAM,eAAe,CAAgC,OAAc,kBAAyC;AAC1G,sBAAkB;AAClB,QAAI,gBAAgB,cAAc,SAAS;AACzC,YAAM,IAAI;AAAA,QACR,yBAAyB,aAAa,2CAA2C,cAAc,OAAO;AAAA,MACxG;AAAA,IACF;AAEA,QAAI,MAAM,kBAAkB,eAAe;AACzC,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,MAAM;AAE1B,QAAI,YAA8B;AAAA,MAChC,SAAS,MAAM;AAAA,MACf,SAAS,MAAM;AAAA,MACf,MAAM,MAAM;AAAA,MACZ,SAAS,KAAK,MAAM,MAAM,OAAO;AAAA,IACnC;AAEA,aAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,YAAM,CAAC,SAAS,SAAS,IAAI,iBAAiB,CAAC;AAC/C,UAAI,WAAW,YAAa;AAC5B,UAAI,UAAU,cAAe;AAE7B,YAAM,cAAc,UAAU;AAC9B,UAAI,aAAa;AACf,oBAAY,YAAY,SAAS;AACjC,YAAI,cAAc,KAAM,QAAO;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,cAAc,MAAM;AACtB,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB;AACvB,UAAM,UAAU,UAAU;AAC1B,UAAM,UAAU,UAAU;AAC1B,UAAM,OAAO,UAAU;AACvB,UAAM,UAAU,KAAK,UAAU,UAAU,OAAO;AAEhD,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,CAAgC,QAAiB,kBAAoC;AACzG,WAAO,OACJ,IAAI,CAAC,UAAU,aAAa,OAAO,iBAAiB,mBAAmB,CAAC,EACxE,OAAO,CAAC,UAA8C,UAAU,IAAI;AAAA,EACzE;AAEA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,uBAAuB;AACzB,aAAO,cAAc;AAAA,IACvB;AAAA,IACA,mBAAmB,CAAC,OAAqB;AACvC,YAAM,uBAAuB,cAAc;AAE3C,UAAI,wBAAwB,qBAAqB;AAC/C;AAAA,MACF;AAEA,eAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,cAAM,CAAC,SAAS,SAAS,IAAI,iBAAiB,CAAC;AAC/C,YAAI,WAAW,qBAAsB;AACrC,uBAAe,IAAI,SAAS,SAAS;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpYO,SAAS,kBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAGmB;AACjB,MAAI,eAAe;AAEnB,SAAO;AAAA,IACL,IAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAAA,IACA,IAAI,QAAQ,UAAa;AACvB,sBAAgB,QAAQ;AACxB,qBAAe;AAAA,IACjB;AAAA,EACF;AACF;;;ACdO,SAAS,wBAAwB,QAAsB,WAAmB;AAC/E,SAAO,OACJ,YAAY,SAAS,EACrB,YAAY,EACZ,UAAU,OAAO,QAAQ,CAAC,QAAQ,IAAI,QAAQ,EAAE,WAAW,CAAC,EAC5D,UAAU,SAAS,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC;AACtD;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGG;AACD,QAAM,SAAS;AAIf,QAAM,MAAM,CAAC,QAA+B;AAC1C,UAAM,CAAC,MAAM,IAAI,OAAO;AAAA,MACtB;AAAA,MACA,EAAE,IAAI;AAAA,MACN,CAACC,KAAI,WACHA,IACG,WAAW,aAAuB,EAClC,MAAM,OAAO,KAAK,OAAO,KAAK,CAAC,EAC/B,OAAO,OAAO,EACd,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAAA,MAC5B,EAAE,aAAa,SAAS;AAAA,IAC1B;AAEA,WAAO,QAAQ,SAAS;AAAA,EAC1B;AAEA,QAAM,MAAM,CAAC,KAAa,UAAkB;AAC1C,WAAO;AAAA,MACL;AAAA,MACA,EAAE,KAAK,MAAM;AAAA,MACb,CAACA,KAAI,WACHA,IACG,WAAW,aAAuB,EAClC,OAAO,EAAE,KAAK,OAAO,KAAK,GAAG,OAAO,OAAO,OAAO,EAAE,CAAC,EACrD,WAAW,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO,OAAO,OAAO,EAAE,CAAC,CAAC;AAAA,MAClE,EAAE,aAAa,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,QAAgB;AAC9B,WAAO;AAAA,MACL;AAAA,MACA,EAAE,IAAI;AAAA,MACN,CAACA,KAAI,WAAWA,IAAG,WAAW,aAAuB,EAAE,MAAM,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,MACtF,EAAE,aAAa,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,qBAAqB,CAAI,KAAa,iBAAgC;AAC1E,UAAM,QAAQ,IAAI,GAAG;AACrB,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,cAAc,OAAO,SAAS,OAAO,EAAE;AAC7C,WAAO,OAAO,MAAM,WAAW,IAAI,eAAe;AAAA,EACpD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,yBAAyB,CAAC,KAAa,iBACrC,kBAA0B;AAAA,MACxB,cAAc,IAAI,GAAG,KAAK;AAAA,MAC1B,eAAe,CAAC,QAAQ,IAAI,KAAK,GAAG;AAAA,IACtC,CAAC;AAAA,IACH,yBAAyB,CAAC,KAAa,iBACrC,kBAA0B;AAAA,MACxB,cAAc,mBAAmB,KAAK,YAAY;AAAA,MAClD,eAAe,CAAC,QAAQ,IAAI,KAAK,IAAI,SAAS,CAAC;AAAA,IACjD,CAAC;AAAA,EACL;AACF;;;AC7DO,IAAM,uBAA0C;AAAA,EACrD;AAAA,IACE,SAAS;AAAA,IACT,IAAI,CAAC,QAAgC;AACnC,UAAI,QAAQ,8BAA8B,IAAI,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAU3D;AACF,UAAI,QAAQ,8BAA8B,IAAI,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,QAK9D;AAAA,IACJ;AAAA,EACF;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,IAAI,CAAC,QAAgC;AACnC,UAAI,QAAQ,eAAe,IAAI,eAAe,uDAAuD;AAAA,IACvG;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,MAO3B;AACP,QAAM,MAA8B;AAAA,IAClC,iBAAiB,KAAK;AAAA,IACtB,oBAAoB,KAAK;AAAA,IACzB,SAAS,KAAK;AAAA,EAChB;AACA,aAAW,aAAa,KAAK,YAAY;AACvC,QAAI,UAAU,UAAU,KAAK,QAAQ,SAAS;AAC5C,WAAK,YAAY,MAAM;AACrB,kBAAU,GAAG,GAAG;AAChB,aAAK,QAAQ,UAAU,UAAU;AAAA,MACnC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,IAA0B;AAE5D,KAAG,cAAc,CAAC,WAAW,wBAAwB,OAAO,QAAQ,WAAW,GAAG,EAAE,aAAa,SAAS,CAAC;AAG3G,QAAM,UAAU,oBAAoB,EAAE,IAAI,eAAe,YAAY,CAAC;AACtE,sBAAoB;AAAA,IAClB,YAAY;AAAA,IACZ,SAAS,QAAQ,wBAAwB,2BAA2B,EAAE;AAAA,IACtE,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,SAAS,CAACC,SAAQ,GAAG,QAAQA,MAAK,EAAE,aAAa,SAAS,CAAC;AAAA,IAC3D,aAAa,CAAC,aAAa,GAAG,mBAAmB,QAAQ;AAAA,EAC3D,CAAC;AACH;AAEO,SAAS,oBAAoB,IAA0B;AAC5D,KAAG;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,EAAE,aAAa,SAAS;AAAA,EAC1B;AACF;;;ACpGO,IAAM,gCAAgC,CAAC;AAAA,EAC5C;AAAA,EACA;AACF,MAGM;AACJ,QAAM,iBAAiB,wBAAwB;AAAA,IAC7C,iBAAiB,MAAM;AACrB,YAAM,CAAC,OAAO,IAAI,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,UACE,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,QAChB;AAAA,QACA,CAACC,KAAI,WAAW;AACd,iBAAQA,IACL,WAAW,kBAA6B,EACxC,OAAO,SAAS,EAChB,MAAM,WAAW,KAAK,OAAO,SAAS,CAAC,EACvC,MAAM,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,QAC5C;AAAA,QACA,EAAE,aAAa,SAAS;AAAA,MAC1B;AACA,YAAM,OAAO,UAAW,KAAK,MAAM,QAAQ,OAAO,IAA6B;AAC/E,aAAO;AAAA,IACT;AAAA,IACA,oBAAoB,MAAM;AACxB,SAAG;AAAA,QACD;AAAA,QACA;AAAA,UACE,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,QAChB;AAAA,QACA,CAACA,KAAI,WACFA,IAAuD,WAAW,kBAA6B,EAAE,OAAO;AAAA,UACvG,SAAS,OAAO,SAAS;AAAA,UACzB,SAAS,OAAO,SAAS;AAAA,UACzB,SAAS,OAAO,SAAS;AAAA,QAC3B,CAAC;AAAA,QACH,EAAE,aAAa,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,oBAAoB,MAAM;AACxB,SAAG;AAAA,QACD;AAAA,QACA;AAAA,UACE,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA,QAChB;AAAA,QACA,CAACA,KAAI,WACFA,IACE,YAAY,kBAA6B,EACzC,IAAI;AAAA,UACH,SAAS,OAAO,SAAS;AAAA,QAC3B,CAAC,EACA,MAAM,WAAW,KAAK,OAAO,SAAS,CAAC,EACvC,MAAM,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,QAC5C,EAAE,aAAa,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,YAAM,gBAAgB,CAAC;AACvB,iBAAW,OAAO,OAAO,KAAK,KAAK,OAAO,GAAG;AAC3C,sBAAc,GAAG,IAAI;AAAA,MACvB;AACA,SAAG;AAAA,QACD,oBAAoB,KAAK,OAAO;AAAA,QAChC,KAAK;AAAA,QACL,CAACA,QAAOA,IAAG,WAAW,KAAK,OAAO,EAAE,OAAO,aAAa;AAAA,QACxD,EAAE,aAAa,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,YAAM,OAAO,MAAM,KAAK,OAAO,KAAK,KAAK,OAAO,CAAC;AACjD,SAAG;AAAA,QACD;AAAA,UACE,KAAK,UAAU,QAAQ,KAAK,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,GAAG,QAAQ,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC;AAAA,UAC9F,YAAY,CAAC,GAAG,KAAK,IAAI,CAAC,QAAQ,KAAK,QAAQ,GAAG,CAAC,GAAG,KAAK,MAAM;AAAA,QACnE;AAAA,QACA,EAAE,aAAa,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAUO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AAKtB,QAAM,mBAAmB,CAAC,EAAE,OAAO,KAAK,MAAuB;AAC7D,QAAI,MAAM;AAER,uBAAiB,EAAE,OAAO,KAAK,CAAC;AAChC;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,MAAM,MAAM,OAAO;AAE7C,iBAAa,YAAY;AACzB,eAAW,EAAE,SAAS,MAAM,SAAS,SAAS,aAAa,CAAC;AAE5D,UAAM,eAAe,CAAC;AACtB,eAAW,OAAO,OAAO,KAAK,YAAY,GAAG;AAC3C,mBAAa,GAAG,IAAI,MAAM;AAAA,IAC5B;AAEA,wBAAoB;AAAA,MAClB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,SAAS,KAAK,UAAU,YAAY;AAAA,IACtC,CAAC;AAAA,EACH;AAMA,QAAM,mBAAmB,CAAC,EAAE,OAAO,KAAK,MAAuB;AAC7D,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,QAAQ,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY;AAAA,IAC/E;AACA,UAAM,eAAe,KAAK,MAAM,MAAM,OAAO;AAE7C,UAAM,gBAAgB,CAAC;AACvB,QAAI,aAAa;AAEjB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,YAAM,sBAAsB,KAAK,GAAG;AACpC,YAAM,yBAAyB,MAAM;AAErC,UAAI,CAAC,uBAAuB,CAAC,0BAA0B,yBAAyB,qBAAqB;AACnG,sBAAc,GAAG,IAAI;AACrB,aAAK,GAAG,IAAI;AACZ,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAEA,eAAW;AAAA,MACT,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,SAAS;AAAA,IACX,CAAC;AACD,wBAAoB;AAAA,MAClB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,SAAS,KAAK,UAAU,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,UAA4B;AAClC,UAAM,OAAO,iBAAiB;AAAA,MAC5B,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM;AAAA,IACjB,CAAC;AAID,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,gBAAgB;AACnB,yBAAiB;AAAA,UACf;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,QAAQ,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY;AAAA,QAC/E;AAEA,yBAAiB;AAAA,UACf;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MACA;AACE,cAAM;AAAA,IACV;AAAA,EACF;AACF;;;ACrIO,SAAS,kBAAkB,SAA0B;AAC1D,QAAM,cAAc,QAAQ,gBAAgB,CAAC,aAAa,SAAS;AACnE,QAAM,cAAc,uBAEjB;AAEH,QAAM,gBAAgB,CAAC,QAAyB,cAAsB,WAAgC;AACpG,QAAI,OAAO,WAAW,GAAG;AACvB;AAAA,IACF;AAEA,gBAAY,MAAM;AAChB,iBAAW,SAAS,QAAQ;AAC1B,gBAAQ,aAAa;AAAA,UACnB,gBAAgB,MAAM,kBAAkB,QAAQ,SAAS;AAAA,UACzD,WAAW,MAAM,aAAa,aAAa,QAAQ,IAAI,WAAW,CAAC;AAAA,UACnE,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,MAAM;AAAA,UACf,SAAS,EAAE,QAAQ,OAAO;AAAA,UAC1B,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,0BAAsB;AAAA,EACxB;AAEA,QAAM,qBAAqB,CAAC,QAA0B,iBAAyB;AAC7E,kBAAc,SAAS,cAAc,MAAM;AAAA,EAC7C;AAEA,QAAM,mBAAmB,CAAC,WAA2B;AACnD,kBAAc,OAAO,QAAQ,QAAQ,MAAM;AAAA,EAC7C;AAEA,QAAM,sBAAsB,CAAC,WAA8B;AACzD,kBAAc,UAAU,IAAI,MAAM;AAAA,EACpC;AAEA,QAAM,gBAAgB,CAAC,OAAqB,EAAE,kBAAkB,IAAqC,CAAC,MAAM;AAC1G,UAAM,iBAAqC;AAAA,MACzC,gBAAgB,QAAQ,SAAS;AAAA,MACjC,WAAW,aAAa,QAAQ,IAAI,WAAW,CAAC;AAAA,MAChD,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,SAAS,MAAM;AAAA,MACf,QAAQ;AAAA,MACR,gBAAgB,QAAQ;AAAA,MACxB,SAAS,MAAM;AAAA,MACf,SAAS,EAAE,QAAQ,OAAO;AAAA,MAC1B,QAAQ;AAAA,IACV;AAEA,QAAI,mBAAmB;AACrB,kBAAY,MAAM;AAChB,gBAAQ,aAAa,cAAc;AACnC,8BAAsB,cAAc;AAAA,MACtC,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,aAAa,cAAc;AACnC,4BAAsB,cAAc;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,wBAAwB,MAAM;AAClC,gBAAY,cAAc,kBAAkB;AAAA,MAC1C,QAAQ,QAAQ,OAAO;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,CAAC,YAA8C;AACpE,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,SAAS,QAAQ,eAAe;AAAA,MACpC,GAAG;AAAA,MACH,OAAO,QAAQ;AAAA,IACjB,CAAC;AACD,UAAM,UAAU,OAAO,SAAS;AAChC,QAAI,SAAS;AACX,aAAO,IAAI;AAAA,IACb;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,YAAY,OAAO,OAAO,SAAS,CAAC,GAAG,WAAW,QAAQ,eAAe;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,wBAAwB,CAAC,UAA8B;AAC3D,QAAI,MAAM,WAAW,WAAW;AAC9B,YAAM,IAAI,MAAM,SAAS,MAAM,OAAO,iBAAiB;AAAA,IACzD;AAEA,QAAI;AAEF,UAAI,MAAM,WAAW,WAAW,MAAM,WAAW,UAAU;AACzD,gBAAQ,IAAI,SAAS,eAAe,MAAM,SAAS,CAAC;AAAA,MACtD;AAGA,YAAM,gBAAgB,QAAQ,SAAS,aAAa,OAAO,QAAQ,SAAS,mBAAmB;AAE/F,UAAI,kBAAkB,MAAM;AAE1B,cAAM,SAAS;AACf,cAAM,iBAAiB,QAAQ,SAAS;AACxC,eAAO;AAAA,MACT;AAGA,YAAM,iBAAiB,cAAc;AACrC,YAAM,OAAO,cAAc;AAC3B,YAAM,UAAU,cAAc;AAC9B,YAAM,UAAU,cAAc;AAC9B,YAAM,UAAU,cAAc;AAE9B,cAAQ,qBAAqB,KAAK;AAClC,YAAM,SAAS;AAAA,IACjB,SAAS,OAAO;AACd,cAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAM,SAAS;AAAA,IACjB,UAAE;AACA,cAAQ,YAAY,MAAM,SAAS;AAAA,QACjC,QAAQ,MAAM;AAAA,QACd,gBAAgB,MAAM;AAAA,QACtB,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,wBAAwB,yBAAyB,YAAY;AACjE,QAAI,UAAU;AACd,WAAO,SAAS;AACd,YAAM,QAAQ,QAAQ;AAEtB,YAAM,QAAQ,eAAe,EAAE,QAAQ,WAAW,OAAO,IAAI,CAAC;AAC9D,YAAM,SAAS,MAAM;AACrB,gBAAU,MAAM;AAEhB,UAAI,OAAO,WAAW,GAAG;AACvB;AAAA,MACF;AAEA,iBAAW,SAAS,QAAQ;AAC1B,oBAAY,MAAM;AAChB,gCAAsB,KAAK;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,4BAAsB;AAAA,IACxB;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAEA,kBAAkB,YAAY;AAAA,IAC9B,qBAAqB,YAAY;AAAA,EACnC;AACF;;;ACvPO,IAAM,yBAAyB,CAAC,EAAE,SAAS,gBAAgB,MAAwB;AACxF,UAAQ,iBAAiB,kBAAkB,CAAC,UAAU;AACpD,oBAAgB,EAAE,WAAW,MAAM,QAAQ,OAAO,CAAC;AAAA,EACrD,CAAC;AACH;;;ACXA,OAAO,qBAAqB;AA+DrB,IAAM,6BAA6B,CAAC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAkC;AAChC,QAAM,cAAc,uBAEjB;AAEH,MAAI,cAAiC,EAAE,MAAM,WAAW,QAAQ,kBAAkB;AAElF,QAAM,iBAAiB,CAAC,UAA6B;AACnD,kBAAc;AACd,gBAAY,cAAc,iBAAiB,MAAM,IAAI;AAAA,EACvD;AAEA,QAAM,aAAa;AAAA,IACjB,YAAY;AACV,UAAI,YAAY,SAAS,WAAW;AAClC,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AAEA,UAAI,CAAC,eAAe;AAClB,gBAAQ,KAAK,oDAAoD;AACjE,uBAAe,EAAE,MAAM,WAAW,QAAQ,kBAAkB,CAAC;AAC7D;AAAA,MACF;AAEA,qBAAe,EAAE,MAAM,UAAU,CAAC;AAElC,YAAM,gBAAgB,MAAM,cAAc,YAAY;AACpD,eAAO,MAAM,gBAAgB;AAAA,UAC3B,mBAAmB,CAAC,cAAc;AAChC,uBAAW,EAAE,cAAc,WAAW,aAAa,MAAM,CAAC;AAAA,UAC5D;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,cAAc,SAAS;AAC1B,uBAAe,EAAE,MAAM,WAAW,QAAQ,wBAAwB,CAAC;AACnE,gBAAQ,KAAK,kCAAkC,cAAc,KAAK;AAClE;AAAA,MACF;AAEA,qBAAe;AAAA,QACb,MAAM;AAAA,QACN,QAAQ,cAAc;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,IACA,EAAE,kBAAkB,MAAM;AAAA,EAC5B;AAEA,QAAM,iBAAiB;AAAA,IACrB,YAAY;AACV,UAAI,YAAY,SAAS,UAAU;AACjC;AAAA,MACF;AAEA,YAAM,WAAW;AACjB,YAAM,mBAAmB;AAAA,IAC3B;AAAA,IACA,EAAE,kBAAkB,MAAM;AAAA,EAC5B;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO,WAA0B;AAC/B,UAAI,YAAY,SAAS,UAAU;AACjC;AAAA,MACF;AACA,YAAM,SAAS,YAAY;AAE3B,qBAAe,EAAE,MAAM,UAAU,CAAC;AAElC,YAAM,mBAAmB,MAAM,cAAc,YAAY;AACvD,eAAO,MAAM,OAAO,aAAa;AAAA,MACnC,CAAC;AAED,UAAI,CAAC,iBAAiB,SAAS;AAC7B,gBAAQ,KAAK,gDAAgD,iBAAiB,KAAK;AAAA,MACrF;AAEA,qBAAe,EAAE,MAAM,WAAW,OAAO,CAAC;AAAA,IAC5C;AAAA,IACA,EAAE,kBAAkB,MAAM;AAAA,EAC5B;AAEA,QAAM,WAAW,YAAY;AAC3B,QAAI,YAAY,SAAS,UAAU;AACjC,YAAM,WAAW;AAAA,IACnB;AAEA,QAAI,YAAY,SAAS,UAAU;AACjC,YAAM,eAAe;AAAA,IACvB;AAAA,EACF;AAEA,MAAI,sBAAqC;AACzC,MAAI,cAAoC;AACxC,QAAM,aAAa,CAAC,YAA+D;AACjF,QAAI,YAAY,SAAS,UAAU;AACjC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,UAAM,eAAe,SAAS;AAE9B,QAAI,iBAAiB,UAAa,gBAAgB,WAAW,SAAS;AACpE,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,QAAI,aAAa;AACf,UAAI,iBAAiB,WAAc,CAAC,uBAAuB,sBAAsB,eAAe;AAC9F,8BAAsB;AAAA,MACxB;AACA,aAAO;AAAA,IACT;AAEA,kBAAc,cAAc;AAAA,MAC1B,aAAa,WAAW;AAAA,MACxB,eAAe,SAAS,cAAc,SAAY;AAAA,IACpD,CAAC,EACE,MAAM,CAAC,UAAU;AAChB,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,gBAAU,mBAAmB;AAAA,IAC/B,CAAC,EACA,QAAQ,MAAM;AACb,oBAAc;AAEd,YAAM,aAAa;AACnB,4BAAsB;AAEtB,UAAI,cAAc,aAAa,WAAW,SAAS;AACjD,mBAAW,EAAE,cAAc,WAAW,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AACH,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,OAAO,SAA4B;AACvD,QAAI,UAAU;AACd,QAAI,cAAc,KAAK;AACvB,WAAO,SAAS;AACd,UAAI,YAAY,SAAS,UAAU;AACjC;AAAA,MACF;AACA,YAAM,SAAS,YAAY;AAE3B,YAAM,WAAW,MAAM;AAAA,QACrB,MACE,OAAO,WAAW;AAAA,UAChB,GAAG;AAAA,UACH;AAAA,QACF,CAAC;AAAA,QACH;AAAA,UACE,KAAK;AAAA,UACL,aAAa;AAAA,UACb,iBAAiB;AAAA,UACjB,eAAe;AAAA,UACf,SAAS;AAAA,QACX;AAAA,MACF;AACA,gBAAU,SAAS;AACnB,oBAAc,SAAS;AAEvB,UAAI,SAAS,QAAQ;AACnB,gBAAQ;AAAA,UACN,SAAS,OAAO,IAAI,CAAC,MAAM;AACzB,gBAAI,EAAE,iBAAiB,SAAS,sBAAsB;AACpD,oBAAM,IAAI;AAAA,gBACR,wBAAwB,EAAE,cAAc,2CAA2C,SAAS,oBAAoB;AAAA,cAClH;AAAA,YACF;AACA,mBAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AACA,UAAI,SAAS,cAAc,WAAW,SAAS;AAC7C;AAAA,MACF;AACA,UAAI,SAAS,aAAa,WAAW,SAAS;AAC5C,mBAAW,UAAU,SAAS;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,qBAAqB,yBAAyB,YAAY;AAC9D,WAAO,MAAM;AACX,YAAM,cAAc,QAAQ,eAAe;AAAA,QACzC,QAAQ;AAAA,QACR,aAAa,WAAW;AAAA,QACxB,eAAe;AAAA,QACf,OAAO;AAAA,MACT,CAAC;AACD,UAAI,YAAY,OAAO,WAAW,GAAG;AACnC;AAAA,MACF;AAEA,UAAI,YAAY,SAAS,UAAU;AACjC;AAAA,MACF;AACA,YAAM,SAAS,YAAY;AAE3B,YAAM,iBAAiB,SAAS,cAAc,YAAY,MAAM;AAEhE,UAAI,eAAe,SAAS,GAAG;AAC7B,YAAI;AACF,gBAAM;AAAA,YACJ,MACE,OAAO,WAAW;AAAA,cAChB;AAAA,cACA,QAAQ;AAAA,YACV,CAAC;AAAA,YACH;AAAA,cACE,KAAK;AAAA,cACL,aAAa;AAAA,cACb,iBAAiB;AAAA,cACjB,eAAe;AAAA,cACf,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,MAAM,wCAAwC,KAAK;AAC3D,oBAAU,mBAAmB;AAC7B;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,UAAU,YAAY;AACjC,UAAI,CAAC,YAAY,SAAS;AACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,MAAM;AAC5B,uBAAmB;AAAA,EACrB;AACA,UAAQ,iBAAiB,kBAAkB,eAAe;AAE1D,QAAM,WAAW,MAAwC,YAAY;AAErE,QAAM,UAAU,YAAY;AAC1B,UAAM,UAAU,cAAc;AAC9B,YAAQ,oBAAoB,kBAAkB,eAAe;AAAA,EAC/D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,YAAY;AAAA,IAC9B,qBAAqB,YAAY;AAAA,EACnC;AACF;;;AC7TO,SAAS,8BACd,OACA,MACA;AACA,MAAI,KAAK,aAAa;AACpB,YAAQ,MAAM,MAAM,WAAW,KAAK,KAAK,WAAW;AAAA,EACtD;AACA,MAAI,KAAK,QAAQ;AACf,YAAQ,MAAM,MAAM,UAAU,KAAK,KAAK,MAAM;AAAA,EAChD;AACA,MAAI,KAAK,eAAe;AACtB,YAAQ,MAAM,MAAM,UAAU,MAAM,KAAK,aAAa;AAAA,EACxD;AACA,MAAI,KAAK,eAAe;AACtB,YAAQ,MAAM,MAAM,kBAAkB,MAAM,KAAK,aAAa;AAAA,EAChE;AAEA,SAAO,MAAM,MAAM,KAAK,SAAS,EAAE,EAAE,QAAQ,WAAW,KAAK;AAC/D;;;ACjBO,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAsE7B,IAAM,wBAAwB;AAAA,EACnC,UAAU;AAAA,EACV,WAAW;AACb;AAOO,IAAM,0BAA0B,CAAC,WAA4C;AAClF,SAAO;AAAA,IACL,UAAU,IAAI,sBAAsB,GAAG,MAAM,IAAI,sBAAsB,QAAQ,EAAE;AAAA,IACjF,WAAW,IAAI,sBAAsB,GAAG,MAAM,IAAI,sBAAsB,SAAS,EAAE;AAAA,EACrF;AACF;AAcO,SAAS,oBAAoB,SAAgD;AAClF,SAAO,OAAO,YAAY,YAAY,YAAY,QAAQ,UAAU,WAAW,QAAQ,SAAS;AAClG;AAEO,SAAS,uBAAuB,SAAmD;AACxF,SAAO,OAAO,YAAY,YAAY,YAAY,QAAQ,UAAU,WAAW,QAAQ,SAAS;AAClG;AAEO,SAAS,wBAAwB,SAAoD;AAC1F,SACE,OAAO,YAAY,YAAY,YAAY,QAAQ,UAAU,WAAW,eAAe,WAAW,UAAU;AAEhH;AAEO,SAAS,6BAA6B,SAAyD;AACpG,SAAO,OAAO,YAAY,YAAY,YAAY,QAAQ,UAAU,WAAW,QAAQ,SAAS;AAClG;AAEO,SAAS,4BAA4B,SAAwD;AAClG,SAAO,OAAO,YAAY,YAAY,YAAY,QAAQ,sBAAsB,WAAW,CAAC,CAAC,QAAQ;AACvG;","names":["db","sql","sql","perf","sql","db","sql","db"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["export type DeferredPromise<T> = {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n};\n\nexport function createDeferredPromise<T>(opts?: { timeout?: number; onTimeout?: () => void }): DeferredPromise<T> {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const promise = new Promise<T>((_resolve, _reject) => {\n resolve = (value) => {\n if (timeoutId) clearTimeout(timeoutId);\n _resolve(value);\n };\n reject = (reason) => {\n if (timeoutId) clearTimeout(timeoutId);\n _reject(reason);\n };\n\n if (opts?.timeout) {\n timeoutId = setTimeout(() => {\n _reject(new Error(`Promise timed out after ${opts.timeout}ms`));\n tryCatch(() => opts?.onTimeout?.());\n }, opts.timeout);\n }\n });\n\n return { promise, resolve, reject };\n}\n\nexport const generateId = () => {\n return crypto.randomUUID();\n};\n\nexport type DistributiveOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never;\n\nexport function ensureSingletonExecution<T, TArgs extends any[]>(\n fn: (...args: TArgs) => Promise<T>,\n opts: { queueReExecution?: boolean } = { queueReExecution: true },\n) {\n let executingPromise: Promise<T> | null = null;\n let shouldReExecute = false;\n\n const wrappedFn = (...args: TArgs) => {\n if (executingPromise) {\n shouldReExecute = true;\n return executingPromise;\n }\n\n executingPromise = fn(...args).finally(() => {\n executingPromise = null;\n\n if (shouldReExecute && opts?.queueReExecution) {\n shouldReExecute = false;\n wrappedFn(...args);\n }\n });\n return executingPromise;\n };\n\n wrappedFn.promise = () => executingPromise;\n wrappedFn.isExecuting = () => !!executingPromise;\n\n return wrappedFn;\n}\n\nexport function createAutoFlushBuffer<T>({ size, flush }: { size: number; flush: (items: T[]) => void }) {\n const buffer: T[] = [];\n\n return {\n add(item: T) {\n buffer.push(item);\n if (buffer.length >= size) {\n flush(buffer);\n buffer.length = 0;\n }\n },\n flush() {\n flush(buffer);\n buffer.length = 0;\n },\n };\n}\n\nexport function createAsyncAutoFlushBuffer<T>({\n size,\n flush,\n}: {\n size: number;\n flush: (items: T[]) => void | Promise<void>;\n}) {\n const buffer: T[] = [];\n\n return {\n async add(item: T) {\n buffer.push(item);\n if (buffer.length >= size) {\n await this.flush();\n }\n },\n async flush() {\n const itemsToFlush = buffer.splice(0);\n if (itemsToFlush.length === 0) {\n return;\n }\n await flush(itemsToFlush);\n },\n };\n}\n\nexport class TypedBroadcastChannel<TMessage> {\n private readonly channel: BroadcastChannel;\n\n constructor(name: string) {\n this.channel = new BroadcastChannel(name);\n }\n\n postMessage(message: TMessage) {\n this.channel.postMessage(message);\n }\n\n set onmessage(callback: ((event: MessageEvent<TMessage>) => void) | null) {\n this.channel.onmessage = callback;\n }\n\n close() {\n this.channel.close();\n }\n}\n\nexport class TypedEvent<T = unknown> extends Event {\n readonly payload: T;\n constructor(type: string, payload: T) {\n super(type);\n this.payload = payload;\n }\n}\n\nexport type TypedEventTarget<T extends Record<string, unknown>> = {\n addEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => void;\n removeEventListener: <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => void;\n dispatchEvent: <K extends keyof T & string>(type: K, payload: T[K]) => void;\n};\n\nexport const createTypedEventTarget = <T extends Record<string, unknown>>(): TypedEventTarget<T> => {\n const eventTarget = new EventTarget();\n\n const addEventListener = <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => {\n eventTarget.addEventListener(type, listener as (e: Event) => void);\n };\n\n const removeEventListener = <K extends keyof T & string>(type: K, listener: (event: TypedEvent<T[K]>) => void) => {\n eventTarget.removeEventListener(type, listener as (e: Event) => void);\n };\n\n const dispatchEvent = <K extends keyof T & string>(type: K, payload: T[K]) => {\n eventTarget.dispatchEvent(new TypedEvent(type, payload));\n };\n\n return {\n addEventListener,\n removeEventListener,\n dispatchEvent,\n };\n};\n\ntype TryCatchResult<T> =\n | {\n success: true;\n data: T;\n }\n | {\n success: false;\n error: unknown;\n };\n\nexport function tryCatch<T>(fn: () => T): TryCatchResult<T> {\n try {\n return {\n success: true,\n data: fn(),\n };\n } catch (error) {\n return {\n success: false,\n error,\n };\n }\n}\n\nexport async function tryCatchAsync<T>(fn: () => Promise<T>): Promise<TryCatchResult<T>> {\n try {\n return {\n success: true,\n data: await fn(),\n };\n } catch (error) {\n return {\n success: false,\n error,\n };\n }\n}\n\nexport function jsonSafeParse<T>(json: string) {\n return tryCatch(() => JSON.parse(json) as T);\n}\n\n/** Quote a SQLite identifier (table/column name), handling dot-separated schema qualifiers. */\nexport function quoteId(name: string): string {\n return name\n .split(\".\")\n .map((s) => `\"${s.replace(/\"/g, '\"\"')}\"`)\n .join(\".\");\n}\n"],"mappings":"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","names":[]}
|