@fozy-labs/rx-toolkit 0.5.3-rc.2 → 0.5.3
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.
- package/LICENSE +21 -21
- package/README.md +143 -137
- package/dist/common/devtools/combineDevtools.js +3 -3
- package/dist/common/devtools/index.d.ts +3 -3
- package/dist/common/devtools/index.js +3 -3
- package/dist/common/devtools/reduxDevtools.d.ts +1 -1
- package/dist/common/devtools/reduxDevtools.js +17 -17
- package/dist/common/devtools/types.d.ts +0 -6
- package/dist/common/options/SharedOptions.d.ts +1 -0
- package/dist/common/options/SharedOptions.js +6 -0
- package/dist/common/options/index.d.ts +1 -1
- package/dist/common/options/index.js +1 -1
- package/dist/common/react/index.d.ts +2 -2
- package/dist/common/react/index.js +2 -2
- package/dist/common/react/useConstant.js +1 -1
- package/dist/common/utils/deepEqual.js +1 -1
- package/dist/common/utils/index.d.ts +3 -3
- package/dist/common/utils/index.js +3 -3
- package/dist/common/utils/shallowEqual.js +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/query/SKIP_TOKEN.js +1 -1
- package/dist/query/api/createCommand.d.ts +1 -1
- package/dist/query/api/createOperation.d.ts +1 -1
- package/dist/query/api/createOperation.js +1 -1
- package/dist/query/api/createResource.d.ts +1 -1
- package/dist/query/api/createResourceDuplicator.d.ts +1 -1
- package/dist/query/core/Command/Command.d.ts +7 -7
- package/dist/query/core/Command/Command.js +2 -2
- package/dist/query/core/Command/CommandAgent.d.ts +1 -1
- package/dist/query/core/Command/index.d.ts +2 -2
- package/dist/query/core/Command/index.js +2 -2
- package/dist/query/core/{Opertation → Operation}/Operation.d.ts +2 -2
- package/dist/query/core/{Opertation → Operation}/Operation.js +1 -1
- package/dist/query/core/{Opertation → Operation}/OperationAgent.d.ts +1 -1
- package/dist/query/core/{Opertation → Operation}/OperationAgent.js +1 -1
- package/dist/query/core/QueriesCache.d.ts +1 -1
- package/dist/query/core/QueriesCache.js +1 -1
- package/dist/query/core/QueriesLifetimeHooks.js +7 -7
- package/dist/query/core/Resource/Resource.d.ts +15 -15
- package/dist/query/core/Resource/Resource.js +7 -7
- package/dist/query/core/Resource/ResourceAgent.d.ts +1 -1
- package/dist/query/core/Resource/ResourceAgent.js +2 -2
- package/dist/query/core/Resource/ResourceDuplicator.d.ts +16 -16
- package/dist/query/core/Resource/ResourceDuplicator.js +18 -20
- package/dist/query/core/Resource/ResourceDuplicatorAgent.d.ts +5 -5
- package/dist/query/core/Resource/ResourceDuplicatorAgent.js +2 -2
- package/dist/query/core/Resource/ResourceRef.d.ts +2 -2
- package/dist/query/core/Resource/ResourceRef.js +12 -12
- package/dist/query/index.d.ts +11 -10
- package/dist/query/index.js +11 -10
- package/dist/query/lib/IndirectMap.js +4 -4
- package/dist/query/react/useCommandAgent.d.ts +2 -2
- package/dist/query/react/useOperationAgent.d.ts +1 -1
- package/dist/query/react/useOperationAgent.js +1 -1
- package/dist/query/react/useResourceAgent.d.ts +3 -3
- package/dist/query/react/useResourceAgent.js +1 -1
- package/dist/query/react/useResourceRef.d.ts +3 -3
- package/dist/query/react/useResourceRef.js +7 -2
- package/dist/query/types/Command.types.d.ts +1 -1
- package/dist/query/types/Operation.types.d.ts +1 -1
- package/dist/query/types/Resource.types.d.ts +7 -5
- package/dist/query/types/index.d.ts +4 -4
- package/dist/query/types/index.js +4 -4
- package/dist/query-v2/api/createApi.d.ts +10 -0
- package/dist/query-v2/api/createApi.js +83 -0
- package/dist/query-v2/core/common/CacheEntry.d.ts +29 -0
- package/dist/query-v2/core/common/CacheEntry.js +71 -0
- package/dist/query-v2/core/common/CacheMap.d.ts +38 -0
- package/dist/query-v2/core/common/CacheMap.js +127 -0
- package/dist/query-v2/core/common/LifecycleHooks.d.ts +22 -0
- package/dist/query-v2/core/common/LifecycleHooks.js +104 -0
- package/dist/query-v2/core/common/index.d.ts +3 -0
- package/dist/query-v2/core/common/index.js +3 -0
- package/dist/query-v2/core/index.d.ts +3 -0
- package/dist/query-v2/core/index.js +3 -0
- package/dist/query-v2/core/machines/Machine.d.ts +14 -0
- package/dist/query-v2/core/machines/Machine.js +33 -0
- package/dist/query-v2/core/machines/MachineError.d.ts +11 -0
- package/dist/query-v2/core/machines/MachineError.js +26 -0
- package/dist/query-v2/core/machines/MachineIdle.d.ts +8 -0
- package/dist/query-v2/core/machines/MachineIdle.js +19 -0
- package/dist/query-v2/core/machines/MachinePending.d.ts +12 -0
- package/dist/query-v2/core/machines/MachinePending.js +29 -0
- package/dist/query-v2/core/machines/MachineRefreshing.d.ts +14 -0
- package/dist/query-v2/core/machines/MachineRefreshing.js +46 -0
- package/dist/query-v2/core/machines/MachineSuccess.d.ts +16 -0
- package/dist/query-v2/core/machines/MachineSuccess.js +42 -0
- package/dist/query-v2/core/machines/MachineWithData.d.ts +18 -0
- package/dist/query-v2/core/machines/MachineWithData.js +40 -0
- package/dist/query-v2/core/machines/Patcher.d.ts +20 -0
- package/dist/query-v2/core/machines/Patcher.js +104 -0
- package/dist/query-v2/core/machines/index.d.ts +8 -0
- package/dist/query-v2/core/machines/index.js +8 -0
- package/dist/query-v2/core/resource/ResourceV2.d.ts +120 -0
- package/dist/query-v2/core/resource/ResourceV2.js +464 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.d.ts +26 -0
- package/dist/query-v2/core/resource/ResourceV2Agent.js +132 -0
- package/dist/query-v2/core/resource/index.d.ts +2 -0
- package/dist/query-v2/core/resource/index.js +2 -0
- package/dist/query-v2/index.d.ts +11 -0
- package/dist/query-v2/index.js +17 -0
- package/dist/query-v2/lib/NO_VALUE.d.ts +2 -0
- package/dist/query-v2/lib/NO_VALUE.js +1 -0
- package/dist/query-v2/lib/SKIP_TOKEN.d.ts +2 -0
- package/dist/query-v2/lib/SKIP_TOKEN.js +1 -0
- package/dist/query-v2/lib/index.d.ts +4 -0
- package/dist/query-v2/lib/index.js +3 -0
- package/dist/query-v2/lib/stableStringify.d.ts +8 -0
- package/dist/query-v2/lib/stableStringify.js +23 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.d.ts +25 -0
- package/dist/query-v2/plugins/ReactHooksPlugin.js +19 -0
- package/dist/query-v2/plugins/types.d.ts +1 -0
- package/dist/query-v2/plugins/types.js +1 -0
- package/dist/query-v2/react/__tests__/helpers.d.ts +12 -0
- package/dist/query-v2/react/__tests__/helpers.js +33 -0
- package/dist/query-v2/react/index.d.ts +2 -0
- package/dist/query-v2/react/index.js +2 -0
- package/dist/query-v2/react/useResourceV2Agent.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Agent.js +36 -0
- package/dist/query-v2/react/useResourceV2Ref.d.ts +12 -0
- package/dist/query-v2/react/useResourceV2Ref.js +57 -0
- package/dist/query-v2/snapshot/Snapshot.d.ts +13 -0
- package/dist/query-v2/snapshot/Snapshot.js +76 -0
- package/dist/query-v2/types/agent.types.d.ts +54 -0
- package/dist/query-v2/types/agent.types.js +1 -0
- package/dist/query-v2/types/api.types.d.ts +22 -0
- package/dist/query-v2/types/api.types.js +1 -0
- package/dist/query-v2/types/cache.types.d.ts +37 -0
- package/dist/query-v2/types/cache.types.js +1 -0
- package/dist/query-v2/types/index.d.ts +9 -0
- package/dist/query-v2/types/index.js +9 -0
- package/dist/query-v2/types/lifecycle.types.d.ts +25 -0
- package/dist/query-v2/types/lifecycle.types.js +1 -0
- package/dist/query-v2/types/machine.types.d.ts +67 -0
- package/dist/query-v2/types/machine.types.js +1 -0
- package/dist/query-v2/types/plugin.types.d.ts +38 -0
- package/dist/query-v2/types/plugin.types.js +1 -0
- package/dist/query-v2/types/resource.types.d.ts +35 -0
- package/dist/query-v2/types/resource.types.js +1 -0
- package/dist/query-v2/types/shared.types.d.ts +20 -0
- package/dist/query-v2/types/shared.types.js +1 -0
- package/dist/query-v2/types/snapshot.types.d.ts +21 -0
- package/dist/query-v2/types/snapshot.types.js +1 -0
- package/dist/signals/base/Batcher.js +9 -5
- package/dist/signals/base/ComputeCache.js +3 -3
- package/dist/signals/base/DependencyTracker.js +1 -1
- package/dist/signals/base/Devtools.d.ts +3 -2
- package/dist/signals/base/Devtools.js +54 -27
- package/dist/signals/base/Indexer.js +1 -1
- package/dist/signals/base/ReadonlySignal.js +1 -1
- package/dist/signals/base/SyncObservable.d.ts +1 -2
- package/dist/signals/base/SyncObservable.js +2 -5
- package/dist/signals/base/index.d.ts +6 -6
- package/dist/signals/base/index.js +6 -6
- package/dist/signals/index.d.ts +5 -4
- package/dist/signals/index.js +5 -4
- package/dist/signals/operators/index.d.ts +1 -1
- package/dist/signals/operators/index.js +1 -1
- package/dist/signals/react/index.d.ts +1 -1
- package/dist/signals/react/index.js +1 -1
- package/dist/signals/signals/Computed.d.ts +3 -4
- package/dist/signals/signals/Computed.js +18 -10
- package/dist/signals/signals/Effect.js +2 -1
- package/dist/signals/signals/LocalState.d.ts +3 -4
- package/dist/signals/signals/LocalState.js +8 -8
- package/dist/signals/signals/Signal.d.ts +7 -6
- package/dist/signals/signals/Signal.js +4 -1
- package/dist/signals/signals/State.d.ts +4 -5
- package/dist/signals/signals/State.js +23 -9
- package/dist/signals/signals/index.d.ts +5 -5
- package/dist/signals/signals/index.js +5 -6
- package/dist/signals/types/SignalOptions.d.ts +16 -0
- package/dist/signals/types/SignalOptions.js +1 -0
- package/dist/signals/types/index.d.ts +3 -1
- package/dist/signals/types/index.js +3 -1
- package/dist/signals/types/normalizeSignalOptions.d.ts +2 -0
- package/dist/signals/types/normalizeSignalOptions.js +10 -0
- package/dist/signals/types/signals.types.d.ts +2 -3
- package/docs/CHANGELOG.md +111 -90
- package/docs/CONTRIBUTING.md +230 -0
- package/docs/contributing/ai-assisted-development.md +47 -0
- package/docs/contributing/query-v2/README.md +379 -0
- package/docs/{release → contributing/release}/README.md +59 -59
- package/docs/devtools/README.md +228 -228
- package/docs/migrations/0.5.0.md +58 -58
- package/docs/migrations/query-v2.md +171 -0
- package/docs/options/README.md +92 -92
- package/docs/query/README.md +575 -573
- package/docs/query-v2/README.md +280 -0
- package/docs/query-v2/api-reference.md +235 -0
- package/docs/query-v2/optimistic-updates.md +148 -0
- package/docs/query-v2/ssr.md +130 -0
- package/docs/signals/README.md +300 -300
- package/docs/usage/react/README.md +309 -309
- package/package.json +86 -63
package/docs/query/README.md
CHANGED
|
@@ -1,573 +1,575 @@
|
|
|
1
|
-
# RxQuery
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Resources
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Commands
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Agents
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
|
97
|
-
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
|
148
|
-
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
*
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
*
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
ResourceRef
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
console.
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return <div
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
})
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
1
|
+
# RxQuery
|
|
2
|
+
|
|
3
|
+
> **Note:** Экспериментальная версия Query v2 доступна — см. [Query v2](../query-v2/README.md).
|
|
4
|
+
|
|
5
|
+
RxQuery — система для управления асинхронными запросами и кэшированием данных в RxToolkit. Она состоит из двух основных компонентов: **Resources** и **Commands**.
|
|
6
|
+
|
|
7
|
+
## Основные концепции
|
|
8
|
+
|
|
9
|
+
### Resources (Ресурсы)
|
|
10
|
+
|
|
11
|
+
Resources предназначены для реактивного кэширования повторяемых запросов. Они автоматически управляют состоянием загрузки, кэшируют результаты и обеспечивают эффективную инвалидацию данных.
|
|
12
|
+
|
|
13
|
+
**Ключевые особенности:**
|
|
14
|
+
- Автоматическое кэширование по аргументам запроса
|
|
15
|
+
- Поддержка AbortController для отмены запросов
|
|
16
|
+
- Реактивные обновления состояния
|
|
17
|
+
- Оптимистичные обновления
|
|
18
|
+
- Гибкое управление временем жизни кэша
|
|
19
|
+
|
|
20
|
+
### Commands (Команды)
|
|
21
|
+
|
|
22
|
+
Commands представляют одноразовые команды или мутации. Они не кэшируются, но предоставляют состояние выполнения и могут связываться с ресурсами для их обновления.
|
|
23
|
+
|
|
24
|
+
**Ключевые особенности:**
|
|
25
|
+
- Отслеживание состояния выполнения
|
|
26
|
+
- Связывание с ресурсами для их обновления
|
|
27
|
+
- Поддержка оптимистичных обновлений
|
|
28
|
+
- Возможность блокировки связанных ресурсов
|
|
29
|
+
- Автоматический откат при ошибках
|
|
30
|
+
|
|
31
|
+
### Agents (Агенты)
|
|
32
|
+
|
|
33
|
+
Agents представляют собой интеллектуальные обертки над ресурсами (или командами), которые обеспечивают более удобную работу с состояниями запросов для потребителей.
|
|
34
|
+
|
|
35
|
+
**Основная проблема, которую решают агенты:**
|
|
36
|
+
|
|
37
|
+
Кэш ресурсов содержит "сырые" состояния отдельных запросов, но потребителям нужна более высокоуровневая логика:
|
|
38
|
+
- `isInitialLoading` должно быть true только при первой загрузке ресурса
|
|
39
|
+
- При смене аргументов запроса нужно показывать данные предыдущего запроса, пока загружается новый
|
|
40
|
+
- Состояние загрузки должно отражать контекст использования, а не просто состояние кэша
|
|
41
|
+
|
|
42
|
+
### ResourceRef (Ссылка на ресурс)
|
|
43
|
+
|
|
44
|
+
Ref — это абстракция для взаимодействия с элементом кэша ресурса напрямую.
|
|
45
|
+
|
|
46
|
+
**Особенности:**
|
|
47
|
+
- Команды используют ref под капотом для управления связанным ресурсом
|
|
48
|
+
- Ref может ссылаться на отсутствующий элемент кэша
|
|
49
|
+
- Позволяет выполнять patch-транзакции для оптимистичных обновлений
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## API
|
|
54
|
+
|
|
55
|
+
### createResource
|
|
56
|
+
|
|
57
|
+
Создает новый ресурс для кэширования данных.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { createResource } from '@fozy-labs/rx-toolkit';
|
|
61
|
+
|
|
62
|
+
interface User {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
email: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const userResource = createResource<{ id: string }, User>({
|
|
69
|
+
async queryFn(args, tools) {
|
|
70
|
+
const response = await fetch(`/api/users/${args.id}`, {
|
|
71
|
+
signal: tools.abortSignal // Поддержка отмены запроса
|
|
72
|
+
});
|
|
73
|
+
return response.json();
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Опционально: трансформация данных
|
|
77
|
+
select: (data) => ({
|
|
78
|
+
id: data.id,
|
|
79
|
+
name: data.name,
|
|
80
|
+
email: data.email
|
|
81
|
+
}),
|
|
82
|
+
|
|
83
|
+
// Опционально: время жизни кэша (по умолчанию 60 секунд)
|
|
84
|
+
cacheLifetime: 30000, // 30 секунд
|
|
85
|
+
|
|
86
|
+
// Опционально: имя для devtools
|
|
87
|
+
devtoolsName: 'user-resource',
|
|
88
|
+
|
|
89
|
+
// Опционально: кастомное сравнение аргументов
|
|
90
|
+
compareArgsFn: (args1, args2) => args1.id === args2.id,
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Параметры createResource:**
|
|
95
|
+
|
|
96
|
+
| Параметр | Тип | Описание |
|
|
97
|
+
|----------|-----|----------|
|
|
98
|
+
| `queryFn` | `(args, tools) => Promise<Result>` | Функция выполнения запроса |
|
|
99
|
+
| `select` | `(data) => Selected` | Опциональная функция трансформации данных |
|
|
100
|
+
| `cacheLifetime` | `number \| false` | Время жизни кэша в мс (default: 60000). `false` — кэш не удаляется |
|
|
101
|
+
| `compareArgsFn` | `(args1, args2) => boolean` | Кастомная функция сравнения аргументов |
|
|
102
|
+
| `onCacheEntryAdded` | `(args, tools) => void` | Хук при добавлении элемента в кэш |
|
|
103
|
+
| `onQueryStarted` | `(args, tools) => void` | Хук при старте запроса |
|
|
104
|
+
| `devtoolsName` | `string \| false` | Имя для devtools (`false` — отключить) |
|
|
105
|
+
|
|
106
|
+
**Tools в queryFn:**
|
|
107
|
+
- `abortSignal` — AbortSignal для отмены запроса
|
|
108
|
+
|
|
109
|
+
### createCommand
|
|
110
|
+
|
|
111
|
+
Создает новую команду для выполнения мутаций.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { createCommand } from '@fozy-labs/rx-toolkit';
|
|
115
|
+
|
|
116
|
+
const updateUser = createCommand<
|
|
117
|
+
{ id: string; data: Partial<User> },
|
|
118
|
+
User
|
|
119
|
+
>({
|
|
120
|
+
async queryFn(args) {
|
|
121
|
+
const response = await fetch(`/api/users/${args.id}`, {
|
|
122
|
+
method: 'PATCH',
|
|
123
|
+
headers: { 'Content-Type': 'application/json' },
|
|
124
|
+
body: JSON.stringify(args.data)
|
|
125
|
+
});
|
|
126
|
+
return response.json();
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
// Связывание с ресурсами
|
|
130
|
+
link(add) {
|
|
131
|
+
add({
|
|
132
|
+
resource: userResource,
|
|
133
|
+
forwardArgs: (args) => ({ id: args.id }),
|
|
134
|
+
// Обновление кэша после успешного запроса
|
|
135
|
+
update({ draft, args, data }) {
|
|
136
|
+
Object.assign(draft, args.data);
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
devtoolsName: 'update-user',
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Параметры createCommand:**
|
|
146
|
+
|
|
147
|
+
| Параметр | Тип | Описание |
|
|
148
|
+
|---------------------|-----------------------------|-----------------------------------------------|
|
|
149
|
+
| `queryFn` | `(args) => Promise<Result>` | Функция выполнения команды |
|
|
150
|
+
| `select` | `(data) => Selected` | Опциональная функция трансформации результата |
|
|
151
|
+
| `link` | `(add) => void` | Функция связывания с ресурсами |
|
|
152
|
+
| `cacheLifetime` | `number \| false` | Время жизни кэша команды (default: 1000) |
|
|
153
|
+
| `onCacheEntryAdded` | `(args, tools) => void` | Хук при добавлении в кэш |
|
|
154
|
+
| `onQueryStarted` | `(args, tools) => void` | Хук при старте команды |
|
|
155
|
+
| `devtoolsName` | `string \| false` | Имя для devtools |
|
|
156
|
+
|
|
157
|
+
> **Note:** `createOperation` and `useOperationAgent` are deprecated aliases for `createCommand` and `useCommandAgent` respectively. They will be removed in v0.6.0.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Свойства Link
|
|
162
|
+
|
|
163
|
+
Link позволяет связывать команды с ресурсами для автоматического обновления кэша:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
type LinkOptions<D, RD> = {
|
|
167
|
+
/**
|
|
168
|
+
* Целевой ресурс, с которым связывается команда
|
|
169
|
+
* @required
|
|
170
|
+
*/
|
|
171
|
+
resource: ResourceInstance<RD>;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Функция для получения аргументов ресурса из аргументов команды.
|
|
175
|
+
* Используется для определения какой элемент в кэше нужно обновить
|
|
176
|
+
* @required
|
|
177
|
+
*/
|
|
178
|
+
forwardArgs: (args: D["Args"]) => RD["Args"];
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Инвалидация кэша после выполнения команды.
|
|
182
|
+
* При true — кэш будет очищен и ресурс перезагрузится
|
|
183
|
+
* @default false
|
|
184
|
+
*/
|
|
185
|
+
invalidate?: boolean;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Блокировка ресурса во время выполнения команды.
|
|
189
|
+
* При true — ресурс не сможет выполнять новые запросы
|
|
190
|
+
* @default false
|
|
191
|
+
*/
|
|
192
|
+
lock?: boolean;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Обновление кэша ПОСЛЕ успешного выполнения команды.
|
|
196
|
+
* Использует Immer для иммутабельных обновлений
|
|
197
|
+
*/
|
|
198
|
+
update?: (tools: {
|
|
199
|
+
draft: RD["Data"]; // Immer draft для мутации
|
|
200
|
+
args: D["Args"]; // Аргументы команды
|
|
201
|
+
data: D["Data"]; // Результат команды
|
|
202
|
+
}) => void | RD["Data"];
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Оптимистичное обновление ДО выполнения команды.
|
|
206
|
+
* Позволяет обновить UI немедленно
|
|
207
|
+
*/
|
|
208
|
+
optimisticUpdate?: (tools: {
|
|
209
|
+
draft: RD["Data"]; // Immer draft для мутации
|
|
210
|
+
args: D["Args"]; // Аргументы команды
|
|
211
|
+
}) => void | RD["Data"];
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Создание нового элемента в кэше.
|
|
215
|
+
* Используется когда команда создает новую сущность
|
|
216
|
+
*/
|
|
217
|
+
create?: (tools: {
|
|
218
|
+
args: D["Args"];
|
|
219
|
+
data: D["Data"];
|
|
220
|
+
}) => RD["Data"] | Promise<RD["Data"]>;
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Пример: Оптимистичные обновления
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const toggleCartItem = createCommand({
|
|
228
|
+
queryFn: async (args: { id: string; enabled: boolean }) => {
|
|
229
|
+
return fetch(`/api/cart/toggle`, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
body: JSON.stringify(args)
|
|
232
|
+
}).then(r => r.json());
|
|
233
|
+
},
|
|
234
|
+
link(add) {
|
|
235
|
+
add({
|
|
236
|
+
resource: cartResource,
|
|
237
|
+
forwardArgs: () => undefined, // Корзина без параметров
|
|
238
|
+
|
|
239
|
+
// Оптимистичное обновление — UI обновится мгновенно
|
|
240
|
+
optimisticUpdate: ({ draft, args }) => {
|
|
241
|
+
const item = draft.items.find(i => i.id === args.id);
|
|
242
|
+
if (item) {
|
|
243
|
+
item.enabled = args.enabled;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// При ошибке изменения автоматически откатятся
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Состояния запросов
|
|
255
|
+
|
|
256
|
+
### ResourceQueryState
|
|
257
|
+
|
|
258
|
+
Состояние запроса ресурса через агента:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
type ResourceQueryState<D> = {
|
|
262
|
+
/** Инициализирован ли хотя бы один запрос */
|
|
263
|
+
isInitiated: boolean;
|
|
264
|
+
|
|
265
|
+
/** Любая загрузка (первая или повторная) */
|
|
266
|
+
isLoading: boolean;
|
|
267
|
+
|
|
268
|
+
/** Первая загрузка (данных еще не было) */
|
|
269
|
+
isInitialLoading: boolean;
|
|
270
|
+
|
|
271
|
+
/** Перезагрузка (данные уже есть) */
|
|
272
|
+
isReloading: boolean;
|
|
273
|
+
|
|
274
|
+
/** Завершен ли запрос */
|
|
275
|
+
isDone: boolean;
|
|
276
|
+
|
|
277
|
+
/** Успешно ли завершен последний запрос */
|
|
278
|
+
isSuccess: boolean;
|
|
279
|
+
|
|
280
|
+
/** Произошла ли ошибка последнего запроса */
|
|
281
|
+
isError: boolean;
|
|
282
|
+
|
|
283
|
+
/** Заблокирован ли ресурс командой */
|
|
284
|
+
isLocked: boolean;
|
|
285
|
+
|
|
286
|
+
/** Оригинал ошибки, если есть */
|
|
287
|
+
error: unknown | undefined;
|
|
288
|
+
|
|
289
|
+
/** Данные (или select данных) */
|
|
290
|
+
data: D["Data"] | undefined;
|
|
291
|
+
|
|
292
|
+
/** Аргументы последнего запроса */
|
|
293
|
+
args: D["Args"] | undefined;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### CommandQueryState
|
|
298
|
+
|
|
299
|
+
Состояние выполнения команды:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
type CommandQueryState<D> = {
|
|
303
|
+
isInitiated: boolean;
|
|
304
|
+
isLoading: boolean;
|
|
305
|
+
isDone: boolean;
|
|
306
|
+
isSuccess: boolean;
|
|
307
|
+
isError: boolean;
|
|
308
|
+
error: unknown | undefined;
|
|
309
|
+
data: D["Data"] | undefined;
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## ResourceRef API
|
|
316
|
+
|
|
317
|
+
ResourceRef предоставляет низкоуровневый доступ к элементу кэша:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
type ResourceRefInstance<D> = {
|
|
321
|
+
/** Проверка наличия элемента в кэше */
|
|
322
|
+
get has(): boolean;
|
|
323
|
+
|
|
324
|
+
/** Блокировка ресурса (возвращает функцию разблокировки) */
|
|
325
|
+
lock(): { unlock: () => void };
|
|
326
|
+
|
|
327
|
+
/** Снятие одной блокировки */
|
|
328
|
+
unlockOne(): void;
|
|
329
|
+
|
|
330
|
+
/** Patch-транзакция для изменения данных */
|
|
331
|
+
patch(patchFn: (data: D['Data']) => void): ResourceTransaction | null;
|
|
332
|
+
|
|
333
|
+
/** Инвалидация (очистка) кэша */
|
|
334
|
+
invalidate(): void;
|
|
335
|
+
|
|
336
|
+
/** Создание элемента в кэше с данными */
|
|
337
|
+
create(data: D['Data']): void;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Patch-транзакции
|
|
342
|
+
|
|
343
|
+
Транзакции позволяют делать изменения с возможностью отката:
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
type ResourceTransaction = {
|
|
347
|
+
patches: ImmerPatch[] // Патчи изменений
|
|
348
|
+
inversePatches: ImmerPatch[] // Патчи для отката
|
|
349
|
+
status: 'pending' | 'committed' | 'aborted'
|
|
350
|
+
abort(): void // Откатить изменения
|
|
351
|
+
commit(): void // Подтвердить изменения
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Пример использования транзакций:**
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { useResourceRef } from '@fozy-labs/rx-toolkit';
|
|
359
|
+
|
|
360
|
+
function TodoList() {
|
|
361
|
+
const todoRef = useResourceRef(todoResource, undefined);
|
|
362
|
+
const [pendingChanges, setPendingChanges] = useState([]);
|
|
363
|
+
|
|
364
|
+
const handleToggle = (itemId: number) => {
|
|
365
|
+
const transaction = todoRef.patch((draft) => {
|
|
366
|
+
const item = draft.items.find(i => i.id === itemId);
|
|
367
|
+
if (item) item.completed = !item.completed;
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (transaction) {
|
|
371
|
+
setPendingChanges(prev => [...prev, {
|
|
372
|
+
id: itemId,
|
|
373
|
+
transaction
|
|
374
|
+
}]);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const commitChange = (id: number) => {
|
|
379
|
+
const change = pendingChanges.find(c => c.id === id);
|
|
380
|
+
change?.transaction.commit();
|
|
381
|
+
setPendingChanges(prev => prev.filter(c => c.id !== id));
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
const abortChange = (id: number) => {
|
|
385
|
+
const change = pendingChanges.find(c => c.id === id);
|
|
386
|
+
change?.transaction.abort(); // Данные вернутся к исходным
|
|
387
|
+
setPendingChanges(prev => prev.filter(c => c.id !== id));
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Lifecycle хуки
|
|
395
|
+
|
|
396
|
+
### onCacheEntryAdded
|
|
397
|
+
|
|
398
|
+
Вызывается при добавлении нового элемента в кэш:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
const userResource = createResource({
|
|
402
|
+
queryFn: fetchUser,
|
|
403
|
+
|
|
404
|
+
onCacheEntryAdded(args, { $cacheDataLoaded, $cacheEntryRemoved, dataChanged$ }) {
|
|
405
|
+
// args — аргументы запроса
|
|
406
|
+
|
|
407
|
+
// Ожидание первой загрузки данных
|
|
408
|
+
$cacheDataLoaded.then(() => {
|
|
409
|
+
console.log('Данные загружены в кэш');
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Ожидание удаления из кэша
|
|
413
|
+
$cacheEntryRemoved.then(() => {
|
|
414
|
+
console.log('Элемент удален из кэша');
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Подписка на изменения данных
|
|
418
|
+
const sub = dataChanged$.subscribe(data => {
|
|
419
|
+
console.log('Данные изменились:', data);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### onQueryStarted
|
|
426
|
+
|
|
427
|
+
Вызывается при старте каждого запроса:
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
const userResource = createResource({
|
|
431
|
+
queryFn: fetchUser,
|
|
432
|
+
|
|
433
|
+
async onQueryStarted(args, { $queryFulfilled }) {
|
|
434
|
+
console.log('Запрос начат с аргументами:', args);
|
|
435
|
+
|
|
436
|
+
const result = await $queryFulfilled;
|
|
437
|
+
|
|
438
|
+
if (result.isError) {
|
|
439
|
+
console.error('Ошибка запроса:', result.error);
|
|
440
|
+
} else {
|
|
441
|
+
console.log('Запрос успешен:', result.data);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Утилиты
|
|
450
|
+
|
|
451
|
+
### resetAllQueriesCache
|
|
452
|
+
|
|
453
|
+
Сбрасывает кэш всех ресурсов в приложении:
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
import { resetAllQueriesCache } from '@fozy-labs/rx-toolkit';
|
|
457
|
+
|
|
458
|
+
function LogoutButton() {
|
|
459
|
+
const handleLogout = () => {
|
|
460
|
+
// Очистить все кэшированные данные при выходе
|
|
461
|
+
resetAllQueriesCache();
|
|
462
|
+
navigate('/login');
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
return <button onClick={handleLogout}>Выйти</button>;
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### SKIP токен
|
|
470
|
+
|
|
471
|
+
Используется для условного пропуска запроса:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
import { useResourceAgent, SKIP } from '@fozy-labs/rx-toolkit';
|
|
475
|
+
|
|
476
|
+
function UserProfile({ userId }: { userId: string | null }) {
|
|
477
|
+
// Запрос будет выполнен только если userId не null
|
|
478
|
+
const userQuery = useResourceAgent(
|
|
479
|
+
userResource,
|
|
480
|
+
userId ? { id: userId } : SKIP
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
if (!userId) return <div>Выберите пользователя</div>;
|
|
484
|
+
if (userQuery.isLoading) return <div>Загрузка...</div>;
|
|
485
|
+
|
|
486
|
+
return <div>{userQuery.data?.name}</div>;
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Примеры
|
|
493
|
+
|
|
494
|
+
### Корзина покупок с оптимистичными обновлениями
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
import { createResource, createCommand, useResourceAgent, useCommandAgent } from '@fozy-labs/rx-toolkit';
|
|
498
|
+
|
|
499
|
+
const cartResource = createResource({
|
|
500
|
+
queryFn: () => fetch('/api/cart').then(r => r.json()),
|
|
501
|
+
devtoolsName: 'cart'
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
const toggleCartItem = createCommand({
|
|
505
|
+
queryFn: (args: { id: string; enabled: boolean }) =>
|
|
506
|
+
fetch('/api/cart/toggle', {
|
|
507
|
+
method: 'POST',
|
|
508
|
+
body: JSON.stringify(args)
|
|
509
|
+
}).then(r => r.json()),
|
|
510
|
+
|
|
511
|
+
link(add) {
|
|
512
|
+
add({
|
|
513
|
+
resource: cartResource,
|
|
514
|
+
forwardArgs: () => undefined,
|
|
515
|
+
optimisticUpdate: ({ draft, args }) => {
|
|
516
|
+
const item = draft.items.find(i => i.id === args.id);
|
|
517
|
+
if (item) item.enabled = args.enabled;
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
function ShoppingCart() {
|
|
524
|
+
const cartQuery = useResourceAgent(cartResource, undefined);
|
|
525
|
+
const [toggleItem, toggleState] = useCommandAgent(toggleCartItem);
|
|
526
|
+
|
|
527
|
+
return (
|
|
528
|
+
<div>
|
|
529
|
+
{cartQuery.data?.items.map(item => (
|
|
530
|
+
<div key={item.id}>
|
|
531
|
+
<span>{item.name}</span>
|
|
532
|
+
<button onClick={() => toggleItem({
|
|
533
|
+
id: item.id,
|
|
534
|
+
enabled: !item.enabled
|
|
535
|
+
})}>
|
|
536
|
+
{item.enabled ? 'Убрать' : 'Добавить'}
|
|
537
|
+
</button>
|
|
538
|
+
</div>
|
|
539
|
+
))}
|
|
540
|
+
</div>
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Зависимые запросы
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
const userResource = createResource({
|
|
549
|
+
queryFn: (args: { id: number }) => fetch(`/api/users/${args.id}`).then(r => r.json()),
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
const userStatsResource = createResource({
|
|
553
|
+
queryFn: (args: { userId: number; period: string }) =>
|
|
554
|
+
fetch(`/api/users/${args.userId}/stats?period=${args.period}`).then(r => r.json()),
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
function UserDashboard({ userId }: { userId: number }) {
|
|
558
|
+
const [period, setPeriod] = useState('daily');
|
|
559
|
+
|
|
560
|
+
const userQuery = useResourceAgent(userResource, { id: userId });
|
|
561
|
+
|
|
562
|
+
// Запрос статистики выполняется только после загрузки пользователя
|
|
563
|
+
const statsQuery = useResourceAgent(
|
|
564
|
+
userStatsResource,
|
|
565
|
+
userQuery.isSuccess ? { userId, period } : SKIP
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
// ...
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## React интеграция
|
|
573
|
+
|
|
574
|
+
См. [React интеграция](../usage/react/README.md) для подробной информации о React хуках.
|
|
575
|
+
|