@effect-app/vue 2.32.0 → 2.34.0

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/src/mutate.ts CHANGED
@@ -2,13 +2,13 @@
2
2
  import * as Result from "@effect-rx/rx/Result"
3
3
  import type { InvalidateOptions, InvalidateQueryFilters } from "@tanstack/vue-query"
4
4
  import { useQueryClient } from "@tanstack/vue-query"
5
- import type { Cause } from "effect-app"
5
+ import type { Cause, Exit } from "effect-app"
6
6
  import { Effect, Option } from "effect-app"
7
7
  import type { RequestHandler, RequestHandlerWithInput, TaggedRequestClassAny } from "effect-app/client/clientFor"
8
8
  import { tuple } from "effect-app/Function"
9
9
  import type { ComputedRef, Ref } from "vue"
10
10
  import { computed, shallowRef } from "vue"
11
- import { makeQueryKey, reportRuntimeError } from "./lib.js"
11
+ import { makeQueryKey } from "./lib.js"
12
12
 
13
13
  export const getQueryKey = (h: { name: string }) => {
14
14
  const key = makeQueryKey(h)
@@ -70,15 +70,6 @@ export function make<A, E, R>(self: Effect<A, E, R>) {
70
70
  return tuple(result, latestSuccess, execute)
71
71
  }
72
72
 
73
- export type MaybeRef<T> = Ref<T> | ComputedRef<T> | T
74
- type MaybeRefDeep<T> = MaybeRef<
75
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
76
- T extends Function ? T
77
- : T extends object ? {
78
- [Property in keyof T]: MaybeRefDeep<T[Property]>
79
- }
80
- : T
81
- >
82
73
 
83
74
  export interface MutationOptions<A, E, R, A2 = A, E2 = E, R2 = R, I = void> {
84
75
  /**
@@ -91,8 +82,8 @@ export interface MutationOptions<A, E, R, A2 = A, E2 = E, R2 = R, I = void> {
91
82
  * This can be overridden by providing a function that returns an array of filters and options.
92
83
  */
93
84
  queryInvalidation?: (defaultKey: string[], name: string) => {
94
- filters?: MaybeRefDeep<InvalidateQueryFilters> | undefined
95
- options?: MaybeRefDeep<InvalidateOptions> | undefined
85
+ filters?: InvalidateQueryFilters | undefined
86
+ options?: InvalidateOptions | undefined
96
87
  }[]
97
88
  }
98
89
 
@@ -107,22 +98,46 @@ export interface MutationOptions<A, E, R, A2 = A, E2 = E, R2 = R, I = void> {
107
98
  // }
108
99
  */
109
100
 
110
- export const asResult = <Args extends readonly any[], A, E, R>(
111
- handler: (...args: Args) => Effect<A, E, R>
101
+ export const asResult: {
102
+ <A, E, R>(
103
+ handler: Effect<A, E, R>
104
+ ): readonly [ComputedRef<Result.Result<A, E>>, Effect<Exit<A, E>, never, void>]
105
+ <Args extends readonly any[], A, E, R>(
106
+ handler: (...args: Args) => Effect<A, E, R>
107
+ ): readonly [ComputedRef<Result.Result<A, E>>, (...args: Args) => Effect<Exit<A, E>, never, void>]
108
+ } = <Args extends readonly any[], A, E, R>(
109
+ handler: Effect<A, E, R> | ((...args: Args) => Effect<A, E, R>)
112
110
  ) => {
113
111
  const state = shallowRef<Result.Result<A, E>>(Result.initial())
114
112
 
115
- const act = (...args: Args) =>
116
- Effect
113
+ const act = Effect.isEffect(handler)
114
+ ? Effect
117
115
  .sync(() => {
118
116
  state.value = Result.initial(true)
119
117
  })
120
118
  .pipe(
121
- Effect.zipRight(Effect.suspend(() => handler(...args))),
122
- Effect.onExit((exit) => Effect.sync(() => (state.value = Result.fromExit(exit))))
119
+ Effect.zipRight(Effect.suspend(() =>
120
+ handler.pipe(
121
+ Effect.exit,
122
+ Effect.tap((exit) => Effect.sync(() => (state.value = Result.fromExit(exit))))
123
+ )
124
+ ))
123
125
  )
126
+ : (...args: Args) =>
127
+ Effect
128
+ .sync(() => {
129
+ state.value = Result.initial(true)
130
+ })
131
+ .pipe(
132
+ Effect.zipRight(Effect.suspend(() =>
133
+ handler(...args).pipe(
134
+ Effect.exit,
135
+ Effect.tap((exit) => Effect.sync(() => (state.value = Result.fromExit(exit))))
136
+ )
137
+ ))
138
+ )
124
139
 
125
- return tuple(state, act)
140
+ return tuple(computed(() => state.value), act) as any
126
141
  }
127
142
 
128
143
  export const makeMutation = () => {
@@ -130,21 +145,15 @@ export const makeMutation = () => {
130
145
  * Pass a function that returns an Effect, e.g from a client action, or an Effect
131
146
  * Returns a tuple with state ref and execution function which reports errors as Toast.
132
147
  */
133
- const useSafeMutation: {
148
+ const useMutation: {
134
149
  <I, E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
135
150
  self: RequestHandlerWithInput<I, A, E, R, Request>,
136
151
  options?: MutationOptions<A, E, R, A2, E2, R2, I>
137
- ): readonly [
138
- Readonly<Ref<Result.Result<A2, E2>>>,
139
- (i: I) => Effect<A2, E2, R2>
140
- ]
152
+ ): (i: I) => Effect<A2, E2, R2>
141
153
  <E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
142
154
  self: RequestHandler<A, E, R, Request>,
143
155
  options?: MutationOptions<A, E, R, A2, E2, R2>
144
- ): readonly [
145
- Readonly<Ref<Result.Result<A2, E2>>>,
146
- Effect<A2, E2, R2>
147
- ]
156
+ ): Effect<A2, E2, R2>
148
157
  } = <I, E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
149
158
  self: RequestHandlerWithInput<I, A, E, R, Request> | RequestHandler<A, E, R, Request>,
150
159
  options?: MutationOptions<A, E, R, A2, E2, R2, I>
@@ -152,8 +161,8 @@ export const makeMutation = () => {
152
161
  const queryClient = useQueryClient()
153
162
 
154
163
  const invalidateQueries = (
155
- filters?: MaybeRefDeep<InvalidateQueryFilters>,
156
- options?: MaybeRefDeep<InvalidateOptions>
164
+ filters?: InvalidateQueryFilters,
165
+ options?: InvalidateOptions
157
166
  ) => Effect.promise(() => queryClient.invalidateQueries(filters, options))
158
167
 
159
168
  const invalidateCache = Effect.suspend(() => {
@@ -184,26 +193,17 @@ export const makeMutation = () => {
184
193
 
185
194
  const mapHandler = options?.mapHandler ?? ((_) => _)
186
195
 
187
- const [state, handle_] = asResult((self: Effect<A, E, R>, i: I | void = void 0) => (mapHandler(
196
+ const handle = (self: Effect<A, E, R>, i: I | void = void 0) => (mapHandler(
188
197
  Effect.tapBoth(self, { onFailure: () => invalidateCache, onSuccess: () => invalidateCache }),
189
198
  i as I
190
- ) as Effect<A2, E2, R2>))
191
-
192
- const handle = (self: Effect<A, E, R>, name: string, i: I | void = void 0) =>
193
- handle_(self, i).pipe(
194
- Effect.tapDefect(reportRuntimeError),
195
- Effect.withSpan(`mutation ${name}`, { captureStackTrace: false })
196
- )
199
+ ) as Effect<A2, E2, R2>)
197
200
 
198
201
  const handler = self.handler
199
- const r = tuple(
200
- state,
201
- Effect.isEffect(handler) ? handle(handler, self.name) : (i: I) => handle(handler(i), self.name, i)
202
- )
202
+ const r = Effect.isEffect(handler) ? handle(handler) : (i: I) => handle(handler(i), i)
203
203
 
204
204
  return r as any
205
205
  }
206
- return useSafeMutation
206
+ return useMutation
207
207
  }
208
208
 
209
209
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type