@g9tm/syncdata 1.5.0 → 1.5.2

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 (59) 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.js.map +1 -1
  15. package/dist/client/model.js.map +1 -1
  16. package/dist/client/progress.js.map +1 -1
  17. package/dist/client/runs.js.map +1 -1
  18. package/dist/client/storeTypes.js.map +1 -1
  19. package/dist/client/transport.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/internal/abort.js.map +1 -1
  24. package/dist/internal/base64.js.map +1 -1
  25. package/dist/internal/dotnetFormat.js.map +1 -1
  26. package/dist/internal/md5.js.map +1 -1
  27. package/dist/internal/sha256.js.map +1 -1
  28. package/dist/internal/utf8.js.map +1 -1
  29. package/dist/node/index.js.map +1 -1
  30. package/dist/node/snapshotFileSink.js.map +1 -1
  31. package/dist/node/sqliteDriver.js.map +1 -1
  32. package/dist/protocol/dtos.js.map +1 -1
  33. package/dist/protocol/protocol.js.map +1 -1
  34. package/dist/protocol/rowBatch/columnLayout.js.map +1 -1
  35. package/dist/protocol/rowBatch/format.js.map +1 -1
  36. package/dist/protocol/rowBatch/reader.js.map +1 -1
  37. package/dist/protocol/rowBatch/writer.js.map +1 -1
  38. package/dist/protocol/wire.js.map +1 -1
  39. package/dist/signalr/index.js.map +1 -1
  40. package/dist/signalr/protocols.js.map +1 -1
  41. package/dist/signalr/transport.d.ts +7 -3
  42. package/dist/signalr/transport.js +2 -1
  43. package/dist/signalr/transport.js.map +1 -1
  44. package/dist/sqlite/apply.js.map +1 -1
  45. package/dist/sqlite/commands.js.map +1 -1
  46. package/dist/sqlite/connection.js.map +1 -1
  47. package/dist/sqlite/driver.js.map +1 -1
  48. package/dist/sqlite/index.js.map +1 -1
  49. package/dist/sqlite/internals.js.map +1 -1
  50. package/dist/sqlite/options.js.map +1 -1
  51. package/dist/sqlite/push.js.map +1 -1
  52. package/dist/sqlite/query.js.map +1 -1
  53. package/dist/sqlite/revocation.js.map +1 -1
  54. package/dist/sqlite/sql.js +113 -113
  55. package/dist/sqlite/sql.js.map +1 -1
  56. package/dist/sqlite/store.js.map +1 -1
  57. package/dist/sqlite/values.js.map +1 -1
  58. package/dist/testing/index.js.map +1 -1
  59. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/client/model.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client/Model/G9CSyncClientModel.cs: the client model and its builder (the .NET source generator\n// has no TypeScript twin; build the model in code, or from the same table list the .NET app generates).\nimport { G9ESyncColumnType, columnTypeName, isColumnType } from '../abstractions/enums.js';\nimport { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';\nimport { G9SyncKey } from '../abstractions/key.js';\nimport type { G9DtClientTableModel } from '../protocol/dtos.js';\n\n/** A synced column as the client build understands it. */\nexport interface G9SyncClientColumn {\n readonly name: string;\n readonly type: G9ESyncColumnType;\n readonly nullable: boolean;\n}\n\n/** A secondary index the client store creates. */\nexport interface G9SyncClientIndex {\n readonly name: string;\n readonly columns: readonly string[];\n readonly unique: boolean;\n}\n\n/**\n * A synced table of the client model. Column order is the bit order of the local dirty mask; it is local and never sent\n * over the wire (the push maps bits to the negotiated column order).\n */\nexport class G9SyncClientTable {\n /** Server logical name, e.g. `Operation.Pot`. */\n readonly serverName: string;\n /** Local table name, e.g. `Pot`. */\n readonly localName: string;\n readonly keyColumn: string;\n readonly keyType: G9ESyncColumnType;\n /** Synced columns except the key. */\n readonly columns: readonly G9SyncClientColumn[];\n readonly indexes: readonly G9SyncClientIndex[];\n private readonly _index: { [lowerName: string]: number } = {};\n\n constructor(\n serverName: string,\n localName: string,\n keyColumn: string,\n keyType: G9ESyncColumnType,\n columns: readonly G9SyncClientColumn[],\n indexes: readonly G9SyncClientIndex[],\n ) {\n this.serverName = serverName;\n this.localName = localName;\n this.keyColumn = keyColumn;\n this.keyType = keyType;\n this.columns = columns;\n this.indexes = indexes;\n for (let i = 0; i < columns.length; i++) this._index[(columns[i] as G9SyncClientColumn).name.toLowerCase()] = i;\n }\n\n /** Index of a column (its dirty-mask bit), or -1. Case-insensitive, like .NET's OrdinalIgnoreCase lookup. */\n indexOf(column: string): number {\n const index = this._index[column.toLowerCase()];\n return index === undefined ? -1 : index;\n }\n\n toWire(): G9DtClientTableModel {\n return {\n name: this.serverName,\n keyColumn: this.keyColumn,\n keyType: this.keyType,\n columns: this.columns.map((c) => ({ name: c.name, type: c.type, nullable: c.nullable })),\n };\n }\n}\n\n/** The immutable client model (`G9CSyncClientModel`). Build it with {@link G9SyncClientModelBuilder}. */\nexport class G9SyncClientModel {\n readonly tables: readonly G9SyncClientTable[];\n private readonly _byServer: { [lower: string]: G9SyncClientTable } = {};\n private readonly _byLocal: { [lower: string]: G9SyncClientTable } = {};\n\n constructor(tables: readonly G9SyncClientTable[]) {\n this.tables = tables;\n for (const table of tables) {\n this._byServer[table.serverName.toLowerCase()] = table;\n this._byLocal[table.localName.toLowerCase()] = table;\n }\n }\n\n findByServerName(serverName: string): G9SyncClientTable | null {\n return this._byServer[serverName.toLowerCase()] ?? null;\n }\n\n findByLocalName(localName: string): G9SyncClientTable | null {\n return this._byLocal[localName.toLowerCase()] ?? null;\n }\n}\n\n/** Builds the client model (`G9CSyncClientModelBuilder`). */\nexport class G9SyncClientModelBuilder {\n static readonly MaxColumns = 62;\n private readonly _tables: { server: string; local: string; builder: G9SyncClientTableBuilder }[] = [];\n\n table(serverName: string, localName: string, configure: (table: G9SyncClientTableBuilder) => void): this {\n if (typeof serverName !== 'string' || serverName.trim() === '') throw new TypeError('A server table name is required.');\n if (typeof localName !== 'string' || localName.trim() === '') throw new TypeError('A local table name is required.');\n const builder = new G9SyncClientTableBuilder();\n configure(builder);\n this._tables.push({ server: serverName, local: localName, builder });\n return this;\n }\n\n build(): G9SyncClientModel {\n const errors: string[] = [];\n const tables: G9SyncClientTable[] = [];\n const servers: { [lower: string]: true } = {};\n const locals: { [lower: string]: true } = {};\n for (const { server, local, builder } of this._tables) {\n if (servers[server.toLowerCase()]) errors.push(`Server table '${server}' is mapped twice.`);\n servers[server.toLowerCase()] = true;\n if (locals[local.toLowerCase()]) errors.push(`Local table '${local}' is mapped twice.`);\n locals[local.toLowerCase()] = true;\n if (local.toLowerCase().indexOf('g9_') === 0) errors.push(`Local table '${local}' uses the reserved prefix g9_.`);\n const table = builder.build(server, local, errors);\n if (table) tables.push(table);\n }\n if (errors.length > 0) {\n throw new G9SyncException(G9SyncErrorCodes.ModelInvalid, 'The G9SyncData client model is invalid:\\n' + errors.map((e) => ' - ' + e).join('\\n'));\n }\n return new G9SyncClientModel(tables);\n }\n}\n\nexport class G9SyncClientTableBuilder {\n private readonly _columns: G9SyncClientColumn[] = [];\n private readonly _indexes: G9SyncClientIndex[] = [];\n private _key: string | null = null;\n private _keyType: number = G9ESyncColumnType.Guid;\n\n key(column: string, type: G9ESyncColumnType = G9ESyncColumnType.Guid): this {\n if (typeof column !== 'string' || column.trim() === '') throw new TypeError('A key column is required.');\n this._key = column;\n this._keyType = type;\n return this;\n }\n\n column(name: string, type: G9ESyncColumnType, nullable = true): this {\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A column name is required.');\n this._columns.push({ name, type, nullable });\n return this;\n }\n\n index(name: string | null, unique: boolean, ...columns: string[]): this {\n this._indexes.push({ name: name ?? '', columns, unique });\n return this;\n }\n\n /** @internal */\n build(server: string, local: string, errors: string[]): G9SyncClientTable | null {\n const before = errors.length;\n if (this._key === null) errors.push(`${local}: no key.`);\n else if (!G9SyncKey.isSupportedKeyType(this._keyType)) errors.push(`${local}: key type ${columnTypeName(this._keyType)} is not supported.`);\n if (this._columns.length > G9SyncClientModelBuilder.MaxColumns) {\n errors.push(`${local}: ${this._columns.length} columns; the maximum is ${G9SyncClientModelBuilder.MaxColumns}.`);\n }\n const names: { [lower: string]: true } = {};\n if (this._key !== null) names[this._key.toLowerCase()] = true;\n for (const column of this._columns) {\n if (names[column.name.toLowerCase()]) errors.push(`${local}: column '${column.name}' is declared twice (or as the key).`);\n names[column.name.toLowerCase()] = true;\n if (!isColumnType(column.type)) errors.push(`${local}.${column.name}: invalid type.`);\n }\n const indexes: G9SyncClientIndex[] = [];\n for (const index of this._indexes) {\n if (index.columns.length === 0) errors.push(`${local}: an index has no columns.`);\n for (const column of index.columns) {\n if (!names[column.toLowerCase()]) errors.push(`${local}: index column '${column}' is not a synced column.`);\n }\n const name = index.name.trim() === '' ? 'IX_' + local + '_' + index.columns.join('_') : index.name;\n indexes.push({ name, columns: index.columns.slice(), unique: index.unique });\n }\n return errors.length > before ? null : new G9SyncClientTable(server, local, this._key as string, this._keyType as G9ESyncColumnType, this._columns.slice(), indexes);\n }\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/client/model.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client/Model/G9CSyncClientModel.cs: the client model and its builder (the .NET source generator\r\n// has no TypeScript twin; build the model in code, or from the same table list the .NET app generates).\r\nimport { G9ESyncColumnType, columnTypeName, isColumnType } from '../abstractions/enums.js';\r\nimport { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';\r\nimport { G9SyncKey } from '../abstractions/key.js';\r\nimport type { G9DtClientTableModel } from '../protocol/dtos.js';\r\n\r\n/** A synced column as the client build understands it. */\r\nexport interface G9SyncClientColumn {\r\n readonly name: string;\r\n readonly type: G9ESyncColumnType;\r\n readonly nullable: boolean;\r\n}\r\n\r\n/** A secondary index the client store creates. */\r\nexport interface G9SyncClientIndex {\r\n readonly name: string;\r\n readonly columns: readonly string[];\r\n readonly unique: boolean;\r\n}\r\n\r\n/**\r\n * A synced table of the client model. Column order is the bit order of the local dirty mask; it is local and never sent\r\n * over the wire (the push maps bits to the negotiated column order).\r\n */\r\nexport class G9SyncClientTable {\r\n /** Server logical name, e.g. `Operation.Pot`. */\r\n readonly serverName: string;\r\n /** Local table name, e.g. `Pot`. */\r\n readonly localName: string;\r\n readonly keyColumn: string;\r\n readonly keyType: G9ESyncColumnType;\r\n /** Synced columns except the key. */\r\n readonly columns: readonly G9SyncClientColumn[];\r\n readonly indexes: readonly G9SyncClientIndex[];\r\n private readonly _index: { [lowerName: string]: number } = {};\r\n\r\n constructor(\r\n serverName: string,\r\n localName: string,\r\n keyColumn: string,\r\n keyType: G9ESyncColumnType,\r\n columns: readonly G9SyncClientColumn[],\r\n indexes: readonly G9SyncClientIndex[],\r\n ) {\r\n this.serverName = serverName;\r\n this.localName = localName;\r\n this.keyColumn = keyColumn;\r\n this.keyType = keyType;\r\n this.columns = columns;\r\n this.indexes = indexes;\r\n for (let i = 0; i < columns.length; i++) this._index[(columns[i] as G9SyncClientColumn).name.toLowerCase()] = i;\r\n }\r\n\r\n /** Index of a column (its dirty-mask bit), or -1. Case-insensitive, like .NET's OrdinalIgnoreCase lookup. */\r\n indexOf(column: string): number {\r\n const index = this._index[column.toLowerCase()];\r\n return index === undefined ? -1 : index;\r\n }\r\n\r\n toWire(): G9DtClientTableModel {\r\n return {\r\n name: this.serverName,\r\n keyColumn: this.keyColumn,\r\n keyType: this.keyType,\r\n columns: this.columns.map((c) => ({ name: c.name, type: c.type, nullable: c.nullable })),\r\n };\r\n }\r\n}\r\n\r\n/** The immutable client model (`G9CSyncClientModel`). Build it with {@link G9SyncClientModelBuilder}. */\r\nexport class G9SyncClientModel {\r\n readonly tables: readonly G9SyncClientTable[];\r\n private readonly _byServer: { [lower: string]: G9SyncClientTable } = {};\r\n private readonly _byLocal: { [lower: string]: G9SyncClientTable } = {};\r\n\r\n constructor(tables: readonly G9SyncClientTable[]) {\r\n this.tables = tables;\r\n for (const table of tables) {\r\n this._byServer[table.serverName.toLowerCase()] = table;\r\n this._byLocal[table.localName.toLowerCase()] = table;\r\n }\r\n }\r\n\r\n findByServerName(serverName: string): G9SyncClientTable | null {\r\n return this._byServer[serverName.toLowerCase()] ?? null;\r\n }\r\n\r\n findByLocalName(localName: string): G9SyncClientTable | null {\r\n return this._byLocal[localName.toLowerCase()] ?? null;\r\n }\r\n}\r\n\r\n/** Builds the client model (`G9CSyncClientModelBuilder`). */\r\nexport class G9SyncClientModelBuilder {\r\n static readonly MaxColumns = 62;\r\n private readonly _tables: { server: string; local: string; builder: G9SyncClientTableBuilder }[] = [];\r\n\r\n table(serverName: string, localName: string, configure: (table: G9SyncClientTableBuilder) => void): this {\r\n if (typeof serverName !== 'string' || serverName.trim() === '') throw new TypeError('A server table name is required.');\r\n if (typeof localName !== 'string' || localName.trim() === '') throw new TypeError('A local table name is required.');\r\n const builder = new G9SyncClientTableBuilder();\r\n configure(builder);\r\n this._tables.push({ server: serverName, local: localName, builder });\r\n return this;\r\n }\r\n\r\n build(): G9SyncClientModel {\r\n const errors: string[] = [];\r\n const tables: G9SyncClientTable[] = [];\r\n const servers: { [lower: string]: true } = {};\r\n const locals: { [lower: string]: true } = {};\r\n for (const { server, local, builder } of this._tables) {\r\n if (servers[server.toLowerCase()]) errors.push(`Server table '${server}' is mapped twice.`);\r\n servers[server.toLowerCase()] = true;\r\n if (locals[local.toLowerCase()]) errors.push(`Local table '${local}' is mapped twice.`);\r\n locals[local.toLowerCase()] = true;\r\n if (local.toLowerCase().indexOf('g9_') === 0) errors.push(`Local table '${local}' uses the reserved prefix g9_.`);\r\n const table = builder.build(server, local, errors);\r\n if (table) tables.push(table);\r\n }\r\n if (errors.length > 0) {\r\n throw new G9SyncException(G9SyncErrorCodes.ModelInvalid, 'The G9SyncData client model is invalid:\\n' + errors.map((e) => ' - ' + e).join('\\n'));\r\n }\r\n return new G9SyncClientModel(tables);\r\n }\r\n}\r\n\r\nexport class G9SyncClientTableBuilder {\r\n private readonly _columns: G9SyncClientColumn[] = [];\r\n private readonly _indexes: G9SyncClientIndex[] = [];\r\n private _key: string | null = null;\r\n private _keyType: number = G9ESyncColumnType.Guid;\r\n\r\n key(column: string, type: G9ESyncColumnType = G9ESyncColumnType.Guid): this {\r\n if (typeof column !== 'string' || column.trim() === '') throw new TypeError('A key column is required.');\r\n this._key = column;\r\n this._keyType = type;\r\n return this;\r\n }\r\n\r\n column(name: string, type: G9ESyncColumnType, nullable = true): this {\r\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A column name is required.');\r\n this._columns.push({ name, type, nullable });\r\n return this;\r\n }\r\n\r\n index(name: string | null, unique: boolean, ...columns: string[]): this {\r\n this._indexes.push({ name: name ?? '', columns, unique });\r\n return this;\r\n }\r\n\r\n /** @internal */\r\n build(server: string, local: string, errors: string[]): G9SyncClientTable | null {\r\n const before = errors.length;\r\n if (this._key === null) errors.push(`${local}: no key.`);\r\n else if (!G9SyncKey.isSupportedKeyType(this._keyType)) errors.push(`${local}: key type ${columnTypeName(this._keyType)} is not supported.`);\r\n if (this._columns.length > G9SyncClientModelBuilder.MaxColumns) {\r\n errors.push(`${local}: ${this._columns.length} columns; the maximum is ${G9SyncClientModelBuilder.MaxColumns}.`);\r\n }\r\n const names: { [lower: string]: true } = {};\r\n if (this._key !== null) names[this._key.toLowerCase()] = true;\r\n for (const column of this._columns) {\r\n if (names[column.name.toLowerCase()]) errors.push(`${local}: column '${column.name}' is declared twice (or as the key).`);\r\n names[column.name.toLowerCase()] = true;\r\n if (!isColumnType(column.type)) errors.push(`${local}.${column.name}: invalid type.`);\r\n }\r\n const indexes: G9SyncClientIndex[] = [];\r\n for (const index of this._indexes) {\r\n if (index.columns.length === 0) errors.push(`${local}: an index has no columns.`);\r\n for (const column of index.columns) {\r\n if (!names[column.toLowerCase()]) errors.push(`${local}: index column '${column}' is not a synced column.`);\r\n }\r\n const name = index.name.trim() === '' ? 'IX_' + local + '_' + index.columns.join('_') : index.name;\r\n indexes.push({ name, columns: index.columns.slice(), unique: index.unique });\r\n }\r\n return errors.length > before ? null : new G9SyncClientTable(server, local, this._key as string, this._keyType as G9ESyncColumnType, this._columns.slice(), indexes);\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/client/progress.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Client/Progress/G9DtSyncProgress.cs and G9CSyncProgressTracker.cs\n// (AiGuides/09-Progress-Model.md): monotonic progress from phase transitions and row/byte counts.\n\n/** Phases of a sync run, in execution order (`G9ESyncPhase`). */\nexport const G9ESyncPhase = {\n Queued: 0,\n Connecting: 1,\n Pushing: 2,\n Reconciling: 3,\n Planning: 4,\n Downloading: 5,\n Applying: 6,\n PostStep: 7,\n Completed: 8,\n Canceled: 9,\n Failed: 10,\n} as const;\nexport type G9ESyncPhase = (typeof G9ESyncPhase)[keyof typeof G9ESyncPhase];\n\nconst PHASE_NAMES = ['Queued', 'Connecting', 'Pushing', 'Reconciling', 'Planning', 'Downloading', 'Applying', 'PostStep', 'Completed', 'Canceled', 'Failed'];\n\n/** The .NET enum member name of a phase (the statistics and PhaseMs keys), e.g. `Downloading`. */\nexport function phaseName(phase: number): string {\n return PHASE_NAMES[phase] ?? String(phase);\n}\n\n/**\n * One progress sample. `overall` is monotonic within a run and reaches 1 only when the run completed. The library emits\n * numbers and phases; localising them is the app's job.\n */\nexport interface G9DtSyncProgress {\n runId: string;\n phase: G9ESyncPhase;\n /** 0..1, monotonic. */\n overall: number;\n /** 0..1 inside the phase. */\n phaseFraction: number;\n rowsDone: number;\n rowsTotal: number;\n bytesDone: number;\n bytesTotal: number;\n subscriptionKey: string | null;\n table: string | null;\n rowsPerSecond: number;\n /** Estimated milliseconds to completion of the run, or null while unknown. */\n etaMs: number | null;\n queuedBehind: number;\n postStepName: string | null;\n cancelPending: boolean;\n}\n\ninterface PlanEntry {\n phase: G9ESyncPhase;\n name: string | null;\n expectedMs: number;\n}\n\n/**\n * Turns phase transitions and counts into monotonic progress. Each phase entered gets a span of the REMAINING bar in\n * proportion to its expected share of the remaining work, so monotonicity holds by construction; a phase without a\n * real signal creeps toward 90% of its span along an exponential curve scaled by its expected duration.\n */\nexport class G9SyncProgressTracker {\n private readonly _runId: string;\n private readonly _publish: (progress: G9DtSyncProgress) => void;\n private readonly _queuedBehind: () => number;\n private readonly _minIntervalMs: number;\n private readonly _plan: PlanEntry[] = [];\n private readonly _durations: { [key: string]: number } = {};\n private readonly _runStart = Date.now();\n private _phaseStart = Date.now();\n private _timer: ReturnType<typeof setInterval> | null = null;\n\n private _phase: G9ESyncPhase = G9ESyncPhase.Queued;\n private _postStep: string | null = null;\n private _table: string | null = null;\n private _subscription: string | null = null;\n private _base = 0;\n private _span = 0;\n private _overall = 0;\n private _fraction = 0;\n private _phaseExpectedMs = 0;\n private _rowsDone = 0;\n private _rowsTotal = 0;\n private _bytesDone = 0;\n private _bytesTotal = 0;\n private _lastPublish = 0;\n private _realSignal = false;\n private _terminal = false;\n private _cancelPending = false;\n private _disposed = false;\n private _lastPublished: G9DtSyncProgress | null = null;\n\n constructor(runId: string, publish: (progress: G9DtSyncProgress) => void, queuedBehind: () => number, maxHz: number) {\n this._runId = runId;\n this._publish = publish;\n this._queuedBehind = queuedBehind;\n this._minIntervalMs = maxHz <= 0 ? 0 : 1000 / maxHz;\n }\n\n get overall(): number {\n return this._overall;\n }\n\n /** Measured milliseconds per phase (post steps keyed `PostStep:name`). */\n get durations(): { [key: string]: number } {\n const out: { [key: string]: number } = {};\n for (const key of Object.keys(this._durations)) out[key] = this._durations[key] as number;\n return out;\n }\n\n /** Appends a phase to the plan with its expected duration. */\n plan(phase: G9ESyncPhase, expectedMs: number, name: string | null = null): void {\n if (!this._terminal) this._plan.push({ phase, name, expectedMs: Math.max(0, expectedMs) });\n }\n\n /** Updates the expected duration of a planned phase that has not started yet. */\n expect(phase: G9ESyncPhase, expectedMs: number, name: string | null = null): void {\n for (const entry of this._plan) {\n if (entry.phase === phase && entry.name === name) {\n entry.expectedMs = Math.max(0, expectedMs);\n return;\n }\n }\n }\n\n enter(phase: G9ESyncPhase, rowsTotal = 0, bytesTotal = 0, name: string | null = null): void {\n if (this._terminal || this._disposed) return;\n this._close();\n let index = -1;\n for (let i = 0; i < this._plan.length; i++) {\n const entry = this._plan[i] as PlanEntry;\n if (entry.phase === phase && entry.name === name) {\n index = i;\n break;\n }\n }\n let expected = 500;\n if (index >= 0) {\n expected = (this._plan[index] as PlanEntry).expectedMs;\n this._plan.splice(0, index + 1);\n }\n expected = Math.max(1, expected);\n let remaining = 0;\n for (const entry of this._plan) remaining += entry.expectedMs;\n this._base = this._overall;\n this._span = ((1 - this._base) * expected) / (expected + remaining);\n this._phase = phase;\n this._postStep = name;\n this._rowsDone = 0;\n this._rowsTotal = Math.max(0, rowsTotal);\n this._bytesDone = 0;\n this._bytesTotal = Math.max(0, bytesTotal);\n this._fraction = 0;\n this._realSignal = false;\n this._phaseExpectedMs = expected;\n this._phaseStart = Date.now();\n if (this._timer === null) this._timer = setInterval(() => this._creep(), 200);\n this._emit(this._sample(true));\n }\n\n /** Reports absolute counts for the current phase. */\n report(rowsDone: number, bytesDone = -1, table: string | null = null, subscriptionKey: string | null = null): void {\n if (this._terminal || this._disposed) return;\n this._rowsDone = Math.max(0, rowsDone);\n if (bytesDone >= 0) this._bytesDone = bytesDone;\n if (table !== null) this._table = table;\n if (subscriptionKey !== null) this._subscription = subscriptionKey;\n const fraction = this._rowsTotal > 0 ? this._rowsDone / this._rowsTotal : this._bytesTotal > 0 ? this._bytesDone / this._bytesTotal : this._fraction;\n this._realSignal = this._rowsTotal > 0 || this._bytesTotal > 0;\n this._advance(fraction);\n this._emit(this._sample(false));\n }\n\n /** Reports a 0..1 fraction of the current phase (post steps). */\n reportFraction(fraction: number): void {\n if (this._terminal || this._disposed) return;\n this._realSignal = true;\n this._advance(fraction);\n this._emit(this._sample(false));\n }\n\n setCancelPending(): void {\n if (this._terminal || this._disposed) return;\n this._cancelPending = true;\n this._emit(this._sample(true));\n }\n\n complete(terminal: G9ESyncPhase): void {\n if (this._terminal || this._disposed) return;\n this._close();\n this._terminal = true;\n this._stopTimer();\n if (terminal === G9ESyncPhase.Completed) {\n this._overall = 1;\n this._fraction = 1;\n }\n this._phase = terminal;\n this._emit(this._sample(true));\n }\n\n dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._stopTimer();\n }\n\n private _stopTimer(): void {\n if (this._timer !== null) {\n clearInterval(this._timer);\n this._timer = null;\n }\n }\n\n private _creep(): void {\n if (this._terminal || this._disposed || this._realSignal || this._phase === G9ESyncPhase.Queued) return;\n const elapsed = Date.now() - this._phaseStart;\n this._advance(0.9 * (1 - Math.exp(-elapsed / Math.max(100, this._phaseExpectedMs))));\n this._emit(this._sample(false));\n }\n\n private _advance(fraction: number): void {\n const clamped = Math.min(Math.max(fraction, 0), 0.995);\n if (clamped > this._fraction) this._fraction = clamped;\n const overall = Math.min(0.999, this._base + this._span * this._fraction);\n if (overall > this._overall) this._overall = overall;\n }\n\n private _close(): void {\n const phase = this._phase;\n if (phase === G9ESyncPhase.Queued || phase === G9ESyncPhase.Completed || phase === G9ESyncPhase.Canceled || phase === G9ESyncPhase.Failed) return;\n const key = phase === G9ESyncPhase.PostStep ? 'PostStep:' + (this._postStep ?? '') : phaseName(phase);\n this._durations[key] = (this._durations[key] ?? 0) + (Date.now() - this._phaseStart);\n this._overall = Math.max(this._overall, Math.min(0.999, this._base + this._span));\n }\n\n private _sample(force: boolean): G9DtSyncProgress | null {\n const now = Date.now();\n if (!force && now - this._lastPublish < this._minIntervalMs) return null;\n this._lastPublish = now;\n const phaseSeconds = Math.max(0.001, (now - this._phaseStart) / 1000);\n let eta: number | null = null;\n if (this._terminal) eta = 0;\n else if (this._overall > 0.02) eta = ((now - this._runStart) * (1 - this._overall)) / this._overall;\n let queued = 0;\n try {\n queued = this._queuedBehind();\n } catch {\n queued = 0;\n }\n return {\n runId: this._runId,\n phase: this._phase,\n overall: this._overall,\n phaseFraction: this._fraction,\n rowsDone: this._rowsDone,\n rowsTotal: this._rowsTotal,\n bytesDone: this._bytesDone,\n bytesTotal: this._bytesTotal,\n subscriptionKey: this._subscription,\n table: this._table,\n rowsPerSecond: this._rowsDone / phaseSeconds,\n etaMs: eta,\n queuedBehind: queued,\n postStepName: this._postStep,\n cancelPending: this._cancelPending,\n };\n }\n\n /** Publishes a sample unless it would go backwards (lower overall or an earlier phase). */\n private _emit(sample: G9DtSyncProgress | null): void {\n if (sample === null) return;\n const last = this._lastPublished;\n if (last !== null && (sample.overall < last.overall || sample.phase < last.phase)) return;\n this._lastPublished = sample;\n try {\n this._publish(sample);\n } catch {\n // A progress consumer must never break the sync.\n }\n }\n}\n"]}
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/client/progress.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Client/Progress/G9DtSyncProgress.cs and G9CSyncProgressTracker.cs\r\n// (AiGuides/09-Progress-Model.md): monotonic progress from phase transitions and row/byte counts.\r\n\r\n/** Phases of a sync run, in execution order (`G9ESyncPhase`). */\r\nexport const G9ESyncPhase = {\r\n Queued: 0,\r\n Connecting: 1,\r\n Pushing: 2,\r\n Reconciling: 3,\r\n Planning: 4,\r\n Downloading: 5,\r\n Applying: 6,\r\n PostStep: 7,\r\n Completed: 8,\r\n Canceled: 9,\r\n Failed: 10,\r\n} as const;\r\nexport type G9ESyncPhase = (typeof G9ESyncPhase)[keyof typeof G9ESyncPhase];\r\n\r\nconst PHASE_NAMES = ['Queued', 'Connecting', 'Pushing', 'Reconciling', 'Planning', 'Downloading', 'Applying', 'PostStep', 'Completed', 'Canceled', 'Failed'];\r\n\r\n/** The .NET enum member name of a phase (the statistics and PhaseMs keys), e.g. `Downloading`. */\r\nexport function phaseName(phase: number): string {\r\n return PHASE_NAMES[phase] ?? String(phase);\r\n}\r\n\r\n/**\r\n * One progress sample. `overall` is monotonic within a run and reaches 1 only when the run completed. The library emits\r\n * numbers and phases; localising them is the app's job.\r\n */\r\nexport interface G9DtSyncProgress {\r\n runId: string;\r\n phase: G9ESyncPhase;\r\n /** 0..1, monotonic. */\r\n overall: number;\r\n /** 0..1 inside the phase. */\r\n phaseFraction: number;\r\n rowsDone: number;\r\n rowsTotal: number;\r\n bytesDone: number;\r\n bytesTotal: number;\r\n subscriptionKey: string | null;\r\n table: string | null;\r\n rowsPerSecond: number;\r\n /** Estimated milliseconds to completion of the run, or null while unknown. */\r\n etaMs: number | null;\r\n queuedBehind: number;\r\n postStepName: string | null;\r\n cancelPending: boolean;\r\n}\r\n\r\ninterface PlanEntry {\r\n phase: G9ESyncPhase;\r\n name: string | null;\r\n expectedMs: number;\r\n}\r\n\r\n/**\r\n * Turns phase transitions and counts into monotonic progress. Each phase entered gets a span of the REMAINING bar in\r\n * proportion to its expected share of the remaining work, so monotonicity holds by construction; a phase without a\r\n * real signal creeps toward 90% of its span along an exponential curve scaled by its expected duration.\r\n */\r\nexport class G9SyncProgressTracker {\r\n private readonly _runId: string;\r\n private readonly _publish: (progress: G9DtSyncProgress) => void;\r\n private readonly _queuedBehind: () => number;\r\n private readonly _minIntervalMs: number;\r\n private readonly _plan: PlanEntry[] = [];\r\n private readonly _durations: { [key: string]: number } = {};\r\n private readonly _runStart = Date.now();\r\n private _phaseStart = Date.now();\r\n private _timer: ReturnType<typeof setInterval> | null = null;\r\n\r\n private _phase: G9ESyncPhase = G9ESyncPhase.Queued;\r\n private _postStep: string | null = null;\r\n private _table: string | null = null;\r\n private _subscription: string | null = null;\r\n private _base = 0;\r\n private _span = 0;\r\n private _overall = 0;\r\n private _fraction = 0;\r\n private _phaseExpectedMs = 0;\r\n private _rowsDone = 0;\r\n private _rowsTotal = 0;\r\n private _bytesDone = 0;\r\n private _bytesTotal = 0;\r\n private _lastPublish = 0;\r\n private _realSignal = false;\r\n private _terminal = false;\r\n private _cancelPending = false;\r\n private _disposed = false;\r\n private _lastPublished: G9DtSyncProgress | null = null;\r\n\r\n constructor(runId: string, publish: (progress: G9DtSyncProgress) => void, queuedBehind: () => number, maxHz: number) {\r\n this._runId = runId;\r\n this._publish = publish;\r\n this._queuedBehind = queuedBehind;\r\n this._minIntervalMs = maxHz <= 0 ? 0 : 1000 / maxHz;\r\n }\r\n\r\n get overall(): number {\r\n return this._overall;\r\n }\r\n\r\n /** Measured milliseconds per phase (post steps keyed `PostStep:name`). */\r\n get durations(): { [key: string]: number } {\r\n const out: { [key: string]: number } = {};\r\n for (const key of Object.keys(this._durations)) out[key] = this._durations[key] as number;\r\n return out;\r\n }\r\n\r\n /** Appends a phase to the plan with its expected duration. */\r\n plan(phase: G9ESyncPhase, expectedMs: number, name: string | null = null): void {\r\n if (!this._terminal) this._plan.push({ phase, name, expectedMs: Math.max(0, expectedMs) });\r\n }\r\n\r\n /** Updates the expected duration of a planned phase that has not started yet. */\r\n expect(phase: G9ESyncPhase, expectedMs: number, name: string | null = null): void {\r\n for (const entry of this._plan) {\r\n if (entry.phase === phase && entry.name === name) {\r\n entry.expectedMs = Math.max(0, expectedMs);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n enter(phase: G9ESyncPhase, rowsTotal = 0, bytesTotal = 0, name: string | null = null): void {\r\n if (this._terminal || this._disposed) return;\r\n this._close();\r\n let index = -1;\r\n for (let i = 0; i < this._plan.length; i++) {\r\n const entry = this._plan[i] as PlanEntry;\r\n if (entry.phase === phase && entry.name === name) {\r\n index = i;\r\n break;\r\n }\r\n }\r\n let expected = 500;\r\n if (index >= 0) {\r\n expected = (this._plan[index] as PlanEntry).expectedMs;\r\n this._plan.splice(0, index + 1);\r\n }\r\n expected = Math.max(1, expected);\r\n let remaining = 0;\r\n for (const entry of this._plan) remaining += entry.expectedMs;\r\n this._base = this._overall;\r\n this._span = ((1 - this._base) * expected) / (expected + remaining);\r\n this._phase = phase;\r\n this._postStep = name;\r\n this._rowsDone = 0;\r\n this._rowsTotal = Math.max(0, rowsTotal);\r\n this._bytesDone = 0;\r\n this._bytesTotal = Math.max(0, bytesTotal);\r\n this._fraction = 0;\r\n this._realSignal = false;\r\n this._phaseExpectedMs = expected;\r\n this._phaseStart = Date.now();\r\n if (this._timer === null) this._timer = setInterval(() => this._creep(), 200);\r\n this._emit(this._sample(true));\r\n }\r\n\r\n /** Reports absolute counts for the current phase. */\r\n report(rowsDone: number, bytesDone = -1, table: string | null = null, subscriptionKey: string | null = null): void {\r\n if (this._terminal || this._disposed) return;\r\n this._rowsDone = Math.max(0, rowsDone);\r\n if (bytesDone >= 0) this._bytesDone = bytesDone;\r\n if (table !== null) this._table = table;\r\n if (subscriptionKey !== null) this._subscription = subscriptionKey;\r\n const fraction = this._rowsTotal > 0 ? this._rowsDone / this._rowsTotal : this._bytesTotal > 0 ? this._bytesDone / this._bytesTotal : this._fraction;\r\n this._realSignal = this._rowsTotal > 0 || this._bytesTotal > 0;\r\n this._advance(fraction);\r\n this._emit(this._sample(false));\r\n }\r\n\r\n /** Reports a 0..1 fraction of the current phase (post steps). */\r\n reportFraction(fraction: number): void {\r\n if (this._terminal || this._disposed) return;\r\n this._realSignal = true;\r\n this._advance(fraction);\r\n this._emit(this._sample(false));\r\n }\r\n\r\n setCancelPending(): void {\r\n if (this._terminal || this._disposed) return;\r\n this._cancelPending = true;\r\n this._emit(this._sample(true));\r\n }\r\n\r\n complete(terminal: G9ESyncPhase): void {\r\n if (this._terminal || this._disposed) return;\r\n this._close();\r\n this._terminal = true;\r\n this._stopTimer();\r\n if (terminal === G9ESyncPhase.Completed) {\r\n this._overall = 1;\r\n this._fraction = 1;\r\n }\r\n this._phase = terminal;\r\n this._emit(this._sample(true));\r\n }\r\n\r\n dispose(): void {\r\n if (this._disposed) return;\r\n this._disposed = true;\r\n this._stopTimer();\r\n }\r\n\r\n private _stopTimer(): void {\r\n if (this._timer !== null) {\r\n clearInterval(this._timer);\r\n this._timer = null;\r\n }\r\n }\r\n\r\n private _creep(): void {\r\n if (this._terminal || this._disposed || this._realSignal || this._phase === G9ESyncPhase.Queued) return;\r\n const elapsed = Date.now() - this._phaseStart;\r\n this._advance(0.9 * (1 - Math.exp(-elapsed / Math.max(100, this._phaseExpectedMs))));\r\n this._emit(this._sample(false));\r\n }\r\n\r\n private _advance(fraction: number): void {\r\n const clamped = Math.min(Math.max(fraction, 0), 0.995);\r\n if (clamped > this._fraction) this._fraction = clamped;\r\n const overall = Math.min(0.999, this._base + this._span * this._fraction);\r\n if (overall > this._overall) this._overall = overall;\r\n }\r\n\r\n private _close(): void {\r\n const phase = this._phase;\r\n if (phase === G9ESyncPhase.Queued || phase === G9ESyncPhase.Completed || phase === G9ESyncPhase.Canceled || phase === G9ESyncPhase.Failed) return;\r\n const key = phase === G9ESyncPhase.PostStep ? 'PostStep:' + (this._postStep ?? '') : phaseName(phase);\r\n this._durations[key] = (this._durations[key] ?? 0) + (Date.now() - this._phaseStart);\r\n this._overall = Math.max(this._overall, Math.min(0.999, this._base + this._span));\r\n }\r\n\r\n private _sample(force: boolean): G9DtSyncProgress | null {\r\n const now = Date.now();\r\n if (!force && now - this._lastPublish < this._minIntervalMs) return null;\r\n this._lastPublish = now;\r\n const phaseSeconds = Math.max(0.001, (now - this._phaseStart) / 1000);\r\n let eta: number | null = null;\r\n if (this._terminal) eta = 0;\r\n else if (this._overall > 0.02) eta = ((now - this._runStart) * (1 - this._overall)) / this._overall;\r\n let queued = 0;\r\n try {\r\n queued = this._queuedBehind();\r\n } catch {\r\n queued = 0;\r\n }\r\n return {\r\n runId: this._runId,\r\n phase: this._phase,\r\n overall: this._overall,\r\n phaseFraction: this._fraction,\r\n rowsDone: this._rowsDone,\r\n rowsTotal: this._rowsTotal,\r\n bytesDone: this._bytesDone,\r\n bytesTotal: this._bytesTotal,\r\n subscriptionKey: this._subscription,\r\n table: this._table,\r\n rowsPerSecond: this._rowsDone / phaseSeconds,\r\n etaMs: eta,\r\n queuedBehind: queued,\r\n postStepName: this._postStep,\r\n cancelPending: this._cancelPending,\r\n };\r\n }\r\n\r\n /** Publishes a sample unless it would go backwards (lower overall or an earlier phase). */\r\n private _emit(sample: G9DtSyncProgress | null): void {\r\n if (sample === null) return;\r\n const last = this._lastPublished;\r\n if (last !== null && (sample.overall < last.overall || sample.phase < last.phase)) return;\r\n this._lastPublished = sample;\r\n try {\r\n this._publish(sample);\r\n } catch {\r\n // A progress consumer must never break the sync.\r\n }\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/client/runs.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Client/Runs/G9SyncRunTypes.cs and the option/health/error types of G9CSyncEngineOptions.cs.\nimport type { G9ESyncColumnType } from '../abstractions/enums.js';\nimport { G9SyncErrorCodes, G9SyncException, isSyncException } from '../abstractions/errors.js';\nimport { newGuid } from '../abstractions/guid.js';\nimport { G9SyncProtocol } from '../protocol/protocol.js';\nimport type { G9DtSubscriptionState } from '../protocol/dtos.js';\nimport { G9RowBatchFormatError } from '../protocol/rowBatch/format.js';\nimport { columnTypeName } from '../abstractions/enums.js';\nimport { createAbortController, type G9AbortController } from '../internal/abort.js';\nimport type { G9DtSyncProgress, G9ESyncPhase } from './progress.js';\nimport {\n G9ApplyReport,\n G9ELocalStoreFailure,\n isLocalStoreFailure,\n type G9ApplySlice,\n type G9PendingSummary,\n type G9SyncRunReport,\n type G9SyncSubscriptionRecord,\n} from './storeTypes.js';\n\n/** Scheduling priority (`G9ESyncPriority`). A higher priority pre-empts a running background run. */\nexport const G9ESyncPriority = {\n Background: 0,\n Foreground: 1,\n UserInteractive: 2,\n} as const;\nexport type G9ESyncPriority = (typeof G9ESyncPriority)[keyof typeof G9ESyncPriority];\n\nconst PRIORITY_NAMES = ['Background', 'Foreground', 'UserInteractive'];\nexport function priorityName(priority: number): string {\n return PRIORITY_NAMES[priority] ?? String(priority);\n}\n\n/** `G9ESyncOutcome`. */\nexport const G9ESyncOutcome = {\n Succeeded: 0,\n /** Data moved, but some rows were rejected or some subscriptions reported problems. */\n CompletedWithRejections: 1,\n Failed: 2,\n Canceled: 3,\n} as const;\nexport type G9ESyncOutcome = (typeof G9ESyncOutcome)[keyof typeof G9ESyncOutcome];\n\nconst OUTCOME_NAMES = ['Succeeded', 'CompletedWithRejections', 'Failed', 'Canceled'];\nexport function outcomeName(outcome: number): string {\n return OUTCOME_NAMES[outcome] ?? String(outcome);\n}\n\n/** Context handed to an app-owned post step (`G9CSyncPostStepContext`). */\nexport interface G9SyncPostStepContext {\n run: G9SyncRun;\n /** Everything this run changed so far. */\n changes: G9ApplyReport;\n /** Report 0..1 of the step; mapped into the step's slice of the bar. */\n progress: (fraction: number) => void;\n}\n\n/** An app-owned step that runs after the data applied and owns a slice of the progress bar (`G9CSyncPostStep`). */\nexport class G9SyncPostStep {\n readonly name: string;\n readonly weightHint: number;\n readonly action: (context: G9SyncPostStepContext, signal: AbortSignal) => Promise<void>;\n\n constructor(name: string, weightHint: number, action: (context: G9SyncPostStepContext, signal: AbortSignal) => Promise<void>) {\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A post step needs a name.');\n if (typeof action !== 'function') throw new TypeError('A post step needs an action.');\n this.name = name;\n this.weightHint = Math.min(Math.max(weightHint, 0), 0.9);\n this.action = action;\n }\n}\n\n/** A sync request (`G9CSyncRequest`). */\nexport interface G9SyncRequest {\n /** Subscription keys or names to pull; omitted = every local subscription (background runs skip heavy ones). */\n subscriptions?: readonly string[] | null;\n push?: boolean;\n pull?: boolean;\n /** Reconcile the selected subscriptions even when nothing asks for it. */\n forceReconcile?: boolean;\n priority?: G9ESyncPriority;\n postSteps?: readonly G9SyncPostStep[];\n progress?: ((progress: G9DtSyncProgress) => void) | null;\n signal?: AbortSignal | null;\n}\n\n/** The request with its defaults filled in. */\nexport interface G9ResolvedSyncRequest {\n subscriptions: readonly string[] | null;\n push: boolean;\n pull: boolean;\n forceReconcile: boolean;\n priority: G9ESyncPriority;\n postSteps: readonly G9SyncPostStep[];\n progress: ((progress: G9DtSyncProgress) => void) | null;\n signal: AbortSignal | null;\n}\n\nexport function resolveRequest(request: G9SyncRequest | null | undefined): G9ResolvedSyncRequest {\n return {\n subscriptions: request?.subscriptions ?? null,\n push: request?.push ?? true,\n pull: request?.pull ?? true,\n forceReconcile: request?.forceReconcile ?? false,\n priority: request?.priority ?? 1,\n postSteps: request?.postSteps ?? [],\n progress: request?.progress ?? null,\n signal: request?.signal ?? null,\n };\n}\n\n/** `G9CSyncRequest.CanCoalesce`. */\nexport function canCoalesce(request: G9ResolvedSyncRequest): boolean {\n return request.postSteps.length === 0 && request.progress === null && request.signal === null;\n}\n\n/** `G9CSyncRequest.Signature`. */\nexport function requestSignature(request: G9ResolvedSyncRequest): string {\n const subscriptions = request.subscriptions === null ? '*' : request.subscriptions.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(',');\n return `${request.push ? 'True' : 'False'}|${request.pull ? 'True' : 'False'}|${request.forceReconcile ? 'True' : 'False'}|${subscriptions}`;\n}\n\n/** One defect of the client model, as the server sees it (`G9CSyncModelProblem`). */\nexport interface G9SyncModelProblem {\n code: string;\n table: string;\n column: string;\n clientType: G9ESyncColumnType;\n serverType: G9ESyncColumnType;\n}\n\nexport function describeModelProblem(problem: G9SyncModelProblem): string {\n return `${problem.table}.${problem.column} is ${columnTypeName(problem.clientType)} on the client and ${columnTypeName(problem.serverType)} on the server`;\n}\n\n/** The result of a run (`G9CSyncRunResult`). */\nexport interface G9SyncRunResult {\n runId: string;\n outcome: G9ESyncOutcome;\n error: G9SyncException | null;\n pushed: number;\n rejected: number;\n conflicts: number;\n downloaded: number;\n applied: number;\n durationMs: number;\n /** Milliseconds spent in each phase of this run, keyed by phase name. */\n phaseMs: { [phase: string]: number };\n subscriptions: string[];\n /** Subscriptions that could not sync, with the server's reason. */\n problems: G9DtSubscriptionState[];\n /** Defects of the client model the server reported in this run's hello (ADR-0061). */\n modelProblems: G9SyncModelProblem[];\n changes: G9ApplyReport;\n isSuccess: boolean;\n}\n\nexport function makeRunResult(fields: Partial<G9SyncRunResult> & { runId: string; outcome: G9ESyncOutcome }): G9SyncRunResult {\n return {\n error: null,\n pushed: 0,\n rejected: 0,\n conflicts: 0,\n downloaded: 0,\n applied: 0,\n durationMs: 0,\n phaseMs: {},\n subscriptions: [],\n problems: [],\n modelProblems: [],\n changes: new G9ApplyReport(),\n ...fields,\n isSuccess: fields.outcome === G9ESyncOutcome.Succeeded || fields.outcome === G9ESyncOutcome.CompletedWithRejections,\n };\n}\n\n/** A queued or running sync (`G9CSyncRun`). Await {@link completion}; read progress with {@link onProgress} or {@link progress}. */\nexport class G9SyncRun {\n readonly runId: string = newGuid();\n readonly request: G9ResolvedSyncRequest;\n readonly completion: Promise<G9SyncRunResult>;\n latestProgress: G9DtSyncProgress | null = null;\n isStarted = false;\n\n /** @internal */\n readonly cancellation: G9AbortController;\n /** @internal */\n preempted = false;\n\n private _resolve!: (result: G9SyncRunResult) => void;\n private readonly _listeners: ((progress: G9DtSyncProgress) => void)[] = [];\n private readonly _buffer: G9DtSyncProgress[] = [];\n private readonly _waiters: ((value: IteratorResult<G9DtSyncProgress>) => void)[] = [];\n private _done = false;\n private _unlink: () => void = () => undefined;\n\n constructor(request: G9ResolvedSyncRequest) {\n this.request = request;\n this.completion = new Promise<G9SyncRunResult>((resolve) => {\n this._resolve = resolve;\n });\n this.cancellation = createAbortController();\n const external = request.signal;\n if (external) {\n if (external.aborted) this.cancellation.abort();\n else {\n const listener = (): void => this.cancellation.abort();\n external.addEventListener('abort', listener);\n this._unlink = () => external.removeEventListener('abort', listener);\n }\n }\n }\n\n /** Requests cancellation. Network phases stop at once; an apply in progress finishes atomically first. */\n cancel(): void {\n this.cancellation.abort();\n }\n\n /** Subscribes to progress samples; returns the unsubscribe function. */\n onProgress(listener: (progress: G9DtSyncProgress) => void): () => void {\n this._listeners.push(listener);\n return () => {\n const index = this._listeners.indexOf(listener);\n if (index >= 0) this._listeners.splice(index, 1);\n };\n }\n\n /** The progress stream (bounded: the oldest samples are dropped when a reader falls 64 behind), ending with the run. */\n progress(): AsyncIterable<G9DtSyncProgress> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const run = this;\n return {\n [Symbol.asyncIterator](): AsyncIterator<G9DtSyncProgress> {\n return {\n next(): Promise<IteratorResult<G9DtSyncProgress>> {\n const value = run._buffer.shift();\n if (value) return Promise.resolve({ value, done: false });\n if (run._done) return Promise.resolve({ value: undefined as unknown as G9DtSyncProgress, done: true });\n return new Promise((resolve) => run._waiters.push(resolve));\n },\n };\n },\n };\n }\n\n /** @internal */\n publish(progress: G9DtSyncProgress): void {\n this.latestProgress = progress;\n const waiter = this._waiters.shift();\n if (waiter) waiter({ value: progress, done: false });\n else {\n this._buffer.push(progress);\n if (this._buffer.length > 64) this._buffer.shift();\n }\n for (const listener of this._listeners.slice()) {\n try {\n listener(progress);\n } catch {\n // A progress consumer must never break the sync.\n }\n }\n try {\n this.request.progress?.(progress);\n } catch {\n // A progress consumer must never break the sync.\n }\n }\n\n /** @internal */\n complete(result: G9SyncRunResult): void {\n if (this._done) return;\n this._done = true;\n for (const waiter of this._waiters.splice(0, this._waiters.length)) waiter({ value: undefined as unknown as G9DtSyncProgress, done: true });\n this._unlink();\n this._resolve(result);\n }\n}\n\n/** `G9CSubscriptionOptions`. */\nexport interface G9SubscriptionOptions {\n /** Overrides the server definition's ephemeral flag. */\n ephemeral?: boolean;\n ttlMs?: number;\n /** The rows already exist locally: reconcile instead of downloading a snapshot. Call adoptExistingRows first. */\n adoptExistingRows?: boolean;\n}\n\n/** Engine options (`G9CSyncEngineOptions`). Durations are milliseconds. */\nexport interface G9SyncEngineOptions {\n /** Sent at Hello; the server's connect gates may refuse old versions. */\n appVersion?: string | null;\n pushBatchRows?: number;\n /** Transient failures retried inside one run. */\n maxRetries?: number;\n retryBaseDelayMs?: number;\n /** Queue a background pull when the server pokes about changed tables. */\n pullOnChangesAvailable?: boolean;\n changesDebounceMs?: number;\n progressMaxHz?: number;\n fetchKeysPerRequest?: number;\n /** Rows a reconciliation fetches before it applies them (ADR-0066). */\n reconcileApplyRows?: number;\n /** A reconciliation that would fetch at least this many rows of one table hands them to a staged snapshot (ADR-0066). 0 = never. */\n reconcileSnapshotThreshold?: number;\n /** The largest decoded body accepted from one server frame (ADR-0051). */\n maxDecodedFrameBytes?: number;\n /** The newest G9RowBatch body layout to ask the server for (ADR-0040). */\n maxFrameVersion?: number;\n /** Fail a run when the server reports a client column whose type differs (ADR-0061). */\n failOnTypeMismatch?: boolean;\n /**\n * Offer the server to send large first downloads as SQLite snapshot files (ADR-0072), when the store can take them (a store\n * with a `snapshotFiles` sink). Default true. A file that fails is replaced by the same pull as rows, in the same run.\n */\n acceptSnapshotFiles?: boolean;\n /** A staged pull older than this is discarded instead of resumed. */\n stagedPullMaxAgeMs?: number;\n /** Most payload bytes kept in stages other than the one a run resumes (ADR-0060). */\n stagedPullsMaxBytes?: number;\n keepDeletedFeedEntries?: number;\n keepRunReports?: number;\n /** Where the engine logs (the ILogger twin); silent when omitted. */\n logger?: G9SyncLogger | null;\n /** Platform integration (foreground service, keep-awake, connectivity). */\n hooks?: G9SyncHostHooks | null;\n}\n\nexport type G9ResolvedEngineOptions = Required<Omit<G9SyncEngineOptions, 'appVersion' | 'logger' | 'hooks'>> & {\n appVersion: string | null;\n logger: G9SyncLogger | null;\n hooks: G9SyncHostHooks | null;\n};\n\nexport function resolveEngineOptions(options: G9SyncEngineOptions | null | undefined): G9ResolvedEngineOptions {\n return {\n appVersion: options?.appVersion ?? null,\n pushBatchRows: options?.pushBatchRows ?? 2000,\n maxRetries: options?.maxRetries ?? 5,\n retryBaseDelayMs: options?.retryBaseDelayMs ?? 1000,\n pullOnChangesAvailable: options?.pullOnChangesAvailable ?? true,\n changesDebounceMs: options?.changesDebounceMs ?? 2000,\n progressMaxHz: options?.progressMaxHz ?? 10,\n fetchKeysPerRequest: options?.fetchKeysPerRequest ?? 2000,\n reconcileApplyRows: options?.reconcileApplyRows ?? 20000,\n reconcileSnapshotThreshold: options?.reconcileSnapshotThreshold ?? 100000,\n maxDecodedFrameBytes: options?.maxDecodedFrameBytes ?? 64 * 1024 * 1024,\n maxFrameVersion: options?.maxFrameVersion ?? G9SyncProtocol.MaxFrameVersion,\n failOnTypeMismatch: options?.failOnTypeMismatch ?? false,\n acceptSnapshotFiles: options?.acceptSnapshotFiles ?? true,\n stagedPullMaxAgeMs: options?.stagedPullMaxAgeMs ?? 90 * 60 * 1000,\n stagedPullsMaxBytes: options?.stagedPullsMaxBytes ?? 64 * 1024 * 1024,\n keepDeletedFeedEntries: options?.keepDeletedFeedEntries ?? 50000,\n keepRunReports: options?.keepRunReports ?? 50,\n logger: options?.logger ?? null,\n hooks: options?.hooks ?? null,\n };\n}\n\n/** Log levels of {@link G9SyncLogger} (Microsoft.Extensions.Logging's). */\nexport type G9SyncLogLevel = 'debug' | 'information' | 'warning' | 'error';\n\n/** Where the library logs. `eventId` is the .NET LoggerMessage event id of the same message. */\nexport interface G9SyncLogger {\n log(level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void;\n}\n\n/** Platform integration points (`IG9SyncHostHooks`). */\nexport interface G9SyncHostHooks {\n /** Called when a run starts executing; the returned scope's `dispose` runs when it ends. */\n beginRun(run: G9SyncRun, signal: AbortSignal): Promise<{ dispose(): void | Promise<void> } | null>;\n /** False skips automatic background runs. */\n readonly isNetworkAvailable: boolean;\n}\n\n/** `G9CSyncHealth`. */\nexport interface G9SyncHealth {\n clientId: string;\n isConnected: boolean;\n isRunning: boolean;\n queuedRuns: number;\n serverEpoch: string | null;\n lastHelloUtcMs: number | null;\n pending: G9PendingSummary;\n subscriptions: G9SyncSubscriptionRecord[];\n recentRuns: G9SyncRunReport[];\n}\n\n/** `G9CRowsAppliedEventArgs`. */\nexport interface G9RowsAppliedEvent {\n report: G9ApplyReport;\n source: G9ESyncPhase;\n /** Set for a staged pull applied in slices (ADR-0053). */\n slice: G9ApplySlice | null;\n}\n\n/** `G9CSyncErrors.Normalize`: every failure becomes a G9SyncException with a stable code. */\nexport function normalizeError(error: unknown): G9SyncException {\n if (isSyncException(error)) return error as G9SyncException;\n const message = error instanceof Error ? error.message : String(error);\n if (error instanceof Error && error.name === 'AbortError') return new G9SyncException(G9SyncErrorCodes.Canceled, 'The sync was canceled.', { cause: error });\n if (isLocalStoreFailure(error)) {\n const code =\n error.localStoreFailure === G9ELocalStoreFailure.Corrupt\n ? G9SyncErrorCodes.LocalStoreCorrupt\n : error.localStoreFailure === G9ELocalStoreFailure.DiskFull\n ? G9SyncErrorCodes.LocalStoreDiskFull\n : error.localStoreFailure === G9ELocalStoreFailure.Busy\n ? G9SyncErrorCodes.LocalStoreBusy\n : G9SyncErrorCodes.LocalStoreError;\n return new G9SyncException(code, message, { cause: error });\n }\n if (error instanceof G9RowBatchFormatError) return new G9SyncException(G9SyncErrorCodes.Unknown, message, { cause: error });\n if (error instanceof Error && (error.name === 'TimeoutError' || /network|socket|websocket|connection/i.test(error.name))) {\n return new G9SyncException(G9SyncErrorCodes.NetworkFailure, message, { cause: error });\n }\n return new G9SyncException(G9SyncErrorCodes.Unknown, message, { cause: error });\n}\n\n/** `G9CSyncErrors.IsTransient`. */\nexport function isTransientError(error: unknown): boolean {\n const code = normalizeError(error).code;\n return code === G9SyncErrorCodes.NetworkFailure || code === G9SyncErrorCodes.ServerError || code === G9SyncErrorCodes.ServerBusy;\n}\n"]}
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/client/runs.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Client/Runs/G9SyncRunTypes.cs and the option/health/error types of G9CSyncEngineOptions.cs.\r\nimport type { G9ESyncColumnType } from '../abstractions/enums.js';\r\nimport { G9SyncErrorCodes, G9SyncException, isSyncException } from '../abstractions/errors.js';\r\nimport { newGuid } from '../abstractions/guid.js';\r\nimport { G9SyncProtocol } from '../protocol/protocol.js';\r\nimport type { G9DtSubscriptionState } from '../protocol/dtos.js';\r\nimport { G9RowBatchFormatError } from '../protocol/rowBatch/format.js';\r\nimport { columnTypeName } from '../abstractions/enums.js';\r\nimport { createAbortController, type G9AbortController } from '../internal/abort.js';\r\nimport type { G9DtSyncProgress, G9ESyncPhase } from './progress.js';\r\nimport {\r\n G9ApplyReport,\r\n G9ELocalStoreFailure,\r\n isLocalStoreFailure,\r\n type G9ApplySlice,\r\n type G9PendingSummary,\r\n type G9SyncRunReport,\r\n type G9SyncSubscriptionRecord,\r\n} from './storeTypes.js';\r\n\r\n/** Scheduling priority (`G9ESyncPriority`). A higher priority pre-empts a running background run. */\r\nexport const G9ESyncPriority = {\r\n Background: 0,\r\n Foreground: 1,\r\n UserInteractive: 2,\r\n} as const;\r\nexport type G9ESyncPriority = (typeof G9ESyncPriority)[keyof typeof G9ESyncPriority];\r\n\r\nconst PRIORITY_NAMES = ['Background', 'Foreground', 'UserInteractive'];\r\nexport function priorityName(priority: number): string {\r\n return PRIORITY_NAMES[priority] ?? String(priority);\r\n}\r\n\r\n/** `G9ESyncOutcome`. */\r\nexport const G9ESyncOutcome = {\r\n Succeeded: 0,\r\n /** Data moved, but some rows were rejected or some subscriptions reported problems. */\r\n CompletedWithRejections: 1,\r\n Failed: 2,\r\n Canceled: 3,\r\n} as const;\r\nexport type G9ESyncOutcome = (typeof G9ESyncOutcome)[keyof typeof G9ESyncOutcome];\r\n\r\nconst OUTCOME_NAMES = ['Succeeded', 'CompletedWithRejections', 'Failed', 'Canceled'];\r\nexport function outcomeName(outcome: number): string {\r\n return OUTCOME_NAMES[outcome] ?? String(outcome);\r\n}\r\n\r\n/** Context handed to an app-owned post step (`G9CSyncPostStepContext`). */\r\nexport interface G9SyncPostStepContext {\r\n run: G9SyncRun;\r\n /** Everything this run changed so far. */\r\n changes: G9ApplyReport;\r\n /** Report 0..1 of the step; mapped into the step's slice of the bar. */\r\n progress: (fraction: number) => void;\r\n}\r\n\r\n/** An app-owned step that runs after the data applied and owns a slice of the progress bar (`G9CSyncPostStep`). */\r\nexport class G9SyncPostStep {\r\n readonly name: string;\r\n readonly weightHint: number;\r\n readonly action: (context: G9SyncPostStepContext, signal: AbortSignal) => Promise<void>;\r\n\r\n constructor(name: string, weightHint: number, action: (context: G9SyncPostStepContext, signal: AbortSignal) => Promise<void>) {\r\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A post step needs a name.');\r\n if (typeof action !== 'function') throw new TypeError('A post step needs an action.');\r\n this.name = name;\r\n this.weightHint = Math.min(Math.max(weightHint, 0), 0.9);\r\n this.action = action;\r\n }\r\n}\r\n\r\n/** A sync request (`G9CSyncRequest`). */\r\nexport interface G9SyncRequest {\r\n /** Subscription keys or names to pull; omitted = every local subscription (background runs skip heavy ones). */\r\n subscriptions?: readonly string[] | null;\r\n push?: boolean;\r\n pull?: boolean;\r\n /** Reconcile the selected subscriptions even when nothing asks for it. */\r\n forceReconcile?: boolean;\r\n priority?: G9ESyncPriority;\r\n postSteps?: readonly G9SyncPostStep[];\r\n progress?: ((progress: G9DtSyncProgress) => void) | null;\r\n signal?: AbortSignal | null;\r\n}\r\n\r\n/** The request with its defaults filled in. */\r\nexport interface G9ResolvedSyncRequest {\r\n subscriptions: readonly string[] | null;\r\n push: boolean;\r\n pull: boolean;\r\n forceReconcile: boolean;\r\n priority: G9ESyncPriority;\r\n postSteps: readonly G9SyncPostStep[];\r\n progress: ((progress: G9DtSyncProgress) => void) | null;\r\n signal: AbortSignal | null;\r\n}\r\n\r\nexport function resolveRequest(request: G9SyncRequest | null | undefined): G9ResolvedSyncRequest {\r\n return {\r\n subscriptions: request?.subscriptions ?? null,\r\n push: request?.push ?? true,\r\n pull: request?.pull ?? true,\r\n forceReconcile: request?.forceReconcile ?? false,\r\n priority: request?.priority ?? 1,\r\n postSteps: request?.postSteps ?? [],\r\n progress: request?.progress ?? null,\r\n signal: request?.signal ?? null,\r\n };\r\n}\r\n\r\n/** `G9CSyncRequest.CanCoalesce`. */\r\nexport function canCoalesce(request: G9ResolvedSyncRequest): boolean {\r\n return request.postSteps.length === 0 && request.progress === null && request.signal === null;\r\n}\r\n\r\n/** `G9CSyncRequest.Signature`. */\r\nexport function requestSignature(request: G9ResolvedSyncRequest): string {\r\n const subscriptions = request.subscriptions === null ? '*' : request.subscriptions.slice().sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).join(',');\r\n return `${request.push ? 'True' : 'False'}|${request.pull ? 'True' : 'False'}|${request.forceReconcile ? 'True' : 'False'}|${subscriptions}`;\r\n}\r\n\r\n/** One defect of the client model, as the server sees it (`G9CSyncModelProblem`). */\r\nexport interface G9SyncModelProblem {\r\n code: string;\r\n table: string;\r\n column: string;\r\n clientType: G9ESyncColumnType;\r\n serverType: G9ESyncColumnType;\r\n}\r\n\r\nexport function describeModelProblem(problem: G9SyncModelProblem): string {\r\n return `${problem.table}.${problem.column} is ${columnTypeName(problem.clientType)} on the client and ${columnTypeName(problem.serverType)} on the server`;\r\n}\r\n\r\n/** The result of a run (`G9CSyncRunResult`). */\r\nexport interface G9SyncRunResult {\r\n runId: string;\r\n outcome: G9ESyncOutcome;\r\n error: G9SyncException | null;\r\n pushed: number;\r\n rejected: number;\r\n conflicts: number;\r\n downloaded: number;\r\n applied: number;\r\n durationMs: number;\r\n /** Milliseconds spent in each phase of this run, keyed by phase name. */\r\n phaseMs: { [phase: string]: number };\r\n subscriptions: string[];\r\n /** Subscriptions that could not sync, with the server's reason. */\r\n problems: G9DtSubscriptionState[];\r\n /** Defects of the client model the server reported in this run's hello (ADR-0061). */\r\n modelProblems: G9SyncModelProblem[];\r\n changes: G9ApplyReport;\r\n isSuccess: boolean;\r\n}\r\n\r\nexport function makeRunResult(fields: Partial<G9SyncRunResult> & { runId: string; outcome: G9ESyncOutcome }): G9SyncRunResult {\r\n return {\r\n error: null,\r\n pushed: 0,\r\n rejected: 0,\r\n conflicts: 0,\r\n downloaded: 0,\r\n applied: 0,\r\n durationMs: 0,\r\n phaseMs: {},\r\n subscriptions: [],\r\n problems: [],\r\n modelProblems: [],\r\n changes: new G9ApplyReport(),\r\n ...fields,\r\n isSuccess: fields.outcome === G9ESyncOutcome.Succeeded || fields.outcome === G9ESyncOutcome.CompletedWithRejections,\r\n };\r\n}\r\n\r\n/** A queued or running sync (`G9CSyncRun`). Await {@link completion}; read progress with {@link onProgress} or {@link progress}. */\r\nexport class G9SyncRun {\r\n readonly runId: string = newGuid();\r\n readonly request: G9ResolvedSyncRequest;\r\n readonly completion: Promise<G9SyncRunResult>;\r\n latestProgress: G9DtSyncProgress | null = null;\r\n isStarted = false;\r\n\r\n /** @internal */\r\n readonly cancellation: G9AbortController;\r\n /** @internal */\r\n preempted = false;\r\n\r\n private _resolve!: (result: G9SyncRunResult) => void;\r\n private readonly _listeners: ((progress: G9DtSyncProgress) => void)[] = [];\r\n private readonly _buffer: G9DtSyncProgress[] = [];\r\n private readonly _waiters: ((value: IteratorResult<G9DtSyncProgress>) => void)[] = [];\r\n private _done = false;\r\n private _unlink: () => void = () => undefined;\r\n\r\n constructor(request: G9ResolvedSyncRequest) {\r\n this.request = request;\r\n this.completion = new Promise<G9SyncRunResult>((resolve) => {\r\n this._resolve = resolve;\r\n });\r\n this.cancellation = createAbortController();\r\n const external = request.signal;\r\n if (external) {\r\n if (external.aborted) this.cancellation.abort();\r\n else {\r\n const listener = (): void => this.cancellation.abort();\r\n external.addEventListener('abort', listener);\r\n this._unlink = () => external.removeEventListener('abort', listener);\r\n }\r\n }\r\n }\r\n\r\n /** Requests cancellation. Network phases stop at once; an apply in progress finishes atomically first. */\r\n cancel(): void {\r\n this.cancellation.abort();\r\n }\r\n\r\n /** Subscribes to progress samples; returns the unsubscribe function. */\r\n onProgress(listener: (progress: G9DtSyncProgress) => void): () => void {\r\n this._listeners.push(listener);\r\n return () => {\r\n const index = this._listeners.indexOf(listener);\r\n if (index >= 0) this._listeners.splice(index, 1);\r\n };\r\n }\r\n\r\n /** The progress stream (bounded: the oldest samples are dropped when a reader falls 64 behind), ending with the run. */\r\n progress(): AsyncIterable<G9DtSyncProgress> {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const run = this;\r\n return {\r\n [Symbol.asyncIterator](): AsyncIterator<G9DtSyncProgress> {\r\n return {\r\n next(): Promise<IteratorResult<G9DtSyncProgress>> {\r\n const value = run._buffer.shift();\r\n if (value) return Promise.resolve({ value, done: false });\r\n if (run._done) return Promise.resolve({ value: undefined as unknown as G9DtSyncProgress, done: true });\r\n return new Promise((resolve) => run._waiters.push(resolve));\r\n },\r\n };\r\n },\r\n };\r\n }\r\n\r\n /** @internal */\r\n publish(progress: G9DtSyncProgress): void {\r\n this.latestProgress = progress;\r\n const waiter = this._waiters.shift();\r\n if (waiter) waiter({ value: progress, done: false });\r\n else {\r\n this._buffer.push(progress);\r\n if (this._buffer.length > 64) this._buffer.shift();\r\n }\r\n for (const listener of this._listeners.slice()) {\r\n try {\r\n listener(progress);\r\n } catch {\r\n // A progress consumer must never break the sync.\r\n }\r\n }\r\n try {\r\n this.request.progress?.(progress);\r\n } catch {\r\n // A progress consumer must never break the sync.\r\n }\r\n }\r\n\r\n /** @internal */\r\n complete(result: G9SyncRunResult): void {\r\n if (this._done) return;\r\n this._done = true;\r\n for (const waiter of this._waiters.splice(0, this._waiters.length)) waiter({ value: undefined as unknown as G9DtSyncProgress, done: true });\r\n this._unlink();\r\n this._resolve(result);\r\n }\r\n}\r\n\r\n/** `G9CSubscriptionOptions`. */\r\nexport interface G9SubscriptionOptions {\r\n /** Overrides the server definition's ephemeral flag. */\r\n ephemeral?: boolean;\r\n ttlMs?: number;\r\n /** The rows already exist locally: reconcile instead of downloading a snapshot. Call adoptExistingRows first. */\r\n adoptExistingRows?: boolean;\r\n}\r\n\r\n/** Engine options (`G9CSyncEngineOptions`). Durations are milliseconds. */\r\nexport interface G9SyncEngineOptions {\r\n /** Sent at Hello; the server's connect gates may refuse old versions. */\r\n appVersion?: string | null;\r\n pushBatchRows?: number;\r\n /** Transient failures retried inside one run. */\r\n maxRetries?: number;\r\n retryBaseDelayMs?: number;\r\n /** Queue a background pull when the server pokes about changed tables. */\r\n pullOnChangesAvailable?: boolean;\r\n changesDebounceMs?: number;\r\n progressMaxHz?: number;\r\n fetchKeysPerRequest?: number;\r\n /** Rows a reconciliation fetches before it applies them (ADR-0066). */\r\n reconcileApplyRows?: number;\r\n /** A reconciliation that would fetch at least this many rows of one table hands them to a staged snapshot (ADR-0066). 0 = never. */\r\n reconcileSnapshotThreshold?: number;\r\n /** The largest decoded body accepted from one server frame (ADR-0051). */\r\n maxDecodedFrameBytes?: number;\r\n /** The newest G9RowBatch body layout to ask the server for (ADR-0040). */\r\n maxFrameVersion?: number;\r\n /** Fail a run when the server reports a client column whose type differs (ADR-0061). */\r\n failOnTypeMismatch?: boolean;\r\n /**\r\n * Offer the server to send large first downloads as SQLite snapshot files (ADR-0072), when the store can take them (a store\r\n * with a `snapshotFiles` sink). Default true. A file that fails is replaced by the same pull as rows, in the same run.\r\n */\r\n acceptSnapshotFiles?: boolean;\r\n /** A staged pull older than this is discarded instead of resumed. */\r\n stagedPullMaxAgeMs?: number;\r\n /** Most payload bytes kept in stages other than the one a run resumes (ADR-0060). */\r\n stagedPullsMaxBytes?: number;\r\n keepDeletedFeedEntries?: number;\r\n keepRunReports?: number;\r\n /** Where the engine logs (the ILogger twin); silent when omitted. */\r\n logger?: G9SyncLogger | null;\r\n /** Platform integration (foreground service, keep-awake, connectivity). */\r\n hooks?: G9SyncHostHooks | null;\r\n}\r\n\r\nexport type G9ResolvedEngineOptions = Required<Omit<G9SyncEngineOptions, 'appVersion' | 'logger' | 'hooks'>> & {\r\n appVersion: string | null;\r\n logger: G9SyncLogger | null;\r\n hooks: G9SyncHostHooks | null;\r\n};\r\n\r\nexport function resolveEngineOptions(options: G9SyncEngineOptions | null | undefined): G9ResolvedEngineOptions {\r\n return {\r\n appVersion: options?.appVersion ?? null,\r\n pushBatchRows: options?.pushBatchRows ?? 2000,\r\n maxRetries: options?.maxRetries ?? 5,\r\n retryBaseDelayMs: options?.retryBaseDelayMs ?? 1000,\r\n pullOnChangesAvailable: options?.pullOnChangesAvailable ?? true,\r\n changesDebounceMs: options?.changesDebounceMs ?? 2000,\r\n progressMaxHz: options?.progressMaxHz ?? 10,\r\n fetchKeysPerRequest: options?.fetchKeysPerRequest ?? 2000,\r\n reconcileApplyRows: options?.reconcileApplyRows ?? 20000,\r\n reconcileSnapshotThreshold: options?.reconcileSnapshotThreshold ?? 100000,\r\n maxDecodedFrameBytes: options?.maxDecodedFrameBytes ?? 64 * 1024 * 1024,\r\n maxFrameVersion: options?.maxFrameVersion ?? G9SyncProtocol.MaxFrameVersion,\r\n failOnTypeMismatch: options?.failOnTypeMismatch ?? false,\r\n acceptSnapshotFiles: options?.acceptSnapshotFiles ?? true,\r\n stagedPullMaxAgeMs: options?.stagedPullMaxAgeMs ?? 90 * 60 * 1000,\r\n stagedPullsMaxBytes: options?.stagedPullsMaxBytes ?? 64 * 1024 * 1024,\r\n keepDeletedFeedEntries: options?.keepDeletedFeedEntries ?? 50000,\r\n keepRunReports: options?.keepRunReports ?? 50,\r\n logger: options?.logger ?? null,\r\n hooks: options?.hooks ?? null,\r\n };\r\n}\r\n\r\n/** Log levels of {@link G9SyncLogger} (Microsoft.Extensions.Logging's). */\r\nexport type G9SyncLogLevel = 'debug' | 'information' | 'warning' | 'error';\r\n\r\n/** Where the library logs. `eventId` is the .NET LoggerMessage event id of the same message. */\r\nexport interface G9SyncLogger {\r\n log(level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void;\r\n}\r\n\r\n/** Platform integration points (`IG9SyncHostHooks`). */\r\nexport interface G9SyncHostHooks {\r\n /** Called when a run starts executing; the returned scope's `dispose` runs when it ends. */\r\n beginRun(run: G9SyncRun, signal: AbortSignal): Promise<{ dispose(): void | Promise<void> } | null>;\r\n /** False skips automatic background runs. */\r\n readonly isNetworkAvailable: boolean;\r\n}\r\n\r\n/** `G9CSyncHealth`. */\r\nexport interface G9SyncHealth {\r\n clientId: string;\r\n isConnected: boolean;\r\n isRunning: boolean;\r\n queuedRuns: number;\r\n serverEpoch: string | null;\r\n lastHelloUtcMs: number | null;\r\n pending: G9PendingSummary;\r\n subscriptions: G9SyncSubscriptionRecord[];\r\n recentRuns: G9SyncRunReport[];\r\n}\r\n\r\n/** `G9CRowsAppliedEventArgs`. */\r\nexport interface G9RowsAppliedEvent {\r\n report: G9ApplyReport;\r\n source: G9ESyncPhase;\r\n /** Set for a staged pull applied in slices (ADR-0053). */\r\n slice: G9ApplySlice | null;\r\n}\r\n\r\n/** `G9CSyncErrors.Normalize`: every failure becomes a G9SyncException with a stable code. */\r\nexport function normalizeError(error: unknown): G9SyncException {\r\n if (isSyncException(error)) return error as G9SyncException;\r\n const message = error instanceof Error ? error.message : String(error);\r\n if (error instanceof Error && error.name === 'AbortError') return new G9SyncException(G9SyncErrorCodes.Canceled, 'The sync was canceled.', { cause: error });\r\n if (isLocalStoreFailure(error)) {\r\n const code =\r\n error.localStoreFailure === G9ELocalStoreFailure.Corrupt\r\n ? G9SyncErrorCodes.LocalStoreCorrupt\r\n : error.localStoreFailure === G9ELocalStoreFailure.DiskFull\r\n ? G9SyncErrorCodes.LocalStoreDiskFull\r\n : error.localStoreFailure === G9ELocalStoreFailure.Busy\r\n ? G9SyncErrorCodes.LocalStoreBusy\r\n : G9SyncErrorCodes.LocalStoreError;\r\n return new G9SyncException(code, message, { cause: error });\r\n }\r\n if (error instanceof G9RowBatchFormatError) return new G9SyncException(G9SyncErrorCodes.Unknown, message, { cause: error });\r\n if (error instanceof Error && (error.name === 'TimeoutError' || /network|socket|websocket|connection/i.test(error.name))) {\r\n return new G9SyncException(G9SyncErrorCodes.NetworkFailure, message, { cause: error });\r\n }\r\n return new G9SyncException(G9SyncErrorCodes.Unknown, message, { cause: error });\r\n}\r\n\r\n/** `G9CSyncErrors.IsTransient`. */\r\nexport function isTransientError(error: unknown): boolean {\r\n const code = normalizeError(error).code;\r\n return code === G9SyncErrorCodes.NetworkFailure || code === G9SyncErrorCodes.ServerError || code === G9SyncErrorCodes.ServerBusy;\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"storeTypes.js","sourceRoot":"","sources":["../../src/client/storeTypes.ts"],"names":[],"mappings":"AAkCA,8BAA8B;AAC9B,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM,EAAE,CAAC;IACT,cAAc,EAAE,CAAC;IACjB,MAAM,EAAE,CAAC;CACD,CAAC;AAyBX,iDAAiD;AACjD,MAAM,UAAU,iBAAiB,CAAC,MAAgC;IAChE,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;QACpC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;AACJ,CAAC;AAiED,2EAA2E;AAE3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;AACxD,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAErC,yFAAyF;AACzF,oHAAoH;AACpH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAC3C,4FAA4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC,kIAAkI;AAClI,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAEzC,MAAM,OAAO,kBAAkB;IAA/B;QACE,iBAAY,GAAG,CAAC,CAAC;QACjB,oCAA+B,GAAG,CAAC,CAAC;QAC3B,oBAAe,GAAa,EAAE,CAAC;QAC/B,oBAAe,GAAgC,EAAE,CAAC;QAClD,qBAAgB,GAAgC,EAAE,CAAC;QACnD,gBAAW,GAAgC,EAAE,CAAC;QAC9C,cAAS,GAAgC,EAAE,CAAC;QACrD,mBAAc,GAAG,CAAC,CAAC;QACnB,cAAS,GAAG,CAAC,CAAC;QACd,2CAA2C;QAC3C,kBAAa,GAAG,CAAC,CAAC;QAClB,gDAAgD;QAChD,aAAQ,GAAG,CAAC,CAAC;QACb,oEAAoE;QACpE,eAAU,GAAG,CAAC,CAAC;QACf,kGAAkG;QACzF,eAAU,GAAgC,EAAE,CAAC;IA0ExD,CAAC;IAxEC,gIAAgI;IAChI,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,+BAA+B,KAAK,IAAI,CAAC,YAAY,CAAC;IACrG,CAAC;IAED,IAAI,kBAAkB;QACpB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;YAAE,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAW,CAAC;QAClG,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,KAAyB;QAC7B,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,+BAA+B,IAAI,KAAK,CAAC,+BAA+B,CAAC;QAC9E,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAW,CAAC;QACxG,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,yBAAyB;gBAAE,MAAM;YACpE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;gBAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;YAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAW,CAAC;QAC1H,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,iGAAiG;IACjG,QAAQ;QACN,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC;YAAE,OAAO,iBAAiB,CAAC;QACtD,IAAI,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,sBAAsB,IAAI,CAAC,SAAS,gBAAgB,CAAC;QACpF,IAAI;YACF,IAAI,CAAC,eAAe,KAAK,IAAI;gBAC3B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,CAAC,+BAA+B,KAAK,CAAC;oBAC1C,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,cAAc,IAAI,CAAC,+BAA+B,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;QACrF,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,IAAI,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QACnG,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,IAAI,KAAK,IAAI,CAAC,kBAAkB,wCAAwC,IAAI,CAAC,cAAc,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QACnL,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,IAAI,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1H,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI;gBACF,KAAK,IAAI,CAAC,aAAa,sBAAsB,IAAI,CAAC,QAAQ,mBAAmB,IAAI,CAAC,UAAU,OAAO;oBACnG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;yBACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;yBACxC,IAAI,CAAC,IAAI,CAAC;oBACb,GAAG,CAAC;QACR,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;aACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAY,GAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAY,CAAC;aAC7E,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACf,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI;gBACF,IAAI;oBACJ,OAAO;yBACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;;wBACT,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAW,CAAC;wBACvC,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC;wBACtC,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;wBAC5D,OAAO,GAAG,CAAC,IAAI,IAAI,YAAY,EAAE,QAAQ,IAAI,KAAK,CAAC;oBACrD,CAAC,CAAC;yBACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,SAAS,MAAM,CAAC,MAAiC,EAAE,MAAiC;;IAClF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAA,MAAM,CAAC,GAAG,CAAC,mCAAI,CAAC,CAAC,GAAI,MAAM,CAAC,GAAG,CAAY,CAAC;AACpG,CAAC;AAED,gDAAgD;AAChD,MAAM,OAAO,aAAa;IAA1B;QACE,YAAO,GAAG,CAAC,CAAC;QACZ,YAAO,GAAG,CAAC,CAAC;QACZ,aAAQ,GAAG,CAAC,CAAC;QACb,oBAAe,GAAG,CAAC,CAAC;QACpB,8DAA8D;QAC9D,iBAAY,GAAG,CAAC,CAAC;QACjB,aAAQ,GAAG,CAAC,CAAC;QACb,aAAQ,GAAG,CAAC,CAAC;QACb,cAAS,GAAG,CAAC,CAAC;QACd,sBAAiB,GAAG,CAAC,CAAC;QACtB,mBAAc,GAAG,CAAC,CAAC;QACnB,uBAAkB,GAAG,CAAC,CAAC;QACvB,oBAAe,GAAG,CAAC,CAAC;QACpB,uDAAuD;QAC9C,gBAAW,GAAuC,EAAE,CAAC;QAC9D,6EAA6E;QAC7E,kBAAa,GAAG,CAAC,CAAC;QACT,gBAAW,GAAG,IAAI,kBAAkB,EAAE,CAAC;IA0BlD,CAAC;IAxBC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,KAAoB;;QACxB,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe,CAAC;QAC9C,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC;QAClD,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,kBAAkB,CAAC;QACpD,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,mCAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YACvE,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,CAAa;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;CACF;AA8CD,MAAM,wBAAwB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1D,4FAA4F;AAC5F,MAAM,UAAU,2BAA2B,CAAC,MAA6B;;IACvE,MAAM,GAAG,GAAG,CAAC,MAAA,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACzC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAA,MAAM,CAAC,UAAU,mCAAI,EAAE,CAAC,EAAE,CAAC;QACxD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,0CAA0C,CAAC,CAAC;QAClK,IAAI,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,4BAA4B,CAAC,CAAC;IACxJ,CAAC;AACH,CAAC;AAwCD,6FAA6F;AAE7F,8BAA8B;AAC9B,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,EAAE,CAAC;IACV,EAAE,EAAE,CAAC;IACL,QAAQ,EAAE,CAAC;IACX,UAAU,EAAE,CAAC;CACL,CAAC;AAuCX,yFAAyF;AAEzF,6BAA6B;AAC7B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,CAAC;IACf,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;CACR,CAAC;AAGX,kCAAkC;AAClC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,MAAM,EAAE,CAAC;IACT,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;CACD,CAAC;AA2BX,yFAAyF;AACzF,MAAM,OAAO,kBAAkB;IAG7B,YAAoB,KAAkC;QACpD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAKD,MAAM,CAAC,MAAM,CAAC,SAAuD;QACnE,MAAM,OAAO,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAChD,SAAS,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,GAAiB,EAAE,MAA0B;QAClD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;QAClF,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,MAAM,EAAE,CAAC;IACpI,CAAC;IAED,IAAI,CAAC,IAAY;QACf,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;;AAnBD,yEAAyE;AACzD,0BAAO,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;AAqBvD,MAAM,OAAO,yBAAyB;IAAtC;QACW,UAAK,GAAuB,EAAE,CAAC;IAa1C,CAAC;IAXC,IAAI,CAAC,IAAY,EAAE,SAAyC;QAC1D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAChG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,oBAAoB,IAAI,sBAAsB,CAAC,CAAC;QAClH,OAAO,IAAI,yBAAyB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED,+BAA+B;IAC/B,QAAQ,CAAC,IAAY,EAAE,UAAkB,EAAE,SAA0C;QACnF,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjH,CAAC;CACF;AAED,MAAM,OAAO,yBAAyB;IAKpC,YAAY,KAAgC,EAAE,IAAY,EAAE,SAAyC;QACnG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IAED,WAAW,CAAC,WAA2C;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,CAAC,MAAmF;QACxF,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAEO,IAAI,CACV,MAAmF,EACnF,WAAoD;QAEpD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAC9F,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAuBD,4EAA4E;AAE5E,0GAA0G;AAC1G,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;CACC,CAAC;AAQX,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAQ,KAAyC,CAAC,iBAAiB,KAAK,QAAQ,CAAC;AACzI,CAAC","sourcesContent":["// Twins of G9SyncData.Client/Storage/*.cs: the client store contract, its records, local commands, revocation rules\n// and apply diagnostics. The engine is store-agnostic; `@g9tm/syncdata/sqlite` is the implementation.\nimport type { G9EMoveOutPolicy } from '../abstractions/enums.js';\nimport type { G9Long } from '../abstractions/long.js';\nimport type { G9SyncParameters } from '../abstractions/parameters.js';\nimport type {\n G9DtBackfillRequest,\n G9DtCommand,\n G9DtHelloResult,\n G9DtNegotiatedTable,\n G9DtPullContinuation,\n G9DtPullPlan,\n G9DtPushResult,\n G9DtSnapshotFileRequest,\n G9DtSubscriptionDefinition,\n G9DtSubscriptionRef,\n G9DtSyncChunk,\n G9DtTableColumns,\n G9DtTableDigest,\n} from '../protocol/dtos.js';\nimport type { G9SyncClientModel } from './model.js';\n\n// ---------------------------------------------------------------- server state and subscriptions\n\n/** What the client last learned from the server (`G9CClientServerState`). */\nexport interface G9ClientServerState {\n epoch: string | null;\n lastHelloUtcMs: number | null;\n /** Server clock minus device clock, ms. */\n serverClockOffsetMs: number;\n tables: G9DtNegotiatedTable[];\n definitions: G9DtSubscriptionDefinition[];\n}\n\n/** `G9ESubscriptionState`. */\nexport const G9ESubscriptionState = {\n Active: 0,\n NeedsReconcile: 1,\n Failed: 2,\n} as const;\nexport type G9ESubscriptionState = (typeof G9ESubscriptionState)[keyof typeof G9ESubscriptionState];\n\n/** A local subscription (`G9CSyncSubscriptionRecord`). Times are epoch milliseconds UTC. */\nexport interface G9SyncSubscriptionRecord {\n key: string;\n name: string;\n parameters: G9SyncParameters;\n /** Membership slot (bit) for persistent subscriptions; the shared ephemeral slot otherwise. */\n slot: number;\n ephemeral: boolean;\n ttlMs: number | null;\n cursor: string | null;\n /** The move-out policy the server last announced; kept so it still applies once access is gone. */\n moveOutPolicy: G9EMoveOutPolicy | null;\n definitionHash: string | null;\n authHash: string | null;\n state: G9ESubscriptionState;\n lastErrorCode: string | null;\n createdUtcMs: number;\n lastSuccessUtcMs: number | null;\n lastReconcileUtcMs: number | null;\n lastAccessUtcMs: number | null;\n}\n\n/** `G9CSyncSubscriptionRecord.ToReference()`. */\nexport function toSubscriptionRef(record: G9SyncSubscriptionRecord): G9DtSubscriptionRef {\n return {\n name: record.name,\n parameters: record.parameters.values,\n cursor: record.cursor,\n definitionHash: record.definitionHash,\n authHash: record.authHash,\n };\n}\n\n/** A partial update of a subscription record; absent members are left unchanged (`G9CSubscriptionUpdate`). */\nexport interface G9SubscriptionUpdate {\n cursor?: string | null;\n definitionHash?: string | null;\n authHash?: string | null;\n state?: G9ESubscriptionState | null;\n errorCode?: string | null;\n clearError?: boolean;\n succeeded?: boolean;\n reconciled?: boolean;\n accessed?: boolean;\n clearCursor?: boolean;\n}\n\n// ---------------------------------------------------------------- push and pull\n\n/** A push batch built from dirty rows (`G9CPushBatch`). */\nexport interface G9PushBatch {\n batchId: number;\n /** Highest local change sequence included; rows changed after it stay dirty after the acknowledgement. */\n maxSequence: number;\n frames: Uint8Array[];\n tables: G9DtTableColumns[];\n rowCount: number;\n /** True when the byte budget ended the batch early: more pending rows follow. */\n truncated: boolean;\n /** Rows rejected on the device while building the batch (G9S-REJ-TOO-LARGE). */\n rejectedLocally: number;\n /** Commands carried by this batch, in device order. */\n commands: G9DtCommand[];\n}\n\n/** A pull being staged, persisted across restarts (`G9CStagedPull`). */\nexport interface G9StagedPull {\n runId: string;\n plan: G9DtPullPlan;\n createdUtcMs: number;\n backfills: G9DtBackfillRequest[];\n /** What the world looked like when the plan was made (ADR-0046); a run only resumes a stage whose generation matches. */\n generation: string | null;\n /** The cursor each planned subscription had when the plan was made, by subscription key (ADR-0060). */\n plannedFromCursors: { [subscriptionKey: string]: string | null };\n /** The device clock when the stage began, assigned by the store. */\n stageSequence: number;\n}\n\n/** One committed slice of a staged pull (`G9CApplySlice`). */\nexport interface G9ApplySlice {\n report: G9ApplyReport;\n rowsApplied: number;\n rowsAppliedTotal: number;\n rowsPlanned: number;\n isFinal: boolean;\n}\n\n/** `G9CResumePoint`. */\nexport interface G9ResumePoint {\n continuation: G9DtPullContinuation | null;\n stagedRows: number;\n stagedBytes: number;\n complete: boolean;\n}\n\n// ---------------------------------------------------------------- reports\n\n/** Why a table large enough for index deferral kept its indexes live. */\nexport const REASON_TABLE_NOT_EMPTY = 'table-not-empty';\nconst MAX_FOREIGN_TRIGGER_NAMES = 10;\n\n/** How an apply ran, as opposed to what it changed (`G9CApplyDiagnostics`, ADR-0058). */\n/** A file table copied record for record into an empty table with identical columns (the transfer optimisation). */\nexport const FILE_MODE_COPY = 'copy';\n/** A file table copied into an empty table by column name. */\nexport const FILE_MODE_COLUMNS = 'columns';\n/** A file table merged into a table that held rows or protected rows: changed rows only. */\nexport const FILE_MODE_MERGE = 'merge';\n/** A file table inserted into a table holding only OTHER rows (a second site's first load): every row is new, no per-row diff. */\nexport const FILE_MODE_APPEND = 'append';\n\nexport class G9ApplyDiagnostics {\n transactions = 0;\n transactionsWithTriggersSkipped = 0;\n readonly foreignTriggers: string[] = [];\n readonly deferredIndexes: { [table: string]: number } = {};\n readonly liveIndexReasons: { [table: string]: string } = {};\n readonly rowsByTable: { [table: string]: number } = {};\n readonly msByTable: { [table: string]: number } = {};\n indexRebuildMs = 0;\n elapsedMs = 0;\n /** Snapshot files copied in (ADR-0072). */\n snapshotFiles = 0;\n /** Rows that arrived through snapshot files. */\n fileRows = 0;\n /** Milliseconds spent copying snapshot files, metadata included. */\n fileCopyMs = 0;\n /** How each table came out of a snapshot file: `copy`, `columns` or `merge` (see FILE_MODE_*). */\n readonly fileTables: { [table: string]: string } = {};\n\n /** True when every transaction ran with trigger execution off, false when any ran with it on, null when nothing was applied. */\n get triggersSkipped(): boolean | null {\n return this.transactions === 0 ? null : this.transactionsWithTriggersSkipped === this.transactions;\n }\n\n get deferredIndexCount(): number {\n let total = 0;\n for (const key of Object.keys(this.deferredIndexes)) total += this.deferredIndexes[key] as number;\n return total;\n }\n\n merge(other: G9ApplyDiagnostics): void {\n this.transactions += other.transactions;\n this.transactionsWithTriggersSkipped += other.transactionsWithTriggersSkipped;\n this.indexRebuildMs += other.indexRebuildMs;\n this.elapsedMs += other.elapsedMs;\n this.snapshotFiles += other.snapshotFiles;\n this.fileRows += other.fileRows;\n this.fileCopyMs += other.fileCopyMs;\n for (const key of Object.keys(other.fileTables)) this.fileTables[key] = other.fileTables[key] as string;\n for (const name of other.foreignTriggers) {\n if (this.foreignTriggers.length >= MAX_FOREIGN_TRIGGER_NAMES) break;\n if (!this.foreignTriggers.some((n) => n.toLowerCase() === name.toLowerCase())) this.foreignTriggers.push(name);\n }\n addAll(this.deferredIndexes, other.deferredIndexes);\n for (const key of Object.keys(other.liveIndexReasons)) this.liveIndexReasons[key] = other.liveIndexReasons[key] as string;\n addAll(this.rowsByTable, other.rowsByTable);\n addAll(this.msByTable, other.msByTable);\n }\n\n /** One line for a log: what engaged, what did not and why, and the tables that took the time. */\n toString(): string {\n if (this.transactions === 0) return 'nothing applied';\n let text = `${this.transactions} transaction(s) in ${this.elapsedMs} ms; triggers `;\n text +=\n this.triggersSkipped === true\n ? 'skipped'\n : this.transactionsWithTriggersSkipped === 0\n ? 'LIVE'\n : `skipped in ${this.transactionsWithTriggersSkipped} of ${this.transactions}`;\n if (this.foreignTriggers.length > 0) text += ' (foreign: ' + this.foreignTriggers.join(', ') + ')';\n const deferred = Object.keys(this.deferredIndexes);\n if (deferred.length > 0) {\n text += `; ${this.deferredIndexCount} index(es) rebuilt after the load in ${this.indexRebuildMs} ms (` + deferred.map((t) => t + ':' + this.deferredIndexes[t]).join(', ') + ')';\n }\n const live = Object.keys(this.liveIndexReasons);\n if (live.length > 0) text += '; live indexes on ' + live.map((t) => t + ' (' + this.liveIndexReasons[t] + ')').join(', ');\n if (this.snapshotFiles > 0) {\n text +=\n `; ${this.snapshotFiles} snapshot file(s), ${this.fileRows} rows copied in ${this.fileCopyMs} ms (` +\n Object.keys(this.fileTables)\n .map((t) => t + ':' + this.fileTables[t])\n .join(', ') +\n ')';\n }\n const slowest = Object.keys(this.msByTable)\n .sort((a, b) => (this.msByTable[b] as number) - (this.msByTable[a] as number))\n .slice(0, 4);\n if (slowest.length > 0) {\n text +=\n '; ' +\n slowest\n .map((t) => {\n const ms = this.msByTable[t] as number;\n const rows = this.rowsByTable[t] ?? 0;\n const rate = ms > 0 ? Math.floor((rows * 1000) / ms) : rows;\n return `${t} ${rows} rows in ${ms} ms (${rate}/s)`;\n })\n .join(', ');\n }\n return text;\n }\n}\n\nfunction addAll(target: { [key: string]: number }, source: { [key: string]: number }): void {\n for (const key of Object.keys(source)) target[key] = (target[key] ?? 0) + (source[key] as number);\n}\n\n/** What an apply changed (`G9CApplyReport`). */\nexport class G9ApplyReport {\n upserts = 0;\n deletes = 0;\n moveOuts = 0;\n membershipAdded = 0;\n /** Rows skipped because they carry a pending local change. */\n skippedDirty = 0;\n accepted = 0;\n rejected = 0;\n conflicts = 0;\n commandsCompleted = 0;\n revokedDeleted = 0;\n revokedQuarantined = 0;\n revokedRetained = 0;\n /** Changed keys per local table (capped per table). */\n readonly changedKeys: { [localTable: string]: string[] } = {};\n /** Upserts whose row already held exactly the incoming values (ADR-0058). */\n unchangedRows = 0;\n readonly diagnostics = new G9ApplyDiagnostics();\n\n get total(): number {\n return this.upserts + this.deletes + this.moveOuts;\n }\n\n merge(other: G9ApplyReport): void {\n this.unchangedRows += other.unchangedRows;\n this.diagnostics.merge(other.diagnostics);\n this.upserts += other.upserts;\n this.deletes += other.deletes;\n this.moveOuts += other.moveOuts;\n this.membershipAdded += other.membershipAdded;\n this.skippedDirty += other.skippedDirty;\n this.accepted += other.accepted;\n this.rejected += other.rejected;\n this.conflicts += other.conflicts;\n this.commandsCompleted += other.commandsCompleted;\n this.revokedDeleted += other.revokedDeleted;\n this.revokedQuarantined += other.revokedQuarantined;\n this.revokedRetained += other.revokedRetained;\n for (const table of Object.keys(other.changedKeys)) {\n const list = this.changedKeys[table] ?? (this.changedKeys[table] = []);\n for (const key of other.changedKeys[table] as string[]) list.push(key);\n }\n }\n}\n\n/** A local row as seen by reconciliation (`G9CLocalRowEntry`). */\nexport interface G9LocalRowEntry {\n key: string;\n bucket: number;\n version: number;\n hash: G9Long;\n member: boolean;\n dirty: boolean;\n}\n\nexport interface G9PendingTable {\n localTable: string;\n upserts: number;\n deletes: number;\n rejected: number;\n}\n\nexport interface G9PendingSummary {\n totalRows: number;\n rejectedRows: number;\n /** Commands recorded on the device and not yet executed by the server. */\n pendingCommands: number;\n tables: G9PendingTable[];\n}\n\n/** One entry of the local change feed (`G9CChangeFeedEntry`). */\nexport interface G9ChangeFeedEntry {\n sequence: number;\n key: string;\n deleted: boolean;\n localPending: boolean;\n}\n\n/**\n * Narrows a change-feed read to the keys a query of the app's own tables selects (`G9CChangeFeedKeyFilter`): a projection of one\n * site no longer walks the entries of every other site. Deletions are always returned - their rows are gone, so no query can place\n * them. `keySql` is one SELECT of one column, embedded as `pk IN (...)`; parameters are bound by name (`$name`, `@name`, `:name`)\n * and `$g9t`, `$g9a`, `$g9l` belong to the read.\n */\nexport interface G9ChangeFeedKeyFilter {\n keySql: string;\n parameters?: { [name: string]: string | number | null };\n}\n\nconst RESERVED_FEED_PARAMETERS = ['$g9t', '$g9a', '$g9l'];\n\n/** Throws when the filter cannot be embedded safely (`G9CChangeFeedKeyFilter.Validate`). */\nexport function validateChangeFeedKeyFilter(filter: G9ChangeFeedKeyFilter): void {\n const sql = (filter.keySql ?? '').trim();\n if (sql.slice(0, 6).toUpperCase() !== 'SELECT' || sql.indexOf(';') >= 0) {\n throw new Error('A change-feed key filter is a single SELECT statement of one column.');\n }\n for (const name of Object.keys(filter.parameters ?? {})) {\n if (name.length < 2 || '$@:'.indexOf(name[0] as string) < 0) throw new Error(`Change-feed key filter parameter '${name}' must be named ($name, @name or :name).`);\n if (RESERVED_FEED_PARAMETERS.indexOf(name.toLowerCase()) >= 0) throw new Error(`Change-feed key filter parameter '${name}' is reserved by the read.`);\n }\n}\n\nexport interface G9SyncRejection {\n localTable: string;\n key: string;\n code: string;\n message: string | null;\n sqlState: string | null;\n constraint: string | null;\n column: string | null;\n details: string | null;\n atUtcMs: number;\n}\n\n/** A persisted summary of one run (`G9CSyncRunReport`); serialized with the .NET JSON names into g9_runs. */\nexport interface G9SyncRunReport {\n runId: string;\n startedUtcMs: number;\n durationMs: number;\n outcome: string;\n priority: string;\n errorCode: string | null;\n errorMessage: string | null;\n pushed: number;\n rejected: number;\n conflicts: number;\n downloaded: number;\n applied: number;\n downloadedBytes: number;\n subscriptions: string[];\n phaseMs: { [phase: string]: number };\n triggersSkipped: boolean | null;\n foreignTriggers: string[];\n applyTransactions: number;\n indexesDeferred: number;\n indexRebuildMs: number;\n liveIndexReasons: { [table: string]: string };\n unchangedRows: number;\n}\n\n// ---------------------------------------------------------------- local commands (ADR-0025)\n\n/** `G9ELocalCommandState`. */\nexport const G9ELocalCommandState = {\n Pending: 0,\n Ok: 1,\n Rejected: 2,\n Superseded: 3,\n} as const;\nexport type G9ELocalCommandState = (typeof G9ELocalCommandState)[keyof typeof G9ELocalCommandState];\n\n/** A command recorded on this device (`G9CLocalCommand`). */\nexport interface G9LocalCommand {\n commandId: string;\n sequence: number;\n name: string;\n version: number;\n payload: string;\n createdUtcMs: number;\n state: G9ELocalCommandState;\n code: string | null;\n message: string | null;\n result: string | null;\n completedUtcMs: number | null;\n}\n\n/** What to record (`G9CCommandRequest`). */\nexport interface G9CommandRequest {\n name: string;\n version?: number;\n /** JSON payload for the server's handler. */\n payload: string;\n}\n\n/** A value an app binds through {@link G9LocalCommandWriter}: the SQLite driver's value forms, plus booleans. */\nexport type G9LocalSqlArgument = null | number | string | boolean | ArrayBuffer | Uint8Array | { int64: string } | G9Long;\n\n/**\n * Writes a command's local effects in the transaction that records it (`IG9LocalCommandWriter`). Rows written here are\n * not uploaded as row changes; they are protected from pulls until the server's result arrives.\n */\nexport interface G9LocalCommandWriter {\n /** Executes SQL; parameters bind positionally as `$p0`, `$p1`, … */\n execute(sql: string, ...args: G9LocalSqlArgument[]): Promise<number>;\n scalar(sql: string, ...args: G9LocalSqlArgument[]): Promise<unknown>;\n}\n\n// ---------------------------------------------------------------- revocation (ADR-0026)\n\n/** `G9ERevocationReason`. */\nexport const G9ERevocationReason = {\n LeftScope: 0,\n Unsubscribed: 1,\n Expired: 2,\n AccessRevoked: 3,\n} as const;\nexport type G9ERevocationReason = (typeof G9ERevocationReason)[keyof typeof G9ERevocationReason];\n\n/** `G9ERevocationDisposition`. */\nexport const G9ERevocationDisposition = {\n Delete: 0,\n MarkRevoked: 1,\n Quarantine: 2,\n Retain: 3,\n} as const;\nexport type G9ERevocationDisposition = (typeof G9ERevocationDisposition)[keyof typeof G9ERevocationDisposition];\n\n/** A row no subscription holds any more, as a revocation rule sees it (`G9CRevokedRow`). */\nexport interface G9RevokedRow {\n localTable: string;\n key: string;\n reason: G9ERevocationReason;\n subscriptionKey: string | null;\n hasPendingChanges: boolean;\n isRejected: boolean;\n /** Column values (key included) as stored locally; empty when the row no longer exists locally. */\n values: { [column: string]: unknown };\n}\n\n/** Lets a custom rule change the row before its disposition applies. */\nexport interface G9RevokedRowEditor {\n set(column: string, value: unknown): void;\n}\n\nexport interface G9RevocationRule {\n readonly name: string;\n readonly condition: (row: G9RevokedRow) => boolean;\n readonly decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition;\n readonly retainWhile: ((row: G9RevokedRow) => boolean) | null;\n}\n\n/** Ordered revocation rules (`G9CRevocationPolicy`): the first matching rule decides. */\nexport class G9RevocationPolicy {\n readonly rules: readonly G9RevocationRule[];\n\n private constructor(rules: readonly G9RevocationRule[]) {\n this.rules = rules;\n }\n\n /** No rules: delete clean rows, quarantine rows with pending changes. */\n static readonly default = new G9RevocationPolicy([]);\n\n static create(configure: (builder: G9RevocationPolicyBuilder) => void): G9RevocationPolicy {\n const builder = new G9RevocationPolicyBuilder();\n configure(builder);\n return new G9RevocationPolicy(builder.rules.slice());\n }\n\n decide(row: G9RevokedRow, editor: G9RevokedRowEditor): { rule: G9RevocationRule | null; disposition: G9ERevocationDisposition } {\n for (const rule of this.rules) {\n if (rule.condition(row)) return { rule, disposition: rule.decide(row, editor) };\n }\n return { rule: null, disposition: row.hasPendingChanges ? G9ERevocationDisposition.Quarantine : G9ERevocationDisposition.Delete };\n }\n\n find(name: string): G9RevocationRule | null {\n for (const rule of this.rules) if (rule.name === name) return rule;\n return null;\n }\n}\n\nexport class G9RevocationPolicyBuilder {\n readonly rules: G9RevocationRule[] = [];\n\n when(name: string, condition: (row: G9RevokedRow) => boolean): G9RevocationActionBuilder {\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A rule needs a name.');\n if (this.rules.some((r) => r.name === name)) throw new RangeError(`Revocation rule '${name}' is declared twice.`);\n return new G9RevocationActionBuilder(this, name, condition);\n }\n\n /** Rows of one local table. */\n forTable(name: string, localTable: string, condition?: (row: G9RevokedRow) => boolean): G9RevocationActionBuilder {\n const table = localTable.toLowerCase();\n return this.when(name, (row) => row.localTable.toLowerCase() === table && (condition ? condition(row) : true));\n }\n}\n\nexport class G9RevocationActionBuilder {\n private readonly _owner: G9RevocationPolicyBuilder;\n private readonly _name: string;\n private readonly _condition: (row: G9RevokedRow) => boolean;\n\n constructor(owner: G9RevocationPolicyBuilder, name: string, condition: (row: G9RevokedRow) => boolean) {\n this._owner = owner;\n this._name = name;\n this._condition = condition;\n }\n\n delete(): G9RevocationPolicyBuilder {\n return this._add(() => G9ERevocationDisposition.Delete, null);\n }\n\n markRevoked(): G9RevocationPolicyBuilder {\n return this._add(() => G9ERevocationDisposition.MarkRevoked, null);\n }\n\n quarantine(): G9RevocationPolicyBuilder {\n return this._add(() => G9ERevocationDisposition.Quarantine, null);\n }\n\n retainWhile(retainWhile: (row: G9RevokedRow) => boolean): G9RevocationPolicyBuilder {\n return this._add(() => G9ERevocationDisposition.Retain, retainWhile);\n }\n\n custom(decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition): G9RevocationPolicyBuilder {\n return this._add(decide, null);\n }\n\n private _add(\n decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition,\n retainWhile: ((row: G9RevokedRow) => boolean) | null,\n ): G9RevocationPolicyBuilder {\n this._owner.rules.push({ name: this._name, condition: this._condition, decide, retainWhile });\n return this._owner;\n }\n}\n\n/** A row in the holding area (`G9CQuarantinedRow`). */\nexport interface G9QuarantinedRow {\n localTable: string;\n key: string;\n reason: G9ERevocationReason;\n rule: string | null;\n hadPendingChanges: boolean;\n values: { [column: string]: unknown };\n atUtcMs: number;\n}\n\n/** A row kept in the app's table after revocation (`G9CRetainedRow`). */\nexport interface G9RetainedRow {\n localTable: string;\n key: string;\n disposition: G9ERevocationDisposition;\n reason: G9ERevocationReason;\n rule: string | null;\n atUtcMs: number;\n}\n\n// ---------------------------------------------------------------- failures\n\n/** What went wrong inside a client store, in terms an application can act on (`G9ELocalStoreFailure`). */\nexport const G9ELocalStoreFailure = {\n Other: 0,\n Corrupt: 1,\n DiskFull: 2,\n Busy: 3,\n} as const;\nexport type G9ELocalStoreFailure = (typeof G9ELocalStoreFailure)[keyof typeof G9ELocalStoreFailure];\n\n/** Implemented by a store's errors so the engine can give a run's failure a stable code (`IG9SyncLocalStoreFailure`). */\nexport interface G9SyncLocalStoreFailure {\n readonly localStoreFailure: G9ELocalStoreFailure;\n}\n\nexport function isLocalStoreFailure(error: unknown): error is G9SyncLocalStoreFailure {\n return typeof error === 'object' && error !== null && typeof (error as { localStoreFailure?: unknown }).localStoreFailure === 'number';\n}\n\n// ---------------------------------------------------------------- the store contract\n\n/**\n * The client storage provider (`IG9SyncClientStore`): local tables, change capture, subscription membership,\n * staging, apply and metadata. Every method takes an optional AbortSignal (the CancellationToken twin).\n */\nexport interface G9SyncClientStore {\n initialize(model: G9SyncClientModel, signal?: AbortSignal): Promise<void>;\n getClientId(signal?: AbortSignal): Promise<string>;\n getServerState(signal?: AbortSignal): Promise<G9ClientServerState>;\n saveHello(hello: G9DtHelloResult, signal?: AbortSignal): Promise<void>;\n getPendingBackfills(signal?: AbortSignal): Promise<G9DtBackfillRequest[]>;\n\n getSubscriptions(signal?: AbortSignal): Promise<G9SyncSubscriptionRecord[]>;\n ensureSubscription(\n name: string,\n parameters: G9SyncParameters,\n ephemeral: boolean,\n ttlMs: number | null,\n adoptExistingRows: boolean,\n signal?: AbortSignal,\n ): Promise<G9SyncSubscriptionRecord>;\n removeSubscription(key: string, policy: G9EMoveOutPolicy, signal?: AbortSignal): Promise<void>;\n releaseSubscriptionRows(key: string, signal?: AbortSignal): Promise<G9ApplyReport>;\n updateSubscription(key: string, update: G9SubscriptionUpdate, signal?: AbortSignal): Promise<void>;\n collectExpiredEphemeral(utcNowMs: number, signal?: AbortSignal): Promise<number>;\n\n buildPushBatch(tables: readonly G9DtNegotiatedTable[], maxRows: number, maxBytes: number, signal?: AbortSignal): Promise<G9PushBatch | null>;\n forgetUploadedRows(localTable: string, keys: readonly string[] | null, signal?: AbortSignal): Promise<number>;\n applyPushResult(batch: G9PushBatch, result: G9DtPushResult, signal?: AbortSignal): Promise<G9ApplyReport>;\n\n getStagedPull(signal?: AbortSignal): Promise<G9StagedPull | null>;\n /** The newest staged pull planned under exactly this generation, or null (ADR-0060). */\n getStagedPullForGeneration(generation: string, signal?: AbortSignal): Promise<G9StagedPull | null>;\n beginStagedPull(pull: G9StagedPull, signal?: AbortSignal): Promise<void>;\n pruneStagedPulls(olderThanUtcMs: number, maxBytes: number, keepGeneration: string | null, signal?: AbortSignal): Promise<number>;\n discardAllStagedPulls(signal?: AbortSignal): Promise<number>;\n stageChunk(runId: string, chunk: G9DtSyncChunk, signal?: AbortSignal): Promise<void>;\n /**\n * The store's offer to receive large first downloads as SQLite snapshot files (ADR-0072), or null for rows only. A store that\n * makes an offer stages file segments (`chunk.file`) in `stageChunk` and copies the files in `applyStagedPull`.\n */\n describeSnapshotFiles?(negotiated: readonly G9DtNegotiatedTable[]): G9DtSnapshotFileRequest | null;\n getResumePoint(runId: string, signal?: AbortSignal): Promise<G9ResumePoint>;\n applyStagedPull(\n runId: string,\n rowsApplied: ((rows: number) => void) | null,\n slices: ((slice: G9ApplySlice) => void) | null,\n signal?: AbortSignal,\n ): Promise<G9ApplyReport>;\n discardStagedPull(runId: string, signal?: AbortSignal): Promise<void>;\n\n computeDigest(subscriptionKey: string, table: G9DtNegotiatedTable, signal?: AbortSignal): Promise<G9DtTableDigest>;\n readLocalEntries(\n subscriptionKey: string,\n table: G9DtNegotiatedTable,\n buckets: ReadonlySet<number>,\n serverKeys: ReadonlySet<string>,\n signal?: AbortSignal,\n ): Promise<G9LocalRowEntry[]>;\n applyReconcile(\n subscriptionKey: string,\n table: G9DtNegotiatedTable,\n fetchedFrames: readonly Uint8Array[],\n addMembership: readonly string[],\n moveOut: readonly string[],\n policy: G9EMoveOutPolicy,\n signal?: AbortSignal,\n ): Promise<G9ApplyReport>;\n\n getPendingSummary(signal?: AbortSignal): Promise<G9PendingSummary>;\n enqueueCommand(\n request: G9CommandRequest,\n applyLocally: ((writer: G9LocalCommandWriter, signal?: AbortSignal) => Promise<void>) | null,\n signal?: AbortSignal,\n ): Promise<G9LocalCommand>;\n getQuarantined(signal?: AbortSignal): Promise<G9QuarantinedRow[]>;\n restoreQuarantined(localTable: string, key: string, signal?: AbortSignal): Promise<number>;\n discardQuarantined(localTable: string | null, key: string | null, signal?: AbortSignal): Promise<number>;\n getRetained(signal?: AbortSignal): Promise<G9RetainedRow[]>;\n reevaluateRetained(signal?: AbortSignal): Promise<number>;\n getCommands(state: G9ELocalCommandState | null, limit: number, signal?: AbortSignal): Promise<G9LocalCommand[]>;\n readChangeFeed(localTable: string, afterSequence: number, limit: number, signal?: AbortSignal): Promise<G9ChangeFeedEntry[]>;\n /** The feed narrowed to the keys `keyFilter` selects, plus every deletion; fewer than `limit` entries means the read is complete. */\n readChangeFeedFiltered(localTable: string, afterSequence: number, limit: number, keyFilter: G9ChangeFeedKeyFilter, signal?: AbortSignal): Promise<G9ChangeFeedEntry[]>;\n getChangeSequence(signal?: AbortSignal): Promise<number>;\n getChangeFeedFloor(signal?: AbortSignal): Promise<number>;\n getRejections(signal?: AbortSignal): Promise<G9SyncRejection[]>;\n retryRejected(localTable: string | null, key: string | null, signal?: AbortSignal): Promise<number>;\n markDirty(localTable: string, keys: readonly string[], signal?: AbortSignal): Promise<number>;\n adoptExistingRows(signal?: AbortSignal): Promise<number>;\n saveRunReport(report: G9SyncRunReport, keep: number, signal?: AbortSignal): Promise<void>;\n getRecentRunReports(count: number, signal?: AbortSignal): Promise<G9SyncRunReport[]>;\n getPhaseStatistics(signal?: AbortSignal): Promise<{ [key: string]: number }>;\n recordPhaseStatistics(samples: { [key: string]: number }, signal?: AbortSignal): Promise<void>;\n purgeDeletedFeed(keep: number, signal?: AbortSignal): Promise<number>;\n dispose(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"storeTypes.js","sourceRoot":"","sources":["../../src/client/storeTypes.ts"],"names":[],"mappings":"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","sourcesContent":["// Twins of G9SyncData.Client/Storage/*.cs: the client store contract, its records, local commands, revocation rules\r\n// and apply diagnostics. The engine is store-agnostic; `@g9tm/syncdata/sqlite` is the implementation.\r\nimport type { G9EMoveOutPolicy } from '../abstractions/enums.js';\r\nimport type { G9Long } from '../abstractions/long.js';\r\nimport type { G9SyncParameters } from '../abstractions/parameters.js';\r\nimport type {\r\n G9DtBackfillRequest,\r\n G9DtCommand,\r\n G9DtHelloResult,\r\n G9DtNegotiatedTable,\r\n G9DtPullContinuation,\r\n G9DtPullPlan,\r\n G9DtPushResult,\r\n G9DtSnapshotFileRequest,\r\n G9DtSubscriptionDefinition,\r\n G9DtSubscriptionRef,\r\n G9DtSyncChunk,\r\n G9DtTableColumns,\r\n G9DtTableDigest,\r\n} from '../protocol/dtos.js';\r\nimport type { G9SyncClientModel } from './model.js';\r\n\r\n// ---------------------------------------------------------------- server state and subscriptions\r\n\r\n/** What the client last learned from the server (`G9CClientServerState`). */\r\nexport interface G9ClientServerState {\r\n epoch: string | null;\r\n lastHelloUtcMs: number | null;\r\n /** Server clock minus device clock, ms. */\r\n serverClockOffsetMs: number;\r\n tables: G9DtNegotiatedTable[];\r\n definitions: G9DtSubscriptionDefinition[];\r\n}\r\n\r\n/** `G9ESubscriptionState`. */\r\nexport const G9ESubscriptionState = {\r\n Active: 0,\r\n NeedsReconcile: 1,\r\n Failed: 2,\r\n} as const;\r\nexport type G9ESubscriptionState = (typeof G9ESubscriptionState)[keyof typeof G9ESubscriptionState];\r\n\r\n/** A local subscription (`G9CSyncSubscriptionRecord`). Times are epoch milliseconds UTC. */\r\nexport interface G9SyncSubscriptionRecord {\r\n key: string;\r\n name: string;\r\n parameters: G9SyncParameters;\r\n /** Membership slot (bit) for persistent subscriptions; the shared ephemeral slot otherwise. */\r\n slot: number;\r\n ephemeral: boolean;\r\n ttlMs: number | null;\r\n cursor: string | null;\r\n /** The move-out policy the server last announced; kept so it still applies once access is gone. */\r\n moveOutPolicy: G9EMoveOutPolicy | null;\r\n definitionHash: string | null;\r\n authHash: string | null;\r\n state: G9ESubscriptionState;\r\n lastErrorCode: string | null;\r\n createdUtcMs: number;\r\n lastSuccessUtcMs: number | null;\r\n lastReconcileUtcMs: number | null;\r\n lastAccessUtcMs: number | null;\r\n}\r\n\r\n/** `G9CSyncSubscriptionRecord.ToReference()`. */\r\nexport function toSubscriptionRef(record: G9SyncSubscriptionRecord): G9DtSubscriptionRef {\r\n return {\r\n name: record.name,\r\n parameters: record.parameters.values,\r\n cursor: record.cursor,\r\n definitionHash: record.definitionHash,\r\n authHash: record.authHash,\r\n };\r\n}\r\n\r\n/** A partial update of a subscription record; absent members are left unchanged (`G9CSubscriptionUpdate`). */\r\nexport interface G9SubscriptionUpdate {\r\n cursor?: string | null;\r\n definitionHash?: string | null;\r\n authHash?: string | null;\r\n state?: G9ESubscriptionState | null;\r\n errorCode?: string | null;\r\n clearError?: boolean;\r\n succeeded?: boolean;\r\n reconciled?: boolean;\r\n accessed?: boolean;\r\n clearCursor?: boolean;\r\n}\r\n\r\n// ---------------------------------------------------------------- push and pull\r\n\r\n/** A push batch built from dirty rows (`G9CPushBatch`). */\r\nexport interface G9PushBatch {\r\n batchId: number;\r\n /** Highest local change sequence included; rows changed after it stay dirty after the acknowledgement. */\r\n maxSequence: number;\r\n frames: Uint8Array[];\r\n tables: G9DtTableColumns[];\r\n rowCount: number;\r\n /** True when the byte budget ended the batch early: more pending rows follow. */\r\n truncated: boolean;\r\n /** Rows rejected on the device while building the batch (G9S-REJ-TOO-LARGE). */\r\n rejectedLocally: number;\r\n /** Commands carried by this batch, in device order. */\r\n commands: G9DtCommand[];\r\n}\r\n\r\n/** A pull being staged, persisted across restarts (`G9CStagedPull`). */\r\nexport interface G9StagedPull {\r\n runId: string;\r\n plan: G9DtPullPlan;\r\n createdUtcMs: number;\r\n backfills: G9DtBackfillRequest[];\r\n /** What the world looked like when the plan was made (ADR-0046); a run only resumes a stage whose generation matches. */\r\n generation: string | null;\r\n /** The cursor each planned subscription had when the plan was made, by subscription key (ADR-0060). */\r\n plannedFromCursors: { [subscriptionKey: string]: string | null };\r\n /** The device clock when the stage began, assigned by the store. */\r\n stageSequence: number;\r\n}\r\n\r\n/** One committed slice of a staged pull (`G9CApplySlice`). */\r\nexport interface G9ApplySlice {\r\n report: G9ApplyReport;\r\n rowsApplied: number;\r\n rowsAppliedTotal: number;\r\n rowsPlanned: number;\r\n isFinal: boolean;\r\n}\r\n\r\n/** `G9CResumePoint`. */\r\nexport interface G9ResumePoint {\r\n continuation: G9DtPullContinuation | null;\r\n stagedRows: number;\r\n stagedBytes: number;\r\n complete: boolean;\r\n}\r\n\r\n// ---------------------------------------------------------------- reports\r\n\r\n/** Why a table large enough for index deferral kept its indexes live. */\r\nexport const REASON_TABLE_NOT_EMPTY = 'table-not-empty';\r\nconst MAX_FOREIGN_TRIGGER_NAMES = 10;\r\n\r\n/** How an apply ran, as opposed to what it changed (`G9CApplyDiagnostics`, ADR-0058). */\r\n/** A file table copied record for record into an empty table with identical columns (the transfer optimisation). */\r\nexport const FILE_MODE_COPY = 'copy';\r\n/** A file table copied into an empty table by column name. */\r\nexport const FILE_MODE_COLUMNS = 'columns';\r\n/** A file table merged into a table that held rows or protected rows: changed rows only. */\r\nexport const FILE_MODE_MERGE = 'merge';\r\n/** A file table inserted into a table holding only OTHER rows (a second site's first load): every row is new, no per-row diff. */\r\nexport const FILE_MODE_APPEND = 'append';\r\n\r\nexport class G9ApplyDiagnostics {\r\n transactions = 0;\r\n transactionsWithTriggersSkipped = 0;\r\n readonly foreignTriggers: string[] = [];\r\n readonly deferredIndexes: { [table: string]: number } = {};\r\n readonly liveIndexReasons: { [table: string]: string } = {};\r\n readonly rowsByTable: { [table: string]: number } = {};\r\n readonly msByTable: { [table: string]: number } = {};\r\n indexRebuildMs = 0;\r\n elapsedMs = 0;\r\n /** Snapshot files copied in (ADR-0072). */\r\n snapshotFiles = 0;\r\n /** Rows that arrived through snapshot files. */\r\n fileRows = 0;\r\n /** Milliseconds spent copying snapshot files, metadata included. */\r\n fileCopyMs = 0;\r\n /** How each table came out of a snapshot file: `copy`, `columns` or `merge` (see FILE_MODE_*). */\r\n readonly fileTables: { [table: string]: string } = {};\r\n\r\n /** True when every transaction ran with trigger execution off, false when any ran with it on, null when nothing was applied. */\r\n get triggersSkipped(): boolean | null {\r\n return this.transactions === 0 ? null : this.transactionsWithTriggersSkipped === this.transactions;\r\n }\r\n\r\n get deferredIndexCount(): number {\r\n let total = 0;\r\n for (const key of Object.keys(this.deferredIndexes)) total += this.deferredIndexes[key] as number;\r\n return total;\r\n }\r\n\r\n merge(other: G9ApplyDiagnostics): void {\r\n this.transactions += other.transactions;\r\n this.transactionsWithTriggersSkipped += other.transactionsWithTriggersSkipped;\r\n this.indexRebuildMs += other.indexRebuildMs;\r\n this.elapsedMs += other.elapsedMs;\r\n this.snapshotFiles += other.snapshotFiles;\r\n this.fileRows += other.fileRows;\r\n this.fileCopyMs += other.fileCopyMs;\r\n for (const key of Object.keys(other.fileTables)) this.fileTables[key] = other.fileTables[key] as string;\r\n for (const name of other.foreignTriggers) {\r\n if (this.foreignTriggers.length >= MAX_FOREIGN_TRIGGER_NAMES) break;\r\n if (!this.foreignTriggers.some((n) => n.toLowerCase() === name.toLowerCase())) this.foreignTriggers.push(name);\r\n }\r\n addAll(this.deferredIndexes, other.deferredIndexes);\r\n for (const key of Object.keys(other.liveIndexReasons)) this.liveIndexReasons[key] = other.liveIndexReasons[key] as string;\r\n addAll(this.rowsByTable, other.rowsByTable);\r\n addAll(this.msByTable, other.msByTable);\r\n }\r\n\r\n /** One line for a log: what engaged, what did not and why, and the tables that took the time. */\r\n toString(): string {\r\n if (this.transactions === 0) return 'nothing applied';\r\n let text = `${this.transactions} transaction(s) in ${this.elapsedMs} ms; triggers `;\r\n text +=\r\n this.triggersSkipped === true\r\n ? 'skipped'\r\n : this.transactionsWithTriggersSkipped === 0\r\n ? 'LIVE'\r\n : `skipped in ${this.transactionsWithTriggersSkipped} of ${this.transactions}`;\r\n if (this.foreignTriggers.length > 0) text += ' (foreign: ' + this.foreignTriggers.join(', ') + ')';\r\n const deferred = Object.keys(this.deferredIndexes);\r\n if (deferred.length > 0) {\r\n text += `; ${this.deferredIndexCount} index(es) rebuilt after the load in ${this.indexRebuildMs} ms (` + deferred.map((t) => t + ':' + this.deferredIndexes[t]).join(', ') + ')';\r\n }\r\n const live = Object.keys(this.liveIndexReasons);\r\n if (live.length > 0) text += '; live indexes on ' + live.map((t) => t + ' (' + this.liveIndexReasons[t] + ')').join(', ');\r\n if (this.snapshotFiles > 0) {\r\n text +=\r\n `; ${this.snapshotFiles} snapshot file(s), ${this.fileRows} rows copied in ${this.fileCopyMs} ms (` +\r\n Object.keys(this.fileTables)\r\n .map((t) => t + ':' + this.fileTables[t])\r\n .join(', ') +\r\n ')';\r\n }\r\n const slowest = Object.keys(this.msByTable)\r\n .sort((a, b) => (this.msByTable[b] as number) - (this.msByTable[a] as number))\r\n .slice(0, 4);\r\n if (slowest.length > 0) {\r\n text +=\r\n '; ' +\r\n slowest\r\n .map((t) => {\r\n const ms = this.msByTable[t] as number;\r\n const rows = this.rowsByTable[t] ?? 0;\r\n const rate = ms > 0 ? Math.floor((rows * 1000) / ms) : rows;\r\n return `${t} ${rows} rows in ${ms} ms (${rate}/s)`;\r\n })\r\n .join(', ');\r\n }\r\n return text;\r\n }\r\n}\r\n\r\nfunction addAll(target: { [key: string]: number }, source: { [key: string]: number }): void {\r\n for (const key of Object.keys(source)) target[key] = (target[key] ?? 0) + (source[key] as number);\r\n}\r\n\r\n/** What an apply changed (`G9CApplyReport`). */\r\nexport class G9ApplyReport {\r\n upserts = 0;\r\n deletes = 0;\r\n moveOuts = 0;\r\n membershipAdded = 0;\r\n /** Rows skipped because they carry a pending local change. */\r\n skippedDirty = 0;\r\n accepted = 0;\r\n rejected = 0;\r\n conflicts = 0;\r\n commandsCompleted = 0;\r\n revokedDeleted = 0;\r\n revokedQuarantined = 0;\r\n revokedRetained = 0;\r\n /** Changed keys per local table (capped per table). */\r\n readonly changedKeys: { [localTable: string]: string[] } = {};\r\n /** Upserts whose row already held exactly the incoming values (ADR-0058). */\r\n unchangedRows = 0;\r\n readonly diagnostics = new G9ApplyDiagnostics();\r\n\r\n get total(): number {\r\n return this.upserts + this.deletes + this.moveOuts;\r\n }\r\n\r\n merge(other: G9ApplyReport): void {\r\n this.unchangedRows += other.unchangedRows;\r\n this.diagnostics.merge(other.diagnostics);\r\n this.upserts += other.upserts;\r\n this.deletes += other.deletes;\r\n this.moveOuts += other.moveOuts;\r\n this.membershipAdded += other.membershipAdded;\r\n this.skippedDirty += other.skippedDirty;\r\n this.accepted += other.accepted;\r\n this.rejected += other.rejected;\r\n this.conflicts += other.conflicts;\r\n this.commandsCompleted += other.commandsCompleted;\r\n this.revokedDeleted += other.revokedDeleted;\r\n this.revokedQuarantined += other.revokedQuarantined;\r\n this.revokedRetained += other.revokedRetained;\r\n for (const table of Object.keys(other.changedKeys)) {\r\n const list = this.changedKeys[table] ?? (this.changedKeys[table] = []);\r\n for (const key of other.changedKeys[table] as string[]) list.push(key);\r\n }\r\n }\r\n}\r\n\r\n/** A local row as seen by reconciliation (`G9CLocalRowEntry`). */\r\nexport interface G9LocalRowEntry {\r\n key: string;\r\n bucket: number;\r\n version: number;\r\n hash: G9Long;\r\n member: boolean;\r\n dirty: boolean;\r\n}\r\n\r\nexport interface G9PendingTable {\r\n localTable: string;\r\n upserts: number;\r\n deletes: number;\r\n rejected: number;\r\n}\r\n\r\nexport interface G9PendingSummary {\r\n totalRows: number;\r\n rejectedRows: number;\r\n /** Commands recorded on the device and not yet executed by the server. */\r\n pendingCommands: number;\r\n tables: G9PendingTable[];\r\n}\r\n\r\n/** One entry of the local change feed (`G9CChangeFeedEntry`). */\r\nexport interface G9ChangeFeedEntry {\r\n sequence: number;\r\n key: string;\r\n deleted: boolean;\r\n localPending: boolean;\r\n}\r\n\r\n/**\r\n * Narrows a change-feed read to the keys a query of the app's own tables selects (`G9CChangeFeedKeyFilter`): a projection of one\r\n * site no longer walks the entries of every other site. Deletions are always returned - their rows are gone, so no query can place\r\n * them. `keySql` is one SELECT of one column, embedded as `pk IN (...)`; parameters are bound by name (`$name`, `@name`, `:name`)\r\n * and `$g9t`, `$g9a`, `$g9l` belong to the read.\r\n */\r\nexport interface G9ChangeFeedKeyFilter {\r\n keySql: string;\r\n parameters?: { [name: string]: string | number | null };\r\n}\r\n\r\nconst RESERVED_FEED_PARAMETERS = ['$g9t', '$g9a', '$g9l'];\r\n\r\n/** Throws when the filter cannot be embedded safely (`G9CChangeFeedKeyFilter.Validate`). */\r\nexport function validateChangeFeedKeyFilter(filter: G9ChangeFeedKeyFilter): void {\r\n const sql = (filter.keySql ?? '').trim();\r\n if (sql.slice(0, 6).toUpperCase() !== 'SELECT' || sql.indexOf(';') >= 0) {\r\n throw new Error('A change-feed key filter is a single SELECT statement of one column.');\r\n }\r\n for (const name of Object.keys(filter.parameters ?? {})) {\r\n if (name.length < 2 || '$@:'.indexOf(name[0] as string) < 0) throw new Error(`Change-feed key filter parameter '${name}' must be named ($name, @name or :name).`);\r\n if (RESERVED_FEED_PARAMETERS.indexOf(name.toLowerCase()) >= 0) throw new Error(`Change-feed key filter parameter '${name}' is reserved by the read.`);\r\n }\r\n}\r\n\r\nexport interface G9SyncRejection {\r\n localTable: string;\r\n key: string;\r\n code: string;\r\n message: string | null;\r\n sqlState: string | null;\r\n constraint: string | null;\r\n column: string | null;\r\n details: string | null;\r\n atUtcMs: number;\r\n}\r\n\r\n/** A persisted summary of one run (`G9CSyncRunReport`); serialized with the .NET JSON names into g9_runs. */\r\nexport interface G9SyncRunReport {\r\n runId: string;\r\n startedUtcMs: number;\r\n durationMs: number;\r\n outcome: string;\r\n priority: string;\r\n errorCode: string | null;\r\n errorMessage: string | null;\r\n pushed: number;\r\n rejected: number;\r\n conflicts: number;\r\n downloaded: number;\r\n applied: number;\r\n downloadedBytes: number;\r\n subscriptions: string[];\r\n phaseMs: { [phase: string]: number };\r\n triggersSkipped: boolean | null;\r\n foreignTriggers: string[];\r\n applyTransactions: number;\r\n indexesDeferred: number;\r\n indexRebuildMs: number;\r\n liveIndexReasons: { [table: string]: string };\r\n unchangedRows: number;\r\n}\r\n\r\n// ---------------------------------------------------------------- local commands (ADR-0025)\r\n\r\n/** `G9ELocalCommandState`. */\r\nexport const G9ELocalCommandState = {\r\n Pending: 0,\r\n Ok: 1,\r\n Rejected: 2,\r\n Superseded: 3,\r\n} as const;\r\nexport type G9ELocalCommandState = (typeof G9ELocalCommandState)[keyof typeof G9ELocalCommandState];\r\n\r\n/** A command recorded on this device (`G9CLocalCommand`). */\r\nexport interface G9LocalCommand {\r\n commandId: string;\r\n sequence: number;\r\n name: string;\r\n version: number;\r\n payload: string;\r\n createdUtcMs: number;\r\n state: G9ELocalCommandState;\r\n code: string | null;\r\n message: string | null;\r\n result: string | null;\r\n completedUtcMs: number | null;\r\n}\r\n\r\n/** What to record (`G9CCommandRequest`). */\r\nexport interface G9CommandRequest {\r\n name: string;\r\n version?: number;\r\n /** JSON payload for the server's handler. */\r\n payload: string;\r\n}\r\n\r\n/** A value an app binds through {@link G9LocalCommandWriter}: the SQLite driver's value forms, plus booleans. */\r\nexport type G9LocalSqlArgument = null | number | string | boolean | ArrayBuffer | Uint8Array | { int64: string } | G9Long;\r\n\r\n/**\r\n * Writes a command's local effects in the transaction that records it (`IG9LocalCommandWriter`). Rows written here are\r\n * not uploaded as row changes; they are protected from pulls until the server's result arrives.\r\n */\r\nexport interface G9LocalCommandWriter {\r\n /** Executes SQL; parameters bind positionally as `$p0`, `$p1`, … */\r\n execute(sql: string, ...args: G9LocalSqlArgument[]): Promise<number>;\r\n scalar(sql: string, ...args: G9LocalSqlArgument[]): Promise<unknown>;\r\n}\r\n\r\n// ---------------------------------------------------------------- revocation (ADR-0026)\r\n\r\n/** `G9ERevocationReason`. */\r\nexport const G9ERevocationReason = {\r\n LeftScope: 0,\r\n Unsubscribed: 1,\r\n Expired: 2,\r\n AccessRevoked: 3,\r\n} as const;\r\nexport type G9ERevocationReason = (typeof G9ERevocationReason)[keyof typeof G9ERevocationReason];\r\n\r\n/** `G9ERevocationDisposition`. */\r\nexport const G9ERevocationDisposition = {\r\n Delete: 0,\r\n MarkRevoked: 1,\r\n Quarantine: 2,\r\n Retain: 3,\r\n} as const;\r\nexport type G9ERevocationDisposition = (typeof G9ERevocationDisposition)[keyof typeof G9ERevocationDisposition];\r\n\r\n/** A row no subscription holds any more, as a revocation rule sees it (`G9CRevokedRow`). */\r\nexport interface G9RevokedRow {\r\n localTable: string;\r\n key: string;\r\n reason: G9ERevocationReason;\r\n subscriptionKey: string | null;\r\n hasPendingChanges: boolean;\r\n isRejected: boolean;\r\n /** Column values (key included) as stored locally; empty when the row no longer exists locally. */\r\n values: { [column: string]: unknown };\r\n}\r\n\r\n/** Lets a custom rule change the row before its disposition applies. */\r\nexport interface G9RevokedRowEditor {\r\n set(column: string, value: unknown): void;\r\n}\r\n\r\nexport interface G9RevocationRule {\r\n readonly name: string;\r\n readonly condition: (row: G9RevokedRow) => boolean;\r\n readonly decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition;\r\n readonly retainWhile: ((row: G9RevokedRow) => boolean) | null;\r\n}\r\n\r\n/** Ordered revocation rules (`G9CRevocationPolicy`): the first matching rule decides. */\r\nexport class G9RevocationPolicy {\r\n readonly rules: readonly G9RevocationRule[];\r\n\r\n private constructor(rules: readonly G9RevocationRule[]) {\r\n this.rules = rules;\r\n }\r\n\r\n /** No rules: delete clean rows, quarantine rows with pending changes. */\r\n static readonly default = new G9RevocationPolicy([]);\r\n\r\n static create(configure: (builder: G9RevocationPolicyBuilder) => void): G9RevocationPolicy {\r\n const builder = new G9RevocationPolicyBuilder();\r\n configure(builder);\r\n return new G9RevocationPolicy(builder.rules.slice());\r\n }\r\n\r\n decide(row: G9RevokedRow, editor: G9RevokedRowEditor): { rule: G9RevocationRule | null; disposition: G9ERevocationDisposition } {\r\n for (const rule of this.rules) {\r\n if (rule.condition(row)) return { rule, disposition: rule.decide(row, editor) };\r\n }\r\n return { rule: null, disposition: row.hasPendingChanges ? G9ERevocationDisposition.Quarantine : G9ERevocationDisposition.Delete };\r\n }\r\n\r\n find(name: string): G9RevocationRule | null {\r\n for (const rule of this.rules) if (rule.name === name) return rule;\r\n return null;\r\n }\r\n}\r\n\r\nexport class G9RevocationPolicyBuilder {\r\n readonly rules: G9RevocationRule[] = [];\r\n\r\n when(name: string, condition: (row: G9RevokedRow) => boolean): G9RevocationActionBuilder {\r\n if (typeof name !== 'string' || name.trim() === '') throw new TypeError('A rule needs a name.');\r\n if (this.rules.some((r) => r.name === name)) throw new RangeError(`Revocation rule '${name}' is declared twice.`);\r\n return new G9RevocationActionBuilder(this, name, condition);\r\n }\r\n\r\n /** Rows of one local table. */\r\n forTable(name: string, localTable: string, condition?: (row: G9RevokedRow) => boolean): G9RevocationActionBuilder {\r\n const table = localTable.toLowerCase();\r\n return this.when(name, (row) => row.localTable.toLowerCase() === table && (condition ? condition(row) : true));\r\n }\r\n}\r\n\r\nexport class G9RevocationActionBuilder {\r\n private readonly _owner: G9RevocationPolicyBuilder;\r\n private readonly _name: string;\r\n private readonly _condition: (row: G9RevokedRow) => boolean;\r\n\r\n constructor(owner: G9RevocationPolicyBuilder, name: string, condition: (row: G9RevokedRow) => boolean) {\r\n this._owner = owner;\r\n this._name = name;\r\n this._condition = condition;\r\n }\r\n\r\n delete(): G9RevocationPolicyBuilder {\r\n return this._add(() => G9ERevocationDisposition.Delete, null);\r\n }\r\n\r\n markRevoked(): G9RevocationPolicyBuilder {\r\n return this._add(() => G9ERevocationDisposition.MarkRevoked, null);\r\n }\r\n\r\n quarantine(): G9RevocationPolicyBuilder {\r\n return this._add(() => G9ERevocationDisposition.Quarantine, null);\r\n }\r\n\r\n retainWhile(retainWhile: (row: G9RevokedRow) => boolean): G9RevocationPolicyBuilder {\r\n return this._add(() => G9ERevocationDisposition.Retain, retainWhile);\r\n }\r\n\r\n custom(decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition): G9RevocationPolicyBuilder {\r\n return this._add(decide, null);\r\n }\r\n\r\n private _add(\r\n decide: (row: G9RevokedRow, editor: G9RevokedRowEditor) => G9ERevocationDisposition,\r\n retainWhile: ((row: G9RevokedRow) => boolean) | null,\r\n ): G9RevocationPolicyBuilder {\r\n this._owner.rules.push({ name: this._name, condition: this._condition, decide, retainWhile });\r\n return this._owner;\r\n }\r\n}\r\n\r\n/** A row in the holding area (`G9CQuarantinedRow`). */\r\nexport interface G9QuarantinedRow {\r\n localTable: string;\r\n key: string;\r\n reason: G9ERevocationReason;\r\n rule: string | null;\r\n hadPendingChanges: boolean;\r\n values: { [column: string]: unknown };\r\n atUtcMs: number;\r\n}\r\n\r\n/** A row kept in the app's table after revocation (`G9CRetainedRow`). */\r\nexport interface G9RetainedRow {\r\n localTable: string;\r\n key: string;\r\n disposition: G9ERevocationDisposition;\r\n reason: G9ERevocationReason;\r\n rule: string | null;\r\n atUtcMs: number;\r\n}\r\n\r\n// ---------------------------------------------------------------- failures\r\n\r\n/** What went wrong inside a client store, in terms an application can act on (`G9ELocalStoreFailure`). */\r\nexport const G9ELocalStoreFailure = {\r\n Other: 0,\r\n Corrupt: 1,\r\n DiskFull: 2,\r\n Busy: 3,\r\n} as const;\r\nexport type G9ELocalStoreFailure = (typeof G9ELocalStoreFailure)[keyof typeof G9ELocalStoreFailure];\r\n\r\n/** Implemented by a store's errors so the engine can give a run's failure a stable code (`IG9SyncLocalStoreFailure`). */\r\nexport interface G9SyncLocalStoreFailure {\r\n readonly localStoreFailure: G9ELocalStoreFailure;\r\n}\r\n\r\nexport function isLocalStoreFailure(error: unknown): error is G9SyncLocalStoreFailure {\r\n return typeof error === 'object' && error !== null && typeof (error as { localStoreFailure?: unknown }).localStoreFailure === 'number';\r\n}\r\n\r\n// ---------------------------------------------------------------- the store contract\r\n\r\n/**\r\n * The client storage provider (`IG9SyncClientStore`): local tables, change capture, subscription membership,\r\n * staging, apply and metadata. Every method takes an optional AbortSignal (the CancellationToken twin).\r\n */\r\nexport interface G9SyncClientStore {\r\n initialize(model: G9SyncClientModel, signal?: AbortSignal): Promise<void>;\r\n getClientId(signal?: AbortSignal): Promise<string>;\r\n getServerState(signal?: AbortSignal): Promise<G9ClientServerState>;\r\n saveHello(hello: G9DtHelloResult, signal?: AbortSignal): Promise<void>;\r\n getPendingBackfills(signal?: AbortSignal): Promise<G9DtBackfillRequest[]>;\r\n\r\n getSubscriptions(signal?: AbortSignal): Promise<G9SyncSubscriptionRecord[]>;\r\n ensureSubscription(\r\n name: string,\r\n parameters: G9SyncParameters,\r\n ephemeral: boolean,\r\n ttlMs: number | null,\r\n adoptExistingRows: boolean,\r\n signal?: AbortSignal,\r\n ): Promise<G9SyncSubscriptionRecord>;\r\n removeSubscription(key: string, policy: G9EMoveOutPolicy, signal?: AbortSignal): Promise<void>;\r\n releaseSubscriptionRows(key: string, signal?: AbortSignal): Promise<G9ApplyReport>;\r\n updateSubscription(key: string, update: G9SubscriptionUpdate, signal?: AbortSignal): Promise<void>;\r\n collectExpiredEphemeral(utcNowMs: number, signal?: AbortSignal): Promise<number>;\r\n\r\n buildPushBatch(tables: readonly G9DtNegotiatedTable[], maxRows: number, maxBytes: number, signal?: AbortSignal): Promise<G9PushBatch | null>;\r\n forgetUploadedRows(localTable: string, keys: readonly string[] | null, signal?: AbortSignal): Promise<number>;\r\n applyPushResult(batch: G9PushBatch, result: G9DtPushResult, signal?: AbortSignal): Promise<G9ApplyReport>;\r\n\r\n getStagedPull(signal?: AbortSignal): Promise<G9StagedPull | null>;\r\n /** The newest staged pull planned under exactly this generation, or null (ADR-0060). */\r\n getStagedPullForGeneration(generation: string, signal?: AbortSignal): Promise<G9StagedPull | null>;\r\n beginStagedPull(pull: G9StagedPull, signal?: AbortSignal): Promise<void>;\r\n pruneStagedPulls(olderThanUtcMs: number, maxBytes: number, keepGeneration: string | null, signal?: AbortSignal): Promise<number>;\r\n discardAllStagedPulls(signal?: AbortSignal): Promise<number>;\r\n stageChunk(runId: string, chunk: G9DtSyncChunk, signal?: AbortSignal): Promise<void>;\r\n /**\r\n * The store's offer to receive large first downloads as SQLite snapshot files (ADR-0072), or null for rows only. A store that\r\n * makes an offer stages file segments (`chunk.file`) in `stageChunk` and copies the files in `applyStagedPull`.\r\n */\r\n describeSnapshotFiles?(negotiated: readonly G9DtNegotiatedTable[]): G9DtSnapshotFileRequest | null;\r\n getResumePoint(runId: string, signal?: AbortSignal): Promise<G9ResumePoint>;\r\n applyStagedPull(\r\n runId: string,\r\n rowsApplied: ((rows: number) => void) | null,\r\n slices: ((slice: G9ApplySlice) => void) | null,\r\n signal?: AbortSignal,\r\n ): Promise<G9ApplyReport>;\r\n discardStagedPull(runId: string, signal?: AbortSignal): Promise<void>;\r\n\r\n computeDigest(subscriptionKey: string, table: G9DtNegotiatedTable, signal?: AbortSignal): Promise<G9DtTableDigest>;\r\n readLocalEntries(\r\n subscriptionKey: string,\r\n table: G9DtNegotiatedTable,\r\n buckets: ReadonlySet<number>,\r\n serverKeys: ReadonlySet<string>,\r\n signal?: AbortSignal,\r\n ): Promise<G9LocalRowEntry[]>;\r\n applyReconcile(\r\n subscriptionKey: string,\r\n table: G9DtNegotiatedTable,\r\n fetchedFrames: readonly Uint8Array[],\r\n addMembership: readonly string[],\r\n moveOut: readonly string[],\r\n policy: G9EMoveOutPolicy,\r\n signal?: AbortSignal,\r\n ): Promise<G9ApplyReport>;\r\n\r\n getPendingSummary(signal?: AbortSignal): Promise<G9PendingSummary>;\r\n enqueueCommand(\r\n request: G9CommandRequest,\r\n applyLocally: ((writer: G9LocalCommandWriter, signal?: AbortSignal) => Promise<void>) | null,\r\n signal?: AbortSignal,\r\n ): Promise<G9LocalCommand>;\r\n getQuarantined(signal?: AbortSignal): Promise<G9QuarantinedRow[]>;\r\n restoreQuarantined(localTable: string, key: string, signal?: AbortSignal): Promise<number>;\r\n discardQuarantined(localTable: string | null, key: string | null, signal?: AbortSignal): Promise<number>;\r\n getRetained(signal?: AbortSignal): Promise<G9RetainedRow[]>;\r\n reevaluateRetained(signal?: AbortSignal): Promise<number>;\r\n getCommands(state: G9ELocalCommandState | null, limit: number, signal?: AbortSignal): Promise<G9LocalCommand[]>;\r\n readChangeFeed(localTable: string, afterSequence: number, limit: number, signal?: AbortSignal): Promise<G9ChangeFeedEntry[]>;\r\n /** The feed narrowed to the keys `keyFilter` selects, plus every deletion; fewer than `limit` entries means the read is complete. */\r\n readChangeFeedFiltered(localTable: string, afterSequence: number, limit: number, keyFilter: G9ChangeFeedKeyFilter, signal?: AbortSignal): Promise<G9ChangeFeedEntry[]>;\r\n getChangeSequence(signal?: AbortSignal): Promise<number>;\r\n getChangeFeedFloor(signal?: AbortSignal): Promise<number>;\r\n getRejections(signal?: AbortSignal): Promise<G9SyncRejection[]>;\r\n retryRejected(localTable: string | null, key: string | null, signal?: AbortSignal): Promise<number>;\r\n markDirty(localTable: string, keys: readonly string[], signal?: AbortSignal): Promise<number>;\r\n adoptExistingRows(signal?: AbortSignal): Promise<number>;\r\n saveRunReport(report: G9SyncRunReport, keep: number, signal?: AbortSignal): Promise<void>;\r\n getRecentRunReports(count: number, signal?: AbortSignal): Promise<G9SyncRunReport[]>;\r\n getPhaseStatistics(signal?: AbortSignal): Promise<{ [key: string]: number }>;\r\n recordPhaseStatistics(samples: { [key: string]: number }, signal?: AbortSignal): Promise<void>;\r\n purgeDeletedFeed(keep: number, signal?: AbortSignal): Promise<number>;\r\n dispose(): Promise<void>;\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/client/transport.ts"],"names":[],"mappings":"","sourcesContent":["// Twin of G9SyncData.Client/Transport/IG9SyncTransport.cs.\nimport type {\n G9DtChangesAvailable,\n G9DtFetchRowsRequest,\n G9DtHelloRequest,\n G9DtHelloResult,\n G9DtPullContinuation,\n G9DtPullPlan,\n G9DtPullRequest,\n G9DtPushRequest,\n G9DtPushResult,\n G9DtReconcileRequest,\n G9DtSyncChunk,\n} from '../protocol/dtos.js';\n\n/**\n * Carries protocol calls to a G9SyncData server. Implementations: SignalR (`@g9tm/syncdata/signalr`, and its Lynx\n * wiring in `@g9tm/syncdata-lynx`) and the in-memory test transport (`@g9tm/syncdata/testing`). Failures surface as\n * G9SyncException; transport faults use G9S-NET-FAILURE.\n */\nexport interface G9SyncTransport {\n readonly isConnected: boolean;\n /** Subscribes to server \"pokes\" (tables changed); returns the unsubscribe function. */\n onChangesAvailable(handler: (changes: G9DtChangesAvailable) => void): () => void;\n connect(signal?: AbortSignal): Promise<void>;\n hello(request: G9DtHelloRequest, signal?: AbortSignal): Promise<G9DtHelloResult>;\n push(request: G9DtPushRequest, chunks: AsyncIterable<G9DtSyncChunk>, signal?: AbortSignal): Promise<G9DtPushResult>;\n planPull(request: G9DtPullRequest, signal?: AbortSignal): Promise<G9DtPullPlan>;\n pull(token: string, continuation: G9DtPullContinuation | null, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\n reconcile(request: G9DtReconcileRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\n fetchRows(request: G9DtFetchRowsRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\n dispose(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/client/transport.ts"],"names":[],"mappings":"","sourcesContent":["// Twin of G9SyncData.Client/Transport/IG9SyncTransport.cs.\r\nimport type {\r\n G9DtChangesAvailable,\r\n G9DtFetchRowsRequest,\r\n G9DtHelloRequest,\r\n G9DtHelloResult,\r\n G9DtPullContinuation,\r\n G9DtPullPlan,\r\n G9DtPullRequest,\r\n G9DtPushRequest,\r\n G9DtPushResult,\r\n G9DtReconcileRequest,\r\n G9DtSyncChunk,\r\n} from '../protocol/dtos.js';\r\n\r\n/**\r\n * Carries protocol calls to a G9SyncData server. Implementations: SignalR (`@g9tm/syncdata/signalr`, and its Lynx\r\n * wiring in `@g9tm/syncdata-lynx`) and the in-memory test transport (`@g9tm/syncdata/testing`). Failures surface as\r\n * G9SyncException; transport faults use G9S-NET-FAILURE.\r\n */\r\nexport interface G9SyncTransport {\r\n readonly isConnected: boolean;\r\n /** Subscribes to server \"pokes\" (tables changed); returns the unsubscribe function. */\r\n onChangesAvailable(handler: (changes: G9DtChangesAvailable) => void): () => void;\r\n connect(signal?: AbortSignal): Promise<void>;\r\n hello(request: G9DtHelloRequest, signal?: AbortSignal): Promise<G9DtHelloResult>;\r\n push(request: G9DtPushRequest, chunks: AsyncIterable<G9DtSyncChunk>, signal?: AbortSignal): Promise<G9DtPushResult>;\r\n planPull(request: G9DtPullRequest, signal?: AbortSignal): Promise<G9DtPullPlan>;\r\n pull(token: string, continuation: G9DtPullContinuation | null, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\r\n reconcile(request: G9DtReconcileRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\r\n fetchRows(request: G9DtFetchRowsRequest, signal?: AbortSignal): AsyncIterable<G9DtSyncChunk>;\r\n dispose(): Promise<void>;\r\n}\r\n"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */
2
- export declare const VERSION = "1.5.0";
2
+ export declare const VERSION = "1.5.2";
3
3
  export { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';
4
4
  export { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';
5
5
  export { G9Long, parseJson, stringifyJson } from './abstractions/long.js';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the
4
4
  // separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).
5
5
  /** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */
6
- export const VERSION = '1.5.0';
6
+ export const VERSION = '1.5.2';
7
7
  // abstractions
8
8
  export { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';
9
9
  export { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException } from './abstractions/errors.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,uHAAuH;AACvH,sHAAsH;AACtH,oHAAoH;AAEpH,sGAAsG;AACtG,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACjJ,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AAC5I,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAElF,WAAW;AACX,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAA4E,MAAM,+BAA+B,CAAC;AAC3I,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,4BAA4B,CAAC;AAE3H,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAmD,MAAM,mBAAmB,CAAC;AAC9K,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAyB,MAAM,sBAAsB,CAAC;AAC7G,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GAYrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,2CAA2C;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// @g9tm/syncdata — the TypeScript twin of the G9SyncData .NET client (abstractions, protocol, engine). The SQLite store\n// is `@g9tm/syncdata/sqlite`, the SignalR transport `@g9tm/syncdata/signalr`, Node helpers `@g9tm/syncdata/node`, test\n// doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the\n// separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).\n\n/** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */\nexport const VERSION = '1.5.0';\n\n// abstractions\nexport { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';\nexport { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';\nexport { G9Long, parseJson, stringifyJson } from './abstractions/long.js';\nexport { EMPTY_GUID, guidToN, newGuid, normalizeGuid, tryNormalizeGuid } from './abstractions/guid.js';\nexport { G9SyncKey } from './abstractions/key.js';\nexport { G9SyncDigest } from './abstractions/digest.js';\nexport { G9SyncParameters, escapeDataString } from './abstractions/parameters.js';\n\n// protocol\nexport * from './protocol/dtos.js';\nexport { G9SyncHubErrors, G9SyncProtocol, negotiateFrameVersion, tableGroup } from './protocol/protocol.js';\nexport {\n bytesField,\n dateTimeMs,\n fromMessagePackNames,\n G9WireGuid,\n GUID_EXTENSION_TYPE,\n readChangesAvailable,\n readContinuation,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readReconcileSummary,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from './protocol/wire.js';\nexport { G9ECompression, G9EPushRowOp, G9ERowBatchOp, G9RowBatchFormat, G9RowBatchFormatError } from './protocol/rowBatch/format.js';\nexport { G9RowBatchWriter, type G9DateTimeOffsetValue, type G9DateTimeValue, type G9FrameCompressor } from './protocol/rowBatch/writer.js';\nexport {\n G9RowBatchReader,\n getDefaultFrameDecompressor,\n openRowBatch,\n openRowBatchSync,\n readFrameHeader,\n setDefaultFrameDecompressor,\n type G9FrameDecompressor,\n type G9FrameHeader,\n type G9OpenRowBatchOptions,\n} from './protocol/rowBatch/reader.js';\nexport { decimalToDouble, formatDecimal, formatDouble, parseDecimal, type DecimalParts } from './internal/dotnetFormat.js';\n\n// client\nexport { G9SyncClientModel, G9SyncClientModelBuilder, G9SyncClientTable, G9SyncClientTableBuilder, type G9SyncClientColumn, type G9SyncClientIndex } from './client/model.js';\nexport * from './client/storeTypes.js';\nexport type { G9SyncTransport } from './client/transport.js';\nexport { G9ESyncPhase, G9SyncProgressTracker, phaseName, type G9DtSyncProgress } from './client/progress.js';\nexport {\n G9ESyncOutcome,\n G9ESyncPriority,\n G9SyncPostStep,\n G9SyncRun,\n describeModelProblem,\n isTransientError,\n normalizeError,\n outcomeName,\n priorityName,\n resolveEngineOptions,\n type G9RowsAppliedEvent,\n type G9SubscriptionOptions,\n type G9SyncEngineOptions,\n type G9SyncHealth,\n type G9SyncHostHooks,\n type G9SyncLogger,\n type G9SyncLogLevel,\n type G9SyncModelProblem,\n type G9SyncPostStepContext,\n type G9SyncRequest,\n type G9SyncRunResult,\n} from './client/runs.js';\nexport { G9SyncEngine, stageGeneration } from './client/engine.js';\n\n// helpers the Lynx package and tests share\nexport { base64ToBytes, bytesToBase64 } from './internal/base64.js';\nexport { utf8Decode, utf8Encode } from './internal/utf8.js';\nexport { md5 } from './internal/md5.js';\nexport { sha256, toHex } from './internal/sha256.js';\nexport { cancellationError, createAbortController, delay, linkSignals, onAbort, yieldToEventLoop } from './internal/abort.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,uHAAuH;AACvH,sHAAsH;AACtH,oHAAoH;AAEpH,sGAAsG;AACtG,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACjJ,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AAC5I,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAElF,WAAW;AACX,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACrI,OAAO,EAAE,gBAAgB,EAA4E,MAAM,+BAA+B,CAAC;AAC3I,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,4BAA4B,CAAC;AAE3H,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAmD,MAAM,mBAAmB,CAAC;AAC9K,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,SAAS,EAAyB,MAAM,sBAAsB,CAAC;AAC7G,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GAYrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,2CAA2C;AAC3C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// @g9tm/syncdata — the TypeScript twin of the G9SyncData .NET client (abstractions, protocol, engine). The SQLite store\n// is `@g9tm/syncdata/sqlite`, the SignalR transport `@g9tm/syncdata/signalr`, Node helpers `@g9tm/syncdata/node`, test\n// doubles `@g9tm/syncdata/testing`, the pure-JavaScript Brotli decoder `@g9tm/syncdata/brotli-js`; Lynx wiring is the\n// separate package `@g9tm/syncdata-lynx`. Every public type keeps its .NET name without the G9C prefix (PARITY.md).\n\n/** The package version; equal to the .NET packages' (G9SyncDataVersion) — one release, both sides. */\nexport const VERSION = '1.5.2';\n\n// abstractions\nexport { G9EConflictPolicy, G9EMoveOutPolicy, G9ESyncColumnType, G9ESyncDirection, columnTypeName, isColumnType } from './abstractions/enums.js';\nexport { G9SyncErrorCodes, G9SyncException, isRetryableCode, isSyncException, type G9SyncExceptionOptions } from './abstractions/errors.js';\nexport { G9Long, parseJson, stringifyJson } from './abstractions/long.js';\nexport { EMPTY_GUID, guidToN, newGuid, normalizeGuid, tryNormalizeGuid } from './abstractions/guid.js';\nexport { G9SyncKey } from './abstractions/key.js';\nexport { G9SyncDigest } from './abstractions/digest.js';\nexport { G9SyncParameters, escapeDataString } from './abstractions/parameters.js';\n\n// protocol\nexport * from './protocol/dtos.js';\nexport { G9SyncHubErrors, G9SyncProtocol, negotiateFrameVersion, tableGroup } from './protocol/protocol.js';\nexport {\n bytesField,\n dateTimeMs,\n fromMessagePackNames,\n G9WireGuid,\n GUID_EXTENSION_TYPE,\n readChangesAvailable,\n readContinuation,\n readHelloResult,\n readPullPlan,\n readPushResult,\n readReconcileSummary,\n readSyncChunk,\n toMessagePackNames,\n type G9WireFormat,\n} from './protocol/wire.js';\nexport { G9ECompression, G9EPushRowOp, G9ERowBatchOp, G9RowBatchFormat, G9RowBatchFormatError } from './protocol/rowBatch/format.js';\nexport { G9RowBatchWriter, type G9DateTimeOffsetValue, type G9DateTimeValue, type G9FrameCompressor } from './protocol/rowBatch/writer.js';\nexport {\n G9RowBatchReader,\n getDefaultFrameDecompressor,\n openRowBatch,\n openRowBatchSync,\n readFrameHeader,\n setDefaultFrameDecompressor,\n type G9FrameDecompressor,\n type G9FrameHeader,\n type G9OpenRowBatchOptions,\n} from './protocol/rowBatch/reader.js';\nexport { decimalToDouble, formatDecimal, formatDouble, parseDecimal, type DecimalParts } from './internal/dotnetFormat.js';\n\n// client\nexport { G9SyncClientModel, G9SyncClientModelBuilder, G9SyncClientTable, G9SyncClientTableBuilder, type G9SyncClientColumn, type G9SyncClientIndex } from './client/model.js';\nexport * from './client/storeTypes.js';\nexport type { G9SyncTransport } from './client/transport.js';\nexport { G9ESyncPhase, G9SyncProgressTracker, phaseName, type G9DtSyncProgress } from './client/progress.js';\nexport {\n G9ESyncOutcome,\n G9ESyncPriority,\n G9SyncPostStep,\n G9SyncRun,\n describeModelProblem,\n isTransientError,\n normalizeError,\n outcomeName,\n priorityName,\n resolveEngineOptions,\n type G9RowsAppliedEvent,\n type G9SubscriptionOptions,\n type G9SyncEngineOptions,\n type G9SyncHealth,\n type G9SyncHostHooks,\n type G9SyncLogger,\n type G9SyncLogLevel,\n type G9SyncModelProblem,\n type G9SyncPostStepContext,\n type G9SyncRequest,\n type G9SyncRunResult,\n} from './client/runs.js';\nexport { G9SyncEngine, stageGeneration } from './client/engine.js';\n\n// helpers the Lynx package and tests share\nexport { base64ToBytes, bytesToBase64 } from './internal/base64.js';\nexport { utf8Decode, utf8Encode } from './internal/utf8.js';\nexport { md5 } from './internal/md5.js';\nexport { sha256, toHex } from './internal/sha256.js';\nexport { cancellationError, createAbortController, delay, linkSignals, onAbort, yieldToEventLoop } from './internal/abort.js';\n"]}