@tanstack/lit-query 0.2.5 → 0.2.7

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 (43) hide show
  1. package/dist/controllers/BaseController.d.ts +1 -0
  2. package/dist/controllers/BaseController.d.ts.map +1 -1
  3. package/dist/controllers/BaseController.js +11 -2
  4. package/dist/controllers/BaseController.js.map +1 -1
  5. package/dist/createInfiniteQueryController.d.ts.map +1 -1
  6. package/dist/createInfiniteQueryController.js +41 -14
  7. package/dist/createInfiniteQueryController.js.map +1 -1
  8. package/dist/createQueriesController.d.ts.map +1 -1
  9. package/dist/createQueriesController.js +80 -15
  10. package/dist/createQueriesController.js.map +1 -1
  11. package/dist/createQueryController.d.ts.map +1 -1
  12. package/dist/createQueryController.js +37 -10
  13. package/dist/createQueryController.js.map +1 -1
  14. package/dist/queryObserverResultTracker.d.ts +14 -0
  15. package/dist/queryObserverResultTracker.d.ts.map +1 -0
  16. package/dist/queryObserverResultTracker.js +18 -0
  17. package/dist/queryObserverResultTracker.js.map +1 -0
  18. package/dist/useMutationState.d.ts +1 -1
  19. package/dist/useMutationState.d.ts.map +1 -1
  20. package/dist/useMutationState.js +10 -6
  21. package/dist/useMutationState.js.map +1 -1
  22. package/dist-cjs/controllers/BaseController.d.cts +1 -0
  23. package/dist-cjs/controllers/BaseController.js +11 -2
  24. package/dist-cjs/controllers/BaseController.js.map +1 -1
  25. package/dist-cjs/createInfiniteQueryController.js +41 -14
  26. package/dist-cjs/createInfiniteQueryController.js.map +1 -1
  27. package/dist-cjs/createQueriesController.js +79 -14
  28. package/dist-cjs/createQueriesController.js.map +1 -1
  29. package/dist-cjs/createQueryController.js +37 -10
  30. package/dist-cjs/createQueryController.js.map +1 -1
  31. package/dist-cjs/queryObserverResultTracker.d.cts +13 -0
  32. package/dist-cjs/queryObserverResultTracker.js +22 -0
  33. package/dist-cjs/queryObserverResultTracker.js.map +1 -0
  34. package/dist-cjs/useMutationState.d.cts +1 -1
  35. package/dist-cjs/useMutationState.js +10 -6
  36. package/dist-cjs/useMutationState.js.map +1 -1
  37. package/package.json +2 -2
  38. package/src/controllers/BaseController.ts +10 -2
  39. package/src/createInfiniteQueryController.ts +53 -14
  40. package/src/createQueriesController.ts +110 -22
  41. package/src/createQueryController.ts +47 -10
  42. package/src/queryObserverResultTracker.ts +30 -0
  43. package/src/useMutationState.ts +16 -11
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  QueriesObserver,
3
+ replaceEqualDeep,
3
4
  type DefaultError,
4
5
  type DefinedQueryObserverResult,
5
6
  type OmitKeyof,
@@ -322,6 +323,10 @@ class QueriesController<
322
323
  private observer: QueriesObserver<TCombinedResult> | undefined
323
324
  private unsubscribe: (() => void) | undefined
324
325
  private queryClient: QueryClient | undefined
326
+ private queries: Array<QueryObserverOptions> = []
327
+ private combine: QueriesObserverOptions<TCombinedResult>['combine']
328
+ private combinedResult: TCombinedResult | undefined
329
+ private rawResult: Array<QueryObserverResult> = []
325
330
  private explicitInitializationError: unknown | undefined
326
331
  private placeholderInitialized = false
327
332
  private placeholderRetryableFailure = true
@@ -394,8 +399,7 @@ class QueriesController<
394
399
  }
395
400
 
396
401
  this.unsubscribe = this.observer.subscribe((next) => {
397
- const { combine } = this.readResolvedOptions()
398
- this.setResult(this.computeResult(next, combine))
402
+ this.setObserverResult(next)
399
403
  })
400
404
  }
401
405
 
@@ -405,12 +409,14 @@ class QueriesController<
405
409
  this.options,
406
410
  queryClient,
407
411
  )
408
- const observer = new QueriesObserver(queryClient, queries, {
409
- combine,
412
+ this.queries = queries
413
+ this.combine = combine
414
+ const observer = new QueriesObserver(queryClient, this.queries, {
415
+ combine: this.combine,
410
416
  } as QueriesObserverOptions<TCombinedResult>)
411
417
  this.queryClient = queryClient
412
418
  this.observer = observer
413
- this.result = this.computeResult(observer.getCurrentResult(), combine)
419
+ this.assignObserverResult(observer.getCurrentResult(), true)
414
420
  this.explicitInitializationError = undefined
415
421
  this.placeholderInitialized = true
416
422
  return true
@@ -448,6 +454,10 @@ class QueriesController<
448
454
  this.unsubscribeObserver()
449
455
  this.queryClient = undefined
450
456
  this.observer = undefined
457
+ this.queries = []
458
+ this.combine = undefined
459
+ this.combinedResult = undefined
460
+ this.rawResult = []
451
461
  this.setPlaceholderResult()
452
462
  return false
453
463
  }
@@ -459,12 +469,12 @@ class QueriesController<
459
469
  this.unsubscribeObserver()
460
470
  this.queryClient = nextClient
461
471
  const { queries, combine } = this.readResolvedOptions()
462
- this.observer = new QueriesObserver(this.queryClient, queries, {
463
- combine,
472
+ this.queries = queries
473
+ this.combine = combine
474
+ this.observer = new QueriesObserver(this.queryClient, this.queries, {
475
+ combine: this.combine,
464
476
  } as QueriesObserverOptions<TCombinedResult>)
465
- this.setResult(
466
- this.computeResult(this.observer.getCurrentResult(), combine),
467
- )
477
+ this.setObserverResult(this.observer.getCurrentResult(), true)
468
478
  this.placeholderInitialized = true
469
479
  return true
470
480
  }
@@ -475,17 +485,14 @@ class QueriesController<
475
485
  }
476
486
 
477
487
  const { queries, combine } = this.readResolvedOptions()
488
+ this.queries = queries
489
+ this.combine = combine
478
490
 
479
- this.observer.setQueries(queries, {
480
- combine,
491
+ this.observer.setQueries(this.queries, {
492
+ combine: this.combine,
481
493
  } as QueriesObserverOptions<TCombinedResult>)
482
494
 
483
- const [rawResult, getCombinedResult] = this.observer.getOptimisticResult(
484
- queries,
485
- combine,
486
- )
487
-
488
- this.setResult(getCombinedResult(rawResult))
495
+ this.setObserverResult(this.observer.getCurrentResult(), true)
489
496
  return true
490
497
  }
491
498
 
@@ -513,11 +520,87 @@ class QueriesController<
513
520
  return typeof this.options.queries === 'function'
514
521
  }
515
522
 
516
- private computeResult(
523
+ private createResult(rawResult: Array<QueryObserverResult>): TCombinedResult {
524
+ const trackedResult = this.trackResult(rawResult)
525
+ const combine = this.combine
526
+
527
+ if (!combine) {
528
+ return trackedResult as TCombinedResult
529
+ }
530
+
531
+ this.combinedResult = replaceEqualDeep(
532
+ this.combinedResult,
533
+ combine(trackedResult),
534
+ ) as TCombinedResult
535
+
536
+ return this.combinedResult
537
+ }
538
+
539
+ private assignObserverResult(
517
540
  rawResult: Array<QueryObserverResult>,
518
- combine: QueriesObserverOptions<TCombinedResult>['combine'],
519
- ): TCombinedResult {
520
- return (combine ? combine(rawResult) : rawResult) as TCombinedResult
541
+ force = false,
542
+ ): void {
543
+ if (!force && this.hasObserverResult(rawResult)) {
544
+ return
545
+ }
546
+
547
+ this.rawResult = rawResult
548
+ this.result = this.createResult(rawResult)
549
+ }
550
+
551
+ private setObserverResult(
552
+ rawResult: Array<QueryObserverResult>,
553
+ force = false,
554
+ ): void {
555
+ if (!force && this.hasObserverResult(rawResult)) {
556
+ return
557
+ }
558
+
559
+ this.rawResult = rawResult
560
+ this.setResult(this.createResult(rawResult))
561
+ }
562
+
563
+ private hasObserverResult(rawResult: Array<QueryObserverResult>): boolean {
564
+ return (
565
+ this.rawResult.length === rawResult.length &&
566
+ rawResult.every((result, index) =>
567
+ Object.is(this.rawResult[index], result),
568
+ )
569
+ )
570
+ }
571
+
572
+ private getCurrentObserverResults(): Array<QueryObserverResult> {
573
+ if (!this.observer) {
574
+ return []
575
+ }
576
+
577
+ return this.observer
578
+ .getObservers()
579
+ .map((observer) => observer.getCurrentResult())
580
+ }
581
+
582
+ private trackResult(
583
+ rawResult: Array<QueryObserverResult>,
584
+ ): Array<QueryObserverResult> {
585
+ if (!this.observer) {
586
+ return rawResult
587
+ }
588
+
589
+ const observers = this.observer.getObservers()
590
+
591
+ return rawResult.map((result, index) => {
592
+ const observer = observers[index]
593
+
594
+ if (!observer || observer.options.notifyOnChangeProps) {
595
+ return result
596
+ }
597
+
598
+ return observer.trackResult(result, (accessedProp) => {
599
+ observers.forEach((observer) => {
600
+ observer.trackProp(accessedProp)
601
+ })
602
+ })
603
+ })
521
604
  }
522
605
 
523
606
  private static createPlaceholderResult<TCombinedResult>(
@@ -559,10 +642,15 @@ class QueriesController<
559
642
  }
560
643
  }
561
644
 
645
+ if (this.observer) {
646
+ this.assignObserverResult(this.getCurrentObserverResults())
647
+ }
648
+
562
649
  return this.current
563
650
  }
564
651
 
565
652
  private setPlaceholderResult(): void {
653
+ this.rawResult = []
566
654
  this.result = QueriesController.createPlaceholderResult(this.options)
567
655
  this.placeholderInitialized = true
568
656
  }
@@ -16,6 +16,7 @@ import {
16
16
  } from './accessor.js'
17
17
  import { createMissingQueryClientError } from './context.js'
18
18
  import { BaseController } from './controllers/BaseController.js'
19
+ import { QueryObserverResultTracker } from './queryObserverResultTracker.js'
19
20
 
20
21
  /**
21
22
  * Options accepted by `createQueryController`.
@@ -100,6 +101,9 @@ class QueryController<
100
101
  private observer:
101
102
  | QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey>
102
103
  | undefined
104
+ private readonly resultTracker = new QueryObserverResultTracker<
105
+ QueryObserverResult<TData, TError>
106
+ >()
103
107
  private unsubscribe: (() => void) | undefined
104
108
  private queryClient: QueryClient | undefined
105
109
 
@@ -126,7 +130,7 @@ class QueryController<
126
130
  const observer = new QueryObserver(initialClient, defaulted)
127
131
  this.queryClient = initialClient
128
132
  this.observer = observer
129
- this.result = observer.getOptimisticResult(defaulted)
133
+ this.assignObserverResult(observer.getOptimisticResult(defaulted))
130
134
  }
131
135
 
132
136
  protected onConnected(): void {
@@ -138,7 +142,7 @@ class QueryController<
138
142
  this.subscribe()
139
143
  this.observer?.updateResult()
140
144
  if (this.observer) {
141
- this.setResult(this.observer.getCurrentResult())
145
+ this.setObserverResult(this.observer.getCurrentResult())
142
146
  }
143
147
  }
144
148
 
@@ -168,16 +172,16 @@ class QueryController<
168
172
  this.subscribe()
169
173
  this.observer?.updateResult()
170
174
  if (this.observer) {
171
- this.setResult(this.observer.getCurrentResult())
175
+ this.setObserverResult(this.observer.getCurrentResult())
172
176
  }
173
177
  }
174
178
 
175
179
  refetch: QueryObserverResult<TData, TError>['refetch'] = (...args) => {
176
- if (!this.refreshOptions()) {
180
+ if (!this.applyOptions() || !this.observer) {
177
181
  return Promise.reject(createMissingQueryClientError())
178
182
  }
179
183
 
180
- return this.result.refetch(...args)
184
+ return this.observer.refetch(...args)
181
185
  }
182
186
 
183
187
  suspense = async (): Promise<QueryObserverResult<TData, TError>> => {
@@ -195,6 +199,14 @@ class QueryController<
195
199
  return optimistic
196
200
  }
197
201
 
202
+ readCurrent(): QueryObserverResult<TData, TError> {
203
+ if (this.observer) {
204
+ this.assignObserverResult(this.observer.getCurrentResult())
205
+ }
206
+
207
+ return this.current
208
+ }
209
+
198
210
  private subscribe(): void {
199
211
  if (!this.observer) {
200
212
  return
@@ -205,7 +217,7 @@ class QueryController<
205
217
  }
206
218
 
207
219
  this.unsubscribe = this.observer.subscribe((next) => {
208
- this.setResult(next)
220
+ this.setObserverResult(next)
209
221
  })
210
222
  }
211
223
 
@@ -220,6 +232,7 @@ class QueryController<
220
232
  this.unsubscribeObserver()
221
233
  this.queryClient = undefined
222
234
  this.observer = undefined
235
+ this.resultTracker.reset()
223
236
  this.setResult(createPendingQueryResult())
224
237
  return false
225
238
  }
@@ -232,21 +245,45 @@ class QueryController<
232
245
  this.queryClient = nextClient
233
246
  const options = this.defaultOptions()
234
247
  this.observer = new QueryObserver(this.queryClient, options)
235
- this.setResult(this.observer.getOptimisticResult(options))
248
+ this.setObserverResult(this.observer.getOptimisticResult(options))
236
249
  return true
237
250
  }
238
251
 
239
- private refreshOptions(): boolean {
252
+ private applyOptions(): boolean {
240
253
  if (!this.syncClient() || !this.observer) {
241
254
  return false
242
255
  }
243
256
 
244
257
  const options = this.defaultOptions(this.queryClient)
245
258
  this.observer.setOptions(options)
246
- this.setResult(this.observer.getCurrentResult())
247
259
  return true
248
260
  }
249
261
 
262
+ private refreshOptions(): boolean {
263
+ if (!this.applyOptions() || !this.observer) {
264
+ return false
265
+ }
266
+
267
+ this.setObserverResult(this.observer.getCurrentResult())
268
+ return true
269
+ }
270
+
271
+ private assignObserverResult(
272
+ result: QueryObserverResult<TData, TError>,
273
+ ): void {
274
+ const trackedResult = this.resultTracker.update(this.observer, result)
275
+ if (trackedResult) {
276
+ this.result = trackedResult
277
+ }
278
+ }
279
+
280
+ private setObserverResult(result: QueryObserverResult<TData, TError>): void {
281
+ const trackedResult = this.resultTracker.update(this.observer, result)
282
+ if (trackedResult) {
283
+ this.setResult(trackedResult)
284
+ }
285
+ }
286
+
250
287
  private defaultOptions(
251
288
  client = this.queryClient,
252
289
  ): DefaultedQueryObserverOptions<
@@ -332,7 +369,7 @@ export function createQueryController<
332
369
  const controller = new QueryController(host, options, queryClient)
333
370
 
334
371
  return Object.assign(
335
- createValueAccessor(() => controller.current),
372
+ createValueAccessor(() => controller.readCurrent()),
336
373
  {
337
374
  refetch: controller.refetch,
338
375
  suspense: controller.suspense,
@@ -0,0 +1,30 @@
1
+ type TrackableQueryObserver<TResult extends object> = {
2
+ options: { notifyOnChangeProps?: unknown }
3
+ trackResult: (result: TResult) => unknown
4
+ }
5
+
6
+ export class QueryObserverResultTracker<TResult extends object> {
7
+ private result: TResult | undefined
8
+ private usesTracking = false
9
+
10
+ reset(): void {
11
+ this.result = undefined
12
+ this.usesTracking = false
13
+ }
14
+
15
+ update(
16
+ observer: TrackableQueryObserver<TResult> | undefined,
17
+ result: TResult,
18
+ ): TResult | undefined {
19
+ const usesTracking = !!observer && !observer.options.notifyOnChangeProps
20
+
21
+ if (Object.is(this.result, result) && this.usesTracking === usesTracking) {
22
+ return undefined
23
+ }
24
+
25
+ this.result = result
26
+ this.usesTracking = usesTracking
27
+
28
+ return usesTracking ? (observer.trackResult(result) as TResult) : result
29
+ }
30
+ }
@@ -1,8 +1,9 @@
1
- import type {
2
- Mutation,
3
- MutationFilters,
4
- MutationState,
5
- QueryClient,
1
+ import {
2
+ replaceEqualDeep,
3
+ type Mutation,
4
+ type MutationFilters,
5
+ type MutationState,
6
+ type QueryClient,
6
7
  } from '@tanstack/query-core'
7
8
  import type { ReactiveControllerHost } from 'lit'
8
9
  import {
@@ -55,12 +56,12 @@ class MutationStateController<TResult> extends BaseController<TResult[]> {
55
56
 
56
57
  protected onConnected(): void {
57
58
  if (!this.syncClient()) {
58
- this.setResult([])
59
+ this.setMutationState([])
59
60
  return
60
61
  }
61
62
 
62
63
  this.subscribe()
63
- this.setResult(this.computeState())
64
+ this.setMutationState(this.computeState())
64
65
  }
65
66
 
66
67
  protected onDisconnected(): void {
@@ -74,18 +75,18 @@ class MutationStateController<TResult> extends BaseController<TResult[]> {
74
75
  return
75
76
  }
76
77
 
77
- this.setResult(this.syncClient() ? this.computeState() : [])
78
+ this.setMutationState(this.syncClient() ? this.computeState() : [])
78
79
  }
79
80
 
80
81
  protected onQueryClientChanged(): void {
81
82
  if (!this.syncClient()) {
82
- this.setResult([])
83
+ this.setMutationState([])
83
84
  return
84
85
  }
85
86
 
86
87
  if (this.connectedState) {
87
88
  this.subscribe()
88
- this.setResult(this.computeState())
89
+ this.setMutationState(this.computeState())
89
90
  }
90
91
  }
91
92
 
@@ -118,10 +119,14 @@ class MutationStateController<TResult> extends BaseController<TResult[]> {
118
119
  }
119
120
 
120
121
  this.unsubscribe = this.queryClient.getMutationCache().subscribe(() => {
121
- this.setResult(this.computeState())
122
+ this.setMutationState(this.computeState())
122
123
  })
123
124
  }
124
125
 
126
+ private setMutationState(next: TResult[]): void {
127
+ this.setResult(replaceEqualDeep(this.result, next))
128
+ }
129
+
125
130
  private shouldRefreshOnHostUpdate(): boolean {
126
131
  return (
127
132
  typeof this.options.filters === 'function' ||