@powersync/common 1.28.0 → 1.30.0

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.
@@ -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
- insertOnly: options?.insertOnly ?? DEFAULT_TABLE_OPTIONS.insertOnly,
69
- localOnly: options?.localOnly ?? DEFAULT_TABLE_OPTIONS.localOnly,
70
- viewName: options?.viewName
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 ?? false;
116
+ return this.options.localOnly;
98
117
  }
99
118
  get insertOnly() {
100
- return this.options.insertOnly ?? false;
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "1.28.0",
3
+ "version": "1.30.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"