@effect-app/vue 1.26.0 → 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 +17 -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 +48 -136
- 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 +25 -112
- package/dist/makeClient2.d.ts.map +1 -1
- package/dist/makeClient2.js +49 -146
- 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 +97 -332
- 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/makeClient2.ts
CHANGED
|
@@ -1,137 +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 type { Either } from "effect-app"
|
|
8
|
-
import { Array, Cause, Effect, Match, Option, Runtime, S } from "effect-app"
|
|
9
|
-
import { type SupportedErrors } from "effect-app/client"
|
|
4
|
+
import { Cause, Effect, Exit, Match, Option, S } from "effect-app"
|
|
10
5
|
import { Failure, Success } from "effect-app/Operations"
|
|
11
6
|
import { dropUndefinedT } from "effect-app/utils"
|
|
12
7
|
import { computed, type ComputedRef } from "vue"
|
|
8
|
+
import type { Opts, ResponseErrors } from "./makeClient.js"
|
|
13
9
|
import type { MakeIntlReturn } from "./makeIntl.js"
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* Use this after handling an error yourself, still continueing on the Error track, but the error will not be reported.
|
|
18
|
-
*/
|
|
19
|
-
export class SuppressErrors extends Cause.YieldableError {
|
|
20
|
-
readonly _tag = "SuppressErrors"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type ResponseErrors = S.ParseResult.ParseError | SupportedErrors | SuppressErrors
|
|
24
|
-
|
|
25
|
-
export function pauseWhileProcessing(
|
|
26
|
-
iv: Pausable,
|
|
27
|
-
pmf: () => Promise<unknown>
|
|
28
|
-
) {
|
|
29
|
-
return Promise
|
|
30
|
-
.resolve(iv.pause())
|
|
31
|
-
.then(() => pmf())
|
|
32
|
-
.finally(() => iv.resume())
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function useIntervalPauseWhileProcessing(
|
|
36
|
-
pmf: () => Promise<unknown>,
|
|
37
|
-
interval?: MaybeRefOrGetter<number>,
|
|
38
|
-
options?: Omit<UseIntervalFnOptions, "immediateCallback">
|
|
39
|
-
) {
|
|
40
|
-
const iv = useIntervalFn(
|
|
41
|
-
() => pauseWhileProcessing(iv, pmf),
|
|
42
|
-
interval,
|
|
43
|
-
options ? { ...options, immediateCallback: false } : options
|
|
44
|
-
)
|
|
45
|
-
return {
|
|
46
|
-
isActive: iv.isActive
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface Opts<A> extends MutationOptions {
|
|
51
|
-
suppressErrorToast?: boolean
|
|
52
|
-
suppressSuccessToast?: boolean
|
|
53
|
-
successToast?: (a: A) => any
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const withSuccess: {
|
|
57
|
-
<I, E extends ResponseErrors, A, X, R>(
|
|
58
|
-
self: {
|
|
59
|
-
handler: (i: I) => Effect<A, E, R>
|
|
60
|
-
name: string
|
|
61
|
-
},
|
|
62
|
-
onSuccess: (a: A, i: I) => Promise<X>
|
|
63
|
-
): {
|
|
64
|
-
handler: (i: I) => Effect<X, E, R>
|
|
65
|
-
name: string
|
|
66
|
-
}
|
|
67
|
-
<E extends ResponseErrors, A, X, R>(
|
|
68
|
-
self: {
|
|
69
|
-
handler: Effect<A, E, R>
|
|
70
|
-
name: string
|
|
71
|
-
},
|
|
72
|
-
onSuccess: (_: A) => Promise<X>
|
|
73
|
-
): {
|
|
74
|
-
handler: Effect<X, E, R>
|
|
75
|
-
name: string
|
|
76
|
-
}
|
|
77
|
-
} = (self: any, onSuccess: any): any => ({
|
|
78
|
-
...self,
|
|
79
|
-
handler: typeof self.handler === "function"
|
|
80
|
-
? (i: any) =>
|
|
81
|
-
pipe(
|
|
82
|
-
(
|
|
83
|
-
self.handler as (
|
|
84
|
-
i: any
|
|
85
|
-
) => Effect<any, any, any>
|
|
86
|
-
)(i),
|
|
87
|
-
Effect.flatMap((_) =>
|
|
88
|
-
Effect.promise(() => onSuccess(_, i)).pipe(
|
|
89
|
-
Effect.withSpan("onSuccess")
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
: Effect.flatMap(self.handler, (_) => Effect.promise(() => onSuccess(_)).pipe(Effect.withSpan("onSuccess")))
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
export const withSuccessE: {
|
|
97
|
-
<I, E extends ResponseErrors, A, E2, X, R>(
|
|
98
|
-
self: {
|
|
99
|
-
handler: (i: I) => Effect<A, E, R>
|
|
100
|
-
name: string
|
|
101
|
-
},
|
|
102
|
-
onSuccessE: (_: A, i: I) => Effect<X, E2>
|
|
103
|
-
): {
|
|
104
|
-
handler: (i: I) => Effect<X, E | E2, R>
|
|
105
|
-
name: string
|
|
106
|
-
}
|
|
107
|
-
<E extends ResponseErrors, A, E2, X, R>(
|
|
108
|
-
self: {
|
|
109
|
-
handler: Effect<A, E, R>
|
|
110
|
-
name: string
|
|
111
|
-
},
|
|
112
|
-
onSuccessE: (_: A) => Effect<X, E2>
|
|
113
|
-
): {
|
|
114
|
-
handler: Effect<X, E | E2, R>
|
|
115
|
-
name: string
|
|
116
|
-
}
|
|
117
|
-
} = (self: any, onSuccessE: any): any => {
|
|
118
|
-
return {
|
|
119
|
-
...self,
|
|
120
|
-
handler: typeof self.handler === "function"
|
|
121
|
-
? (i: any) =>
|
|
122
|
-
pipe(
|
|
123
|
-
self.handler(i),
|
|
124
|
-
Effect.flatMap((_) => onSuccessE(_, i))
|
|
125
|
-
)
|
|
126
|
-
: Effect.flatMap(self.handler, (_) => onSuccessE(_))
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface Res<A, E> {
|
|
131
|
-
readonly loading: boolean
|
|
132
|
-
readonly data: A | undefined
|
|
133
|
-
readonly error: E | undefined
|
|
134
|
-
}
|
|
10
|
+
import { mutationResultToVue } from "./mutate.js"
|
|
11
|
+
import type { Res } from "./mutate.js"
|
|
12
|
+
import type { MakeMutation2 } from "./mutate2.js"
|
|
135
13
|
|
|
136
14
|
type WithAction<A> = A & {
|
|
137
15
|
action: string
|
|
@@ -139,43 +17,16 @@ type WithAction<A> = A & {
|
|
|
139
17
|
|
|
140
18
|
// computed() takes a getter function and returns a readonly reactive ref
|
|
141
19
|
// object for the returned value from the getter.
|
|
142
|
-
type Resp<I, E, A> = readonly [
|
|
20
|
+
type Resp<I, E, A, R> = readonly [
|
|
143
21
|
ComputedRef<Res<A, E>>,
|
|
144
|
-
WithAction<(I: I) =>
|
|
22
|
+
WithAction<(I: I) => Effect<A, E, R>>
|
|
145
23
|
]
|
|
146
24
|
|
|
147
|
-
type ActResp<E, A> = readonly [
|
|
25
|
+
type ActResp<E, A, R> = readonly [
|
|
148
26
|
ComputedRef<Res<A, E>>,
|
|
149
|
-
WithAction<() =>
|
|
27
|
+
WithAction<() => Effect<A, E, R>>
|
|
150
28
|
]
|
|
151
29
|
|
|
152
|
-
export function mutationResultToVue<A, E>(
|
|
153
|
-
mutationResult: MutationResult<A, E>
|
|
154
|
-
): Res<A, E> {
|
|
155
|
-
switch (mutationResult._tag) {
|
|
156
|
-
case "Loading": {
|
|
157
|
-
return { loading: true, data: undefined, error: undefined }
|
|
158
|
-
}
|
|
159
|
-
case "Success": {
|
|
160
|
-
return {
|
|
161
|
-
loading: false,
|
|
162
|
-
data: mutationResult.data,
|
|
163
|
-
error: undefined
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
case "Error": {
|
|
167
|
-
return {
|
|
168
|
-
loading: false,
|
|
169
|
-
data: undefined,
|
|
170
|
-
error: mutationResult.error
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
case "Initial": {
|
|
174
|
-
return { loading: false, data: undefined, error: undefined }
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
30
|
export const makeClient2 = <Locale extends string, R>(
|
|
180
31
|
useIntl: MakeIntlReturn<Locale>["useIntl"],
|
|
181
32
|
useToast: () => {
|
|
@@ -198,9 +49,10 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
198
49
|
function handleRequestWithToast<
|
|
199
50
|
E extends ResponseErrors,
|
|
200
51
|
A,
|
|
52
|
+
R,
|
|
201
53
|
Args extends unknown[]
|
|
202
54
|
>(
|
|
203
|
-
f: (...args: Args) =>
|
|
55
|
+
f: (...args: Args) => Effect<A, E, R>,
|
|
204
56
|
action: string,
|
|
205
57
|
options: Opts<A> = { suppressErrorToast: false }
|
|
206
58
|
) {
|
|
@@ -218,68 +70,70 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
218
70
|
{ action: message }
|
|
219
71
|
)
|
|
220
72
|
return Object.assign(
|
|
221
|
-
flow(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
73
|
+
flow(
|
|
74
|
+
f,
|
|
75
|
+
Effect.onExit(
|
|
76
|
+
Exit.matchEffect({
|
|
77
|
+
onSuccess: (r) =>
|
|
78
|
+
Effect.gen(function*() {
|
|
79
|
+
if (S.is(Failure)(r)) {
|
|
80
|
+
toast.warning(
|
|
81
|
+
warnMessage + r.message
|
|
82
|
+
? "\n" + r.message
|
|
83
|
+
: ""
|
|
233
84
|
)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
)
|
|
243
|
-
)
|
|
244
|
-
.then((_) => {})
|
|
245
|
-
: r.left._tag === "SuppressErrors"
|
|
246
|
-
? Promise.resolve(void 0)
|
|
247
|
-
: Promise
|
|
248
|
-
.resolve(
|
|
249
|
-
!options.suppressErrorToast
|
|
250
|
-
&& toast.error(`${errorMessage}:\n` + renderError(r.left))
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
toast.success(
|
|
89
|
+
successMessage
|
|
90
|
+
+ (S.is(Success)(r) && r.message
|
|
91
|
+
? "\n" + r.message
|
|
92
|
+
: "")
|
|
251
93
|
)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
action,
|
|
265
|
-
message: `Unexpected Error trying to ${action}`
|
|
266
|
-
}
|
|
267
|
-
Sentry.captureException(err, {
|
|
268
|
-
extra
|
|
269
|
-
})
|
|
270
|
-
console.error(err, extra)
|
|
94
|
+
}),
|
|
95
|
+
onFailure: (err) =>
|
|
96
|
+
Effect.gen(function*() {
|
|
97
|
+
if (Cause.isInterruptedOnly(err)) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const fail = Cause.failureOption(err)
|
|
102
|
+
if (Option.isSome(fail)) {
|
|
103
|
+
if ((fail as any)._tag === "SuppressErrors") {
|
|
104
|
+
return Effect.succeed(void 0)
|
|
105
|
+
}
|
|
271
106
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
107
|
+
if (!options.suppressErrorToast) {
|
|
108
|
+
toast.error(`${errorMessage}:\n` + renderError(fail.value))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.warn(fail, fail.toString())
|
|
112
|
+
return
|
|
278
113
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
114
|
+
|
|
115
|
+
const extra = {
|
|
116
|
+
action,
|
|
117
|
+
message: `Unexpected Error trying to ${action}`
|
|
118
|
+
}
|
|
119
|
+
Sentry.captureException(err, {
|
|
120
|
+
extra
|
|
121
|
+
})
|
|
122
|
+
console.error(err, extra)
|
|
123
|
+
|
|
124
|
+
toast.error(
|
|
125
|
+
intl.value.formatMessage(
|
|
126
|
+
{ id: "handle.unexpected_error" },
|
|
127
|
+
{
|
|
128
|
+
action: message,
|
|
129
|
+
error: JSON.stringify(err, undefined, 2)
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
)
|
|
136
|
+
),
|
|
283
137
|
{ action }
|
|
284
138
|
)
|
|
285
139
|
}
|
|
@@ -343,26 +197,21 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
343
197
|
* Returns a tuple with state ref and execution function which reports errors as Toast.
|
|
344
198
|
*/
|
|
345
199
|
const useAndHandleMutation: {
|
|
346
|
-
<I, E extends ResponseErrors, A>(
|
|
347
|
-
self:
|
|
348
|
-
handler: (i: I) => Effect<A, E, R>
|
|
349
|
-
name: string
|
|
350
|
-
},
|
|
200
|
+
<I, E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
201
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
351
202
|
action: string,
|
|
352
203
|
options?: Opts<A>
|
|
353
|
-
): Resp<I, A, E>
|
|
354
|
-
<E extends ResponseErrors, A>(
|
|
355
|
-
self:
|
|
356
|
-
handler: Effect<A, E, R>
|
|
357
|
-
name: string
|
|
358
|
-
},
|
|
204
|
+
): Resp<I, A, E, R>
|
|
205
|
+
<E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
206
|
+
self: RequestHandler<A, E, R, Request>,
|
|
359
207
|
action: string,
|
|
360
208
|
options?: Opts<A>
|
|
361
|
-
): ActResp<E, A>
|
|
209
|
+
): ActResp<E, A, R>
|
|
362
210
|
} = (self: any, action: any, options?: Opts<any>) => {
|
|
363
211
|
const handleRequestWithToast = useHandleRequestWithToast()
|
|
364
212
|
const [a, b] = useSafeMutation(
|
|
365
213
|
{
|
|
214
|
+
...self,
|
|
366
215
|
handler: Effect.isEffect(self.handler)
|
|
367
216
|
? (pipe(
|
|
368
217
|
Effect.annotateCurrentSpan({ action }),
|
|
@@ -372,8 +221,7 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
372
221
|
pipe(
|
|
373
222
|
Effect.annotateCurrentSpan({ action }),
|
|
374
223
|
Effect.andThen(self.handler(...args))
|
|
375
|
-
)
|
|
376
|
-
name: self.name
|
|
224
|
+
)
|
|
377
225
|
},
|
|
378
226
|
dropUndefinedT({
|
|
379
227
|
queryInvalidation: options?.queryInvalidation
|
|
@@ -387,48 +235,31 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
387
235
|
}
|
|
388
236
|
|
|
389
237
|
function makeUseAndHandleMutation(
|
|
390
|
-
onSuccess?: () => Promise<void>,
|
|
391
238
|
defaultOptions?: Opts<any>
|
|
392
239
|
) {
|
|
393
240
|
return ((self: any, action: any, options: any) => {
|
|
394
241
|
return useAndHandleMutation(
|
|
395
|
-
|
|
396
|
-
handler: typeof self.handler === "function"
|
|
397
|
-
? onSuccess
|
|
398
|
-
? (i: any) => Effect.tap(self.handler(i), () => Effect.promise(onSuccess))
|
|
399
|
-
: self.handler
|
|
400
|
-
: onSuccess
|
|
401
|
-
? (Effect.tap(self.handler, () => Effect.promise(onSuccess)) as any)
|
|
402
|
-
: self.handler,
|
|
403
|
-
name: self.name
|
|
404
|
-
},
|
|
242
|
+
self,
|
|
405
243
|
action,
|
|
406
244
|
{ ...defaultOptions, ...options }
|
|
407
245
|
)
|
|
408
246
|
}) as {
|
|
409
|
-
<I, E extends ResponseErrors, A>(
|
|
410
|
-
self:
|
|
411
|
-
handler: (i: I) => Effect<A, E, R>
|
|
412
|
-
name: string
|
|
413
|
-
},
|
|
247
|
+
<I, E extends ResponseErrors, A, R, Request extends S.TaggedRequest.Any>(
|
|
248
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
414
249
|
action: string,
|
|
415
250
|
options?: Opts<A>
|
|
416
|
-
): Resp<I, A, E>
|
|
417
|
-
<E extends ResponseErrors, A>(
|
|
418
|
-
self:
|
|
419
|
-
handler: Effect<A, E, R>
|
|
420
|
-
name: string
|
|
421
|
-
},
|
|
251
|
+
): Resp<I, A, E, R>
|
|
252
|
+
<E extends ResponseErrors, A, Request extends S.TaggedRequest.Any>(
|
|
253
|
+
self: RequestHandler<A, E, R, Request>,
|
|
422
254
|
action: string,
|
|
423
255
|
options?: Opts<A>
|
|
424
|
-
): ActResp<E, A>
|
|
256
|
+
): ActResp<E, A, R>
|
|
425
257
|
}
|
|
426
258
|
}
|
|
427
259
|
|
|
428
|
-
const useSafeMutationWithState = <I, E, A>(
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}) => {
|
|
260
|
+
const useSafeMutationWithState = <I, E, A, Request extends S.TaggedRequest.Any>(
|
|
261
|
+
self: RequestHandlerWithInput<I, A, E, R, Request>
|
|
262
|
+
) => {
|
|
432
263
|
const [a, b] = useSafeMutation(self)
|
|
433
264
|
|
|
434
265
|
return tuple(
|
|
@@ -445,80 +276,14 @@ export const makeClient2 = <Locale extends string, R>(
|
|
|
445
276
|
}
|
|
446
277
|
}
|
|
447
278
|
|
|
448
|
-
export
|
|
449
|
-
<
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
name: string
|
|
453
|
-
mapPath: (i: I) => string
|
|
454
|
-
},
|
|
455
|
-
map: (i: I) => (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
456
|
-
): {
|
|
457
|
-
handler: (i: I) => Effect<A2, E2, R2>
|
|
458
|
-
name: string
|
|
459
|
-
mapPath: (i: I) => string
|
|
460
|
-
}
|
|
461
|
-
<E, A, R, E2, A2, R2>(
|
|
462
|
-
self: {
|
|
463
|
-
handler: Effect<A, E, R>
|
|
464
|
-
name: string
|
|
465
|
-
mapPath: string
|
|
466
|
-
},
|
|
467
|
-
map: (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
|
|
468
|
-
): {
|
|
469
|
-
handler: Effect<A2, E2, R2>
|
|
470
|
-
name: string
|
|
471
|
-
mapPath: string
|
|
472
|
-
}
|
|
473
|
-
} = (self: any, map: any): any => ({
|
|
474
|
-
...self,
|
|
475
|
-
handler: typeof self.handler === "function"
|
|
476
|
-
? (i: any) => map(i)((self.handler as (i: any) => Effect<any, any, any>)(i))
|
|
477
|
-
: map(self.handler)
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
export function composeQueries<
|
|
481
|
-
R extends Record<string, Result.Result<any, any>>
|
|
482
|
-
>(
|
|
483
|
-
results: R,
|
|
484
|
-
renderPreviousOnFailure?: boolean
|
|
485
|
-
): Result.Result<
|
|
486
|
-
{
|
|
487
|
-
[Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
|
|
488
|
-
: never
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
[Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
|
|
492
|
-
: never
|
|
493
|
-
}[keyof R]
|
|
494
|
-
> {
|
|
495
|
-
const values = renderPreviousOnFailure
|
|
496
|
-
? Object.values(results).map(orPrevious)
|
|
497
|
-
: Object.values(results)
|
|
498
|
-
const error = values.find(Result.isFailure)
|
|
499
|
-
if (error) {
|
|
500
|
-
return error
|
|
501
|
-
}
|
|
502
|
-
const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
|
|
503
|
-
if (initial.value !== undefined) {
|
|
504
|
-
return initial.value
|
|
505
|
-
}
|
|
506
|
-
const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
|
|
507
|
-
if (loading.value !== undefined) {
|
|
508
|
-
return loading.value
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
const isRefreshing = values.some((x) => x.waiting)
|
|
512
|
-
|
|
513
|
-
const r = Object.entries(results).reduce((prev, [key, value]) => {
|
|
514
|
-
prev[key] = Result.value(value).value
|
|
515
|
-
return prev
|
|
516
|
-
}, {} as any)
|
|
517
|
-
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
|
|
518
283
|
}
|
|
519
284
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
|
524
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()
|