@powersync/common 1.6.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.
- package/LICENSE +201 -0
- package/README.md +6 -0
- package/lib/client/AbstractPowerSyncDatabase.d.ts +367 -0
- package/lib/client/AbstractPowerSyncDatabase.js +645 -0
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -0
- package/lib/client/AbstractPowerSyncOpenFactory.d.ts +29 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js +25 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js.map +1 -0
- package/lib/client/connection/PowerSyncBackendConnector.d.ts +23 -0
- package/lib/client/connection/PowerSyncBackendConnector.js +2 -0
- package/lib/client/connection/PowerSyncBackendConnector.js.map +1 -0
- package/lib/client/connection/PowerSyncCredentials.d.ts +5 -0
- package/lib/client/connection/PowerSyncCredentials.js +2 -0
- package/lib/client/connection/PowerSyncCredentials.js.map +1 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +71 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js +8 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -0
- package/lib/client/sync/bucket/CrudBatch.d.ts +31 -0
- package/lib/client/sync/bucket/CrudBatch.js +26 -0
- package/lib/client/sync/bucket/CrudBatch.js.map +1 -0
- package/lib/client/sync/bucket/CrudEntry.d.ts +86 -0
- package/lib/client/sync/bucket/CrudEntry.js +85 -0
- package/lib/client/sync/bucket/CrudEntry.js.map +1 -0
- package/lib/client/sync/bucket/CrudTransaction.d.ts +29 -0
- package/lib/client/sync/bucket/CrudTransaction.js +25 -0
- package/lib/client/sync/bucket/CrudTransaction.js.map +1 -0
- package/lib/client/sync/bucket/OpType.d.ts +16 -0
- package/lib/client/sync/bucket/OpType.js +23 -0
- package/lib/client/sync/bucket/OpType.js.map +1 -0
- package/lib/client/sync/bucket/OplogEntry.d.ts +23 -0
- package/lib/client/sync/bucket/OplogEntry.js +34 -0
- package/lib/client/sync/bucket/OplogEntry.js.map +1 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +66 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js +299 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -0
- package/lib/client/sync/bucket/SyncDataBatch.d.ts +6 -0
- package/lib/client/sync/bucket/SyncDataBatch.js +12 -0
- package/lib/client/sync/bucket/SyncDataBatch.js.map +1 -0
- package/lib/client/sync/bucket/SyncDataBucket.d.ts +40 -0
- package/lib/client/sync/bucket/SyncDataBucket.js +41 -0
- package/lib/client/sync/bucket/SyncDataBucket.js.map +1 -0
- package/lib/client/sync/stream/AbstractRemote.d.ts +25 -0
- package/lib/client/sync/stream/AbstractRemote.js +43 -0
- package/lib/client/sync/stream/AbstractRemote.js.map +1 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +101 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +478 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -0
- package/lib/client/sync/stream/streaming-sync-types.d.ts +116 -0
- package/lib/client/sync/stream/streaming-sync-types.js +23 -0
- package/lib/client/sync/stream/streaming-sync-types.js.map +1 -0
- package/lib/db/Column.d.ts +19 -0
- package/lib/db/Column.js +26 -0
- package/lib/db/Column.js.map +1 -0
- package/lib/db/DBAdapter.d.ts +95 -0
- package/lib/db/DBAdapter.js +20 -0
- package/lib/db/DBAdapter.js.map +1 -0
- package/lib/db/crud/SyncStatus.d.ts +38 -0
- package/lib/db/crud/SyncStatus.js +58 -0
- package/lib/db/crud/SyncStatus.js.map +1 -0
- package/lib/db/crud/UploadQueueStatus.d.ts +20 -0
- package/lib/db/crud/UploadQueueStatus.js +25 -0
- package/lib/db/crud/UploadQueueStatus.js.map +1 -0
- package/lib/db/schema/Index.d.ts +22 -0
- package/lib/db/schema/Index.js +30 -0
- package/lib/db/schema/Index.js.map +1 -0
- package/lib/db/schema/IndexedColumn.d.ts +19 -0
- package/lib/db/schema/IndexedColumn.js +30 -0
- package/lib/db/schema/IndexedColumn.js.map +1 -0
- package/lib/db/schema/Schema.d.ts +38 -0
- package/lib/db/schema/Schema.js +38 -0
- package/lib/db/schema/Schema.js.map +1 -0
- package/lib/db/schema/Table.d.ts +51 -0
- package/lib/db/schema/Table.js +114 -0
- package/lib/db/schema/Table.js.map +1 -0
- package/lib/db/schema/TableV2.d.ts +30 -0
- package/lib/db/schema/TableV2.js +44 -0
- package/lib/db/schema/TableV2.js.map +1 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +31 -0
- package/lib/index.js.map +1 -0
- package/lib/utils/AbortOperation.d.ts +9 -0
- package/lib/utils/AbortOperation.js +19 -0
- package/lib/utils/AbortOperation.js.map +1 -0
- package/lib/utils/BaseObserver.d.ts +20 -0
- package/lib/utils/BaseObserver.js +23 -0
- package/lib/utils/BaseObserver.js.map +1 -0
- package/lib/utils/mutex.d.ts +7 -0
- package/lib/utils/mutex.js +29 -0
- package/lib/utils/mutex.js.map +1 -0
- package/lib/utils/strings.d.ts +3 -0
- package/lib/utils/strings.js +10 -0
- package/lib/utils/strings.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { v4 as uuid } from 'uuid';
|
|
2
|
+
import { extractTableUpdates } from '../../../db/DBAdapter';
|
|
3
|
+
import { PSInternalTable } from './BucketStorageAdapter';
|
|
4
|
+
import { OpTypeEnum } from './OpType';
|
|
5
|
+
import { CrudEntry } from './CrudEntry';
|
|
6
|
+
import Logger from 'js-logger';
|
|
7
|
+
import { BaseObserver } from '../../../utils/BaseObserver';
|
|
8
|
+
const COMPACT_OPERATION_INTERVAL = 1_000;
|
|
9
|
+
export class SqliteBucketStorage extends BaseObserver {
|
|
10
|
+
db;
|
|
11
|
+
mutex;
|
|
12
|
+
logger;
|
|
13
|
+
static MAX_OP_ID = '9223372036854775807';
|
|
14
|
+
tableNames;
|
|
15
|
+
pendingBucketDeletes;
|
|
16
|
+
_hasCompletedSync;
|
|
17
|
+
updateListener;
|
|
18
|
+
/**
|
|
19
|
+
* Count up, and do a compact on startup.
|
|
20
|
+
*/
|
|
21
|
+
compactCounter = COMPACT_OPERATION_INTERVAL;
|
|
22
|
+
constructor(db, mutex, logger = Logger.get('SqliteBucketStorage')) {
|
|
23
|
+
super();
|
|
24
|
+
this.db = db;
|
|
25
|
+
this.mutex = mutex;
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
this._hasCompletedSync = false;
|
|
28
|
+
this.pendingBucketDeletes = true;
|
|
29
|
+
this.tableNames = new Set();
|
|
30
|
+
this.updateListener = db.registerListener({
|
|
31
|
+
tablesUpdated: (update) => {
|
|
32
|
+
const tables = extractTableUpdates(update);
|
|
33
|
+
if (tables.includes(PSInternalTable.CRUD)) {
|
|
34
|
+
this.iterateListeners((l) => l.crudUpdate?.());
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async init() {
|
|
40
|
+
this._hasCompletedSync = false;
|
|
41
|
+
const existingTableRows = await this.db.execute(`SELECT name FROM sqlite_master WHERE type='table' AND name GLOB 'ps_data_*'`);
|
|
42
|
+
for (const row of existingTableRows.rows?._array ?? []) {
|
|
43
|
+
this.tableNames.add(row.name);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async dispose() {
|
|
47
|
+
this.updateListener?.();
|
|
48
|
+
}
|
|
49
|
+
getMaxOpId() {
|
|
50
|
+
return SqliteBucketStorage.MAX_OP_ID;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reset any caches.
|
|
54
|
+
*/
|
|
55
|
+
startSession() { }
|
|
56
|
+
async getBucketStates() {
|
|
57
|
+
const result = await this.db.execute('SELECT name as bucket, cast(last_op as TEXT) as op_id FROM ps_buckets WHERE pending_delete = 0');
|
|
58
|
+
return result.rows?._array ?? [];
|
|
59
|
+
}
|
|
60
|
+
async saveSyncData(batch) {
|
|
61
|
+
await this.writeTransaction(async (tx) => {
|
|
62
|
+
let count = 0;
|
|
63
|
+
for (const b of batch.buckets) {
|
|
64
|
+
const result = await tx.execute('INSERT INTO powersync_operations(op, data) VALUES(?, ?)', [
|
|
65
|
+
'save',
|
|
66
|
+
JSON.stringify({ buckets: [b.toJSON()] })
|
|
67
|
+
]);
|
|
68
|
+
this.logger.debug('saveSyncData', JSON.stringify(result));
|
|
69
|
+
count += b.data.length;
|
|
70
|
+
}
|
|
71
|
+
this.compactCounter += count;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async removeBuckets(buckets) {
|
|
75
|
+
for (const bucket of buckets) {
|
|
76
|
+
await this.deleteBucket(bucket);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Mark a bucket for deletion.
|
|
81
|
+
*/
|
|
82
|
+
async deleteBucket(bucket) {
|
|
83
|
+
// Delete a bucket, but allow it to be re-created.
|
|
84
|
+
// To achieve this, we rename the bucket to a new temp name, and change all ops to remove.
|
|
85
|
+
// By itself, this new bucket would ensure that the previous objects are deleted if they contain no more references.
|
|
86
|
+
// If the old bucket is re-added, this new bucket would have no effect.
|
|
87
|
+
const newName = `$delete_${bucket}_${uuid()}`;
|
|
88
|
+
this.logger.debug('Deleting bucket', bucket);
|
|
89
|
+
// This
|
|
90
|
+
await this.writeTransaction(async (tx) => {
|
|
91
|
+
await tx.execute(`UPDATE ps_oplog SET op=${OpTypeEnum.REMOVE}, data=NULL WHERE op=${OpTypeEnum.PUT} AND superseded=0 AND bucket=?`, [bucket]);
|
|
92
|
+
// Rename bucket
|
|
93
|
+
await tx.execute('UPDATE ps_oplog SET bucket=? WHERE bucket=?', [newName, bucket]);
|
|
94
|
+
await tx.execute('DELETE FROM ps_buckets WHERE name = ?', [bucket]);
|
|
95
|
+
await tx.execute('INSERT INTO ps_buckets(name, pending_delete, last_op) SELECT ?, 1, IFNULL(MAX(op_id), 0) FROM ps_oplog WHERE bucket = ?', [newName, newName]);
|
|
96
|
+
});
|
|
97
|
+
this.logger.debug('done deleting bucket');
|
|
98
|
+
this.pendingBucketDeletes = true;
|
|
99
|
+
}
|
|
100
|
+
async hasCompletedSync() {
|
|
101
|
+
if (this._hasCompletedSync) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
const r = await this.db.execute(`SELECT name, last_applied_op FROM ps_buckets WHERE last_applied_op > 0 LIMIT 1`);
|
|
105
|
+
const completed = !!r.rows?.length;
|
|
106
|
+
if (completed) {
|
|
107
|
+
this._hasCompletedSync = true;
|
|
108
|
+
}
|
|
109
|
+
return completed;
|
|
110
|
+
}
|
|
111
|
+
async syncLocalDatabase(checkpoint) {
|
|
112
|
+
const r = await this.validateChecksums(checkpoint);
|
|
113
|
+
if (!r.checkpointValid) {
|
|
114
|
+
this.logger.error('Checksums failed for', r.checkpointFailures);
|
|
115
|
+
for (const b of r.checkpointFailures ?? []) {
|
|
116
|
+
await this.deleteBucket(b);
|
|
117
|
+
}
|
|
118
|
+
return { ready: false, checkpointValid: false, checkpointFailures: r.checkpointFailures };
|
|
119
|
+
}
|
|
120
|
+
const bucketNames = checkpoint.buckets.map((b) => b.bucket);
|
|
121
|
+
await this.writeTransaction(async (tx) => {
|
|
122
|
+
await tx.execute(`UPDATE ps_buckets SET last_op = ? WHERE name IN (SELECT json_each.value FROM json_each(?))`, [
|
|
123
|
+
checkpoint.last_op_id,
|
|
124
|
+
JSON.stringify(bucketNames)
|
|
125
|
+
]);
|
|
126
|
+
if (checkpoint.write_checkpoint) {
|
|
127
|
+
await tx.execute("UPDATE ps_buckets SET last_op = ? WHERE name = '$local'", [checkpoint.write_checkpoint]);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const valid = await this.updateObjectsFromBuckets(checkpoint);
|
|
131
|
+
if (!valid) {
|
|
132
|
+
this.logger.debug('Not at a consistent checkpoint - cannot update local db');
|
|
133
|
+
return { ready: false, checkpointValid: true };
|
|
134
|
+
}
|
|
135
|
+
await this.forceCompact();
|
|
136
|
+
return {
|
|
137
|
+
ready: true,
|
|
138
|
+
checkpointValid: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Atomically update the local state to the current checkpoint.
|
|
143
|
+
*
|
|
144
|
+
* This includes creating new tables, dropping old tables, and copying data over from the oplog.
|
|
145
|
+
*/
|
|
146
|
+
async updateObjectsFromBuckets(checkpoint) {
|
|
147
|
+
return this.writeTransaction(async (tx) => {
|
|
148
|
+
const { insertId: result } = await tx.execute('INSERT INTO powersync_operations(op, data) VALUES(?, ?)', [
|
|
149
|
+
'sync_local',
|
|
150
|
+
''
|
|
151
|
+
]);
|
|
152
|
+
return result == 1;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async validateChecksums(checkpoint) {
|
|
156
|
+
const rs = await this.db.execute('SELECT powersync_validate_checkpoint(?) as result', [JSON.stringify(checkpoint)]);
|
|
157
|
+
const resultItem = rs.rows?.item(0);
|
|
158
|
+
this.logger.debug('validateChecksums result item', resultItem);
|
|
159
|
+
if (!resultItem) {
|
|
160
|
+
return {
|
|
161
|
+
checkpointValid: false,
|
|
162
|
+
ready: false,
|
|
163
|
+
checkpointFailures: []
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const result = JSON.parse(resultItem['result']);
|
|
167
|
+
if (result['valid']) {
|
|
168
|
+
return { ready: true, checkpointValid: true };
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
return {
|
|
172
|
+
checkpointValid: false,
|
|
173
|
+
ready: false,
|
|
174
|
+
checkpointFailures: result['failed_buckets']
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Force a compact, for tests.
|
|
180
|
+
*/
|
|
181
|
+
async forceCompact() {
|
|
182
|
+
this.compactCounter = COMPACT_OPERATION_INTERVAL;
|
|
183
|
+
this.pendingBucketDeletes = true;
|
|
184
|
+
await this.autoCompact();
|
|
185
|
+
}
|
|
186
|
+
async autoCompact() {
|
|
187
|
+
await this.deletePendingBuckets();
|
|
188
|
+
await this.clearRemoveOps();
|
|
189
|
+
}
|
|
190
|
+
async deletePendingBuckets() {
|
|
191
|
+
if (this.pendingBucketDeletes !== false) {
|
|
192
|
+
await this.writeTransaction(async (tx) => {
|
|
193
|
+
await tx.execute('DELETE FROM ps_oplog WHERE bucket IN (SELECT name FROM ps_buckets WHERE pending_delete = 1 AND last_applied_op = last_op AND last_op >= target_op)');
|
|
194
|
+
await tx.execute('DELETE FROM ps_buckets WHERE pending_delete = 1 AND last_applied_op = last_op AND last_op >= target_op');
|
|
195
|
+
});
|
|
196
|
+
// Executed once after start-up, and again when there are pending deletes.
|
|
197
|
+
this.pendingBucketDeletes = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async clearRemoveOps() {
|
|
201
|
+
if (this.compactCounter < COMPACT_OPERATION_INTERVAL) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
await this.writeTransaction(async (tx) => {
|
|
205
|
+
await tx.execute('INSERT INTO powersync_operations(op, data) VALUES (?, ?)', ['clear_remove_ops', '']);
|
|
206
|
+
});
|
|
207
|
+
this.compactCounter = 0;
|
|
208
|
+
}
|
|
209
|
+
async updateLocalTarget(cb) {
|
|
210
|
+
const rs1 = await this.db.execute("SELECT target_op FROM ps_buckets WHERE name = '$local' AND target_op = ?", [
|
|
211
|
+
SqliteBucketStorage.MAX_OP_ID
|
|
212
|
+
]);
|
|
213
|
+
if (!rs1.rows?.length) {
|
|
214
|
+
// Nothing to update
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
const rs = await this.db.execute("SELECT seq FROM sqlite_sequence WHERE name = 'ps_crud'");
|
|
218
|
+
if (!rs.rows?.length) {
|
|
219
|
+
// Nothing to update
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const seqBefore = rs.rows?.item(0)['seq'];
|
|
223
|
+
const opId = await cb();
|
|
224
|
+
this.logger.debug(`[updateLocalTarget] Updating target to checkpoint ${opId}`);
|
|
225
|
+
return this.writeTransaction(async (tx) => {
|
|
226
|
+
const anyData = await tx.execute('SELECT 1 FROM ps_crud LIMIT 1');
|
|
227
|
+
if (anyData.rows?.length) {
|
|
228
|
+
// if isNotEmpty
|
|
229
|
+
this.logger.debug('updateLocalTarget', 'ps crud is not empty');
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
const rs = await tx.execute("SELECT seq FROM sqlite_sequence WHERE name = 'ps_crud'");
|
|
233
|
+
if (!rs.rows?.length) {
|
|
234
|
+
// assert isNotEmpty
|
|
235
|
+
throw new Error('SQlite Sequence should not be empty');
|
|
236
|
+
}
|
|
237
|
+
const seqAfter = rs.rows?.item(0)['seq'];
|
|
238
|
+
this.logger.debug('seqAfter', JSON.stringify(rs.rows?.item(0)));
|
|
239
|
+
if (seqAfter != seqBefore) {
|
|
240
|
+
this.logger.debug('seqAfter != seqBefore', seqAfter, seqBefore);
|
|
241
|
+
// New crud data may have been uploaded since we got the checkpoint. Abort.
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
const response = await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [opId]);
|
|
245
|
+
this.logger.debug(['[updateLocalTarget] Response from updating target_op ', JSON.stringify(response)]);
|
|
246
|
+
return true;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async hasCrud() {
|
|
250
|
+
const anyData = await this.db.execute('SELECT 1 FROM ps_crud LIMIT 1');
|
|
251
|
+
return !!anyData.rows?.length;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get a batch of objects to send to the server.
|
|
255
|
+
* When the objects are successfully sent to the server, call .complete()
|
|
256
|
+
*/
|
|
257
|
+
async getCrudBatch(limit = 100) {
|
|
258
|
+
if (!(await this.hasCrud())) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const crudResult = await this.db.execute('SELECT * FROM ps_crud ORDER BY id ASC LIMIT ?', [limit]);
|
|
262
|
+
const all = [];
|
|
263
|
+
for (const row of crudResult.rows?._array ?? []) {
|
|
264
|
+
all.push(CrudEntry.fromRow(row));
|
|
265
|
+
}
|
|
266
|
+
if (all.length === 0) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const last = all[all.length - 1];
|
|
270
|
+
return {
|
|
271
|
+
crud: all,
|
|
272
|
+
haveMore: true,
|
|
273
|
+
complete: async (writeCheckpoint) => {
|
|
274
|
+
return this.writeTransaction(async (tx) => {
|
|
275
|
+
await tx.execute('DELETE FROM ps_crud WHERE id <= ?', [last.clientId]);
|
|
276
|
+
if (writeCheckpoint) {
|
|
277
|
+
const crudResult = await tx.execute('SELECT 1 FROM ps_crud LIMIT 1');
|
|
278
|
+
if (crudResult.rows?.length) {
|
|
279
|
+
await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [writeCheckpoint]);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
await tx.execute("UPDATE ps_buckets SET target_op = ? WHERE name='$local'", [this.getMaxOpId()]);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
async writeTransaction(callback, options) {
|
|
290
|
+
return this.db.writeTransaction(callback, options);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Set a target checkpoint.
|
|
294
|
+
*/
|
|
295
|
+
async setTargetCheckpoint(checkpoint) {
|
|
296
|
+
// No-op for now
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=SqliteBucketStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqliteBucketStorage.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/SqliteBucketStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SyncDataBucket } from './SyncDataBucket';
|
|
2
|
+
// TODO JSON
|
|
3
|
+
export class SyncDataBatch {
|
|
4
|
+
buckets;
|
|
5
|
+
static fromJSON(json) {
|
|
6
|
+
return new SyncDataBatch(json.buckets.map((bucket) => SyncDataBucket.fromRow(bucket)));
|
|
7
|
+
}
|
|
8
|
+
constructor(buckets) {
|
|
9
|
+
this.buckets = buckets;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=SyncDataBatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncDataBatch.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/SyncDataBatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,YAAY;AAEZ,MAAM,OAAO,aAAa;IAKL;IAJnB,MAAM,CAAC,QAAQ,CAAC,IAAS;QACvB,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,YAAmB,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;CACjD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { OplogEntry, OplogEntryJSON } from './OplogEntry';
|
|
2
|
+
export type SyncDataBucketJSON = {
|
|
3
|
+
bucket: string;
|
|
4
|
+
has_more?: boolean;
|
|
5
|
+
after?: string;
|
|
6
|
+
next_after?: string;
|
|
7
|
+
data: OplogEntryJSON[];
|
|
8
|
+
};
|
|
9
|
+
export declare const MAX_OP_ID = "9223372036854775807";
|
|
10
|
+
export declare class SyncDataBucket {
|
|
11
|
+
bucket: string;
|
|
12
|
+
data: OplogEntry[];
|
|
13
|
+
/**
|
|
14
|
+
* True if the response does not contain all the data for this bucket, and another request must be made.
|
|
15
|
+
*/
|
|
16
|
+
has_more: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The `after` specified in the request.
|
|
19
|
+
*/
|
|
20
|
+
after?: string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Use this for the next request.
|
|
23
|
+
*/
|
|
24
|
+
next_after?: string | undefined;
|
|
25
|
+
static fromRow(row: SyncDataBucketJSON): SyncDataBucket;
|
|
26
|
+
constructor(bucket: string, data: OplogEntry[],
|
|
27
|
+
/**
|
|
28
|
+
* True if the response does not contain all the data for this bucket, and another request must be made.
|
|
29
|
+
*/
|
|
30
|
+
has_more: boolean,
|
|
31
|
+
/**
|
|
32
|
+
* The `after` specified in the request.
|
|
33
|
+
*/
|
|
34
|
+
after?: string | undefined,
|
|
35
|
+
/**
|
|
36
|
+
* Use this for the next request.
|
|
37
|
+
*/
|
|
38
|
+
next_after?: string | undefined);
|
|
39
|
+
toJSON(): SyncDataBucketJSON;
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { OplogEntry } from './OplogEntry';
|
|
2
|
+
export const MAX_OP_ID = '9223372036854775807';
|
|
3
|
+
export class SyncDataBucket {
|
|
4
|
+
bucket;
|
|
5
|
+
data;
|
|
6
|
+
has_more;
|
|
7
|
+
after;
|
|
8
|
+
next_after;
|
|
9
|
+
static fromRow(row) {
|
|
10
|
+
return new SyncDataBucket(row.bucket, row.data.map((entry) => OplogEntry.fromRow(entry)), row.has_more ?? false, row.after, row.next_after);
|
|
11
|
+
}
|
|
12
|
+
constructor(bucket, data,
|
|
13
|
+
/**
|
|
14
|
+
* True if the response does not contain all the data for this bucket, and another request must be made.
|
|
15
|
+
*/
|
|
16
|
+
has_more,
|
|
17
|
+
/**
|
|
18
|
+
* The `after` specified in the request.
|
|
19
|
+
*/
|
|
20
|
+
after,
|
|
21
|
+
/**
|
|
22
|
+
* Use this for the next request.
|
|
23
|
+
*/
|
|
24
|
+
next_after) {
|
|
25
|
+
this.bucket = bucket;
|
|
26
|
+
this.data = data;
|
|
27
|
+
this.has_more = has_more;
|
|
28
|
+
this.after = after;
|
|
29
|
+
this.next_after = next_after;
|
|
30
|
+
}
|
|
31
|
+
toJSON() {
|
|
32
|
+
return {
|
|
33
|
+
bucket: this.bucket,
|
|
34
|
+
has_more: this.has_more,
|
|
35
|
+
after: this.after,
|
|
36
|
+
next_after: this.next_after,
|
|
37
|
+
data: this.data.map((entry) => entry.toJSON())
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=SyncDataBucket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncDataBucket.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/SyncDataBucket.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAkB,MAAM,cAAc,CAAC;AAU1D,MAAM,CAAC,MAAM,SAAS,GAAG,qBAAqB,CAAC;AAE/C,MAAM,OAAO,cAAc;IAYhB;IACA;IAIA;IAIA;IAIA;IAxBT,MAAM,CAAC,OAAO,CAAC,GAAuB;QACpC,OAAO,IAAI,cAAc,CACvB,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAClD,GAAG,CAAC,QAAQ,IAAI,KAAK,EACrB,GAAG,CAAC,KAAK,EACT,GAAG,CAAC,UAAU,CACf,CAAC;IACJ,CAAC;IAED,YACS,MAAc,EACd,IAAkB;IACzB;;OAEG;IACI,QAAiB;IACxB;;OAEG;IACI,KAAY;IACnB;;OAEG;IACI,UAAiB;QAbjB,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAc;QAIlB,aAAQ,GAAR,QAAQ,CAAS;QAIjB,UAAK,GAAL,KAAK,CAAO;QAIZ,eAAU,GAAV,UAAU,CAAO;IACvB,CAAC;IAEJ,MAAM;QACJ,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ILogger } from 'js-logger';
|
|
3
|
+
import { PowerSyncCredentials } from '../../connection/PowerSyncCredentials';
|
|
4
|
+
export type RemoteConnector = {
|
|
5
|
+
fetchCredentials: () => Promise<PowerSyncCredentials | null>;
|
|
6
|
+
};
|
|
7
|
+
export declare const DEFAULT_REMOTE_LOGGER: ILogger;
|
|
8
|
+
export declare abstract class AbstractRemote {
|
|
9
|
+
protected connector: RemoteConnector;
|
|
10
|
+
protected logger: ILogger;
|
|
11
|
+
protected credentials: PowerSyncCredentials | null;
|
|
12
|
+
constructor(connector: RemoteConnector, logger?: ILogger);
|
|
13
|
+
getCredentials(): Promise<PowerSyncCredentials | null>;
|
|
14
|
+
protected buildRequest(path: string): Promise<{
|
|
15
|
+
url: string;
|
|
16
|
+
headers: {
|
|
17
|
+
'content-type': string;
|
|
18
|
+
Authorization: string;
|
|
19
|
+
};
|
|
20
|
+
}>;
|
|
21
|
+
abstract post(path: string, data: any, headers?: Record<string, string>): Promise<any>;
|
|
22
|
+
abstract get(path: string, headers?: Record<string, string>): Promise<any>;
|
|
23
|
+
abstract postStreaming(path: string, data: any, headers?: Record<string, string>, signal?: AbortSignal): Promise<any>;
|
|
24
|
+
isAvailable(): boolean;
|
|
25
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Logger from 'js-logger';
|
|
2
|
+
// Refresh at least 30 sec before it expires
|
|
3
|
+
const REFRESH_CREDENTIALS_SAFETY_PERIOD_MS = 30_000;
|
|
4
|
+
export const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
|
|
5
|
+
export class AbstractRemote {
|
|
6
|
+
connector;
|
|
7
|
+
logger;
|
|
8
|
+
credentials = null;
|
|
9
|
+
constructor(connector, logger = DEFAULT_REMOTE_LOGGER) {
|
|
10
|
+
this.connector = connector;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
}
|
|
13
|
+
async getCredentials() {
|
|
14
|
+
const { expiresAt } = this.credentials ?? {};
|
|
15
|
+
if (expiresAt && expiresAt > new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS)) {
|
|
16
|
+
return this.credentials;
|
|
17
|
+
}
|
|
18
|
+
this.credentials = await this.connector.fetchCredentials();
|
|
19
|
+
return this.credentials;
|
|
20
|
+
}
|
|
21
|
+
async buildRequest(path) {
|
|
22
|
+
const credentials = await this.getCredentials();
|
|
23
|
+
if (credentials != null && (credentials.endpoint == null || credentials.endpoint == '')) {
|
|
24
|
+
throw new Error('PowerSync endpoint not configured');
|
|
25
|
+
}
|
|
26
|
+
else if (credentials?.token == null || credentials?.token == '') {
|
|
27
|
+
const error = new Error(`Not signed in`);
|
|
28
|
+
error.status = 401;
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
url: credentials.endpoint + path,
|
|
33
|
+
headers: {
|
|
34
|
+
'content-type': 'application/json',
|
|
35
|
+
Authorization: `Token ${credentials.token}`
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
isAvailable() {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=AbstractRemote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractRemote.js","sourceRoot":"","sources":["../../../../src/client/sync/stream/AbstractRemote.ts"],"names":[],"mappings":"AAAA,OAAO,MAAmB,MAAM,WAAW,CAAC;AAO5C,4CAA4C;AAC5C,MAAM,oCAAoC,GAAG,MAAM,CAAC;AAEpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAEnE,MAAM,OAAgB,cAAc;IAItB;IACA;IAJF,WAAW,GAAgC,IAAI,CAAC;IAE1D,YACY,SAA0B,EAC1B,SAAkB,qBAAqB;QADvC,cAAS,GAAT,SAAS,CAAiB;QAC1B,WAAM,GAAN,MAAM,CAAiC;IAChD,CAAC;IAEJ,KAAK,CAAC,cAAc;QAClB,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;QAC7C,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,oCAAoC,CAAC,EAAE,CAAC;YACnG,OAAO,IAAI,CAAC,WAAY,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAES,KAAK,CAAC,YAAY,CAAC,IAAY;QACvC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,IAAI,IAAI,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;aAAM,IAAI,WAAW,EAAE,KAAK,IAAI,IAAI,IAAI,WAAW,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAClE,MAAM,KAAK,GAAQ,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9C,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACnB,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO;YACL,GAAG,EAAE,WAAW,CAAC,QAAQ,GAAG,IAAI;YAChC,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,SAAS,WAAW,CAAC,KAAK,EAAE;aAC5C;SACF,CAAC;IACJ,CAAC;IAMD,WAAW;QACT,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ILogger } from 'js-logger';
|
|
3
|
+
import { StreamingSyncLine, StreamingSyncRequest } from './streaming-sync-types';
|
|
4
|
+
import { AbstractRemote } from './AbstractRemote';
|
|
5
|
+
import { BucketStorageAdapter } from '../bucket/BucketStorageAdapter';
|
|
6
|
+
import { SyncStatus, SyncStatusOptions } from '../../../db/crud/SyncStatus';
|
|
7
|
+
import { BaseObserver, BaseListener, Disposable } from '../../../utils/BaseObserver';
|
|
8
|
+
export declare enum LockType {
|
|
9
|
+
CRUD = "crud",
|
|
10
|
+
SYNC = "sync"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Abstract Lock to be implemented by various JS environments
|
|
14
|
+
*/
|
|
15
|
+
export interface LockOptions<T> {
|
|
16
|
+
callback: () => Promise<T>;
|
|
17
|
+
type: LockType;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}
|
|
20
|
+
export interface AbstractStreamingSyncImplementationOptions {
|
|
21
|
+
adapter: BucketStorageAdapter;
|
|
22
|
+
uploadCrud: () => Promise<void>;
|
|
23
|
+
crudUploadThrottleMs?: number;
|
|
24
|
+
/**
|
|
25
|
+
* An identifier for which PowerSync DB this sync implementation is
|
|
26
|
+
* linked to. Most commonly DB name, but not restricted to DB name.
|
|
27
|
+
*/
|
|
28
|
+
identifier?: string;
|
|
29
|
+
logger?: ILogger;
|
|
30
|
+
remote: AbstractRemote;
|
|
31
|
+
retryDelayMs?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface StreamingSyncImplementationListener extends BaseListener {
|
|
34
|
+
/**
|
|
35
|
+
* Triggered whenever a status update has been attempted to be made or
|
|
36
|
+
* refreshed.
|
|
37
|
+
*/
|
|
38
|
+
statusUpdated?: ((statusUpdate: SyncStatusOptions) => void) | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Triggers whenever the status' members have changed in value
|
|
41
|
+
*/
|
|
42
|
+
statusChanged?: ((status: SyncStatus) => void) | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface StreamingSyncImplementation extends BaseObserver<StreamingSyncImplementationListener>, Disposable {
|
|
45
|
+
/**
|
|
46
|
+
* Connects to the sync service
|
|
47
|
+
*/
|
|
48
|
+
connect(): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Disconnects from the sync services.
|
|
51
|
+
* @throws if not connected or if abort is not controlled internally
|
|
52
|
+
*/
|
|
53
|
+
disconnect(): Promise<void>;
|
|
54
|
+
getWriteCheckpoint: () => Promise<string>;
|
|
55
|
+
hasCompletedSync: () => Promise<boolean>;
|
|
56
|
+
isConnected: boolean;
|
|
57
|
+
lastSyncedAt?: Date;
|
|
58
|
+
syncStatus: SyncStatus;
|
|
59
|
+
triggerCrudUpload: () => void;
|
|
60
|
+
waitForReady(): Promise<void>;
|
|
61
|
+
waitForStatus(status: SyncStatusOptions): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
export declare const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
64
|
+
export declare const DEFAULT_STREAMING_SYNC_OPTIONS: {
|
|
65
|
+
retryDelayMs: number;
|
|
66
|
+
logger: ILogger;
|
|
67
|
+
crudUploadThrottleMs: number;
|
|
68
|
+
};
|
|
69
|
+
export declare abstract class AbstractStreamingSyncImplementation extends BaseObserver<StreamingSyncImplementationListener> implements StreamingSyncImplementation {
|
|
70
|
+
protected _lastSyncedAt: Date | null;
|
|
71
|
+
protected options: AbstractStreamingSyncImplementationOptions;
|
|
72
|
+
protected abortController: AbortController | null;
|
|
73
|
+
protected crudUpdateListener?: () => void;
|
|
74
|
+
protected streamingSyncPromise?: Promise<void>;
|
|
75
|
+
syncStatus: SyncStatus;
|
|
76
|
+
triggerCrudUpload: () => void;
|
|
77
|
+
constructor(options: AbstractStreamingSyncImplementationOptions);
|
|
78
|
+
waitForReady(): Promise<void>;
|
|
79
|
+
waitForStatus(status: SyncStatusOptions): Promise<void>;
|
|
80
|
+
get lastSyncedAt(): Date | undefined;
|
|
81
|
+
get isConnected(): boolean;
|
|
82
|
+
protected get logger(): ILogger;
|
|
83
|
+
dispose(): Promise<void>;
|
|
84
|
+
abstract obtainLock<T>(lockOptions: LockOptions<T>): Promise<T>;
|
|
85
|
+
hasCompletedSync(): Promise<boolean>;
|
|
86
|
+
getWriteCheckpoint(): Promise<string>;
|
|
87
|
+
protected _uploadAllCrud(): Promise<void>;
|
|
88
|
+
protected uploadCrudBatch(): Promise<boolean>;
|
|
89
|
+
connect(): Promise<void>;
|
|
90
|
+
disconnect(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* @deprecated use [connect instead]
|
|
93
|
+
*/
|
|
94
|
+
streamingSync(signal?: AbortSignal): Promise<void>;
|
|
95
|
+
protected streamingSyncIteration(signal: AbortSignal, progress?: () => void): Promise<{
|
|
96
|
+
retry?: boolean;
|
|
97
|
+
}>;
|
|
98
|
+
protected streamingSyncRequest(req: StreamingSyncRequest, signal?: AbortSignal): AsyncGenerator<StreamingSyncLine>;
|
|
99
|
+
protected updateSyncStatus(options: SyncStatusOptions): void;
|
|
100
|
+
private delayRetry;
|
|
101
|
+
}
|