@powersync/common 0.0.0-dev-20250423120133 → 0.0.0-dev-20250520135616
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.mjs +3 -3
- package/lib/client/AbstractPowerSyncDatabase.d.ts +1 -0
- package/lib/client/AbstractPowerSyncDatabase.js +4 -4
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +6 -0
- package/lib/client/sync/bucket/CrudEntry.d.ts +13 -1
- package/lib/client/sync/bucket/CrudEntry.js +16 -2
- package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +2 -1
- package/lib/client/sync/bucket/SqliteBucketStorage.js +18 -3
- package/lib/client/sync/stream/AbstractRemote.d.ts +29 -0
- package/lib/client/sync/stream/AbstractRemote.js +63 -10
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +1 -0
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +47 -2
- package/lib/client/sync/stream/streaming-sync-types.d.ts +1 -1
- package/lib/db/crud/SyncProgress.d.ts +72 -0
- package/lib/db/crud/SyncProgress.js +60 -0
- package/lib/db/crud/SyncStatus.d.ts +20 -0
- package/lib/db/crud/SyncStatus.js +14 -0
- package/lib/db/schema/Schema.d.ts +4 -0
- package/lib/db/schema/Schema.js +1 -10
- package/lib/db/schema/Table.d.ts +34 -8
- package/lib/db/schema/Table.js +48 -9
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SyncProgress } from './SyncProgress.js';
|
|
1
2
|
export class SyncStatus {
|
|
2
3
|
options;
|
|
3
4
|
constructor(options) {
|
|
@@ -67,6 +68,19 @@ export class SyncStatus {
|
|
|
67
68
|
get priorityStatusEntries() {
|
|
68
69
|
return (this.options.priorityStatusEntries ?? []).slice().sort(SyncStatus.comparePriorities);
|
|
69
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* A realtime progress report on how many operations have been downloaded and
|
|
73
|
+
* how many are necessary in total to complete the next sync iteration.
|
|
74
|
+
*
|
|
75
|
+
* This field is only set when {@link SyncDataFlowStatus#downloading} is also true.
|
|
76
|
+
*/
|
|
77
|
+
get downloadProgress() {
|
|
78
|
+
const internalProgress = this.options.dataFlow?.downloadProgress;
|
|
79
|
+
if (internalProgress == null) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return new SyncProgress(internalProgress);
|
|
83
|
+
}
|
|
70
84
|
/**
|
|
71
85
|
* Reports the sync status (a pair of {@link SyncStatus#hasSynced} and {@link SyncStatus#lastSyncedAt} fields)
|
|
72
86
|
* for a specific bucket priority level.
|
|
@@ -18,6 +18,10 @@ export declare class Schema<S extends SchemaType = SchemaType> {
|
|
|
18
18
|
view_name: string;
|
|
19
19
|
local_only: boolean;
|
|
20
20
|
insert_only: boolean;
|
|
21
|
+
include_old: any;
|
|
22
|
+
include_old_only_when_changed: boolean;
|
|
23
|
+
include_metadata: boolean;
|
|
24
|
+
ignore_empty_update: boolean;
|
|
21
25
|
columns: {
|
|
22
26
|
name: string;
|
|
23
27
|
type: import("./Column.js").ColumnType | undefined;
|
package/lib/db/schema/Schema.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Table } from './Table.js';
|
|
2
1
|
/**
|
|
3
2
|
* A schema is a collection of tables. It is used to define the structure of a database.
|
|
4
3
|
*/
|
|
@@ -41,15 +40,7 @@ export class Schema {
|
|
|
41
40
|
}
|
|
42
41
|
convertToClassicTables(props) {
|
|
43
42
|
return Object.entries(props).map(([name, table]) => {
|
|
44
|
-
|
|
45
|
-
name,
|
|
46
|
-
columns: table.columns,
|
|
47
|
-
indexes: table.indexes,
|
|
48
|
-
localOnly: table.localOnly,
|
|
49
|
-
insertOnly: table.insertOnly,
|
|
50
|
-
viewName: table.viewNameOverride || name
|
|
51
|
-
});
|
|
52
|
-
return convertedTable;
|
|
43
|
+
return table.copyWithName(name);
|
|
53
44
|
});
|
|
54
45
|
}
|
|
55
46
|
}
|
package/lib/db/schema/Table.d.ts
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
import { Column, ColumnsType, ColumnType, ExtractColumnValueType } from './Column.js';
|
|
2
2
|
import { Index } from './Index.js';
|
|
3
3
|
import { TableV2 } from './TableV2.js';
|
|
4
|
-
|
|
4
|
+
interface SharedTableOptions {
|
|
5
|
+
localOnly?: boolean;
|
|
6
|
+
insertOnly?: boolean;
|
|
7
|
+
viewName?: string;
|
|
8
|
+
trackPrevious?: boolean | TrackPreviousOptions;
|
|
9
|
+
trackMetadata?: boolean;
|
|
10
|
+
ignoreEmptyUpdates?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Whether to include previous column values when PowerSync tracks local changes.
|
|
13
|
+
*
|
|
14
|
+
* Including old values may be helpful for some backend connector implementations, which is
|
|
15
|
+
* why it can be enabled on per-table or per-columm basis.
|
|
16
|
+
*/
|
|
17
|
+
export interface TrackPreviousOptions {
|
|
18
|
+
/** When defined, a list of column names for which old values should be tracked. */
|
|
19
|
+
columns?: string[];
|
|
20
|
+
/** When enabled, only include values that have actually been changed by an update. */
|
|
21
|
+
onlyWhenChanged?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface TableOptions extends SharedTableOptions {
|
|
5
24
|
/**
|
|
6
25
|
* The synced table name, matching sync rules
|
|
7
26
|
*/
|
|
8
27
|
name: string;
|
|
9
28
|
columns: Column[];
|
|
10
29
|
indexes?: Index[];
|
|
11
|
-
localOnly?: boolean;
|
|
12
|
-
insertOnly?: boolean;
|
|
13
|
-
viewName?: string;
|
|
14
30
|
}
|
|
15
31
|
export type RowType<T extends TableV2<any>> = {
|
|
16
32
|
[K in keyof T['columnMap']]: ExtractColumnValueType<T['columnMap'][K]>;
|
|
@@ -18,16 +34,16 @@ export type RowType<T extends TableV2<any>> = {
|
|
|
18
34
|
id: string;
|
|
19
35
|
};
|
|
20
36
|
export type IndexShorthand = Record<string, string[]>;
|
|
21
|
-
export interface TableV2Options {
|
|
37
|
+
export interface TableV2Options extends SharedTableOptions {
|
|
22
38
|
indexes?: IndexShorthand;
|
|
23
|
-
localOnly?: boolean;
|
|
24
|
-
insertOnly?: boolean;
|
|
25
|
-
viewName?: string;
|
|
26
39
|
}
|
|
27
40
|
export declare const DEFAULT_TABLE_OPTIONS: {
|
|
28
41
|
indexes: never[];
|
|
29
42
|
insertOnly: boolean;
|
|
30
43
|
localOnly: boolean;
|
|
44
|
+
trackPrevious: boolean;
|
|
45
|
+
trackMetadata: boolean;
|
|
46
|
+
ignoreEmptyUpdates: boolean;
|
|
31
47
|
};
|
|
32
48
|
export declare const InvalidSQLCharacters: RegExp;
|
|
33
49
|
export declare class Table<Columns extends ColumnsType = ColumnsType> {
|
|
@@ -96,9 +112,11 @@ export declare class Table<Columns extends ColumnsType = ColumnsType> {
|
|
|
96
112
|
*```
|
|
97
113
|
*/
|
|
98
114
|
constructor(options: TableOptions);
|
|
115
|
+
copyWithName(name: string): Table;
|
|
99
116
|
private isTableV1;
|
|
100
117
|
private initTableV1;
|
|
101
118
|
private initTableV2;
|
|
119
|
+
private applyDefaultOptions;
|
|
102
120
|
get name(): string;
|
|
103
121
|
get viewNameOverride(): string | undefined;
|
|
104
122
|
get viewName(): string;
|
|
@@ -107,6 +125,9 @@ export declare class Table<Columns extends ColumnsType = ColumnsType> {
|
|
|
107
125
|
get indexes(): Index[];
|
|
108
126
|
get localOnly(): boolean;
|
|
109
127
|
get insertOnly(): boolean;
|
|
128
|
+
get trackPrevious(): boolean | TrackPreviousOptions;
|
|
129
|
+
get trackMetadata(): boolean;
|
|
130
|
+
get ignoreEmptyUpdates(): boolean;
|
|
110
131
|
get internalName(): string;
|
|
111
132
|
get validName(): boolean;
|
|
112
133
|
validate(): void;
|
|
@@ -115,6 +136,10 @@ export declare class Table<Columns extends ColumnsType = ColumnsType> {
|
|
|
115
136
|
view_name: string;
|
|
116
137
|
local_only: boolean;
|
|
117
138
|
insert_only: boolean;
|
|
139
|
+
include_old: any;
|
|
140
|
+
include_old_only_when_changed: boolean;
|
|
141
|
+
include_metadata: boolean;
|
|
142
|
+
ignore_empty_update: boolean;
|
|
118
143
|
columns: {
|
|
119
144
|
name: string;
|
|
120
145
|
type: ColumnType | undefined;
|
|
@@ -129,3 +154,4 @@ export declare class Table<Columns extends ColumnsType = ColumnsType> {
|
|
|
129
154
|
}[];
|
|
130
155
|
};
|
|
131
156
|
}
|
|
157
|
+
export {};
|
package/lib/db/schema/Table.js
CHANGED
|
@@ -4,7 +4,10 @@ import { IndexedColumn } from './IndexedColumn.js';
|
|
|
4
4
|
export const DEFAULT_TABLE_OPTIONS = {
|
|
5
5
|
indexes: [],
|
|
6
6
|
insertOnly: false,
|
|
7
|
-
localOnly: false
|
|
7
|
+
localOnly: false,
|
|
8
|
+
trackPrevious: false,
|
|
9
|
+
trackMetadata: false,
|
|
10
|
+
ignoreEmptyUpdates: false
|
|
8
11
|
};
|
|
9
12
|
export const InvalidSQLCharacters = /["'%,.#\s[\]]/;
|
|
10
13
|
export class Table {
|
|
@@ -41,16 +44,21 @@ export class Table {
|
|
|
41
44
|
this.initTableV2(optionsOrColumns, v2Options);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
47
|
+
copyWithName(name) {
|
|
48
|
+
return new Table({
|
|
49
|
+
...this.options,
|
|
50
|
+
name
|
|
51
|
+
});
|
|
52
|
+
}
|
|
44
53
|
isTableV1(arg) {
|
|
45
54
|
return 'columns' in arg && Array.isArray(arg.columns);
|
|
46
55
|
}
|
|
47
56
|
initTableV1(options) {
|
|
48
57
|
this.options = {
|
|
49
58
|
...options,
|
|
50
|
-
indexes: options.indexes || []
|
|
51
|
-
insertOnly: options.insertOnly ?? DEFAULT_TABLE_OPTIONS.insertOnly,
|
|
52
|
-
localOnly: options.localOnly ?? DEFAULT_TABLE_OPTIONS.localOnly
|
|
59
|
+
indexes: options.indexes || []
|
|
53
60
|
};
|
|
61
|
+
this.applyDefaultOptions();
|
|
54
62
|
}
|
|
55
63
|
initTableV2(columns, options) {
|
|
56
64
|
const convertedColumns = Object.entries(columns).map(([name, columnInfo]) => new Column({ name, type: columnInfo.type }));
|
|
@@ -65,12 +73,23 @@ export class Table {
|
|
|
65
73
|
name: '',
|
|
66
74
|
columns: convertedColumns,
|
|
67
75
|
indexes: convertedIndexes,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
viewName: options?.viewName,
|
|
77
|
+
insertOnly: options?.insertOnly,
|
|
78
|
+
localOnly: options?.localOnly,
|
|
79
|
+
trackPrevious: options?.trackPrevious,
|
|
80
|
+
trackMetadata: options?.trackMetadata,
|
|
81
|
+
ignoreEmptyUpdates: options?.ignoreEmptyUpdates
|
|
71
82
|
};
|
|
83
|
+
this.applyDefaultOptions();
|
|
72
84
|
this._mappedColumns = columns;
|
|
73
85
|
}
|
|
86
|
+
applyDefaultOptions() {
|
|
87
|
+
this.options.insertOnly ??= DEFAULT_TABLE_OPTIONS.insertOnly;
|
|
88
|
+
this.options.localOnly ??= DEFAULT_TABLE_OPTIONS.localOnly;
|
|
89
|
+
this.options.trackPrevious ??= DEFAULT_TABLE_OPTIONS.trackPrevious;
|
|
90
|
+
this.options.trackMetadata ??= DEFAULT_TABLE_OPTIONS.trackMetadata;
|
|
91
|
+
this.options.ignoreEmptyUpdates ??= DEFAULT_TABLE_OPTIONS.ignoreEmptyUpdates;
|
|
92
|
+
}
|
|
74
93
|
get name() {
|
|
75
94
|
return this.options.name;
|
|
76
95
|
}
|
|
@@ -94,10 +113,19 @@ export class Table {
|
|
|
94
113
|
return this.options.indexes ?? [];
|
|
95
114
|
}
|
|
96
115
|
get localOnly() {
|
|
97
|
-
return this.options.localOnly
|
|
116
|
+
return this.options.localOnly;
|
|
98
117
|
}
|
|
99
118
|
get insertOnly() {
|
|
100
|
-
return this.options.insertOnly
|
|
119
|
+
return this.options.insertOnly;
|
|
120
|
+
}
|
|
121
|
+
get trackPrevious() {
|
|
122
|
+
return this.options.trackPrevious;
|
|
123
|
+
}
|
|
124
|
+
get trackMetadata() {
|
|
125
|
+
return this.options.trackMetadata;
|
|
126
|
+
}
|
|
127
|
+
get ignoreEmptyUpdates() {
|
|
128
|
+
return this.options.ignoreEmptyUpdates;
|
|
101
129
|
}
|
|
102
130
|
get internalName() {
|
|
103
131
|
if (this.options.localOnly) {
|
|
@@ -124,6 +152,12 @@ export class Table {
|
|
|
124
152
|
if (this.columns.length > MAX_AMOUNT_OF_COLUMNS) {
|
|
125
153
|
throw new Error(`Table has too many columns. The maximum number of columns is ${MAX_AMOUNT_OF_COLUMNS}.`);
|
|
126
154
|
}
|
|
155
|
+
if (this.trackMetadata && this.localOnly) {
|
|
156
|
+
throw new Error(`Can't include metadata for local-only tables.`);
|
|
157
|
+
}
|
|
158
|
+
if (this.trackPrevious != false && this.localOnly) {
|
|
159
|
+
throw new Error(`Can't include old values for local-only tables.`);
|
|
160
|
+
}
|
|
127
161
|
const columnNames = new Set();
|
|
128
162
|
columnNames.add('id');
|
|
129
163
|
for (const column of this.columns) {
|
|
@@ -156,11 +190,16 @@ export class Table {
|
|
|
156
190
|
}
|
|
157
191
|
}
|
|
158
192
|
toJSON() {
|
|
193
|
+
const trackPrevious = this.trackPrevious;
|
|
159
194
|
return {
|
|
160
195
|
name: this.name,
|
|
161
196
|
view_name: this.viewName,
|
|
162
197
|
local_only: this.localOnly,
|
|
163
198
|
insert_only: this.insertOnly,
|
|
199
|
+
include_old: trackPrevious && (trackPrevious.columns ?? true),
|
|
200
|
+
include_old_only_when_changed: typeof trackPrevious == 'object' && trackPrevious.onlyWhenChanged == true,
|
|
201
|
+
include_metadata: this.trackMetadata,
|
|
202
|
+
ignore_empty_update: this.ignoreEmptyUpdates,
|
|
164
203
|
columns: this.columns.map((c) => c.toJSON()),
|
|
165
204
|
indexes: this.indexes.map((e) => e.toJSON(this))
|
|
166
205
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from './client/sync/stream/AbstractRemote.js';
|
|
|
18
18
|
export * from './client/sync/stream/AbstractStreamingSyncImplementation.js';
|
|
19
19
|
export * from './client/sync/stream/streaming-sync-types.js';
|
|
20
20
|
export { MAX_OP_ID } from './client/constants.js';
|
|
21
|
+
export { ProgressWithOperations, SyncProgress } from './db/crud/SyncProgress.js';
|
|
21
22
|
export * from './db/crud/SyncStatus.js';
|
|
22
23
|
export * from './db/crud/UploadQueueStatus.js';
|
|
23
24
|
export * from './db/schema/Schema.js';
|
package/lib/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from './client/sync/stream/AbstractRemote.js';
|
|
|
18
18
|
export * from './client/sync/stream/AbstractStreamingSyncImplementation.js';
|
|
19
19
|
export * from './client/sync/stream/streaming-sync-types.js';
|
|
20
20
|
export { MAX_OP_ID } from './client/constants.js';
|
|
21
|
+
export { SyncProgress } from './db/crud/SyncProgress.js';
|
|
21
22
|
export * from './db/crud/SyncStatus.js';
|
|
22
23
|
export * from './db/crud/UploadQueueStatus.js';
|
|
23
24
|
export * from './db/schema/Schema.js';
|