@effect-app/vue 1.26.1 → 1.26.4
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/CHANGELOG.md +25 -0
- package/_cjs/index.cjs +22 -13
- package/_cjs/index.cjs.map +1 -1
- package/_cjs/internal.cjs +3 -1
- package/_cjs/internal.cjs.map +1 -1
- package/_cjs/lib.cjs +26 -0
- package/_cjs/lib.cjs.map +1 -0
- package/_cjs/makeClient.cjs +5 -84
- package/_cjs/makeClient.cjs.map +1 -1
- package/_cjs/makeClient2.cjs +8 -101
- package/_cjs/makeClient2.cjs.map +1 -1
- package/_cjs/mutate.cjs +41 -4
- package/_cjs/mutate.cjs.map +1 -1
- package/_cjs/mutate2.cjs +1 -1
- package/_cjs/mutate2.cjs.map +1 -1
- package/_cjs/query.cjs +26 -3
- package/_cjs/query.cjs.map +1 -1
- package/_cjs/query2.cjs +4 -26
- package/_cjs/query2.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/internal.d.ts +3 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -2
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +15 -0
- package/dist/makeClient.d.ts +1 -23
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +3 -68
- package/dist/makeClient2.d.ts +19 -73
- package/dist/makeClient2.d.ts.map +1 -1
- package/dist/makeClient2.js +6 -86
- package/dist/mutate.d.ts +9 -1
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +29 -5
- package/dist/mutate2.d.ts +4 -8
- package/dist/mutate2.d.ts.map +1 -1
- package/dist/mutate2.js +2 -2
- package/dist/query.d.ts +5 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +31 -5
- package/dist/query2.d.ts +4 -11
- package/dist/query2.d.ts.map +1 -1
- package/dist/query2.js +5 -27
- package/package.json +14 -4
- package/src/index.ts +3 -1
- package/src/internal.ts +1 -1
- package/src/lib.ts +29 -0
- package/src/makeClient.ts +4 -115
- package/src/makeClient2.ts +27 -183
- package/src/mutate.ts +37 -4
- package/src/mutate2.ts +11 -17
- package/src/query.ts +48 -8
- package/src/query2.ts +11 -57
- package/dist/hooks.d.ts +0 -3
- package/dist/index.d.ts +0 -7
- package/dist/makeContext.d.ts +0 -5
- package/vitest.config.ts.timestamp-1711656440837-d04458a029af.mjs +0 -37
- package/vitest.config.ts.timestamp-1711724061890-e8772f088aa0d.mjs +0 -37
- package/vitest.config.ts.timestamp-1711743471018-f8eca63460d15.mjs +0 -37
- package/vitest.config.ts.timestamp-1711743489536-332f6bf4f074c.mjs +0 -37
- package/vitest.config.ts.timestamp-1711744615240-85d4d02f24414.mjs +0 -37
package/src/makeClient2.ts
CHANGED
|
@@ -1,62 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { flow, pipe, tuple } from "@effect-app/core/Function"
|
|
3
|
-
import type { MutationResult } from "@effect-app/vue"
|
|
4
|
-
import { Result } from "@effect-app/vue"
|
|
5
3
|
import * as Sentry from "@sentry/browser"
|
|
6
|
-
import {
|
|
7
|
-
import { Array, Cause, Effect, Exit, Match, Option, S } from "effect-app"
|
|
8
|
-
import { type SupportedErrors } from "effect-app/client"
|
|
4
|
+
import { Cause, Effect, Exit, Match, Option, S } from "effect-app"
|
|
9
5
|
import { Failure, Success } from "effect-app/Operations"
|
|
10
6
|
import { dropUndefinedT } from "effect-app/utils"
|
|
11
7
|
import { computed, type ComputedRef } from "vue"
|
|
8
|
+
import type { Opts, ResponseErrors } from "./makeClient.js"
|
|
12
9
|
import type { MakeIntlReturn } from "./makeIntl.js"
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* Use this after handling an error yourself, still continueing on the Error track, but the error will not be reported.
|
|
17
|
-
*/
|
|
18
|
-
export class SuppressErrors extends Cause.YieldableError {
|
|
19
|
-
readonly _tag = "SuppressErrors"
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type ResponseErrors = S.ParseResult.ParseError | SupportedErrors | SuppressErrors
|
|
23
|
-
|
|
24
|
-
export function pauseWhileProcessing(
|
|
25
|
-
iv: Pausable,
|
|
26
|
-
pmf: () => Promise<unknown>
|
|
27
|
-
) {
|
|
28
|
-
return Promise
|
|
29
|
-
.resolve(iv.pause())
|
|
30
|
-
.then(() => pmf())
|
|
31
|
-
.finally(() => iv.resume())
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function useIntervalPauseWhileProcessing(
|
|
35
|
-
pmf: () => Promise<unknown>,
|
|
36
|
-
interval?: MaybeRefOrGetter<number>,
|
|
37
|
-
options?: Omit<UseIntervalFnOptions, "immediateCallback">
|
|
38
|
-
) {
|
|
39
|
-
const iv = useIntervalFn(
|
|
40
|
-
() => pauseWhileProcessing(iv, pmf),
|
|
41
|
-
interval,
|
|
42
|
-
options ? { ...options, immediateCallback: false } : options
|
|
43
|
-
)
|
|
44
|
-
return {
|
|
45
|
-
isActive: iv.isActive
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface Opts<A> extends MutationOptions {
|
|
50
|
-
suppressErrorToast?: boolean
|
|
51
|
-
suppressSuccessToast?: boolean
|
|
52
|
-
successToast?: (a: A) => any
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface Res<A, E> {
|
|
56
|
-
readonly loading: boolean
|
|
57
|
-
readonly data: A | undefined
|
|
58
|
-
readonly error: E | undefined
|
|
59
|
-
}
|
|
10
|
+
import { mutationResultToVue } from "./mutate.js"
|
|
11
|
+
import type { Res } from "./mutate.js"
|
|
12
|
+
import type { MakeMutation2 } from "./mutate2.js"
|
|
60
13
|
|
|
61
14
|
type WithAction<A> = A & {
|
|
62
15
|
action: string
|
|
@@ -74,33 +27,6 @@ type ActResp<E, A, R> = readonly [
|
|
|
74
27
|
WithAction<() => Effect<A, E, R>>
|
|
75
28
|
]
|
|
76
29
|
|
|
77
|
-
export function mutationResultToVue<A, E>(
|
|
78
|
-
mutationResult: MutationResult<A, E>
|
|
79
|
-
): Res<A, E> {
|
|
80
|
-
switch (mutationResult._tag) {
|
|
81
|
-
case "Loading": {
|
|
82
|
-
return { loading: true, data: undefined, error: undefined }
|
|
83
|
-
}
|
|
84
|
-
case "Success": {
|
|
85
|
-
return {
|
|
86
|
-
loading: false,
|
|
87
|
-
data: mutationResult.data,
|
|
88
|
-
error: undefined
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
case "Error": {
|
|
92
|
-
return {
|
|
93
|
-
loading: false,
|
|
94
|
-
data: undefined,
|
|
95
|
-
error: mutationResult.error
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
case "Initial": {
|
|
99
|
-
return { loading: false, data: undefined, error: undefined }
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
30
|
export const makeClient2 = <Locale extends string, R>(
|
|
105
31
|
useIntl: MakeIntlReturn<Locale>["useIntl"],
|
|
106
32
|
useToast: () => {
|
|
@@ -271,19 +197,13 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
271
197
|
* Returns a tuple with state ref and execution function which reports errors as Toast.
|
|
272
198
|
*/
|
|
273
199
|
const useAndHandleMutation: {
|
|
274
|
-
<I, E extends ResponseErrors, A, R>(
|
|
275
|
-
self:
|
|
276
|
-
handler: (i: I) => Effect<A, E, R>
|
|
277
|
-
name: string
|
|
278
|
-
},
|
|
200
|
+
<I, E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
201
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
279
202
|
action: string,
|
|
280
203
|
options?: Opts<A>
|
|
281
204
|
): Resp<I, A, E, R>
|
|
282
|
-
<E extends ResponseErrors, A, R>(
|
|
283
|
-
self:
|
|
284
|
-
handler: Effect<A, E, R>
|
|
285
|
-
name: string
|
|
286
|
-
},
|
|
205
|
+
<E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
206
|
+
self: RequestHandler<A, E, R, Request>,
|
|
287
207
|
action: string,
|
|
288
208
|
options?: Opts<A>
|
|
289
209
|
): ActResp<E, A, R>
|
|
@@ -291,6 +211,7 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
291
211
|
const handleRequestWithToast = useHandleRequestWithToast()
|
|
292
212
|
const [a, b] = useSafeMutation(
|
|
293
213
|
{
|
|
214
|
+
...self,
|
|
294
215
|
handler: Effect.isEffect(self.handler)
|
|
295
216
|
? (pipe(
|
|
296
217
|
Effect.annotateCurrentSpan({ action }),
|
|
@@ -300,8 +221,7 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
300
221
|
pipe(
|
|
301
222
|
Effect.annotateCurrentSpan({ action }),
|
|
302
223
|
Effect.andThen(self.handler(...args))
|
|
303
|
-
)
|
|
304
|
-
name: self.name
|
|
224
|
+
)
|
|
305
225
|
},
|
|
306
226
|
dropUndefinedT({
|
|
307
227
|
queryInvalidation: options?.queryInvalidation
|
|
@@ -319,37 +239,27 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
319
239
|
) {
|
|
320
240
|
return ((self: any, action: any, options: any) => {
|
|
321
241
|
return useAndHandleMutation(
|
|
322
|
-
|
|
323
|
-
handler: self.handler,
|
|
324
|
-
name: self.name
|
|
325
|
-
},
|
|
242
|
+
self,
|
|
326
243
|
action,
|
|
327
244
|
{ ...defaultOptions, ...options }
|
|
328
245
|
)
|
|
329
246
|
}) as {
|
|
330
|
-
<I, E extends ResponseErrors, A, R>(
|
|
331
|
-
self:
|
|
332
|
-
handler: (i: I) => Effect<A, E, R>
|
|
333
|
-
name: string
|
|
334
|
-
},
|
|
247
|
+
<I, E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
248
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
335
249
|
action: string,
|
|
336
250
|
options?: Opts<A>
|
|
337
251
|
): Resp<I, A, E, R>
|
|
338
|
-
<E extends ResponseErrors, A>(
|
|
339
|
-
self:
|
|
340
|
-
handler: Effect<A, E, R>
|
|
341
|
-
name: string
|
|
342
|
-
},
|
|
252
|
+
<E extends ResponseErrors, A, Request extends S.TaggedRequest.Any>(
|
|
253
|
+
self: RequestHandler<A, E, R, Request>,
|
|
343
254
|
action: string,
|
|
344
255
|
options?: Opts<A>
|
|
345
256
|
): ActResp<E, A, R>
|
|
346
257
|
}
|
|
347
258
|
}
|
|
348
259
|
|
|
349
|
-
const useSafeMutationWithState = <I, E, A>(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}) => {
|
|
260
|
+
const useSafeMutationWithState = <I, E, A, Request extends S.TaggedRequest.Any>(
|
|
261
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>
|
|
262
|
+
) => {
|
|
353
263
|
const [a, b] = useSafeMutation(self)
|
|
354
264
|
|
|
355
265
|
return tuple(
|
|
@@ -366,80 +276,14 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
366
276
|
}
|
|
367
277
|
}
|
|
368
278
|
|
|
369
|
-
export
|
|
370
|
-
<
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
name: string
|
|
374
|
-
mapPath: (i: I) => string
|
|
375
|
-
},
|
|
376
|
-
map: (i: I) => (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
377
|
-
): {
|
|
378
|
-
handler: (i: I) => Effect<A2, E2, R2>
|
|
379
|
-
name: string
|
|
380
|
-
mapPath: (i: I) => string
|
|
381
|
-
}
|
|
382
|
-
<E, A, R, E2, A2, R2>(
|
|
383
|
-
self: {
|
|
384
|
-
handler: Effect<A, E, R>
|
|
385
|
-
name: string
|
|
386
|
-
mapPath: string
|
|
387
|
-
},
|
|
388
|
-
map: (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
389
|
-
): {
|
|
390
|
-
handler: Effect<A2, E2, R2>
|
|
391
|
-
name: string
|
|
392
|
-
mapPath: string
|
|
393
|
-
}
|
|
394
|
-
} = (self: any, map: any): any => ({
|
|
395
|
-
...self,
|
|
396
|
-
handler: typeof self.handler === "function"
|
|
397
|
-
? (i: any) => map(i)((self.handler as (i: any) => Effect<any, any, any>)(i))
|
|
398
|
-
: map(self.handler)
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
export function composeQueries<
|
|
402
|
-
R extends Record<string, Result.Result<any, any>>
|
|
403
|
-
>(
|
|
404
|
-
results: R,
|
|
405
|
-
renderPreviousOnFailure?: boolean
|
|
406
|
-
): Result.Result<
|
|
407
|
-
{
|
|
408
|
-
[Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
|
|
409
|
-
: never
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
[Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
|
|
413
|
-
: never
|
|
414
|
-
}[keyof R]
|
|
415
|
-
> {
|
|
416
|
-
const values = renderPreviousOnFailure
|
|
417
|
-
? Object.values(results).map(orPrevious)
|
|
418
|
-
: Object.values(results)
|
|
419
|
-
const error = values.find(Result.isFailure)
|
|
420
|
-
if (error) {
|
|
421
|
-
return error
|
|
422
|
-
}
|
|
423
|
-
const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
|
|
424
|
-
if (initial.value !== undefined) {
|
|
425
|
-
return initial.value
|
|
426
|
-
}
|
|
427
|
-
const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
|
|
428
|
-
if (loading.value !== undefined) {
|
|
429
|
-
return loading.value
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const isRefreshing = values.some((x) => x.waiting)
|
|
433
|
-
|
|
434
|
-
const r = Object.entries(results).reduce((prev, [key, value]) => {
|
|
435
|
-
prev[key] = Result.value(value).value
|
|
436
|
-
return prev
|
|
437
|
-
}, {} as any)
|
|
438
|
-
return Result.success(r, isRefreshing)
|
|
279
|
+
export interface RequestHandler<A, E, R, Request extends S.TaggedRequest.Any> {
|
|
280
|
+
handler: Effect<A, E, R>
|
|
281
|
+
name: string
|
|
282
|
+
Request: Request
|
|
439
283
|
}
|
|
440
284
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
285
|
+
export interface RequestHandlerWithInput<I, A, E, R, Request extends S.TaggedRequest.Any> {
|
|
286
|
+
handler: (i: I) => Effect<A, E, R>
|
|
287
|
+
name: string
|
|
288
|
+
Request: Request
|
|
445
289
|
}
|
package/src/mutate.ts
CHANGED
|
@@ -69,13 +69,13 @@ export interface MutationOptions<A, I = void> {
|
|
|
69
69
|
onSuccess?: (a: A, i: I) => Promise<unknown>
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
export const getQueryKey = (name: string) => {
|
|
73
|
-
const key = makeQueryKey(
|
|
72
|
+
export const getQueryKey = (h: { name: string }) => {
|
|
73
|
+
const key = makeQueryKey(h)
|
|
74
74
|
const ns = key.filter((_) => _.startsWith("$"))
|
|
75
75
|
// we invalidate the parent namespace e.g $project/$configuration.get, we invalidate $project
|
|
76
76
|
// for $project/$configuration/$something.get, we invalidate $project/$configuration
|
|
77
77
|
const k = ns.length ? ns.length > 1 ? ns.slice(0, ns.length - 1) : ns : undefined
|
|
78
|
-
if (!k) throw new Error("empty query key for: " + name)
|
|
78
|
+
if (!k) throw new Error("empty query key for: " + h.name)
|
|
79
79
|
return k
|
|
80
80
|
}
|
|
81
81
|
// TODO: more efficient invalidation, including args etc
|
|
@@ -180,7 +180,7 @@ export const makeMutation = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
180
180
|
Effect.tap(() =>
|
|
181
181
|
Effect
|
|
182
182
|
.suspend(() => {
|
|
183
|
-
const queryKey = getQueryKey(self
|
|
183
|
+
const queryKey = getQueryKey(self)
|
|
184
184
|
|
|
185
185
|
if (options?.queryInvalidation) {
|
|
186
186
|
const opts = options.queryInvalidation(queryKey, self.name)
|
|
@@ -225,3 +225,36 @@ export const makeMutation = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
225
225
|
|
|
226
226
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
227
227
|
export interface MakeMutation<R> extends ReturnType<typeof makeMutation<R>> {}
|
|
228
|
+
|
|
229
|
+
export function mutationResultToVue<A, E>(
|
|
230
|
+
mutationResult: MutationResult<A, E>
|
|
231
|
+
): Res<A, E> {
|
|
232
|
+
switch (mutationResult._tag) {
|
|
233
|
+
case "Loading": {
|
|
234
|
+
return { loading: true, data: undefined, error: undefined }
|
|
235
|
+
}
|
|
236
|
+
case "Success": {
|
|
237
|
+
return {
|
|
238
|
+
loading: false,
|
|
239
|
+
data: mutationResult.data,
|
|
240
|
+
error: undefined
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
case "Error": {
|
|
244
|
+
return {
|
|
245
|
+
loading: false,
|
|
246
|
+
data: undefined,
|
|
247
|
+
error: mutationResult.error
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
case "Initial": {
|
|
251
|
+
return { loading: false, data: undefined, error: undefined }
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface Res<A, E> {
|
|
257
|
+
readonly loading: boolean
|
|
258
|
+
readonly data: A | undefined
|
|
259
|
+
readonly error: E | undefined
|
|
260
|
+
}
|
package/src/mutate2.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { tuple } from "@effect-app/core/Function"
|
|
|
3
3
|
import * as Result from "@effect-rx/rx/Result"
|
|
4
4
|
import type { InvalidateOptions, InvalidateQueryFilters } from "@tanstack/vue-query"
|
|
5
5
|
import { useQueryClient } from "@tanstack/vue-query"
|
|
6
|
+
import type { S } from "effect-app"
|
|
6
7
|
import { Cause, Effect, Exit, Option } from "effect-app"
|
|
7
8
|
import type { ComputedRef, Ref } from "vue"
|
|
8
9
|
import { computed, ref, shallowRef } from "vue"
|
|
9
10
|
import { reportRuntimeError } from "./internal.js"
|
|
11
|
+
import type { RequestHandler, RequestHandlerWithInput } from "./makeClient2.js"
|
|
10
12
|
import { getQueryKey } from "./mutate.js"
|
|
11
13
|
|
|
12
14
|
export type WatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T)
|
|
@@ -78,35 +80,27 @@ export interface MutationOptions {
|
|
|
78
80
|
*/
|
|
79
81
|
|
|
80
82
|
export const makeMutation2 = () => {
|
|
81
|
-
type HandlerWithInput<I, A, E, R> = {
|
|
82
|
-
handler: (i: I) => Effect<A, E, R>
|
|
83
|
-
name: string
|
|
84
|
-
}
|
|
85
|
-
type Handler<A, E, R> = { handler: Effect<A, E, R>; name: string }
|
|
86
|
-
|
|
87
83
|
/**
|
|
88
84
|
* Pass a function that returns an Effect, e.g from a client action, or an Effect
|
|
89
85
|
* Returns a tuple with state ref and execution function which reports errors as Toast.
|
|
90
86
|
*/
|
|
91
87
|
const useSafeMutation: {
|
|
92
|
-
<I, E, A, R>(
|
|
93
|
-
self:
|
|
88
|
+
<I, E, A, R, Request extends S.TaggedRequest.Any>(
|
|
89
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
94
90
|
options?: MutationOptions
|
|
95
91
|
): readonly [
|
|
96
92
|
Readonly<Ref<MutationResult<A, E>>>,
|
|
97
93
|
(i: I) => Effect<A, E, R>
|
|
98
94
|
]
|
|
99
|
-
<E, A, R
|
|
95
|
+
<E, A, R, Request extends S.TaggedRequest.Any>(
|
|
96
|
+
self: RequestHandler<A, E, R, Request>,
|
|
97
|
+
options?: MutationOptions
|
|
98
|
+
): readonly [
|
|
100
99
|
Readonly<Ref<MutationResult<A, E>>>,
|
|
101
100
|
() => Effect<A, E, R> // TODO: remove () =>
|
|
102
101
|
]
|
|
103
|
-
} = <I, E, A, R>(
|
|
104
|
-
self:
|
|
105
|
-
handler:
|
|
106
|
-
| HandlerWithInput<I, A, E, R>["handler"]
|
|
107
|
-
| Handler<A, E, R>["handler"]
|
|
108
|
-
name: string
|
|
109
|
-
},
|
|
102
|
+
} = <I, E, A, R, Request extends S.TaggedRequest.Any>(
|
|
103
|
+
self: RequestHandlerWithInput<I, A, E, R, Request> | RequestHandler<A, E, R, Request>,
|
|
110
104
|
options?: MutationOptions
|
|
111
105
|
) => {
|
|
112
106
|
const queryClient = useQueryClient()
|
|
@@ -133,7 +127,7 @@ export const makeMutation2 = () => {
|
|
|
133
127
|
}
|
|
134
128
|
|
|
135
129
|
const invalidateCache = Effect.suspend(() => {
|
|
136
|
-
const queryKey = getQueryKey(self
|
|
130
|
+
const queryKey = getQueryKey(self)
|
|
137
131
|
|
|
138
132
|
if (options?.queryInvalidation) {
|
|
139
133
|
const opts = options.queryInvalidation(queryKey, self.name)
|
package/src/query.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
UseQueryReturnType
|
|
13
13
|
} from "@tanstack/vue-query"
|
|
14
14
|
import { useQuery } from "@tanstack/vue-query"
|
|
15
|
-
import { Cause, Effect, Option, Runtime, S } from "effect-app"
|
|
15
|
+
import { Array, Cause, Effect, Option, Runtime, S } from "effect-app"
|
|
16
16
|
import { ServiceUnavailableError } from "effect-app/client"
|
|
17
17
|
import { computed, ref } from "vue"
|
|
18
18
|
import type { ComputedRef, Ref, WatchSource } from "vue"
|
|
@@ -49,7 +49,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
49
49
|
E,
|
|
50
50
|
R
|
|
51
51
|
>
|
|
52
|
-
mapPath: (req: I) => string
|
|
53
52
|
name: string
|
|
54
53
|
}
|
|
55
54
|
| {
|
|
@@ -58,7 +57,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
58
57
|
E,
|
|
59
58
|
R
|
|
60
59
|
>
|
|
61
|
-
mapPath: string
|
|
62
60
|
name: string
|
|
63
61
|
},
|
|
64
62
|
arg?: I | WatchSource<I>,
|
|
@@ -75,7 +73,7 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
75
73
|
}
|
|
76
74
|
} as any)
|
|
77
75
|
: ref(arg)
|
|
78
|
-
const queryKey = makeQueryKey(q
|
|
76
|
+
const queryKey = makeQueryKey(q)
|
|
79
77
|
const handler = q.handler
|
|
80
78
|
const r = useQuery<unknown, KnownFiberFailure<E>, A>(
|
|
81
79
|
Effect.isEffect(handler)
|
|
@@ -162,7 +160,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
162
160
|
function useSafeQuery<E, A>(
|
|
163
161
|
self: {
|
|
164
162
|
handler: Effect<A, E, R>
|
|
165
|
-
mapPath: string
|
|
166
163
|
name: string
|
|
167
164
|
},
|
|
168
165
|
options?: QueryObserverOptionsCustom // TODO
|
|
@@ -175,7 +172,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
175
172
|
function useSafeQuery<Arg, E, A>(
|
|
176
173
|
self: {
|
|
177
174
|
handler: (arg: Arg) => Effect<A, E, R>
|
|
178
|
-
mapPath: (arg: Arg) => string
|
|
179
175
|
name: string
|
|
180
176
|
},
|
|
181
177
|
arg: Arg | WatchSource<Arg>,
|
|
@@ -198,7 +194,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
198
194
|
E,
|
|
199
195
|
R
|
|
200
196
|
>
|
|
201
|
-
mapPath: (req: I) => string
|
|
202
197
|
name: string
|
|
203
198
|
}
|
|
204
199
|
| {
|
|
@@ -207,7 +202,6 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
207
202
|
E,
|
|
208
203
|
R
|
|
209
204
|
>
|
|
210
|
-
mapPath: string
|
|
211
205
|
name: string
|
|
212
206
|
},
|
|
213
207
|
*/
|
|
@@ -223,3 +217,49 @@ export const makeQuery = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
223
217
|
|
|
224
218
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
225
219
|
export interface MakeQuery<R> extends ReturnType<typeof makeQuery<R>> {}
|
|
220
|
+
|
|
221
|
+
export function composeQueries<
|
|
222
|
+
R extends Record<string, Result.Result<any, any>>
|
|
223
|
+
>(
|
|
224
|
+
results: R,
|
|
225
|
+
renderPreviousOnFailure?: boolean
|
|
226
|
+
): Result.Result<
|
|
227
|
+
{
|
|
228
|
+
[Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
|
|
229
|
+
: never
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
[Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
|
|
233
|
+
: never
|
|
234
|
+
}[keyof R]
|
|
235
|
+
> {
|
|
236
|
+
const values = renderPreviousOnFailure
|
|
237
|
+
? Object.values(results).map(orPrevious)
|
|
238
|
+
: Object.values(results)
|
|
239
|
+
const error = values.find(Result.isFailure)
|
|
240
|
+
if (error) {
|
|
241
|
+
return error
|
|
242
|
+
}
|
|
243
|
+
const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
|
|
244
|
+
if (initial.value !== undefined) {
|
|
245
|
+
return initial.value
|
|
246
|
+
}
|
|
247
|
+
const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
|
|
248
|
+
if (loading.value !== undefined) {
|
|
249
|
+
return loading.value
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const isRefreshing = values.some((x) => x.waiting)
|
|
253
|
+
|
|
254
|
+
const r = Object.entries(results).reduce((prev, [key, value]) => {
|
|
255
|
+
prev[key] = Result.value(value).value
|
|
256
|
+
return prev
|
|
257
|
+
}, {} as any)
|
|
258
|
+
return Result.success(r, isRefreshing)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function orPrevious<E, A>(result: Result.Result<A, E>) {
|
|
262
|
+
return Result.isFailure(result) && Option.isSome(result.previousValue)
|
|
263
|
+
? Result.success(result.previousValue.value, result.waiting)
|
|
264
|
+
: result
|
|
265
|
+
}
|
package/src/query2.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { ServiceUnavailableError } from "effect-app/client"
|
|
|
17
17
|
import { computed, ref } from "vue"
|
|
18
18
|
import type { ComputedRef, Ref, WatchSource } from "vue"
|
|
19
19
|
import { makeQueryKey, reportRuntimeError } from "./internal.js"
|
|
20
|
+
import type { RequestHandler, RequestHandlerWithInput } from "./makeClient2.js"
|
|
20
21
|
|
|
21
22
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
22
23
|
export interface QueryObserverOptionsCustom<
|
|
@@ -39,28 +40,10 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
39
40
|
// declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
|
|
40
41
|
// declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryDefinedReturnType<TData, TError>;
|
|
41
42
|
// declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
|
|
42
|
-
const useSafeQuery_ = <I, A, E>(
|
|
43
|
+
const useSafeQuery_ = <I, A, E, Request extends S.TaggedRequest.Any>(
|
|
43
44
|
q:
|
|
44
|
-
|
|
|
45
|
-
|
|
46
|
-
req: I
|
|
47
|
-
) => Effect<
|
|
48
|
-
A,
|
|
49
|
-
E,
|
|
50
|
-
R
|
|
51
|
-
>
|
|
52
|
-
mapPath: (req: I) => string
|
|
53
|
-
name: string
|
|
54
|
-
}
|
|
55
|
-
| {
|
|
56
|
-
readonly handler: Effect<
|
|
57
|
-
A,
|
|
58
|
-
E,
|
|
59
|
-
R
|
|
60
|
-
>
|
|
61
|
-
mapPath: string
|
|
62
|
-
name: string
|
|
63
|
-
},
|
|
45
|
+
| RequestHandlerWithInput<I, A, E, R, Request>
|
|
46
|
+
| RequestHandler<A, E, R, Request>,
|
|
64
47
|
arg?: I | WatchSource<I>,
|
|
65
48
|
options: QueryObserverOptionsCustom<unknown, KnownFiberFailure<E>, A> = {} // TODO
|
|
66
49
|
) => {
|
|
@@ -75,7 +58,7 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
75
58
|
}
|
|
76
59
|
} as any)
|
|
77
60
|
: ref(arg)
|
|
78
|
-
const queryKey = makeQueryKey(q
|
|
61
|
+
const queryKey = makeQueryKey(q)
|
|
79
62
|
const handler = q.handler
|
|
80
63
|
const r = useQuery<unknown, KnownFiberFailure<E>, A>(
|
|
81
64
|
Effect.isEffect(handler)
|
|
@@ -141,6 +124,8 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
141
124
|
result,
|
|
142
125
|
latestSuccess,
|
|
143
126
|
// one thing to keep in mind is that span will be disconnected as Context does not pass from outside.
|
|
127
|
+
// TODO: consider how we should handle the Result here which is `QueryObserverResult<A, KnownFiberFailure<E>>`
|
|
128
|
+
// and always ends up in the success channel, even when error..
|
|
144
129
|
(options?: RefetchOptions) => Effect.promise(() => r.refetch(options)),
|
|
145
130
|
r
|
|
146
131
|
] as const
|
|
@@ -165,12 +150,8 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
165
150
|
return Result.initial(r.isValidating)
|
|
166
151
|
}
|
|
167
152
|
|
|
168
|
-
function useSafeQuery<E, A>(
|
|
169
|
-
self:
|
|
170
|
-
handler: Effect<A, E, R>
|
|
171
|
-
mapPath: string
|
|
172
|
-
name: string
|
|
173
|
-
},
|
|
153
|
+
function useSafeQuery<E, A, Request extends S.TaggedRequest.Any>(
|
|
154
|
+
self: RequestHandler<A, E, R, Request>,
|
|
174
155
|
options?: QueryObserverOptionsCustom // TODO
|
|
175
156
|
): readonly [
|
|
176
157
|
ComputedRef<Result.Result<A, E>>,
|
|
@@ -178,12 +159,8 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
178
159
|
(options?: RefetchOptions) => Effect<QueryObserverResult<A, KnownFiberFailure<E>>>,
|
|
179
160
|
UseQueryReturnType<any, any>
|
|
180
161
|
]
|
|
181
|
-
function useSafeQuery<Arg, E, A>(
|
|
182
|
-
self:
|
|
183
|
-
handler: (arg: Arg) => Effect<A, E, R>
|
|
184
|
-
mapPath: (arg: Arg) => string
|
|
185
|
-
name: string
|
|
186
|
-
},
|
|
162
|
+
function useSafeQuery<Arg, E, A, Request extends S.TaggedRequest.Any>(
|
|
163
|
+
self: RequestHandlerWithInput<Arg, A, E, R, Request>,
|
|
187
164
|
arg: Arg | WatchSource<Arg>,
|
|
188
165
|
options?: QueryObserverOptionsCustom // TODO
|
|
189
166
|
): readonly [
|
|
@@ -194,29 +171,6 @@ export const makeQuery2 = <R>(runtime: Ref<Runtime.Runtime<R>>) => {
|
|
|
194
171
|
]
|
|
195
172
|
function useSafeQuery(
|
|
196
173
|
self: any,
|
|
197
|
-
/*
|
|
198
|
-
q:
|
|
199
|
-
| {
|
|
200
|
-
handler: (
|
|
201
|
-
req: I
|
|
202
|
-
) => Effect<
|
|
203
|
-
A,
|
|
204
|
-
E,
|
|
205
|
-
R
|
|
206
|
-
>
|
|
207
|
-
mapPath: (req: I) => string
|
|
208
|
-
name: string
|
|
209
|
-
}
|
|
210
|
-
| {
|
|
211
|
-
handler: Effect<
|
|
212
|
-
A,
|
|
213
|
-
E,
|
|
214
|
-
R
|
|
215
|
-
>
|
|
216
|
-
mapPath: string
|
|
217
|
-
name: string
|
|
218
|
-
},
|
|
219
|
-
*/
|
|
220
174
|
argOrOptions?: any,
|
|
221
175
|
options?: any
|
|
222
176
|
) {
|
package/dist/hooks.d.ts
DELETED
package/dist/index.d.ts
DELETED