@g9tm/syncdata 1.2.1

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 (149) hide show
  1. package/LICENSE.md +21 -0
  2. package/PARITY.md +71 -0
  3. package/README.md +71 -0
  4. package/THIRD-PARTY-NOTICES.md +31 -0
  5. package/dist/abstractions/digest.d.ts +27 -0
  6. package/dist/abstractions/digest.js +78 -0
  7. package/dist/abstractions/digest.js.map +1 -0
  8. package/dist/abstractions/enums.d.ts +42 -0
  9. package/dist/abstractions/enums.js +60 -0
  10. package/dist/abstractions/enums.js.map +1 -0
  11. package/dist/abstractions/errors.d.ts +72 -0
  12. package/dist/abstractions/errors.js +90 -0
  13. package/dist/abstractions/errors.js.map +1 -0
  14. package/dist/abstractions/guid.d.ts +24 -0
  15. package/dist/abstractions/guid.js +93 -0
  16. package/dist/abstractions/guid.js.map +1 -0
  17. package/dist/abstractions/key.d.ts +16 -0
  18. package/dist/abstractions/key.js +47 -0
  19. package/dist/abstractions/key.js.map +1 -0
  20. package/dist/abstractions/long.d.ts +103 -0
  21. package/dist/abstractions/long.js +351 -0
  22. package/dist/abstractions/long.js.map +1 -0
  23. package/dist/abstractions/parameters.d.ts +49 -0
  24. package/dist/abstractions/parameters.js +153 -0
  25. package/dist/abstractions/parameters.js.map +1 -0
  26. package/dist/brotli-js/decode.d.ts +8 -0
  27. package/dist/brotli-js/decode.js +2004 -0
  28. package/dist/brotli-js/decode.js.map +1 -0
  29. package/dist/brotli-js/index.d.ts +5 -0
  30. package/dist/brotli-js/index.js +19 -0
  31. package/dist/brotli-js/index.js.map +1 -0
  32. package/dist/client/engine.d.ts +110 -0
  33. package/dist/client/engine.js +1158 -0
  34. package/dist/client/engine.js.map +1 -0
  35. package/dist/client/model.d.ts +61 -0
  36. package/dist/client/model.js +154 -0
  37. package/dist/client/model.js.map +1 -0
  38. package/dist/client/progress.d.ts +101 -0
  39. package/dist/client/progress.js +251 -0
  40. package/dist/client/progress.js.map +1 -0
  41. package/dist/client/runs.d.ts +219 -0
  42. package/dist/client/runs.js +239 -0
  43. package/dist/client/runs.js.map +1 -0
  44. package/dist/client/storeTypes.d.ts +428 -0
  45. package/dist/client/storeTypes.js +256 -0
  46. package/dist/client/storeTypes.js.map +1 -0
  47. package/dist/client/transport.d.ts +19 -0
  48. package/dist/client/transport.js +2 -0
  49. package/dist/client/transport.js.map +1 -0
  50. package/dist/index.d.ts +27 -0
  51. package/dist/index.js +35 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/internal/abort.d.ts +21 -0
  54. package/dist/internal/abort.js +125 -0
  55. package/dist/internal/abort.js.map +1 -0
  56. package/dist/internal/base64.d.ts +8 -0
  57. package/dist/internal/base64.js +85 -0
  58. package/dist/internal/base64.js.map +1 -0
  59. package/dist/internal/dotnetFormat.d.ts +32 -0
  60. package/dist/internal/dotnetFormat.js +207 -0
  61. package/dist/internal/dotnetFormat.js.map +1 -0
  62. package/dist/internal/md5.d.ts +2 -0
  63. package/dist/internal/md5.js +97 -0
  64. package/dist/internal/md5.js.map +1 -0
  65. package/dist/internal/sha256.d.ts +20 -0
  66. package/dist/internal/sha256.js +153 -0
  67. package/dist/internal/sha256.js.map +1 -0
  68. package/dist/internal/utf8.d.ts +8 -0
  69. package/dist/internal/utf8.js +143 -0
  70. package/dist/internal/utf8.js.map +1 -0
  71. package/dist/node/index.d.ts +9 -0
  72. package/dist/node/index.js +35 -0
  73. package/dist/node/index.js.map +1 -0
  74. package/dist/node/sqliteDriver.d.ts +11 -0
  75. package/dist/node/sqliteDriver.js +252 -0
  76. package/dist/node/sqliteDriver.js.map +1 -0
  77. package/dist/protocol/dtos.d.ts +280 -0
  78. package/dist/protocol/dtos.js +33 -0
  79. package/dist/protocol/dtos.js.map +1 -0
  80. package/dist/protocol/protocol.d.ts +36 -0
  81. package/dist/protocol/protocol.js +63 -0
  82. package/dist/protocol/protocol.js.map +1 -0
  83. package/dist/protocol/rowBatch/columnLayout.d.ts +4 -0
  84. package/dist/protocol/rowBatch/columnLayout.js +309 -0
  85. package/dist/protocol/rowBatch/columnLayout.js.map +1 -0
  86. package/dist/protocol/rowBatch/format.d.ts +74 -0
  87. package/dist/protocol/rowBatch/format.js +163 -0
  88. package/dist/protocol/rowBatch/format.js.map +1 -0
  89. package/dist/protocol/rowBatch/reader.d.ts +119 -0
  90. package/dist/protocol/rowBatch/reader.js +459 -0
  91. package/dist/protocol/rowBatch/reader.js.map +1 -0
  92. package/dist/protocol/rowBatch/writer.d.ts +101 -0
  93. package/dist/protocol/rowBatch/writer.js +412 -0
  94. package/dist/protocol/rowBatch/writer.js.map +1 -0
  95. package/dist/protocol/wire.d.ts +32 -0
  96. package/dist/protocol/wire.js +329 -0
  97. package/dist/protocol/wire.js.map +1 -0
  98. package/dist/signalr/index.d.ts +2 -0
  99. package/dist/signalr/index.js +5 -0
  100. package/dist/signalr/index.js.map +1 -0
  101. package/dist/signalr/protocols.d.ts +17 -0
  102. package/dist/signalr/protocols.js +109 -0
  103. package/dist/signalr/protocols.js.map +1 -0
  104. package/dist/signalr/transport.d.ts +67 -0
  105. package/dist/signalr/transport.js +286 -0
  106. package/dist/signalr/transport.js.map +1 -0
  107. package/dist/sqlite/apply.d.ts +91 -0
  108. package/dist/sqlite/apply.js +657 -0
  109. package/dist/sqlite/apply.js.map +1 -0
  110. package/dist/sqlite/commands.d.ts +24 -0
  111. package/dist/sqlite/commands.js +167 -0
  112. package/dist/sqlite/commands.js.map +1 -0
  113. package/dist/sqlite/connection.d.ts +81 -0
  114. package/dist/sqlite/connection.js +322 -0
  115. package/dist/sqlite/connection.js.map +1 -0
  116. package/dist/sqlite/driver.d.ts +63 -0
  117. package/dist/sqlite/driver.js +9 -0
  118. package/dist/sqlite/driver.js.map +1 -0
  119. package/dist/sqlite/index.d.ts +6 -0
  120. package/dist/sqlite/index.js +7 -0
  121. package/dist/sqlite/index.js.map +1 -0
  122. package/dist/sqlite/internals.d.ts +63 -0
  123. package/dist/sqlite/internals.js +194 -0
  124. package/dist/sqlite/internals.js.map +1 -0
  125. package/dist/sqlite/options.d.ts +78 -0
  126. package/dist/sqlite/options.js +78 -0
  127. package/dist/sqlite/options.js.map +1 -0
  128. package/dist/sqlite/push.d.ts +9 -0
  129. package/dist/sqlite/push.js +272 -0
  130. package/dist/sqlite/push.js.map +1 -0
  131. package/dist/sqlite/query.d.ts +38 -0
  132. package/dist/sqlite/query.js +476 -0
  133. package/dist/sqlite/query.js.map +1 -0
  134. package/dist/sqlite/revocation.d.ts +28 -0
  135. package/dist/sqlite/revocation.js +337 -0
  136. package/dist/sqlite/revocation.js.map +1 -0
  137. package/dist/sqlite/sql.d.ts +60 -0
  138. package/dist/sqlite/sql.js +324 -0
  139. package/dist/sqlite/sql.js.map +1 -0
  140. package/dist/sqlite/store.d.ts +116 -0
  141. package/dist/sqlite/store.js +664 -0
  142. package/dist/sqlite/store.js.map +1 -0
  143. package/dist/sqlite/values.d.ts +29 -0
  144. package/dist/sqlite/values.js +288 -0
  145. package/dist/sqlite/values.js.map +1 -0
  146. package/dist/testing/index.d.ts +61 -0
  147. package/dist/testing/index.js +175 -0
  148. package/dist/testing/index.js.map +1 -0
  149. package/package.json +104 -0
@@ -0,0 +1,194 @@
1
+ // Shared state and helpers of the SQLite store's parts (the C# partial class G9CSqliteSyncStore is split the same way:
2
+ // core, apply, push, query, commands, revocation, incarnation, recovery).
3
+ import { G9ESyncColumnType } from '../abstractions/enums.js';
4
+ import { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';
5
+ import { G9Long, parseJson, stringifyJson } from '../abstractions/long.js';
6
+ import { G9SyncParameters } from '../abstractions/parameters.js';
7
+ import { base64ToBytes, bytesToBase64 } from '../internal/base64.js';
8
+ import { G9ESubscriptionState } from '../client/storeTypes.js';
9
+ import { readNegotiatedTable, readSubscriptionDefinition } from '../protocol/wire.js';
10
+ import { asNumber, asOptionalString, asString } from './connection.js';
11
+ import { isInt64Tag } from './driver.js';
12
+ import { quote } from './sql.js';
13
+ /** A table of the model with its local metadata (`LocalTable`). */
14
+ export class LocalTable {
15
+ constructor(model, tid, negotiated, syncedColumns) {
16
+ this.model = model;
17
+ this.tid = tid;
18
+ this.negotiated = negotiated;
19
+ this.syncedColumns = syncedColumns;
20
+ }
21
+ get quoted() {
22
+ return quote(this.model.localName);
23
+ }
24
+ get keyQuoted() {
25
+ return quote(this.model.keyColumn);
26
+ }
27
+ }
28
+ export function logTo(logger, level, eventId, message, error) {
29
+ if (!logger)
30
+ return;
31
+ try {
32
+ logger.log(level, eventId, message, error);
33
+ }
34
+ catch {
35
+ // A logger must never break the store.
36
+ }
37
+ }
38
+ export function nowMs() {
39
+ return Date.now();
40
+ }
41
+ export async function meta(connection, key) {
42
+ const value = await connection.scalar('SELECT value FROM g9_meta WHERE key = $k', { $k: key });
43
+ return value === null ? null : asString(value);
44
+ }
45
+ export async function setMeta(connection, key, value) {
46
+ await connection.exec('INSERT INTO g9_meta (key, value) VALUES ($k, $v) ON CONFLICT(key) DO UPDATE SET value = excluded.value', { $k: key, $v: value });
47
+ }
48
+ /** `KeyValue`: the key in the table's storage form (integers for an integer key). */
49
+ export function keyValue(table, canonicalKey) {
50
+ if (table.model.keyType === G9ESyncColumnType.Int32 || table.model.keyType === G9ESyncColumnType.Int64) {
51
+ return G9Long.parse(canonicalKey).toSqlValue();
52
+ }
53
+ return canonicalKey;
54
+ }
55
+ export function getLocal(store, localName) {
56
+ const table = store.byLocal.get(localName.toLowerCase());
57
+ if (!table)
58
+ throw new RangeError(`'${localName}' is not a synced table.`);
59
+ return table;
60
+ }
61
+ export function findByServerName(store, serverName) {
62
+ var _a;
63
+ const table = store.ensureInitialized().findByServerName(serverName);
64
+ return table ? ((_a = store.byLocal.get(table.localName.toLowerCase())) !== null && _a !== void 0 ? _a : null) : null;
65
+ }
66
+ export function byTid(store, tid) {
67
+ for (const table of store.byLocal.values())
68
+ if (table.tid === tid)
69
+ return table;
70
+ return null;
71
+ }
72
+ /** Reads subscriptions, all or one key, oldest first. */
73
+ export async function readSubscriptions(connection, key) {
74
+ const rows = await connection.query('SELECT key, name, params, slot, ephemeral, ttl_seconds, cursor, definition_hash, auth_hash, state, error_code, created_utc, ' +
75
+ 'last_success_utc, last_reconcile_utc, last_access_utc, move_out_policy FROM g9_subscriptions' +
76
+ (key === null ? '' : ' WHERE key = $k') +
77
+ ' ORDER BY created_utc', key === null ? undefined : { $k: key });
78
+ return rows.map((r) => {
79
+ const parameters = JSON.parse(asString(r[2]));
80
+ return {
81
+ key: asString(r[0]),
82
+ name: asString(r[1]),
83
+ parameters: G9SyncParameters.fromValues(parameters !== null && parameters !== void 0 ? parameters : {}),
84
+ slot: asNumber(r[3]),
85
+ ephemeral: asNumber(r[4]) !== 0,
86
+ ttlMs: r[5] === null ? null : asNumber(r[5]) * 1000,
87
+ cursor: asOptionalString(r[6]),
88
+ definitionHash: asOptionalString(r[7]),
89
+ authHash: asOptionalString(r[8]),
90
+ state: asNumber(r[9]),
91
+ lastErrorCode: asOptionalString(r[10]),
92
+ createdUtcMs: asNumber(r[11]),
93
+ lastSuccessUtcMs: r[12] === null ? null : asNumber(r[12]),
94
+ lastReconcileUtcMs: r[13] === null ? null : asNumber(r[13]),
95
+ lastAccessUtcMs: r[14] === null ? null : asNumber(r[14]),
96
+ moveOutPolicy: r[15] === null ? null : asNumber(r[15]),
97
+ };
98
+ });
99
+ }
100
+ /**
101
+ * JSON of a persisted DTO in the form .NET's source-generated context writes (camelCase, nulls omitted), so a database
102
+ * written by either side reads on the other.
103
+ */
104
+ export function persistedJson(value) {
105
+ return stringifyJson(dropNulls(value));
106
+ }
107
+ function dropNulls(value) {
108
+ if (Array.isArray(value))
109
+ return value.map(dropNulls);
110
+ if (value === null || typeof value !== 'object' || value instanceof G9Long)
111
+ return value;
112
+ const out = {};
113
+ for (const key of Object.keys(value)) {
114
+ const item = value[key];
115
+ if (item === null || item === undefined)
116
+ continue;
117
+ out[key] = dropNulls(item);
118
+ }
119
+ return out;
120
+ }
121
+ export function readPersistedNegotiated(json) {
122
+ return json === null ? null : readNegotiatedTable(parseJson(json));
123
+ }
124
+ export function readPersistedDefinitions(json) {
125
+ if (json === null)
126
+ return [];
127
+ const parsed = parseJson(json);
128
+ return Array.isArray(parsed) ? parsed.map(readSubscriptionDefinition) : [];
129
+ }
130
+ /** SQLite values as JSON (`SerializeValues`): text as strings, numbers as numbers, blobs as `{"$b64": "…"}`. */
131
+ export function serializeValues(values) {
132
+ const out = {};
133
+ for (const column of Object.keys(values)) {
134
+ const value = values[column];
135
+ if (value === null || value === undefined)
136
+ out[column] = null;
137
+ else if (typeof value === 'number')
138
+ out[column] = value;
139
+ else if (isInt64Tag(value))
140
+ out[column] = G9Long.parse(value.int64);
141
+ else if (value instanceof G9Long)
142
+ out[column] = value;
143
+ else if (value instanceof ArrayBuffer)
144
+ out[column] = { $b64: bytesToBase64(new Uint8Array(value)) };
145
+ else if (value instanceof Uint8Array)
146
+ out[column] = { $b64: bytesToBase64(value) };
147
+ else if (typeof value === 'boolean')
148
+ out[column] = value ? 'True' : 'False';
149
+ else
150
+ out[column] = String(value);
151
+ }
152
+ return stringifyJson(out);
153
+ }
154
+ /** `DeserializeValues`: numbers as integers when they are, int64 beyond 2^53 as tags, `{"$b64"}` as BLOBs. */
155
+ export function deserializeValues(json) {
156
+ const parsed = parseJson(json);
157
+ const out = {};
158
+ for (const column of Object.keys(parsed)) {
159
+ const value = parsed[column];
160
+ if (value === null || value === undefined)
161
+ out[column] = null;
162
+ else if (value instanceof G9Long)
163
+ out[column] = value.toSqlValue();
164
+ else if (typeof value === 'number' || typeof value === 'string')
165
+ out[column] = value;
166
+ else if (typeof value === 'object' && typeof value.$b64 === 'string') {
167
+ const bytes = base64ToBytes(value.$b64);
168
+ const copy = new Uint8Array(bytes.length);
169
+ copy.set(bytes);
170
+ out[column] = copy.buffer;
171
+ }
172
+ else
173
+ out[column] = JSON.stringify(value);
174
+ }
175
+ return out;
176
+ }
177
+ /** Reads every column of a local row (`ReadLocalValues`): column name → stored value; empty when the row is gone. */
178
+ export async function readLocalValues(connection, table, key) {
179
+ const results = await connection.runStatements([{ sql: `SELECT * FROM ${table.quoted} WHERE ${table.keyQuoted} = ?1`, params: [keyValue(table, key)] }]);
180
+ const result = results[0];
181
+ const values = {};
182
+ if (!result || result.rows.length === 0)
183
+ return values;
184
+ const row = result.rows[0];
185
+ result.columns.forEach((name, i) => {
186
+ values[name] = row[i];
187
+ });
188
+ return values;
189
+ }
190
+ /** A store error that the engine maps to G9S-LOCAL-STORE. */
191
+ export function storeError(message) {
192
+ return new G9SyncException(G9SyncErrorCodes.LocalStoreError, message);
193
+ }
194
+ //# sourceMappingURL=internals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internals.js","sourceRoot":"","sources":["../../src/sqlite/internals.ts"],"names":[],"mappings":"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","sourcesContent":["// Shared state and helpers of the SQLite store's parts (the C# partial class G9CSqliteSyncStore is split the same way:\n// core, apply, push, query, commands, revocation, incarnation, recovery).\nimport { G9ESyncColumnType } from '../abstractions/enums.js';\nimport { G9SyncErrorCodes, G9SyncException } from '../abstractions/errors.js';\nimport { G9Long, parseJson, stringifyJson } from '../abstractions/long.js';\nimport { G9SyncParameters } from '../abstractions/parameters.js';\nimport { base64ToBytes, bytesToBase64 } from '../internal/base64.js';\nimport type { G9SyncClientModel, G9SyncClientTable } from '../client/model.js';\nimport type { G9SyncLogger, G9SyncLogLevel } from '../client/runs.js';\nimport { G9ESubscriptionState, type G9SyncSubscriptionRecord } from '../client/storeTypes.js';\nimport type { G9DtNegotiatedTable } from '../protocol/dtos.js';\nimport { readNegotiatedTable, readSubscriptionDefinition } from '../protocol/wire.js';\nimport { asNumber, asOptionalString, asString, type G9AsyncLock, type G9SqliteConnection } from './connection.js';\nimport { isInt64Tag, type G9SqlValue } from './driver.js';\nimport { quote } from './sql.js';\nimport type { G9ResolvedSqliteStoreOptions } from './options.js';\n\n/** A table of the model with its local metadata (`LocalTable`). */\nexport class LocalTable {\n readonly model: G9SyncClientTable;\n readonly tid: number;\n negotiated: G9DtNegotiatedTable | null;\n syncedColumns: string[];\n\n constructor(model: G9SyncClientTable, tid: number, negotiated: G9DtNegotiatedTable | null, syncedColumns: string[]) {\n this.model = model;\n this.tid = tid;\n this.negotiated = negotiated;\n this.syncedColumns = syncedColumns;\n }\n\n get quoted(): string {\n return quote(this.model.localName);\n }\n\n get keyQuoted(): string {\n return quote(this.model.keyColumn);\n }\n}\n\n/** What the store's parts share. */\nexport interface StoreInternals {\n readonly options: G9ResolvedSqliteStoreOptions;\n readonly writeLock: G9AsyncLock;\n /** The connection library writes go through (under the write lock). */\n writer(): G9SqliteConnection;\n /** A connection for reads that never wait on a running write. */\n reader(): G9SqliteConnection;\n ensureInitialized(): G9SyncClientModel;\n byLocal: Map<string, LocalTable>;\n byServerId: Map<number, LocalTable>;\n log(level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void;\n}\n\nexport function logTo(logger: G9SyncLogger | null, level: G9SyncLogLevel, eventId: number, message: string, error?: unknown): void {\n if (!logger) return;\n try {\n logger.log(level, eventId, message, error);\n } catch {\n // A logger must never break the store.\n }\n}\n\nexport function nowMs(): number {\n return Date.now();\n}\n\nexport async function meta(connection: G9SqliteConnection, key: string): Promise<string | null> {\n const value = await connection.scalar('SELECT value FROM g9_meta WHERE key = $k', { $k: key });\n return value === null ? null : asString(value);\n}\n\nexport async function setMeta(connection: G9SqliteConnection, key: string, value: string | null): Promise<void> {\n await connection.exec('INSERT INTO g9_meta (key, value) VALUES ($k, $v) ON CONFLICT(key) DO UPDATE SET value = excluded.value', { $k: key, $v: value });\n}\n\n/** `KeyValue`: the key in the table's storage form (integers for an integer key). */\nexport function keyValue(table: LocalTable, canonicalKey: string): G9SqlValue {\n if (table.model.keyType === G9ESyncColumnType.Int32 || table.model.keyType === G9ESyncColumnType.Int64) {\n return G9Long.parse(canonicalKey).toSqlValue();\n }\n return canonicalKey;\n}\n\nexport function getLocal(store: StoreInternals, localName: string): LocalTable {\n const table = store.byLocal.get(localName.toLowerCase());\n if (!table) throw new RangeError(`'${localName}' is not a synced table.`);\n return table;\n}\n\nexport function findByServerName(store: StoreInternals, serverName: string): LocalTable | null {\n const table = store.ensureInitialized().findByServerName(serverName);\n return table ? (store.byLocal.get(table.localName.toLowerCase()) ?? null) : null;\n}\n\nexport function byTid(store: StoreInternals, tid: number): LocalTable | null {\n for (const table of store.byLocal.values()) if (table.tid === tid) return table;\n return null;\n}\n\n/** Reads subscriptions, all or one key, oldest first. */\nexport async function readSubscriptions(connection: G9SqliteConnection, key: string | null): Promise<G9SyncSubscriptionRecord[]> {\n const rows = await connection.query(\n 'SELECT key, name, params, slot, ephemeral, ttl_seconds, cursor, definition_hash, auth_hash, state, error_code, created_utc, ' +\n 'last_success_utc, last_reconcile_utc, last_access_utc, move_out_policy FROM g9_subscriptions' +\n (key === null ? '' : ' WHERE key = $k') +\n ' ORDER BY created_utc',\n key === null ? undefined : { $k: key },\n );\n return rows.map((r) => {\n const parameters = JSON.parse(asString(r[2])) as { [name: string]: string } | null;\n return {\n key: asString(r[0]),\n name: asString(r[1]),\n parameters: G9SyncParameters.fromValues(parameters ?? {}),\n slot: asNumber(r[3]),\n ephemeral: asNumber(r[4]) !== 0,\n ttlMs: r[5] === null ? null : asNumber(r[5]) * 1000,\n cursor: asOptionalString(r[6]),\n definitionHash: asOptionalString(r[7]),\n authHash: asOptionalString(r[8]),\n state: asNumber(r[9]) as G9ESubscriptionState,\n lastErrorCode: asOptionalString(r[10]),\n createdUtcMs: asNumber(r[11]),\n lastSuccessUtcMs: r[12] === null ? null : asNumber(r[12]),\n lastReconcileUtcMs: r[13] === null ? null : asNumber(r[13]),\n lastAccessUtcMs: r[14] === null ? null : asNumber(r[14]),\n moveOutPolicy: r[15] === null ? null : (asNumber(r[15]) as G9SyncSubscriptionRecord['moveOutPolicy']),\n };\n });\n}\n\n/**\n * JSON of a persisted DTO in the form .NET's source-generated context writes (camelCase, nulls omitted), so a database\n * written by either side reads on the other.\n */\nexport function persistedJson(value: unknown): string {\n return stringifyJson(dropNulls(value));\n}\n\nfunction dropNulls(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(dropNulls);\n if (value === null || typeof value !== 'object' || value instanceof G9Long) return value;\n const out: { [key: string]: unknown } = {};\n for (const key of Object.keys(value as object)) {\n const item = (value as { [key: string]: unknown })[key];\n if (item === null || item === undefined) continue;\n out[key] = dropNulls(item);\n }\n return out;\n}\n\nexport function readPersistedNegotiated(json: string | null): G9DtNegotiatedTable | null {\n return json === null ? null : readNegotiatedTable(parseJson(json));\n}\n\nexport function readPersistedDefinitions(json: string | null) {\n if (json === null) return [];\n const parsed = parseJson(json);\n return Array.isArray(parsed) ? parsed.map(readSubscriptionDefinition) : [];\n}\n\n/** SQLite values as JSON (`SerializeValues`): text as strings, numbers as numbers, blobs as `{\"$b64\": \"…\"}`. */\nexport function serializeValues(values: { [column: string]: unknown }): string {\n const out: { [column: string]: unknown } = {};\n for (const column of Object.keys(values)) {\n const value = values[column];\n if (value === null || value === undefined) out[column] = null;\n else if (typeof value === 'number') out[column] = value;\n else if (isInt64Tag(value)) out[column] = G9Long.parse(value.int64);\n else if (value instanceof G9Long) out[column] = value;\n else if (value instanceof ArrayBuffer) out[column] = { $b64: bytesToBase64(new Uint8Array(value)) };\n else if (value instanceof Uint8Array) out[column] = { $b64: bytesToBase64(value) };\n else if (typeof value === 'boolean') out[column] = value ? 'True' : 'False';\n else out[column] = String(value);\n }\n return stringifyJson(out);\n}\n\n/** `DeserializeValues`: numbers as integers when they are, int64 beyond 2^53 as tags, `{\"$b64\"}` as BLOBs. */\nexport function deserializeValues(json: string): { [column: string]: G9SqlValue } {\n const parsed = parseJson(json) as { [column: string]: unknown };\n const out: { [column: string]: G9SqlValue } = {};\n for (const column of Object.keys(parsed)) {\n const value = parsed[column];\n if (value === null || value === undefined) out[column] = null;\n else if (value instanceof G9Long) out[column] = value.toSqlValue();\n else if (typeof value === 'number' || typeof value === 'string') out[column] = value;\n else if (typeof value === 'object' && typeof (value as { $b64?: unknown }).$b64 === 'string') {\n const bytes = base64ToBytes((value as { $b64: string }).$b64);\n const copy = new Uint8Array(bytes.length);\n copy.set(bytes);\n out[column] = copy.buffer;\n } else out[column] = JSON.stringify(value);\n }\n return out;\n}\n\n/** Reads every column of a local row (`ReadLocalValues`): column name → stored value; empty when the row is gone. */\nexport async function readLocalValues(connection: G9SqliteConnection, table: LocalTable, key: string): Promise<{ [column: string]: G9SqlValue }> {\n const results = await connection.runStatements([{ sql: `SELECT * FROM ${table.quoted} WHERE ${table.keyQuoted} = ?1`, params: [keyValue(table, key)] }]);\n const result = results[0];\n const values: { [column: string]: G9SqlValue } = {};\n if (!result || result.rows.length === 0) return values;\n const row = result.rows[0] as readonly G9SqlValue[];\n result.columns.forEach((name, i) => {\n values[name] = row[i] as G9SqlValue;\n });\n return values;\n}\n\n/** A store error that the engine maps to G9S-LOCAL-STORE. */\nexport function storeError(message: string): G9SyncException {\n return new G9SyncException(G9SyncErrorCodes.LocalStoreError, message);\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import type { G9SyncLogger } from '../client/runs.js';
2
+ import { G9RevocationPolicy } from '../client/storeTypes.js';
3
+ import type { G9FrameDecompressor } from '../protocol/rowBatch/reader.js';
4
+ import type { G9FrameCompressor } from '../protocol/rowBatch/writer.js';
5
+ import type { G9SqliteDriver } from './driver.js';
6
+ import { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage } from './sql.js';
7
+ /** Where the installation's incarnation lives, outside the platform's backup set (ADR-0067). */
8
+ export interface G9IncarnationMarker {
9
+ /** The marker's value, or null when there is none (or it cannot be read). */
10
+ read(): Promise<string | null>;
11
+ /** Writes the marker whole; false when it cannot be written (restore detection is then off for the run). */
12
+ write(value: string): Promise<boolean>;
13
+ }
14
+ /** The file operations a file-based marker needs (structurally `G9FileSystem` of @g9tm/signalr-supernetcore-client). */
15
+ export interface G9MarkerFileSystem {
16
+ stat(path: string): Promise<{
17
+ readonly size: number;
18
+ } | null>;
19
+ read(path: string, offset: number, length: number): Promise<Uint8Array | ArrayBuffer>;
20
+ write(path: string, offset: number, bytes: Uint8Array, truncate?: boolean): Promise<void>;
21
+ move(from: string, to: string): Promise<void>;
22
+ remove(path: string): Promise<void>;
23
+ }
24
+ export interface G9SqliteSyncStoreOptions {
25
+ /** The SQLite driver (Lynx native, Lynxtron, or `nodeSqliteDriver()` from `@g9tm/syncdata/node`). */
26
+ driver: G9SqliteDriver;
27
+ /** Database file path. */
28
+ databasePath: string;
29
+ dateTimeStorage?: G9ESqliteDateTimeStorage;
30
+ /** Text format for DateTime values; only the .NET default `yyyy-MM-dd'T'HH:mm:ss.fffffff` is supported. */
31
+ dateTimeFormat?: string;
32
+ decimalStorage?: G9ESqliteDecimalStorage;
33
+ /** Restore/copy detection (ADR-0067): a marker outside the backup set. Null (default) turns the check off. */
34
+ incarnationMarker?: G9IncarnationMarker | null;
35
+ /** How long a writer waits for the database lock (the app may be writing). */
36
+ busyTimeoutMs?: number;
37
+ useWriteAheadLog?: boolean;
38
+ /** What happens to a row no subscription holds any more (ADR-0026). */
39
+ revocation?: G9RevocationPolicy;
40
+ /** The largest decoded body accepted from one frame the store applies (ADR-0051, ADR-0066). */
41
+ maxDecodedFrameBytes?: number;
42
+ /** Changed keys reported per table in an apply report. */
43
+ maxChangedKeysPerTable?: number;
44
+ /**
45
+ * Large applies run without evaluating the library's own triggers (ADR-0034): the TypeScript store has no
46
+ * SQLITE_DBCONFIG_ENABLE_TRIGGER, so it drops its own capture and command triggers inside the apply transaction and
47
+ * re-creates them from their stored SQL before commit (PARITY.md). Never while the database holds a foreign trigger.
48
+ */
49
+ skipTriggersDuringApply?: boolean;
50
+ /** The smallest staged pull (rows) for which triggers are skipped; smaller applies are not worth the schema change. */
51
+ skipTriggersMinRows?: number;
52
+ rebuildIndexesAfterRows?: number;
53
+ rebuildIndexesMinimumGrowth?: number;
54
+ /** Rows per committed slice of a staged pull, or 0 to apply it in one transaction (ADR-0053). */
55
+ applySliceRows?: number;
56
+ applySliceRowsMax?: number;
57
+ maintenanceAfterRows?: number;
58
+ synchronousNormalForDownloads?: boolean;
59
+ /** journal_size_limit of the store's connections; negative = no limit. */
60
+ walSizeLimitBytes?: number;
61
+ /** Statements per driver call in the apply loop (one bridge round trip each). */
62
+ statementsPerBatch?: number;
63
+ /** Brotli decoder for downloaded frames; the process default (setDefaultFrameDecompressor) when omitted. */
64
+ frameDecompressor?: G9FrameDecompressor | null;
65
+ /** Brotli encoder for push frames; uncompressed frames when omitted (every server accepts them). */
66
+ frameCompressor?: G9FrameCompressor | null;
67
+ logger?: G9SyncLogger | null;
68
+ }
69
+ export type G9ResolvedSqliteStoreOptions = Required<Omit<G9SqliteSyncStoreOptions, 'incarnationMarker' | 'frameDecompressor' | 'frameCompressor' | 'logger'>> & {
70
+ incarnationMarker: G9IncarnationMarker | null;
71
+ frameDecompressor: G9FrameDecompressor | null;
72
+ frameCompressor: G9FrameCompressor | null;
73
+ logger: G9SyncLogger | null;
74
+ };
75
+ export declare const DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.fffffff";
76
+ export declare function resolveStoreOptions(options: G9SqliteSyncStoreOptions): G9ResolvedSqliteStoreOptions;
77
+ /** A marker in a file, written whole and moved into place (a marker cut short by a crash would read as another installation). */
78
+ export declare function fileIncarnationMarker(fileSystem: G9MarkerFileSystem, path: string): G9IncarnationMarker;
@@ -0,0 +1,78 @@
1
+ import { G9RevocationPolicy } from '../client/storeTypes.js';
2
+ import { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage } from './sql.js';
3
+ export const DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.fffffff";
4
+ export function resolveStoreOptions(options) {
5
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
6
+ if (!options || !options.driver)
7
+ throw new TypeError('A SQLite driver is required.');
8
+ if (typeof options.databasePath !== 'string' || options.databasePath.trim() === '')
9
+ throw new TypeError('Set databasePath.');
10
+ const format = (_a = options.dateTimeFormat) !== null && _a !== void 0 ? _a : DEFAULT_DATE_TIME_FORMAT;
11
+ if (format !== DEFAULT_DATE_TIME_FORMAT) {
12
+ throw new RangeError(`Only the DateTime format ${DEFAULT_DATE_TIME_FORMAT} is supported by the TypeScript store (PARITY.md).`);
13
+ }
14
+ return {
15
+ driver: options.driver,
16
+ databasePath: options.databasePath,
17
+ dateTimeStorage: (_b = options.dateTimeStorage) !== null && _b !== void 0 ? _b : G9ESqliteDateTimeStorage.Text,
18
+ dateTimeFormat: format,
19
+ decimalStorage: (_c = options.decimalStorage) !== null && _c !== void 0 ? _c : G9ESqliteDecimalStorage.Real,
20
+ incarnationMarker: (_d = options.incarnationMarker) !== null && _d !== void 0 ? _d : null,
21
+ busyTimeoutMs: (_e = options.busyTimeoutMs) !== null && _e !== void 0 ? _e : 30000,
22
+ useWriteAheadLog: (_f = options.useWriteAheadLog) !== null && _f !== void 0 ? _f : true,
23
+ revocation: (_g = options.revocation) !== null && _g !== void 0 ? _g : G9RevocationPolicy.default,
24
+ maxDecodedFrameBytes: (_h = options.maxDecodedFrameBytes) !== null && _h !== void 0 ? _h : 64 * 1024 * 1024,
25
+ maxChangedKeysPerTable: (_j = options.maxChangedKeysPerTable) !== null && _j !== void 0 ? _j : 5000,
26
+ skipTriggersDuringApply: (_k = options.skipTriggersDuringApply) !== null && _k !== void 0 ? _k : true,
27
+ skipTriggersMinRows: (_l = options.skipTriggersMinRows) !== null && _l !== void 0 ? _l : 5000,
28
+ rebuildIndexesAfterRows: (_m = options.rebuildIndexesAfterRows) !== null && _m !== void 0 ? _m : 20000,
29
+ rebuildIndexesMinimumGrowth: (_o = options.rebuildIndexesMinimumGrowth) !== null && _o !== void 0 ? _o : 1,
30
+ applySliceRows: (_p = options.applySliceRows) !== null && _p !== void 0 ? _p : 0,
31
+ applySliceRowsMax: (_q = options.applySliceRowsMax) !== null && _q !== void 0 ? _q : 32000,
32
+ maintenanceAfterRows: (_r = options.maintenanceAfterRows) !== null && _r !== void 0 ? _r : 10000,
33
+ synchronousNormalForDownloads: (_s = options.synchronousNormalForDownloads) !== null && _s !== void 0 ? _s : true,
34
+ walSizeLimitBytes: (_t = options.walSizeLimitBytes) !== null && _t !== void 0 ? _t : 64 * 1024 * 1024,
35
+ statementsPerBatch: (_u = options.statementsPerBatch) !== null && _u !== void 0 ? _u : 1500,
36
+ frameDecompressor: (_v = options.frameDecompressor) !== null && _v !== void 0 ? _v : null,
37
+ frameCompressor: (_w = options.frameCompressor) !== null && _w !== void 0 ? _w : null,
38
+ logger: (_x = options.logger) !== null && _x !== void 0 ? _x : null,
39
+ };
40
+ }
41
+ /** A marker in a file, written whole and moved into place (a marker cut short by a crash would read as another installation). */
42
+ export function fileIncarnationMarker(fileSystem, path) {
43
+ return {
44
+ async read() {
45
+ try {
46
+ const stat = await fileSystem.stat(path);
47
+ if (!stat)
48
+ return null;
49
+ const data = await fileSystem.read(path, 0, stat.size);
50
+ const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
51
+ let text = '';
52
+ for (let i = 0; i < bytes.length; i++)
53
+ text += String.fromCharCode(bytes[i]);
54
+ text = text.trim();
55
+ return text.length === 0 ? null : text;
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ },
61
+ async write(value) {
62
+ try {
63
+ const bytes = new Uint8Array(value.length);
64
+ for (let i = 0; i < value.length; i++)
65
+ bytes[i] = value.charCodeAt(i) & 0x7f;
66
+ const temporary = path + '.tmp';
67
+ await fileSystem.write(temporary, 0, bytes, true);
68
+ await fileSystem.remove(path);
69
+ await fileSystem.move(temporary, path);
70
+ return true;
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ },
76
+ };
77
+ }
78
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/sqlite/options.ts"],"names":[],"mappings":"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","sourcesContent":["// Twin of G9SyncData.Client.Sqlite/G9CSqliteSyncStoreOptions.cs. Durations are milliseconds.\nimport type { G9SyncLogger } from '../client/runs.js';\nimport { G9RevocationPolicy } from '../client/storeTypes.js';\nimport type { G9FrameDecompressor } from '../protocol/rowBatch/reader.js';\nimport type { G9FrameCompressor } from '../protocol/rowBatch/writer.js';\nimport type { G9SqliteDriver } from './driver.js';\nimport { G9ESqliteDateTimeStorage, G9ESqliteDecimalStorage } from './sql.js';\n\n/** Where the installation's incarnation lives, outside the platform's backup set (ADR-0067). */\nexport interface G9IncarnationMarker {\n /** The marker's value, or null when there is none (or it cannot be read). */\n read(): Promise<string | null>;\n /** Writes the marker whole; false when it cannot be written (restore detection is then off for the run). */\n write(value: string): Promise<boolean>;\n}\n\n/** The file operations a file-based marker needs (structurally `G9FileSystem` of @g9tm/signalr-supernetcore-client). */\nexport interface G9MarkerFileSystem {\n stat(path: string): Promise<{ readonly size: number } | null>;\n read(path: string, offset: number, length: number): Promise<Uint8Array | ArrayBuffer>;\n write(path: string, offset: number, bytes: Uint8Array, truncate?: boolean): Promise<void>;\n move(from: string, to: string): Promise<void>;\n remove(path: string): Promise<void>;\n}\n\nexport interface G9SqliteSyncStoreOptions {\n /** The SQLite driver (Lynx native, Lynxtron, or `nodeSqliteDriver()` from `@g9tm/syncdata/node`). */\n driver: G9SqliteDriver;\n /** Database file path. */\n databasePath: string;\n dateTimeStorage?: G9ESqliteDateTimeStorage;\n /** Text format for DateTime values; only the .NET default `yyyy-MM-dd'T'HH:mm:ss.fffffff` is supported. */\n dateTimeFormat?: string;\n decimalStorage?: G9ESqliteDecimalStorage;\n /** Restore/copy detection (ADR-0067): a marker outside the backup set. Null (default) turns the check off. */\n incarnationMarker?: G9IncarnationMarker | null;\n /** How long a writer waits for the database lock (the app may be writing). */\n busyTimeoutMs?: number;\n useWriteAheadLog?: boolean;\n /** What happens to a row no subscription holds any more (ADR-0026). */\n revocation?: G9RevocationPolicy;\n /** The largest decoded body accepted from one frame the store applies (ADR-0051, ADR-0066). */\n maxDecodedFrameBytes?: number;\n /** Changed keys reported per table in an apply report. */\n maxChangedKeysPerTable?: number;\n /**\n * Large applies run without evaluating the library's own triggers (ADR-0034): the TypeScript store has no\n * SQLITE_DBCONFIG_ENABLE_TRIGGER, so it drops its own capture and command triggers inside the apply transaction and\n * re-creates them from their stored SQL before commit (PARITY.md). Never while the database holds a foreign trigger.\n */\n skipTriggersDuringApply?: boolean;\n /** The smallest staged pull (rows) for which triggers are skipped; smaller applies are not worth the schema change. */\n skipTriggersMinRows?: number;\n rebuildIndexesAfterRows?: number;\n rebuildIndexesMinimumGrowth?: number;\n /** Rows per committed slice of a staged pull, or 0 to apply it in one transaction (ADR-0053). */\n applySliceRows?: number;\n applySliceRowsMax?: number;\n maintenanceAfterRows?: number;\n synchronousNormalForDownloads?: boolean;\n /** journal_size_limit of the store's connections; negative = no limit. */\n walSizeLimitBytes?: number;\n /** Statements per driver call in the apply loop (one bridge round trip each). */\n statementsPerBatch?: number;\n /** Brotli decoder for downloaded frames; the process default (setDefaultFrameDecompressor) when omitted. */\n frameDecompressor?: G9FrameDecompressor | null;\n /** Brotli encoder for push frames; uncompressed frames when omitted (every server accepts them). */\n frameCompressor?: G9FrameCompressor | null;\n logger?: G9SyncLogger | null;\n}\n\nexport type G9ResolvedSqliteStoreOptions = Required<Omit<G9SqliteSyncStoreOptions, 'incarnationMarker' | 'frameDecompressor' | 'frameCompressor' | 'logger'>> & {\n incarnationMarker: G9IncarnationMarker | null;\n frameDecompressor: G9FrameDecompressor | null;\n frameCompressor: G9FrameCompressor | null;\n logger: G9SyncLogger | null;\n};\n\nexport const DEFAULT_DATE_TIME_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.fffffff\";\n\nexport function resolveStoreOptions(options: G9SqliteSyncStoreOptions): G9ResolvedSqliteStoreOptions {\n if (!options || !options.driver) throw new TypeError('A SQLite driver is required.');\n if (typeof options.databasePath !== 'string' || options.databasePath.trim() === '') throw new TypeError('Set databasePath.');\n const format = options.dateTimeFormat ?? DEFAULT_DATE_TIME_FORMAT;\n if (format !== DEFAULT_DATE_TIME_FORMAT) {\n throw new RangeError(`Only the DateTime format ${DEFAULT_DATE_TIME_FORMAT} is supported by the TypeScript store (PARITY.md).`);\n }\n return {\n driver: options.driver,\n databasePath: options.databasePath,\n dateTimeStorage: options.dateTimeStorage ?? G9ESqliteDateTimeStorage.Text,\n dateTimeFormat: format,\n decimalStorage: options.decimalStorage ?? G9ESqliteDecimalStorage.Real,\n incarnationMarker: options.incarnationMarker ?? null,\n busyTimeoutMs: options.busyTimeoutMs ?? 30000,\n useWriteAheadLog: options.useWriteAheadLog ?? true,\n revocation: options.revocation ?? G9RevocationPolicy.default,\n maxDecodedFrameBytes: options.maxDecodedFrameBytes ?? 64 * 1024 * 1024,\n maxChangedKeysPerTable: options.maxChangedKeysPerTable ?? 5000,\n skipTriggersDuringApply: options.skipTriggersDuringApply ?? true,\n skipTriggersMinRows: options.skipTriggersMinRows ?? 5000,\n rebuildIndexesAfterRows: options.rebuildIndexesAfterRows ?? 20000,\n rebuildIndexesMinimumGrowth: options.rebuildIndexesMinimumGrowth ?? 1,\n applySliceRows: options.applySliceRows ?? 0,\n applySliceRowsMax: options.applySliceRowsMax ?? 32000,\n maintenanceAfterRows: options.maintenanceAfterRows ?? 10000,\n synchronousNormalForDownloads: options.synchronousNormalForDownloads ?? true,\n walSizeLimitBytes: options.walSizeLimitBytes ?? 64 * 1024 * 1024,\n statementsPerBatch: options.statementsPerBatch ?? 1500,\n frameDecompressor: options.frameDecompressor ?? null,\n frameCompressor: options.frameCompressor ?? null,\n logger: options.logger ?? null,\n };\n}\n\n/** A marker in a file, written whole and moved into place (a marker cut short by a crash would read as another installation). */\nexport function fileIncarnationMarker(fileSystem: G9MarkerFileSystem, path: string): G9IncarnationMarker {\n return {\n async read(): Promise<string | null> {\n try {\n const stat = await fileSystem.stat(path);\n if (!stat) return null;\n const data = await fileSystem.read(path, 0, stat.size);\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n let text = '';\n for (let i = 0; i < bytes.length; i++) text += String.fromCharCode(bytes[i] as number);\n text = text.trim();\n return text.length === 0 ? null : text;\n } catch {\n return null;\n }\n },\n async write(value: string): Promise<boolean> {\n try {\n const bytes = new Uint8Array(value.length);\n for (let i = 0; i < value.length; i++) bytes[i] = value.charCodeAt(i) & 0x7f;\n const temporary = path + '.tmp';\n await fileSystem.write(temporary, 0, bytes, true);\n await fileSystem.remove(path);\n await fileSystem.move(temporary, path);\n return true;\n } catch {\n return false;\n }\n },\n };\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { G9ApplyReport, type G9PushBatch } from '../client/storeTypes.js';
2
+ import type { G9DtNegotiatedTable, G9DtPushResult } from '../protocol/dtos.js';
3
+ import { type StoreInternals } from './internals.js';
4
+ /** `BuildPushBatchAsync`: the next batch of pending changes, oldest first, within the row and byte budgets. */
5
+ export declare function buildPushBatch(store: StoreInternals, tables: readonly G9DtNegotiatedTable[], maxRows: number, maxBytes: number): Promise<G9PushBatch | null>;
6
+ /** `ForgetUploadedRowsAsync`: removes uploaded rows of an UPLOAD-ONLY table without uploading a delete. */
7
+ export declare function forgetUploadedRows(store: StoreInternals, localTable: string, keys: readonly string[] | null): Promise<number>;
8
+ /** `ApplyPushResultAsync`. */
9
+ export declare function applyPushResult(store: StoreInternals, batch: G9PushBatch, result: G9DtPushResult, signal?: AbortSignal): Promise<G9ApplyReport>;