@powersync/common 0.0.0-dev-20250714151300 → 0.0.0-dev-20250715104704

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 (35) hide show
  1. package/dist/bundle.cjs +5 -5
  2. package/dist/bundle.mjs +3 -3
  3. package/lib/client/AbstractPowerSyncDatabase.d.ts +5 -56
  4. package/lib/client/AbstractPowerSyncDatabase.js +32 -96
  5. package/lib/client/ConnectionManager.d.ts +4 -4
  6. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +2 -2
  7. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +9 -5
  8. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +21 -18
  9. package/lib/db/schema/RawTable.d.ts +57 -0
  10. package/lib/db/schema/RawTable.js +28 -0
  11. package/lib/db/schema/Schema.d.ts +14 -0
  12. package/lib/db/schema/Schema.js +20 -1
  13. package/lib/index.d.ts +1 -7
  14. package/lib/index.js +1 -7
  15. package/lib/utils/BaseObserver.d.ts +4 -3
  16. package/lib/utils/BaseObserver.js +0 -3
  17. package/package.json +1 -1
  18. package/lib/client/CustomQuery.d.ts +0 -25
  19. package/lib/client/CustomQuery.js +0 -41
  20. package/lib/client/Query.d.ts +0 -79
  21. package/lib/client/Query.js +0 -1
  22. package/lib/client/watched/GetAllQuery.d.ts +0 -32
  23. package/lib/client/watched/GetAllQuery.js +0 -24
  24. package/lib/client/watched/WatchedQuery.d.ts +0 -93
  25. package/lib/client/watched/WatchedQuery.js +0 -12
  26. package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +0 -67
  27. package/lib/client/watched/processors/AbstractQueryProcessor.js +0 -136
  28. package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +0 -129
  29. package/lib/client/watched/processors/DifferentialQueryProcessor.js +0 -175
  30. package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +0 -27
  31. package/lib/client/watched/processors/OnChangeQueryProcessor.js +0 -74
  32. package/lib/client/watched/processors/comparators.d.ts +0 -24
  33. package/lib/client/watched/processors/comparators.js +0 -33
  34. package/lib/utils/MetaBaseObserver.d.ts +0 -29
  35. package/lib/utils/MetaBaseObserver.js +0 -50
@@ -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,15 +29,9 @@ 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';
39
32
  export * from './utils/AbortOperation.js';
40
33
  export * from './utils/BaseObserver.js';
34
+ export * from './utils/ControlledExecutor.js';
41
35
  export * from './utils/DataStream.js';
42
36
  export * from './utils/Logger.js';
43
37
  export * from './utils/parseQuery.js';
package/lib/index.js CHANGED
@@ -29,15 +29,9 @@ 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';
39
32
  export * from './utils/AbortOperation.js';
40
33
  export * from './utils/BaseObserver.js';
34
+ export * from './utils/ControlledExecutor.js';
41
35
  export * from './utils/DataStream.js';
42
36
  export * from './utils/Logger.js';
43
37
  export * from './utils/parseQuery.js';
@@ -1,14 +1,15 @@
1
1
  export interface Disposable {
2
- dispose: () => Promise<void> | void;
2
+ dispose: () => Promise<void>;
3
3
  }
4
- export type BaseListener = Record<string, ((...event: any) => any) | undefined>;
5
4
  export interface BaseObserverInterface<T extends BaseListener> {
6
5
  registerListener(listener: Partial<T>): () => void;
7
6
  }
7
+ export type BaseListener = {
8
+ [key: string]: ((...event: any) => any) | undefined;
9
+ };
8
10
  export declare class BaseObserver<T extends BaseListener = BaseListener> implements BaseObserverInterface<T> {
9
11
  protected listeners: Set<Partial<T>>;
10
12
  constructor();
11
- dispose(): void;
12
13
  /**
13
14
  * Register a listener for updates to the PowerSync client.
14
15
  */
@@ -1,9 +1,6 @@
1
1
  export class BaseObserver {
2
2
  listeners = new Set();
3
3
  constructor() { }
4
- dispose() {
5
- this.listeners.clear();
6
- }
7
4
  /**
8
5
  * Register a listener for updates to the PowerSync client.
9
6
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "0.0.0-dev-20250714151300",
3
+ "version": "0.0.0-dev-20250715104704",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -1,25 +0,0 @@
1
- import { AbstractPowerSyncDatabase } from './AbstractPowerSyncDatabase.js';
2
- import { Query, StandardWatchedQueryOptions } from './Query.js';
3
- import { DifferentialQueryProcessor, DifferentialWatchedQueryOptions } from './watched/processors/DifferentialQueryProcessor.js';
4
- import { OnChangeQueryProcessor } from './watched/processors/OnChangeQueryProcessor.js';
5
- import { WatchCompatibleQuery, WatchedQueryOptions } from './watched/WatchedQuery.js';
6
- /**
7
- * @internal
8
- */
9
- export interface CustomQueryOptions<RowType> {
10
- db: AbstractPowerSyncDatabase;
11
- query: WatchCompatibleQuery<RowType[]>;
12
- }
13
- /**
14
- * @internal
15
- */
16
- export declare class CustomQuery<RowType> implements Query<RowType> {
17
- protected options: CustomQueryOptions<RowType>;
18
- constructor(options: CustomQueryOptions<RowType>);
19
- protected resolveOptions(options: WatchedQueryOptions): {
20
- reportFetching: boolean | undefined;
21
- throttleMs: number | undefined;
22
- };
23
- watch(watchOptions: StandardWatchedQueryOptions<RowType>): OnChangeQueryProcessor<RowType[]>;
24
- differentialWatch(differentialWatchOptions: DifferentialWatchedQueryOptions<RowType>): DifferentialQueryProcessor<RowType>;
25
- }
@@ -1,41 +0,0 @@
1
- import { FalsyComparator } from './watched/processors/comparators.js';
2
- import { DifferentialQueryProcessor } from './watched/processors/DifferentialQueryProcessor.js';
3
- import { OnChangeQueryProcessor } from './watched/processors/OnChangeQueryProcessor.js';
4
- import { DEFAULT_WATCH_QUERY_OPTIONS } from './watched/WatchedQuery.js';
5
- /**
6
- * @internal
7
- */
8
- export class CustomQuery {
9
- options;
10
- constructor(options) {
11
- this.options = options;
12
- }
13
- resolveOptions(options) {
14
- return {
15
- reportFetching: options?.reportFetching ?? DEFAULT_WATCH_QUERY_OPTIONS.reportFetching,
16
- throttleMs: options?.throttleMs ?? DEFAULT_WATCH_QUERY_OPTIONS.throttleMs
17
- };
18
- }
19
- watch(watchOptions) {
20
- return new OnChangeQueryProcessor({
21
- db: this.options.db,
22
- comparator: watchOptions?.comparator ?? FalsyComparator,
23
- placeholderData: watchOptions?.placeholderData ?? [],
24
- watchOptions: {
25
- ...this.resolveOptions(watchOptions),
26
- query: this.options.query
27
- }
28
- });
29
- }
30
- differentialWatch(differentialWatchOptions) {
31
- return new DifferentialQueryProcessor({
32
- db: this.options.db,
33
- differentiator: differentialWatchOptions?.differentiator,
34
- placeholderData: differentialWatchOptions?.placeholderData ?? [],
35
- watchOptions: {
36
- ...this.resolveOptions(differentialWatchOptions),
37
- query: this.options.query
38
- }
39
- });
40
- }
41
- }
@@ -1,79 +0,0 @@
1
- import { ArrayComparator } from './watched/processors/comparators.js';
2
- import { DifferentialWatchedQuery, DifferentialWatchedQueryOptions } from './watched/processors/DifferentialQueryProcessor.js';
3
- import { ComparisonWatchedQuery } from './watched/processors/OnChangeQueryProcessor.js';
4
- import { WatchedQueryOptions } from './watched/WatchedQuery.js';
5
- /**
6
- * Query parameters for {@link ArrayQueryDefinition#parameters}
7
- */
8
- export type QueryParam = string | number | boolean | null | undefined | bigint | Uint8Array;
9
- /**
10
- * Options for building a query with {@link AbstractPowerSyncDatabase#query}.
11
- * This query will be executed with {@link AbstractPowerSyncDatabase#getAll}.
12
- */
13
- export interface ArrayQueryDefinition<RowType = unknown> {
14
- sql: string;
15
- parameters?: ReadonlyArray<Readonly<QueryParam>>;
16
- /**
17
- * Maps the raw SQLite row to a custom typed object.
18
- * @example
19
- * ```javascript
20
- * mapper: (row) => ({
21
- * ...row,
22
- * created_at: new Date(row.created_at as string),
23
- * })
24
- * ```
25
- */
26
- mapper?: (row: Record<string, unknown>) => RowType;
27
- }
28
- /**
29
- * Options for {@link Query.watch}.
30
- */
31
- export interface StandardWatchedQueryOptions<RowType> extends WatchedQueryOptions {
32
- /**
33
- * Optional comparator which processes the items of an array of rows.
34
- * The comparator compares the result set rows by index using the {@link ArrayComparatorOptions#compareBy} function.
35
- * The comparator reports a changed result set as soon as a row does not match the previous result set.
36
- *
37
- * @example
38
- * ```javascript
39
- * comparator: new ArrayComparator({
40
- * compareBy: (item) => JSON.stringify(item)
41
- * })
42
- * ```
43
- */
44
- comparator?: ArrayComparator<RowType>;
45
- /**
46
- * The initial data state reported while the query is loading for the first time.
47
- * @default []
48
- */
49
- placeholderData?: RowType[];
50
- }
51
- export interface Query<RowType> {
52
- /**
53
- * Creates a {@link WatchedQuery} which watches and emits results of the linked query.
54
- *
55
- * By default the returned watched query will emit changes whenever a change to the underlying SQLite tables is made.
56
- * These changes might not be relevant to the query, but the query will emit a new result set.
57
- *
58
- * A {@link StandardWatchedQueryOptions#comparator} can be provided to limit the data emissions. The watched query will still
59
- * query the underlying DB on underlying table changes, but the result will only be emitted if the comparator detects a change in the results.
60
- *
61
- * The comparator in this method is optimized and returns early as soon as it detects a change. Each data emission will correlate to a change in the result set,
62
- * but note that the result set will not maintain internal object references to the previous result set. If internal object references are needed,
63
- * consider using {@link Query#differentialWatch} instead.
64
- */
65
- watch(options?: StandardWatchedQueryOptions<RowType>): ComparisonWatchedQuery<ReadonlyArray<Readonly<RowType>>>;
66
- /**
67
- * Creates a {@link WatchedQuery} which watches and emits results of the linked query.
68
- *
69
- * This query method watches for changes in the underlying SQLite tables and runs the query on each table change.
70
- * The difference between the current and previous result set is computed.
71
- * The watched query will not emit changes if the result set is identical to the previous result set.
72
- * If the result set is different, the watched query will emit the new result set and provide a detailed diff of the changes.
73
- *
74
- * The deep differentiation allows maintaining result set object references between result emissions.
75
- * The {@link DifferentialWatchedQuery#state} `data` array will contain the previous row references for unchanged rows.
76
- * A detailed diff of the changes can be accessed via {@link DifferentialWatchedQuery#state} `diff`.
77
- */
78
- differentialWatch(options?: DifferentialWatchedQueryOptions<RowType>): DifferentialWatchedQuery<RowType>;
79
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,32 +0,0 @@
1
- import { CompiledQuery } from '../../types/types.js';
2
- import { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
3
- import { WatchCompatibleQuery } from './WatchedQuery.js';
4
- /**
5
- * Options for {@link GetAllQuery}.
6
- */
7
- export type GetAllQueryOptions<RowType = unknown> = {
8
- sql: string;
9
- parameters?: ReadonlyArray<unknown>;
10
- /**
11
- * Optional mapper function to convert raw rows into the desired RowType.
12
- * @example
13
- * ```javascript
14
- * (rawRow) => ({
15
- * id: rawRow.id,
16
- * created_at: new Date(rawRow.created_at),
17
- * })
18
- * ```
19
- */
20
- mapper?: (rawRow: Record<string, unknown>) => RowType;
21
- };
22
- /**
23
- * Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
24
- */
25
- export declare class GetAllQuery<RowType = unknown> implements WatchCompatibleQuery<RowType[]> {
26
- protected options: GetAllQueryOptions<RowType>;
27
- constructor(options: GetAllQueryOptions<RowType>);
28
- compile(): CompiledQuery;
29
- execute(options: {
30
- db: AbstractPowerSyncDatabase;
31
- }): Promise<RowType[]>;
32
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
3
- */
4
- export class GetAllQuery {
5
- options;
6
- constructor(options) {
7
- this.options = options;
8
- }
9
- compile() {
10
- return {
11
- sql: this.options.sql,
12
- parameters: this.options.parameters ?? []
13
- };
14
- }
15
- async execute(options) {
16
- const { db } = options;
17
- const { sql, parameters = [] } = this.compile();
18
- const rawResult = await db.getAll(sql, [...parameters]);
19
- if (this.options.mapper) {
20
- return rawResult.map(this.options.mapper);
21
- }
22
- return rawResult;
23
- }
24
- }
@@ -1,93 +0,0 @@
1
- import { CompiledQuery } from '../../types/types.js';
2
- import { BaseListener } from '../../utils/BaseObserver.js';
3
- import { MetaBaseObserverInterface } from '../../utils/MetaBaseObserver.js';
4
- import { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
5
- /**
6
- * State for {@link WatchedQuery} instances.
7
- */
8
- export interface WatchedQueryState<Data> {
9
- /**
10
- * Indicates the initial loading state (hard loading).
11
- * Loading becomes false once the first set of results from the watched query is available or an error occurs.
12
- */
13
- readonly isLoading: boolean;
14
- /**
15
- * Indicates whether the query is currently fetching data, is true during the initial load
16
- * and any time when the query is re-evaluating (useful for large queries).
17
- */
18
- readonly isFetching: boolean;
19
- /**
20
- * The last error that occurred while executing the query.
21
- */
22
- readonly error: Error | null;
23
- /**
24
- * The last time the query was updated.
25
- */
26
- readonly lastUpdated: Date | null;
27
- /**
28
- * The last data returned by the query.
29
- */
30
- readonly data: Data;
31
- }
32
- /**
33
- * Options provided to the `execute` method of a {@link WatchCompatibleQuery}.
34
- */
35
- export interface WatchExecuteOptions {
36
- sql: string;
37
- parameters: any[];
38
- db: AbstractPowerSyncDatabase;
39
- }
40
- /**
41
- * Similar to {@link CompatibleQuery}, except the `execute` method
42
- * does not enforce an Array result type.
43
- */
44
- export interface WatchCompatibleQuery<ResultType> {
45
- execute(options: WatchExecuteOptions): Promise<ResultType>;
46
- compile(): CompiledQuery;
47
- }
48
- export interface WatchedQueryOptions {
49
- /** The minimum interval between queries. */
50
- throttleMs?: number;
51
- /**
52
- * If true (default) the watched query will update its state to report
53
- * on the fetching state of the query.
54
- * Setting to false reduces the number of state changes if the fetch status
55
- * is not relevant to the consumer.
56
- */
57
- reportFetching?: boolean;
58
- }
59
- export declare enum WatchedQueryListenerEvent {
60
- ON_DATA = "onData",
61
- ON_ERROR = "onError",
62
- ON_STATE_CHANGE = "onStateChange",
63
- CLOSED = "closed"
64
- }
65
- export interface WatchedQueryListener<Data> extends BaseListener {
66
- [WatchedQueryListenerEvent.ON_DATA]?: (data: Data) => void | Promise<void>;
67
- [WatchedQueryListenerEvent.ON_ERROR]?: (error: Error) => void | Promise<void>;
68
- [WatchedQueryListenerEvent.ON_STATE_CHANGE]?: (state: WatchedQueryState<Data>) => void | Promise<void>;
69
- [WatchedQueryListenerEvent.CLOSED]?: () => void | Promise<void>;
70
- }
71
- export declare const DEFAULT_WATCH_THROTTLE_MS = 30;
72
- export declare const DEFAULT_WATCH_QUERY_OPTIONS: WatchedQueryOptions;
73
- export interface WatchedQuery<Data = unknown, Settings extends WatchedQueryOptions = WatchedQueryOptions, Listener extends WatchedQueryListener<Data> = WatchedQueryListener<Data>> extends MetaBaseObserverInterface<Listener> {
74
- /**
75
- * Current state of the watched query.
76
- */
77
- readonly state: WatchedQueryState<Data>;
78
- readonly closed: boolean;
79
- /**
80
- * Subscribe to watched query events.
81
- * @returns A function to unsubscribe from the events.
82
- */
83
- registerListener(listener: Listener): () => void;
84
- /**
85
- * Updates the underlying query options.
86
- * This will trigger a re-evaluation of the query and update the state.
87
- */
88
- updateSettings(options: Settings): Promise<void>;
89
- /**
90
- * Close the watched query and end all subscriptions.
91
- */
92
- close(): Promise<void>;
93
- }
@@ -1,12 +0,0 @@
1
- export var WatchedQueryListenerEvent;
2
- (function (WatchedQueryListenerEvent) {
3
- WatchedQueryListenerEvent["ON_DATA"] = "onData";
4
- WatchedQueryListenerEvent["ON_ERROR"] = "onError";
5
- WatchedQueryListenerEvent["ON_STATE_CHANGE"] = "onStateChange";
6
- WatchedQueryListenerEvent["CLOSED"] = "closed";
7
- })(WatchedQueryListenerEvent || (WatchedQueryListenerEvent = {}));
8
- export const DEFAULT_WATCH_THROTTLE_MS = 30;
9
- export const DEFAULT_WATCH_QUERY_OPTIONS = {
10
- throttleMs: DEFAULT_WATCH_THROTTLE_MS,
11
- reportFetching: true
12
- };
@@ -1,67 +0,0 @@
1
- import { AbstractPowerSyncDatabase } from '../../../client/AbstractPowerSyncDatabase.js';
2
- import { MetaBaseObserver } from '../../../utils/MetaBaseObserver.js';
3
- import { WatchedQuery, WatchedQueryListener, WatchedQueryOptions, WatchedQueryState } from '../WatchedQuery.js';
4
- /**
5
- * @internal
6
- */
7
- export interface AbstractQueryProcessorOptions<Data, Settings extends WatchedQueryOptions = WatchedQueryOptions> {
8
- db: AbstractPowerSyncDatabase;
9
- watchOptions: Settings;
10
- placeholderData: Data;
11
- }
12
- /**
13
- * @internal
14
- */
15
- export interface LinkQueryOptions<Data, Settings extends WatchedQueryOptions = WatchedQueryOptions> {
16
- abortSignal: AbortSignal;
17
- settings: Settings;
18
- }
19
- type MutableDeep<T> = T extends ReadonlyArray<infer U> ? U[] : T;
20
- /**
21
- * @internal Mutable version of {@link WatchedQueryState}.
22
- * This is used internally to allow updates to the state.
23
- */
24
- export type MutableWatchedQueryState<Data> = {
25
- -readonly [P in keyof WatchedQueryState<Data>]: MutableDeep<WatchedQueryState<Data>[P]>;
26
- };
27
- type WatchedQueryProcessorListener<Data> = WatchedQueryListener<Data>;
28
- /**
29
- * Performs underlying watching and yields a stream of results.
30
- * @internal
31
- */
32
- export declare abstract class AbstractQueryProcessor<Data = unknown[], Settings extends WatchedQueryOptions = WatchedQueryOptions> extends MetaBaseObserver<WatchedQueryProcessorListener<Data>> implements WatchedQuery<Data, Settings> {
33
- protected options: AbstractQueryProcessorOptions<Data, Settings>;
34
- readonly state: WatchedQueryState<Data>;
35
- protected abortController: AbortController;
36
- protected initialized: Promise<void>;
37
- protected _closed: boolean;
38
- protected disposeListeners: (() => void) | null;
39
- get closed(): boolean;
40
- constructor(options: AbstractQueryProcessorOptions<Data, Settings>);
41
- protected constructInitialState(): WatchedQueryState<Data>;
42
- protected get reportFetching(): boolean;
43
- /**
44
- * Updates the underlying query.
45
- */
46
- updateSettings(settings: Settings): Promise<void>;
47
- /**
48
- * This method is used to link a query to the subscribers of this listener class.
49
- * This method should perform actual query watching and report results via {@link updateState} method.
50
- */
51
- protected abstract linkQuery(options: LinkQueryOptions<Data>): Promise<void>;
52
- protected updateState(update: Partial<MutableWatchedQueryState<Data>>): Promise<void>;
53
- /**
54
- * Configures base DB listeners and links the query to listeners.
55
- */
56
- protected init(): Promise<void>;
57
- close(): Promise<void>;
58
- /**
59
- * Runs a callback and reports errors to the error listeners.
60
- */
61
- protected runWithReporting<T>(callback: () => Promise<T>): Promise<void>;
62
- /**
63
- * Iterate listeners and reports errors to onError handlers.
64
- */
65
- protected iterateAsyncListenersWithError(callback: (listener: Partial<WatchedQueryProcessorListener<Data>>) => Promise<void> | void): Promise<void>;
66
- }
67
- export {};
@@ -1,136 +0,0 @@
1
- import { MetaBaseObserver } from '../../../utils/MetaBaseObserver.js';
2
- /**
3
- * Performs underlying watching and yields a stream of results.
4
- * @internal
5
- */
6
- export class AbstractQueryProcessor extends MetaBaseObserver {
7
- options;
8
- state;
9
- abortController;
10
- initialized;
11
- _closed;
12
- disposeListeners;
13
- get closed() {
14
- return this._closed;
15
- }
16
- constructor(options) {
17
- super();
18
- this.options = options;
19
- this.abortController = new AbortController();
20
- this._closed = false;
21
- this.state = this.constructInitialState();
22
- this.disposeListeners = null;
23
- this.initialized = this.init();
24
- }
25
- constructInitialState() {
26
- return {
27
- isLoading: true,
28
- isFetching: this.reportFetching, // Only set to true if we will report updates in future
29
- error: null,
30
- lastUpdated: null,
31
- data: this.options.placeholderData
32
- };
33
- }
34
- get reportFetching() {
35
- return this.options.watchOptions.reportFetching ?? true;
36
- }
37
- /**
38
- * Updates the underlying query.
39
- */
40
- async updateSettings(settings) {
41
- await this.initialized;
42
- if (!this.state.isLoading) {
43
- await this.updateState({
44
- isLoading: true,
45
- isFetching: this.reportFetching ? true : false
46
- });
47
- }
48
- this.options.watchOptions = settings;
49
- this.abortController.abort();
50
- this.abortController = new AbortController();
51
- await this.runWithReporting(() => this.linkQuery({
52
- abortSignal: this.abortController.signal,
53
- settings
54
- }));
55
- }
56
- async updateState(update) {
57
- if (typeof update.error !== 'undefined') {
58
- await this.iterateAsyncListenersWithError(async (l) => l.onError?.(update.error));
59
- // An error always stops for the current fetching state
60
- update.isFetching = false;
61
- update.isLoading = false;
62
- }
63
- Object.assign(this.state, { lastUpdated: new Date() }, update);
64
- if (typeof update.data !== 'undefined') {
65
- await this.iterateAsyncListenersWithError(async (l) => l.onData?.(this.state.data));
66
- }
67
- await this.iterateAsyncListenersWithError(async (l) => l.onStateChange?.(this.state));
68
- }
69
- /**
70
- * Configures base DB listeners and links the query to listeners.
71
- */
72
- async init() {
73
- const { db } = this.options;
74
- const disposeCloseListener = db.registerListener({
75
- closing: async () => {
76
- await this.close();
77
- }
78
- });
79
- // Wait for the schema to be set before listening to changes
80
- await db.waitForReady();
81
- const disposeSchemaListener = db.registerListener({
82
- schemaChanged: async () => {
83
- await this.runWithReporting(async () => {
84
- await this.updateSettings(this.options.watchOptions);
85
- });
86
- }
87
- });
88
- this.disposeListeners = () => {
89
- disposeCloseListener();
90
- disposeSchemaListener();
91
- };
92
- // Initial setup
93
- this.runWithReporting(async () => {
94
- await this.updateSettings(this.options.watchOptions);
95
- });
96
- }
97
- async close() {
98
- await this.initialized;
99
- this.abortController.abort();
100
- this.disposeListeners?.();
101
- this.disposeListeners = null;
102
- this._closed = true;
103
- this.iterateListeners((l) => l.closed?.());
104
- this.listeners.clear();
105
- }
106
- /**
107
- * Runs a callback and reports errors to the error listeners.
108
- */
109
- async runWithReporting(callback) {
110
- try {
111
- await callback();
112
- }
113
- catch (error) {
114
- // This will update the error on the state and iterate error listeners
115
- await this.updateState({ error });
116
- }
117
- }
118
- /**
119
- * Iterate listeners and reports errors to onError handlers.
120
- */
121
- async iterateAsyncListenersWithError(callback) {
122
- try {
123
- await this.iterateAsyncListeners(async (l) => callback(l));
124
- }
125
- catch (error) {
126
- try {
127
- await this.iterateAsyncListeners(async (l) => l.onError?.(error));
128
- }
129
- catch (error) {
130
- // Errors here are ignored
131
- // since we are already in an error state
132
- this.options.db.logger.error('Watched query error handler threw an Error', error);
133
- }
134
- }
135
- }
136
- }