@powersync/service-core 0.18.0 → 0.18.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/CHANGELOG.md +6 -0
- package/dist/api/RouteAPI.d.ts +8 -0
- package/dist/routes/configure-fastify.d.ts +3 -3
- package/dist/routes/endpoints/admin.d.ts +6 -6
- package/dist/routes/endpoints/checkpointing.js +13 -83
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/util/checkpointing.d.ts +13 -0
- package/dist/util/checkpointing.js +92 -0
- package/dist/util/checkpointing.js.map +1 -0
- package/dist/util/util-index.d.ts +1 -0
- package/dist/util/util-index.js +1 -0
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +0 -1
- package/dist/util/utils.js +0 -9
- package/dist/util/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/api/RouteAPI.ts +10 -0
- package/src/routes/endpoints/checkpointing.ts +8 -19
- package/src/util/checkpointing.ts +43 -0
- package/src/util/util-index.ts +1 -0
- package/src/util/utils.ts +0 -10
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
package/dist/api/RouteAPI.d.ts
CHANGED
|
@@ -46,6 +46,13 @@ export interface RouteAPI {
|
|
|
46
46
|
* Get the current LSN or equivalent replication HEAD position identifier
|
|
47
47
|
*/
|
|
48
48
|
getReplicationHead(): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Get the current LSN or equivalent replication HEAD position identifier.
|
|
51
|
+
*
|
|
52
|
+
* The position is provided to the callback. After the callback returns,
|
|
53
|
+
* the replication head or a greater one will be streamed on the replication stream.
|
|
54
|
+
*/
|
|
55
|
+
createReplicationHead<T>(callback: ReplicationHeadCallback<T>): Promise<T>;
|
|
49
56
|
/**
|
|
50
57
|
* @returns The schema for tables inside the connected database. This is typically
|
|
51
58
|
* used to validate sync rules.
|
|
@@ -65,3 +72,4 @@ export interface RouteAPI {
|
|
|
65
72
|
*/
|
|
66
73
|
getParseSyncRulesOptions(): ParseSyncRulesOptions;
|
|
67
74
|
}
|
|
75
|
+
export type ReplicationHeadCallback<T> = (head: string) => Promise<T>;
|
|
@@ -426,8 +426,8 @@ export declare const DEFAULT_ROUTE_OPTIONS: {
|
|
|
426
426
|
level: "warning" | "fatal";
|
|
427
427
|
}[];
|
|
428
428
|
connections: {
|
|
429
|
-
tag: string;
|
|
430
429
|
id: string;
|
|
430
|
+
tag: string;
|
|
431
431
|
slot_name: string;
|
|
432
432
|
initial_replication_done: boolean;
|
|
433
433
|
tables: {
|
|
@@ -458,8 +458,8 @@ export declare const DEFAULT_ROUTE_OPTIONS: {
|
|
|
458
458
|
level: "warning" | "fatal";
|
|
459
459
|
}[];
|
|
460
460
|
connections: {
|
|
461
|
-
tag: string;
|
|
462
461
|
id: string;
|
|
462
|
+
tag: string;
|
|
463
463
|
slot_name: string;
|
|
464
464
|
initial_replication_done: boolean;
|
|
465
465
|
tables: {
|
|
@@ -501,8 +501,8 @@ export declare const DEFAULT_ROUTE_OPTIONS: {
|
|
|
501
501
|
level: "warning" | "fatal";
|
|
502
502
|
}[];
|
|
503
503
|
connections: {
|
|
504
|
-
tag: string;
|
|
505
504
|
id: string;
|
|
505
|
+
tag: string;
|
|
506
506
|
slot_name: string;
|
|
507
507
|
initial_replication_done: boolean;
|
|
508
508
|
tables: {
|
|
@@ -405,8 +405,8 @@ export declare const validate: router.Endpoint<{
|
|
|
405
405
|
level: "warning" | "fatal";
|
|
406
406
|
}[];
|
|
407
407
|
connections: {
|
|
408
|
-
tag: string;
|
|
409
408
|
id: string;
|
|
409
|
+
tag: string;
|
|
410
410
|
slot_name: string;
|
|
411
411
|
initial_replication_done: boolean;
|
|
412
412
|
tables: {
|
|
@@ -437,8 +437,8 @@ export declare const validate: router.Endpoint<{
|
|
|
437
437
|
level: "warning" | "fatal";
|
|
438
438
|
}[];
|
|
439
439
|
connections: {
|
|
440
|
-
tag: string;
|
|
441
440
|
id: string;
|
|
441
|
+
tag: string;
|
|
442
442
|
slot_name: string;
|
|
443
443
|
initial_replication_done: boolean;
|
|
444
444
|
tables: {
|
|
@@ -480,8 +480,8 @@ export declare const validate: router.Endpoint<{
|
|
|
480
480
|
level: "warning" | "fatal";
|
|
481
481
|
}[];
|
|
482
482
|
connections: {
|
|
483
|
-
tag: string;
|
|
484
483
|
id: string;
|
|
484
|
+
tag: string;
|
|
485
485
|
slot_name: string;
|
|
486
486
|
initial_replication_done: boolean;
|
|
487
487
|
tables: {
|
|
@@ -906,8 +906,8 @@ export declare const ADMIN_ROUTES: ((router.Endpoint<{
|
|
|
906
906
|
level: "warning" | "fatal";
|
|
907
907
|
}[];
|
|
908
908
|
connections: {
|
|
909
|
-
tag: string;
|
|
910
909
|
id: string;
|
|
910
|
+
tag: string;
|
|
911
911
|
slot_name: string;
|
|
912
912
|
initial_replication_done: boolean;
|
|
913
913
|
tables: {
|
|
@@ -938,8 +938,8 @@ export declare const ADMIN_ROUTES: ((router.Endpoint<{
|
|
|
938
938
|
level: "warning" | "fatal";
|
|
939
939
|
}[];
|
|
940
940
|
connections: {
|
|
941
|
-
tag: string;
|
|
942
941
|
id: string;
|
|
942
|
+
tag: string;
|
|
943
943
|
slot_name: string;
|
|
944
944
|
initial_replication_done: boolean;
|
|
945
945
|
tables: {
|
|
@@ -981,8 +981,8 @@ export declare const ADMIN_ROUTES: ((router.Endpoint<{
|
|
|
981
981
|
level: "warning" | "fatal";
|
|
982
982
|
}[];
|
|
983
983
|
connections: {
|
|
984
|
-
tag: string;
|
|
985
984
|
id: string;
|
|
985
|
+
tag: string;
|
|
986
986
|
slot_name: string;
|
|
987
987
|
initial_replication_done: boolean;
|
|
988
988
|
tables: {
|
|
@@ -1,58 +1,5 @@
|
|
|
1
|
-
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
-
if (value !== null && value !== void 0) {
|
|
3
|
-
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
-
var dispose, inner;
|
|
5
|
-
if (async) {
|
|
6
|
-
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
-
dispose = value[Symbol.asyncDispose];
|
|
8
|
-
}
|
|
9
|
-
if (dispose === void 0) {
|
|
10
|
-
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
-
dispose = value[Symbol.dispose];
|
|
12
|
-
if (async) inner = dispose;
|
|
13
|
-
}
|
|
14
|
-
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
-
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
-
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
-
}
|
|
18
|
-
else if (async) {
|
|
19
|
-
env.stack.push({ async: true });
|
|
20
|
-
}
|
|
21
|
-
return value;
|
|
22
|
-
};
|
|
23
|
-
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
-
return function (env) {
|
|
25
|
-
function fail(e) {
|
|
26
|
-
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
-
env.hasError = true;
|
|
28
|
-
}
|
|
29
|
-
var r, s = 0;
|
|
30
|
-
function next() {
|
|
31
|
-
while (r = env.stack.pop()) {
|
|
32
|
-
try {
|
|
33
|
-
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
-
if (r.dispose) {
|
|
35
|
-
var result = r.dispose.call(r.value);
|
|
36
|
-
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
-
}
|
|
38
|
-
else s |= 1;
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
fail(e);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
-
if (env.hasError) throw env.error;
|
|
46
|
-
}
|
|
47
|
-
return next();
|
|
48
|
-
};
|
|
49
|
-
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
-
var e = new Error(message);
|
|
51
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
-
});
|
|
53
1
|
import { logger, router, schema } from '@powersync/lib-services-framework';
|
|
54
2
|
import * as t from 'ts-codec';
|
|
55
|
-
import * as framework from '@powersync/lib-services-framework';
|
|
56
3
|
import * as util from '../../util/util-index.js';
|
|
57
4
|
import { authUser } from '../auth.js';
|
|
58
5
|
import { routeDefinition } from '../router.js';
|
|
@@ -70,7 +17,7 @@ export const writeCheckpoint = routeDefinition({
|
|
|
70
17
|
// This old API needs a persisted checkpoint id.
|
|
71
18
|
// Since we don't use LSNs anymore, the only way to get that is to wait.
|
|
72
19
|
const start = Date.now();
|
|
73
|
-
const head = await apiHandler.
|
|
20
|
+
const head = await apiHandler.createReplicationHead(async (head) => head);
|
|
74
21
|
const timeout = 50_000;
|
|
75
22
|
logger.info(`Waiting for LSN checkpoint: ${head}`);
|
|
76
23
|
while (Date.now() - start < timeout) {
|
|
@@ -93,35 +40,18 @@ export const writeCheckpoint2 = routeDefinition({
|
|
|
93
40
|
authorize: authUser,
|
|
94
41
|
validator: schema.createTsCodecValidator(WriteCheckpointRequest, { allowAdditional: true }),
|
|
95
42
|
handler: async (payload) => {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const syncBucketStorage = __addDisposableResource(env_1, activeBucketStorage.getInstance(activeSyncRules), false);
|
|
109
|
-
const writeCheckpoint = await syncBucketStorage.createManagedWriteCheckpoint({
|
|
110
|
-
user_id: full_user_id,
|
|
111
|
-
heads: { '1': currentCheckpoint }
|
|
112
|
-
});
|
|
113
|
-
logger.info(`Write checkpoint 2: ${JSON.stringify({ currentCheckpoint, id: String(full_user_id) })}`);
|
|
114
|
-
return {
|
|
115
|
-
write_checkpoint: String(writeCheckpoint)
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
catch (e_1) {
|
|
119
|
-
env_1.error = e_1;
|
|
120
|
-
env_1.hasError = true;
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
__disposeResources(env_1);
|
|
124
|
-
}
|
|
43
|
+
const { user_id, service_context } = payload.context;
|
|
44
|
+
const apiHandler = service_context.routerEngine.getAPI();
|
|
45
|
+
const { replicationHead, writeCheckpoint } = await util.createWriteCheckpoint({
|
|
46
|
+
userId: user_id,
|
|
47
|
+
clientId: payload.params.client_id,
|
|
48
|
+
api: apiHandler,
|
|
49
|
+
storage: service_context.storageEngine.activeBucketStorage
|
|
50
|
+
});
|
|
51
|
+
logger.info(`Write checkpoint for ${user_id}/${payload.params.client_id}: ${writeCheckpoint} | ${replicationHead}`);
|
|
52
|
+
return {
|
|
53
|
+
write_checkpoint: String(writeCheckpoint)
|
|
54
|
+
};
|
|
125
55
|
}
|
|
126
56
|
});
|
|
127
57
|
export const CHECKPOINT_ROUTES = [writeCheckpoint, writeCheckpoint2];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpointing.js","sourceRoot":"","sources":["../../../src/routes/endpoints/checkpointing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpointing.js","sourceRoot":"","sources":["../../../src/routes/endpoints/checkpointing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RouteAPI } from '../api/RouteAPI.js';
|
|
2
|
+
import { BucketStorageFactory } from '../storage/BucketStorage.js';
|
|
3
|
+
export interface CreateWriteCheckpointOptions {
|
|
4
|
+
userId: string | undefined;
|
|
5
|
+
clientId: string | undefined;
|
|
6
|
+
api: RouteAPI;
|
|
7
|
+
storage: BucketStorageFactory;
|
|
8
|
+
}
|
|
9
|
+
export declare function createWriteCheckpoint(options: CreateWriteCheckpointOptions): Promise<{
|
|
10
|
+
writeCheckpoint: string;
|
|
11
|
+
replicationHead: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function checkpointUserId(user_id: string | undefined, client_id: string | undefined): string;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
import { ErrorCode, ServiceError } from '@powersync/lib-services-framework';
|
|
54
|
+
export async function createWriteCheckpoint(options) {
|
|
55
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
56
|
+
try {
|
|
57
|
+
const full_user_id = checkpointUserId(options.userId, options.clientId);
|
|
58
|
+
const activeSyncRules = await options.storage.getActiveSyncRulesContent();
|
|
59
|
+
if (!activeSyncRules) {
|
|
60
|
+
throw new ServiceError(ErrorCode.PSYNC_S2302, `Cannot create Write Checkpoint since no sync rules are active.`);
|
|
61
|
+
}
|
|
62
|
+
const syncBucketStorage = __addDisposableResource(env_1, options.storage.getInstance(activeSyncRules), false);
|
|
63
|
+
const { writeCheckpoint, currentCheckpoint } = await options.api.createReplicationHead(async (currentCheckpoint) => {
|
|
64
|
+
const writeCheckpoint = await syncBucketStorage.createManagedWriteCheckpoint({
|
|
65
|
+
user_id: full_user_id,
|
|
66
|
+
heads: { '1': currentCheckpoint }
|
|
67
|
+
});
|
|
68
|
+
return { writeCheckpoint, currentCheckpoint };
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
writeCheckpoint: String(writeCheckpoint),
|
|
72
|
+
replicationHead: currentCheckpoint
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (e_1) {
|
|
76
|
+
env_1.error = e_1;
|
|
77
|
+
env_1.hasError = true;
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
__disposeResources(env_1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function checkpointUserId(user_id, client_id) {
|
|
84
|
+
if (user_id == null) {
|
|
85
|
+
throw new Error('user_id is required');
|
|
86
|
+
}
|
|
87
|
+
if (client_id == null) {
|
|
88
|
+
return user_id;
|
|
89
|
+
}
|
|
90
|
+
return `${user_id}/${client_id}`;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=checkpointing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpointing.js","sourceRoot":"","sources":["../../src/util/checkpointing.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAU,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAUpF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAqC;;;QAC/E,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAExE,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC;QAC1E,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,WAAW,EAAE,gEAAgE,CAAC,CAAC;QAClH,CAAC;QAED,MAAM,iBAAiB,kCAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,CAAC,QAAA,CAAC;QAEvE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE;YACjH,MAAM,eAAe,GAAG,MAAM,iBAAiB,CAAC,4BAA4B,CAAC;gBAC3E,OAAO,EAAE,YAAY;gBACrB,KAAK,EAAE,EAAE,GAAG,EAAE,iBAAiB,EAAE;aAClC,CAAC,CAAC;YACH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,eAAe,EAAE,MAAM,CAAC,eAAe,CAAC;YACxC,eAAe,EAAE,iBAAiB;SACnC,CAAC;;;;;;;;;CACH;AAED,MAAM,UAAU,gBAAgB,CAAC,OAA2B,EAAE,SAA6B;IACzF,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -5,6 +5,7 @@ export * from './Mutex.js';
|
|
|
5
5
|
export * from './protocol-types.js';
|
|
6
6
|
export * from './secs.js';
|
|
7
7
|
export * from './utils.js';
|
|
8
|
+
export * from './checkpointing.js';
|
|
8
9
|
export * from './config.js';
|
|
9
10
|
export * from './config/compound-config-collector.js';
|
|
10
11
|
export * from './config/types.js';
|
package/dist/util/util-index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from './Mutex.js';
|
|
|
5
5
|
export * from './protocol-types.js';
|
|
6
6
|
export * from './secs.js';
|
|
7
7
|
export * from './utils.js';
|
|
8
|
+
export * from './checkpointing.js';
|
|
8
9
|
export * from './config.js';
|
|
9
10
|
export * from './config/compound-config-collector.js';
|
|
10
11
|
export * from './config/types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util-index.js","sourceRoot":"","sources":["../../src/util/util-index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"util-index.js","sourceRoot":"","sources":["../../src/util/util-index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AAEnC,cAAc,aAAa,CAAC;AAC5B,cAAc,uCAAuC,CAAC;AACtD,cAAc,mBAAmB,CAAC;AAElC,cAAc,yCAAyC,CAAC;AACxD,cAAc,qDAAqD,CAAC;AACpE,cAAc,uDAAuD,CAAC;AACtE,cAAc,yDAAyD,CAAC;AAExE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,uCAAuC,CAAC;AACtD,cAAc,4CAA4C,CAAC"}
|
package/dist/util/utils.d.ts
CHANGED
|
@@ -24,7 +24,6 @@ export declare function hasToastedValues(row: sync_rules.ToastableSqliteRow): bo
|
|
|
24
24
|
* If we don't store data, we assume we always have a complete row.
|
|
25
25
|
*/
|
|
26
26
|
export declare function isCompleteRow(storeData: boolean, row: sync_rules.ToastableSqliteRow): row is sync_rules.SqliteRow;
|
|
27
|
-
export declare function checkpointUserId(user_id: string | undefined, client_id: string | undefined): string;
|
|
28
27
|
/**
|
|
29
28
|
* Reduce a bucket to the final state as stored on the client.
|
|
30
29
|
*
|
package/dist/util/utils.js
CHANGED
|
@@ -117,15 +117,6 @@ export function isCompleteRow(storeData, row) {
|
|
|
117
117
|
}
|
|
118
118
|
return !hasToastedValues(row);
|
|
119
119
|
}
|
|
120
|
-
export function checkpointUserId(user_id, client_id) {
|
|
121
|
-
if (user_id == null) {
|
|
122
|
-
throw new Error('user_id is required');
|
|
123
|
-
}
|
|
124
|
-
if (client_id == null) {
|
|
125
|
-
return user_id;
|
|
126
|
-
}
|
|
127
|
-
return `${user_id}/${client_id}`;
|
|
128
|
-
}
|
|
129
120
|
/**
|
|
130
121
|
* Reduce a bucket to the final state as stored on the client.
|
|
131
122
|
*
|
package/dist/util/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAM7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAI1E,MAAM,CAAC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,EAAU,EAAE,IAAY;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,6EAA6E;IAC7E,6CAA6C;IAC7C,IAAI,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,EAAE,KAAK,OAAO,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAqB,EAAE,OAAoB;IACvE,mBAAmB;IACnB,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAElD,KAAK,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,QAAQ;YACR,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACjE,UAAU;gBACV,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,cAAc,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC;QAC5C,cAAc,EAAE,CAAC,GAAG,QAAQ,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAiB,EAAE,CAAyB;IAC7E,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,YAAY;YACrB,QAAQ,EAAE,CAAC,CAAC,eAAe;SAC5B,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,YAAY;YAC/B,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,eAAe,CAAC;SACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAoC,EACpC,OAAmC;IAEnC,IAAI,MAAM,GAAwB,EAAE,CAAC;IACrC,KAAK,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,KAAoC,EACpC,OAAmC;IAEnC,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACxB,gDAAgD;QAChD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,WAAW,GAAG,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1D,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAyB;IACtD,+EAA+E;IAC/E,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAkC;IACjE,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,SAAkB,EAAE,GAAkC;IAClF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,gDAAgD;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAM7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAI1E,MAAM,CAAC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,EAAU,EAAE,IAAY;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,6EAA6E;IAC7E,6CAA6C;IAC7C,IAAI,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,EAAE,KAAK,OAAO,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAqB,EAAE,OAAoB;IACvE,mBAAmB;IACnB,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAElD,KAAK,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,QAAQ;YACR,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACjE,UAAU;gBACV,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,cAAc,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC;QAC5C,cAAc,EAAE,CAAC,GAAG,QAAQ,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAiB,EAAE,CAAyB;IAC7E,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,YAAY;YACrB,QAAQ,EAAE,CAAC,CAAC,eAAe;SAC5B,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,YAAY;YAC/B,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,eAAe,CAAC;SACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAoC,EACpC,OAAmC;IAEnC,IAAI,MAAM,GAAwB,EAAE,CAAC;IACrC,KAAK,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,KAAoC,EACpC,OAAmC;IAEnC,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACxB,gDAAgD;QAChD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,WAAW,GAAG,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1D,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAyB;IACtD,+EAA+E;IAC/E,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAkC;IACjE,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,SAAkB,EAAE,GAAkC;IAClF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,gDAAgD;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,UAAwB;IACnD,IAAI,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,EAAE,CAAC,EAAE,IAAI,KAAK,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAkB,CAAC,CAAC;YAC3E,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAkB,CAAC,CAAC;YAC3E,CAAC;YACD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,QAAkB,CAAC,CAAC;QACrE,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC;YAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,aAAa,GAAG,EAAE,CAAC,QAAkB,CAAC;QACxC,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;YAC3B,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,QAAkB,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAI,UAAU,GAAiB;QAC7B,wDAAwD;QACxD,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE;QACpD,GAAG,IAAI;KACR,CAAC;IAEF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,KAAiB;IAC/B,OAAO,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiD;IAC/E,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QACxB,+CAA+C;QAC/C,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;YACvC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
package/src/api/RouteAPI.ts
CHANGED
|
@@ -54,6 +54,14 @@ export interface RouteAPI {
|
|
|
54
54
|
*/
|
|
55
55
|
getReplicationHead(): Promise<string>;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Get the current LSN or equivalent replication HEAD position identifier.
|
|
59
|
+
*
|
|
60
|
+
* The position is provided to the callback. After the callback returns,
|
|
61
|
+
* the replication head or a greater one will be streamed on the replication stream.
|
|
62
|
+
*/
|
|
63
|
+
createReplicationHead<T>(callback: ReplicationHeadCallback<T>): Promise<T>;
|
|
64
|
+
|
|
57
65
|
/**
|
|
58
66
|
* @returns The schema for tables inside the connected database. This is typically
|
|
59
67
|
* used to validate sync rules.
|
|
@@ -76,3 +84,5 @@ export interface RouteAPI {
|
|
|
76
84
|
*/
|
|
77
85
|
getParseSyncRulesOptions(): ParseSyncRulesOptions;
|
|
78
86
|
}
|
|
87
|
+
|
|
88
|
+
export type ReplicationHeadCallback<T> = (head: string) => Promise<T>;
|
|
@@ -25,7 +25,7 @@ export const writeCheckpoint = routeDefinition({
|
|
|
25
25
|
// Since we don't use LSNs anymore, the only way to get that is to wait.
|
|
26
26
|
const start = Date.now();
|
|
27
27
|
|
|
28
|
-
const head = await apiHandler.
|
|
28
|
+
const head = await apiHandler.createReplicationHead(async (head) => head);
|
|
29
29
|
|
|
30
30
|
const timeout = 50_000;
|
|
31
31
|
|
|
@@ -56,25 +56,14 @@ export const writeCheckpoint2 = routeDefinition({
|
|
|
56
56
|
|
|
57
57
|
const apiHandler = service_context.routerEngine!.getAPI();
|
|
58
58
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
storageEngine: { activeBucketStorage }
|
|
65
|
-
} = service_context;
|
|
66
|
-
|
|
67
|
-
const activeSyncRules = await activeBucketStorage.getActiveSyncRulesContent();
|
|
68
|
-
if (!activeSyncRules) {
|
|
69
|
-
throw new framework.errors.ValidationError(`Cannot create Write Checkpoint since no sync rules are active.`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
using syncBucketStorage = activeBucketStorage.getInstance(activeSyncRules);
|
|
73
|
-
const writeCheckpoint = await syncBucketStorage.createManagedWriteCheckpoint({
|
|
74
|
-
user_id: full_user_id,
|
|
75
|
-
heads: { '1': currentCheckpoint }
|
|
59
|
+
const { replicationHead, writeCheckpoint } = await util.createWriteCheckpoint({
|
|
60
|
+
userId: user_id,
|
|
61
|
+
clientId: payload.params.client_id,
|
|
62
|
+
api: apiHandler,
|
|
63
|
+
storage: service_context.storageEngine.activeBucketStorage
|
|
76
64
|
});
|
|
77
|
-
|
|
65
|
+
|
|
66
|
+
logger.info(`Write checkpoint for ${user_id}/${payload.params.client_id}: ${writeCheckpoint} | ${replicationHead}`);
|
|
78
67
|
|
|
79
68
|
return {
|
|
80
69
|
write_checkpoint: String(writeCheckpoint)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
2
|
+
import { RouteAPI } from '../api/RouteAPI.js';
|
|
3
|
+
import { BucketStorageFactory } from '../storage/BucketStorage.js';
|
|
4
|
+
|
|
5
|
+
export interface CreateWriteCheckpointOptions {
|
|
6
|
+
userId: string | undefined;
|
|
7
|
+
clientId: string | undefined;
|
|
8
|
+
api: RouteAPI;
|
|
9
|
+
storage: BucketStorageFactory;
|
|
10
|
+
}
|
|
11
|
+
export async function createWriteCheckpoint(options: CreateWriteCheckpointOptions) {
|
|
12
|
+
const full_user_id = checkpointUserId(options.userId, options.clientId);
|
|
13
|
+
|
|
14
|
+
const activeSyncRules = await options.storage.getActiveSyncRulesContent();
|
|
15
|
+
if (!activeSyncRules) {
|
|
16
|
+
throw new ServiceError(ErrorCode.PSYNC_S2302, `Cannot create Write Checkpoint since no sync rules are active.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
using syncBucketStorage = options.storage.getInstance(activeSyncRules);
|
|
20
|
+
|
|
21
|
+
const { writeCheckpoint, currentCheckpoint } = await options.api.createReplicationHead(async (currentCheckpoint) => {
|
|
22
|
+
const writeCheckpoint = await syncBucketStorage.createManagedWriteCheckpoint({
|
|
23
|
+
user_id: full_user_id,
|
|
24
|
+
heads: { '1': currentCheckpoint }
|
|
25
|
+
});
|
|
26
|
+
return { writeCheckpoint, currentCheckpoint };
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
writeCheckpoint: String(writeCheckpoint),
|
|
31
|
+
replicationHead: currentCheckpoint
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function checkpointUserId(user_id: string | undefined, client_id: string | undefined) {
|
|
36
|
+
if (user_id == null) {
|
|
37
|
+
throw new Error('user_id is required');
|
|
38
|
+
}
|
|
39
|
+
if (client_id == null) {
|
|
40
|
+
return user_id;
|
|
41
|
+
}
|
|
42
|
+
return `${user_id}/${client_id}`;
|
|
43
|
+
}
|
package/src/util/util-index.ts
CHANGED
package/src/util/utils.ts
CHANGED
|
@@ -145,16 +145,6 @@ export function isCompleteRow(storeData: boolean, row: sync_rules.ToastableSqlit
|
|
|
145
145
|
return !hasToastedValues(row);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
export function checkpointUserId(user_id: string | undefined, client_id: string | undefined) {
|
|
149
|
-
if (user_id == null) {
|
|
150
|
-
throw new Error('user_id is required');
|
|
151
|
-
}
|
|
152
|
-
if (client_id == null) {
|
|
153
|
-
return user_id;
|
|
154
|
-
}
|
|
155
|
-
return `${user_id}/${client_id}`;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
148
|
/**
|
|
159
149
|
* Reduce a bucket to the final state as stored on the client.
|
|
160
150
|
*
|