@effect-app/vue 4.0.0-beta.15 → 4.0.0-beta.150
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 +952 -0
- package/dist/commander.d.ts +370 -0
- package/dist/commander.d.ts.map +1 -0
- package/dist/commander.js +587 -0
- package/dist/confirm.d.ts +19 -0
- package/dist/confirm.d.ts.map +1 -0
- package/dist/confirm.js +24 -0
- package/dist/errorReporter.d.ts +4 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +12 -18
- package/dist/form.d.ts +13 -4
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +38 -9
- package/dist/index.d.ts +1 -1
- package/dist/intl.d.ts +15 -0
- package/dist/intl.d.ts.map +1 -0
- package/dist/intl.js +9 -0
- package/dist/lib.d.ts +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/makeClient.d.ts +84 -275
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +44 -351
- package/dist/makeContext.d.ts +1 -1
- package/dist/makeContext.d.ts.map +1 -1
- package/dist/makeIntl.d.ts +1 -1
- package/dist/makeIntl.d.ts.map +1 -1
- package/dist/makeUseCommand.d.ts +8 -0
- package/dist/makeUseCommand.d.ts.map +1 -0
- package/dist/makeUseCommand.js +13 -0
- package/dist/mutate.d.ts +2 -2
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +1 -1
- package/dist/query.d.ts +11 -15
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +24 -24
- package/dist/routeParams.d.ts +1 -1
- package/dist/runtime.d.ts +5 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +27 -17
- package/dist/toast.d.ts +46 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +32 -0
- package/dist/withToast.d.ts +26 -0
- package/dist/withToast.d.ts.map +1 -0
- package/dist/withToast.js +49 -0
- package/package.json +46 -46
- package/src/{experimental/commander.ts → commander.ts} +922 -249
- package/src/{experimental/confirm.ts → confirm.ts} +10 -14
- package/src/errorReporter.ts +60 -72
- package/src/form.ts +51 -12
- package/src/intl.ts +12 -0
- package/src/makeClient.ts +177 -1008
- package/src/{experimental/makeUseCommand.ts → makeUseCommand.ts} +3 -3
- package/src/query.ts +45 -46
- package/src/runtime.ts +39 -18
- package/src/{experimental/toast.ts → toast.ts} +11 -25
- package/src/{experimental/withToast.ts → withToast.ts} +15 -6
- package/test/Mutation.test.ts +130 -10
- package/test/dist/form.test.d.ts.map +1 -1
- package/test/dist/stubs.d.ts +983 -118
- package/test/dist/stubs.d.ts.map +1 -1
- package/test/dist/stubs.js +50 -23
- package/test/form-validation-errors.test.ts +23 -19
- package/test/form.test.ts +20 -2
- package/test/makeClient.test.ts +54 -39
- package/test/stubs.ts +61 -26
- package/tsconfig.json +0 -1
- package/dist/experimental/commander.d.ts +0 -359
- package/dist/experimental/commander.d.ts.map +0 -1
- package/dist/experimental/commander.js +0 -557
- package/dist/experimental/confirm.d.ts +0 -19
- package/dist/experimental/confirm.d.ts.map +0 -1
- package/dist/experimental/confirm.js +0 -28
- package/dist/experimental/intl.d.ts +0 -16
- package/dist/experimental/intl.d.ts.map +0 -1
- package/dist/experimental/intl.js +0 -5
- package/dist/experimental/makeUseCommand.d.ts +0 -8
- package/dist/experimental/makeUseCommand.d.ts.map +0 -1
- package/dist/experimental/makeUseCommand.js +0 -13
- package/dist/experimental/toast.d.ts +0 -47
- package/dist/experimental/toast.d.ts.map +0 -1
- package/dist/experimental/toast.js +0 -41
- package/dist/experimental/withToast.d.ts +0 -25
- package/dist/experimental/withToast.d.ts.map +0 -1
- package/dist/experimental/withToast.js +0 -45
- package/src/experimental/intl.ts +0 -9
package/src/makeClient.ts
CHANGED
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { type InvalidateOptions, type InvalidateQueryFilters, isCancelledError, type QueryObserverResult, type RefetchOptions, type UseQueryReturnType } from "@tanstack/vue-query"
|
|
3
3
|
import { camelCase } from "change-case"
|
|
4
|
-
import {
|
|
4
|
+
import { type Context, Effect, Exit, type Layer, type ManagedRuntime, Struct } from "effect-app"
|
|
5
5
|
import { type ApiClientFactory, type Req } from "effect-app/client"
|
|
6
|
-
import type { RequestHandler, RequestHandlers, RequestHandlerWithInput,
|
|
7
|
-
import {
|
|
8
|
-
import { constant, identity, pipe, tuple } from "effect-app/Function"
|
|
9
|
-
import { type OperationFailure, OperationSuccess } from "effect-app/Operations"
|
|
10
|
-
import { dropUndefinedT, extendM } from "effect-app/utils"
|
|
6
|
+
import type { ExtractModuleName, RequestHandler, RequestHandlers, RequestHandlerWithInput, RequestsAny } from "effect-app/client/clientFor"
|
|
7
|
+
import { extendM } from "effect-app/utils"
|
|
11
8
|
import { type Fiber } from "effect/Fiber"
|
|
12
9
|
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { type
|
|
16
|
-
import {
|
|
17
|
-
import { type
|
|
18
|
-
import { Toast } from "./experimental/toast.js"
|
|
19
|
-
import { buildFieldInfoFromFieldsRoot } from "./form.js"
|
|
20
|
-
import { reportRuntimeError } from "./lib.js"
|
|
21
|
-
import { asResult, makeMutation, type MutationOptions, type MutationOptionsBase, mutationResultToVue, type Res, useMakeMutation } from "./mutate.js"
|
|
10
|
+
import { type ComputedRef, onBeforeUnmount, ref, type WatchSource } from "vue"
|
|
11
|
+
import { type Commander, CommanderStatic } from "./commander.js"
|
|
12
|
+
import { type I18n } from "./intl.js"
|
|
13
|
+
import { type CommanderResolved, makeUseCommand } from "./makeUseCommand.js"
|
|
14
|
+
import { makeMutation, type MutationOptionsBase, useMakeMutation } from "./mutate.js"
|
|
22
15
|
import { type CustomUndefinedInitialQueryOptions, makeQuery } from "./query.js"
|
|
16
|
+
import { makeRunPromise } from "./runtime.js"
|
|
17
|
+
import { type Toast } from "./toast.js"
|
|
23
18
|
|
|
24
19
|
const mapHandler = <A, E, R, I = void, A2 = A, E2 = E, R2 = R>(
|
|
25
20
|
handler: Effect.Effect<A, E, R> | ((i: I) => Effect.Effect<A, E, R>),
|
|
26
21
|
map: (self: Effect.Effect<A, E, R>, i: I) => Effect.Effect<A2, E2, R2>
|
|
27
22
|
) => Effect.isEffect(handler) ? map(handler, undefined as any) : (i: I) => map(handler(i), i)
|
|
28
23
|
|
|
29
|
-
export interface
|
|
24
|
+
export interface CommandRequestExtensions<RT, Id extends string, I, A, E, R> {
|
|
30
25
|
/** Defines a Command based on this call, taking the `id` of the call as the `id` of the Command.
|
|
31
26
|
* The Request function will be taken as the first member of the Command, the Command required input will be the Request input.
|
|
32
27
|
* see Command.wrap for details */
|
|
@@ -44,16 +39,14 @@ export interface RequestExtWithInput<
|
|
|
44
39
|
A,
|
|
45
40
|
E,
|
|
46
41
|
R
|
|
47
|
-
> extends Commander.CommandContextLocal<Id, Id>,
|
|
42
|
+
> extends Commander.CommandContextLocal<Id, Id>, CommandRequestExtensions<RT, Id, I, A, E, R> {
|
|
48
43
|
/**
|
|
49
|
-
*
|
|
44
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
45
|
+
* This does not perform query cache invalidation.
|
|
50
46
|
*/
|
|
51
|
-
(i: I)
|
|
47
|
+
request: (i: I) => Effect.Effect<A, E, R>
|
|
52
48
|
}
|
|
53
49
|
|
|
54
|
-
/**
|
|
55
|
-
* Request the endpoint
|
|
56
|
-
*/
|
|
57
50
|
export interface RequestExt<
|
|
58
51
|
RT,
|
|
59
52
|
Id extends string,
|
|
@@ -63,25 +56,62 @@ export interface RequestExt<
|
|
|
63
56
|
> extends
|
|
64
57
|
Commander.CommandContextLocal<Id, Id>,
|
|
65
58
|
Commander.CommanderWrap<RT, Id, Id, undefined, void, A, E, R>,
|
|
66
|
-
|
|
67
|
-
Effect.Effect<A, E, R>
|
|
59
|
+
CommandRequestExtensions<RT, Id, void, A, E, R>
|
|
68
60
|
{
|
|
61
|
+
/**
|
|
62
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
63
|
+
* This does not perform query cache invalidation.
|
|
64
|
+
*/
|
|
65
|
+
request: Effect.Effect<A, E, R>
|
|
69
66
|
}
|
|
70
67
|
|
|
71
|
-
export type
|
|
68
|
+
export type CommandRequestWithExtensions<RT, Req> = Req extends
|
|
72
69
|
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer _Request, infer Id>
|
|
73
70
|
? RequestExtWithInput<RT, Id, I, A, E, R>
|
|
74
71
|
: Req extends RequestHandler<infer A, infer E, infer R, infer _Request, infer Id> ? RequestExt<RT, Id, A, E, R>
|
|
75
72
|
: never
|
|
76
73
|
|
|
74
|
+
export interface QueryExtensionsWithInput<I, A, E, R> {
|
|
75
|
+
/**
|
|
76
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
77
|
+
* This does not set up query state tracking.
|
|
78
|
+
*/
|
|
79
|
+
request: (i: I) => Effect.Effect<A, E, R>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface QueryExtensions<A, E, R> {
|
|
83
|
+
/**
|
|
84
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
85
|
+
* This does not set up query state tracking.
|
|
86
|
+
*/
|
|
87
|
+
request: Effect.Effect<A, E, R>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type QueryRequestWithExtensions<Req> = Req extends
|
|
91
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer _Request, infer _Id>
|
|
92
|
+
? QueryExtensionsWithInput<I, A, E, R>
|
|
93
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer _Request, infer _Id> ? QueryExtensions<A, E, R>
|
|
94
|
+
: never
|
|
95
|
+
|
|
96
|
+
type QueryHandler<Req> = Req extends
|
|
97
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
98
|
+
? Request["type"] extends "query" ? RequestHandlerWithInput<I, A, E, R, Request, Id> : never
|
|
99
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
100
|
+
? Request["type"] extends "query" ? RequestHandler<A, E, R, Request, Id> : never
|
|
101
|
+
: never
|
|
102
|
+
|
|
103
|
+
type CommandHandler<Req> = Req extends
|
|
104
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
105
|
+
? Request["type"] extends "command" ? RequestHandlerWithInput<I, A, E, R, Request, Id> : never
|
|
106
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
107
|
+
? Request["type"] extends "command" ? RequestHandler<A, E, R, Request, Id> : never
|
|
108
|
+
: never
|
|
109
|
+
|
|
77
110
|
export interface MutationExtensions<RT, Id extends string, I, A, E, R> {
|
|
78
111
|
/** Defines a Command based on this mutation, taking the `id` of the mutation as the `id` of the Command.
|
|
79
112
|
* The Mutation function will be taken as the first member of the Command, the Command required input will be the Mutation input.
|
|
80
113
|
* see Command.wrap for details */
|
|
81
114
|
wrap: Commander.CommanderWrap<RT, Id, Id, undefined, I, A, E, R>
|
|
82
|
-
/** Defines a Command based on this mutation, taking the `id` of the mutation as the `id` of the Command.
|
|
83
|
-
* see Command.fn for details */
|
|
84
|
-
fn: Commander.CommanderFn<RT, Id, Id, undefined>
|
|
85
115
|
}
|
|
86
116
|
|
|
87
117
|
/** my other doc */
|
|
@@ -92,19 +122,23 @@ export interface MutationExtWithInput<
|
|
|
92
122
|
A,
|
|
93
123
|
E,
|
|
94
124
|
R
|
|
95
|
-
> extends
|
|
125
|
+
> extends MutationExtensions<RT, Id, I, A, E, R> {
|
|
96
126
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
127
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
128
|
+
* Also invalidates query caches using the request namespace by default.
|
|
129
|
+
* Namespace invalidation targets parent namespace keys
|
|
130
|
+
* (for example `$project/$configuration.get` invalidates `$project`).
|
|
131
|
+
* Override invalidation in client options via `queryInvalidation`.
|
|
100
132
|
*/
|
|
101
133
|
(i: I): Effect.Effect<A, E, R>
|
|
102
134
|
}
|
|
103
135
|
|
|
104
136
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
137
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
138
|
+
* Also invalidates query caches using the request namespace by default.
|
|
139
|
+
* Namespace invalidation targets parent namespace keys
|
|
140
|
+
* (for example `$project/$configuration.get` invalidates `$project`).
|
|
141
|
+
* Override invalidation in client options via `queryInvalidation`.
|
|
108
142
|
*/
|
|
109
143
|
export interface MutationExt<
|
|
110
144
|
RT,
|
|
@@ -112,12 +146,7 @@ export interface MutationExt<
|
|
|
112
146
|
A,
|
|
113
147
|
E,
|
|
114
148
|
R
|
|
115
|
-
> extends
|
|
116
|
-
Commander.CommandContextLocal<Id, Id>,
|
|
117
|
-
Commander.CommanderWrap<RT, Id, Id, undefined, void, A, E, R>,
|
|
118
|
-
MutationExtensions<RT, Id, void, A, E, R>,
|
|
119
|
-
Effect.Effect<A, E, R>
|
|
120
|
-
{
|
|
149
|
+
> extends MutationExtensions<RT, Id, void, A, E, R>, Effect.Effect<A, E, R> {
|
|
121
150
|
}
|
|
122
151
|
|
|
123
152
|
export type MutationWithExtensions<RT, Req> = Req extends
|
|
@@ -134,27 +163,29 @@ declare const useSuspenseQuery_: QueryImpl<any>["useSuspenseQuery"]
|
|
|
134
163
|
|
|
135
164
|
export interface QueriesWithInput<Request extends Req, Id extends string, I, A, E> {
|
|
136
165
|
/**
|
|
137
|
-
*
|
|
166
|
+
* Read helper for query requests.
|
|
167
|
+
* Runs as a tracked Vue Query and returns reactive state.
|
|
168
|
+
* Queries read state and should not be used to mutate it.
|
|
138
169
|
*/
|
|
139
170
|
query: ReturnType<typeof useQuery_<I, E, A, Request, Id>>
|
|
140
171
|
// TODO or suspense as Option?
|
|
141
172
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* So that Suspense and error boundaries can be used.
|
|
173
|
+
* Like `.query`, but returns a Promise for setup-time awaiting.
|
|
174
|
+
* Use this when integrating with Vue Suspense / error boundaries.
|
|
145
175
|
*/
|
|
146
176
|
suspense: ReturnType<typeof useSuspenseQuery_<I, E, A, Request, Id>>
|
|
147
177
|
}
|
|
148
178
|
export interface QueriesWithoutInput<Request extends Req, Id extends string, A, E> {
|
|
149
179
|
/**
|
|
150
|
-
*
|
|
180
|
+
* Read helper for query requests.
|
|
181
|
+
* Runs as a tracked Vue Query and returns reactive state.
|
|
182
|
+
* Queries read state and should not be used to mutate it.
|
|
151
183
|
*/
|
|
152
184
|
query: ReturnType<typeof useQuery_<E, A, Request, Id>>
|
|
153
185
|
// TODO or suspense as Option?
|
|
154
186
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* So that Suspense and error boundaries can be used.
|
|
187
|
+
* Like `.query`, but returns a Promise for setup-time awaiting.
|
|
188
|
+
* Use this when integrating with Vue Suspense / error boundaries.
|
|
158
189
|
*/
|
|
159
190
|
suspense: ReturnType<typeof useSuspenseQuery_<E, A, Request, Id>>
|
|
160
191
|
}
|
|
@@ -166,176 +197,18 @@ export type MissingDependencies<RT, R> = {
|
|
|
166
197
|
|
|
167
198
|
export type Queries<RT, Req> = Req extends
|
|
168
199
|
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
169
|
-
? Exclude<R, RT> extends never ? QueriesWithInput<Request, Id, I, A, E>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
200
|
+
? Request["type"] extends "query" ? Exclude<R, RT> extends never ? QueriesWithInput<Request, Id, I, A, E>
|
|
201
|
+
: {
|
|
202
|
+
query: MissingDependencies<RT, R> & {}
|
|
203
|
+
suspense: MissingDependencies<RT, R> & {}
|
|
204
|
+
}
|
|
205
|
+
: never
|
|
174
206
|
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
175
|
-
? Exclude<R, RT> extends never ? QueriesWithoutInput<Request, Id, A, E>
|
|
176
|
-
|
|
207
|
+
? Request["type"] extends "query" ? Exclude<R, RT> extends never ? QueriesWithoutInput<Request, Id, A, E>
|
|
208
|
+
: { query: MissingDependencies<RT, R> & {}; suspense: MissingDependencies<RT, R> & {} }
|
|
209
|
+
: never
|
|
177
210
|
: never
|
|
178
211
|
|
|
179
|
-
/**
|
|
180
|
-
* Use this after handling an error yourself, still continueing on the Error track, but the error will not be reported.
|
|
181
|
-
*/
|
|
182
|
-
export class SuppressErrors extends Data.TaggedError("SuppressErrors")<{}> {
|
|
183
|
-
readonly [ErrorSilenced] = true as const
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export type ResponseErrors = S.SchemaError | SupportedErrors | SuppressErrors | OperationFailure
|
|
187
|
-
|
|
188
|
-
export interface Opts<
|
|
189
|
-
A,
|
|
190
|
-
E,
|
|
191
|
-
R,
|
|
192
|
-
I = void,
|
|
193
|
-
A2 = A,
|
|
194
|
-
E2 = E,
|
|
195
|
-
R2 = R,
|
|
196
|
-
ESuccess = never,
|
|
197
|
-
RSuccess = never,
|
|
198
|
-
EError = never,
|
|
199
|
-
RError = never,
|
|
200
|
-
EDefect = never,
|
|
201
|
-
RDefect = never
|
|
202
|
-
> extends MutationOptions<A, E, R, A2, E2, R2, I> {
|
|
203
|
-
/** set to `undefined` to use default message */
|
|
204
|
-
successMessage?: ((a: A2, i: I) => Effect.Effect<string | undefined, ESuccess, RSuccess>) | undefined
|
|
205
|
-
/** set to `undefined` to use default message */
|
|
206
|
-
failMessage?: ((e: E2, i: I) => Effect.Effect<string | undefined, EError, RError>) | undefined
|
|
207
|
-
/** set to `undefined` to use default message */
|
|
208
|
-
defectMessage?: ((e: Cause.Cause<E2>, i: I) => Effect.Effect<string | undefined, EDefect, RDefect>) | undefined
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export interface LowOpts<
|
|
212
|
-
A,
|
|
213
|
-
E,
|
|
214
|
-
I = void,
|
|
215
|
-
ESuccess = never,
|
|
216
|
-
RSuccess = never,
|
|
217
|
-
EError = never,
|
|
218
|
-
RError = never,
|
|
219
|
-
EDefect = never,
|
|
220
|
-
RDefect = never
|
|
221
|
-
> {
|
|
222
|
-
onSuccess: (a: A, i: I) => Effect.Effect<void, ESuccess, RSuccess>
|
|
223
|
-
onFail: (e: E, i: I) => Effect.Effect<void, EError, RError>
|
|
224
|
-
onDefect: (e: Cause.Cause<E>, i: I) => Effect.Effect<void, EDefect, RDefect>
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface LowOptsOptional<
|
|
228
|
-
A,
|
|
229
|
-
E,
|
|
230
|
-
R,
|
|
231
|
-
I = void,
|
|
232
|
-
A2 = A,
|
|
233
|
-
E2 = E,
|
|
234
|
-
R2 = R,
|
|
235
|
-
ESuccess = never,
|
|
236
|
-
RSuccess = never,
|
|
237
|
-
EError = never,
|
|
238
|
-
RError = never,
|
|
239
|
-
EDefect = never,
|
|
240
|
-
RDefect = never
|
|
241
|
-
> extends MutationOptions<A, E, R, A2, E2, R2, I> {
|
|
242
|
-
onSuccess?: (a: A, i: I) => Effect.Effect<void, ESuccess, RSuccess>
|
|
243
|
-
onFail?: (e: E, i: I) => Effect.Effect<void, EError, RError>
|
|
244
|
-
onDefect?: (e: Cause.Cause<E>, i: I) => Effect.Effect<void, EDefect, RDefect>
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
type WithAction<A> = A & {
|
|
248
|
-
action: string
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// computed() takes a getter function and returns a readonly reactive ref
|
|
252
|
-
// object for the returned value from the getter.
|
|
253
|
-
|
|
254
|
-
type Resp<I, A, E, R, V = ComputedRef<Res<A, E>>> = readonly [
|
|
255
|
-
V,
|
|
256
|
-
WithAction<(I: I) => Effect.Effect<Exit.Exit<A, E>, never, R>>
|
|
257
|
-
]
|
|
258
|
-
|
|
259
|
-
type ActResp<A, E, R, V = ComputedRef<Res<A, E>>> = readonly [
|
|
260
|
-
V,
|
|
261
|
-
WithAction<Effect.Effect<Exit.Exit<A, E>, never, R>>
|
|
262
|
-
]
|
|
263
|
-
|
|
264
|
-
export const suppressToast = constant(Effect.succeed(undefined))
|
|
265
|
-
|
|
266
|
-
/** handles errors as specified and reports defects */
|
|
267
|
-
function handleRequest<
|
|
268
|
-
E extends ResponseErrors,
|
|
269
|
-
A,
|
|
270
|
-
R,
|
|
271
|
-
I = void,
|
|
272
|
-
ESuccess = never,
|
|
273
|
-
RSuccess = never,
|
|
274
|
-
EError = never,
|
|
275
|
-
RError = never,
|
|
276
|
-
EDefect = never,
|
|
277
|
-
RDefect = never
|
|
278
|
-
>(
|
|
279
|
-
f: Effect.Effect<Exit.Exit<A, E>, never, R> | ((i: I) => Effect.Effect<Exit.Exit<A, E>, never, R>),
|
|
280
|
-
id: string,
|
|
281
|
-
action: string,
|
|
282
|
-
options: {
|
|
283
|
-
onSuccess: (a: A, i: I) => Effect.Effect<void, ESuccess, RSuccess>
|
|
284
|
-
onFail: (e: E, i: I) => Effect.Effect<void, EError, RError>
|
|
285
|
-
onDefect: (e: Cause.Cause<E>, i: I) => Effect.Effect<void, EDefect, RDefect>
|
|
286
|
-
}
|
|
287
|
-
) {
|
|
288
|
-
const handleEffect = (i: any) => (self: Effect.Effect<Exit.Exit<A, E>, never, R>) =>
|
|
289
|
-
self.pipe(
|
|
290
|
-
Effect.tap(
|
|
291
|
-
Effect.matchCauseEffect({
|
|
292
|
-
onSuccess: (r) => options.onSuccess(r, i),
|
|
293
|
-
onFailure: (cause) =>
|
|
294
|
-
Effect.gen(function*() {
|
|
295
|
-
if (Cause.hasInterruptsOnly(cause)) {
|
|
296
|
-
console.info(`Interrupted while trying to ${action}`)
|
|
297
|
-
return
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const fail = Cause.findErrorOption(cause)
|
|
301
|
-
if (Option.isSome(fail)) {
|
|
302
|
-
if (fail.value._tag === "SuppressErrors") {
|
|
303
|
-
console.info(`Suppressed error trying to ${action}`, fail.value)
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
const message = `Failure trying to ${action}`
|
|
307
|
-
yield* reportMessage(message, { action, error: fail.value })
|
|
308
|
-
yield* options.onFail(fail.value, i)
|
|
309
|
-
return
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const extra = {
|
|
313
|
-
action,
|
|
314
|
-
message: `Unexpected Error trying to ${action}`
|
|
315
|
-
}
|
|
316
|
-
yield* reportRuntimeError(cause, extra)
|
|
317
|
-
|
|
318
|
-
yield* options.onDefect(cause, i)
|
|
319
|
-
})
|
|
320
|
-
})
|
|
321
|
-
),
|
|
322
|
-
Effect.withSpan(`mutation ${id}`, {}, { captureStackTrace: false })
|
|
323
|
-
)
|
|
324
|
-
return Object.assign(
|
|
325
|
-
Effect.isEffect(f)
|
|
326
|
-
? pipe(
|
|
327
|
-
f,
|
|
328
|
-
handleEffect(void 0)
|
|
329
|
-
)
|
|
330
|
-
: (i: I) =>
|
|
331
|
-
pipe(
|
|
332
|
-
f(i),
|
|
333
|
-
handleEffect(i)
|
|
334
|
-
),
|
|
335
|
-
{ action }
|
|
336
|
-
)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
212
|
const _useMutation = makeMutation()
|
|
340
213
|
|
|
341
214
|
/**
|
|
@@ -389,702 +262,10 @@ export const useMutationInt = (): typeof _useMutation => {
|
|
|
389
262
|
)
|
|
390
263
|
}
|
|
391
264
|
|
|
392
|
-
export
|
|
393
|
-
constructor(
|
|
394
|
-
private readonly getRuntime: () => ServiceMap.ServiceMap<RT>,
|
|
395
|
-
private readonly toast: Toast,
|
|
396
|
-
private readonly intl: I18n
|
|
397
|
-
) {}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
401
|
-
* you should use the result ref to render errors!
|
|
402
|
-
* @deprecated use `Command.fn` and friends instead
|
|
403
|
-
*/
|
|
404
|
-
readonly useSafeMutation: {
|
|
405
|
-
/**
|
|
406
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
407
|
-
* you should use the result ref to render errors!
|
|
408
|
-
* @deprecated use `Command.fn` and friends instead
|
|
409
|
-
*/
|
|
410
|
-
<I, E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
411
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
412
|
-
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
413
|
-
): readonly [
|
|
414
|
-
ComputedRef<AsyncResult.AsyncResult<A2, E2>>,
|
|
415
|
-
(i: I) => Effect.Effect<Exit.Exit<A2, E2>, never, R2>
|
|
416
|
-
]
|
|
417
|
-
/**
|
|
418
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
419
|
-
* you should use the result ref to render errors!
|
|
420
|
-
* @deprecated use `Command.fn` and friends instead
|
|
421
|
-
*/
|
|
422
|
-
<E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
423
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
424
|
-
options?: MutationOptions<A, E, R, A2, E2, R2>
|
|
425
|
-
): readonly [
|
|
426
|
-
ComputedRef<AsyncResult.AsyncResult<A2, E2>>,
|
|
427
|
-
Effect.Effect<Exit.Exit<A2, E2>, never, R2>
|
|
428
|
-
]
|
|
429
|
-
} = <I, E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
430
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name> | RequestHandler<A, E, R, Request, Name>,
|
|
431
|
-
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
432
|
-
) => {
|
|
433
|
-
const unsafe = _useMutation(self as any, options)
|
|
434
|
-
|
|
435
|
-
type MH = NonNullable<NonNullable<typeof options>["mapHandler"]>
|
|
436
|
-
const mh = options?.mapHandler ?? identity as MH
|
|
437
|
-
|
|
438
|
-
const [a, b] = asResult(
|
|
439
|
-
mapHandler(
|
|
440
|
-
mapHandler(unsafe as any, mh),
|
|
441
|
-
Effect.tapCauseIf(Cause.hasDies, (cause) => reportRuntimeError(cause))
|
|
442
|
-
) as any
|
|
443
|
-
)
|
|
444
|
-
return [
|
|
445
|
-
a,
|
|
446
|
-
mapHandler(
|
|
447
|
-
b,
|
|
448
|
-
Effect.withSpan(`mutation ${self.id}`, {}, { captureStackTrace: false })
|
|
449
|
-
)
|
|
450
|
-
] as const as any
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/** handles errors as toasts and reports defects
|
|
454
|
-
* @deprecated use `Command.fn` and friends instead
|
|
455
|
-
*/
|
|
456
|
-
readonly useHandleRequestWithToast = () => {
|
|
457
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
458
|
-
const self = this
|
|
459
|
-
return handleRequestWithToast
|
|
460
|
-
/**
|
|
461
|
-
* Pass a function that returns a Promise.
|
|
462
|
-
* Returns an execution function which reports errors as Toast.
|
|
463
|
-
*/
|
|
464
|
-
function handleRequestWithToast<
|
|
465
|
-
A,
|
|
466
|
-
E extends ResponseErrors,
|
|
467
|
-
R,
|
|
468
|
-
I = void,
|
|
469
|
-
A2 = A,
|
|
470
|
-
E2 extends ResponseErrors = E,
|
|
471
|
-
R2 = R,
|
|
472
|
-
ESuccess = never,
|
|
473
|
-
RSuccess = never,
|
|
474
|
-
EError = never,
|
|
475
|
-
RError = never,
|
|
476
|
-
EDefect = never,
|
|
477
|
-
RDefect = never
|
|
478
|
-
>(
|
|
479
|
-
f: Effect.Effect<Exit.Exit<A2, E2>, never, R2> | ((i: I) => Effect.Effect<Exit.Exit<A2, E2>, never, R2>),
|
|
480
|
-
id: string,
|
|
481
|
-
action: string,
|
|
482
|
-
options: Opts<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect> = {}
|
|
483
|
-
) {
|
|
484
|
-
const actionMessage = self.intl.formatMessage({ id: `action.${action}`, defaultMessage: action })
|
|
485
|
-
const defaultWarnMessage = self.intl.formatMessage(
|
|
486
|
-
{ id: "handle.with_warnings" },
|
|
487
|
-
{ action: actionMessage }
|
|
488
|
-
)
|
|
489
|
-
const defaultSuccessMessage = self.intl.formatMessage(
|
|
490
|
-
{ id: "handle.success" },
|
|
491
|
-
{ action: actionMessage }
|
|
492
|
-
)
|
|
493
|
-
const defaultErrorMessage = self.intl.formatMessage(
|
|
494
|
-
{ id: "handle.with_errors" },
|
|
495
|
-
{ action: actionMessage }
|
|
496
|
-
)
|
|
497
|
-
|
|
498
|
-
return handleRequest<E2, A2, R2, any, ESuccess, RSuccess, EError, RError, EDefect, RDefect>(f, id, action, {
|
|
499
|
-
onSuccess: Effect.fnUntraced(function*(a, i) {
|
|
500
|
-
const message = options.successMessage ? yield* options.successMessage(a, i) : defaultSuccessMessage
|
|
501
|
-
+ (S.is(OperationSuccess)(a) && a.message
|
|
502
|
-
? "\n" + a.message
|
|
503
|
-
: "")
|
|
504
|
-
if (message) {
|
|
505
|
-
yield* self.toast.success(message)
|
|
506
|
-
}
|
|
507
|
-
}),
|
|
508
|
-
onFail: Effect.fnUntraced(function*(e, i) {
|
|
509
|
-
if (!options.failMessage && e._tag === "OperationFailure") {
|
|
510
|
-
yield* self.toast.warning(
|
|
511
|
-
defaultWarnMessage + e.message
|
|
512
|
-
? "\n" + e.message
|
|
513
|
-
: ""
|
|
514
|
-
)
|
|
515
|
-
return
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
const message = options.failMessage
|
|
519
|
-
? yield* options.failMessage(e, i)
|
|
520
|
-
: `${defaultErrorMessage}:\n` + renderError(e)
|
|
521
|
-
if (message) {
|
|
522
|
-
yield* self.toast.error(message)
|
|
523
|
-
}
|
|
524
|
-
}),
|
|
525
|
-
onDefect: Effect.fnUntraced(function*(cause, i) {
|
|
526
|
-
const message = options.defectMessage
|
|
527
|
-
? yield* options.defectMessage(cause, i)
|
|
528
|
-
: self.intl.formatMessage(
|
|
529
|
-
{ id: "handle.unexpected_error" },
|
|
530
|
-
{
|
|
531
|
-
action: actionMessage,
|
|
532
|
-
error: Cause.pretty(cause)
|
|
533
|
-
}
|
|
534
|
-
)
|
|
535
|
-
if (message) {
|
|
536
|
-
yield* self.toast.error(message)
|
|
537
|
-
}
|
|
538
|
-
})
|
|
539
|
-
})
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
function renderError(e: ResponseErrors): string {
|
|
543
|
-
return Match.value(e as any).pipe(
|
|
544
|
-
Match.tags({
|
|
545
|
-
// HttpErrorRequest: e =>
|
|
546
|
-
// this.intl.value.formatMessage(
|
|
547
|
-
// { id: "handle.request_error" },
|
|
548
|
-
// { error: `${e.error}` },
|
|
549
|
-
// ),
|
|
550
|
-
// HttpErrorResponse: e =>
|
|
551
|
-
// e.response.status >= 500 ||
|
|
552
|
-
// e.response.body._tag !== "Some" ||
|
|
553
|
-
// !e.response.body.value
|
|
554
|
-
// ? this.intl.value.formatMessage(
|
|
555
|
-
// { id: "handle.error_response" },
|
|
556
|
-
// {
|
|
557
|
-
// error: `${
|
|
558
|
-
// e.response.body._tag === "Some" && e.response.body.value
|
|
559
|
-
// ? parseError(e.response.body.value)
|
|
560
|
-
// : "Unknown"
|
|
561
|
-
// } (${e.response.status})`,
|
|
562
|
-
// },
|
|
563
|
-
// )
|
|
564
|
-
// : this.intl.value.formatMessage(
|
|
565
|
-
// { id: "handle.unexpected_error" },
|
|
566
|
-
// {
|
|
567
|
-
// error:
|
|
568
|
-
// JSON.stringify(e.response.body, undefined, 2) +
|
|
569
|
-
// "( " +
|
|
570
|
-
// e.response.status +
|
|
571
|
-
// ")",
|
|
572
|
-
// },
|
|
573
|
-
// ),
|
|
574
|
-
// ResponseError: e =>
|
|
575
|
-
// this.intl.value.formatMessage(
|
|
576
|
-
// { id: "handle.response_error" },
|
|
577
|
-
// { error: `${e.error}` },
|
|
578
|
-
// ),
|
|
579
|
-
SchemaError: (e: any) => {
|
|
580
|
-
console.warn(e.toString())
|
|
581
|
-
return self.intl.formatMessage({ id: "validation.failed" })
|
|
582
|
-
}
|
|
583
|
-
}),
|
|
584
|
-
Match.orElse((e: any) => `${e.message ?? e._tag ?? e}`)
|
|
585
|
-
)
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
591
|
-
* Returns a tuple with raw Result and execution function which reports success and errors as Toast.
|
|
592
|
-
* @deprecated use `Command.fn` and friends instead
|
|
593
|
-
*/
|
|
594
|
-
readonly useAndHandleMutationResult: {
|
|
595
|
-
/**
|
|
596
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
597
|
-
* Returns a tuple with raw Result and execution function which reports success and errors as Toast.
|
|
598
|
-
* @deprecated use `Command.fn` and friends instead
|
|
599
|
-
*/
|
|
600
|
-
<
|
|
601
|
-
I,
|
|
602
|
-
E extends ResponseErrors,
|
|
603
|
-
A,
|
|
604
|
-
R,
|
|
605
|
-
Request extends Req,
|
|
606
|
-
Name extends string,
|
|
607
|
-
A2 = A,
|
|
608
|
-
E2 extends ResponseErrors = E,
|
|
609
|
-
R2 = R,
|
|
610
|
-
ESuccess = never,
|
|
611
|
-
RSuccess = never,
|
|
612
|
-
EError = never,
|
|
613
|
-
RError = never,
|
|
614
|
-
EDefect = never,
|
|
615
|
-
RDefect = never
|
|
616
|
-
>(
|
|
617
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
618
|
-
action: string,
|
|
619
|
-
options?: Opts<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
620
|
-
): Resp<I, A2, E2, R2, ComputedRef<AsyncResult.AsyncResult<A2, E2>>>
|
|
621
|
-
/**
|
|
622
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
623
|
-
* Returns a tuple with raw Result and execution function which reports success and errors as Toast.
|
|
624
|
-
* @deprecated use `Command.fn` and friends instead
|
|
625
|
-
*/
|
|
626
|
-
<
|
|
627
|
-
E extends ResponseErrors,
|
|
628
|
-
A,
|
|
629
|
-
R,
|
|
630
|
-
Request extends Req,
|
|
631
|
-
Name extends string,
|
|
632
|
-
A2 = A,
|
|
633
|
-
E2 extends ResponseErrors = E,
|
|
634
|
-
R2 = R,
|
|
635
|
-
ESuccess = never,
|
|
636
|
-
RSuccess = never,
|
|
637
|
-
EError = never,
|
|
638
|
-
RError = never,
|
|
639
|
-
EDefect = never,
|
|
640
|
-
RDefect = never
|
|
641
|
-
>(
|
|
642
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
643
|
-
action: string,
|
|
644
|
-
options?: Opts<A, E, R, void, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
645
|
-
): ActResp<A2, E2, R2, ComputedRef<AsyncResult.AsyncResult<A2, E2>>>
|
|
646
|
-
} = <E extends ResponseErrors, A, R, Request extends Req, Name extends string, I>(
|
|
647
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name> | RequestHandler<A, E, R, Request, Name>,
|
|
648
|
-
action: any,
|
|
649
|
-
options?: Opts<any, any, any, any, any, any, any, any, any, any, any, any, any>
|
|
650
|
-
): any => {
|
|
651
|
-
const handleRequestWithToast = this.useHandleRequestWithToast()
|
|
652
|
-
const handler = self.handler
|
|
653
|
-
const unsafe = _useMutation({
|
|
654
|
-
...self,
|
|
655
|
-
handler: Effect.isEffect(handler)
|
|
656
|
-
? (pipe(
|
|
657
|
-
Effect.annotateCurrentSpan({ action }),
|
|
658
|
-
Effect.andThen(handler)
|
|
659
|
-
) as any)
|
|
660
|
-
: (...args: [any]) =>
|
|
661
|
-
pipe(
|
|
662
|
-
Effect.annotateCurrentSpan({ action }),
|
|
663
|
-
Effect.andThen(handler(...args))
|
|
664
|
-
)
|
|
665
|
-
}, options ? dropUndefinedT(options) : undefined)
|
|
666
|
-
|
|
667
|
-
type MH = NonNullable<NonNullable<typeof options>["mapHandler"]>
|
|
668
|
-
const mh = options?.mapHandler ?? identity as MH
|
|
669
|
-
|
|
670
|
-
// Effect.tapDefect(reportRuntimeError) handled in toast handler,
|
|
671
|
-
const [a, b] = asResult(mapHandler(unsafe, mh) as any)
|
|
672
|
-
|
|
673
|
-
return tuple(
|
|
674
|
-
a,
|
|
675
|
-
handleRequestWithToast(b as any, self.id, action, options)
|
|
676
|
-
)
|
|
677
|
-
}
|
|
678
|
-
//
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
682
|
-
* Returns a tuple with state ref and execution function which reports success and errors as Toast.
|
|
683
|
-
*
|
|
684
|
-
* @deprecated use `Command.fn` and friends instead
|
|
685
|
-
*/
|
|
686
|
-
readonly useAndHandleMutation: {
|
|
687
|
-
/**
|
|
688
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
689
|
-
* Returns a tuple with state ref and execution function which reports success and errors as Toast.
|
|
690
|
-
*
|
|
691
|
-
* @deprecated use `Command.fn` and friends instead
|
|
692
|
-
*/
|
|
693
|
-
<
|
|
694
|
-
I,
|
|
695
|
-
E extends ResponseErrors,
|
|
696
|
-
A,
|
|
697
|
-
R,
|
|
698
|
-
Request extends Req,
|
|
699
|
-
Name extends string,
|
|
700
|
-
A2 = A,
|
|
701
|
-
E2 extends ResponseErrors = E,
|
|
702
|
-
R2 = R,
|
|
703
|
-
ESuccess = never,
|
|
704
|
-
RSuccess = never,
|
|
705
|
-
EError = never,
|
|
706
|
-
RError = never,
|
|
707
|
-
EDefect = never,
|
|
708
|
-
RDefect = never
|
|
709
|
-
>(
|
|
710
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
711
|
-
action: string,
|
|
712
|
-
options?: Opts<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
713
|
-
): Resp<I, A2, E2, R2>
|
|
714
|
-
/**
|
|
715
|
-
* Pass a function that returns an Effect, e.g from a client action, give it a name.
|
|
716
|
-
* Returns a tuple with state ref and execution function which reports success and errors as Toast.
|
|
717
|
-
*
|
|
718
|
-
* @deprecated use `Command.fn` and friends instead
|
|
719
|
-
*/
|
|
720
|
-
<
|
|
721
|
-
E extends ResponseErrors,
|
|
722
|
-
A,
|
|
723
|
-
R,
|
|
724
|
-
Request extends Req,
|
|
725
|
-
Name extends string,
|
|
726
|
-
A2 = A,
|
|
727
|
-
E2 extends ResponseErrors = E,
|
|
728
|
-
R2 = R,
|
|
729
|
-
ESuccess = never,
|
|
730
|
-
RSuccess = never,
|
|
731
|
-
EError = never,
|
|
732
|
-
RError = never,
|
|
733
|
-
EDefect = never,
|
|
734
|
-
RDefect = never
|
|
735
|
-
>(
|
|
736
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
737
|
-
action: string,
|
|
738
|
-
options?: Opts<A, E, R, void, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
739
|
-
): ActResp<A2, E2, R2>
|
|
740
|
-
} = (
|
|
741
|
-
self: any,
|
|
742
|
-
action: any,
|
|
743
|
-
options?: Opts<any, any, any, any, any, any, any, any, any, any, any, any, any>
|
|
744
|
-
): any => {
|
|
745
|
-
const [a, b] = this.useAndHandleMutationResult(self, action, options)
|
|
746
|
-
|
|
747
|
-
return tuple(
|
|
748
|
-
computed(() => mutationResultToVue(a.value)),
|
|
749
|
-
b
|
|
750
|
-
)
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
/** @deprecated use `Command.fn` and friends instead */
|
|
754
|
-
readonly makeUseAndHandleMutation = (
|
|
755
|
-
defaultOptions?: Opts<any, any, any, any, any, any, any, any, any>
|
|
756
|
-
) =>
|
|
757
|
-
((self: any, action: any, options: any) => {
|
|
758
|
-
return this.useAndHandleMutation(
|
|
759
|
-
self,
|
|
760
|
-
action,
|
|
761
|
-
{ ...defaultOptions, ...options }
|
|
762
|
-
)
|
|
763
|
-
}) as unknown as {
|
|
764
|
-
<
|
|
765
|
-
I,
|
|
766
|
-
E extends ResponseErrors,
|
|
767
|
-
A,
|
|
768
|
-
R,
|
|
769
|
-
Request extends Req,
|
|
770
|
-
Name extends string,
|
|
771
|
-
A2 = A,
|
|
772
|
-
E2 extends ResponseErrors = E,
|
|
773
|
-
R2 = R,
|
|
774
|
-
ESuccess = never,
|
|
775
|
-
RSuccess = never,
|
|
776
|
-
EError = never,
|
|
777
|
-
RError = never,
|
|
778
|
-
EDefect = never,
|
|
779
|
-
RDefect = never
|
|
780
|
-
>(
|
|
781
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
782
|
-
action: string,
|
|
783
|
-
options?: Opts<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
784
|
-
): Resp<I, A2, E2, R2>
|
|
785
|
-
<
|
|
786
|
-
E extends ResponseErrors,
|
|
787
|
-
A,
|
|
788
|
-
R,
|
|
789
|
-
Request extends Req,
|
|
790
|
-
Name extends string,
|
|
791
|
-
A2 = A,
|
|
792
|
-
E2 extends ResponseErrors = E,
|
|
793
|
-
R2 = R,
|
|
794
|
-
ESuccess = never,
|
|
795
|
-
RSuccess = never,
|
|
796
|
-
EError = never,
|
|
797
|
-
RError = never,
|
|
798
|
-
EDefect = never,
|
|
799
|
-
RDefect = never
|
|
800
|
-
>(
|
|
801
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
802
|
-
action: string,
|
|
803
|
-
options?: Opts<A, E, R, void, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
804
|
-
): ActResp<A2, E2, R2>
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* The same as @see useAndHandleMutation, but does not display any toasts by default.
|
|
809
|
-
* Messages for success, error and defect toasts can be provided in the Options.
|
|
810
|
-
* @deprecated use `Command.fn` and friends instead
|
|
811
|
-
*/
|
|
812
|
-
readonly useAndHandleMutationSilently: {
|
|
813
|
-
/**
|
|
814
|
-
* The same as @see useAndHandleMutation, but does not display any toasts by default.
|
|
815
|
-
* Messages for success, error and defect toasts can be provided in the Options.
|
|
816
|
-
* @deprecated use `Command.fn` and friends instead
|
|
817
|
-
*/
|
|
818
|
-
<
|
|
819
|
-
I,
|
|
820
|
-
E extends ResponseErrors,
|
|
821
|
-
A,
|
|
822
|
-
R,
|
|
823
|
-
Request extends Req,
|
|
824
|
-
Name extends string,
|
|
825
|
-
A2 = A,
|
|
826
|
-
E2 extends ResponseErrors = E,
|
|
827
|
-
R2 = R,
|
|
828
|
-
ESuccess = never,
|
|
829
|
-
RSuccess = never,
|
|
830
|
-
EError = never,
|
|
831
|
-
RError = never,
|
|
832
|
-
EDefect = never,
|
|
833
|
-
RDefect = never
|
|
834
|
-
>(
|
|
835
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
836
|
-
action: string,
|
|
837
|
-
options?: Opts<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
838
|
-
): Resp<I, A2, E2, R>
|
|
839
|
-
/**
|
|
840
|
-
* The same as @see useAndHandleMutation, but does not display any toasts by default.
|
|
841
|
-
* Messages for success, error and defect toasts can be provided in the Options.
|
|
842
|
-
* @deprecated use `Command.fn` and friends instead
|
|
843
|
-
*/
|
|
844
|
-
<
|
|
845
|
-
E extends ResponseErrors,
|
|
846
|
-
A,
|
|
847
|
-
R,
|
|
848
|
-
Request extends Req,
|
|
849
|
-
Name extends string,
|
|
850
|
-
A2 = A,
|
|
851
|
-
E2 extends ResponseErrors = E,
|
|
852
|
-
R2 = R,
|
|
853
|
-
ESuccess = never,
|
|
854
|
-
RSuccess = never,
|
|
855
|
-
EError = never,
|
|
856
|
-
RError = never,
|
|
857
|
-
EDefect = never,
|
|
858
|
-
RDefect = never
|
|
859
|
-
>(
|
|
860
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
861
|
-
action: string,
|
|
862
|
-
options?: Opts<A, E, R, void, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
863
|
-
): ActResp<void, never, R>
|
|
864
|
-
} = this.makeUseAndHandleMutation({
|
|
865
|
-
successMessage: suppressToast,
|
|
866
|
-
failMessage: suppressToast,
|
|
867
|
-
defectMessage: suppressToast
|
|
868
|
-
}) as any
|
|
869
|
-
|
|
870
|
-
/**
|
|
871
|
-
* The same as @see useAndHandleMutation, but does not act on success, error or defect by default.
|
|
872
|
-
* Actions for success, error and defect can be provided in the Options.
|
|
873
|
-
* @deprecated use `Command.fn` and friends instead
|
|
874
|
-
*/
|
|
875
|
-
readonly useAndHandleMutationCustom: {
|
|
876
|
-
/**
|
|
877
|
-
* The same as @see useAndHandleMutation, but does not act on success, error or defect by default.
|
|
878
|
-
* Actions for success, error and defect can be provided in the Options.
|
|
879
|
-
* @deprecated use `Command.fn` and friends instead
|
|
880
|
-
*/
|
|
881
|
-
<
|
|
882
|
-
I,
|
|
883
|
-
E extends ResponseErrors,
|
|
884
|
-
A,
|
|
885
|
-
R,
|
|
886
|
-
Request extends Req,
|
|
887
|
-
Name extends string,
|
|
888
|
-
A2 = A,
|
|
889
|
-
E2 extends ResponseErrors = E,
|
|
890
|
-
R2 = R,
|
|
891
|
-
ESuccess = never,
|
|
892
|
-
RSuccess = never,
|
|
893
|
-
EError = never,
|
|
894
|
-
RError = never,
|
|
895
|
-
EDefect = never,
|
|
896
|
-
RDefect = never
|
|
897
|
-
>(
|
|
898
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
899
|
-
action: string,
|
|
900
|
-
options?: LowOptsOptional<A, E, R, I, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
901
|
-
): Resp<I, A2, E2, R2>
|
|
902
|
-
/**
|
|
903
|
-
* The same as @see useAndHandleMutation, but does not act on success, error or defect by default.
|
|
904
|
-
* Actions for success, error and defect can be provided in the Options.
|
|
905
|
-
* @deprecated use `Command.fn` and friends instead
|
|
906
|
-
*/
|
|
907
|
-
<
|
|
908
|
-
E extends ResponseErrors,
|
|
909
|
-
A,
|
|
910
|
-
R,
|
|
911
|
-
Request extends Req,
|
|
912
|
-
Name extends string,
|
|
913
|
-
A2 = A,
|
|
914
|
-
E2 extends ResponseErrors = E,
|
|
915
|
-
R2 = R,
|
|
916
|
-
ESuccess = never,
|
|
917
|
-
RSuccess = never,
|
|
918
|
-
EError = never,
|
|
919
|
-
RError = never,
|
|
920
|
-
EDefect = never,
|
|
921
|
-
RDefect = never
|
|
922
|
-
>(
|
|
923
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
924
|
-
action: string,
|
|
925
|
-
options?: LowOptsOptional<A, E, R, void, A2, E2, R2, ESuccess, RSuccess, EError, RError, EDefect, RDefect>
|
|
926
|
-
): ActResp<A2, E2, R2>
|
|
927
|
-
} = (self: any, action: string, options: any) => {
|
|
928
|
-
const unsafe = _useMutation({
|
|
929
|
-
...self,
|
|
930
|
-
handler: Effect.isEffect(self.handler)
|
|
931
|
-
? (pipe(
|
|
932
|
-
Effect.annotateCurrentSpan({ action }),
|
|
933
|
-
Effect.andThen(self.handler)
|
|
934
|
-
) as any)
|
|
935
|
-
: (...args: any[]) =>
|
|
936
|
-
pipe(
|
|
937
|
-
Effect.annotateCurrentSpan({ action }),
|
|
938
|
-
Effect.andThen(self.handler(...args))
|
|
939
|
-
)
|
|
940
|
-
}, options ? dropUndefinedT(options) : undefined)
|
|
941
|
-
|
|
942
|
-
type MH = NonNullable<NonNullable<typeof options>["mapHandler"]>
|
|
943
|
-
const mh = options?.mapHandler ?? identity as MH
|
|
944
|
-
|
|
945
|
-
const [a, b] = asResult(
|
|
946
|
-
mapHandler(
|
|
947
|
-
mapHandler(unsafe as any, mh),
|
|
948
|
-
Effect.tapCauseIf(Cause.hasDies, (cause) => reportRuntimeError(cause))
|
|
949
|
-
) as any
|
|
950
|
-
)
|
|
951
|
-
|
|
952
|
-
return tuple(
|
|
953
|
-
computed(() => mutationResultToVue(a.value)),
|
|
954
|
-
handleRequest(b as any, self.id, action, {
|
|
955
|
-
onSuccess: suppressToast,
|
|
956
|
-
onDefect: suppressToast,
|
|
957
|
-
onFail: suppressToast,
|
|
958
|
-
...options
|
|
959
|
-
})
|
|
960
|
-
) as any
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
/**
|
|
964
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
965
|
-
* you should use the result ref to render errors!
|
|
966
|
-
* @deprecated use `Command.fn` and friends instead
|
|
967
|
-
*/
|
|
968
|
-
readonly useSafeMutationWithState: {
|
|
969
|
-
/**
|
|
970
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
971
|
-
* you should use the result ref to render errors!
|
|
972
|
-
* @deprecated use `Command.fn` and friends instead
|
|
973
|
-
*/
|
|
974
|
-
<I, E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
975
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name>,
|
|
976
|
-
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
977
|
-
): readonly [
|
|
978
|
-
ComputedRef<Res<A, E>>,
|
|
979
|
-
(i: I) => Effect.Effect<Exit.Exit<A2, E2>, never, R2>
|
|
980
|
-
]
|
|
981
|
-
/**
|
|
982
|
-
* Effect results are converted to Exit, so errors are ignored by default.
|
|
983
|
-
* you should use the result ref to render errors!
|
|
984
|
-
* @deprecated use `Command.fn` and friends instead
|
|
985
|
-
*/
|
|
986
|
-
<E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
987
|
-
self: RequestHandler<A, E, R, Request, Name>,
|
|
988
|
-
options?: MutationOptions<A, E, R, A2, E2, R2>
|
|
989
|
-
): readonly [
|
|
990
|
-
ComputedRef<Res<A, E>>,
|
|
991
|
-
Effect.Effect<Exit.Exit<A2, E2>, never, R2>
|
|
992
|
-
]
|
|
993
|
-
} = <I, E, A, R, Request extends Req, Name extends string, A2 = A, E2 = E, R2 = R>(
|
|
994
|
-
self: RequestHandlerWithInput<I, A, E, R, Request, Name> | RequestHandler<A, E, R, Request, Name>,
|
|
995
|
-
options?: MutationOptions<A, E, R, A2, E2, R2, I>
|
|
996
|
-
) => {
|
|
997
|
-
const [a, b] = this.useSafeMutation(self as any, options)
|
|
998
|
-
|
|
999
|
-
return tuple(
|
|
1000
|
-
computed(() => mutationResultToVue(a.value)),
|
|
1001
|
-
b
|
|
1002
|
-
) as any
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
/** @deprecated use OmegaForm */
|
|
1006
|
-
readonly buildFormFromSchema = <
|
|
1007
|
-
From extends Record<PropertyKey, any>,
|
|
1008
|
-
To extends Record<PropertyKey, any>,
|
|
1009
|
-
C extends Record<PropertyKey, any>,
|
|
1010
|
-
OnSubmitA
|
|
1011
|
-
>(
|
|
1012
|
-
s:
|
|
1013
|
-
& S.Codec<To>
|
|
1014
|
-
& { new(c: C): any; extend: any; fields: S.Struct.Fields },
|
|
1015
|
-
state: Ref<Omit<From, "_tag">>,
|
|
1016
|
-
onSubmit: (a: To) => Effect.Effect<OnSubmitA, never, RT>
|
|
1017
|
-
) => {
|
|
1018
|
-
const fields = buildFieldInfoFromFieldsRoot(s).fields
|
|
1019
|
-
const schema = S.Struct(Struct.omit(s.fields, ["_tag"])) as unknown as S.Codec<any> & {
|
|
1020
|
-
readonly DecodingServices: never
|
|
1021
|
-
}
|
|
1022
|
-
const parse = S.decodeUnknownSync(schema)
|
|
1023
|
-
const isDirty = ref(false)
|
|
1024
|
-
const isValid = ref(true)
|
|
1025
|
-
const isLoading = ref(false)
|
|
1026
|
-
const runPromise = Effect.runPromiseWith(this.getRuntime())
|
|
1027
|
-
|
|
1028
|
-
const submit1 =
|
|
1029
|
-
(onSubmit: (a: To) => Effect.Effect<OnSubmitA, never, never>) =>
|
|
1030
|
-
async <T extends Promise<{ valid: boolean }>>(e: T) => {
|
|
1031
|
-
isLoading.value = true
|
|
1032
|
-
try {
|
|
1033
|
-
const r = await e
|
|
1034
|
-
if (!r.valid) return
|
|
1035
|
-
return await runPromise(onSubmit(new (s as any)(await runPromise(parse(state.value)))) as any)
|
|
1036
|
-
} finally {
|
|
1037
|
-
isLoading.value = false
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
const submit = submit1(onSubmit as any)
|
|
1041
|
-
|
|
1042
|
-
watch(
|
|
1043
|
-
state,
|
|
1044
|
-
(v) => {
|
|
1045
|
-
// TODO: do better
|
|
1046
|
-
isDirty.value = JSON.stringify(v) !== JSON.stringify(state.value)
|
|
1047
|
-
},
|
|
1048
|
-
{ deep: true }
|
|
1049
|
-
)
|
|
1050
|
-
|
|
1051
|
-
const submitFromState = Effect.gen(function*() {
|
|
1052
|
-
return yield* (onSubmit(yield* parse(state.value)) as any)
|
|
1053
|
-
})
|
|
1054
|
-
|
|
1055
|
-
const submitFromStatePromise = () => runPromise(submitFromState as any)
|
|
1056
|
-
|
|
1057
|
-
return {
|
|
1058
|
-
fields,
|
|
1059
|
-
/** optimized for Vuetify v-form submit callback */
|
|
1060
|
-
submit,
|
|
1061
|
-
/** optimized for Native form submit callback or general use */
|
|
1062
|
-
submitFromState,
|
|
1063
|
-
submitFromStatePromise,
|
|
1064
|
-
isDirty,
|
|
1065
|
-
isValid,
|
|
1066
|
-
isLoading
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
1072
|
-
export class LegacyMutation extends ServiceMap.Service<LegacyMutation>()("LegacyMutation", {
|
|
1073
|
-
make: Effect.gen(function*() {
|
|
1074
|
-
const intl = yield* I18n
|
|
1075
|
-
const toast = yield* Toast
|
|
1076
|
-
|
|
1077
|
-
return <R>(getRuntime: () => ServiceMap.ServiceMap<R>) => new LegacyMutationImpl(getRuntime, toast, intl)
|
|
1078
|
-
})
|
|
1079
|
-
}) {
|
|
1080
|
-
static readonly DefaultWithoutDependencies = Layer.effect(this, this.make)
|
|
1081
|
-
static readonly Default = this.DefaultWithoutDependencies
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
export type ClientFrom<M extends Requests> = RequestHandlers<never, never, M, M["meta"]["moduleName"]>
|
|
265
|
+
export type ClientFrom<M extends RequestsAny> = RequestHandlers<never, never, M, ExtractModuleName<M>>
|
|
1085
266
|
|
|
1086
267
|
export class QueryImpl<R> {
|
|
1087
|
-
constructor(readonly getRuntime: () =>
|
|
268
|
+
constructor(readonly getRuntime: () => Context.Context<R>) {
|
|
1088
269
|
this.useQuery = makeQuery(this.getRuntime)
|
|
1089
270
|
}
|
|
1090
271
|
/**
|
|
@@ -1163,7 +344,7 @@ export class QueryImpl<R> {
|
|
|
1163
344
|
} = <Arg, E, A, Request extends Req, Name extends string>(
|
|
1164
345
|
self: RequestHandlerWithInput<Arg, A, E, R, Request, Name> | RequestHandler<A, E, R, Request, Name>
|
|
1165
346
|
) => {
|
|
1166
|
-
const runPromise =
|
|
347
|
+
const runPromise = makeRunPromise(this.getRuntime())
|
|
1167
348
|
const q = this.useQuery(self as any) as any
|
|
1168
349
|
return (argOrOptions?: any, options?: any) => {
|
|
1169
350
|
const [resultRef, latestRef, fetch, uqrt] = q(argOrOptions, { ...options, suspense: true } // experimental_prefetchInRender: true }
|
|
@@ -1214,10 +395,10 @@ export class QueryImpl<R> {
|
|
|
1214
395
|
}
|
|
1215
396
|
|
|
1216
397
|
// somehow mrt.runtimeEffect doesnt work sync, but this workaround works fine? not sure why though as the layers are generally only sync
|
|
1217
|
-
const managedRuntimeRt = <A, E>(mrt: ManagedRuntime.ManagedRuntime<A, E>) => mrt.runSync(Effect.
|
|
398
|
+
const managedRuntimeRt = <A, E>(mrt: ManagedRuntime.ManagedRuntime<A, E>) => mrt.runSync(Effect.context<A>())
|
|
1218
399
|
|
|
1219
400
|
type Base = I18n | Toast
|
|
1220
|
-
type Mix = ApiClientFactory | Commander |
|
|
401
|
+
type Mix = ApiClientFactory | Commander | Base
|
|
1221
402
|
export const makeClient = <RT_, RTHooks>(
|
|
1222
403
|
// global, but only accessible after startup has completed
|
|
1223
404
|
getBaseMrt: () => ManagedRuntime.ManagedRuntime<RT_ | Mix, never>,
|
|
@@ -1225,54 +406,26 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1225
406
|
rtHooks: Layer.Layer<RTHooks, never, Mix>
|
|
1226
407
|
) => {
|
|
1227
408
|
type RT = RT_ | Mix
|
|
1228
|
-
const getRt = Effect.services<RT>()
|
|
1229
409
|
const getBaseRt = () => managedRuntimeRt(getBaseMrt())
|
|
1230
410
|
const makeCommand = makeUseCommand<RT, RTHooks>(rtHooks)
|
|
1231
|
-
const makeMutation = Effect.gen(function*() {
|
|
1232
|
-
const mut = yield* LegacyMutation
|
|
1233
|
-
|
|
1234
|
-
return mut(() => getBaseMrt().runSync(getRt))
|
|
1235
|
-
})
|
|
1236
411
|
let cmd: Effect.Success<typeof makeCommand>
|
|
1237
412
|
const useCommand = () => cmd ??= getBaseMrt().runSync(makeCommand)
|
|
1238
|
-
let mut: Effect.Success<typeof makeMutation>
|
|
1239
|
-
const getMutation = () => mut ??= getBaseMrt().runSync(makeMutation)
|
|
1240
413
|
|
|
1241
414
|
let m: ReturnType<typeof useMutationInt>
|
|
1242
415
|
const useMutation = () => m ??= useMutationInt()
|
|
1243
416
|
|
|
1244
|
-
const keys = [
|
|
1245
|
-
"useSafeMutationWithState",
|
|
1246
|
-
"useAndHandleMutation",
|
|
1247
|
-
"useAndHandleMutationResult",
|
|
1248
|
-
"useAndHandleMutationSilently",
|
|
1249
|
-
"useAndHandleMutationCustom",
|
|
1250
|
-
"makeUseAndHandleMutation",
|
|
1251
|
-
"useHandleRequestWithToast",
|
|
1252
|
-
"buildFormFromSchema",
|
|
1253
|
-
"useSafeMutation"
|
|
1254
|
-
] as const satisfies readonly (keyof ReturnType<typeof getMutation>)[]
|
|
1255
|
-
type mut = Pick<LegacyMutationImpl<RT>, typeof keys[number]>
|
|
1256
|
-
|
|
1257
|
-
const mutations = keys.reduce(
|
|
1258
|
-
(prev, cur) => {
|
|
1259
|
-
;(prev as any)[cur] = ((...args: [any]) => {
|
|
1260
|
-
return (getMutation() as any)[cur](...args)
|
|
1261
|
-
}) as any
|
|
1262
|
-
return prev
|
|
1263
|
-
},
|
|
1264
|
-
{} as Pick<LegacyMutationImpl<RT>, typeof keys[number]>
|
|
1265
|
-
)
|
|
1266
|
-
|
|
1267
417
|
const query = new QueryImpl(getBaseRt)
|
|
1268
418
|
const useQuery = query.useQuery
|
|
1269
419
|
const useSuspenseQuery = query.useSuspenseQuery
|
|
1270
420
|
|
|
1271
|
-
const mapQuery = <M extends
|
|
421
|
+
const mapQuery = <M extends RequestsAny>(
|
|
1272
422
|
client: ClientFrom<M>
|
|
1273
423
|
) => {
|
|
1274
424
|
const queries = Struct.keys(client).reduce(
|
|
1275
425
|
(acc, key) => {
|
|
426
|
+
if (client[key].Request.type !== "query") {
|
|
427
|
+
return acc
|
|
428
|
+
}
|
|
1276
429
|
;(acc as any)[camelCase(key) + "Query"] = Object.assign(useQuery(client[key] as any), {
|
|
1277
430
|
id: client[key].id
|
|
1278
431
|
})
|
|
@@ -1284,26 +437,35 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1284
437
|
{} as
|
|
1285
438
|
& {
|
|
1286
439
|
// apparently can't get JSDoc in here..
|
|
1287
|
-
[
|
|
440
|
+
[
|
|
441
|
+
Key in keyof typeof client as QueryHandler<typeof client[Key]> extends never ? never
|
|
442
|
+
: `${ToCamel<string & Key>}Query`
|
|
443
|
+
]: Queries<RT, QueryHandler<typeof client[Key]>>["query"]
|
|
1288
444
|
}
|
|
1289
445
|
// todo: or suspense as an Option?
|
|
1290
446
|
& {
|
|
1291
447
|
// apparently can't get JSDoc in here..
|
|
1292
|
-
[
|
|
448
|
+
[
|
|
449
|
+
Key in keyof typeof client as QueryHandler<typeof client[Key]> extends never ? never
|
|
450
|
+
: `${ToCamel<string & Key>}SuspenseQuery`
|
|
451
|
+
]: Queries<
|
|
1293
452
|
RT,
|
|
1294
|
-
typeof client[Key]
|
|
453
|
+
QueryHandler<typeof client[Key]>
|
|
1295
454
|
>["suspense"]
|
|
1296
455
|
}
|
|
1297
456
|
)
|
|
1298
457
|
return queries
|
|
1299
458
|
}
|
|
1300
459
|
|
|
1301
|
-
const mapRequest = <M extends
|
|
460
|
+
const mapRequest = <M extends RequestsAny>(
|
|
1302
461
|
client: ClientFrom<M>
|
|
1303
462
|
) => {
|
|
1304
463
|
const Command = useCommand()
|
|
1305
464
|
const mutations = Struct.keys(client).reduce(
|
|
1306
465
|
(acc, key) => {
|
|
466
|
+
if (client[key].Request.type !== "command") {
|
|
467
|
+
return acc
|
|
468
|
+
}
|
|
1307
469
|
const mut = client[key].handler
|
|
1308
470
|
const fn = Command.fn(client[key].id)
|
|
1309
471
|
const wrap = Command.wrap({ mutate: Effect.isEffect(mut) ? () => mut : mut, id: client[key].id })
|
|
@@ -1315,36 +477,40 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1315
477
|
return acc
|
|
1316
478
|
},
|
|
1317
479
|
{} as {
|
|
1318
|
-
[
|
|
480
|
+
[
|
|
481
|
+
Key in keyof typeof client as CommandHandler<typeof client[Key]> extends never ? never
|
|
482
|
+
: `${ToCamel<string & Key>}Request`
|
|
483
|
+
]: CommandRequestWithExtensions<
|
|
1319
484
|
RT | RTHooks,
|
|
1320
|
-
typeof client[Key]
|
|
485
|
+
CommandHandler<typeof client[Key]>
|
|
1321
486
|
>
|
|
1322
487
|
}
|
|
1323
488
|
)
|
|
1324
489
|
return mutations
|
|
1325
490
|
}
|
|
1326
491
|
|
|
1327
|
-
const mapMutation = <M extends
|
|
492
|
+
const mapMutation = <M extends RequestsAny>(
|
|
1328
493
|
client: ClientFrom<M>
|
|
1329
494
|
) => {
|
|
1330
495
|
const Command = useCommand()
|
|
1331
496
|
const mutation = useMutation()
|
|
1332
497
|
const mutations = Struct.keys(client).reduce(
|
|
1333
498
|
(acc, key) => {
|
|
499
|
+
if (client[key].Request.type !== "command") {
|
|
500
|
+
return acc
|
|
501
|
+
}
|
|
1334
502
|
const mut: any = mutation(client[key] as any)
|
|
1335
|
-
const fn = Command.fn(client[key].id)
|
|
1336
503
|
const wrap = Command.wrap({ mutate: Effect.isEffect(mut) ? () => mut : mut, id: client[key].id })
|
|
1337
|
-
;(acc as any)[camelCase(key) + "Mutation"] = Object.assign(
|
|
1338
|
-
mut,
|
|
1339
|
-
fn, // to get the i18n key etc.
|
|
1340
|
-
{ wrap, fn }
|
|
1341
|
-
)
|
|
504
|
+
;(acc as any)[camelCase(key) + "Mutation"] = Object.assign(mut, { wrap })
|
|
1342
505
|
return acc
|
|
1343
506
|
},
|
|
1344
507
|
{} as {
|
|
1345
|
-
[
|
|
508
|
+
[
|
|
509
|
+
Key in keyof typeof client as CommandHandler<typeof client[Key]> extends never ? never
|
|
510
|
+
: `${ToCamel<string & Key>}Mutation`
|
|
511
|
+
]: MutationWithExtensions<
|
|
1346
512
|
RT | RTHooks,
|
|
1347
|
-
typeof client[Key]
|
|
513
|
+
CommandHandler<typeof client[Key]>
|
|
1348
514
|
>
|
|
1349
515
|
}
|
|
1350
516
|
)
|
|
@@ -1353,7 +519,7 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1353
519
|
|
|
1354
520
|
// make available .query, .suspense and .mutate for each operation
|
|
1355
521
|
// and a .helpers with all mutations and queries
|
|
1356
|
-
const mapClient = <M extends
|
|
522
|
+
const mapClient = <M extends RequestsAny>(
|
|
1357
523
|
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>
|
|
1358
524
|
) =>
|
|
1359
525
|
(
|
|
@@ -1364,47 +530,59 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1364
530
|
const invalidation = queryInvalidation?.(client)
|
|
1365
531
|
const extended = Struct.keys(client).reduce(
|
|
1366
532
|
(acc, key) => {
|
|
533
|
+
const requestType = client[key].Request.type
|
|
1367
534
|
const fn = Command.fn(client[key].id)
|
|
1368
|
-
const mutate = extendM(
|
|
1369
|
-
mutation(
|
|
1370
|
-
client[key] as any,
|
|
1371
|
-
invalidation?.[key] ? { queryInvalidation: invalidation[key] } : undefined
|
|
1372
|
-
),
|
|
1373
|
-
(mutate) =>
|
|
1374
|
-
Object.assign(
|
|
1375
|
-
mutate,
|
|
1376
|
-
fn, // to get the i18n key etc.
|
|
1377
|
-
{
|
|
1378
|
-
wrap: Command.wrap({ mutate: Effect.isEffect(mutate) ? () => mutate : mutate, id: client[key].id }),
|
|
1379
|
-
fn
|
|
1380
|
-
}
|
|
1381
|
-
)
|
|
1382
|
-
)
|
|
1383
|
-
|
|
1384
535
|
const h_ = client[key].handler
|
|
1385
|
-
const
|
|
536
|
+
const wrapInput = Effect.isEffect(h_)
|
|
1386
537
|
? () => h_
|
|
1387
538
|
: (...args: [any]) => h_(...args)
|
|
539
|
+
const request = Effect.isEffect(h_) ? h_ : wrapInput
|
|
1388
540
|
;(acc as any)[key] = Object.assign(
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
541
|
+
requestType === "query"
|
|
542
|
+
? {
|
|
543
|
+
...client[key],
|
|
544
|
+
request,
|
|
545
|
+
query: useQuery(client[key] as any),
|
|
546
|
+
suspense: useSuspenseQuery(client[key] as any)
|
|
547
|
+
}
|
|
548
|
+
: {
|
|
549
|
+
mutate: extendM(
|
|
550
|
+
mutation(
|
|
551
|
+
client[key] as any,
|
|
552
|
+
invalidation?.[key] ? { queryInvalidation: invalidation[key] } : undefined
|
|
553
|
+
),
|
|
554
|
+
(mutate) =>
|
|
555
|
+
Object.assign(
|
|
556
|
+
mutate,
|
|
557
|
+
{
|
|
558
|
+
wrap: Command.wrap({
|
|
559
|
+
mutate: Effect.isEffect(mutate) ? () => mutate : mutate,
|
|
560
|
+
id: client[key].id
|
|
561
|
+
})
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
),
|
|
565
|
+
...client[key],
|
|
566
|
+
...fn, // to get the i18n key etc.
|
|
567
|
+
request,
|
|
568
|
+
fn,
|
|
569
|
+
wrap: Command.wrap({ mutate: wrapInput, id: client[key].id })
|
|
570
|
+
}
|
|
1399
571
|
)
|
|
1400
572
|
return acc
|
|
1401
573
|
},
|
|
1402
574
|
{} as {
|
|
1403
575
|
[Key in keyof typeof client]:
|
|
1404
576
|
& typeof client[Key]
|
|
1405
|
-
&
|
|
1406
|
-
|
|
1407
|
-
|
|
577
|
+
& (QueryHandler<typeof client[Key]> extends never ? {}
|
|
578
|
+
:
|
|
579
|
+
& QueryRequestWithExtensions<QueryHandler<typeof client[Key]>>
|
|
580
|
+
& Queries<RT, QueryHandler<typeof client[Key]>>)
|
|
581
|
+
& (CommandHandler<typeof client[Key]> extends never ? {}
|
|
582
|
+
: CommandRequestWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>>)
|
|
583
|
+
& (CommandHandler<typeof client[Key]> extends never ? {}
|
|
584
|
+
: { mutate: MutationWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>> })
|
|
585
|
+
& { Input: typeof client[Key] extends RequestHandlerWithInput<infer I, any, any, any, any, any> ? I : never }
|
|
1408
586
|
}
|
|
1409
587
|
)
|
|
1410
588
|
return Object.assign(extended, { helpers: { ...mapRequest(client), ...mapMutation(client), ...mapQuery(client) } })
|
|
@@ -1412,7 +590,7 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1412
590
|
|
|
1413
591
|
// TODO: Clean up this delay initialisation messs
|
|
1414
592
|
// TODO; invalidateQueries should perhaps be configured in the Request impl themselves?
|
|
1415
|
-
const clientFor__ = <M extends
|
|
593
|
+
const clientFor__ = <M extends RequestsAny>(
|
|
1416
594
|
m: M,
|
|
1417
595
|
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>
|
|
1418
596
|
) => getBaseMrt().runSync(clientFor_(m).pipe(Effect.map(mapClient(queryInvalidation))))
|
|
@@ -1420,7 +598,7 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1420
598
|
// delay client creation until first access
|
|
1421
599
|
// the idea is that we don't need the useNuxtApp().$runtime (only available at later initialisation stage)
|
|
1422
600
|
// until we are at a place where it is available..
|
|
1423
|
-
const clientFor = <M extends
|
|
601
|
+
const clientFor = <M extends RequestsAny>(
|
|
1424
602
|
m: M,
|
|
1425
603
|
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>
|
|
1426
604
|
) => {
|
|
@@ -1444,11 +622,6 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1444
622
|
return proxy
|
|
1445
623
|
}
|
|
1446
624
|
|
|
1447
|
-
const legacy: Legacy<RT> = {
|
|
1448
|
-
...mutations,
|
|
1449
|
-
...query
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
625
|
const Command: CommanderResolved<RT, RTHooks> = {
|
|
1453
626
|
...{
|
|
1454
627
|
// delay initialisation until first use...
|
|
@@ -1463,17 +636,10 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1463
636
|
return {
|
|
1464
637
|
Command,
|
|
1465
638
|
useCommand,
|
|
1466
|
-
clientFor
|
|
1467
|
-
legacy
|
|
639
|
+
clientFor
|
|
1468
640
|
}
|
|
1469
641
|
}
|
|
1470
642
|
|
|
1471
|
-
export interface Legacy<R>
|
|
1472
|
-
extends
|
|
1473
|
-
Pick<QueryImpl<R>, "useQuery" | "useSuspenseQuery">,
|
|
1474
|
-
Omit<LegacyMutationImpl<R>, "getRuntime" | "toast" | "intl">
|
|
1475
|
-
{}
|
|
1476
|
-
|
|
1477
643
|
export type QueryInvalidation<M> = {
|
|
1478
644
|
[K in keyof M]?: (defaultKey: string[], name: string) => {
|
|
1479
645
|
filters?: InvalidateQueryFilters | undefined
|
|
@@ -1497,6 +663,9 @@ export interface CommandBase<I = void, A = void> {
|
|
|
1497
663
|
|
|
1498
664
|
export interface EffectCommand<I = void, A = unknown, E = unknown> extends CommandBase<I, Fiber<A, E>> {}
|
|
1499
665
|
|
|
1500
|
-
|
|
1501
|
-
|
|
666
|
+
type RequestInputFromMake<I extends { readonly make: (...args: any[]) => any }> = Parameters<I["make"]> extends
|
|
667
|
+
[infer A, ...ReadonlyArray<any>] ? A : void
|
|
668
|
+
|
|
669
|
+
export interface CommandFromRequest<I extends { readonly make: (...args: any[]) => any }, A = unknown, E = unknown>
|
|
670
|
+
extends EffectCommand<RequestInputFromMake<I>, A, E>
|
|
1502
671
|
{}
|