@g9tm/syncdata 1.5.1 → 1.5.3

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 (64) hide show
  1. package/LICENSE.md +21 -21
  2. package/PARITY.md +96 -96
  3. package/README.md +71 -71
  4. package/THIRD-PARTY-NOTICES.md +31 -31
  5. package/dist/abstractions/digest.js.map +1 -1
  6. package/dist/abstractions/enums.js.map +1 -1
  7. package/dist/abstractions/errors.js.map +1 -1
  8. package/dist/abstractions/guid.js.map +1 -1
  9. package/dist/abstractions/key.js.map +1 -1
  10. package/dist/abstractions/long.js.map +1 -1
  11. package/dist/abstractions/parameters.js.map +1 -1
  12. package/dist/brotli-js/decode.js.map +1 -1
  13. package/dist/brotli-js/index.js.map +1 -1
  14. package/dist/client/engine.d.ts +6 -0
  15. package/dist/client/engine.js +9 -0
  16. package/dist/client/engine.js.map +1 -1
  17. package/dist/client/model.js.map +1 -1
  18. package/dist/client/progress.js.map +1 -1
  19. package/dist/client/runs.js.map +1 -1
  20. package/dist/client/storeTypes.d.ts +2 -0
  21. package/dist/client/storeTypes.js.map +1 -1
  22. package/dist/client/transport.js.map +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal/abort.js.map +1 -1
  27. package/dist/internal/base64.js.map +1 -1
  28. package/dist/internal/dotnetFormat.js.map +1 -1
  29. package/dist/internal/md5.js.map +1 -1
  30. package/dist/internal/sha256.js.map +1 -1
  31. package/dist/internal/utf8.js.map +1 -1
  32. package/dist/node/index.js.map +1 -1
  33. package/dist/node/snapshotFileSink.js.map +1 -1
  34. package/dist/node/sqliteDriver.js.map +1 -1
  35. package/dist/protocol/dtos.js.map +1 -1
  36. package/dist/protocol/protocol.js.map +1 -1
  37. package/dist/protocol/rowBatch/columnLayout.js.map +1 -1
  38. package/dist/protocol/rowBatch/format.js.map +1 -1
  39. package/dist/protocol/rowBatch/reader.js.map +1 -1
  40. package/dist/protocol/rowBatch/writer.js.map +1 -1
  41. package/dist/protocol/wire.js.map +1 -1
  42. package/dist/signalr/index.js.map +1 -1
  43. package/dist/signalr/protocols.js.map +1 -1
  44. package/dist/signalr/transport.js.map +1 -1
  45. package/dist/sqlite/apply.js.map +1 -1
  46. package/dist/sqlite/commands.js.map +1 -1
  47. package/dist/sqlite/connection.js.map +1 -1
  48. package/dist/sqlite/driver.js.map +1 -1
  49. package/dist/sqlite/index.js.map +1 -1
  50. package/dist/sqlite/internals.js.map +1 -1
  51. package/dist/sqlite/options.js.map +1 -1
  52. package/dist/sqlite/push.js.map +1 -1
  53. package/dist/sqlite/query.js.map +1 -1
  54. package/dist/sqlite/revocation.d.ts +6 -0
  55. package/dist/sqlite/revocation.js +41 -0
  56. package/dist/sqlite/revocation.js.map +1 -1
  57. package/dist/sqlite/sql.js +113 -113
  58. package/dist/sqlite/sql.js.map +1 -1
  59. package/dist/sqlite/store.d.ts +1 -0
  60. package/dist/sqlite/store.js +3 -0
  61. package/dist/sqlite/store.js.map +1 -1
  62. package/dist/sqlite/values.js.map +1 -1
  63. package/dist/testing/index.js.map +1 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/sqlite/driver.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,oHAAoH;AACpH,qHAAqH;AACrH,sEAAsE;AAqEtE,mCAAmC;AACnC,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC,IAAI,OAAQ,KAA6B,CAAC,KAAK,KAAK,QAAQ,CAAC;AACpJ,CAAC","sourcesContent":["// The SQLite driver boundary, structurally identical to G9LynxControls' `G9SqliteDriver` (@g9lynx/sqlite,\n// driver/types.ts): the Lynx native driver (Android androidx.sqlite bundled, iOS), the Lynxtron driver and the Node\n// reference driver all satisfy it, and this package depends on none of them. One `run` = one bridge round trip for N\n// statements, each statement ONE SQL statement with `?` placeholders.\n\n/** An int64 outside ±(2^53 − 1), tagged so it is never mistaken for text. */\nexport interface G9Int64Tag {\n readonly int64: string;\n}\n\n/** A value crossing the driver boundary: null, a number, text, a BLOB (ArrayBuffer) or an int64 tag. */\nexport type G9SqlValue = null | number | string | ArrayBuffer | G9Int64Tag;\n\nexport interface G9DriverStatement {\n readonly sql: string;\n readonly params: readonly G9SqlValue[];\n}\n\nexport interface G9SqlResult {\n readonly columns: readonly string[];\n readonly rows: readonly (readonly G9SqlValue[])[];\n readonly changes: number;\n readonly lastInsertRowId: G9SqlValue;\n}\n\nexport type G9SessionToken = string & { readonly __g9Session: true };\nexport type G9TxToken = string & { readonly __g9Tx: true };\n\nexport interface G9ConnectionPragmas {\n readonly journalMode?: 'wal' | 'delete' | 'truncate' | 'memory';\n readonly busyTimeoutMs?: number;\n readonly foreignKeys?: boolean;\n readonly tempStore?: 'memory' | 'file' | 'default';\n readonly cacheSize?: number;\n readonly mmapSize?: number;\n}\n\nexport interface G9OpenOptions {\n readonly path: string;\n readonly readOnly?: boolean;\n readonly create?: boolean;\n readonly durability?: 'full' | 'normal';\n readonly pragmas?: G9ConnectionPragmas;\n}\n\nexport interface G9RunOptions {\n readonly tx?: G9TxToken;\n readonly signal?: AbortSignal;\n readonly maxRows?: number;\n readonly atomic?: boolean;\n}\n\nexport interface G9DriverCapabilities {\n readonly sqliteVersion: string;\n readonly maxVariables: number;\n readonly json1: boolean;\n readonly returning: boolean;\n readonly upsert: boolean;\n readonly interrupt: boolean;\n}\n\nexport interface G9SqliteDriver {\n readonly name: string;\n capabilities(): Promise<G9DriverCapabilities>;\n open(options: G9OpenOptions): Promise<G9SessionToken>;\n run(session: G9SessionToken, statements: readonly G9DriverStatement[], options?: G9RunOptions): Promise<G9SqlResult[]>;\n begin(session: G9SessionToken, mode: 'deferred' | 'immediate'): Promise<G9TxToken>;\n commit(tx: G9TxToken): Promise<void>;\n rollback(tx: G9TxToken): Promise<void>;\n close(session: G9SessionToken): Promise<void>;\n}\n\n/** True for an `{ int64 }` tag. */\nexport function isInt64Tag(value: unknown): value is G9Int64Tag {\n return typeof value === 'object' && value !== null && !(value instanceof ArrayBuffer) && typeof (value as { int64?: unknown }).int64 === 'string';\n}\n"]}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/sqlite/driver.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,oHAAoH;AACpH,qHAAqH;AACrH,sEAAsE;AAqEtE,mCAAmC;AACnC,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC,IAAI,OAAQ,KAA6B,CAAC,KAAK,KAAK,QAAQ,CAAC;AACpJ,CAAC","sourcesContent":["// The SQLite driver boundary, structurally identical to G9LynxControls' `G9SqliteDriver` (@g9lynx/sqlite,\r\n// driver/types.ts): the Lynx native driver (Android androidx.sqlite bundled, iOS), the Lynxtron driver and the Node\r\n// reference driver all satisfy it, and this package depends on none of them. One `run` = one bridge round trip for N\r\n// statements, each statement ONE SQL statement with `?` placeholders.\r\n\r\n/** An int64 outside ±(2^53 − 1), tagged so it is never mistaken for text. */\r\nexport interface G9Int64Tag {\r\n readonly int64: string;\r\n}\r\n\r\n/** A value crossing the driver boundary: null, a number, text, a BLOB (ArrayBuffer) or an int64 tag. */\r\nexport type G9SqlValue = null | number | string | ArrayBuffer | G9Int64Tag;\r\n\r\nexport interface G9DriverStatement {\r\n readonly sql: string;\r\n readonly params: readonly G9SqlValue[];\r\n}\r\n\r\nexport interface G9SqlResult {\r\n readonly columns: readonly string[];\r\n readonly rows: readonly (readonly G9SqlValue[])[];\r\n readonly changes: number;\r\n readonly lastInsertRowId: G9SqlValue;\r\n}\r\n\r\nexport type G9SessionToken = string & { readonly __g9Session: true };\r\nexport type G9TxToken = string & { readonly __g9Tx: true };\r\n\r\nexport interface G9ConnectionPragmas {\r\n readonly journalMode?: 'wal' | 'delete' | 'truncate' | 'memory';\r\n readonly busyTimeoutMs?: number;\r\n readonly foreignKeys?: boolean;\r\n readonly tempStore?: 'memory' | 'file' | 'default';\r\n readonly cacheSize?: number;\r\n readonly mmapSize?: number;\r\n}\r\n\r\nexport interface G9OpenOptions {\r\n readonly path: string;\r\n readonly readOnly?: boolean;\r\n readonly create?: boolean;\r\n readonly durability?: 'full' | 'normal';\r\n readonly pragmas?: G9ConnectionPragmas;\r\n}\r\n\r\nexport interface G9RunOptions {\r\n readonly tx?: G9TxToken;\r\n readonly signal?: AbortSignal;\r\n readonly maxRows?: number;\r\n readonly atomic?: boolean;\r\n}\r\n\r\nexport interface G9DriverCapabilities {\r\n readonly sqliteVersion: string;\r\n readonly maxVariables: number;\r\n readonly json1: boolean;\r\n readonly returning: boolean;\r\n readonly upsert: boolean;\r\n readonly interrupt: boolean;\r\n}\r\n\r\nexport interface G9SqliteDriver {\r\n readonly name: string;\r\n capabilities(): Promise<G9DriverCapabilities>;\r\n open(options: G9OpenOptions): Promise<G9SessionToken>;\r\n run(session: G9SessionToken, statements: readonly G9DriverStatement[], options?: G9RunOptions): Promise<G9SqlResult[]>;\r\n begin(session: G9SessionToken, mode: 'deferred' | 'immediate'): Promise<G9TxToken>;\r\n commit(tx: G9TxToken): Promise<void>;\r\n rollback(tx: G9TxToken): Promise<void>;\r\n close(session: G9SessionToken): Promise<void>;\r\n}\r\n\r\n/** True for an `{ int64 }` tag. */\r\nexport function isInt64Tag(value: unknown): value is G9Int64Tag {\r\n return typeof value === 'object' && value !== null && !(value instanceof ArrayBuffer) && typeof (value as { int64?: unknown }).int64 === 'string';\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sqlite/index.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,OAAO,EAAE,iBAAiB,EAAwB,MAAM,YAAY,CAAC;AACrE,OAAO,EACL,qBAAqB,GAMtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,mBAAmB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC","sourcesContent":["// @g9tm/syncdata/sqlite — the SQLite client store (twin of G9SyncData.Client.Sqlite) over the G9SqliteDriver contract.\nexport { G9SqliteSyncStore, type G9PendingExport } from './store.js';\nexport {\n fileIncarnationMarker,\n type G9IncarnationMarker,\n type G9MarkerFileSystem,\n type G9SnapshotFileSink,\n type G9SqliteSyncStoreOptions,\n type G9ResolvedSqliteStoreOptions,\n} from './options.js';\nexport { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage, splitSql } from './sql.js';\nexport { G9SqliteStoreError } from './connection.js';\nexport { SNAPSHOT_FILE_APPLICATION_ID, SNAPSHOT_FILE_FORMAT_VERSION } from './snapshotFiles.js';\nexport { formatTicks, formatDateTimeOffset, parseDateTime, parseDateTimeOffset, ticksOf, ticksToUnixMs } from './values.js';\nexport type {\n G9ConnectionPragmas,\n G9DriverCapabilities,\n G9DriverStatement,\n G9Int64Tag,\n G9OpenOptions,\n G9RunOptions,\n G9SessionToken,\n G9SqlResult,\n G9SqlValue,\n G9SqliteDriver,\n G9TxToken,\n} from './driver.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sqlite/index.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,OAAO,EAAE,iBAAiB,EAAwB,MAAM,YAAY,CAAC;AACrE,OAAO,EACL,qBAAqB,GAMtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,mBAAmB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC","sourcesContent":["// @g9tm/syncdata/sqlite — the SQLite client store (twin of G9SyncData.Client.Sqlite) over the G9SqliteDriver contract.\r\nexport { G9SqliteSyncStore, type G9PendingExport } from './store.js';\r\nexport {\r\n fileIncarnationMarker,\r\n type G9IncarnationMarker,\r\n type G9MarkerFileSystem,\r\n type G9SnapshotFileSink,\r\n type G9SqliteSyncStoreOptions,\r\n type G9ResolvedSqliteStoreOptions,\r\n} from './options.js';\r\nexport { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage, splitSql } from './sql.js';\r\nexport { G9SqliteStoreError } from './connection.js';\r\nexport { SNAPSHOT_FILE_APPLICATION_ID, SNAPSHOT_FILE_FORMAT_VERSION } from './snapshotFiles.js';\r\nexport { formatTicks, formatDateTimeOffset, parseDateTime, parseDateTimeOffset, ticksOf, ticksToUnixMs } from './values.js';\r\nexport type {\r\n G9ConnectionPragmas,\r\n G9DriverCapabilities,\r\n G9DriverStatement,\r\n G9Int64Tag,\r\n G9OpenOptions,\r\n G9RunOptions,\r\n G9SessionToken,\r\n G9SqlResult,\r\n G9SqlValue,\r\n G9SqliteDriver,\r\n G9TxToken,\r\n} from './driver.js';\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"internals.js","sourceRoot":"","sources":["../../src/sqlite/internals.ts"],"names":[],"mappings":"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","sourcesContent":["// Shared state and helpers of the SQLite store's parts (the C# partial class G9CSqliteSyncStore is split the same way:\n// core, apply, push, query, commands, revocation, incarnation, recovery).\nimport { G9ESyncColumnType } from '../abstractions/enums.js';\nimport { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';\nimport { G9Long, parseJson, stringifyJson } from '../abstractions/long.js';\nimport { G9SyncParameters } from '../abstractions/parameters.js';\nimport { base64ToBytes, bytesToBase64 } from '../internal/base64.js';\nimport type { G9SyncClientModel, G9SyncClientTable } from '../client/model.js';\nimport type { G9SyncLogger, G9SyncLogLevel } from '../client/runs.js';\nimport { G9ESubscriptionState, type G9SyncSubscriptionRecord } from '../client/storeTypes.js';\nimport type { G9DtNegotiatedTable } from '../protocol/dtos.js';\nimport { readNegotiatedTable, readSubscriptionDefinition } from '../protocol/wire.js';\nimport { asNumber, asOptionalString, asString, type G9AsyncLock, type G9SqliteConnection } from './connection.js';\nimport { isInt64Tag, type G9SqlValue } from './driver.js';\nimport { quote } from './sql.js';\nimport type { G9ResolvedSqliteStoreOptions } from './options.js';\n\n/** A table of the model with its local metadata (`LocalTable`). */\nexport class LocalTable {\n readonly model: G9SyncClientTable;\n readonly tid: number;\n negotiated: G9DtNegotiatedTable | null;\n syncedColumns: string[];\n\n constructor(model: G9SyncClientTable, tid: number, negotiated: G9DtNegotiatedTable | null, syncedColumns: string[]) {\n this.model = model;\n this.tid = tid;\n this.negotiated = negotiated;\n this.syncedColumns = syncedColumns;\n }\n\n get quoted(): string {\n return quote(this.model.localName);\n }\n\n get keyQuoted(): string {\n return quote(this.model.keyColumn);\n }\n}\n\n/** What the store's parts share. */\nexport interface StoreInternals {\n readonly options: G9ResolvedSqliteStoreOptions;\n readonly writeLock: G9AsyncLock;\n /** The connection library writes go through (under the write lock). */\n writer(): G9SqliteConnection;\n /** A connection for reads that never wait on a running write. */\n reader(): G9SqliteConnection;\n ensureInitialized(): G9SyncClientModel;\n byLocal: Map<string, LocalTable>;\n byServerId: Map<number, LocalTable>;\n log(level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void;\n}\n\nexport function logTo(logger: G9SyncLogger | null, level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void {\n if (!logger) return;\n try {\n logger.log(level, eventId, message, error);\n } catch {\n // A logger must never break the store.\n }\n}\n\nexport function nowMs(): number {\n return Date.now();\n}\n\nexport async function meta(connection: G9SqliteConnection, key: string): Promise<string | null> {\n const value = await connection.scalar('SELECT value FROM g9_meta WHERE key = $k', { $k: key });\n return value === null ? null : asString(value);\n}\n\nexport async function setMeta(connection: G9SqliteConnection, key: string, value: string | null): Promise<void> {\n await connection.exec('INSERT INTO g9_meta (key, value) VALUES ($k, $v) ON CONFLICT(key) DO UPDATE SET value = excluded.value', { $k: key, $v: value });\n}\n\n/** `KeyValue`: the key in the table's storage form (integers for an integer key). */\nexport function keyValue(table: LocalTable, canonicalKey: string): G9SqlValue {\n if (table.model.keyType === G9ESyncColumnType.Int32 || table.model.keyType === G9ESyncColumnType.Int64) {\n return G9Long.parse(canonicalKey).toSqlValue();\n }\n return canonicalKey;\n}\n\nexport function getLocal(store: StoreInternals, localName: string): LocalTable {\n const table = store.byLocal.get(localName.toLowerCase());\n if (!table) throw new RangeError(`'${localName}' is not a synced table.`);\n return table;\n}\n\nexport function findByServerName(store: StoreInternals, serverName: string): LocalTable | null {\n const table = store.ensureInitialized().findByServerName(serverName);\n return table ? (store.byLocal.get(table.localName.toLowerCase()) ?? null) : null;\n}\n\nexport function byTid(store: StoreInternals, tid: number): LocalTable | null {\n for (const table of store.byLocal.values()) if (table.tid === tid) return table;\n return null;\n}\n\n/** Reads subscriptions, all or one key, oldest first. */\nexport async function readSubscriptions(connection: G9SqliteConnection, key: string | null): Promise<G9SyncSubscriptionRecord[]> {\n const rows = await connection.query(\n 'SELECT key, name, params, slot, ephemeral, ttl_seconds, cursor, definition_hash, auth_hash, state, error_code, created_utc, ' +\n 'last_success_utc, last_reconcile_utc, last_access_utc, move_out_policy FROM g9_subscriptions' +\n (key === null ? '' : ' WHERE key = $k') +\n ' ORDER BY created_utc',\n key === null ? undefined : { $k: key },\n );\n return rows.map((r) => {\n const parameters = JSON.parse(asString(r[2])) as { [name: string]: string } | null;\n return {\n key: asString(r[0]),\n name: asString(r[1]),\n parameters: G9SyncParameters.fromValues(parameters ?? {}),\n slot: asNumber(r[3]),\n ephemeral: asNumber(r[4]) !== 0,\n ttlMs: r[5] === null ? null : asNumber(r[5]) * 1000,\n cursor: asOptionalString(r[6]),\n definitionHash: asOptionalString(r[7]),\n authHash: asOptionalString(r[8]),\n state: asNumber(r[9]) as G9ESubscriptionState,\n lastErrorCode: asOptionalString(r[10]),\n createdUtcMs: asNumber(r[11]),\n lastSuccessUtcMs: r[12] === null ? null : asNumber(r[12]),\n lastReconcileUtcMs: r[13] === null ? null : asNumber(r[13]),\n lastAccessUtcMs: r[14] === null ? null : asNumber(r[14]),\n moveOutPolicy: r[15] === null ? null : (asNumber(r[15]) as G9SyncSubscriptionRecord['moveOutPolicy']),\n };\n });\n}\n\n/**\n * JSON of a persisted DTO in the form .NET's source-generated context writes (camelCase, nulls omitted), so a database\n * written by either side reads on the other.\n */\nexport function persistedJson(value: unknown): string {\n return stringifyJson(dropNulls(value));\n}\n\nfunction dropNulls(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(dropNulls);\n if (value === null || typeof value !== 'object' || value instanceof G9Long) return value;\n const out: { [key: string]: unknown } = {};\n for (const key of Object.keys(value as object)) {\n const item = (value as { [key: string]: unknown })[key];\n if (item === null || item === undefined) continue;\n out[key] = dropNulls(item);\n }\n return out;\n}\n\nexport function readPersistedNegotiated(json: string | null): G9DtNegotiatedTable | null {\n return json === null ? null : readNegotiatedTable(parseJson(json));\n}\n\nexport function readPersistedDefinitions(json: string | null) {\n if (json === null) return [];\n const parsed = parseJson(json);\n return Array.isArray(parsed) ? parsed.map(readSubscriptionDefinition) : [];\n}\n\n/** SQLite values as JSON (`SerializeValues`): text as strings, numbers as numbers, blobs as `{\"$b64\": \"…\"}`. */\nexport function serializeValues(values: { [column: string]: unknown }): string {\n const out: { [column: string]: unknown } = {};\n for (const column of Object.keys(values)) {\n const value = values[column];\n if (value === null || value === undefined) out[column] = null;\n else if (typeof value === 'number') out[column] = value;\n else if (isInt64Tag(value)) out[column] = G9Long.parse(value.int64);\n else if (value instanceof G9Long) out[column] = value;\n else if (value instanceof ArrayBuffer) out[column] = { $b64: bytesToBase64(new Uint8Array(value)) };\n else if (value instanceof Uint8Array) out[column] = { $b64: bytesToBase64(value) };\n else if (typeof value === 'boolean') out[column] = value ? 'True' : 'False';\n else out[column] = String(value);\n }\n return stringifyJson(out);\n}\n\n/** `DeserializeValues`: numbers as integers when they are, int64 beyond 2^53 as tags, `{\"$b64\"}` as BLOBs. */\nexport function deserializeValues(json: string): { [column: string]: G9SqlValue } {\n const parsed = parseJson(json) as { [column: string]: unknown };\n const out: { [column: string]: G9SqlValue } = {};\n for (const column of Object.keys(parsed)) {\n const value = parsed[column];\n if (value === null || value === undefined) out[column] = null;\n else if (value instanceof G9Long) out[column] = value.toSqlValue();\n else if (typeof value === 'number' || typeof value === 'string') out[column] = value;\n else if (typeof value === 'object' && typeof (value as { $b64?: unknown }).$b64 === 'string') {\n const bytes = base64ToBytes((value as { $b64: string }).$b64);\n const copy = new Uint8Array(bytes.length);\n copy.set(bytes);\n out[column] = copy.buffer;\n } else out[column] = JSON.stringify(value);\n }\n return out;\n}\n\n/** Reads every column of a local row (`ReadLocalValues`): column name → stored value; empty when the row is gone. */\nexport async function readLocalValues(connection: G9SqliteConnection, table: LocalTable, key: string): Promise<{ [column: string]: G9SqlValue }> {\n const results = await connection.runStatements([{ sql: `SELECT * FROM ${table.quoted} WHERE ${table.keyQuoted} = ?1`, params: [keyValue(table, key)] }]);\n const result = results[0];\n const values: { [column: string]: G9SqlValue } = {};\n if (!result || result.rows.length === 0) return values;\n const row = result.rows[0] as readonly G9SqlValue[];\n result.columns.forEach((name, i) => {\n values[name] = row[i] as G9SqlValue;\n });\n return values;\n}\n\n/** A store error that the engine maps to G9S-LOCAL-STORE. */\nexport function storeError(message: string): G9SyncException {\n return new G9SyncException(G9SyncErrorCodes.LocalStoreError, message);\n}\n"]}
1
+ {"version":3,"file":"internals.js","sourceRoot":"","sources":["../../src/sqlite/internals.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,0EAA0E;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAiC,MAAM,yBAAyB,CAAC;AAE9F,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAA6C,MAAM,iBAAiB,CAAC;AAClH,OAAO,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,mEAAmE;AACnE,MAAM,OAAO,UAAU;IAMrB,YAAY,KAAwB,EAAE,GAAW,EAAE,UAAsC,EAAE,aAAuB;QAChH,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,SAAS;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;CACF;AAgBD,MAAM,UAAU,KAAK,CAAC,MAA2B,EAAE,KAAqB,EAAE,OAAe,EAAE,OAAe,EAAE,KAAe;IACzH,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,UAA8B,EAAE,GAAW;IACpE,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,0CAA0C,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/F,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,UAA8B,EAAE,GAAW,EAAE,KAAoB;IAC7F,MAAM,UAAU,CAAC,IAAI,CAAC,wGAAwG,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1J,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CAAC,KAAiB,EAAE,YAAoB;IAC9D,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,iBAAiB,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,iBAAiB,CAAC,KAAK,EAAE,CAAC;QACvG,OAAO,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAqB,EAAE,SAAiB;IAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,IAAI,SAAS,0BAA0B,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAqB,EAAE,UAAkB;;IACxE,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACrE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,MAAA,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,mCAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAqB,EAAE,GAAW;IACtD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE;QAAE,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;IAChF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAA8B,EAAE,GAAkB;IACxF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CACjC,8HAA8H;QAC5H,8FAA8F;QAC9F,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC;QACvC,uBAAuB,EACzB,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CACvC,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAsC,CAAC;QACnF,OAAO;YACL,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,UAAU,EAAE,gBAAgB,CAAC,UAAU,CAAC,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE,CAAC;YACzD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/B,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;YACnD,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAyB;YAC7C,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzD,kBAAkB,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3D,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxD,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAA+C;SACtG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,MAAM;QAAE,OAAO,KAAK,CAAC;IACzF,MAAM,GAAG,GAA+B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAI,KAAoC,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QAClD,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAmB;IACzD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAmB;IAC1D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7E,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,eAAe,CAAC,MAAqC;IACnE,MAAM,GAAG,GAAkC,EAAE,CAAC;IAC9C,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;aACzD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;aACnD,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;aAC/D,IAAI,KAAK,YAAY,MAAM;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;aACjD,IAAI,KAAK,YAAY,WAAW;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;aAC/F,IAAI,KAAK,YAAY,UAAU;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;aAC9E,IAAI,OAAO,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;;YACvE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAkC,CAAC;IAChE,MAAM,GAAG,GAAqC,EAAE,CAAC;IACjD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;aACzD,IAAI,KAAK,YAAY,MAAM;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;aAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;aAChF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7F,MAAM,KAAK,GAAG,aAAa,CAAE,KAA0B,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,CAAC;;YAAM,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qHAAqH;AACrH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAA8B,EAAE,KAAiB,EAAE,GAAW;IAClG,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,iBAAiB,KAAK,CAAC,MAAM,UAAU,KAAK,CAAC,SAAS,OAAO,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzJ,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAqC,EAAE,CAAC;IACpD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAA0B,CAAC;IACpD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAe,CAAC;IACtC,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,eAAe,CAAC,gBAAgB,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC","sourcesContent":["// Shared state and helpers of the SQLite store's parts (the C# partial class G9CSqliteSyncStore is split the same way:\r\n// core, apply, push, query, commands, revocation, incarnation, recovery).\r\nimport { G9ESyncColumnType } from '../abstractions/enums.js';\r\nimport { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';\r\nimport { G9Long, parseJson, stringifyJson } from '../abstractions/long.js';\r\nimport { G9SyncParameters } from '../abstractions/parameters.js';\r\nimport { base64ToBytes, bytesToBase64 } from '../internal/base64.js';\r\nimport type { G9SyncClientModel, G9SyncClientTable } from '../client/model.js';\r\nimport type { G9SyncLogger, G9SyncLogLevel } from '../client/runs.js';\r\nimport { G9ESubscriptionState, type G9SyncSubscriptionRecord } from '../client/storeTypes.js';\r\nimport type { G9DtNegotiatedTable } from '../protocol/dtos.js';\r\nimport { readNegotiatedTable, readSubscriptionDefinition } from '../protocol/wire.js';\r\nimport { asNumber, asOptionalString, asString, type G9AsyncLock, type G9SqliteConnection } from './connection.js';\r\nimport { isInt64Tag, type G9SqlValue } from './driver.js';\r\nimport { quote } from './sql.js';\r\nimport type { G9ResolvedSqliteStoreOptions } from './options.js';\r\n\r\n/** A table of the model with its local metadata (`LocalTable`). */\r\nexport class LocalTable {\r\n readonly model: G9SyncClientTable;\r\n readonly tid: number;\r\n negotiated: G9DtNegotiatedTable | null;\r\n syncedColumns: string[];\r\n\r\n constructor(model: G9SyncClientTable, tid: number, negotiated: G9DtNegotiatedTable | null, syncedColumns: string[]) {\r\n this.model = model;\r\n this.tid = tid;\r\n this.negotiated = negotiated;\r\n this.syncedColumns = syncedColumns;\r\n }\r\n\r\n get quoted(): string {\r\n return quote(this.model.localName);\r\n }\r\n\r\n get keyQuoted(): string {\r\n return quote(this.model.keyColumn);\r\n }\r\n}\r\n\r\n/** What the store's parts share. */\r\nexport interface StoreInternals {\r\n readonly options: G9ResolvedSqliteStoreOptions;\r\n readonly writeLock: G9AsyncLock;\r\n /** The connection library writes go through (under the write lock). */\r\n writer(): G9SqliteConnection;\r\n /** A connection for reads that never wait on a running write. */\r\n reader(): G9SqliteConnection;\r\n ensureInitialized(): G9SyncClientModel;\r\n byLocal: Map<string, LocalTable>;\r\n byServerId: Map<number, LocalTable>;\r\n log(level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void;\r\n}\r\n\r\nexport function logTo(logger: G9SyncLogger | null, level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void {\r\n if (!logger) return;\r\n try {\r\n logger.log(level, eventId, message, error);\r\n } catch {\r\n // A logger must never break the store.\r\n }\r\n}\r\n\r\nexport function nowMs(): number {\r\n return Date.now();\r\n}\r\n\r\nexport async function meta(connection: G9SqliteConnection, key: string): Promise<string | null> {\r\n const value = await connection.scalar('SELECT value FROM g9_meta WHERE key = $k', { $k: key });\r\n return value === null ? null : asString(value);\r\n}\r\n\r\nexport async function setMeta(connection: G9SqliteConnection, key: string, value: string | null): Promise<void> {\r\n await connection.exec('INSERT INTO g9_meta (key, value) VALUES ($k, $v) ON CONFLICT(key) DO UPDATE SET value = excluded.value', { $k: key, $v: value });\r\n}\r\n\r\n/** `KeyValue`: the key in the table's storage form (integers for an integer key). */\r\nexport function keyValue(table: LocalTable, canonicalKey: string): G9SqlValue {\r\n if (table.model.keyType === G9ESyncColumnType.Int32 || table.model.keyType === G9ESyncColumnType.Int64) {\r\n return G9Long.parse(canonicalKey).toSqlValue();\r\n }\r\n return canonicalKey;\r\n}\r\n\r\nexport function getLocal(store: StoreInternals, localName: string): LocalTable {\r\n const table = store.byLocal.get(localName.toLowerCase());\r\n if (!table) throw new RangeError(`'${localName}' is not a synced table.`);\r\n return table;\r\n}\r\n\r\nexport function findByServerName(store: StoreInternals, serverName: string): LocalTable | null {\r\n const table = store.ensureInitialized().findByServerName(serverName);\r\n return table ? (store.byLocal.get(table.localName.toLowerCase()) ?? null) : null;\r\n}\r\n\r\nexport function byTid(store: StoreInternals, tid: number): LocalTable | null {\r\n for (const table of store.byLocal.values()) if (table.tid === tid) return table;\r\n return null;\r\n}\r\n\r\n/** Reads subscriptions, all or one key, oldest first. */\r\nexport async function readSubscriptions(connection: G9SqliteConnection, key: string | null): Promise<G9SyncSubscriptionRecord[]> {\r\n const rows = await connection.query(\r\n 'SELECT key, name, params, slot, ephemeral, ttl_seconds, cursor, definition_hash, auth_hash, state, error_code, created_utc, ' +\r\n 'last_success_utc, last_reconcile_utc, last_access_utc, move_out_policy FROM g9_subscriptions' +\r\n (key === null ? '' : ' WHERE key = $k') +\r\n ' ORDER BY created_utc',\r\n key === null ? undefined : { $k: key },\r\n );\r\n return rows.map((r) => {\r\n const parameters = JSON.parse(asString(r[2])) as { [name: string]: string } | null;\r\n return {\r\n key: asString(r[0]),\r\n name: asString(r[1]),\r\n parameters: G9SyncParameters.fromValues(parameters ?? {}),\r\n slot: asNumber(r[3]),\r\n ephemeral: asNumber(r[4]) !== 0,\r\n ttlMs: r[5] === null ? null : asNumber(r[5]) * 1000,\r\n cursor: asOptionalString(r[6]),\r\n definitionHash: asOptionalString(r[7]),\r\n authHash: asOptionalString(r[8]),\r\n state: asNumber(r[9]) as G9ESubscriptionState,\r\n lastErrorCode: asOptionalString(r[10]),\r\n createdUtcMs: asNumber(r[11]),\r\n lastSuccessUtcMs: r[12] === null ? null : asNumber(r[12]),\r\n lastReconcileUtcMs: r[13] === null ? null : asNumber(r[13]),\r\n lastAccessUtcMs: r[14] === null ? null : asNumber(r[14]),\r\n moveOutPolicy: r[15] === null ? null : (asNumber(r[15]) as G9SyncSubscriptionRecord['moveOutPolicy']),\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * JSON of a persisted DTO in the form .NET's source-generated context writes (camelCase, nulls omitted), so a database\r\n * written by either side reads on the other.\r\n */\r\nexport function persistedJson(value: unknown): string {\r\n return stringifyJson(dropNulls(value));\r\n}\r\n\r\nfunction dropNulls(value: unknown): unknown {\r\n if (Array.isArray(value)) return value.map(dropNulls);\r\n if (value === null || typeof value !== 'object' || value instanceof G9Long) return value;\r\n const out: { [key: string]: unknown } = {};\r\n for (const key of Object.keys(value as object)) {\r\n const item = (value as { [key: string]: unknown })[key];\r\n if (item === null || item === undefined) continue;\r\n out[key] = dropNulls(item);\r\n }\r\n return out;\r\n}\r\n\r\nexport function readPersistedNegotiated(json: string | null): G9DtNegotiatedTable | null {\r\n return json === null ? null : readNegotiatedTable(parseJson(json));\r\n}\r\n\r\nexport function readPersistedDefinitions(json: string | null) {\r\n if (json === null) return [];\r\n const parsed = parseJson(json);\r\n return Array.isArray(parsed) ? parsed.map(readSubscriptionDefinition) : [];\r\n}\r\n\r\n/** SQLite values as JSON (`SerializeValues`): text as strings, numbers as numbers, blobs as `{\"$b64\": \"…\"}`. */\r\nexport function serializeValues(values: { [column: string]: unknown }): string {\r\n const out: { [column: string]: unknown } = {};\r\n for (const column of Object.keys(values)) {\r\n const value = values[column];\r\n if (value === null || value === undefined) out[column] = null;\r\n else if (typeof value === 'number') out[column] = value;\r\n else if (isInt64Tag(value)) out[column] = G9Long.parse(value.int64);\r\n else if (value instanceof G9Long) out[column] = value;\r\n else if (value instanceof ArrayBuffer) out[column] = { $b64: bytesToBase64(new Uint8Array(value)) };\r\n else if (value instanceof Uint8Array) out[column] = { $b64: bytesToBase64(value) };\r\n else if (typeof value === 'boolean') out[column] = value ? 'True' : 'False';\r\n else out[column] = String(value);\r\n }\r\n return stringifyJson(out);\r\n}\r\n\r\n/** `DeserializeValues`: numbers as integers when they are, int64 beyond 2^53 as tags, `{\"$b64\"}` as BLOBs. */\r\nexport function deserializeValues(json: string): { [column: string]: G9SqlValue } {\r\n const parsed = parseJson(json) as { [column: string]: unknown };\r\n const out: { [column: string]: G9SqlValue } = {};\r\n for (const column of Object.keys(parsed)) {\r\n const value = parsed[column];\r\n if (value === null || value === undefined) out[column] = null;\r\n else if (value instanceof G9Long) out[column] = value.toSqlValue();\r\n else if (typeof value === 'number' || typeof value === 'string') out[column] = value;\r\n else if (typeof value === 'object' && typeof (value as { $b64?: unknown }).$b64 === 'string') {\r\n const bytes = base64ToBytes((value as { $b64: string }).$b64);\r\n const copy = new Uint8Array(bytes.length);\r\n copy.set(bytes);\r\n out[column] = copy.buffer;\r\n } else out[column] = JSON.stringify(value);\r\n }\r\n return out;\r\n}\r\n\r\n/** Reads every column of a local row (`ReadLocalValues`): column name → stored value; empty when the row is gone. */\r\nexport async function readLocalValues(connection: G9SqliteConnection, table: LocalTable, key: string): Promise<{ [column: string]: G9SqlValue }> {\r\n const results = await connection.runStatements([{ sql: `SELECT * FROM ${table.quoted} WHERE ${table.keyQuoted} = ?1`, params: [keyValue(table, key)] }]);\r\n const result = results[0];\r\n const values: { [column: string]: G9SqlValue } = {};\r\n if (!result || result.rows.length === 0) return values;\r\n const row = result.rows[0] as readonly G9SqlValue[];\r\n result.columns.forEach((name, i) => {\r\n values[name] = row[i] as G9SqlValue;\r\n });\r\n return values;\r\n}\r\n\r\n/** A store error that the engine maps to G9S-LOCAL-STORE. */\r\nexport function storeError(message: string): G9SyncException {\r\n return new G9SyncException(G9SyncErrorCodes.LocalStoreError, message);\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/sqlite/options.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.Sqlite/G9CSqliteSyncStoreOptions.cs. Durations are milliseconds.\nimport type { G9SyncLogger } from '../client/runs.js';\nimport { G9RevocationPolicy } from '../client/storeTypes.js';\nimport type { G9FrameDecompressor } from '../protocol/rowBatch/reader.js';\nimport type { G9FrameCompressor } from '../protocol/rowBatch/writer.js';\nimport type { G9SqliteDriver } from './driver.js';\nimport { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage } from './sql.js';\n\n/** Where the installation's incarnation lives, outside the platform's backup set (ADR-0067). */\nexport interface G9IncarnationMarker {\n /** The marker's value, or null when there is none (or it cannot be read). */\n read(): Promise<string | null>;\n /** Writes the marker whole; false when it cannot be written (restore detection is then off for the run). */\n write(value: string): Promise<boolean>;\n}\n\n/** The file operations a file-based marker needs (structurally `G9FileSystem` of @g9tm/signalr-supernetcore-client). */\nexport interface G9MarkerFileSystem {\n stat(path: string): Promise<{ readonly size: number } | null>;\n read(path: string, offset: number, length: number): Promise<Uint8Array | ArrayBuffer>;\n write(path: string, offset: number, bytes: Uint8Array, truncate?: boolean): Promise<void>;\n move(from: string, to: string): Promise<void>;\n remove(path: string): Promise<void>;\n}\n\n/**\n * Where a device writes downloaded snapshot files (ADR-0072). The bytes of a file never pass through the store's own code:\n * each segment goes straight from the transport to `writeSegment`, which a platform implements natively (Lynx: the\n * `G9SyncDataLynxModule` of @g9tm/syncdata-lynx; Node: `nodeSnapshotFileSink` of @g9tm/syncdata/node). The store reads the\n * finished file through SQLite's ATTACH, so the sink never needs to read a file back except its 100-byte header.\n */\nexport interface G9SnapshotFileSink {\n /** The directory staged files go to (created when missing). Use a cache directory, outside the backup set. */\n readonly directory: string;\n /** Creates `path` (or truncates it) as `size` zero bytes. */\n create(path: string, size: number): Promise<void>;\n /**\n * Decompresses one Brotli segment (each segment is compressed on its own), checks that it is `length` bytes whose SHA-256 is\n * `sha256` (lower-case hex), and writes it at `offset` in `path`. With `sync`, the file is flushed to disk before the promise\n * settles. Rejects - writing nothing - when the segment does not decompress to `length` bytes or fails its hash.\n */\n writeSegment(path: string, offset: number, compressed: Uint8Array, length: number, sha256: string, sync: boolean): Promise<void>;\n /** The file's size, or null when it does not exist. */\n size(path: string): Promise<number | null>;\n /** The first `length` bytes of the file (the SQLite header check). */\n head(path: string, length: number): Promise<Uint8Array>;\n /** Deletes the file; a missing file is not an error. */\n remove(path: string): Promise<void>;\n /** The full paths of the files in `directory` (for the sweep of files no stage refers to). */\n list(directory: string): Promise<string[]>;\n}\n\nexport interface G9SqliteSyncStoreOptions {\n /** The SQLite driver (Lynx native, Lynxtron, or `nodeSqliteDriver()` from `@g9tm/syncdata/node`). */\n driver: G9SqliteDriver;\n /** Database file path. */\n databasePath: string;\n dateTimeStorage?: G9ESqliteDateTimeStorage;\n /** Text format for DateTime values; only the .NET default `yyyy-MM-dd'T'HH:mm:ss.fffffff` is supported. */\n dateTimeFormat?: string;\n decimalStorage?: G9ESqliteDecimalStorage;\n /** Restore/copy detection (ADR-0067): a marker outside the backup set. Null (default) turns the check off. */\n incarnationMarker?: G9IncarnationMarker | null;\n /** How long a writer waits for the database lock (the app may be writing). */\n busyTimeoutMs?: number;\n useWriteAheadLog?: boolean;\n /** What happens to a row no subscription holds any more (ADR-0026). */\n revocation?: G9RevocationPolicy;\n /** The largest decoded body accepted from one frame the store applies (ADR-0051, ADR-0066). */\n maxDecodedFrameBytes?: number;\n /** Changed keys reported per table in an apply report. */\n maxChangedKeysPerTable?: number;\n /**\n * Large applies run without evaluating the library's own triggers (ADR-0034): the TypeScript store has no\n * SQLITE_DBCONFIG_ENABLE_TRIGGER, so it drops its own capture and command triggers inside the apply transaction and\n * re-creates them from their stored SQL before commit (PARITY.md). Never while the database holds a foreign trigger.\n */\n skipTriggersDuringApply?: boolean;\n /** The smallest staged pull (rows) for which triggers are skipped; smaller applies are not worth the schema change. */\n skipTriggersMinRows?: number;\n rebuildIndexesAfterRows?: number;\n rebuildIndexesMinimumGrowth?: number;\n /** Rows per committed slice of a staged pull, or 0 to apply it in one transaction (ADR-0053). */\n applySliceRows?: number;\n applySliceRowsMax?: number;\n maintenanceAfterRows?: number;\n synchronousNormalForDownloads?: boolean;\n /** journal_size_limit of the store's connections; negative = no limit. */\n walSizeLimitBytes?: number;\n /** Statements per driver call in the apply loop (one bridge round trip each). */\n statementsPerBatch?: number;\n /** Brotli decoder for downloaded frames; the process default (setDefaultFrameDecompressor) when omitted. */\n frameDecompressor?: G9FrameDecompressor | null;\n /** Brotli encoder for push frames; uncompressed frames when omitted (every server accepts them). */\n frameCompressor?: G9FrameCompressor | null;\n logger?: G9SyncLogger | null;\n /**\n * Where snapshot files are written (ADR-0072). Null (default): the store does not offer to receive them and every pull is\n * rows. With a sink, large first downloads can arrive as a SQLite file the apply copies instead of inserting row by row.\n */\n snapshotFiles?: G9SnapshotFileSink | null;\n /** A subscription is sent as a file only when its snapshot is at least this many rows; 0 leaves it to the server. */\n snapshotFileMinRows?: number;\n /** The largest snapshot file accepted, uncompressed (default 2 GiB). */\n snapshotFileMaxBytes?: number;\n /** Bytes between two durable resume points of a file download (flush, then the stage row). Default 8 MiB. */\n snapshotFileCheckpointBytes?: number;\n}\n\nexport type G9ResolvedSqliteStoreOptions = Required<Omit<G9SqliteSyncStoreOptions, 'incarnationMarker' | 'frameDecompressor' | 'frameCompressor' | 'logger' | 'snapshotFiles'>> & {\n incarnationMarker: G9IncarnationMarker | null;\n frameDecompressor: G9FrameDecompressor | null;\n frameCompressor: G9FrameCompressor | null;\n logger: G9SyncLogger | null;\n snapshotFiles: G9SnapshotFileSink | null;\n};\n\nexport const DEFAULT_DATE_TIME_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.fffffff\";\n\nexport function resolveStoreOptions(options: G9SqliteSyncStoreOptions): G9ResolvedSqliteStoreOptions {\n if (!options || !options.driver) throw new TypeError('A SQLite driver is required.');\n if (typeof options.databasePath !== 'string' || options.databasePath.trim() === '') throw new TypeError('Set databasePath.');\n const format = options.dateTimeFormat ?? DEFAULT_DATE_TIME_FORMAT;\n if (format !== DEFAULT_DATE_TIME_FORMAT) {\n throw new RangeError(`Only the DateTime format ${DEFAULT_DATE_TIME_FORMAT} is supported by the TypeScript store (PARITY.md).`);\n }\n return {\n driver: options.driver,\n databasePath: options.databasePath,\n dateTimeStorage: options.dateTimeStorage ?? G9ESqliteDateTimeStorage.Text,\n dateTimeFormat: format,\n decimalStorage: options.decimalStorage ?? G9ESqliteDecimalStorage.Real,\n incarnationMarker: options.incarnationMarker ?? null,\n busyTimeoutMs: options.busyTimeoutMs ?? 30000,\n useWriteAheadLog: options.useWriteAheadLog ?? true,\n revocation: options.revocation ?? G9RevocationPolicy.default,\n maxDecodedFrameBytes: options.maxDecodedFrameBytes ?? 64 * 1024 * 1024,\n maxChangedKeysPerTable: options.maxChangedKeysPerTable ?? 5000,\n skipTriggersDuringApply: options.skipTriggersDuringApply ?? true,\n skipTriggersMinRows: options.skipTriggersMinRows ?? 5000,\n rebuildIndexesAfterRows: options.rebuildIndexesAfterRows ?? 20000,\n rebuildIndexesMinimumGrowth: options.rebuildIndexesMinimumGrowth ?? 1,\n applySliceRows: options.applySliceRows ?? 0,\n applySliceRowsMax: options.applySliceRowsMax ?? 32000,\n maintenanceAfterRows: options.maintenanceAfterRows ?? 10000,\n synchronousNormalForDownloads: options.synchronousNormalForDownloads ?? true,\n walSizeLimitBytes: options.walSizeLimitBytes ?? 64 * 1024 * 1024,\n statementsPerBatch: options.statementsPerBatch ?? 1500,\n frameDecompressor: options.frameDecompressor ?? null,\n frameCompressor: options.frameCompressor ?? null,\n logger: options.logger ?? null,\n snapshotFiles: options.snapshotFiles ?? null,\n snapshotFileMinRows: options.snapshotFileMinRows ?? 0,\n snapshotFileMaxBytes: options.snapshotFileMaxBytes ?? 2 * 1024 * 1024 * 1024,\n snapshotFileCheckpointBytes: options.snapshotFileCheckpointBytes ?? 8 * 1024 * 1024,\n };\n}\n\n/** A marker in a file, written whole and moved into place (a marker cut short by a crash would read as another installation). */\nexport function fileIncarnationMarker(fileSystem: G9MarkerFileSystem, path: string): G9IncarnationMarker {\n return {\n async read(): Promise<string | null> {\n try {\n const stat = await fileSystem.stat(path);\n if (!stat) return null;\n const data = await fileSystem.read(path, 0, stat.size);\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n let text = '';\n for (let i = 0; i < bytes.length; i++) text += String.fromCharCode(bytes[i] as number);\n text = text.trim();\n return text.length === 0 ? null : text;\n } catch {\n return null;\n }\n },\n async write(value: string): Promise<boolean> {\n try {\n const bytes = new Uint8Array(value.length);\n for (let i = 0; i < value.length; i++) bytes[i] = value.charCodeAt(i) & 0x7f;\n const temporary = path + '.tmp';\n await fileSystem.write(temporary, 0, bytes, true);\n await fileSystem.remove(path);\n await fileSystem.move(temporary, path);\n return true;\n } catch {\n return false;\n }\n },\n };\n}\n"]}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/sqlite/options.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.Sqlite/G9CSqliteSyncStoreOptions.cs. Durations are milliseconds.\r\nimport type { G9SyncLogger } from '../client/runs.js';\r\nimport { G9RevocationPolicy } from '../client/storeTypes.js';\r\nimport type { G9FrameDecompressor } from '../protocol/rowBatch/reader.js';\r\nimport type { G9FrameCompressor } from '../protocol/rowBatch/writer.js';\r\nimport type { G9SqliteDriver } from './driver.js';\r\nimport { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage } from './sql.js';\r\n\r\n/** Where the installation's incarnation lives, outside the platform's backup set (ADR-0067). */\r\nexport interface G9IncarnationMarker {\r\n /** The marker's value, or null when there is none (or it cannot be read). */\r\n read(): Promise<string | null>;\r\n /** Writes the marker whole; false when it cannot be written (restore detection is then off for the run). */\r\n write(value: string): Promise<boolean>;\r\n}\r\n\r\n/** The file operations a file-based marker needs (structurally `G9FileSystem` of @g9tm/signalr-supernetcore-client). */\r\nexport interface G9MarkerFileSystem {\r\n stat(path: string): Promise<{ readonly size: number } | null>;\r\n read(path: string, offset: number, length: number): Promise<Uint8Array | ArrayBuffer>;\r\n write(path: string, offset: number, bytes: Uint8Array, truncate?: boolean): Promise<void>;\r\n move(from: string, to: string): Promise<void>;\r\n remove(path: string): Promise<void>;\r\n}\r\n\r\n/**\r\n * Where a device writes downloaded snapshot files (ADR-0072). The bytes of a file never pass through the store's own code:\r\n * each segment goes straight from the transport to `writeSegment`, which a platform implements natively (Lynx: the\r\n * `G9SyncDataLynxModule` of @g9tm/syncdata-lynx; Node: `nodeSnapshotFileSink` of @g9tm/syncdata/node). The store reads the\r\n * finished file through SQLite's ATTACH, so the sink never needs to read a file back except its 100-byte header.\r\n */\r\nexport interface G9SnapshotFileSink {\r\n /** The directory staged files go to (created when missing). Use a cache directory, outside the backup set. */\r\n readonly directory: string;\r\n /** Creates `path` (or truncates it) as `size` zero bytes. */\r\n create(path: string, size: number): Promise<void>;\r\n /**\r\n * Decompresses one Brotli segment (each segment is compressed on its own), checks that it is `length` bytes whose SHA-256 is\r\n * `sha256` (lower-case hex), and writes it at `offset` in `path`. With `sync`, the file is flushed to disk before the promise\r\n * settles. Rejects - writing nothing - when the segment does not decompress to `length` bytes or fails its hash.\r\n */\r\n writeSegment(path: string, offset: number, compressed: Uint8Array, length: number, sha256: string, sync: boolean): Promise<void>;\r\n /** The file's size, or null when it does not exist. */\r\n size(path: string): Promise<number | null>;\r\n /** The first `length` bytes of the file (the SQLite header check). */\r\n head(path: string, length: number): Promise<Uint8Array>;\r\n /** Deletes the file; a missing file is not an error. */\r\n remove(path: string): Promise<void>;\r\n /** The full paths of the files in `directory` (for the sweep of files no stage refers to). */\r\n list(directory: string): Promise<string[]>;\r\n}\r\n\r\nexport interface G9SqliteSyncStoreOptions {\r\n /** The SQLite driver (Lynx native, Lynxtron, or `nodeSqliteDriver()` from `@g9tm/syncdata/node`). */\r\n driver: G9SqliteDriver;\r\n /** Database file path. */\r\n databasePath: string;\r\n dateTimeStorage?: G9ESqliteDateTimeStorage;\r\n /** Text format for DateTime values; only the .NET default `yyyy-MM-dd'T'HH:mm:ss.fffffff` is supported. */\r\n dateTimeFormat?: string;\r\n decimalStorage?: G9ESqliteDecimalStorage;\r\n /** Restore/copy detection (ADR-0067): a marker outside the backup set. Null (default) turns the check off. */\r\n incarnationMarker?: G9IncarnationMarker | null;\r\n /** How long a writer waits for the database lock (the app may be writing). */\r\n busyTimeoutMs?: number;\r\n useWriteAheadLog?: boolean;\r\n /** What happens to a row no subscription holds any more (ADR-0026). */\r\n revocation?: G9RevocationPolicy;\r\n /** The largest decoded body accepted from one frame the store applies (ADR-0051, ADR-0066). */\r\n maxDecodedFrameBytes?: number;\r\n /** Changed keys reported per table in an apply report. */\r\n maxChangedKeysPerTable?: number;\r\n /**\r\n * Large applies run without evaluating the library's own triggers (ADR-0034): the TypeScript store has no\r\n * SQLITE_DBCONFIG_ENABLE_TRIGGER, so it drops its own capture and command triggers inside the apply transaction and\r\n * re-creates them from their stored SQL before commit (PARITY.md). Never while the database holds a foreign trigger.\r\n */\r\n skipTriggersDuringApply?: boolean;\r\n /** The smallest staged pull (rows) for which triggers are skipped; smaller applies are not worth the schema change. */\r\n skipTriggersMinRows?: number;\r\n rebuildIndexesAfterRows?: number;\r\n rebuildIndexesMinimumGrowth?: number;\r\n /** Rows per committed slice of a staged pull, or 0 to apply it in one transaction (ADR-0053). */\r\n applySliceRows?: number;\r\n applySliceRowsMax?: number;\r\n maintenanceAfterRows?: number;\r\n synchronousNormalForDownloads?: boolean;\r\n /** journal_size_limit of the store's connections; negative = no limit. */\r\n walSizeLimitBytes?: number;\r\n /** Statements per driver call in the apply loop (one bridge round trip each). */\r\n statementsPerBatch?: number;\r\n /** Brotli decoder for downloaded frames; the process default (setDefaultFrameDecompressor) when omitted. */\r\n frameDecompressor?: G9FrameDecompressor | null;\r\n /** Brotli encoder for push frames; uncompressed frames when omitted (every server accepts them). */\r\n frameCompressor?: G9FrameCompressor | null;\r\n logger?: G9SyncLogger | null;\r\n /**\r\n * Where snapshot files are written (ADR-0072). Null (default): the store does not offer to receive them and every pull is\r\n * rows. With a sink, large first downloads can arrive as a SQLite file the apply copies instead of inserting row by row.\r\n */\r\n snapshotFiles?: G9SnapshotFileSink | null;\r\n /** A subscription is sent as a file only when its snapshot is at least this many rows; 0 leaves it to the server. */\r\n snapshotFileMinRows?: number;\r\n /** The largest snapshot file accepted, uncompressed (default 2 GiB). */\r\n snapshotFileMaxBytes?: number;\r\n /** Bytes between two durable resume points of a file download (flush, then the stage row). Default 8 MiB. */\r\n snapshotFileCheckpointBytes?: number;\r\n}\r\n\r\nexport type G9ResolvedSqliteStoreOptions = Required<Omit<G9SqliteSyncStoreOptions, 'incarnationMarker' | 'frameDecompressor' | 'frameCompressor' | 'logger' | 'snapshotFiles'>> & {\r\n incarnationMarker: G9IncarnationMarker | null;\r\n frameDecompressor: G9FrameDecompressor | null;\r\n frameCompressor: G9FrameCompressor | null;\r\n logger: G9SyncLogger | null;\r\n snapshotFiles: G9SnapshotFileSink | null;\r\n};\r\n\r\nexport const DEFAULT_DATE_TIME_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.fffffff\";\r\n\r\nexport function resolveStoreOptions(options: G9SqliteSyncStoreOptions): G9ResolvedSqliteStoreOptions {\r\n if (!options || !options.driver) throw new TypeError('A SQLite driver is required.');\r\n if (typeof options.databasePath !== 'string' || options.databasePath.trim() === '') throw new TypeError('Set databasePath.');\r\n const format = options.dateTimeFormat ?? DEFAULT_DATE_TIME_FORMAT;\r\n if (format !== DEFAULT_DATE_TIME_FORMAT) {\r\n throw new RangeError(`Only the DateTime format ${DEFAULT_DATE_TIME_FORMAT} is supported by the TypeScript store (PARITY.md).`);\r\n }\r\n return {\r\n driver: options.driver,\r\n databasePath: options.databasePath,\r\n dateTimeStorage: options.dateTimeStorage ?? G9ESqliteDateTimeStorage.Text,\r\n dateTimeFormat: format,\r\n decimalStorage: options.decimalStorage ?? G9ESqliteDecimalStorage.Real,\r\n incarnationMarker: options.incarnationMarker ?? null,\r\n busyTimeoutMs: options.busyTimeoutMs ?? 30000,\r\n useWriteAheadLog: options.useWriteAheadLog ?? true,\r\n revocation: options.revocation ?? G9RevocationPolicy.default,\r\n maxDecodedFrameBytes: options.maxDecodedFrameBytes ?? 64 * 1024 * 1024,\r\n maxChangedKeysPerTable: options.maxChangedKeysPerTable ?? 5000,\r\n skipTriggersDuringApply: options.skipTriggersDuringApply ?? true,\r\n skipTriggersMinRows: options.skipTriggersMinRows ?? 5000,\r\n rebuildIndexesAfterRows: options.rebuildIndexesAfterRows ?? 20000,\r\n rebuildIndexesMinimumGrowth: options.rebuildIndexesMinimumGrowth ?? 1,\r\n applySliceRows: options.applySliceRows ?? 0,\r\n applySliceRowsMax: options.applySliceRowsMax ?? 32000,\r\n maintenanceAfterRows: options.maintenanceAfterRows ?? 10000,\r\n synchronousNormalForDownloads: options.synchronousNormalForDownloads ?? true,\r\n walSizeLimitBytes: options.walSizeLimitBytes ?? 64 * 1024 * 1024,\r\n statementsPerBatch: options.statementsPerBatch ?? 1500,\r\n frameDecompressor: options.frameDecompressor ?? null,\r\n frameCompressor: options.frameCompressor ?? null,\r\n logger: options.logger ?? null,\r\n snapshotFiles: options.snapshotFiles ?? null,\r\n snapshotFileMinRows: options.snapshotFileMinRows ?? 0,\r\n snapshotFileMaxBytes: options.snapshotFileMaxBytes ?? 2 * 1024 * 1024 * 1024,\r\n snapshotFileCheckpointBytes: options.snapshotFileCheckpointBytes ?? 8 * 1024 * 1024,\r\n };\r\n}\r\n\r\n/** A marker in a file, written whole and moved into place (a marker cut short by a crash would read as another installation). */\r\nexport function fileIncarnationMarker(fileSystem: G9MarkerFileSystem, path: string): G9IncarnationMarker {\r\n return {\r\n async read(): Promise<string | null> {\r\n try {\r\n const stat = await fileSystem.stat(path);\r\n if (!stat) return null;\r\n const data = await fileSystem.read(path, 0, stat.size);\r\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\r\n let text = '';\r\n for (let i = 0; i < bytes.length; i++) text += String.fromCharCode(bytes[i] as number);\r\n text = text.trim();\r\n return text.length === 0 ? null : text;\r\n } catch {\r\n return null;\r\n }\r\n },\r\n async write(value: string): Promise<boolean> {\r\n try {\r\n const bytes = new Uint8Array(value.length);\r\n for (let i = 0; i < value.length; i++) bytes[i] = value.charCodeAt(i) & 0x7f;\r\n const temporary = path + '.tmp';\r\n await fileSystem.write(temporary, 0, bytes, true);\r\n await fileSystem.remove(path);\r\n await fileSystem.move(temporary, path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n };\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sqlite/push.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,2HAA2H;AAC3H,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAoB,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAwC,MAAM,gBAAgB,CAAC;AAClI,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAiB1F,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,+GAA+G;AAC/G,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAqB,EAAE,MAAsC,EAAE,OAAe,EAAE,QAAgB;IACnI,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyF,CAAC;IACpH,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;QAChC,IAAI,UAAU,CAAC,SAAS,KAAK,gBAAgB,CAAC,YAAY;YAAE,SAAS;QACrE,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,eAAe;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1E,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,eAAe;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO;aAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACtF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpF,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAC9B,KAAK,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;;QACjD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,KAAK,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/F,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,iHAAiH;QACjH,kHAAkH;QAClH,mHAAmH;QACnH,MAAM,GAAG,GACP,4IAA4I;YAC5I,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACd,GAAG;YACH,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,yBAAyB,CAAC;YACvD,gCAAgC,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACnG,MAAM,OAAO,GACX,UAAU,CAAC,IAAI,KAAK,CAAC;YACnB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACtJ,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACpB,CAAC,CAAC,CAAC;QAEJ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,mFAAmF;gBACnF,MAAM,UAAU,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;YACtG,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,qHAAqH;QACrH,kEAAkE;QAClE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;QAChD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,QAAQ,GAAkD,EAAE,CAAC;QACnE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,MAAM,GACV,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;oBACxB,CAAC,CAAC,iBAAiB,KAAK,CAAC,KAAK,CAAC,MAAM,UAAU,KAAK,CAAC,KAAK,CAAC,SAAS,OAAO;oBAC3E,CAAC,CAAC,UAAU,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,MAAM,UAAU,KAAK,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC;gBAClK,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;gBACtC,MAAM,CAAC,YAAY,CACjB,aAAa,CAAC,IAAI,EAClB,KAAK,CAAC,UAAU,CAAC,OAAO,EACxB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EACzB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CACjC,CAAC;gBACF,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBAChH,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACjC,CAAC;YAED,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,QAAQ,CAAC;YACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YAC5C,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBACpB,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;gBAC5C,IAAI,QAAQ,GAAG,CAAC,IAAI,UAAU,GAAG,WAAW,GAAG,QAAQ,EAAE,CAAC;oBACxD,SAAS,GAAG,IAAI,CAAC;oBACjB,MAAM;gBACR,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC/F,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,QAAQ,EAAE,CAAC;gBACX,mBAAmB,GAAG,GAAG,CAAC,GAAG,CAAC;gBAC9B,UAAU,IAAI,WAAW,CAAC;gBAC1B,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/F,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC/F,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,QAAQ,EAAE,CAAC;gBACX,mBAAmB,GAAG,GAAG,CAAC,GAAG,CAAC;gBAC9B,UAAU,IAAI,YAAY,GAAG,QAAQ,CAAC;gBACtC,SAAS;YACX,CAAC;YAED,IAAI,QAAQ,GAAG,YAAY,GAAG,QAAQ,CAAC;YACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,QAAQ,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAe,EAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAgB,CAAC,IAAI,CAAC,CAAC;YACpJ,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;gBACxB,wGAAwG;gBACxG,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC/D,SAAS;YACX,CAAC;YACD,IAAI,QAAQ,GAAG,CAAC,IAAI,UAAU,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC;gBACrD,SAAS,GAAG,IAAI,CAAC;gBACjB,MAAM;YACR,CAAC;YAED,IAAI,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChD,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAgB,CAAC,KAAK,CAAC;oBAAE,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAClH,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC5F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAe,EAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAClK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC;YACX,mBAAmB,GAAG,GAAG,CAAC,GAAG,CAAC;YAC9B,UAAU,IAAI,QAAQ,CAAC;QACzB,CAAC;QAED,KAAK,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3C,MAAM,UAAU,CAAC,IAAI,CAAC,6DAA6D,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5G,MAAM,UAAU,CAAC,IAAI,CACnB,0HAA0H;gBACxH,gEAAgE,EAClE;gBACE,EAAE,EAAE,GAAG;gBACP,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,gBAAgB,CAAC,cAAc;gBACtC,QAAQ,EAAE,uBAAuB,KAAK,sCAAsC,QAAQ,kBAAkB;gBACtG,GAAG,EAAE,KAAK,EAAE;aACb,CACF,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC/I,CAAC;QAED,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,MAAM,UAAU,GAAuB,EAAE,CAAC;QAC1C,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YAC/B,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;YACnF,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxG,CAAC,CAAC,CAAC;QAEH,IAAI,OAAe,CAAC;QACpB,IAAI,WAAmB,CAAC;QACxB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,MAAM,CAAC,MAAA,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,mCAAI,GAAG,CAAC,CAAC;YACnE,WAAW,GAAG,mBAAmB,CAAC;YAClC,MAAM,OAAO,CAAC,UAAU,EAAE,eAAe,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YAChE,MAAM,OAAO,CAAC,UAAU,EAAE,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAChE,MAAM,OAAO,CAAC,UAAU,EAAE,kBAAkB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,UAAU,CAAC,IAAI,CAAC,6DAA6D,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC7H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACzI,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,2GAA2G;AAC3G,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAqB,EAAE,UAAkB,EAAE,IAA8B;IAChH,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,KAAK,gBAAgB,CAAC,UAAU,EAAE,CAAC;QACpF,MAAM,IAAI,KAAK,CAAC,IAAI,UAAU,sFAAsF,CAAC,CAAC;IACxH,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAC9B,KAAK,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,UAAU,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC,gCAAgC;QACtG,MAAM,UAAU,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;QAChH,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,MAAM,UAAU,CAAC,IAAI,CAAC,gFAAgF,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7H,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,UAAU,CAAC,IAAI,CAAC,uGAAuG,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9J,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC,CAAC;QACtF,MAAM,UAAU,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,SAAS,yCAAyC,CAAC,CAAC;QAC1H,MAAM,UAAU,CAAC,IAAI,CAAC,gGAAgG,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3I,MAAM,UAAU,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACrE,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,8BAA8B;AAC9B,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAqB,EAAE,KAAkB,EAAE,MAAsB,EAAE,MAAoB;IAC3H,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAC1B,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAC9B,KAAK,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;;QACjD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAClC,oHAAoH;QACpH,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;QAC5E,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,kBAAkB,EAAE,KAAK,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACtH,OAAO,CAAC,MAAM,CAAC,iBAAiB,GAAG,SAAS,CAAC;QAE7C,MAAM,SAAS,GACb,sCAAsC;YACtC,2DAA2D;YAC3D,qEAAqE;YACrE,6EAA6E;YAC7E,4CAA4C;YAC5C,uDAAuD,CAAC;QAC1D,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAW,EAAE,CAAC,CAAC;gBACnL,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GACb,mFAAmF;YACnF,0HAA0H;YAC1H,iFAAiF,CAAC;QACpF,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;QACpB,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE;gBAC7B,EAAE,EAAE,KAAK,CAAC,GAAG;gBACb,GAAG,EAAE,SAAS,CAAC,GAAG;gBAClB,EAAE,EAAE,KAAK,CAAC,WAAW;gBACrB,KAAK,EAAE,SAAS,CAAC,IAAI;gBACrB,QAAQ,EAAE,MAAA,SAAS,CAAC,OAAO,mCAAI,IAAI;gBACnC,MAAM,EAAE,MAAA,SAAS,CAAC,QAAQ,mCAAI,IAAI;gBAClC,WAAW,EAAE,MAAA,SAAS,CAAC,UAAU,mCAAI,IAAI;gBACzC,OAAO,EAAE,MAAA,SAAS,CAAC,MAAM,mCAAI,IAAI;gBACjC,QAAQ,EAAE,MAAA,SAAS,CAAC,OAAO,mCAAI,IAAI;gBACnC,IAAI,EAAE,GAAG;aACV,CAAC,CAAC;YACH,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QACnD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,eAAe;YAAE,MAAM,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAE1F,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,UAAU,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QACpG,OAAO,OAAO,CAAC,MAAM,CAAC;IACxB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["// Twin of G9SyncData.Client.Sqlite/G9CSqliteSyncStore.Push.cs: dirty rows in local change order become push frames; the\n// result clears exactly the rows that were sent (rows edited meanwhile stay dirty), flags rejections and applies canonical\n// server rows.\nimport { G9ESyncDirection } from '../abstractions/enums.js';\nimport { G9SyncErrorCodes } from '../abstractions/errors.js';\nimport { G9Long } from '../abstractions/long.js';\nimport { utf8Encode } from '../internal/utf8.js';\nimport { G9ApplyReport, type G9PushBatch } from '../client/storeTypes.js';\nimport type { G9DtNegotiatedTable, G9DtPushResult, G9DtTableColumns } from '../protocol/dtos.js';\nimport { G9EPushRowOp, G9ERowBatchOp } from '../protocol/rowBatch/format.js';\nimport { G9RowBatchWriter } from '../protocol/rowBatch/writer.js';\nimport { applyFrame, beginApply, endApply } from './apply.js';\nimport { completeCommands, readPendingCommands } from './commands.js';\nimport { asLong, asNumber, asString } from './connection.js';\nimport type { G9SqlValue } from './driver.js';\nimport { findByServerName, getLocal, keyValue, meta, nowMs, setMeta, type LocalTable, type StoreInternals } from './internals.js';\nimport { quote } from './sql.js';\nimport { estimateEncodedBytes, pushSelectExpression, writeLocalValue } from './values.js';\n\ninterface PushColumn {\n name: string;\n type: number;\n local: number;\n}\n\ninterface PushSection {\n table: LocalTable;\n negotiated: G9DtNegotiatedTable;\n columns: PushColumn[];\n writer: G9RowBatchWriter;\n select: string;\n rows: number;\n}\n\nconst ROW_OVERHEAD = 48;\n\n/** `BuildPushBatchAsync`: the next batch of pending changes, oldest first, within the row and byte budgets. */\nexport async function buildPushBatch(store: StoreInternals, tables: readonly G9DtNegotiatedTable[], maxRows: number, maxBytes: number): Promise<G9PushBatch | null> {\n store.ensureInitialized();\n const uploadable = new Map<number, { table: LocalTable; negotiated: G9DtNegotiatedTable; columns: PushColumn[] }>();\n for (const negotiated of tables) {\n if (negotiated.direction === G9ESyncDirection.DownloadOnly) continue;\n const local = findByServerName(store, negotiated.name);\n if (!local) continue;\n const readOnly = new Set<string>();\n for (const c of negotiated.readOnlyColumns) readOnly.add(c.toLowerCase());\n for (const c of negotiated.computedColumns) readOnly.add(c.toLowerCase());\n const columns = negotiated.columns\n .filter((c) => !readOnly.has(c.name.toLowerCase()) && local.model.indexOf(c.name) >= 0)\n .map((c) => ({ name: c.name, type: c.type, local: local.model.indexOf(c.name) }));\n uploadable.set(local.tid, { table: local, negotiated, columns });\n }\n\n return store.writeLock.run(() =>\n store.writer().transaction('immediate', async () => {\n const connection = store.writer();\n const inflightBatch = await meta(connection, 'inflight_batch_id');\n const inflightMax = await meta(connection, 'inflight_max_seq');\n const offsetText = await meta(connection, 'server_offset_ms');\n const offsetMs = offsetText !== null && /^[+-]?\\d+$/.test(offsetText) ? Number(offsetText) : 0;\n\n const tids = Array.from(uploadable.keys());\n // `+tid`: the unary plus keeps the tid list from driving the plan. Without it SQLite searches the primary key by\n // tid — every row of every uploadable table (486k on a farm device, 16 s on the bridge) — and sorts them, instead\n // of walking the partial g9_rows_dirty index, which holds only the pending rows and is already in local_seq order.\n const sql =\n 'SELECT tid, pk, dirty, dirty_mask, server_ver, local_seq, coalesce(hlc_ms, 0) FROM g9_rows WHERE dirty <> 0 AND rejected = 0 AND +tid IN (' +\n tids.join(',') +\n ')' +\n (inflightMax === null ? '' : ' AND local_seq <= $imax') +\n ' ORDER BY local_seq LIMIT $max';\n const commands = await readPendingCommands(store, connection, inflightBatch, Math.max(1, maxRows));\n const pending =\n uploadable.size === 0\n ? []\n : await connection.query(sql, inflightMax === null ? { $max: Math.max(1, maxRows) } : { $max: Math.max(1, maxRows), $imax: Number(inflightMax) });\n const rows = pending.map((r) => ({\n tid: asNumber(r[0]),\n key: asString(r[1]),\n dirty: asNumber(r[2]),\n mask: asLong(r[3]),\n base: asNumber(r[4]),\n seq: asNumber(r[5]),\n hlc: asNumber(r[6]),\n }));\n\n if (rows.length === 0 && commands.length === 0) {\n if (inflightBatch !== null) {\n // Everything the in-flight batch carried has been resolved another way; forget it.\n await connection.exec(\"DELETE FROM g9_meta WHERE key IN ('inflight_batch_id', 'inflight_max_seq')\");\n }\n return null;\n }\n\n // Rows are encoded in local_seq order and the batch ends at the first row past the byte budget, so a batch is always\n // a PREFIX of the pending changes. One section (frame) per table.\n const sections = new Map<number, PushSection>();\n let included = 0;\n let includedMaxSequence = 0;\n let budgetUsed = 0;\n let truncated = false;\n const tooLarge: { tid: number; key: string; bytes: number }[] = [];\n for (const row of rows) {\n const entry = uploadable.get(row.tid);\n if (!entry) continue;\n let section = sections.get(row.tid);\n if (!section) {\n const select =\n entry.columns.length === 0\n ? `SELECT 1 FROM ${entry.table.quoted} WHERE ${entry.table.keyQuoted} = $k`\n : `SELECT ${entry.columns.map((c) => pushSelectExpression(quote(c.name), c.type)).join(', ')} FROM ${entry.table.quoted} WHERE ${entry.table.keyQuoted} = $k`;\n const writer = new G9RowBatchWriter();\n writer.beginSection(\n G9ERowBatchOp.Push,\n entry.negotiated.tableId,\n entry.table.model.keyType,\n entry.columns.map((c) => c.type),\n );\n section = { table: entry.table, negotiated: entry.negotiated, columns: entry.columns, writer, select, rows: 0 };\n sections.set(row.tid, section);\n }\n\n const hlc = row.hlc === 0 ? 0 : row.hlc + offsetMs;\n const keyBytes = utf8Encode(row.key).length;\n if (row.dirty === 2) {\n const deleteBytes = ROW_OVERHEAD + keyBytes;\n if (included > 0 && budgetUsed + deleteBytes > maxBytes) {\n truncated = true;\n break;\n }\n section.writer.beginPushRow(row.key, G9EPushRowOp.Delete, row.seq, row.base, G9Long.ZERO, hlc);\n section.writer.endRow();\n section.rows++;\n included++;\n includedMaxSequence = row.seq;\n budgetUsed += deleteBytes;\n continue;\n }\n\n const found = await connection.query(section.select, { $k: keyValue(section.table, row.key) });\n const values = found[0];\n if (!values) {\n section.writer.beginPushRow(row.key, G9EPushRowOp.Delete, row.seq, row.base, G9Long.ZERO, hlc);\n section.writer.endRow();\n section.rows++;\n included++;\n includedMaxSequence = row.seq;\n budgetUsed += ROW_OVERHEAD + keyBytes;\n continue;\n }\n\n let rowBytes = ROW_OVERHEAD + keyBytes;\n for (let j = 0; j < section.columns.length; j++) rowBytes += estimateEncodedBytes(values[j] as G9SqlValue, (section.columns[j] as PushColumn).type);\n if (rowBytes > maxBytes) {\n // Can never fit, whatever else the batch carries: reject it here so it does not block every later push.\n tooLarge.push({ tid: row.tid, key: row.key, bytes: rowBytes });\n continue;\n }\n if (included > 0 && budgetUsed + rowBytes > maxBytes) {\n truncated = true;\n break;\n }\n\n let pushMask = G9Long.ZERO;\n for (let j = 0; j < section.columns.length; j++) {\n if (row.mask.testBit((section.columns[j] as PushColumn).local)) pushMask = pushMask.or(G9Long.ONE.shiftLeft(j));\n }\n section.writer.beginPushRow(row.key, G9EPushRowOp.Upsert, row.seq, row.base, pushMask, hlc);\n for (let j = 0; j < section.columns.length; j++) writeLocalValue(section.writer, values[j] as G9SqlValue, (section.columns[j] as PushColumn).type, store.options);\n section.writer.endRow();\n section.rows++;\n included++;\n includedMaxSequence = row.seq;\n budgetUsed += rowBytes;\n }\n\n for (const { tid, key, bytes } of tooLarge) {\n await connection.exec('UPDATE g9_rows SET rejected = 1 WHERE tid = $t AND pk = $pk', { $t: tid, $pk: key });\n await connection.exec(\n 'INSERT OR REPLACE INTO g9_rejections (tid, pk, code, message, sql_state, constraint_name, column_name, details, at_utc) ' +\n 'VALUES ($t, $pk, $code, $message, NULL, NULL, NULL, NULL, $at)',\n {\n $t: tid,\n $pk: key,\n $code: G9SyncErrorCodes.RejectTooLarge,\n $message: `The row needs about ${bytes} bytes; the server accepts at most ${maxBytes} bytes per push.`,\n $at: nowMs(),\n },\n );\n }\n\n if (included === 0 && commands.length === 0) {\n if (tooLarge.length === 0) return null;\n return { batchId: 0, maxSequence: 0, frames: [], tables: [], rowCount: 0, truncated: false, rejectedLocally: tooLarge.length, commands: [] };\n }\n\n const frames: Uint8Array[] = [];\n const usedTables: G9DtTableColumns[] = [];\n sections.forEach((section) => {\n if (section.rows === 0) return;\n section.writer.endSection();\n frames.push(section.writer.toFrame({ compressor: store.options.frameCompressor }));\n usedTables.push({ tableId: section.negotiated.tableId, columns: section.columns.map((c) => c.name) });\n });\n\n let batchId: number;\n let maxSequence: number;\n if (inflightBatch !== null) {\n batchId = Number(inflightBatch);\n maxSequence = Number(inflightMax);\n } else {\n batchId = Number((await meta(connection, 'next_batch_id')) ?? '1');\n maxSequence = includedMaxSequence;\n await setMeta(connection, 'next_batch_id', String(batchId + 1));\n await setMeta(connection, 'inflight_batch_id', String(batchId));\n await setMeta(connection, 'inflight_max_seq', String(maxSequence));\n }\n for (const item of commands) {\n await connection.exec('UPDATE g9_commands SET batch_id = $b WHERE command_id = $id', { $b: batchId, $id: item.commandId });\n }\n return { batchId, maxSequence, frames, tables: usedTables, rowCount: included, truncated, rejectedLocally: tooLarge.length, commands };\n }),\n );\n}\n\n/** `ForgetUploadedRowsAsync`: removes uploaded rows of an UPLOAD-ONLY table without uploading a delete. */\nexport async function forgetUploadedRows(store: StoreInternals, localTable: string, keys: readonly string[] | null): Promise<number> {\n store.ensureInitialized();\n const table = getLocal(store, localTable);\n if (!table.negotiated || table.negotiated.direction !== G9ESyncDirection.UploadOnly) {\n throw new Error(`'${localTable}' is not upload-only: deleting its rows locally is a change the server must receive.`);\n }\n return store.writeLock.run(() =>\n store.writer().transaction('immediate', async () => {\n const connection = store.writer();\n await connection.exec('UPDATE g9_ctx SET applying = 1 WHERE id = 1'); // a library write: not captured\n await connection.exec('CREATE TEMP TABLE IF NOT EXISTS g9_forget (pk TEXT PRIMARY KEY); DELETE FROM g9_forget');\n if (keys === null) {\n await connection.exec('INSERT INTO g9_forget (pk) SELECT pk FROM g9_rows WHERE tid = $t AND dirty = 0', { $t: table.tid });\n } else {\n for (const key of keys) {\n await connection.exec('INSERT OR IGNORE INTO g9_forget (pk) SELECT pk FROM g9_rows WHERE tid = $t AND pk = $pk AND dirty = 0', { $t: table.tid, $pk: key });\n }\n }\n const forgotten = asNumber(await connection.scalar('SELECT count(*) FROM g9_forget'));\n await connection.exec(`DELETE FROM ${table.quoted} WHERE CAST(${table.keyQuoted} AS TEXT) IN (SELECT pk FROM g9_forget)`);\n await connection.exec('DELETE FROM g9_rows WHERE tid = $t AND pk IN (SELECT pk FROM g9_forget); DELETE FROM g9_forget', { $t: table.tid });\n await connection.exec('UPDATE g9_ctx SET applying = 0 WHERE id = 1');\n return forgotten;\n }),\n );\n}\n\n/** `ApplyPushResultAsync`. */\nexport async function applyPushResult(store: StoreInternals, batch: G9PushBatch, result: G9DtPushResult, signal?: AbortSignal): Promise<G9ApplyReport> {\n store.ensureInitialized();\n return store.writeLock.run(() =>\n store.writer().transaction('immediate', async () => {\n const connection = store.writer();\n // Before BeginApply: finished commands release their rows, so the canonical rows below replace the optimistic ones.\n const completed = await completeCommands(connection, result.commandResults);\n const context = await beginApply(store, connection, { dirtyAfterSequence: batch.maxSequence, backfills: [], signal });\n context.report.commandsCompleted = completed;\n\n const acceptSql =\n 'UPDATE g9_rows SET server_ver = $v, ' +\n 'dirty = CASE WHEN local_seq <= $m THEN 0 ELSE dirty END, ' +\n 'dirty_mask = CASE WHEN local_seq <= $m THEN 0 ELSE dirty_mask END, ' +\n 'deleted = CASE WHEN local_seq <= $m AND dirty = 2 THEN 1 ELSE deleted END, ' +\n 'rejected = 0 WHERE tid = $t AND pk = $pk; ' +\n 'DELETE FROM g9_rejections WHERE tid = $t AND pk = $pk';\n for (const accepted of result.accepted) {\n const table = store.byServerId.get(accepted.tableId);\n if (!table) continue;\n for (let i = 0; i < accepted.keys.length; i++) {\n await context.queue(acceptSql, { $v: i < accepted.versions.length ? (accepted.versions[i] as number) : 0, $m: batch.maxSequence, $t: table.tid, $pk: accepted.keys[i] as string });\n context.report.accepted++;\n }\n }\n\n const rejectSql =\n 'UPDATE g9_rows SET rejected = 1 WHERE tid = $t AND pk = $pk AND local_seq <= $m; ' +\n 'INSERT OR REPLACE INTO g9_rejections (tid, pk, code, message, sql_state, constraint_name, column_name, details, at_utc) ' +\n 'VALUES ($t, $pk, $code, $message, $state, $constraint, $column, $details, $now)';\n const now = nowMs();\n for (const rejection of result.rejections) {\n const table = store.byServerId.get(rejection.tableId);\n if (!table) continue;\n await context.queue(rejectSql, {\n $t: table.tid,\n $pk: rejection.key,\n $m: batch.maxSequence,\n $code: rejection.code,\n $message: rejection.message ?? null,\n $state: rejection.sqlState ?? null,\n $constraint: rejection.constraint ?? null,\n $column: rejection.column ?? null,\n $details: rejection.details ?? null,\n $now: now,\n });\n context.report.rejected++;\n }\n\n context.report.conflicts = result.conflicts.length;\n await context.flush();\n for (const frame of result.canonicalFrames) await applyFrame(store, context, frame, null);\n\n await endApply(context);\n await connection.exec(\"DELETE FROM g9_meta WHERE key IN ('inflight_batch_id', 'inflight_max_seq')\");\n return context.report;\n }),\n );\n}\n"]}
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sqlite/push.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.Sqlite/G9CSqliteSyncStore.Push.cs: dirty rows in local change order become push frames; the\r\n// result clears exactly the rows that were sent (rows edited meanwhile stay dirty), flags rejections and applies canonical\r\n// server rows.\r\nimport { G9ESyncDirection } from '../abstractions/enums.js';\r\nimport { G9SyncErrorCodes } from '../abstractions/errors.js';\r\nimport { G9Long } from '../abstractions/long.js';\r\nimport { utf8Encode } from '../internal/utf8.js';\r\nimport { G9ApplyReport, type G9PushBatch } from '../client/storeTypes.js';\r\nimport type { G9DtNegotiatedTable, G9DtPushResult, G9DtTableColumns } from '../protocol/dtos.js';\r\nimport { G9EPushRowOp, G9ERowBatchOp } from '../protocol/rowBatch/format.js';\r\nimport { G9RowBatchWriter } from '../protocol/rowBatch/writer.js';\r\nimport { applyFrame, beginApply, endApply } from './apply.js';\r\nimport { completeCommands, readPendingCommands } from './commands.js';\r\nimport { asLong, asNumber, asString } from './connection.js';\r\nimport type { G9SqlValue } from './driver.js';\r\nimport { findByServerName, getLocal, keyValue, meta, nowMs, setMeta, type LocalTable, type StoreInternals } from './internals.js';\r\nimport { quote } from './sql.js';\r\nimport { estimateEncodedBytes, pushSelectExpression, writeLocalValue } from './values.js';\r\n\r\ninterface PushColumn {\r\n name: string;\r\n type: number;\r\n local: number;\r\n}\r\n\r\ninterface PushSection {\r\n table: LocalTable;\r\n negotiated: G9DtNegotiatedTable;\r\n columns: PushColumn[];\r\n writer: G9RowBatchWriter;\r\n select: string;\r\n rows: number;\r\n}\r\n\r\nconst ROW_OVERHEAD = 48;\r\n\r\n/** `BuildPushBatchAsync`: the next batch of pending changes, oldest first, within the row and byte budgets. */\r\nexport async function buildPushBatch(store: StoreInternals, tables: readonly G9DtNegotiatedTable[], maxRows: number, maxBytes: number): Promise<G9PushBatch | null> {\r\n store.ensureInitialized();\r\n const uploadable = new Map<number, { table: LocalTable; negotiated: G9DtNegotiatedTable; columns: PushColumn[] }>();\r\n for (const negotiated of tables) {\r\n if (negotiated.direction === G9ESyncDirection.DownloadOnly) continue;\r\n const local = findByServerName(store, negotiated.name);\r\n if (!local) continue;\r\n const readOnly = new Set<string>();\r\n for (const c of negotiated.readOnlyColumns) readOnly.add(c.toLowerCase());\r\n for (const c of negotiated.computedColumns) readOnly.add(c.toLowerCase());\r\n const columns = negotiated.columns\r\n .filter((c) => !readOnly.has(c.name.toLowerCase()) && local.model.indexOf(c.name) >= 0)\r\n .map((c) => ({ name: c.name, type: c.type, local: local.model.indexOf(c.name) }));\r\n uploadable.set(local.tid, { table: local, negotiated, columns });\r\n }\r\n\r\n return store.writeLock.run(() =>\r\n store.writer().transaction('immediate', async () => {\r\n const connection = store.writer();\r\n const inflightBatch = await meta(connection, 'inflight_batch_id');\r\n const inflightMax = await meta(connection, 'inflight_max_seq');\r\n const offsetText = await meta(connection, 'server_offset_ms');\r\n const offsetMs = offsetText !== null && /^[+-]?\\d+$/.test(offsetText) ? Number(offsetText) : 0;\r\n\r\n const tids = Array.from(uploadable.keys());\r\n // `+tid`: the unary plus keeps the tid list from driving the plan. Without it SQLite searches the primary key by\r\n // tid — every row of every uploadable table (486k on a farm device, 16 s on the bridge) — and sorts them, instead\r\n // of walking the partial g9_rows_dirty index, which holds only the pending rows and is already in local_seq order.\r\n const sql =\r\n 'SELECT tid, pk, dirty, dirty_mask, server_ver, local_seq, coalesce(hlc_ms, 0) FROM g9_rows WHERE dirty <> 0 AND rejected = 0 AND +tid IN (' +\r\n tids.join(',') +\r\n ')' +\r\n (inflightMax === null ? '' : ' AND local_seq <= $imax') +\r\n ' ORDER BY local_seq LIMIT $max';\r\n const commands = await readPendingCommands(store, connection, inflightBatch, Math.max(1, maxRows));\r\n const pending =\r\n uploadable.size === 0\r\n ? []\r\n : await connection.query(sql, inflightMax === null ? { $max: Math.max(1, maxRows) } : { $max: Math.max(1, maxRows), $imax: Number(inflightMax) });\r\n const rows = pending.map((r) => ({\r\n tid: asNumber(r[0]),\r\n key: asString(r[1]),\r\n dirty: asNumber(r[2]),\r\n mask: asLong(r[3]),\r\n base: asNumber(r[4]),\r\n seq: asNumber(r[5]),\r\n hlc: asNumber(r[6]),\r\n }));\r\n\r\n if (rows.length === 0 && commands.length === 0) {\r\n if (inflightBatch !== null) {\r\n // Everything the in-flight batch carried has been resolved another way; forget it.\r\n await connection.exec(\"DELETE FROM g9_meta WHERE key IN ('inflight_batch_id', 'inflight_max_seq')\");\r\n }\r\n return null;\r\n }\r\n\r\n // Rows are encoded in local_seq order and the batch ends at the first row past the byte budget, so a batch is always\r\n // a PREFIX of the pending changes. One section (frame) per table.\r\n const sections = new Map<number, PushSection>();\r\n let included = 0;\r\n let includedMaxSequence = 0;\r\n let budgetUsed = 0;\r\n let truncated = false;\r\n const tooLarge: { tid: number; key: string; bytes: number }[] = [];\r\n for (const row of rows) {\r\n const entry = uploadable.get(row.tid);\r\n if (!entry) continue;\r\n let section = sections.get(row.tid);\r\n if (!section) {\r\n const select =\r\n entry.columns.length === 0\r\n ? `SELECT 1 FROM ${entry.table.quoted} WHERE ${entry.table.keyQuoted} = $k`\r\n : `SELECT ${entry.columns.map((c) => pushSelectExpression(quote(c.name), c.type)).join(', ')} FROM ${entry.table.quoted} WHERE ${entry.table.keyQuoted} = $k`;\r\n const writer = new G9RowBatchWriter();\r\n writer.beginSection(\r\n G9ERowBatchOp.Push,\r\n entry.negotiated.tableId,\r\n entry.table.model.keyType,\r\n entry.columns.map((c) => c.type),\r\n );\r\n section = { table: entry.table, negotiated: entry.negotiated, columns: entry.columns, writer, select, rows: 0 };\r\n sections.set(row.tid, section);\r\n }\r\n\r\n const hlc = row.hlc === 0 ? 0 : row.hlc + offsetMs;\r\n const keyBytes = utf8Encode(row.key).length;\r\n if (row.dirty === 2) {\r\n const deleteBytes = ROW_OVERHEAD + keyBytes;\r\n if (included > 0 && budgetUsed + deleteBytes > maxBytes) {\r\n truncated = true;\r\n break;\r\n }\r\n section.writer.beginPushRow(row.key, G9EPushRowOp.Delete, row.seq, row.base, G9Long.ZERO, hlc);\r\n section.writer.endRow();\r\n section.rows++;\r\n included++;\r\n includedMaxSequence = row.seq;\r\n budgetUsed += deleteBytes;\r\n continue;\r\n }\r\n\r\n const found = await connection.query(section.select, { $k: keyValue(section.table, row.key) });\r\n const values = found[0];\r\n if (!values) {\r\n section.writer.beginPushRow(row.key, G9EPushRowOp.Delete, row.seq, row.base, G9Long.ZERO, hlc);\r\n section.writer.endRow();\r\n section.rows++;\r\n included++;\r\n includedMaxSequence = row.seq;\r\n budgetUsed += ROW_OVERHEAD + keyBytes;\r\n continue;\r\n }\r\n\r\n let rowBytes = ROW_OVERHEAD + keyBytes;\r\n for (let j = 0; j < section.columns.length; j++) rowBytes += estimateEncodedBytes(values[j] as G9SqlValue, (section.columns[j] as PushColumn).type);\r\n if (rowBytes > maxBytes) {\r\n // Can never fit, whatever else the batch carries: reject it here so it does not block every later push.\r\n tooLarge.push({ tid: row.tid, key: row.key, bytes: rowBytes });\r\n continue;\r\n }\r\n if (included > 0 && budgetUsed + rowBytes > maxBytes) {\r\n truncated = true;\r\n break;\r\n }\r\n\r\n let pushMask = G9Long.ZERO;\r\n for (let j = 0; j < section.columns.length; j++) {\r\n if (row.mask.testBit((section.columns[j] as PushColumn).local)) pushMask = pushMask.or(G9Long.ONE.shiftLeft(j));\r\n }\r\n section.writer.beginPushRow(row.key, G9EPushRowOp.Upsert, row.seq, row.base, pushMask, hlc);\r\n for (let j = 0; j < section.columns.length; j++) writeLocalValue(section.writer, values[j] as G9SqlValue, (section.columns[j] as PushColumn).type, store.options);\r\n section.writer.endRow();\r\n section.rows++;\r\n included++;\r\n includedMaxSequence = row.seq;\r\n budgetUsed += rowBytes;\r\n }\r\n\r\n for (const { tid, key, bytes } of tooLarge) {\r\n await connection.exec('UPDATE g9_rows SET rejected = 1 WHERE tid = $t AND pk = $pk', { $t: tid, $pk: key });\r\n await connection.exec(\r\n 'INSERT OR REPLACE INTO g9_rejections (tid, pk, code, message, sql_state, constraint_name, column_name, details, at_utc) ' +\r\n 'VALUES ($t, $pk, $code, $message, NULL, NULL, NULL, NULL, $at)',\r\n {\r\n $t: tid,\r\n $pk: key,\r\n $code: G9SyncErrorCodes.RejectTooLarge,\r\n $message: `The row needs about ${bytes} bytes; the server accepts at most ${maxBytes} bytes per push.`,\r\n $at: nowMs(),\r\n },\r\n );\r\n }\r\n\r\n if (included === 0 && commands.length === 0) {\r\n if (tooLarge.length === 0) return null;\r\n return { batchId: 0, maxSequence: 0, frames: [], tables: [], rowCount: 0, truncated: false, rejectedLocally: tooLarge.length, commands: [] };\r\n }\r\n\r\n const frames: Uint8Array[] = [];\r\n const usedTables: G9DtTableColumns[] = [];\r\n sections.forEach((section) => {\r\n if (section.rows === 0) return;\r\n section.writer.endSection();\r\n frames.push(section.writer.toFrame({ compressor: store.options.frameCompressor }));\r\n usedTables.push({ tableId: section.negotiated.tableId, columns: section.columns.map((c) => c.name) });\r\n });\r\n\r\n let batchId: number;\r\n let maxSequence: number;\r\n if (inflightBatch !== null) {\r\n batchId = Number(inflightBatch);\r\n maxSequence = Number(inflightMax);\r\n } else {\r\n batchId = Number((await meta(connection, 'next_batch_id')) ?? '1');\r\n maxSequence = includedMaxSequence;\r\n await setMeta(connection, 'next_batch_id', String(batchId + 1));\r\n await setMeta(connection, 'inflight_batch_id', String(batchId));\r\n await setMeta(connection, 'inflight_max_seq', String(maxSequence));\r\n }\r\n for (const item of commands) {\r\n await connection.exec('UPDATE g9_commands SET batch_id = $b WHERE command_id = $id', { $b: batchId, $id: item.commandId });\r\n }\r\n return { batchId, maxSequence, frames, tables: usedTables, rowCount: included, truncated, rejectedLocally: tooLarge.length, commands };\r\n }),\r\n );\r\n}\r\n\r\n/** `ForgetUploadedRowsAsync`: removes uploaded rows of an UPLOAD-ONLY table without uploading a delete. */\r\nexport async function forgetUploadedRows(store: StoreInternals, localTable: string, keys: readonly string[] | null): Promise<number> {\r\n store.ensureInitialized();\r\n const table = getLocal(store, localTable);\r\n if (!table.negotiated || table.negotiated.direction !== G9ESyncDirection.UploadOnly) {\r\n throw new Error(`'${localTable}' is not upload-only: deleting its rows locally is a change the server must receive.`);\r\n }\r\n return store.writeLock.run(() =>\r\n store.writer().transaction('immediate', async () => {\r\n const connection = store.writer();\r\n await connection.exec('UPDATE g9_ctx SET applying = 1 WHERE id = 1'); // a library write: not captured\r\n await connection.exec('CREATE TEMP TABLE IF NOT EXISTS g9_forget (pk TEXT PRIMARY KEY); DELETE FROM g9_forget');\r\n if (keys === null) {\r\n await connection.exec('INSERT INTO g9_forget (pk) SELECT pk FROM g9_rows WHERE tid = $t AND dirty = 0', { $t: table.tid });\r\n } else {\r\n for (const key of keys) {\r\n await connection.exec('INSERT OR IGNORE INTO g9_forget (pk) SELECT pk FROM g9_rows WHERE tid = $t AND pk = $pk AND dirty = 0', { $t: table.tid, $pk: key });\r\n }\r\n }\r\n const forgotten = asNumber(await connection.scalar('SELECT count(*) FROM g9_forget'));\r\n await connection.exec(`DELETE FROM ${table.quoted} WHERE CAST(${table.keyQuoted} AS TEXT) IN (SELECT pk FROM g9_forget)`);\r\n await connection.exec('DELETE FROM g9_rows WHERE tid = $t AND pk IN (SELECT pk FROM g9_forget); DELETE FROM g9_forget', { $t: table.tid });\r\n await connection.exec('UPDATE g9_ctx SET applying = 0 WHERE id = 1');\r\n return forgotten;\r\n }),\r\n );\r\n}\r\n\r\n/** `ApplyPushResultAsync`. */\r\nexport async function applyPushResult(store: StoreInternals, batch: G9PushBatch, result: G9DtPushResult, signal?: AbortSignal): Promise<G9ApplyReport> {\r\n store.ensureInitialized();\r\n return store.writeLock.run(() =>\r\n store.writer().transaction('immediate', async () => {\r\n const connection = store.writer();\r\n // Before BeginApply: finished commands release their rows, so the canonical rows below replace the optimistic ones.\r\n const completed = await completeCommands(connection, result.commandResults);\r\n const context = await beginApply(store, connection, { dirtyAfterSequence: batch.maxSequence, backfills: [], signal });\r\n context.report.commandsCompleted = completed;\r\n\r\n const acceptSql =\r\n 'UPDATE g9_rows SET server_ver = $v, ' +\r\n 'dirty = CASE WHEN local_seq <= $m THEN 0 ELSE dirty END, ' +\r\n 'dirty_mask = CASE WHEN local_seq <= $m THEN 0 ELSE dirty_mask END, ' +\r\n 'deleted = CASE WHEN local_seq <= $m AND dirty = 2 THEN 1 ELSE deleted END, ' +\r\n 'rejected = 0 WHERE tid = $t AND pk = $pk; ' +\r\n 'DELETE FROM g9_rejections WHERE tid = $t AND pk = $pk';\r\n for (const accepted of result.accepted) {\r\n const table = store.byServerId.get(accepted.tableId);\r\n if (!table) continue;\r\n for (let i = 0; i < accepted.keys.length; i++) {\r\n await context.queue(acceptSql, { $v: i < accepted.versions.length ? (accepted.versions[i] as number) : 0, $m: batch.maxSequence, $t: table.tid, $pk: accepted.keys[i] as string });\r\n context.report.accepted++;\r\n }\r\n }\r\n\r\n const rejectSql =\r\n 'UPDATE g9_rows SET rejected = 1 WHERE tid = $t AND pk = $pk AND local_seq <= $m; ' +\r\n 'INSERT OR REPLACE INTO g9_rejections (tid, pk, code, message, sql_state, constraint_name, column_name, details, at_utc) ' +\r\n 'VALUES ($t, $pk, $code, $message, $state, $constraint, $column, $details, $now)';\r\n const now = nowMs();\r\n for (const rejection of result.rejections) {\r\n const table = store.byServerId.get(rejection.tableId);\r\n if (!table) continue;\r\n await context.queue(rejectSql, {\r\n $t: table.tid,\r\n $pk: rejection.key,\r\n $m: batch.maxSequence,\r\n $code: rejection.code,\r\n $message: rejection.message ?? null,\r\n $state: rejection.sqlState ?? null,\r\n $constraint: rejection.constraint ?? null,\r\n $column: rejection.column ?? null,\r\n $details: rejection.details ?? null,\r\n $now: now,\r\n });\r\n context.report.rejected++;\r\n }\r\n\r\n context.report.conflicts = result.conflicts.length;\r\n await context.flush();\r\n for (const frame of result.canonicalFrames) await applyFrame(store, context, frame, null);\r\n\r\n await endApply(context);\r\n await connection.exec(\"DELETE FROM g9_meta WHERE key IN ('inflight_batch_id', 'inflight_max_seq')\");\r\n return context.report;\r\n }),\r\n );\r\n}\r\n"]}