Skip to content

Commit a0e0c70

Browse files
improve generics
1 parent c108094 commit a0e0c70

File tree

6 files changed

+94
-22
lines changed

6 files changed

+94
-22
lines changed

packages/common/src/client/AbstractPowerSyncDatabase.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,10 +879,9 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
879879
const { mode } = options;
880880
const builderFactory = WatchedQueryBuilderMap[mode];
881881
if (!builderFactory) {
882-
debugger;
883882
throw new Error(`Unsupported watch mode: ${mode}`);
884883
}
885-
return builderFactory(this);
884+
return builderFactory(this) as WatchedQueryBuilderMap[Mode];
886885
}
887886

888887
/**

packages/common/src/client/watched/WatchedQuery.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ export interface WatchCompatibleQuery<ResultType> {
4646
}
4747

4848
export interface WatchedQueryOptions<DataType> {
49-
query: WatchCompatibleQuery<DataType>;
50-
5149
/**
5250
* Initial result data which is presented while the initial loading is executing
5351
*/
@@ -85,7 +83,8 @@ export interface WatchedQueryListener extends BaseListener {
8583
subscriptionsChanged: (counts: SubscriptionCounts) => void;
8684
}
8785

88-
export interface WatchedQuery<Data> extends BaseObserverInterface<WatchedQueryListener> {
86+
export interface WatchedQuery<Data, Settings extends WatchedQueryOptions<Data> = WatchedQueryOptions<Data>>
87+
extends BaseObserverInterface<WatchedQueryListener> {
8988
/**
9089
* Current state of the watched query.
9190
*/
@@ -105,7 +104,7 @@ export interface WatchedQuery<Data> extends BaseObserverInterface<WatchedQueryLi
105104
* Updates the underlying query options.
106105
* This will trigger a re-evaluation of the query and update the state.
107106
*/
108-
updateSettings(options: WatchedQueryOptions<Data>): Promise<void>;
107+
updateSettings(options: Settings): Promise<void>;
109108

110109
/**
111110
* Close the watched query and end all subscriptions.

packages/common/src/client/watched/processors/AbstractQueryProcessor.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@ import {
1313
/**
1414
* @internal
1515
*/
16-
export interface AbstractQueryProcessorOptions<Data> {
16+
export interface AbstractQueryProcessorOptions<
17+
Data,
18+
Settings extends WatchedQueryOptions<Data> = WatchedQueryOptions<Data>
19+
> {
1720
db: AbstractPowerSyncDatabase;
18-
watchOptions: WatchedQueryOptions<Data>;
21+
watchOptions: Settings;
1922
}
2023

2124
/**
2225
* @internal
2326
*/
24-
export interface LinkQueryOptions<Data> {
27+
export interface LinkQueryOptions<Data, Settings extends WatchedQueryOptions<Data> = WatchedQueryOptions<Data>> {
2528
abortSignal: AbortSignal;
26-
query: WatchedQueryOptions<Data>;
29+
settings: Settings;
2730
}
2831

2932
type WatchedQueryProcessorListener<Data> = WatchedQuerySubscription<Data> & WatchedQueryListener;
@@ -32,7 +35,10 @@ type WatchedQueryProcessorListener<Data> = WatchedQuerySubscription<Data> & Watc
3235
* Performs underlying watching and yields a stream of results.
3336
* @internal
3437
*/
35-
export abstract class AbstractQueryProcessor<Data = unknown[]>
38+
export abstract class AbstractQueryProcessor<
39+
Data = unknown[],
40+
Settings extends WatchedQueryOptions<Data> = WatchedQueryOptions<Data>
41+
>
3642
extends BaseObserver<WatchedQueryProcessorListener<Data>>
3743
implements WatchedQuery<Data>
3844
{
@@ -56,7 +62,7 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
5662
}, {}) as SubscriptionCounts;
5763
}
5864

59-
constructor(protected options: AbstractQueryProcessorOptions<Data>) {
65+
constructor(protected options: AbstractQueryProcessorOptions<Data, Settings>) {
6066
super();
6167
this.abortController = new AbortController();
6268
this._closed = false;
@@ -78,15 +84,23 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
7884
/**
7985
* Updates the underlying query.
8086
*/
81-
async updateSettings(query: WatchedQueryOptions<Data>) {
87+
async updateSettings(settings: Settings) {
8288
await this.initialized;
8389

84-
this.options.watchOptions = query;
90+
if (!this.state.isLoading) {
91+
await this.updateState({
92+
isLoading: true,
93+
isFetching: this.reportFetching ? true : false,
94+
data: settings.placeholderData
95+
});
96+
}
97+
98+
this.options.watchOptions = settings;
8599
this.abortController.abort();
86100
this.abortController = new AbortController();
87101
await this.linkQuery({
88102
abortSignal: this.abortController.signal,
89-
query
103+
settings
90104
});
91105
}
92106

packages/common/src/client/watched/processors/ComparisonWatchedQueryBuilder.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import { AbstractPowerSyncDatabase } from '../../../client/AbstractPowerSyncDatabase.js';
2-
import { WatchedQuery, WatchedQueryOptions } from '../WatchedQuery.js';
2+
import { WatchedQuery } from '../WatchedQuery.js';
33
import { WatchedQueryBuilder } from '../WatchedQueryBuilder.js';
44
import { WatchedQueryComparator } from './comparators.js';
5-
import { OnChangeQueryProcessor } from './OnChangeQueryProcessor.js';
5+
import { ComparisonWatchedQuerySettings, OnChangeQueryProcessor } from './OnChangeQueryProcessor.js';
66

77
export interface ComparisonWatchProcessorOptions<DataType> {
88
comparator?: WatchedQueryComparator<DataType>;
9-
watch: WatchedQueryOptions<DataType>;
9+
watch: ComparisonWatchedQuerySettings<DataType>;
1010
}
1111

1212
export class ComparisonWatchedQueryBuilder implements WatchedQueryBuilder {
1313
constructor(protected db: AbstractPowerSyncDatabase) {}
1414

15-
build<DataType>(options: ComparisonWatchProcessorOptions<DataType>): WatchedQuery<DataType> {
15+
build<DataType>(
16+
options: ComparisonWatchProcessorOptions<DataType>
17+
): WatchedQuery<DataType, ComparisonWatchedQuerySettings<DataType>> {
1618
return new OnChangeQueryProcessor({
1719
db: this.db,
1820
comparator: options.comparator ?? {

packages/common/src/client/watched/processors/OnChangeQueryProcessor.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { WatchedQueryState } from '../WatchedQuery.js';
1+
import { WatchCompatibleQuery, WatchedQueryOptions, WatchedQueryState } from '../WatchedQuery.js';
22
import { AbstractQueryProcessor, AbstractQueryProcessorOptions, LinkQueryOptions } from './AbstractQueryProcessor.js';
33
import { WatchedQueryComparator } from './comparators.js';
44

5+
export interface ComparisonWatchedQuerySettings<DataType> extends WatchedQueryOptions<DataType> {
6+
query: WatchCompatibleQuery<DataType>;
7+
}
8+
59
/**
610
* @internal
711
*/
8-
export interface OnChangeQueryProcessorOptions<Data> extends AbstractQueryProcessorOptions<Data> {
12+
export interface OnChangeQueryProcessorOptions<Data>
13+
extends AbstractQueryProcessorOptions<Data, ComparisonWatchedQuerySettings<Data>> {
914
comparator?: WatchedQueryComparator<Data>;
1015
}
1116

@@ -14,7 +19,7 @@ export interface OnChangeQueryProcessorOptions<Data> extends AbstractQueryProces
1419
* Results are emitted on every change of the relevant tables.
1520
* @internal
1621
*/
17-
export class OnChangeQueryProcessor<Data> extends AbstractQueryProcessor<Data> {
22+
export class OnChangeQueryProcessor<Data> extends AbstractQueryProcessor<Data, ComparisonWatchedQuerySettings<Data>> {
1823
constructor(protected options: OnChangeQueryProcessorOptions<Data>) {
1924
super(options);
2025
}

packages/web/tests/watch.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,4 +452,57 @@ describe('Watch Tests', { sequential: true }, () => {
452452
expect(notificationCount).equals(1);
453453
expect(watch.state.data).toHaveLength(1);
454454
});
455+
456+
it('should allow updating queries', async () => {
457+
// Create sample data
458+
await powersync.execute('INSERT INTO assets(id, make, customer_id) VALUES (uuid(), ?, ?)', ['test', uuid()]);
459+
await powersync.execute('INSERT INTO assets(id, make, customer_id) VALUES (uuid(), ?, ?)', ['nottest', uuid()]);
460+
461+
const watch = powersync
462+
.incrementalWatch({
463+
mode: IncrementalWatchMode.COMPARISON
464+
})
465+
.build({
466+
watch: {
467+
query: new GetAllQuery<{ make: string }>({
468+
sql: 'SELECT * FROM assets where make = ?',
469+
parameters: ['test']
470+
}),
471+
placeholderData: [],
472+
reportFetching: false
473+
}
474+
});
475+
476+
expect(watch.state.isFetching).false;
477+
478+
await vi.waitFor(
479+
() => {
480+
expect(watch.state.isLoading).false;
481+
},
482+
{ timeout: 1000 }
483+
);
484+
485+
expect(watch.state.data).toHaveLength(1);
486+
expect(watch.state.data[0].make).equals('test');
487+
488+
await watch.updateSettings({
489+
placeholderData: [],
490+
query: new GetAllQuery<{ make: string }>({
491+
sql: 'SELECT * FROM assets where make = ?',
492+
parameters: ['nottest']
493+
})
494+
});
495+
496+
expect(watch.state.isLoading).true;
497+
498+
await vi.waitFor(
499+
() => {
500+
expect(watch.state.isLoading).false;
501+
},
502+
{ timeout: 1000 }
503+
);
504+
505+
expect(watch.state.data).toHaveLength(1);
506+
expect(watch.state.data[0].make).equals('nottest');
507+
});
455508
});

0 commit comments

Comments
 (0)