@tanstack/lit-query 0.0.1 → 0.2.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 (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -43
  3. package/dist/QueryClientProvider.d.ts +85 -0
  4. package/dist/QueryClientProvider.d.ts.map +1 -0
  5. package/dist/QueryClientProvider.js +137 -0
  6. package/dist/QueryClientProvider.js.map +1 -0
  7. package/dist/accessor.d.ts +32 -0
  8. package/dist/accessor.d.ts.map +1 -0
  9. package/dist/accessor.js +12 -0
  10. package/dist/accessor.js.map +1 -0
  11. package/dist/context.d.ts +59 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +100 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/controllers/BaseController.d.ts +38 -0
  16. package/dist/controllers/BaseController.d.ts.map +1 -0
  17. package/dist/controllers/BaseController.js +204 -0
  18. package/dist/controllers/BaseController.js.map +1 -0
  19. package/dist/createInfiniteQueryController.d.ts +76 -0
  20. package/dist/createInfiniteQueryController.d.ts.map +1 -0
  21. package/dist/createInfiniteQueryController.js +221 -0
  22. package/dist/createInfiniteQueryController.js.map +1 -0
  23. package/dist/createMutationController.d.ts +79 -0
  24. package/dist/createMutationController.d.ts.map +1 -0
  25. package/dist/createMutationController.js +193 -0
  26. package/dist/createMutationController.js.map +1 -0
  27. package/dist/createQueriesController.d.ts +145 -0
  28. package/dist/createQueriesController.d.ts.map +1 -0
  29. package/dist/createQueriesController.js +302 -0
  30. package/dist/createQueriesController.js.map +1 -0
  31. package/dist/createQueryController.d.ts +67 -0
  32. package/dist/createQueryController.d.ts.map +1 -0
  33. package/dist/createQueryController.js +211 -0
  34. package/dist/createQueryController.js.map +1 -0
  35. package/dist/index.d.ts +24 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +15 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/infiniteQueryOptions.d.ts +21 -0
  40. package/dist/infiniteQueryOptions.d.ts.map +1 -0
  41. package/dist/infiniteQueryOptions.js +22 -0
  42. package/dist/infiniteQueryOptions.js.map +1 -0
  43. package/dist/mutationOptions.d.ts +19 -0
  44. package/dist/mutationOptions.d.ts.map +1 -0
  45. package/dist/mutationOptions.js +20 -0
  46. package/dist/mutationOptions.js.map +1 -0
  47. package/dist/queryOptions.d.ts +62 -0
  48. package/dist/queryOptions.d.ts.map +1 -0
  49. package/dist/queryOptions.js +4 -0
  50. package/dist/queryOptions.js.map +1 -0
  51. package/dist/types.d.ts +31 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/useIsFetching.d.ts +45 -0
  56. package/dist/useIsFetching.d.ts.map +1 -0
  57. package/dist/useIsFetching.js +116 -0
  58. package/dist/useIsFetching.js.map +1 -0
  59. package/dist/useIsMutating.d.ts +45 -0
  60. package/dist/useIsMutating.d.ts.map +1 -0
  61. package/dist/useIsMutating.js +116 -0
  62. package/dist/useIsMutating.js.map +1 -0
  63. package/dist/useMutationState.d.ts +57 -0
  64. package/dist/useMutationState.d.ts.map +1 -0
  65. package/dist/useMutationState.js +132 -0
  66. package/dist/useMutationState.js.map +1 -0
  67. package/dist-cjs/QueryClientProvider.d.cts +84 -0
  68. package/dist-cjs/QueryClientProvider.js +141 -0
  69. package/dist-cjs/QueryClientProvider.js.map +1 -0
  70. package/dist-cjs/accessor.d.cts +31 -0
  71. package/dist-cjs/accessor.js +16 -0
  72. package/dist-cjs/accessor.js.map +1 -0
  73. package/dist-cjs/context.d.cts +58 -0
  74. package/dist-cjs/context.js +109 -0
  75. package/dist-cjs/context.js.map +1 -0
  76. package/dist-cjs/controllers/BaseController.d.cts +37 -0
  77. package/dist-cjs/controllers/BaseController.js +208 -0
  78. package/dist-cjs/controllers/BaseController.js.map +1 -0
  79. package/dist-cjs/createInfiniteQueryController.d.cts +75 -0
  80. package/dist-cjs/createInfiniteQueryController.js +224 -0
  81. package/dist-cjs/createInfiniteQueryController.js.map +1 -0
  82. package/dist-cjs/createMutationController.d.cts +78 -0
  83. package/dist-cjs/createMutationController.js +196 -0
  84. package/dist-cjs/createMutationController.js.map +1 -0
  85. package/dist-cjs/createQueriesController.d.cts +144 -0
  86. package/dist-cjs/createQueriesController.js +305 -0
  87. package/dist-cjs/createQueriesController.js.map +1 -0
  88. package/dist-cjs/createQueryController.d.cts +66 -0
  89. package/dist-cjs/createQueryController.js +214 -0
  90. package/dist-cjs/createQueryController.js.map +1 -0
  91. package/dist-cjs/index.d.cts +23 -0
  92. package/dist-cjs/index.js +49 -0
  93. package/dist-cjs/index.js.map +1 -0
  94. package/dist-cjs/infiniteQueryOptions.d.cts +20 -0
  95. package/dist-cjs/infiniteQueryOptions.js +25 -0
  96. package/dist-cjs/infiniteQueryOptions.js.map +1 -0
  97. package/dist-cjs/mutationOptions.d.cts +18 -0
  98. package/dist-cjs/mutationOptions.js +23 -0
  99. package/dist-cjs/mutationOptions.js.map +1 -0
  100. package/dist-cjs/package.json +3 -0
  101. package/dist-cjs/queryOptions.d.cts +61 -0
  102. package/dist-cjs/queryOptions.js +7 -0
  103. package/dist-cjs/queryOptions.js.map +1 -0
  104. package/dist-cjs/types.d.cts +30 -0
  105. package/dist-cjs/types.js +3 -0
  106. package/dist-cjs/types.js.map +1 -0
  107. package/dist-cjs/useIsFetching.d.cts +44 -0
  108. package/dist-cjs/useIsFetching.js +119 -0
  109. package/dist-cjs/useIsFetching.js.map +1 -0
  110. package/dist-cjs/useIsMutating.d.cts +44 -0
  111. package/dist-cjs/useIsMutating.js +119 -0
  112. package/dist-cjs/useIsMutating.js.map +1 -0
  113. package/dist-cjs/useMutationState.d.cts +56 -0
  114. package/dist-cjs/useMutationState.js +135 -0
  115. package/dist-cjs/useMutationState.js.map +1 -0
  116. package/package.json +73 -8
  117. package/src/QueryClientProvider.ts +174 -0
  118. package/src/accessor.ts +43 -0
  119. package/src/context.ts +120 -0
  120. package/src/controllers/BaseController.ts +284 -0
  121. package/src/createInfiniteQueryController.ts +394 -0
  122. package/src/createMutationController.ts +361 -0
  123. package/src/createQueriesController.ts +633 -0
  124. package/src/createQueryController.ts +342 -0
  125. package/src/index.ts +72 -0
  126. package/src/infiniteQueryOptions.ts +48 -0
  127. package/src/mutationOptions.ts +31 -0
  128. package/src/queryOptions.ts +143 -0
  129. package/src/types.ts +77 -0
  130. package/src/useIsFetching.ts +159 -0
  131. package/src/useIsMutating.ts +159 -0
  132. package/src/useMutationState.ts +201 -0
@@ -0,0 +1,394 @@
1
+ import {
2
+ InfiniteQueryObserver,
3
+ type DefaultError,
4
+ type DefaultedInfiniteQueryObserverOptions,
5
+ type InfiniteData,
6
+ type InfiniteQueryObserverOptions,
7
+ type InfiniteQueryObserverResult,
8
+ type QueryKey,
9
+ } from '@tanstack/query-core'
10
+ import type { QueryClient } from '@tanstack/query-core'
11
+ import type { ReactiveControllerHost } from 'lit'
12
+ import {
13
+ createValueAccessor,
14
+ readAccessor,
15
+ type Accessor,
16
+ type ValueAccessor,
17
+ } from './accessor.js'
18
+ import { createMissingQueryClientError } from './context.js'
19
+ import { BaseController } from './controllers/BaseController.js'
20
+
21
+ /**
22
+ * Options accepted by `createInfiniteQueryController`.
23
+ *
24
+ * This is the Lit adapter shape for `InfiniteQueryObserverOptions`. Pass it
25
+ * directly or through an `Accessor` when the options depend on Lit host state.
26
+ */
27
+ export type CreateInfiniteQueryOptions<
28
+ TQueryFnData = unknown,
29
+ TError = DefaultError,
30
+ TData = InfiniteData<TQueryFnData>,
31
+ TQueryKey extends QueryKey = QueryKey,
32
+ TPageParam = unknown,
33
+ > = InfiniteQueryObserverOptions<
34
+ TQueryFnData,
35
+ TError,
36
+ TData,
37
+ TQueryKey,
38
+ TPageParam
39
+ >
40
+
41
+ /**
42
+ * Accessor returned by `createInfiniteQueryController`.
43
+ *
44
+ * Call the accessor or read its `current` property to get the latest infinite
45
+ * query result. The attached methods delegate to the active infinite query
46
+ * observer.
47
+ */
48
+ export type InfiniteQueryResultAccessor<TData, TError> = ValueAccessor<
49
+ InfiniteQueryObserverResult<TData, TError>
50
+ > & {
51
+ /** Refetches the current infinite query. */
52
+ refetch: InfiniteQueryObserverResult<TData, TError>['refetch']
53
+ /** Fetches the next page for the current infinite query. */
54
+ fetchNextPage: InfiniteQueryObserverResult<TData, TError>['fetchNextPage']
55
+ /** Fetches the previous page for the current infinite query. */
56
+ fetchPreviousPage: InfiniteQueryObserverResult<
57
+ TData,
58
+ TError
59
+ >['fetchPreviousPage']
60
+ /** Removes the controller from its Lit host and unsubscribes observers. */
61
+ destroy: () => void
62
+ }
63
+
64
+ function createPendingInfiniteQueryResult<
65
+ TData,
66
+ TError,
67
+ >(): InfiniteQueryObserverResult<TData, TError> {
68
+ return {
69
+ data: undefined,
70
+ dataUpdatedAt: 0,
71
+ error: null,
72
+ errorUpdatedAt: 0,
73
+ failureCount: 0,
74
+ failureReason: null,
75
+ errorUpdateCount: 0,
76
+ isError: false,
77
+ isFetched: false,
78
+ isFetchedAfterMount: false,
79
+ isFetching: false,
80
+ isInitialLoading: false,
81
+ isLoading: false,
82
+ isLoadingError: false,
83
+ isPaused: false,
84
+ isPending: true,
85
+ isPlaceholderData: false,
86
+ isRefetchError: false,
87
+ isRefetching: false,
88
+ isStale: true,
89
+ isEnabled: true,
90
+ isSuccess: false,
91
+ fetchStatus: 'idle',
92
+ status: 'pending',
93
+ refetch: (() =>
94
+ Promise.reject(
95
+ createMissingQueryClientError(),
96
+ )) as InfiniteQueryObserverResult<TData, TError>['refetch'],
97
+ fetchNextPage: (() =>
98
+ Promise.reject(
99
+ createMissingQueryClientError(),
100
+ )) as InfiniteQueryObserverResult<TData, TError>['fetchNextPage'],
101
+ fetchPreviousPage: (() =>
102
+ Promise.reject(
103
+ createMissingQueryClientError(),
104
+ )) as InfiniteQueryObserverResult<TData, TError>['fetchPreviousPage'],
105
+ hasNextPage: false,
106
+ hasPreviousPage: false,
107
+ isFetchNextPageError: false,
108
+ isFetchingNextPage: false,
109
+ isFetchPreviousPageError: false,
110
+ isFetchingPreviousPage: false,
111
+ promise: Promise.resolve(undefined as never),
112
+ } as unknown as InfiniteQueryObserverResult<TData, TError>
113
+ }
114
+
115
+ class InfiniteQueryController<
116
+ TQueryFnData,
117
+ TError,
118
+ TData,
119
+ TQueryKey extends QueryKey,
120
+ TPageParam,
121
+ > extends BaseController<InfiniteQueryObserverResult<TData, TError>> {
122
+ private readonly options: Accessor<
123
+ CreateInfiniteQueryOptions<
124
+ TQueryFnData,
125
+ TError,
126
+ TData,
127
+ TQueryKey,
128
+ TPageParam
129
+ >
130
+ >
131
+ private observer:
132
+ | InfiniteQueryObserver<TQueryFnData, TError, TData, TQueryKey, TPageParam>
133
+ | undefined
134
+ private unsubscribe: (() => void) | undefined
135
+ private queryClient: QueryClient | undefined
136
+
137
+ constructor(
138
+ host: ReactiveControllerHost,
139
+ options: Accessor<
140
+ CreateInfiniteQueryOptions<
141
+ TQueryFnData,
142
+ TError,
143
+ TData,
144
+ TQueryKey,
145
+ TPageParam
146
+ >
147
+ >,
148
+ queryClient?: QueryClient,
149
+ ) {
150
+ super(host, createPendingInfiniteQueryResult(), queryClient)
151
+ this.options = options
152
+
153
+ if (!queryClient) {
154
+ return
155
+ }
156
+
157
+ if (typeof options === 'function') {
158
+ return
159
+ }
160
+
161
+ const defaulted = this.defaultOptions(queryClient)
162
+ const observer = new InfiniteQueryObserver(queryClient, defaulted)
163
+ this.queryClient = queryClient
164
+ this.observer = observer
165
+ this.result = observer.getOptimisticResult(defaulted)
166
+ }
167
+
168
+ protected onConnected(): void {
169
+ if (!this.syncClient()) {
170
+ return
171
+ }
172
+
173
+ this.refreshOptions()
174
+ this.subscribe()
175
+ this.observer?.updateResult()
176
+ if (this.observer) {
177
+ this.setResult(this.observer.getCurrentResult())
178
+ }
179
+ }
180
+
181
+ protected onDisconnected(): void {
182
+ this.unsubscribeObserver()
183
+ this.syncClient()
184
+ }
185
+
186
+ protected onHostUpdate(): void {
187
+ if (typeof this.options !== 'function') {
188
+ return
189
+ }
190
+
191
+ this.refreshOptions()
192
+ }
193
+
194
+ protected onQueryClientChanged(): void {
195
+ if (!this.syncClient() || !this.connectedState) {
196
+ return
197
+ }
198
+
199
+ this.refreshOptions()
200
+ this.subscribe()
201
+ this.observer?.updateResult()
202
+ if (this.observer) {
203
+ this.setResult(this.observer.getCurrentResult())
204
+ }
205
+ }
206
+
207
+ refetch: InfiniteQueryObserverResult<TData, TError>['refetch'] = (
208
+ ...args
209
+ ) => {
210
+ if (!this.refreshOptions()) {
211
+ return Promise.reject(createMissingQueryClientError())
212
+ }
213
+
214
+ return this.result.refetch(...args)
215
+ }
216
+
217
+ fetchNextPage: InfiniteQueryObserverResult<TData, TError>['fetchNextPage'] = (
218
+ ...args
219
+ ) => {
220
+ if (!this.refreshOptions()) {
221
+ return Promise.reject(createMissingQueryClientError())
222
+ }
223
+
224
+ return this.result.fetchNextPage(...args)
225
+ }
226
+
227
+ fetchPreviousPage: InfiniteQueryObserverResult<
228
+ TData,
229
+ TError
230
+ >['fetchPreviousPage'] = (...args) => {
231
+ if (!this.refreshOptions()) {
232
+ return Promise.reject(createMissingQueryClientError())
233
+ }
234
+
235
+ return this.result.fetchPreviousPage(...args)
236
+ }
237
+
238
+ private subscribe(): void {
239
+ if (!this.observer) {
240
+ return
241
+ }
242
+
243
+ if (this.unsubscribe) {
244
+ return
245
+ }
246
+
247
+ this.unsubscribe = this.observer.subscribe((next) => {
248
+ this.setResult(next)
249
+ })
250
+ }
251
+
252
+ private unsubscribeObserver(): void {
253
+ this.unsubscribe?.()
254
+ this.unsubscribe = undefined
255
+ }
256
+
257
+ private syncClient(): boolean {
258
+ const nextClient = this.tryGetQueryClient()
259
+ if (!nextClient) {
260
+ this.unsubscribeObserver()
261
+ this.queryClient = undefined
262
+ this.observer = undefined
263
+ this.setResult(createPendingInfiniteQueryResult())
264
+ return false
265
+ }
266
+
267
+ if (nextClient === this.queryClient) {
268
+ return true
269
+ }
270
+
271
+ this.unsubscribeObserver()
272
+ this.queryClient = nextClient
273
+ const options = this.defaultOptions(this.queryClient)
274
+ this.observer = new InfiniteQueryObserver(this.queryClient, options)
275
+ this.setResult(this.observer.getOptimisticResult(options))
276
+ return true
277
+ }
278
+
279
+ private refreshOptions(): boolean {
280
+ if (!this.syncClient() || !this.observer || !this.queryClient) {
281
+ return false
282
+ }
283
+
284
+ const options = this.defaultOptions(this.queryClient)
285
+ this.observer.setOptions(options)
286
+ this.setResult(this.observer.getOptimisticResult(options))
287
+ return true
288
+ }
289
+
290
+ private defaultOptions(
291
+ client = this.queryClient,
292
+ ): DefaultedInfiniteQueryObserverOptions<
293
+ TQueryFnData,
294
+ TError,
295
+ TData,
296
+ TQueryKey,
297
+ TPageParam
298
+ > {
299
+ if (!client) {
300
+ throw createMissingQueryClientError()
301
+ }
302
+
303
+ const defaulted = client.defaultQueryOptions(
304
+ readAccessor(this.options),
305
+ ) as DefaultedInfiniteQueryObserverOptions<
306
+ TQueryFnData,
307
+ TError,
308
+ TData,
309
+ TQueryKey,
310
+ TPageParam
311
+ >
312
+ ;(defaulted as { _optimisticResults?: 'optimistic' })._optimisticResults =
313
+ 'optimistic'
314
+ return defaulted
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Creates a Lit reactive controller that subscribes the host to an infinite
320
+ * query.
321
+ *
322
+ * The returned accessor is callable and also exposes `current`, `refetch`,
323
+ * `fetchNextPage`, `fetchPreviousPage`, and `destroy`. When `options` is a
324
+ * function, it is re-read during host updates so query keys and options can
325
+ * follow reactive host state.
326
+ *
327
+ * If `queryClient` is omitted, the controller resolves the client from the
328
+ * nearest connected `QueryClientProvider`.
329
+ *
330
+ * @param host - The Lit reactive controller host that owns the infinite query
331
+ * subscription.
332
+ * @param options - Infinite query observer options, or a getter that returns
333
+ * options.
334
+ * @param queryClient - Optional explicit query client. Provide this for
335
+ * controllers that should not resolve a client from Lit context.
336
+ * @returns An accessor for the latest infinite query result with page helper
337
+ * methods.
338
+ *
339
+ * @example
340
+ * ```ts
341
+ * import { LitElement, html } from 'lit'
342
+ * import { createInfiniteQueryController } from '@tanstack/lit-query'
343
+ *
344
+ * class ProjectsView extends LitElement {
345
+ * private readonly projects = createInfiniteQueryController(this, {
346
+ * queryKey: ['projects'],
347
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
348
+ * initialPageParam: 0,
349
+ * getNextPageParam: (lastPage) => lastPage.nextCursor,
350
+ * })
351
+ *
352
+ * render() {
353
+ * const query = this.projects()
354
+ *
355
+ * return html`
356
+ * <button ?disabled=${!query.hasNextPage} @click=${() => this.projects.fetchNextPage()}>
357
+ * Load more
358
+ * </button>
359
+ * `
360
+ * }
361
+ * }
362
+ * ```
363
+ */
364
+ export function createInfiniteQueryController<
365
+ TQueryFnData = unknown,
366
+ TError = DefaultError,
367
+ TData = InfiniteData<TQueryFnData>,
368
+ TQueryKey extends QueryKey = QueryKey,
369
+ TPageParam = unknown,
370
+ >(
371
+ host: ReactiveControllerHost,
372
+ options: Accessor<
373
+ CreateInfiniteQueryOptions<
374
+ TQueryFnData,
375
+ TError,
376
+ TData,
377
+ TQueryKey,
378
+ TPageParam
379
+ >
380
+ >,
381
+ queryClient?: QueryClient,
382
+ ): InfiniteQueryResultAccessor<TData, TError> {
383
+ const controller = new InfiniteQueryController(host, options, queryClient)
384
+
385
+ return Object.assign(
386
+ createValueAccessor(() => controller.current),
387
+ {
388
+ refetch: controller.refetch,
389
+ fetchNextPage: controller.fetchNextPage,
390
+ fetchPreviousPage: controller.fetchPreviousPage,
391
+ destroy: () => controller.destroy(),
392
+ },
393
+ )
394
+ }