@powersync/common 1.41.0 → 1.41.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/dist/bundle.cjs +10809 -22
- package/dist/bundle.cjs.map +1 -0
- package/dist/bundle.mjs +10730 -22
- package/dist/bundle.mjs.map +1 -0
- package/dist/bundle.node.cjs +10809 -0
- package/dist/bundle.node.cjs.map +1 -0
- package/dist/bundle.node.mjs +10730 -0
- package/dist/bundle.node.mjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/lib/client/AbstractPowerSyncDatabase.js +1 -0
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js +1 -0
- package/lib/client/AbstractPowerSyncOpenFactory.js.map +1 -0
- package/lib/client/ConnectionManager.js +1 -0
- package/lib/client/ConnectionManager.js.map +1 -0
- package/lib/client/CustomQuery.js +1 -0
- package/lib/client/CustomQuery.js.map +1 -0
- package/lib/client/Query.js +1 -0
- package/lib/client/Query.js.map +1 -0
- package/lib/client/SQLOpenFactory.js +1 -0
- package/lib/client/SQLOpenFactory.js.map +1 -0
- package/lib/client/compilableQueryWatch.js +1 -0
- package/lib/client/compilableQueryWatch.js.map +1 -0
- package/lib/client/connection/PowerSyncBackendConnector.js +1 -0
- package/lib/client/connection/PowerSyncBackendConnector.js.map +1 -0
- package/lib/client/connection/PowerSyncCredentials.js +1 -0
- package/lib/client/connection/PowerSyncCredentials.js.map +1 -0
- package/lib/client/constants.js +1 -0
- package/lib/client/constants.js.map +1 -0
- package/lib/client/runOnSchemaChange.js +1 -0
- package/lib/client/runOnSchemaChange.js.map +1 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js +1 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -0
- package/lib/client/sync/bucket/CrudBatch.js +1 -0
- package/lib/client/sync/bucket/CrudBatch.js.map +1 -0
- package/lib/client/sync/bucket/CrudEntry.js +1 -0
- package/lib/client/sync/bucket/CrudEntry.js.map +1 -0
- package/lib/client/sync/bucket/CrudTransaction.js +1 -0
- package/lib/client/sync/bucket/CrudTransaction.js.map +1 -0
- package/lib/client/sync/bucket/OpType.js +1 -0
- package/lib/client/sync/bucket/OpType.js.map +1 -0
- package/lib/client/sync/bucket/OplogEntry.js +1 -0
- package/lib/client/sync/bucket/OplogEntry.js.map +1 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js +1 -0
- package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -0
- package/lib/client/sync/bucket/SyncDataBatch.js +1 -0
- package/lib/client/sync/bucket/SyncDataBatch.js.map +1 -0
- package/lib/client/sync/bucket/SyncDataBucket.js +1 -0
- package/lib/client/sync/bucket/SyncDataBucket.js.map +1 -0
- package/lib/client/sync/stream/AbstractRemote.d.ts +5 -0
- package/lib/client/sync/stream/AbstractRemote.js +9 -2
- package/lib/client/sync/stream/AbstractRemote.js.map +1 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +1 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -0
- package/lib/client/sync/stream/WebsocketClientTransport.js +1 -0
- package/lib/client/sync/stream/WebsocketClientTransport.js.map +1 -0
- package/lib/client/sync/stream/core-instruction.js +1 -0
- package/lib/client/sync/stream/core-instruction.js.map +1 -0
- package/lib/client/sync/stream/streaming-sync-types.js +1 -0
- package/lib/client/sync/stream/streaming-sync-types.js.map +1 -0
- package/lib/client/sync/sync-streams.js +1 -0
- package/lib/client/sync/sync-streams.js.map +1 -0
- package/lib/client/triggers/TriggerManager.js +1 -0
- package/lib/client/triggers/TriggerManager.js.map +1 -0
- package/lib/client/triggers/TriggerManagerImpl.js +1 -0
- package/lib/client/triggers/TriggerManagerImpl.js.map +1 -0
- package/lib/client/triggers/sanitizeSQL.js +1 -0
- package/lib/client/triggers/sanitizeSQL.js.map +1 -0
- package/lib/client/watched/GetAllQuery.js +1 -0
- package/lib/client/watched/GetAllQuery.js.map +1 -0
- package/lib/client/watched/WatchedQuery.js +1 -0
- package/lib/client/watched/WatchedQuery.js.map +1 -0
- package/lib/client/watched/processors/AbstractQueryProcessor.js +1 -0
- package/lib/client/watched/processors/AbstractQueryProcessor.js.map +1 -0
- package/lib/client/watched/processors/DifferentialQueryProcessor.js +1 -0
- package/lib/client/watched/processors/DifferentialQueryProcessor.js.map +1 -0
- package/lib/client/watched/processors/OnChangeQueryProcessor.js +1 -0
- package/lib/client/watched/processors/OnChangeQueryProcessor.js.map +1 -0
- package/lib/client/watched/processors/comparators.js +1 -0
- package/lib/client/watched/processors/comparators.js.map +1 -0
- package/lib/db/DBAdapter.js +1 -0
- package/lib/db/DBAdapter.js.map +1 -0
- package/lib/db/crud/SyncProgress.js +1 -0
- package/lib/db/crud/SyncProgress.js.map +1 -0
- package/lib/db/crud/SyncStatus.js +1 -0
- package/lib/db/crud/SyncStatus.js.map +1 -0
- package/lib/db/crud/UploadQueueStatus.js +1 -0
- package/lib/db/crud/UploadQueueStatus.js.map +1 -0
- package/lib/db/schema/Column.js +1 -0
- package/lib/db/schema/Column.js.map +1 -0
- package/lib/db/schema/Index.js +1 -0
- package/lib/db/schema/Index.js.map +1 -0
- package/lib/db/schema/IndexedColumn.js +1 -0
- package/lib/db/schema/IndexedColumn.js.map +1 -0
- package/lib/db/schema/RawTable.js +1 -0
- package/lib/db/schema/RawTable.js.map +1 -0
- package/lib/db/schema/Schema.js +1 -0
- package/lib/db/schema/Schema.js.map +1 -0
- package/lib/db/schema/Table.js +1 -0
- package/lib/db/schema/Table.js.map +1 -0
- package/lib/db/schema/TableV2.js +1 -0
- package/lib/db/schema/TableV2.js.map +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -0
- package/lib/types/types.js +1 -0
- package/lib/types/types.js.map +1 -0
- package/lib/utils/AbortOperation.js +1 -0
- package/lib/utils/AbortOperation.js.map +1 -0
- package/lib/utils/BaseObserver.js +1 -0
- package/lib/utils/BaseObserver.js.map +1 -0
- package/lib/utils/ControlledExecutor.js +1 -0
- package/lib/utils/ControlledExecutor.js.map +1 -0
- package/lib/utils/DataStream.js +1 -0
- package/lib/utils/DataStream.js.map +1 -0
- package/lib/utils/Logger.js +1 -0
- package/lib/utils/Logger.js.map +1 -0
- package/lib/utils/MetaBaseObserver.js +1 -0
- package/lib/utils/MetaBaseObserver.js.map +1 -0
- package/lib/utils/async.js +1 -0
- package/lib/utils/async.js.map +1 -0
- package/lib/utils/mutex.js +1 -0
- package/lib/utils/mutex.js.map +1 -0
- package/lib/utils/parseQuery.js +1 -0
- package/lib/utils/parseQuery.js.map +1 -0
- package/package.json +23 -15
- package/src/client/AbstractPowerSyncDatabase.ts +1343 -0
- package/src/client/AbstractPowerSyncOpenFactory.ts +39 -0
- package/src/client/ConnectionManager.ts +402 -0
- package/src/client/CustomQuery.ts +56 -0
- package/src/client/Query.ts +106 -0
- package/src/client/SQLOpenFactory.ts +55 -0
- package/src/client/compilableQueryWatch.ts +55 -0
- package/src/client/connection/PowerSyncBackendConnector.ts +25 -0
- package/src/client/connection/PowerSyncCredentials.ts +5 -0
- package/src/client/constants.ts +1 -0
- package/src/client/runOnSchemaChange.ts +31 -0
- package/src/client/sync/bucket/BucketStorageAdapter.ts +118 -0
- package/src/client/sync/bucket/CrudBatch.ts +21 -0
- package/src/client/sync/bucket/CrudEntry.ts +172 -0
- package/src/client/sync/bucket/CrudTransaction.ts +21 -0
- package/src/client/sync/bucket/OpType.ts +23 -0
- package/src/client/sync/bucket/OplogEntry.ts +50 -0
- package/src/client/sync/bucket/SqliteBucketStorage.ts +395 -0
- package/src/client/sync/bucket/SyncDataBatch.ts +11 -0
- package/src/client/sync/bucket/SyncDataBucket.ts +49 -0
- package/src/client/sync/stream/AbstractRemote.ts +626 -0
- package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +1258 -0
- package/src/client/sync/stream/WebsocketClientTransport.ts +80 -0
- package/src/client/sync/stream/core-instruction.ts +99 -0
- package/src/client/sync/stream/streaming-sync-types.ts +205 -0
- package/src/client/sync/sync-streams.ts +107 -0
- package/src/client/triggers/TriggerManager.ts +384 -0
- package/src/client/triggers/TriggerManagerImpl.ts +314 -0
- package/src/client/triggers/sanitizeSQL.ts +66 -0
- package/src/client/watched/GetAllQuery.ts +46 -0
- package/src/client/watched/WatchedQuery.ts +121 -0
- package/src/client/watched/processors/AbstractQueryProcessor.ts +226 -0
- package/src/client/watched/processors/DifferentialQueryProcessor.ts +305 -0
- package/src/client/watched/processors/OnChangeQueryProcessor.ts +122 -0
- package/src/client/watched/processors/comparators.ts +57 -0
- package/src/db/DBAdapter.ts +134 -0
- package/src/db/crud/SyncProgress.ts +100 -0
- package/src/db/crud/SyncStatus.ts +308 -0
- package/src/db/crud/UploadQueueStatus.ts +20 -0
- package/src/db/schema/Column.ts +60 -0
- package/src/db/schema/Index.ts +39 -0
- package/src/db/schema/IndexedColumn.ts +42 -0
- package/src/db/schema/RawTable.ts +67 -0
- package/src/db/schema/Schema.ts +76 -0
- package/src/db/schema/Table.ts +359 -0
- package/src/db/schema/TableV2.ts +9 -0
- package/src/index.ts +52 -0
- package/src/types/types.ts +9 -0
- package/src/utils/AbortOperation.ts +17 -0
- package/src/utils/BaseObserver.ts +41 -0
- package/src/utils/ControlledExecutor.ts +72 -0
- package/src/utils/DataStream.ts +211 -0
- package/src/utils/Logger.ts +47 -0
- package/src/utils/MetaBaseObserver.ts +81 -0
- package/src/utils/async.ts +61 -0
- package/src/utils/mutex.ts +34 -0
- package/src/utils/parseQuery.ts +25 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CompilableQuery } from './../types/types.js';
|
|
2
|
+
import { AbstractPowerSyncDatabase, SQLWatchOptions } from './AbstractPowerSyncDatabase.js';
|
|
3
|
+
import { runOnSchemaChange } from './runOnSchemaChange.js';
|
|
4
|
+
|
|
5
|
+
export interface CompilableQueryWatchHandler<T> {
|
|
6
|
+
onResult: (results: T[]) => void;
|
|
7
|
+
onError?: (error: Error) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function compilableQueryWatch<T>(
|
|
11
|
+
db: AbstractPowerSyncDatabase,
|
|
12
|
+
query: CompilableQuery<T>,
|
|
13
|
+
handler: CompilableQueryWatchHandler<T>,
|
|
14
|
+
options?: SQLWatchOptions
|
|
15
|
+
): void {
|
|
16
|
+
const { onResult, onError = (e: Error) => {} } = handler ?? {};
|
|
17
|
+
if (!onResult) {
|
|
18
|
+
throw new Error('onResult is required');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const watchQuery = async (abortSignal: AbortSignal) => {
|
|
22
|
+
try {
|
|
23
|
+
const toSql = query.compile();
|
|
24
|
+
const resolvedTables = await db.resolveTables(toSql.sql, toSql.parameters as [], options);
|
|
25
|
+
|
|
26
|
+
// Fetch initial data
|
|
27
|
+
const result = await query.execute();
|
|
28
|
+
onResult(result);
|
|
29
|
+
|
|
30
|
+
db.onChangeWithCallback(
|
|
31
|
+
{
|
|
32
|
+
onChange: async () => {
|
|
33
|
+
try {
|
|
34
|
+
const result = await query.execute();
|
|
35
|
+
onResult(result);
|
|
36
|
+
} catch (error: any) {
|
|
37
|
+
onError(error);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
onError
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
...(options ?? {}),
|
|
44
|
+
tables: resolvedTables,
|
|
45
|
+
// Override the abort signal since we intercept it
|
|
46
|
+
signal: abortSignal
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
} catch (error: any) {
|
|
50
|
+
onError(error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
runOnSchemaChange(watchQuery, db, options);
|
|
55
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PowerSyncCredentials } from './PowerSyncCredentials.js';
|
|
2
|
+
import type { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
|
|
3
|
+
|
|
4
|
+
export interface PowerSyncBackendConnector {
|
|
5
|
+
/** Allows the PowerSync client to retrieve an authentication token from your backend
|
|
6
|
+
* which is used to authenticate against the PowerSync service.
|
|
7
|
+
*
|
|
8
|
+
* This should always fetch a fresh set of credentials - don't use cached
|
|
9
|
+
* values.
|
|
10
|
+
*
|
|
11
|
+
* Return null if the user is not signed in. Throw an error if credentials
|
|
12
|
+
* cannot be fetched due to a network error or other temporary error.
|
|
13
|
+
*
|
|
14
|
+
* This token is kept for the duration of a sync connection.
|
|
15
|
+
*/
|
|
16
|
+
fetchCredentials: () => Promise<PowerSyncCredentials | null>;
|
|
17
|
+
|
|
18
|
+
/** Upload local changes to the app backend.
|
|
19
|
+
*
|
|
20
|
+
* Use {@link AbstractPowerSyncDatabase.getCrudBatch} to get a batch of changes to upload.
|
|
21
|
+
*
|
|
22
|
+
* Any thrown errors will result in a retry after the configured wait period (default: 5 seconds).
|
|
23
|
+
*/
|
|
24
|
+
uploadData: (database: AbstractPowerSyncDatabase) => Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MAX_OP_ID = '9223372036854775807';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AbstractPowerSyncDatabase, SQLWatchOptions } from './AbstractPowerSyncDatabase.js';
|
|
2
|
+
|
|
3
|
+
export function runOnSchemaChange(
|
|
4
|
+
callback: (signal: AbortSignal) => void,
|
|
5
|
+
db: AbstractPowerSyncDatabase,
|
|
6
|
+
options?: SQLWatchOptions
|
|
7
|
+
): void {
|
|
8
|
+
const triggerWatchedQuery = () => {
|
|
9
|
+
const abortController = new AbortController();
|
|
10
|
+
let disposeSchemaListener: (() => void) | null = null;
|
|
11
|
+
const stopWatching = () => {
|
|
12
|
+
abortController.abort('Abort triggered');
|
|
13
|
+
disposeSchemaListener?.();
|
|
14
|
+
disposeSchemaListener = null;
|
|
15
|
+
// Stop listening to upstream abort for this watch
|
|
16
|
+
options?.signal?.removeEventListener('abort', stopWatching);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
options?.signal?.addEventListener('abort', stopWatching);
|
|
20
|
+
disposeSchemaListener = db.registerListener({
|
|
21
|
+
schemaChanged: async () => {
|
|
22
|
+
stopWatching();
|
|
23
|
+
// Re trigger the watched query (recursively), setTimeout ensures that we don't modify the list of listeners while iterating through them
|
|
24
|
+
setTimeout(() => triggerWatchedQuery(), 0);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
callback(abortController.signal);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
triggerWatchedQuery();
|
|
31
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { BaseListener, BaseObserverInterface, Disposable } from '../../../utils/BaseObserver.js';
|
|
2
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
3
|
+
import { CrudEntry, OpId } from './CrudEntry.js';
|
|
4
|
+
import { SyncDataBatch } from './SyncDataBatch.js';
|
|
5
|
+
|
|
6
|
+
export interface BucketDescription {
|
|
7
|
+
name: string;
|
|
8
|
+
priority: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Checkpoint {
|
|
12
|
+
last_op_id: OpId;
|
|
13
|
+
buckets: BucketChecksum[];
|
|
14
|
+
write_checkpoint?: string;
|
|
15
|
+
streams?: any[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BucketState {
|
|
19
|
+
bucket: string;
|
|
20
|
+
op_id: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ChecksumCache {
|
|
24
|
+
checksums: Map<string, { checksum: BucketChecksum; last_op_id: OpId }>;
|
|
25
|
+
lastOpId: OpId;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SyncLocalDatabaseResult {
|
|
29
|
+
ready: boolean;
|
|
30
|
+
checkpointValid: boolean;
|
|
31
|
+
checkpointFailures?: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type SavedProgress = {
|
|
35
|
+
atLast: number;
|
|
36
|
+
sinceLast: number;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type BucketOperationProgress = Record<string, SavedProgress>;
|
|
40
|
+
|
|
41
|
+
export interface BucketChecksum {
|
|
42
|
+
bucket: string;
|
|
43
|
+
priority?: number;
|
|
44
|
+
/**
|
|
45
|
+
* 32-bit unsigned hash.
|
|
46
|
+
*/
|
|
47
|
+
checksum: number;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Count of operations - informational only.
|
|
51
|
+
*/
|
|
52
|
+
count?: number;
|
|
53
|
+
/**
|
|
54
|
+
* The JavaScript client does not use this field, which is why it's defined to be `any`. We rely on the structure of
|
|
55
|
+
* this interface to pass custom `BucketChecksum`s to the Rust client in unit tests, which so all fields need to be
|
|
56
|
+
* present.
|
|
57
|
+
*/
|
|
58
|
+
subscriptions?: any;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export enum PSInternalTable {
|
|
62
|
+
DATA = 'ps_data',
|
|
63
|
+
CRUD = 'ps_crud',
|
|
64
|
+
BUCKETS = 'ps_buckets',
|
|
65
|
+
OPLOG = 'ps_oplog',
|
|
66
|
+
UNTYPED = 'ps_untyped'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export enum PowerSyncControlCommand {
|
|
70
|
+
PROCESS_TEXT_LINE = 'line_text',
|
|
71
|
+
PROCESS_BSON_LINE = 'line_binary',
|
|
72
|
+
STOP = 'stop',
|
|
73
|
+
START = 'start',
|
|
74
|
+
NOTIFY_TOKEN_REFRESHED = 'refreshed_token',
|
|
75
|
+
NOTIFY_CRUD_UPLOAD_COMPLETED = 'completed_upload',
|
|
76
|
+
UPDATE_SUBSCRIPTIONS = 'update_subscriptions'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface BucketStorageListener extends BaseListener {
|
|
80
|
+
crudUpdate: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface BucketStorageAdapter extends BaseObserverInterface<BucketStorageListener>, Disposable {
|
|
84
|
+
init(): Promise<void>;
|
|
85
|
+
saveSyncData(batch: SyncDataBatch, fixedKeyFormat?: boolean): Promise<void>;
|
|
86
|
+
removeBuckets(buckets: string[]): Promise<void>;
|
|
87
|
+
setTargetCheckpoint(checkpoint: Checkpoint): Promise<void>;
|
|
88
|
+
|
|
89
|
+
startSession(): void;
|
|
90
|
+
|
|
91
|
+
getBucketStates(): Promise<BucketState[]>;
|
|
92
|
+
getBucketOperationProgress(): Promise<BucketOperationProgress>;
|
|
93
|
+
hasMigratedSubkeys(): Promise<boolean>;
|
|
94
|
+
migrateToFixedSubkeys(): Promise<void>;
|
|
95
|
+
|
|
96
|
+
syncLocalDatabase(
|
|
97
|
+
checkpoint: Checkpoint,
|
|
98
|
+
priority?: number
|
|
99
|
+
): Promise<{ checkpointValid: boolean; ready: boolean; failures?: any[] }>;
|
|
100
|
+
|
|
101
|
+
nextCrudItem(): Promise<CrudEntry | undefined>;
|
|
102
|
+
hasCrud(): Promise<boolean>;
|
|
103
|
+
getCrudBatch(limit?: number): Promise<CrudBatch | null>;
|
|
104
|
+
|
|
105
|
+
hasCompletedSync(): Promise<boolean>;
|
|
106
|
+
updateLocalTarget(cb: () => Promise<string>): Promise<boolean>;
|
|
107
|
+
getMaxOpId(): string;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get an unique client id.
|
|
111
|
+
*/
|
|
112
|
+
getClientId(): Promise<string>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Invokes the `powersync_control` function for the sync client.
|
|
116
|
+
*/
|
|
117
|
+
control(op: PowerSyncControlCommand, payload: string | Uint8Array | null): Promise<string>;
|
|
118
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CrudEntry } from './CrudEntry.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A batch of client-side changes.
|
|
5
|
+
*/
|
|
6
|
+
export class CrudBatch {
|
|
7
|
+
constructor(
|
|
8
|
+
/**
|
|
9
|
+
* List of client-side changes.
|
|
10
|
+
*/
|
|
11
|
+
public crud: CrudEntry[],
|
|
12
|
+
/**
|
|
13
|
+
* true if there are more changes in the local queue.
|
|
14
|
+
*/
|
|
15
|
+
public haveMore: boolean,
|
|
16
|
+
/**
|
|
17
|
+
* Call to remove the changes from the local queue, once successfully uploaded.
|
|
18
|
+
*/
|
|
19
|
+
public complete: (writeCheckpoint?: string) => Promise<void>
|
|
20
|
+
) {}
|
|
21
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 64-bit unsigned integer stored as a string in base-10.
|
|
3
|
+
*
|
|
4
|
+
* Not sortable as a string.
|
|
5
|
+
*/
|
|
6
|
+
export type OpId = string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Type of local change.
|
|
10
|
+
*/
|
|
11
|
+
export enum UpdateType {
|
|
12
|
+
/** Insert or replace existing row. All non-null columns are included in the data. Generated by INSERT statements. */
|
|
13
|
+
PUT = 'PUT',
|
|
14
|
+
/** Update existing row. Contains the id, and value of each changed column. Generated by UPDATE statements. */
|
|
15
|
+
PATCH = 'PATCH',
|
|
16
|
+
/** Delete existing row. Contains the id. Generated by DELETE statements. */
|
|
17
|
+
DELETE = 'DELETE'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type CrudEntryJSON = {
|
|
21
|
+
id: string;
|
|
22
|
+
data: string;
|
|
23
|
+
tx_id?: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type CrudEntryDataJSON = {
|
|
27
|
+
data: Record<string, any>;
|
|
28
|
+
old?: Record<string, any>;
|
|
29
|
+
op: UpdateType;
|
|
30
|
+
type: string;
|
|
31
|
+
id: string;
|
|
32
|
+
metadata?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The output JSON seems to be a third type of JSON, not the same as the input JSON.
|
|
37
|
+
*/
|
|
38
|
+
type CrudEntryOutputJSON = {
|
|
39
|
+
op_id: number;
|
|
40
|
+
op: UpdateType;
|
|
41
|
+
type: string;
|
|
42
|
+
id: string;
|
|
43
|
+
tx_id?: number;
|
|
44
|
+
data?: Record<string, any>;
|
|
45
|
+
old?: Record<string, any>;
|
|
46
|
+
metadata?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A single client-side change.
|
|
51
|
+
*/
|
|
52
|
+
export class CrudEntry {
|
|
53
|
+
/**
|
|
54
|
+
* Auto-incrementing client-side id.
|
|
55
|
+
*/
|
|
56
|
+
clientId: number;
|
|
57
|
+
/**
|
|
58
|
+
* ID of the changed row.
|
|
59
|
+
*/
|
|
60
|
+
id: string;
|
|
61
|
+
/**
|
|
62
|
+
* Type of change.
|
|
63
|
+
*/
|
|
64
|
+
op: UpdateType;
|
|
65
|
+
/**
|
|
66
|
+
* Data associated with the change.
|
|
67
|
+
*/
|
|
68
|
+
opData?: Record<string, any>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* For tables where the `trackPreviousValues` option has been enabled, this tracks previous values for
|
|
72
|
+
* `UPDATE` and `DELETE` statements.
|
|
73
|
+
*/
|
|
74
|
+
previousValues?: Record<string, any>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Table that contained the change.
|
|
78
|
+
*/
|
|
79
|
+
table: string;
|
|
80
|
+
/**
|
|
81
|
+
* Auto-incrementing transaction id. This is the same for all operations within the same transaction.
|
|
82
|
+
*/
|
|
83
|
+
transactionId?: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Client-side metadata attached with this write.
|
|
87
|
+
*
|
|
88
|
+
* This field is only available when the `trackMetadata` option was set to `true` when creating a table
|
|
89
|
+
* and the insert or update statement set the `_metadata` column.
|
|
90
|
+
*/
|
|
91
|
+
metadata?: string;
|
|
92
|
+
|
|
93
|
+
static fromRow(dbRow: CrudEntryJSON) {
|
|
94
|
+
const data: CrudEntryDataJSON = JSON.parse(dbRow.data);
|
|
95
|
+
return new CrudEntry(
|
|
96
|
+
parseInt(dbRow.id),
|
|
97
|
+
data.op,
|
|
98
|
+
data.type,
|
|
99
|
+
data.id,
|
|
100
|
+
dbRow.tx_id,
|
|
101
|
+
data.data,
|
|
102
|
+
data.old,
|
|
103
|
+
data.metadata
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
constructor(
|
|
108
|
+
clientId: number,
|
|
109
|
+
op: UpdateType,
|
|
110
|
+
table: string,
|
|
111
|
+
id: string,
|
|
112
|
+
transactionId?: number,
|
|
113
|
+
opData?: Record<string, any>,
|
|
114
|
+
previousValues?: Record<string, any>,
|
|
115
|
+
metadata?: string
|
|
116
|
+
) {
|
|
117
|
+
this.clientId = clientId;
|
|
118
|
+
this.id = id;
|
|
119
|
+
this.op = op;
|
|
120
|
+
this.opData = opData;
|
|
121
|
+
this.table = table;
|
|
122
|
+
this.transactionId = transactionId;
|
|
123
|
+
this.previousValues = previousValues;
|
|
124
|
+
this.metadata = metadata;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Converts the change to JSON format.
|
|
129
|
+
*/
|
|
130
|
+
toJSON(): CrudEntryOutputJSON {
|
|
131
|
+
return {
|
|
132
|
+
op_id: this.clientId,
|
|
133
|
+
op: this.op,
|
|
134
|
+
type: this.table,
|
|
135
|
+
id: this.id,
|
|
136
|
+
tx_id: this.transactionId,
|
|
137
|
+
data: this.opData,
|
|
138
|
+
old: this.previousValues,
|
|
139
|
+
metadata: this.metadata
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
equals(entry: CrudEntry) {
|
|
144
|
+
return JSON.stringify(this.toComparisonArray()) == JSON.stringify(entry.toComparisonArray());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The hash code for this object.
|
|
149
|
+
* @deprecated This should not be necessary in the JS SDK.
|
|
150
|
+
* Use the @see CrudEntry#equals method instead.
|
|
151
|
+
* TODO remove in the next major release.
|
|
152
|
+
*/
|
|
153
|
+
hashCode() {
|
|
154
|
+
return JSON.stringify(this.toComparisonArray());
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Generates an array for use in deep comparison operations
|
|
159
|
+
*/
|
|
160
|
+
toComparisonArray() {
|
|
161
|
+
return [
|
|
162
|
+
this.transactionId,
|
|
163
|
+
this.clientId,
|
|
164
|
+
this.op,
|
|
165
|
+
this.table,
|
|
166
|
+
this.id,
|
|
167
|
+
this.opData,
|
|
168
|
+
this.previousValues,
|
|
169
|
+
this.metadata
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CrudBatch } from './CrudBatch.js';
|
|
2
|
+
import { CrudEntry } from './CrudEntry.js';
|
|
3
|
+
|
|
4
|
+
export class CrudTransaction extends CrudBatch {
|
|
5
|
+
constructor(
|
|
6
|
+
/**
|
|
7
|
+
* List of client-side changes.
|
|
8
|
+
*/
|
|
9
|
+
public crud: CrudEntry[],
|
|
10
|
+
/**
|
|
11
|
+
* Call to remove the changes from the local queue, once successfully uploaded.
|
|
12
|
+
*/
|
|
13
|
+
public complete: (checkpoint?: string) => Promise<void>,
|
|
14
|
+
/**
|
|
15
|
+
* If null, this contains a list of changes recorded without an explicit transaction associated.
|
|
16
|
+
*/
|
|
17
|
+
public transactionId?: number
|
|
18
|
+
) {
|
|
19
|
+
super(crud, false, complete);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export enum OpTypeEnum {
|
|
2
|
+
CLEAR = 1,
|
|
3
|
+
MOVE = 2,
|
|
4
|
+
PUT = 3,
|
|
5
|
+
REMOVE = 4
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type OpTypeJSON = string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Used internally for sync buckets.
|
|
12
|
+
*/
|
|
13
|
+
export class OpType {
|
|
14
|
+
static fromJSON(jsonValue: OpTypeJSON) {
|
|
15
|
+
return new OpType(OpTypeEnum[jsonValue]);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
constructor(public value: OpTypeEnum) {}
|
|
19
|
+
|
|
20
|
+
toJSON() {
|
|
21
|
+
return Object.entries(OpTypeEnum).find(([, value]) => value === this.value)![0];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { OpId } from './CrudEntry.js';
|
|
2
|
+
import { OpType, OpTypeJSON } from './OpType.js';
|
|
3
|
+
|
|
4
|
+
export interface OplogEntryJSON {
|
|
5
|
+
checksum: number;
|
|
6
|
+
data?: string;
|
|
7
|
+
object_id?: string;
|
|
8
|
+
object_type?: string;
|
|
9
|
+
op_id: string;
|
|
10
|
+
op: OpTypeJSON;
|
|
11
|
+
subkey?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class OplogEntry {
|
|
15
|
+
static fromRow(row: OplogEntryJSON) {
|
|
16
|
+
return new OplogEntry(
|
|
17
|
+
row.op_id,
|
|
18
|
+
OpType.fromJSON(row.op),
|
|
19
|
+
row.checksum,
|
|
20
|
+
row.subkey,
|
|
21
|
+
row.object_type,
|
|
22
|
+
row.object_id,
|
|
23
|
+
row.data
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
public op_id: OpId,
|
|
29
|
+
public op: OpType,
|
|
30
|
+
public checksum: number,
|
|
31
|
+
public subkey?: string,
|
|
32
|
+
public object_type?: string,
|
|
33
|
+
public object_id?: string,
|
|
34
|
+
public data?: string
|
|
35
|
+
) {}
|
|
36
|
+
|
|
37
|
+
toJSON(fixedKeyEncoding = false): OplogEntryJSON {
|
|
38
|
+
return {
|
|
39
|
+
op_id: this.op_id,
|
|
40
|
+
op: this.op.toJSON(),
|
|
41
|
+
object_type: this.object_type,
|
|
42
|
+
object_id: this.object_id,
|
|
43
|
+
checksum: this.checksum,
|
|
44
|
+
data: this.data,
|
|
45
|
+
// Older versions of the JS SDK used to always JSON.stringify here. That has always been wrong,
|
|
46
|
+
// but we need to migrate gradually to not break existing databases.
|
|
47
|
+
subkey: fixedKeyEncoding ? this.subkey : JSON.stringify(this.subkey)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|