@effect-app/vue 1.26.1 → 1.26.2
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 +9 -0
- package/_cjs/index.cjs +22 -13
- package/_cjs/index.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 +37 -0
- package/_cjs/mutate.cjs.map +1 -1
- package/_cjs/mutate2.cjs.map +1 -1
- package/_cjs/query.cjs +25 -2
- package/_cjs/query.cjs.map +1 -1
- package/_cjs/query2.cjs +3 -25
- package/_cjs/query2.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/lib.d.ts +8 -0
- 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 +6 -0
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +25 -1
- package/dist/mutate2.d.ts +4 -8
- package/dist/mutate2.d.ts.map +1 -1
- package/dist/mutate2.js +1 -1
- package/dist/query.d.ts +5 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +30 -4
- package/dist/query2.d.ts +4 -11
- package/dist/query2.d.ts.map +1 -1
- package/dist/query2.js +4 -26
- package/package.json +14 -4
- package/src/index.ts +3 -1
- package/src/lib.ts +29 -0
- package/src/makeClient.ts +4 -115
- package/src/makeClient2.ts +27 -183
- package/src/mutate.ts +33 -0
- package/src/mutate2.ts +10 -16
- package/src/query.ts +47 -7
- package/src/query2.ts +10 -56
- 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/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export *
|
|
1
|
+
export * from "./lib.js"
|
|
2
|
+
|
|
2
3
|
export * from "./hooks.js"
|
|
3
4
|
export * from "./makeClient.js"
|
|
5
|
+
export * from "./makeClient2.js"
|
|
4
6
|
export * from "./makeContext.js"
|
|
5
7
|
export * from "./makeIntl.js"
|
|
6
8
|
export * from "./runtime.js"
|
package/src/lib.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Pausable, useIntervalFn, type UseIntervalFnOptions } from "@vueuse/core"
|
|
2
|
+
import type { MaybeRefOrGetter } from "vue"
|
|
3
|
+
|
|
4
|
+
export * as Result from "@effect-rx/rx/Result"
|
|
5
|
+
|
|
6
|
+
export function pauseWhileProcessing(
|
|
7
|
+
iv: Pausable,
|
|
8
|
+
pmf: () => Promise<unknown>
|
|
9
|
+
) {
|
|
10
|
+
return Promise
|
|
11
|
+
.resolve(iv.pause())
|
|
12
|
+
.then(() => pmf())
|
|
13
|
+
.finally(() => iv.resume())
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useIntervalPauseWhileProcessing(
|
|
17
|
+
pmf: () => Promise<unknown>,
|
|
18
|
+
interval?: MaybeRefOrGetter<number>,
|
|
19
|
+
options?: Omit<UseIntervalFnOptions, "immediateCallback">
|
|
20
|
+
) {
|
|
21
|
+
const iv = useIntervalFn(
|
|
22
|
+
() => pauseWhileProcessing(iv, pmf),
|
|
23
|
+
interval,
|
|
24
|
+
options ? { ...options, immediateCallback: false } : options
|
|
25
|
+
)
|
|
26
|
+
return {
|
|
27
|
+
isActive: iv.isActive
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/makeClient.ts
CHANGED
|
@@ -1,18 +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 { type MaybeRefOrGetter, type Pausable, useIntervalFn, type UseIntervalFnOptions } from "@vueuse/core"
|
|
7
4
|
import type { Either } from "effect-app"
|
|
8
|
-
import {
|
|
5
|
+
import { Cause, Effect, Match, Runtime, S } from "effect-app"
|
|
9
6
|
import { type SupportedErrors } from "effect-app/client"
|
|
10
7
|
import { Failure, Success } from "effect-app/Operations"
|
|
11
8
|
import { dropUndefinedT } from "effect-app/utils"
|
|
12
|
-
import type { R } from "vitest/dist/chunks/config.Crbj2GAb.js"
|
|
13
9
|
import { computed, type ComputedRef } from "vue"
|
|
14
10
|
import type { MakeIntlReturn } from "./makeIntl.js"
|
|
15
|
-
import type { MakeMutation, MutationOptions } from "./mutate.js"
|
|
11
|
+
import type { MakeMutation, MutationOptions, Res } from "./mutate.js"
|
|
12
|
+
import { mutationResultToVue } from "./mutate.js"
|
|
16
13
|
|
|
17
14
|
/**
|
|
18
15
|
* Use this after handling an error yourself, still continueing on the Error track, but the error will not be reported.
|
|
@@ -23,31 +20,6 @@ export class SuppressErrors extends Cause.YieldableError {
|
|
|
23
20
|
|
|
24
21
|
export type ResponseErrors = S.ParseResult.ParseError | SupportedErrors | SuppressErrors
|
|
25
22
|
|
|
26
|
-
export function pauseWhileProcessing(
|
|
27
|
-
iv: Pausable,
|
|
28
|
-
pmf: () => Promise<unknown>
|
|
29
|
-
) {
|
|
30
|
-
return Promise
|
|
31
|
-
.resolve(iv.pause())
|
|
32
|
-
.then(() => pmf())
|
|
33
|
-
.finally(() => iv.resume())
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function useIntervalPauseWhileProcessing(
|
|
37
|
-
pmf: () => Promise<unknown>,
|
|
38
|
-
interval?: MaybeRefOrGetter<number>,
|
|
39
|
-
options?: Omit<UseIntervalFnOptions, "immediateCallback">
|
|
40
|
-
) {
|
|
41
|
-
const iv = useIntervalFn(
|
|
42
|
-
() => pauseWhileProcessing(iv, pmf),
|
|
43
|
-
interval,
|
|
44
|
-
options ? { ...options, immediateCallback: false } : options
|
|
45
|
-
)
|
|
46
|
-
return {
|
|
47
|
-
isActive: iv.isActive
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
23
|
export interface Opts<A, I = void> extends MutationOptions<A, I> {
|
|
52
24
|
suppressErrorToast?: boolean
|
|
53
25
|
suppressSuccessToast?: boolean
|
|
@@ -83,7 +55,7 @@ export const withSuccess: {
|
|
|
83
55
|
(
|
|
84
56
|
self.handler as (
|
|
85
57
|
i: any
|
|
86
|
-
) => Effect<any, any,
|
|
58
|
+
) => Effect<any, any, any>
|
|
87
59
|
)(i),
|
|
88
60
|
Effect.flatMap((_) =>
|
|
89
61
|
Effect.promise(() => onSuccess(_, i)).pipe(
|
|
@@ -128,12 +100,6 @@ export const withSuccessE: {
|
|
|
128
100
|
}
|
|
129
101
|
}
|
|
130
102
|
|
|
131
|
-
export interface Res<A, E> {
|
|
132
|
-
readonly loading: boolean
|
|
133
|
-
readonly data: A | undefined
|
|
134
|
-
readonly error: E | undefined
|
|
135
|
-
}
|
|
136
|
-
|
|
137
103
|
type WithAction<A> = A & {
|
|
138
104
|
action: string
|
|
139
105
|
}
|
|
@@ -150,33 +116,6 @@ type ActResp<E, A> = readonly [
|
|
|
150
116
|
WithAction<() => Promise<void>>
|
|
151
117
|
]
|
|
152
118
|
|
|
153
|
-
export function mutationResultToVue<A, E>(
|
|
154
|
-
mutationResult: MutationResult<A, E>
|
|
155
|
-
): Res<A, E> {
|
|
156
|
-
switch (mutationResult._tag) {
|
|
157
|
-
case "Loading": {
|
|
158
|
-
return { loading: true, data: undefined, error: undefined }
|
|
159
|
-
}
|
|
160
|
-
case "Success": {
|
|
161
|
-
return {
|
|
162
|
-
loading: false,
|
|
163
|
-
data: mutationResult.data,
|
|
164
|
-
error: undefined
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
case "Error": {
|
|
168
|
-
return {
|
|
169
|
-
loading: false,
|
|
170
|
-
data: undefined,
|
|
171
|
-
error: mutationResult.error
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
case "Initial": {
|
|
175
|
-
return { loading: false, data: undefined, error: undefined }
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
119
|
export const makeClient = <Locale extends string, R>(
|
|
181
120
|
useIntl: MakeIntlReturn<Locale>["useIntl"],
|
|
182
121
|
useToast: () => {
|
|
@@ -452,25 +391,21 @@ export const mapHandler: {
|
|
|
452
391
|
self: {
|
|
453
392
|
handler: (i: I) => Effect<A, E, R>
|
|
454
393
|
name: string
|
|
455
|
-
mapPath: (i: I) => string
|
|
456
394
|
},
|
|
457
395
|
map: (i: I) => (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
458
396
|
): {
|
|
459
397
|
handler: (i: I) => Effect<A2, E2, R2>
|
|
460
398
|
name: string
|
|
461
|
-
mapPath: (i: I) => string
|
|
462
399
|
}
|
|
463
400
|
<E, A, R, E2, A2, R2>(
|
|
464
401
|
self: {
|
|
465
402
|
handler: Effect<A, E, R>
|
|
466
403
|
name: string
|
|
467
|
-
mapPath: string
|
|
468
404
|
},
|
|
469
405
|
map: (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
470
406
|
): {
|
|
471
407
|
handler: Effect<A2, E2, R2>
|
|
472
408
|
name: string
|
|
473
|
-
mapPath: string
|
|
474
409
|
}
|
|
475
410
|
} = (self: any, map: any): any => ({
|
|
476
411
|
...self,
|
|
@@ -478,49 +413,3 @@ export const mapHandler: {
|
|
|
478
413
|
? (i: any) => map(i)((self.handler as (i: any) => Effect<any, any, any>)(i))
|
|
479
414
|
: map(self.handler)
|
|
480
415
|
})
|
|
481
|
-
|
|
482
|
-
export function composeQueries<
|
|
483
|
-
R extends Record<string, Result.Result<any, any>>
|
|
484
|
-
>(
|
|
485
|
-
results: R,
|
|
486
|
-
renderPreviousOnFailure?: boolean
|
|
487
|
-
): Result.Result<
|
|
488
|
-
{
|
|
489
|
-
[Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
|
|
490
|
-
: never
|
|
491
|
-
},
|
|
492
|
-
{
|
|
493
|
-
[Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
|
|
494
|
-
: never
|
|
495
|
-
}[keyof R]
|
|
496
|
-
> {
|
|
497
|
-
const values = renderPreviousOnFailure
|
|
498
|
-
? Object.values(results).map(orPrevious)
|
|
499
|
-
: Object.values(results)
|
|
500
|
-
const error = values.find(Result.isFailure)
|
|
501
|
-
if (error) {
|
|
502
|
-
return error
|
|
503
|
-
}
|
|
504
|
-
const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
|
|
505
|
-
if (initial.value !== undefined) {
|
|
506
|
-
return initial.value
|
|
507
|
-
}
|
|
508
|
-
const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
|
|
509
|
-
if (loading.value !== undefined) {
|
|
510
|
-
return loading.value
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const isRefreshing = values.some((x) => x.waiting)
|
|
514
|
-
|
|
515
|
-
const r = Object.entries(results).reduce((prev, [key, value]) => {
|
|
516
|
-
prev[key] = Result.value(value).value
|
|
517
|
-
return prev
|
|
518
|
-
}, {} as any)
|
|
519
|
-
return Result.success(r, isRefreshing)
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
function orPrevious<E, A>(result: Result.Result<A, E>) {
|
|
523
|
-
return Result.isFailure(result) && Option.isSome(result.previousValue)
|
|
524
|
-
? Result.success(result.previousValue.value, result.waiting)
|
|
525
|
-
: result
|
|
526
|
-
}
|
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
|
@@ -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()
|
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>,
|
|
@@ -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
|
+
}
|