@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,361 @@
1
+ import {
2
+ MutationObserver,
3
+ type DefaultError,
4
+ type MutateOptions,
5
+ type MutationObserverOptions,
6
+ type MutationObserverResult,
7
+ } from '@tanstack/query-core'
8
+ import type { QueryClient } from '@tanstack/query-core'
9
+ import type { ReactiveControllerHost } from 'lit'
10
+ import {
11
+ createValueAccessor,
12
+ readAccessor,
13
+ type Accessor,
14
+ type ValueAccessor,
15
+ } from './accessor.js'
16
+ import { createMissingQueryClientError } from './context.js'
17
+ import { BaseController } from './controllers/BaseController.js'
18
+
19
+ /**
20
+ * Options accepted by `createMutationController`.
21
+ *
22
+ * This is the Lit adapter shape for `MutationObserverOptions`. Pass it directly
23
+ * or through an `Accessor` when the options depend on Lit host state.
24
+ */
25
+ export type CreateMutationOptions<
26
+ TData = unknown,
27
+ TError = DefaultError,
28
+ TVariables = void,
29
+ TOnMutateResult = unknown,
30
+ > = MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>
31
+
32
+ /**
33
+ * Accessor returned by `createMutationController`.
34
+ *
35
+ * Call the accessor or read its `current` property to get the latest mutation
36
+ * result. The attached methods delegate to the active mutation observer.
37
+ */
38
+ export type MutationResultAccessor<TData, TError, TVariables, TOnMutateResult> =
39
+ ValueAccessor<
40
+ MutationObserverResult<TData, TError, TVariables, TOnMutateResult>
41
+ > & {
42
+ /**
43
+ * Starts the mutation and swallows the returned promise.
44
+ *
45
+ * Throws synchronously if no `QueryClient` can be resolved.
46
+ */
47
+ mutate: (
48
+ variables: TVariables,
49
+ options?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,
50
+ ) => void
51
+ /**
52
+ * Starts the mutation and returns the observer promise.
53
+ *
54
+ * Rejects if no `QueryClient` can be resolved.
55
+ */
56
+ mutateAsync: MutationObserverResult<
57
+ TData,
58
+ TError,
59
+ TVariables,
60
+ TOnMutateResult
61
+ >['mutate']
62
+ /** Resets the mutation observer to its idle state. */
63
+ reset: MutationObserverResult<
64
+ TData,
65
+ TError,
66
+ TVariables,
67
+ TOnMutateResult
68
+ >['reset']
69
+ /** Removes the controller from its Lit host and unsubscribes observers. */
70
+ destroy: () => void
71
+ }
72
+
73
+ function createIdleMutationResult<
74
+ TData,
75
+ TError,
76
+ TVariables,
77
+ TOnMutateResult,
78
+ >(): MutationObserverResult<TData, TError, TVariables, TOnMutateResult> {
79
+ return {
80
+ context: undefined,
81
+ data: undefined,
82
+ error: null,
83
+ failureCount: 0,
84
+ failureReason: null,
85
+ isError: false,
86
+ isIdle: true,
87
+ isPending: false,
88
+ isPaused: false,
89
+ isSuccess: false,
90
+ status: 'idle',
91
+ submittedAt: 0,
92
+ variables: undefined,
93
+ mutate: (() =>
94
+ Promise.reject(
95
+ createMissingQueryClientError(),
96
+ )) as MutationObserverResult<
97
+ TData,
98
+ TError,
99
+ TVariables,
100
+ TOnMutateResult
101
+ >['mutate'],
102
+ reset: (() => undefined) as MutationObserverResult<
103
+ TData,
104
+ TError,
105
+ TVariables,
106
+ TOnMutateResult
107
+ >['reset'],
108
+ } as MutationObserverResult<TData, TError, TVariables, TOnMutateResult>
109
+ }
110
+
111
+ class MutationController<
112
+ TData,
113
+ TError,
114
+ TVariables,
115
+ TOnMutateResult,
116
+ > extends BaseController<
117
+ MutationObserverResult<TData, TError, TVariables, TOnMutateResult>
118
+ > {
119
+ private readonly options: Accessor<
120
+ CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>
121
+ >
122
+ private observer:
123
+ | MutationObserver<TData, TError, TVariables, TOnMutateResult>
124
+ | undefined
125
+ private unsubscribe: (() => void) | undefined
126
+ private queryClient: QueryClient | undefined
127
+
128
+ constructor(
129
+ host: ReactiveControllerHost,
130
+ options: Accessor<
131
+ CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>
132
+ >,
133
+ queryClient?: QueryClient,
134
+ ) {
135
+ super(host, createIdleMutationResult(), queryClient)
136
+ this.options = options
137
+
138
+ if (!queryClient) {
139
+ return
140
+ }
141
+
142
+ if (typeof options === 'function') {
143
+ return
144
+ }
145
+
146
+ const observer = new MutationObserver(
147
+ queryClient,
148
+ this.defaultOptions(queryClient),
149
+ )
150
+ this.queryClient = queryClient
151
+ this.observer = observer
152
+ this.result = observer.getCurrentResult()
153
+ }
154
+
155
+ protected onConnected(): void {
156
+ if (!this.syncClient()) {
157
+ return
158
+ }
159
+
160
+ this.refreshOptions()
161
+ this.subscribe()
162
+ if (this.observer) {
163
+ this.setResult(this.observer.getCurrentResult())
164
+ }
165
+ }
166
+
167
+ protected onDisconnected(): void {
168
+ this.unsubscribeObserver()
169
+ this.syncClient()
170
+ }
171
+
172
+ protected onHostUpdate(): void {
173
+ if (typeof this.options !== 'function') {
174
+ return
175
+ }
176
+
177
+ this.refreshOptions()
178
+ }
179
+
180
+ protected onQueryClientChanged(): void {
181
+ if (!this.syncClient() || !this.connectedState) {
182
+ return
183
+ }
184
+
185
+ this.refreshOptions()
186
+ this.subscribe()
187
+ if (this.observer) {
188
+ this.setResult(this.observer.getCurrentResult())
189
+ }
190
+ }
191
+
192
+ mutate = (
193
+ variables: TVariables,
194
+ mutateOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,
195
+ ): void => {
196
+ if (!this.syncClient() || !this.observer) {
197
+ throw createMissingQueryClientError()
198
+ }
199
+
200
+ void this.observer.mutate(variables, mutateOptions).catch(() => {
201
+ // Intentionally swallow in sync mutate path.
202
+ })
203
+ }
204
+
205
+ mutateAsync: MutationObserverResult<
206
+ TData,
207
+ TError,
208
+ TVariables,
209
+ TOnMutateResult
210
+ >['mutate'] = (...args) => {
211
+ if (!this.syncClient() || !this.observer) {
212
+ return Promise.reject(createMissingQueryClientError())
213
+ }
214
+
215
+ return this.observer.mutate(...args)
216
+ }
217
+
218
+ reset: MutationObserverResult<
219
+ TData,
220
+ TError,
221
+ TVariables,
222
+ TOnMutateResult
223
+ >['reset'] = () => {
224
+ if (!this.syncClient() || !this.observer) {
225
+ return
226
+ }
227
+
228
+ this.observer.reset()
229
+ this.setResult(this.observer.getCurrentResult())
230
+ }
231
+
232
+ private subscribe(): void {
233
+ if (!this.observer) {
234
+ return
235
+ }
236
+
237
+ if (this.unsubscribe) {
238
+ return
239
+ }
240
+
241
+ this.unsubscribe = this.observer.subscribe((next) => {
242
+ this.setResult(next)
243
+ })
244
+ }
245
+
246
+ private unsubscribeObserver(): void {
247
+ this.unsubscribe?.()
248
+ this.unsubscribe = undefined
249
+ }
250
+
251
+ private syncClient(): boolean {
252
+ const nextClient = this.tryGetQueryClient()
253
+ if (!nextClient) {
254
+ this.unsubscribeObserver()
255
+ this.queryClient = undefined
256
+ this.observer = undefined
257
+ this.setResult(createIdleMutationResult())
258
+ return false
259
+ }
260
+
261
+ if (nextClient === this.queryClient) {
262
+ return true
263
+ }
264
+
265
+ this.unsubscribeObserver()
266
+ this.queryClient = nextClient
267
+ this.observer = new MutationObserver(
268
+ this.queryClient,
269
+ this.defaultOptions(this.queryClient),
270
+ )
271
+ this.setResult(this.observer.getCurrentResult())
272
+ return true
273
+ }
274
+
275
+ private refreshOptions(): boolean {
276
+ if (!this.syncClient() || !this.observer || !this.queryClient) {
277
+ return false
278
+ }
279
+
280
+ this.observer.setOptions(this.defaultOptions())
281
+ this.setResult(this.observer.getCurrentResult())
282
+ return true
283
+ }
284
+
285
+ private defaultOptions(
286
+ client = this.queryClient,
287
+ ): MutationObserverOptions<TData, TError, TVariables, TOnMutateResult> {
288
+ if (!client) {
289
+ throw createMissingQueryClientError()
290
+ }
291
+
292
+ return client.defaultMutationOptions(readAccessor(this.options))
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Creates a Lit reactive controller that subscribes the host to a mutation.
298
+ *
299
+ * The returned accessor is callable and also exposes `current`, `mutate`,
300
+ * `mutateAsync`, `reset`, and `destroy`. When `options` is a function, it is
301
+ * re-read during host updates so mutation options can follow reactive host
302
+ * state.
303
+ *
304
+ * If `queryClient` is omitted, the controller resolves the client from the
305
+ * nearest connected `QueryClientProvider`.
306
+ *
307
+ * @param host - The Lit reactive controller host that owns the mutation
308
+ * subscription.
309
+ * @param options - Mutation observer options, or a getter that returns options.
310
+ * @param queryClient - Optional explicit query client. Provide this for
311
+ * controllers that should not resolve a client from Lit context.
312
+ * @returns An accessor for the latest mutation result with mutation helper
313
+ * methods.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * import { LitElement, html } from 'lit'
318
+ * import { createMutationController } from '@tanstack/lit-query'
319
+ *
320
+ * class AddTodoForm extends LitElement {
321
+ * private readonly addTodo = createMutationController(this, {
322
+ * mutationFn: (title: string) =>
323
+ * fetch('/api/todos', { method: 'POST', body: JSON.stringify({ title }) }),
324
+ * })
325
+ *
326
+ * render() {
327
+ * const mutation = this.addTodo()
328
+ *
329
+ * return html`
330
+ * <button ?disabled=${mutation.isPending} @click=${() => this.addTodo.mutate('Ship docs')}>
331
+ * Add todo
332
+ * </button>
333
+ * `
334
+ * }
335
+ * }
336
+ * ```
337
+ */
338
+ export function createMutationController<
339
+ TData = unknown,
340
+ TError = DefaultError,
341
+ TVariables = void,
342
+ TOnMutateResult = unknown,
343
+ >(
344
+ host: ReactiveControllerHost,
345
+ options: Accessor<
346
+ CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>
347
+ >,
348
+ queryClient?: QueryClient,
349
+ ): MutationResultAccessor<TData, TError, TVariables, TOnMutateResult> {
350
+ const controller = new MutationController(host, options, queryClient)
351
+
352
+ return Object.assign(
353
+ createValueAccessor(() => controller.current),
354
+ {
355
+ mutate: controller.mutate,
356
+ mutateAsync: controller.mutateAsync,
357
+ reset: controller.reset,
358
+ destroy: () => controller.destroy(),
359
+ },
360
+ )
361
+ }