@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.
Files changed (54) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/_cjs/index.cjs +22 -13
  3. package/_cjs/index.cjs.map +1 -1
  4. package/_cjs/lib.cjs +26 -0
  5. package/_cjs/lib.cjs.map +1 -0
  6. package/_cjs/makeClient.cjs +5 -84
  7. package/_cjs/makeClient.cjs.map +1 -1
  8. package/_cjs/makeClient2.cjs +48 -136
  9. package/_cjs/makeClient2.cjs.map +1 -1
  10. package/_cjs/mutate.cjs +37 -0
  11. package/_cjs/mutate.cjs.map +1 -1
  12. package/_cjs/mutate2.cjs.map +1 -1
  13. package/_cjs/query.cjs +25 -2
  14. package/_cjs/query.cjs.map +1 -1
  15. package/_cjs/query2.cjs +3 -25
  16. package/_cjs/query2.cjs.map +1 -1
  17. package/dist/index.d.ts +2 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -2
  20. package/dist/lib.d.ts +8 -0
  21. package/dist/lib.d.ts.map +1 -0
  22. package/dist/lib.js +15 -0
  23. package/dist/makeClient.d.ts +1 -23
  24. package/dist/makeClient.d.ts.map +1 -1
  25. package/dist/makeClient.js +3 -68
  26. package/dist/makeClient2.d.ts +25 -112
  27. package/dist/makeClient2.d.ts.map +1 -1
  28. package/dist/makeClient2.js +49 -146
  29. package/dist/mutate.d.ts +6 -0
  30. package/dist/mutate.d.ts.map +1 -1
  31. package/dist/mutate.js +25 -1
  32. package/dist/mutate2.d.ts +4 -8
  33. package/dist/mutate2.d.ts.map +1 -1
  34. package/dist/mutate2.js +1 -1
  35. package/dist/query.d.ts +5 -2
  36. package/dist/query.d.ts.map +1 -1
  37. package/dist/query.js +30 -4
  38. package/dist/query2.d.ts +4 -11
  39. package/dist/query2.d.ts.map +1 -1
  40. package/dist/query2.js +4 -26
  41. package/package.json +14 -4
  42. package/src/index.ts +3 -1
  43. package/src/lib.ts +29 -0
  44. package/src/makeClient.ts +4 -115
  45. package/src/makeClient2.ts +97 -332
  46. package/src/mutate.ts +33 -0
  47. package/src/mutate2.ts +10 -16
  48. package/src/query.ts +47 -7
  49. package/src/query2.ts +10 -56
  50. package/vitest.config.ts.timestamp-1711656440837-d04458a029af.mjs +0 -37
  51. package/vitest.config.ts.timestamp-1711724061890-e8772f088aa0d.mjs +0 -37
  52. package/vitest.config.ts.timestamp-1711743471018-f8eca63460d15.mjs +0 -37
  53. package/vitest.config.ts.timestamp-1711743489536-332f6bf4f074c.mjs +0 -37
  54. package/vitest.config.ts.timestamp-1711744615240-85d4d02f24414.mjs +0 -37
@@ -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 { type MaybeRefOrGetter, type Pausable, useIntervalFn, type UseIntervalFnOptions } from "@vueuse/core"
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 type { MakeMutation2, MutationOptions } from "./mutate2.js"
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) => Promise<void>>
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<() => Promise<void>>
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) => Promise<Either<A, E>>,
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(f, (p) =>
222
- p.then(
223
- (r) =>
224
- r._tag === "Right"
225
- ? S.is(Failure)(r.right)
226
- ? Promise
227
- .resolve(
228
- toast.warning(
229
- warnMessage + r.right.message
230
- ? "\n" + r.right.message
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
- .then((_) => {})
235
- : Promise
236
- .resolve(
237
- toast.success(
238
- successMessage
239
- + (S.is(Success)(r.right) && r.right.message
240
- ? "\n" + r.right.message
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
- .then((_) => {
253
- console.warn(r.left, r.left.toString())
254
- }),
255
- (err) => {
256
- if (
257
- Cause.isInterruptedException(err)
258
- || (Runtime.isFiberFailure(err)
259
- && Cause.isInterruptedOnly(err[Runtime.FiberFailureCauseId]))
260
- ) {
261
- return
262
- }
263
- const extra = {
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
- return toast.error(
273
- intl.value.formatMessage(
274
- { id: "handle.unexpected_error" },
275
- {
276
- action: message,
277
- error: JSON.stringify(err, undefined, 2)
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>(self: {
429
- handler: (i: I) => Effect<A, E, R>
430
- name: string
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 const mapHandler: {
449
- <I, E, R, A, E2, A2, R2>(
450
- self: {
451
- handler: (i: I) => Effect<A, E, R>
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
- function orPrevious<E, A>(result: Result.Result<A, E>) {
521
- return Result.isFailure(result) && Option.isSome(result.previousValue)
522
- ? Result.success(result.previousValue.value, result.waiting)
523
- : result
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: HandlerWithInput<I, A, E, R>,
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>(self: Handler<A, E, R>, options?: MutationOptions): readonly [
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()