@effect-app/vue 2.15.1 → 2.16.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/CHANGELOG.md +16 -0
- package/_cjs/index.cjs +22 -0
- package/_cjs/index.cjs.map +1 -1
- package/_cjs/lib.cjs +4 -0
- package/_cjs/lib.cjs.map +1 -1
- package/_cjs/makeClient.cjs.map +1 -1
- package/_cjs/mutate.cjs +9 -16
- package/_cjs/mutate.cjs.map +1 -1
- package/_cjs/query.cjs +25 -0
- package/_cjs/query.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/lib.d.ts +4 -0
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +5 -1
- package/dist/makeClient.d.ts +23 -23
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +1 -1
- package/dist/mutate.d.ts +4 -3
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +8 -15
- package/dist/query.d.ts +5 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +30 -2
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/lib.ts +4 -0
- package/src/makeClient.ts +64 -25
- package/src/mutate.ts +37 -42
- package/src/query.ts +47 -1
package/src/mutate.ts
CHANGED
|
@@ -102,7 +102,8 @@ type MaybeRefDeep<T> = MaybeRef<
|
|
|
102
102
|
: T
|
|
103
103
|
>
|
|
104
104
|
|
|
105
|
-
export interface MutationOptions {
|
|
105
|
+
export interface MutationOptions<A, E, R, A2 = A, E2 = E, R2 = R, I = void> {
|
|
106
|
+
mapHandler?: (handler: Effect<A, E, R>, input: I) => Effect<A2, E2, R2>
|
|
106
107
|
queryInvalidation?: (defaultKey: string[], name: string) => {
|
|
107
108
|
filters?: MaybeRefDeep<InvalidateQueryFilters> | undefined
|
|
108
109
|
options?: MaybeRefDeep<InvalidateOptions> | undefined
|
|
@@ -126,33 +127,33 @@ export const makeMutation = () => {
|
|
|
126
127
|
* Returns a tuple with state ref and execution function which reports errors as Toast.
|
|
127
128
|
*/
|
|
128
129
|
const useSafeMutation: {
|
|
129
|
-
<I, E, A, R, Request extends TaggedRequestClassAny>(
|
|
130
|
+
<I, E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
|
|
130
131
|
self: RequestHandlerWithInput<I, A, E, R, Request>,
|
|
131
|
-
options?: MutationOptions
|
|
132
|
+
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
132
133
|
): readonly [
|
|
133
|
-
Readonly<Ref<MutationResult<
|
|
134
|
-
(i: I) => Effect<
|
|
134
|
+
Readonly<Ref<MutationResult<A2, E2>>>,
|
|
135
|
+
(i: I) => Effect<A2, E2, R2>
|
|
135
136
|
]
|
|
136
|
-
<E, A, R, Request extends TaggedRequestClassAny>(
|
|
137
|
+
<E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
|
|
137
138
|
self: RequestHandler<A, E, R, Request>,
|
|
138
|
-
options?: MutationOptions
|
|
139
|
+
options?: MutationOptions<A, E, R, A2, E2, R2>
|
|
139
140
|
): readonly [
|
|
140
|
-
Readonly<Ref<MutationResult<
|
|
141
|
-
Effect<
|
|
141
|
+
Readonly<Ref<MutationResult<A2, E2>>>,
|
|
142
|
+
Effect<A2, E2, R2>
|
|
142
143
|
]
|
|
143
|
-
} = <I, E, A, R, Request extends TaggedRequestClassAny>(
|
|
144
|
+
} = <I, E, A, R, Request extends TaggedRequestClassAny, A2 = A, E2 = E, R2 = R>(
|
|
144
145
|
self: RequestHandlerWithInput<I, A, E, R, Request> | RequestHandler<A, E, R, Request>,
|
|
145
|
-
options?: MutationOptions
|
|
146
|
+
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
146
147
|
) => {
|
|
147
148
|
const queryClient = useQueryClient()
|
|
148
|
-
const state: Ref<MutationResult<
|
|
149
|
+
const state: Ref<MutationResult<A2, E2>> = ref<MutationResult<A2, E2>>({ _tag: "Initial" }) as any
|
|
149
150
|
|
|
150
151
|
const invalidateQueries = (
|
|
151
152
|
filters?: MaybeRefDeep<InvalidateQueryFilters>,
|
|
152
153
|
options?: MaybeRefDeep<InvalidateOptions>
|
|
153
154
|
) => Effect.promise(() => queryClient.invalidateQueries(filters, options))
|
|
154
155
|
|
|
155
|
-
function handleExit(exit: Exit.Exit<
|
|
156
|
+
function handleExit(exit: Exit.Exit<A2, E2>) {
|
|
156
157
|
return Effect.sync(() => {
|
|
157
158
|
if (Exit.isSuccess(exit)) {
|
|
158
159
|
state.value = { _tag: "Success", data: exit.value }
|
|
@@ -193,36 +194,30 @@ export const makeMutation = () => {
|
|
|
193
194
|
.pipe(Effect.withSpan("client.query.invalidation", { captureStackTrace: false }))
|
|
194
195
|
})
|
|
195
196
|
|
|
197
|
+
const mapHandler = options?.mapHandler ?? ((_) => _)
|
|
198
|
+
|
|
199
|
+
const handle = (self: Effect<A, E, R>, name: string, i: I | void = void 0) =>
|
|
200
|
+
Effect
|
|
201
|
+
.sync(() => {
|
|
202
|
+
state.value = { _tag: "Loading" }
|
|
203
|
+
})
|
|
204
|
+
.pipe(
|
|
205
|
+
Effect.zipRight(
|
|
206
|
+
mapHandler(
|
|
207
|
+
Effect.tapBoth(self, { onFailure: () => invalidateCache, onSuccess: () => invalidateCache }),
|
|
208
|
+
i as I
|
|
209
|
+
) as Effect<A2, E2, R2>
|
|
210
|
+
),
|
|
211
|
+
Effect.tapDefect(reportRuntimeError),
|
|
212
|
+
Effect.onExit(handleExit),
|
|
213
|
+
Effect.withSpan(`mutation ${name}`, { captureStackTrace: false })
|
|
214
|
+
)
|
|
215
|
+
|
|
196
216
|
const handler = self.handler
|
|
197
|
-
const r =
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
.sync(() => {
|
|
202
|
-
state.value = { _tag: "Loading" }
|
|
203
|
-
})
|
|
204
|
-
.pipe(
|
|
205
|
-
Effect.zipRight(handler),
|
|
206
|
-
Effect.tap(invalidateCache),
|
|
207
|
-
Effect.tapDefect(reportRuntimeError),
|
|
208
|
-
Effect.onExit(handleExit),
|
|
209
|
-
Effect.withSpan(`mutation ${self.name}`, { captureStackTrace: false })
|
|
210
|
-
)
|
|
211
|
-
)
|
|
212
|
-
: tuple(state, (fst: I) => {
|
|
213
|
-
const effect = handler(fst)
|
|
214
|
-
return Effect
|
|
215
|
-
.sync(() => {
|
|
216
|
-
state.value = { _tag: "Loading" }
|
|
217
|
-
})
|
|
218
|
-
.pipe(
|
|
219
|
-
Effect.zipRight(effect),
|
|
220
|
-
Effect.tapBoth({ onFailure: () => invalidateCache, onSuccess: () => invalidateCache }),
|
|
221
|
-
Effect.tapDefect(reportRuntimeError),
|
|
222
|
-
Effect.onExit(handleExit),
|
|
223
|
-
Effect.withSpan(`mutation ${self.name}`, { captureStackTrace: false })
|
|
224
|
-
)
|
|
225
|
-
})
|
|
217
|
+
const r = tuple(
|
|
218
|
+
state,
|
|
219
|
+
Effect.isEffect(handler) ? handle(handler, self.name) : (i: I) => handle(handler(i), self.name, i)
|
|
220
|
+
)
|
|
226
221
|
|
|
227
222
|
return r as any
|
|
228
223
|
}
|
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 type { RequestHandler, RequestHandlerWithInput, TaggedRequestClassAny } from "effect-app/client/clientFor"
|
|
18
18
|
import { isHttpRequestError, isHttpResponseError } from "effect-app/http/http-client"
|
|
@@ -203,3 +203,49 @@ export const makeQuery = <R>(runtime: ShallowRef<Runtime.Runtime<R> | undefined>
|
|
|
203
203
|
|
|
204
204
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
205
205
|
export interface MakeQuery2<R> extends ReturnType<typeof makeQuery<R>> {}
|
|
206
|
+
|
|
207
|
+
function orPrevious<E, A>(result: Result.Result<A, E>) {
|
|
208
|
+
return Result.isFailure(result) && Option.isSome(result.previousValue)
|
|
209
|
+
? Result.success(result.previousValue.value, result.waiting)
|
|
210
|
+
: result
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function composeQueries<
|
|
214
|
+
R extends Record<string, Result.Result<any, any>>
|
|
215
|
+
>(
|
|
216
|
+
results: R,
|
|
217
|
+
renderPreviousOnFailure?: boolean
|
|
218
|
+
): Result.Result<
|
|
219
|
+
{
|
|
220
|
+
[Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
|
|
221
|
+
: never
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
[Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
|
|
225
|
+
: never
|
|
226
|
+
}[keyof R]
|
|
227
|
+
> {
|
|
228
|
+
const values = renderPreviousOnFailure
|
|
229
|
+
? Object.values(results).map(orPrevious)
|
|
230
|
+
: Object.values(results)
|
|
231
|
+
const error = values.find(Result.isFailure)
|
|
232
|
+
if (error) {
|
|
233
|
+
return error
|
|
234
|
+
}
|
|
235
|
+
const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
|
|
236
|
+
if (initial.value !== undefined) {
|
|
237
|
+
return initial.value
|
|
238
|
+
}
|
|
239
|
+
const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
|
|
240
|
+
if (loading.value !== undefined) {
|
|
241
|
+
return loading.value
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const isRefreshing = values.some((x) => x.waiting)
|
|
245
|
+
|
|
246
|
+
const r = Object.entries(results).reduce((prev, [key, value]) => {
|
|
247
|
+
prev[key] = Result.value(value).value
|
|
248
|
+
return prev
|
|
249
|
+
}, {} as any)
|
|
250
|
+
return Result.success(r, isRefreshing)
|
|
251
|
+
}
|