@powersync/common 1.33.2 → 1.35.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.
Files changed (42) hide show
  1. package/dist/bundle.cjs +5 -5
  2. package/dist/bundle.mjs +3 -3
  3. package/lib/client/AbstractPowerSyncDatabase.d.ts +58 -13
  4. package/lib/client/AbstractPowerSyncDatabase.js +107 -50
  5. package/lib/client/ConnectionManager.d.ts +4 -4
  6. package/lib/client/CustomQuery.d.ts +22 -0
  7. package/lib/client/CustomQuery.js +42 -0
  8. package/lib/client/Query.d.ts +97 -0
  9. package/lib/client/Query.js +1 -0
  10. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +2 -2
  11. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +1 -3
  12. package/lib/client/sync/bucket/SqliteBucketStorage.js +15 -17
  13. package/lib/client/sync/stream/AbstractRemote.d.ts +1 -10
  14. package/lib/client/sync/stream/AbstractRemote.js +31 -35
  15. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +13 -8
  16. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +112 -82
  17. package/lib/client/sync/stream/streaming-sync-types.d.ts +4 -0
  18. package/lib/client/watched/GetAllQuery.d.ts +32 -0
  19. package/lib/client/watched/GetAllQuery.js +24 -0
  20. package/lib/client/watched/WatchedQuery.d.ts +98 -0
  21. package/lib/client/watched/WatchedQuery.js +12 -0
  22. package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +67 -0
  23. package/lib/client/watched/processors/AbstractQueryProcessor.js +135 -0
  24. package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +121 -0
  25. package/lib/client/watched/processors/DifferentialQueryProcessor.js +166 -0
  26. package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +33 -0
  27. package/lib/client/watched/processors/OnChangeQueryProcessor.js +76 -0
  28. package/lib/client/watched/processors/comparators.d.ts +30 -0
  29. package/lib/client/watched/processors/comparators.js +34 -0
  30. package/lib/db/schema/RawTable.d.ts +61 -0
  31. package/lib/db/schema/RawTable.js +32 -0
  32. package/lib/db/schema/Schema.d.ts +14 -0
  33. package/lib/db/schema/Schema.js +20 -1
  34. package/lib/index.d.ts +8 -0
  35. package/lib/index.js +8 -0
  36. package/lib/utils/BaseObserver.d.ts +3 -4
  37. package/lib/utils/BaseObserver.js +3 -0
  38. package/lib/utils/MetaBaseObserver.d.ts +29 -0
  39. package/lib/utils/MetaBaseObserver.js +50 -0
  40. package/lib/utils/async.d.ts +0 -1
  41. package/lib/utils/async.js +0 -10
  42. package/package.json +1 -1
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Instructs PowerSync to sync data into a "raw" table.
3
+ *
4
+ * Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
5
+ * using client-side table and column constraints.
6
+ *
7
+ * To collect local writes to raw tables with PowerSync, custom triggers are required. See
8
+ * {@link https://docs.powersync.com/usage/use-case-examples/raw-tables the documentation} for details and an example on
9
+ * using raw tables.
10
+ *
11
+ * Note that raw tables are only supported when using the new `SyncClientImplementation.rust` sync client.
12
+ *
13
+ * @experimental Please note that this feature is experimental at the moment, and not covered by PowerSync semver or
14
+ * stability guarantees.
15
+ */
16
+ export class RawTable {
17
+ /**
18
+ * The name of the table.
19
+ *
20
+ * This does not have to match the actual table name in the schema - {@link put} and {@link delete} are free to use
21
+ * another table. Instead, this name is used by the sync client to recognize that operations on this table (as it
22
+ * appears in the source / backend database) are to be handled specially.
23
+ */
24
+ name;
25
+ put;
26
+ delete;
27
+ constructor(name, type) {
28
+ this.name = name;
29
+ this.put = type.put;
30
+ this.delete = type.delete;
31
+ }
32
+ }
@@ -1,3 +1,4 @@
1
+ import { RawTable, RawTableType } from './RawTable.js';
1
2
  import { RowType, Table } from './Table.js';
2
3
  type SchemaType = Record<string, Table<any>>;
3
4
  export type SchemaTableType<S extends SchemaType> = {
@@ -10,7 +11,19 @@ export declare class Schema<S extends SchemaType = SchemaType> {
10
11
  readonly types: SchemaTableType<S>;
11
12
  readonly props: S;
12
13
  readonly tables: Table[];
14
+ readonly rawTables: RawTable[];
13
15
  constructor(tables: Table[] | S);
16
+ /**
17
+ * Adds raw tables to this schema. Raw tables are identified by their name, but entirely managed by the application
18
+ * developer instead of automatically by PowerSync.
19
+ * Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
20
+ * using client-side table and column constraints.
21
+ * Note that raw tables are only supported when using the new `SyncClientImplementation.rust` sync client.
22
+ *
23
+ * @param tables An object of (table name, raw table definition) entries.
24
+ * @experimental Note that the raw tables API is still experimental and may change in the future.
25
+ */
26
+ withRawTables(tables: Record<string, RawTableType>): void;
14
27
  validate(): void;
15
28
  toJSON(): {
16
29
  tables: {
@@ -35,6 +48,7 @@ export declare class Schema<S extends SchemaType = SchemaType> {
35
48
  }[];
36
49
  }[];
37
50
  }[];
51
+ raw_tables: RawTable[];
38
52
  };
39
53
  private convertToClassicTables;
40
54
  }
@@ -1,3 +1,4 @@
1
+ import { RawTable } from './RawTable.js';
1
2
  /**
2
3
  * A schema is a collection of tables. It is used to define the structure of a database.
3
4
  */
@@ -8,6 +9,7 @@ export class Schema {
8
9
  types;
9
10
  props;
10
11
  tables;
12
+ rawTables;
11
13
  constructor(tables) {
12
14
  if (Array.isArray(tables)) {
13
15
  /*
@@ -26,6 +28,22 @@ export class Schema {
26
28
  this.props = tables;
27
29
  this.tables = this.convertToClassicTables(this.props);
28
30
  }
31
+ this.rawTables = [];
32
+ }
33
+ /**
34
+ * Adds raw tables to this schema. Raw tables are identified by their name, but entirely managed by the application
35
+ * developer instead of automatically by PowerSync.
36
+ * Since raw tables are not backed by JSON, running complex queries on them may be more efficient. Further, they allow
37
+ * using client-side table and column constraints.
38
+ * Note that raw tables are only supported when using the new `SyncClientImplementation.rust` sync client.
39
+ *
40
+ * @param tables An object of (table name, raw table definition) entries.
41
+ * @experimental Note that the raw tables API is still experimental and may change in the future.
42
+ */
43
+ withRawTables(tables) {
44
+ for (const [name, rawTableDefinition] of Object.entries(tables)) {
45
+ this.rawTables.push(new RawTable(name, rawTableDefinition));
46
+ }
29
47
  }
30
48
  validate() {
31
49
  for (const table of this.tables) {
@@ -35,7 +53,8 @@ export class Schema {
35
53
  toJSON() {
36
54
  return {
37
55
  // This is required because "name" field is not present in TableV2
38
- tables: this.tables.map((t) => t.toJSON())
56
+ tables: this.tables.map((t) => t.toJSON()),
57
+ raw_tables: this.rawTables
39
58
  };
40
59
  }
41
60
  convertToClassicTables(props) {
package/lib/index.d.ts CHANGED
@@ -29,8 +29,16 @@ export * from './db/schema/IndexedColumn.js';
29
29
  export * from './db/schema/Schema.js';
30
30
  export * from './db/schema/Table.js';
31
31
  export * from './db/schema/TableV2.js';
32
+ export * from './client/Query.js';
33
+ export * from './client/watched/GetAllQuery.js';
34
+ export * from './client/watched/processors/AbstractQueryProcessor.js';
35
+ export * from './client/watched/processors/comparators.js';
36
+ export * from './client/watched/processors/DifferentialQueryProcessor.js';
37
+ export * from './client/watched/processors/OnChangeQueryProcessor.js';
38
+ export * from './client/watched/WatchedQuery.js';
32
39
  export * from './utils/AbortOperation.js';
33
40
  export * from './utils/BaseObserver.js';
41
+ export * from './utils/ControlledExecutor.js';
34
42
  export * from './utils/DataStream.js';
35
43
  export * from './utils/Logger.js';
36
44
  export * from './utils/parseQuery.js';
package/lib/index.js CHANGED
@@ -29,8 +29,16 @@ export * from './db/schema/IndexedColumn.js';
29
29
  export * from './db/schema/Schema.js';
30
30
  export * from './db/schema/Table.js';
31
31
  export * from './db/schema/TableV2.js';
32
+ export * from './client/Query.js';
33
+ export * from './client/watched/GetAllQuery.js';
34
+ export * from './client/watched/processors/AbstractQueryProcessor.js';
35
+ export * from './client/watched/processors/comparators.js';
36
+ export * from './client/watched/processors/DifferentialQueryProcessor.js';
37
+ export * from './client/watched/processors/OnChangeQueryProcessor.js';
38
+ export * from './client/watched/WatchedQuery.js';
32
39
  export * from './utils/AbortOperation.js';
33
40
  export * from './utils/BaseObserver.js';
41
+ export * from './utils/ControlledExecutor.js';
34
42
  export * from './utils/DataStream.js';
35
43
  export * from './utils/Logger.js';
36
44
  export * from './utils/parseQuery.js';
@@ -1,15 +1,14 @@
1
1
  export interface Disposable {
2
- dispose: () => Promise<void>;
2
+ dispose: () => Promise<void> | void;
3
3
  }
4
+ export type BaseListener = Record<string, ((...event: any) => any) | undefined>;
4
5
  export interface BaseObserverInterface<T extends BaseListener> {
5
6
  registerListener(listener: Partial<T>): () => void;
6
7
  }
7
- export type BaseListener = {
8
- [key: string]: ((...event: any) => any) | undefined;
9
- };
10
8
  export declare class BaseObserver<T extends BaseListener = BaseListener> implements BaseObserverInterface<T> {
11
9
  protected listeners: Set<Partial<T>>;
12
10
  constructor();
11
+ dispose(): void;
13
12
  /**
14
13
  * Register a listener for updates to the PowerSync client.
15
14
  */
@@ -1,6 +1,9 @@
1
1
  export class BaseObserver {
2
2
  listeners = new Set();
3
3
  constructor() { }
4
+ dispose() {
5
+ this.listeners.clear();
6
+ }
4
7
  /**
5
8
  * Register a listener for updates to the PowerSync client.
6
9
  */
@@ -0,0 +1,29 @@
1
+ import { BaseListener, BaseObserver, BaseObserverInterface } from './BaseObserver.js';
2
+ /**
3
+ * Represents the counts of listeners for each event type in a BaseListener.
4
+ */
5
+ export type ListenerCounts<Listener extends BaseListener> = Partial<Record<keyof Listener, number>> & {
6
+ total: number;
7
+ };
8
+ /**
9
+ * Meta listener which reports the counts of listeners for each event type.
10
+ */
11
+ export interface MetaListener<ParentListener extends BaseListener> extends BaseListener {
12
+ listenersChanged?: (counts: ListenerCounts<ParentListener>) => void;
13
+ }
14
+ export interface ListenerMetaManager<Listener extends BaseListener> extends BaseObserverInterface<MetaListener<Listener>> {
15
+ counts: ListenerCounts<Listener>;
16
+ }
17
+ export interface MetaBaseObserverInterface<Listener extends BaseListener> extends BaseObserverInterface<Listener> {
18
+ listenerMeta: ListenerMetaManager<Listener>;
19
+ }
20
+ /**
21
+ * A BaseObserver that tracks the counts of listeners for each event type.
22
+ */
23
+ export declare class MetaBaseObserver<Listener extends BaseListener> extends BaseObserver<Listener> implements MetaBaseObserverInterface<Listener> {
24
+ protected get listenerCounts(): ListenerCounts<Listener>;
25
+ get listenerMeta(): ListenerMetaManager<Listener>;
26
+ protected metaListener: BaseObserver<MetaListener<Listener>>;
27
+ constructor();
28
+ registerListener(listener: Partial<Listener>): () => void;
29
+ }
@@ -0,0 +1,50 @@
1
+ import { BaseObserver } from './BaseObserver.js';
2
+ /**
3
+ * A BaseObserver that tracks the counts of listeners for each event type.
4
+ */
5
+ export class MetaBaseObserver extends BaseObserver {
6
+ get listenerCounts() {
7
+ const counts = {};
8
+ let total = 0;
9
+ for (const listener of this.listeners) {
10
+ for (const key in listener) {
11
+ if (listener[key]) {
12
+ counts[key] = (counts[key] ?? 0) + 1;
13
+ total++;
14
+ }
15
+ }
16
+ }
17
+ return {
18
+ ...counts,
19
+ total
20
+ };
21
+ }
22
+ get listenerMeta() {
23
+ return {
24
+ counts: this.listenerCounts,
25
+ // Allows registering a meta listener that will be notified of changes in listener counts
26
+ registerListener: (listener) => {
27
+ return this.metaListener.registerListener(listener);
28
+ }
29
+ };
30
+ }
31
+ metaListener;
32
+ constructor() {
33
+ super();
34
+ this.metaListener = new BaseObserver();
35
+ }
36
+ registerListener(listener) {
37
+ const dispose = super.registerListener(listener);
38
+ const updatedCount = this.listenerCounts;
39
+ this.metaListener.iterateListeners((l) => {
40
+ l.listenersChanged?.(updatedCount);
41
+ });
42
+ return () => {
43
+ dispose();
44
+ const updatedCount = this.listenerCounts;
45
+ this.metaListener.iterateListeners((l) => {
46
+ l.listenersChanged?.(updatedCount);
47
+ });
48
+ };
49
+ }
50
+ }
@@ -12,4 +12,3 @@ export declare function throttleTrailing(func: () => void, wait: number): () =>
12
12
  * Roughly equivalent to lodash/throttle with {leading: true, trailing: true}
13
13
  */
14
14
  export declare function throttleLeadingTrailing(func: () => void, wait: number): () => void;
15
- export declare function onAbortPromise(signal: AbortSignal): Promise<void>;
@@ -43,13 +43,3 @@ export function throttleLeadingTrailing(func, wait) {
43
43
  }
44
44
  };
45
45
  }
46
- export function onAbortPromise(signal) {
47
- return new Promise((resolve) => {
48
- if (signal.aborted) {
49
- resolve();
50
- }
51
- else {
52
- signal.onabort = () => resolve();
53
- }
54
- });
55
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "1.33.2",
3
+ "version": "1.35.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"