@supalive/core 1.10.0 → 1.12.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.
Files changed (69) hide show
  1. package/dist/db-ClCicssQ.js.map +1 -1
  2. package/dist/index-C_Zew1wH.d.ts +2209 -0
  3. package/dist/index-C_Zew1wH.d.ts.map +1 -0
  4. package/dist/index-DDDAcnJj.d.ts +2208 -0
  5. package/dist/index-DDDAcnJj.d.ts.map +1 -0
  6. package/dist/mysql-BXy4mk-9.d.ts +113 -0
  7. package/dist/mysql-BXy4mk-9.d.ts.map +1 -0
  8. package/dist/mysql-D-PGYc1L.js +609 -0
  9. package/dist/mysql-D-PGYc1L.js.map +1 -0
  10. package/dist/mysql-DF8eJO-v.d.ts +113 -0
  11. package/dist/mysql-DF8eJO-v.d.ts.map +1 -0
  12. package/dist/mysql-XUkTkefP.js +610 -0
  13. package/dist/mysql-XUkTkefP.js.map +1 -0
  14. package/dist/mysql-txOOzccX.js +609 -0
  15. package/dist/mysql-txOOzccX.js.map +1 -0
  16. package/dist/overlap-checker-BdNoCPtA.js +259 -0
  17. package/dist/overlap-checker-BdNoCPtA.js.map +1 -0
  18. package/dist/overlap-checker-BoWNco2y.js +258 -0
  19. package/dist/overlap-checker-BoWNco2y.js.map +1 -0
  20. package/dist/overlap-checker-DvRqQOTe.js +265 -0
  21. package/dist/overlap-checker-DvRqQOTe.js.map +1 -0
  22. package/dist/postgres-C7CHroi9.js +865 -0
  23. package/dist/postgres-C7CHroi9.js.map +1 -0
  24. package/dist/postgres-CapFFTTn.d.ts +117 -0
  25. package/dist/postgres-CapFFTTn.d.ts.map +1 -0
  26. package/dist/postgres-Cn9vTBX7.js +864 -0
  27. package/dist/postgres-Cn9vTBX7.js.map +1 -0
  28. package/dist/postgres-EXjuHMUi.d.ts +117 -0
  29. package/dist/postgres-EXjuHMUi.d.ts.map +1 -0
  30. package/dist/postgres-tLkdxhFu.js +864 -0
  31. package/dist/postgres-tLkdxhFu.js.map +1 -0
  32. package/dist/query-Bpw8wO6L.js +730 -0
  33. package/dist/query-Bpw8wO6L.js.map +1 -0
  34. package/dist/realtime_db-e3TztUUT.js +272 -0
  35. package/dist/realtime_db-e3TztUUT.js.map +1 -0
  36. package/dist/schema-CWdfWuIj.js +105 -0
  37. package/dist/schema-CWdfWuIj.js.map +1 -0
  38. package/dist/src/client/index.d.ts +1 -1
  39. package/dist/src/client/index.js +4 -4
  40. package/dist/src/exports/mysql.d.ts +1 -1
  41. package/dist/src/exports/mysql.js +1 -1
  42. package/dist/src/exports/postgres.d.ts +1 -1
  43. package/dist/src/exports/postgres.js +1 -1
  44. package/dist/src/exports/procedure.d.ts +1 -1
  45. package/dist/src/exports/procedure.js +3 -2
  46. package/dist/src/exports/procedure.js.map +1 -1
  47. package/dist/src/exports/schema-sql.d.ts +1 -1
  48. package/dist/src/exports/schema-sql.js +2 -2
  49. package/dist/src/exports/server.d.ts +4 -4
  50. package/dist/src/exports/server.js +11 -4
  51. package/dist/src/exports/server.js.map +1 -1
  52. package/dist/src/exports/sub-manager-worker-entry.js +1 -1
  53. package/dist/src/exports/types.d.ts +2 -2
  54. package/dist/src/exports/types.js +1 -1
  55. package/dist/sub-worker-dispatch-Cl-XnBwq.js +810 -0
  56. package/dist/sub-worker-dispatch-Cl-XnBwq.js.map +1 -0
  57. package/dist/sub-worker-dispatch-Cokz99D1.js +810 -0
  58. package/dist/sub-worker-dispatch-Cokz99D1.js.map +1 -0
  59. package/dist/sub-worker-dispatch-DohrszOw.js +810 -0
  60. package/dist/sub-worker-dispatch-DohrszOw.js.map +1 -0
  61. package/dist/table-id-x9y1eHUr.js +91 -0
  62. package/dist/table-id-x9y1eHUr.js.map +1 -0
  63. package/dist/types_db-CmxFWgU3.js +171 -0
  64. package/dist/types_db-CmxFWgU3.js.map +1 -0
  65. package/dist/types_server-BF5Y0s__.d.ts +521 -0
  66. package/dist/types_server-BF5Y0s__.d.ts.map +1 -0
  67. package/dist/types_server-SPElhjga.d.ts +521 -0
  68. package/dist/types_server-SPElhjga.d.ts.map +1 -0
  69. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"db-ClCicssQ.js","names":[],"sources":["../src/db/db.ts"],"sourcesContent":["import { CacheLayer } from \"./cache\";\nimport type { CommitLogEntry, PointRead, RawPointRead, RawReadEntry } from \"./types_db\";\nimport { ReadEntry, WriteEntry } from \"./types_db\";\n\nexport interface DbQueryResult<T = any> {\n rows: T[];\n rowCount?: number | null;\n}\n\nexport interface RawClient {\n query<T = any>(sql: string, params?: unknown[]): Promise<DbQueryResult<T>>;\n}\n\nexport interface PooledClient extends RawClient {\n release(): void;\n}\n\nexport type DbType = \"postgres\" | \"mysql\";\n\n/** Fixed key for the PG advisory lock that serializes core init across processes. */\nexport const CORE_INIT_LOCK_KEY = 895124309;\n/** Name for the MySQL `GET_LOCK` that serializes core init across processes. */\nexport const CORE_INIT_LOCK_NAME = \"supalive_core_init\";\n\nexport interface PendingPointEntry {\n entry: PointRead;\n /* Table name and point read id = key = `${tableName} ${entry.id}` */\n key: string;\n}\n\nexport interface PreparedQuery {\n sql: string;\n params: unknown[] | unknown[][];\n operation: \"insertSingle\" | \"insertBatch\" | \"updateSingle\" | \"updateBatch\" | \"deleteSingle\" | \"deleteBatch\" | \"pointReadValidation\" | \"commit_logs\";\n table: string;\n entryId?: unknown;\n expectedTs?: bigint,\n entries?: WriteEntry[],\n pendingsEntry?: PendingPointEntry[];\n};\n\nexport interface PreparedQueries {\n commits: PreparedQuery[];\n validateReadPoints?: PreparedQuery[];\n hasRangeRead: boolean;\n tableIds?: Uint8Array[];\n rawReadSet?: RawReadEntry[],\n}\n\n/**\n * Bound to a single dedicated connection that holds the core-init lock. Passed\n * to the callback of {@link Database.withCoreInitLock} so version reads/writes\n * and migration statements all run under the same lock.\n */\nexport interface CoreInitLockCtx {\n exec(sql: string, params?: unknown[]): Promise<DbQueryResult>;\n getVersion(): Promise<bigint>;\n setVersion(version: bigint): Promise<void>;\n}\n\nexport interface Database {\n readonly dbType: DbType;\n readonly sqlBuilder: SqlBuilder;\n columnTypes: Map<string, Map<string, string>>;\n /**\n * Current core schema version stored in `metadata.core_version`, or `0n`\n * when unset. Read on a pooled connection for the lock-free fast path of\n * {@link initCore}.\n */\n getCoreVersion(): Promise<bigint>;\n /**\n * Runtime bootstrap statements to apply when migrating core TO `toVersion`\n * (i.e. the `toVersion - 1` → `toVersion` step): data seeds, backfills, or a\n * schema change that must be applied directly at runtime. Dialect-specific;\n * the core schema (tables, indexes, the `global_commit_ts` sequence/counter)\n * lives in the generated schema instead — see `coreTablesSql`.\n */\n coreMigrationStatements(toVersion: bigint): string[];\n /**\n * Run `fn` while holding the cross-process core-init lock (PG\n * `pg_advisory_xact_lock`, MySQL `GET_LOCK`) on a single dedicated\n * connection, so concurrent servers can't race the core migration. All of\n * `fn`'s work runs on that locked connection via {@link CoreInitLockCtx}.\n */\n withCoreInitLock(fn: (ctx: CoreInitLockCtx) => Promise<void>): Promise<void>;\n bootstrapColumnTypes(opts: { redis?: CacheLayer; cacheKey: string; tables?: string[]; }): Promise<void>;\n query<T = any>(sql: string, params?: unknown[]): Promise<DbQueryResult<T>>;\n getClient(): Promise<PooledClient>;\n getTransactionClient(): Promise<TxDatabase>;\n getLatestSnapshotTimestamp(): Promise<bigint>;\n updateLatestSnapshotTimestamp(commitTs: bigint): Promise<void>;\n /**\n * The retention watermark: the boundary `ts` below which commit_logs have\n * been pruned, so any cache entry whose `lastSnapshotTs` is below it can no\n * longer be freshness-checked (its scan window would miss deleted rows) and\n * must be recomputed. Persisted in the `metadata` table (survives restarts)\n * as a cheap PK read — callers load it into an in-memory variable at startup\n * and keep it fresh via pub/sub rather than reading it per query. Returns the\n * -1n genesis when nothing has been pruned yet (matching the empty-DB snapshot\n * ts), so every entry is scannable.\n */\n getMinSnapshotTimestamp(): Promise<bigint>;\n /**\n * Advance the retention watermark. Monotonic: only ever moves forward (a\n * stale writer can never lower it). Called by the sub-manager right before it\n * prunes commit_logs below `ts`.\n */\n updateMinSnapshotTimestamp(ts: bigint): Promise<void>;\n getNextTimestamp(): Promise<bigint>;\n prepareCommitWrites(readSet: ReadEntry[], writeSet: WriteEntry[], commitTs: LazyCommitTsParam): Promise<PreparedQueries>;\n commitWrites(beginTs: bigint, queries: PreparedQueries, commitTs: bigint): Promise<{ success: boolean }>;\n close(): Promise<void>;\n /**\n * Delete commit_logs older than `ts` (exclusive). Used by the periodic\n * retention sweep in SubscriptionManager so the table doesn't grow\n * unbounded.\n */\n pruneCommitLogsBefore(ts: bigint): Promise<bigint>;\n /**\n * Oldest `ts` still present in commit_logs (i.e. the retention watermark\n * after the last prune), or `null` when the table is empty. A cache entry\n * whose `lastSnapshotTs` is below it can no longer be freshness-checked via\n * {@link getCommitLogsBetweenTs} (the logs it would need were pruned), so the\n * one-shot/register cache paths recompute instead of trusting it.\n */\n getMinCommitLogTs(): Promise<bigint | null>;\n /**\n * Half-open range scan: ts >= beginTs AND ts < endTs. Used by the\n * subscription-recovery path to replay logs in a specific time window.\n */\n getCommitLogsBetweenTs(beginTs: bigint, endTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]>;\n /**\n * Conflict-check scan for OCC: ts >= sinceTs AND ts <> excludeTs. The\n * exclude is our own commitTs so we don't conflict with ourselves; the\n * lack of an upper bound is intentional, so a concurrent peer that\n * happens to have a higher commitTs but committed before us is still\n * visible. (MVCC keeps in-flight peers invisible until they commit.)\n */\n getCommitLogsSinceTs(sinceTs: bigint, excludeTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]>;\n /**\n * For each `update`/`delete` entry, attach `prevData` (consumed by the\n * invalidator) and `expectedCommitTs` (the CAS fence).\n *\n * `expectedCommitTs` is preferentially copied from a prior point-read of\n * the same row in `readSet` — that's the value the handler's logic\n * actually depended on, so the CAS check enforces beginTs-level isolation\n * for read-then-update patterns. If no prior read exists (\"blind\"\n * write), we fall back to the value observed in this batch fetch (weak\n * OCC, sufficient for writes that don't depend on prior state).\n *\n * `prevData` always comes from this batch fetch (SELECT * per table) so\n * the invalidator has the full row regardless of which columns the\n * handler's read selected.\n *\n * If the target row no longer exists at fetch time, `expectedCommitTs`\n * is left undefined and the per-row CAS will match nothing — surfaced\n * as OccConflictError.\n */\n attachPrevDataToWriteSet(writeSet: WriteEntry[], readSet: ReadEntry[]): Promise<void>;\n}\n\nexport interface TxDatabase extends Database {\n begin(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n}\n\nexport interface JsonOpOptions {\n /**\n * When true, the bound `value` parameter is treated as already prepared\n * for the underlying SQL (e.g. a literal JSON path string for\n * jsonHasKey, a JSON-encoded literal for the contains family). When\n * false/omitted, the value was prepared client-side from a JS value.\n */\n raw?: boolean;\n /**\n * 1-based positional index of an extra bound parameter holding a\n * jsonpath that scopes the contains-family check to a sub-document of\n * the target column. When omitted, the check runs against the whole\n * column value.\n */\n pathIndex?: number;\n /**\n * jsonHasKey only: when set, multiple path parameters are bound starting\n * at `paramIndex`, and the predicate evaluates whether any (`one`) or\n * every (`all`) path exists in the column.\n */\n mode?: \"one\" | \"all\";\n /** Number of bound path parameters in multi-path mode. */\n pathCount?: number;\n}\n\nexport interface SqlBuilder {\n placeholder(index: number): string;\n like(col: string, paramIndex: number): string;\n ilike(col: string, paramIndex: number): string;\n icontains(col: string, paramIndex: number): string;\n /** PG @> ; MySQL JSON_CONTAINS */\n jsonContains(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /** PG <@ ; MySQL JSON_CONTAINS(candidate, target) */\n jsonContainedBy(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /**\n * Key/path existence. With `opts.raw === true`, the bound param is a JSON\n * path expression (PG `jsonb_path_exists`, MySQL `JSON_CONTAINS_PATH`).\n * Otherwise the bound param is a literal top-level key (PG `?`, MySQL\n * `JSON_CONTAINS_PATH($.\"<key>\")` with server-side quoting).\n * With `opts.pathCount` set, emits the multi-path form keyed by `mode`.\n */\n jsonHasKey(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /** Array membership: target array contains the given element. */\n jsonArrayContains(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n}\n\nexport class LazyCommitTsParam {\n constructor(public value: unknown) { }\n\n // used by postgres\n toPostgres(prepareValue: (value: any) => any): any {\n return prepareValue(this.value);\n }\n\n // used by mysql\n toString() {\n return (this.value as any).toString();\n }\n\n validate() {\n const p = new LazyCommitTsParam(undefined);\n const hasNotObjConstructor = p.constructor !== Object;\n const hasNotToJSON = typeof (p as any).toJSON !== 'function';\n console.log('constructor must not object', hasNotObjConstructor);\n console.log('should not have toJSON', hasNotToJSON);\n }\n}"],"mappings":";;AAoBA,MAAa,qBAAqB;;AAElC,MAAa,sBAAsB;AAgMnC,IAAa,oBAAb,MAAa,kBAAkB;CACV;CAAnB,YAAY,OAAuB;EAAhB,KAAA,QAAA;CAAkB;CAGrC,WAAW,cAAwC;EACjD,OAAO,aAAa,KAAK,KAAK;CAChC;CAGA,WAAW;EACT,OAAQ,KAAK,MAAc,SAAS;CACtC;CAEA,WAAW;EACT,MAAM,IAAI,IAAI,kBAAkB,KAAA,CAAS;EACzC,MAAM,uBAAuB,EAAE,gBAAgB;EAC/C,MAAM,eAAe,OAAQ,EAAU,WAAW;EAClD,QAAQ,IAAI,+BAA+B,oBAAoB;EAC/D,QAAQ,IAAI,0BAA0B,YAAY;CACpD;AACF"}
1
+ {"version":3,"file":"db-ClCicssQ.js","names":[],"sources":["../src/db/db.ts"],"sourcesContent":["import { CacheLayer } from \"./cache\";\nimport type { CommitLogEntry, PointRead, RawPointRead, RawReadEntry } from \"./types_db\";\nimport { ReadEntry, WriteEntry } from \"./types_db\";\n\nexport interface DbQueryResult<T = any> {\n rows: T[];\n rowCount?: number | null;\n}\n\nexport interface RawClient {\n query<T = any>(sql: string, params?: unknown[]): Promise<DbQueryResult<T>>;\n}\n\nexport interface PooledClient extends RawClient {\n release(): void;\n}\n\nexport type DbType = \"postgres\" | \"mysql\";\n\n/** Fixed key for the PG advisory lock that serializes core init across processes. */\nexport const CORE_INIT_LOCK_KEY = 895124309;\n/** Name for the MySQL `GET_LOCK` that serializes core init across processes. */\nexport const CORE_INIT_LOCK_NAME = \"supalive_core_init\";\n\nexport interface PendingPointEntry {\n entry: PointRead;\n /* Table name and point read id = key = `${tableName} ${entry.id}` */\n key: string;\n}\n\nexport interface PreparedQuery {\n sql: string;\n params: unknown[] | unknown[][];\n operation: \"insertSingle\" | \"insertBatch\" | \"updateSingle\" | \"updateBatch\" | \"deleteSingle\" | \"deleteBatch\" | \"pointReadValidation\" | \"commit_logs\";\n table: string;\n entryId?: unknown;\n expectedTs?: bigint,\n entries?: WriteEntry[],\n pendingsEntry?: PendingPointEntry[];\n};\n\nexport interface PreparedQueries {\n commits: PreparedQuery[];\n validateReadPoints?: PreparedQuery[];\n hasRangeRead: boolean;\n tableIds?: Uint8Array[];\n rawReadSet?: RawReadEntry[],\n}\n\n/**\n * Bound to a single dedicated connection that holds the core-init lock. Passed\n * to the callback of {@link Database.withCoreInitLock} so version reads/writes\n * and migration statements all run under the same lock.\n */\nexport interface CoreInitLockCtx {\n exec(sql: string, params?: unknown[]): Promise<DbQueryResult>;\n getVersion(): Promise<bigint>;\n setVersion(version: bigint): Promise<void>;\n}\n\nexport interface Database {\n readonly dbType: DbType;\n readonly sqlBuilder: SqlBuilder;\n columnTypes: Map<string, Map<string, string>>;\n /**\n * Current core schema version stored in `metadata.core_version`, or `0n`\n * when unset. Read on a pooled connection for the lock-free fast path of\n * {@link initCore}.\n */\n getCoreVersion(): Promise<bigint>;\n /**\n * Runtime bootstrap statements to apply when migrating core TO `toVersion`\n * (i.e. the `toVersion - 1` → `toVersion` step): data seeds, backfills, or a\n * schema change that must be applied directly at runtime. Dialect-specific;\n * the core schema (tables, indexes, the `global_commit_ts` sequence/counter)\n * lives in the generated schema instead — see `coreTablesSql`.\n */\n coreMigrationStatements(toVersion: bigint): string[];\n /**\n * Run `fn` while holding the cross-process core-init lock (PG\n * `pg_advisory_xact_lock`, MySQL `GET_LOCK`) on a single dedicated\n * connection, so concurrent servers can't race the core migration. All of\n * `fn`'s work runs on that locked connection via {@link CoreInitLockCtx}.\n */\n withCoreInitLock(fn: (ctx: CoreInitLockCtx) => Promise<void>): Promise<void>;\n bootstrapColumnTypes(opts: { redis?: CacheLayer; cacheKey: string; tables?: string[]; }): Promise<void>;\n query<T = any>(sql: string, params?: unknown[]): Promise<DbQueryResult<T>>;\n getClient(): Promise<PooledClient>;\n getTransactionClient(): Promise<TxDatabase>;\n getLatestSnapshotTimestamp(): Promise<bigint>;\n updateLatestSnapshotTimestamp(commitTs: bigint): Promise<void>;\n /**\n * The retention watermark: the boundary `ts` below which commit_logs have\n * been pruned, so any cache entry whose `lastSnapshotTs` is below it can no\n * longer be freshness-checked (its scan window would miss deleted rows) and\n * must be recomputed. Persisted in the `metadata` table (survives restarts)\n * as a cheap PK read — callers load it into an in-memory variable at startup\n * and keep it fresh via pub/sub rather than reading it per query. Returns the\n * -1n genesis when nothing has been pruned yet (matching the empty-DB snapshot\n * ts), so every entry is scannable.\n */\n getMinSnapshotTimestamp(): Promise<bigint>;\n /**\n * Advance the retention watermark. Monotonic: only ever moves forward (a\n * stale writer can never lower it). Called by the sub-manager right before it\n * prunes commit_logs below `ts`.\n */\n updateMinSnapshotTimestamp(ts: bigint): Promise<void>;\n getNextTimestamp(): Promise<bigint>;\n prepareCommitWrites(readSet: ReadEntry[], writeSet: WriteEntry[], commitTs: LazyCommitTsParam): Promise<PreparedQueries>;\n commitWrites(beginTs: bigint, queries: PreparedQueries, commitTs: bigint): Promise<{ success: boolean }>;\n close(): Promise<void>;\n /**\n * Delete commit_logs older than `ts` (exclusive). Used by the periodic\n * retention sweep in SubscriptionManager so the table doesn't grow\n * unbounded.\n */\n pruneCommitLogsBefore(ts: bigint): Promise<bigint>;\n /**\n * Oldest `ts` still present in commit_logs (i.e. the retention watermark\n * after the last prune), or `null` when the table is empty. A cache entry\n * whose `lastSnapshotTs` is below it can no longer be freshness-checked via\n * {@link getCommitLogsBetweenTs} (the logs it would need were pruned), so the\n * one-shot/register cache paths recompute instead of trusting it.\n */\n getMinCommitLogTs(): Promise<bigint | null>;\n /**\n * Half-open range scan: ts >= beginTs AND ts < endTs. Used by the\n * subscription-recovery path to replay logs in a specific time window.\n */\n getCommitLogsBetweenTs(beginTs: bigint, endTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]>;\n /**\n * Existence-only freshness probe for point reads: does any commit in the\n * half-open window `[beginTs, endTs)` touch one of the exact `(tableId, id)`\n * pairs in `points`? Returns as soon as one match is found.\n *\n * Point-read overlap is a pure key match (`checkPointReadOverlap`), so it can\n * be answered entirely in SQL with a `(table_id, id)` tuple `IN` against the\n * `commit_logs_by_table_and_id (table_id, id, ts)` index — no row `data`\n * blobs fetched, no JSON parsed. This is the precise-filtering path used by\n * {@link CacheFreshness} for tables whose read set is point-reads-only; tables\n * that also carry a range read still go through {@link getCommitLogsBetweenTs}\n * because their predicates must be evaluated in-app. `points` empty → `false`.\n */\n hasCommitForPoints(\n beginTs: bigint,\n endTs: bigint,\n points: { tableId: Uint8Array; id: Uint8Array }[],\n ): Promise<boolean>;\n /**\n * Conflict-check scan for OCC: ts >= sinceTs AND ts <> excludeTs. The\n * exclude is our own commitTs so we don't conflict with ourselves; the\n * lack of an upper bound is intentional, so a concurrent peer that\n * happens to have a higher commitTs but committed before us is still\n * visible. (MVCC keeps in-flight peers invisible until they commit.)\n */\n getCommitLogsSinceTs(sinceTs: bigint, excludeTs: bigint, tableIds: Uint8Array[]): Promise<CommitLogEntry[]>;\n /**\n * For each `update`/`delete` entry, attach `prevData` (consumed by the\n * invalidator) and `expectedCommitTs` (the CAS fence).\n *\n * `expectedCommitTs` is preferentially copied from a prior point-read of\n * the same row in `readSet` — that's the value the handler's logic\n * actually depended on, so the CAS check enforces beginTs-level isolation\n * for read-then-update patterns. If no prior read exists (\"blind\"\n * write), we fall back to the value observed in this batch fetch (weak\n * OCC, sufficient for writes that don't depend on prior state).\n *\n * `prevData` always comes from this batch fetch (SELECT * per table) so\n * the invalidator has the full row regardless of which columns the\n * handler's read selected.\n *\n * If the target row no longer exists at fetch time, `expectedCommitTs`\n * is left undefined and the per-row CAS will match nothing — surfaced\n * as OccConflictError.\n */\n attachPrevDataToWriteSet(writeSet: WriteEntry[], readSet: ReadEntry[]): Promise<void>;\n}\n\nexport interface TxDatabase extends Database {\n begin(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n}\n\nexport interface JsonOpOptions {\n /**\n * When true, the bound `value` parameter is treated as already prepared\n * for the underlying SQL (e.g. a literal JSON path string for\n * jsonHasKey, a JSON-encoded literal for the contains family). When\n * false/omitted, the value was prepared client-side from a JS value.\n */\n raw?: boolean;\n /**\n * 1-based positional index of an extra bound parameter holding a\n * jsonpath that scopes the contains-family check to a sub-document of\n * the target column. When omitted, the check runs against the whole\n * column value.\n */\n pathIndex?: number;\n /**\n * jsonHasKey only: when set, multiple path parameters are bound starting\n * at `paramIndex`, and the predicate evaluates whether any (`one`) or\n * every (`all`) path exists in the column.\n */\n mode?: \"one\" | \"all\";\n /** Number of bound path parameters in multi-path mode. */\n pathCount?: number;\n}\n\nexport interface SqlBuilder {\n placeholder(index: number): string;\n like(col: string, paramIndex: number): string;\n ilike(col: string, paramIndex: number): string;\n icontains(col: string, paramIndex: number): string;\n /** PG @> ; MySQL JSON_CONTAINS */\n jsonContains(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /** PG <@ ; MySQL JSON_CONTAINS(candidate, target) */\n jsonContainedBy(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /**\n * Key/path existence. With `opts.raw === true`, the bound param is a JSON\n * path expression (PG `jsonb_path_exists`, MySQL `JSON_CONTAINS_PATH`).\n * Otherwise the bound param is a literal top-level key (PG `?`, MySQL\n * `JSON_CONTAINS_PATH($.\"<key>\")` with server-side quoting).\n * With `opts.pathCount` set, emits the multi-path form keyed by `mode`.\n */\n jsonHasKey(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n /** Array membership: target array contains the given element. */\n jsonArrayContains(col: string, paramIndex: number, opts?: JsonOpOptions): string;\n}\n\nexport class LazyCommitTsParam {\n constructor(public value: unknown) { }\n\n // used by postgres\n toPostgres(prepareValue: (value: any) => any): any {\n return prepareValue(this.value);\n }\n\n // used by mysql\n toString() {\n return (this.value as any).toString();\n }\n\n validate() {\n const p = new LazyCommitTsParam(undefined);\n const hasNotObjConstructor = p.constructor !== Object;\n const hasNotToJSON = typeof (p as any).toJSON !== 'function';\n console.log('constructor must not object', hasNotObjConstructor);\n console.log('should not have toJSON', hasNotToJSON);\n }\n}"],"mappings":";;AAoBA,MAAa,qBAAqB;;AAElC,MAAa,sBAAsB;AAkNnC,IAAa,oBAAb,MAAa,kBAAkB;CACV;CAAnB,YAAY,OAAuB;EAAhB,KAAA,QAAA;CAAkB;CAGrC,WAAW,cAAwC;EACjD,OAAO,aAAa,KAAK,KAAK;CAChC;CAGA,WAAW;EACT,OAAQ,KAAK,MAAc,SAAS;CACtC;CAEA,WAAW;EACT,MAAM,IAAI,IAAI,kBAAkB,KAAA,CAAS;EACzC,MAAM,uBAAuB,EAAE,gBAAgB;EAC/C,MAAM,eAAe,OAAQ,EAAU,WAAW;EAClD,QAAQ,IAAI,+BAA+B,oBAAoB;EAC/D,QAAQ,IAAI,0BAA0B,YAAY;CACpD;AACF"}