@effect-app/vue 4.0.0-beta.17 → 4.0.0-beta.170
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 +1090 -0
- package/dist/commander.d.ts +370 -0
- package/dist/commander.d.ts.map +1 -0
- package/dist/commander.js +591 -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 +41 -12
- 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 +8 -9
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +34 -7
- package/dist/makeClient.d.ts +119 -277
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +155 -359
- 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 +4 -4
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +7 -7
- package/dist/query.d.ts +11 -15
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +19 -27
- 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/eslint.config.mjs +2 -2
- package/package.json +48 -48
- package/src/{experimental/commander.ts → commander.ts} +930 -255
- package/src/{experimental/confirm.ts → confirm.ts} +10 -14
- package/src/errorReporter.ts +60 -72
- package/src/form.ts +55 -16
- package/src/intl.ts +12 -0
- package/src/lib.ts +50 -13
- package/src/makeClient.ts +454 -1023
- package/src/{experimental/makeUseCommand.ts → makeUseCommand.ts} +3 -3
- package/src/mutate.ts +40 -32
- package/src/query.ts +39 -50
- 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/lib.test.d.ts.map +1 -0
- package/test/dist/stubs.d.ts +2123 -118
- package/test/dist/stubs.d.ts.map +1 -1
- package/test/dist/stubs.js +77 -23
- package/test/form-validation-errors.test.ts +23 -19
- package/test/form.test.ts +20 -2
- package/test/lib.test.ts +240 -0
- package/test/makeClient.test.ts +209 -38
- package/test/stubs.ts +112 -40
- package/tsconfig.json +0 -1
- package/tsconfig.json.bak +2 -2
- package/tsconfig.src.json +34 -34
- package/tsconfig.test.json +2 -2
- package/vitest.config.ts +5 -5
- 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,45 @@
|
|
|
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, Hash, type Layer, type ManagedRuntime, S, 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
|
|
9
|
-
import { type OperationFailure, OperationSuccess } from "effect-app/Operations"
|
|
10
|
-
import { dropUndefinedT, extendM } from "effect-app/utils"
|
|
6
|
+
import type { ExtractModuleName, RequestHandler, RequestHandlers, RequestHandlerWithInput, RequestInputFromMake, RequestsAny } from "effect-app/client/clientFor"
|
|
7
|
+
import type { InvalidationCallback } from "effect-app/client/makeClient"
|
|
8
|
+
import type * as ExitResult from "effect/Exit"
|
|
11
9
|
import { type Fiber } from "effect/Fiber"
|
|
12
10
|
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"
|
|
11
|
+
import { type ComputedRef, onBeforeUnmount, ref, type WatchSource } from "vue"
|
|
12
|
+
import { type Commander, CommanderStatic } from "./commander.js"
|
|
13
|
+
import { type I18n } from "./intl.js"
|
|
14
|
+
import { type CommanderResolved, makeUseCommand } from "./makeUseCommand.js"
|
|
15
|
+
import { makeMutation, type MutationOptionsBase, useMakeMutation } from "./mutate.js"
|
|
22
16
|
import { type CustomUndefinedInitialQueryOptions, makeQuery } from "./query.js"
|
|
17
|
+
import { makeRunPromise } from "./runtime.js"
|
|
18
|
+
import { type Toast } from "./toast.js"
|
|
23
19
|
|
|
24
20
|
const mapHandler = <A, E, R, I = void, A2 = A, E2 = E, R2 = R>(
|
|
25
21
|
handler: Effect.Effect<A, E, R> | ((i: I) => Effect.Effect<A, E, R>),
|
|
26
22
|
map: (self: Effect.Effect<A, E, R>, i: I) => Effect.Effect<A2, E2, R2>
|
|
27
23
|
) => Effect.isEffect(handler) ? map(handler, undefined as any) : (i: I) => map(handler(i), i)
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
// TODO: optimize - work from encoded shape directly
|
|
26
|
+
const projectHandler = (
|
|
27
|
+
handler: Effect.Effect<any, any, any> | ((i: any) => Effect.Effect<any, any, any>),
|
|
28
|
+
successSchema: S.Top,
|
|
29
|
+
projectionSchema: S.Top
|
|
30
|
+
) => {
|
|
31
|
+
const encode = S.encodeEffect(successSchema)
|
|
32
|
+
const decode = S.decodeEffectConcurrently(projectionSchema)
|
|
33
|
+
return mapHandler(handler, (self) =>
|
|
34
|
+
self.pipe(
|
|
35
|
+
Effect.flatMap(encode),
|
|
36
|
+
Effect.flatMap(decode)
|
|
37
|
+
))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const projectionSchemaHash = (schema: S.Top) => String(Hash.hash(schema.ast))
|
|
41
|
+
|
|
42
|
+
export interface CommandRequestExtensions<RT, Id extends string, I, A, E, R> {
|
|
30
43
|
/** Defines a Command based on this call, taking the `id` of the call as the `id` of the Command.
|
|
31
44
|
* The Request function will be taken as the first member of the Command, the Command required input will be the Request input.
|
|
32
45
|
* see Command.wrap for details */
|
|
@@ -44,16 +57,14 @@ export interface RequestExtWithInput<
|
|
|
44
57
|
A,
|
|
45
58
|
E,
|
|
46
59
|
R
|
|
47
|
-
> extends Commander.CommandContextLocal<Id, Id>,
|
|
60
|
+
> extends Commander.CommandContextLocal<Id, Id>, CommandRequestExtensions<RT, Id, I, A, E, R> {
|
|
48
61
|
/**
|
|
49
|
-
*
|
|
62
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
63
|
+
* This does not perform query cache invalidation.
|
|
50
64
|
*/
|
|
51
|
-
(i: I)
|
|
65
|
+
request: (i: I) => Effect.Effect<A, E, R>
|
|
52
66
|
}
|
|
53
67
|
|
|
54
|
-
/**
|
|
55
|
-
* Request the endpoint
|
|
56
|
-
*/
|
|
57
68
|
export interface RequestExt<
|
|
58
69
|
RT,
|
|
59
70
|
Id extends string,
|
|
@@ -63,25 +74,62 @@ export interface RequestExt<
|
|
|
63
74
|
> extends
|
|
64
75
|
Commander.CommandContextLocal<Id, Id>,
|
|
65
76
|
Commander.CommanderWrap<RT, Id, Id, undefined, void, A, E, R>,
|
|
66
|
-
|
|
67
|
-
Effect.Effect<A, E, R>
|
|
77
|
+
CommandRequestExtensions<RT, Id, void, A, E, R>
|
|
68
78
|
{
|
|
79
|
+
/**
|
|
80
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
81
|
+
* This does not perform query cache invalidation.
|
|
82
|
+
*/
|
|
83
|
+
request: Effect.Effect<A, E, R>
|
|
69
84
|
}
|
|
70
85
|
|
|
71
|
-
export type
|
|
86
|
+
export type CommandRequestWithExtensions<RT, Req> = Req extends
|
|
72
87
|
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer _Request, infer Id>
|
|
73
88
|
? RequestExtWithInput<RT, Id, I, A, E, R>
|
|
74
89
|
: Req extends RequestHandler<infer A, infer E, infer R, infer _Request, infer Id> ? RequestExt<RT, Id, A, E, R>
|
|
75
90
|
: never
|
|
76
91
|
|
|
92
|
+
export interface QueryExtensionsWithInput<I, A, E, R> {
|
|
93
|
+
/**
|
|
94
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
95
|
+
* This does not set up query state tracking.
|
|
96
|
+
*/
|
|
97
|
+
request: (i: I) => Effect.Effect<A, E, R>
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface QueryExtensions<A, E, R> {
|
|
101
|
+
/**
|
|
102
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
103
|
+
* This does not set up query state tracking.
|
|
104
|
+
*/
|
|
105
|
+
request: Effect.Effect<A, E, R>
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type QueryRequestWithExtensions<Req> = Req extends
|
|
109
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer _Request, infer _Id>
|
|
110
|
+
? QueryExtensionsWithInput<I, A, E, R>
|
|
111
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer _Request, infer _Id> ? QueryExtensions<A, E, R>
|
|
112
|
+
: never
|
|
113
|
+
|
|
114
|
+
type QueryHandler<Req> = Req extends
|
|
115
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
116
|
+
? Request["type"] extends "query" ? RequestHandlerWithInput<I, A, E, R, Request, Id> : never
|
|
117
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
118
|
+
? Request["type"] extends "query" ? RequestHandler<A, E, R, Request, Id> : never
|
|
119
|
+
: never
|
|
120
|
+
|
|
121
|
+
type CommandHandler<Req> = Req extends
|
|
122
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
123
|
+
? Request["type"] extends "command" ? RequestHandlerWithInput<I, A, E, R, Request, Id> : never
|
|
124
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
125
|
+
? Request["type"] extends "command" ? RequestHandler<A, E, R, Request, Id> : never
|
|
126
|
+
: never
|
|
127
|
+
|
|
77
128
|
export interface MutationExtensions<RT, Id extends string, I, A, E, R> {
|
|
78
129
|
/** Defines a Command based on this mutation, taking the `id` of the mutation as the `id` of the Command.
|
|
79
130
|
* The Mutation function will be taken as the first member of the Command, the Command required input will be the Mutation input.
|
|
80
131
|
* see Command.wrap for details */
|
|
81
132
|
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
133
|
}
|
|
86
134
|
|
|
87
135
|
/** my other doc */
|
|
@@ -91,39 +139,63 @@ export interface MutationExtWithInput<
|
|
|
91
139
|
I,
|
|
92
140
|
A,
|
|
93
141
|
E,
|
|
94
|
-
R
|
|
95
|
-
|
|
142
|
+
R,
|
|
143
|
+
EA = unknown
|
|
144
|
+
> extends MutationExtensions<RT, Id, I, A, E, R> {
|
|
96
145
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
146
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
147
|
+
* Also invalidates query caches using the request namespace by default.
|
|
148
|
+
* Namespace invalidation targets parent namespace keys
|
|
149
|
+
* (for example `$project/$configuration.get` invalidates `$project`).
|
|
150
|
+
* Override invalidation in client options via `queryInvalidation`.
|
|
100
151
|
*/
|
|
101
152
|
(i: I): Effect.Effect<A, E, R>
|
|
153
|
+
|
|
154
|
+
project: <ProjSchema extends S.Top>(
|
|
155
|
+
schema: EA extends ProjSchema["Encoded"] ? ProjSchema : never
|
|
156
|
+
) => MutationExtWithInput<
|
|
157
|
+
RT,
|
|
158
|
+
Id,
|
|
159
|
+
I,
|
|
160
|
+
S.Schema.Type<ProjSchema>,
|
|
161
|
+
E | S.SchemaError,
|
|
162
|
+
R | S.Codec.DecodingServices<ProjSchema>,
|
|
163
|
+
S.Codec.Encoded<ProjSchema>
|
|
164
|
+
>
|
|
102
165
|
}
|
|
103
166
|
|
|
104
167
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
168
|
+
* Send the request to the endpoint and return the raw Effect response.
|
|
169
|
+
* Also invalidates query caches using the request namespace by default.
|
|
170
|
+
* Namespace invalidation targets parent namespace keys
|
|
171
|
+
* (for example `$project/$configuration.get` invalidates `$project`).
|
|
172
|
+
* Override invalidation in client options via `queryInvalidation`.
|
|
108
173
|
*/
|
|
109
174
|
export interface MutationExt<
|
|
110
175
|
RT,
|
|
111
176
|
Id extends string,
|
|
112
177
|
A,
|
|
113
178
|
E,
|
|
114
|
-
R
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
179
|
+
R,
|
|
180
|
+
EA = unknown
|
|
181
|
+
> extends MutationExtensions<RT, Id, void, A, E, R>, Effect.Effect<A, E, R> {
|
|
182
|
+
project: <ProjSchema extends S.Top>(
|
|
183
|
+
schema: EA extends ProjSchema["Encoded"] ? ProjSchema : never
|
|
184
|
+
) => MutationExt<
|
|
185
|
+
RT,
|
|
186
|
+
Id,
|
|
187
|
+
S.Schema.Type<ProjSchema>,
|
|
188
|
+
E | S.SchemaError,
|
|
189
|
+
R | S.Codec.DecodingServices<ProjSchema>,
|
|
190
|
+
S.Codec.Encoded<ProjSchema>
|
|
191
|
+
>
|
|
121
192
|
}
|
|
122
193
|
|
|
123
194
|
export type MutationWithExtensions<RT, Req> = Req extends
|
|
124
|
-
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer
|
|
125
|
-
? MutationExtWithInput<RT, Id, I, A, E, R
|
|
126
|
-
: Req extends RequestHandler<infer A, infer E, infer R, infer
|
|
195
|
+
RequestHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id>
|
|
196
|
+
? MutationExtWithInput<RT, Id, I, A, E, R, S.Codec.Encoded<Request["success"]>>
|
|
197
|
+
: Req extends RequestHandler<infer A, infer E, infer R, infer Request, infer Id>
|
|
198
|
+
? MutationExt<RT, Id, A, E, R, S.Codec.Encoded<Request["success"]>>
|
|
127
199
|
: never
|
|
128
200
|
|
|
129
201
|
// we don't really care about the RT, as we are in charge of ensuring runtime safety anyway
|
|
@@ -132,29 +204,72 @@ declare const useQuery_: QueryImpl<any>["useQuery"]
|
|
|
132
204
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
133
205
|
declare const useSuspenseQuery_: QueryImpl<any>["useSuspenseQuery"]
|
|
134
206
|
|
|
207
|
+
export interface ProjectResult<RT, I, B, E, R, Request extends Req, Id extends string> {
|
|
208
|
+
request: (i: I) => Effect.Effect<B, E, R>
|
|
209
|
+
query: Exclude<R, RT> extends never ? ReturnType<typeof useQuery_<I, E, B, Request, Id>>
|
|
210
|
+
: MissingDependencies<RT, R> & {}
|
|
211
|
+
suspense: Exclude<R, RT> extends never ? ReturnType<typeof useSuspenseQuery_<I, E, B, Request, Id>>
|
|
212
|
+
: MissingDependencies<RT, R> & {}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export type QueryProjection<RT, HandlerReq> = HandlerReq extends
|
|
216
|
+
RequestHandlerWithInput<infer I, infer _A, infer E, infer R, infer Request, infer Id>
|
|
217
|
+
? Request["type"] extends "query" ? {
|
|
218
|
+
project: <ProjSchema extends S.Top>(
|
|
219
|
+
schema: S.Codec.Encoded<Request["success"]> extends ProjSchema["Encoded"] ? ProjSchema : never
|
|
220
|
+
) => ProjectResult<
|
|
221
|
+
RT,
|
|
222
|
+
I,
|
|
223
|
+
S.Schema.Type<ProjSchema>,
|
|
224
|
+
E | S.SchemaError,
|
|
225
|
+
R | S.Codec.DecodingServices<ProjSchema>,
|
|
226
|
+
Request,
|
|
227
|
+
Id
|
|
228
|
+
>
|
|
229
|
+
}
|
|
230
|
+
: {}
|
|
231
|
+
: HandlerReq extends RequestHandler<infer _A, infer E, infer R, infer Request, infer Id>
|
|
232
|
+
? Request["type"] extends "query" ? {
|
|
233
|
+
project: <ProjSchema extends S.Top>(
|
|
234
|
+
schema: S.Codec.Encoded<Request["success"]> extends ProjSchema["Encoded"] ? ProjSchema : never
|
|
235
|
+
) => ProjectResult<
|
|
236
|
+
RT,
|
|
237
|
+
void,
|
|
238
|
+
S.Schema.Type<ProjSchema>,
|
|
239
|
+
E | S.SchemaError,
|
|
240
|
+
R | S.Codec.DecodingServices<ProjSchema>,
|
|
241
|
+
Request,
|
|
242
|
+
Id
|
|
243
|
+
>
|
|
244
|
+
}
|
|
245
|
+
: {}
|
|
246
|
+
: {}
|
|
247
|
+
|
|
135
248
|
export interface QueriesWithInput<Request extends Req, Id extends string, I, A, E> {
|
|
136
249
|
/**
|
|
137
|
-
*
|
|
250
|
+
* Read helper for query requests.
|
|
251
|
+
* Runs as a tracked Vue Query and returns reactive state.
|
|
252
|
+
* Queries read state and should not be used to mutate it.
|
|
138
253
|
*/
|
|
139
254
|
query: ReturnType<typeof useQuery_<I, E, A, Request, Id>>
|
|
140
255
|
// TODO or suspense as Option?
|
|
141
256
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* So that Suspense and error boundaries can be used.
|
|
257
|
+
* Like `.query`, but returns a Promise for setup-time awaiting.
|
|
258
|
+
* Use this when integrating with Vue Suspense / error boundaries.
|
|
145
259
|
*/
|
|
146
260
|
suspense: ReturnType<typeof useSuspenseQuery_<I, E, A, Request, Id>>
|
|
147
261
|
}
|
|
148
262
|
export interface QueriesWithoutInput<Request extends Req, Id extends string, A, E> {
|
|
149
263
|
/**
|
|
150
|
-
*
|
|
264
|
+
* Read helper for query requests.
|
|
265
|
+
* Runs as a tracked Vue Query and returns reactive state.
|
|
266
|
+
* Queries read state and should not be used to mutate it.
|
|
151
267
|
*/
|
|
152
268
|
query: ReturnType<typeof useQuery_<E, A, Request, Id>>
|
|
153
269
|
// TODO or suspense as Option?
|
|
154
270
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* So that Suspense and error boundaries can be used.
|
|
271
|
+
* Like `.query`, but returns a Promise for setup-time awaiting.
|
|
272
|
+
* Use this when integrating with Vue Suspense / error boundaries.
|
|
158
273
|
*/
|
|
159
274
|
suspense: ReturnType<typeof useSuspenseQuery_<E, A, Request, Id>>
|
|
160
275
|
}
|
|
@@ -166,176 +281,18 @@ export type MissingDependencies<RT, R> = {
|
|
|
166
281
|
|
|
167
282
|
export type Queries<RT, Req> = Req extends
|
|
168
283
|
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
|
-
|
|
284
|
+
? Request["type"] extends "query" ? Exclude<R, RT> extends never ? QueriesWithInput<Request, Id, I, A, E>
|
|
285
|
+
: {
|
|
286
|
+
query: MissingDependencies<RT, R> & {}
|
|
287
|
+
suspense: MissingDependencies<RT, R> & {}
|
|
288
|
+
}
|
|
289
|
+
: never
|
|
174
290
|
: 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
|
-
|
|
291
|
+
? Request["type"] extends "query" ? Exclude<R, RT> extends never ? QueriesWithoutInput<Request, Id, A, E>
|
|
292
|
+
: { query: MissingDependencies<RT, R> & {}; suspense: MissingDependencies<RT, R> & {} }
|
|
293
|
+
: never
|
|
177
294
|
: never
|
|
178
295
|
|
|
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
296
|
const _useMutation = makeMutation()
|
|
340
297
|
|
|
341
298
|
/**
|
|
@@ -389,702 +346,10 @@ export const useMutationInt = (): typeof _useMutation => {
|
|
|
389
346
|
)
|
|
390
347
|
}
|
|
391
348
|
|
|
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"]>
|
|
349
|
+
export type ClientFrom<M extends RequestsAny> = RequestHandlers<never, never, M, ExtractModuleName<M>>
|
|
1085
350
|
|
|
1086
351
|
export class QueryImpl<R> {
|
|
1087
|
-
constructor(readonly getRuntime: () =>
|
|
352
|
+
constructor(readonly getRuntime: () => Context.Context<R>) {
|
|
1088
353
|
this.useQuery = makeQuery(this.getRuntime)
|
|
1089
354
|
}
|
|
1090
355
|
/**
|
|
@@ -1163,7 +428,7 @@ export class QueryImpl<R> {
|
|
|
1163
428
|
} = <Arg, E, A, Request extends Req, Name extends string>(
|
|
1164
429
|
self: RequestHandlerWithInput<Arg, A, E, R, Request, Name> | RequestHandler<A, E, R, Request, Name>
|
|
1165
430
|
) => {
|
|
1166
|
-
const runPromise =
|
|
431
|
+
const runPromise = makeRunPromise(this.getRuntime())
|
|
1167
432
|
const q = this.useQuery(self as any) as any
|
|
1168
433
|
return (argOrOptions?: any, options?: any) => {
|
|
1169
434
|
const [resultRef, latestRef, fetch, uqrt] = q(argOrOptions, { ...options, suspense: true } // experimental_prefetchInRender: true }
|
|
@@ -1214,10 +479,64 @@ export class QueryImpl<R> {
|
|
|
1214
479
|
}
|
|
1215
480
|
|
|
1216
481
|
// 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.
|
|
482
|
+
const managedRuntimeRt = <A, E>(mrt: ManagedRuntime.ManagedRuntime<A, E>) => mrt.runSync(Effect.context<A>())
|
|
1218
483
|
|
|
1219
484
|
type Base = I18n | Toast
|
|
1220
|
-
type Mix = ApiClientFactory | Commander |
|
|
485
|
+
type Mix = ApiClientFactory | Commander | Base
|
|
486
|
+
|
|
487
|
+
type InvalidationResources = Record<string, Record<string, unknown>>
|
|
488
|
+
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends ((arg: infer I) => void) ? I
|
|
489
|
+
: never
|
|
490
|
+
|
|
491
|
+
type CommandInvalidationResources<Req> = Req extends {
|
|
492
|
+
readonly type: "command"
|
|
493
|
+
readonly "~invalidationResources"?: infer Resources
|
|
494
|
+
} ? NonNullable<Resources> extends InvalidationResources ? NonNullable<Resources> : never
|
|
495
|
+
: Req extends {
|
|
496
|
+
readonly config?: infer Config
|
|
497
|
+
} ? Config extends {
|
|
498
|
+
readonly invalidationResources?: infer LegacyResources
|
|
499
|
+
} ? NonNullable<LegacyResources> extends InvalidationResources ? NonNullable<LegacyResources> : never
|
|
500
|
+
: Config extends {
|
|
501
|
+
readonly invalidatesQueries?: InvalidationCallback<infer LegacyResources, any, any, any>
|
|
502
|
+
} ? NonNullable<LegacyResources> extends InvalidationResources ? NonNullable<LegacyResources> : never
|
|
503
|
+
: never
|
|
504
|
+
: never
|
|
505
|
+
|
|
506
|
+
type InvalidationResourcesForUnion<M extends RequestsAny> = {
|
|
507
|
+
[K in keyof M]: CommandInvalidationResources<M[K]>
|
|
508
|
+
}[keyof M]
|
|
509
|
+
|
|
510
|
+
type InvalidationResourcesFor<M extends RequestsAny> = [InvalidationResourcesForUnion<M>] extends [never] ? never
|
|
511
|
+
: UnionToIntersection<InvalidationResourcesForUnion<M>> extends infer R ? R extends InvalidationResources ? R
|
|
512
|
+
: never
|
|
513
|
+
: never
|
|
514
|
+
|
|
515
|
+
type QueryInvalidationFactory<M extends RequestsAny> = (client: ClientFrom<M>) => QueryInvalidation<M>
|
|
516
|
+
|
|
517
|
+
type StrictResourcesArg<Shape, Actual extends Shape = Shape> =
|
|
518
|
+
& Actual
|
|
519
|
+
& Record<Exclude<keyof Actual, keyof Shape>, never>
|
|
520
|
+
|
|
521
|
+
type ClientForArgs<
|
|
522
|
+
M extends RequestsAny,
|
|
523
|
+
Resources extends InvalidationResourcesFor<M> = InvalidationResourcesFor<M>
|
|
524
|
+
> = [InvalidationResourcesFor<M>] extends [never]
|
|
525
|
+
? [
|
|
526
|
+
queryInvalidation?: QueryInvalidationFactory<M>,
|
|
527
|
+
invalidationResources?: StrictResourcesArg<
|
|
528
|
+
InvalidationResourcesFor<M>,
|
|
529
|
+
Resources
|
|
530
|
+
>
|
|
531
|
+
]
|
|
532
|
+
: [
|
|
533
|
+
queryInvalidation: QueryInvalidationFactory<M> | undefined,
|
|
534
|
+
invalidationResources: StrictResourcesArg<
|
|
535
|
+
InvalidationResourcesFor<M>,
|
|
536
|
+
Resources
|
|
537
|
+
>
|
|
538
|
+
]
|
|
539
|
+
|
|
1221
540
|
export const makeClient = <RT_, RTHooks>(
|
|
1222
541
|
// global, but only accessible after startup has completed
|
|
1223
542
|
getBaseMrt: () => ManagedRuntime.ManagedRuntime<RT_ | Mix, never>,
|
|
@@ -1225,54 +544,62 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1225
544
|
rtHooks: Layer.Layer<RTHooks, never, Mix>
|
|
1226
545
|
) => {
|
|
1227
546
|
type RT = RT_ | Mix
|
|
1228
|
-
const getRt = Effect.services<RT>()
|
|
1229
547
|
const getBaseRt = () => managedRuntimeRt(getBaseMrt())
|
|
1230
548
|
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
549
|
let cmd: Effect.Success<typeof makeCommand>
|
|
1237
550
|
const useCommand = () => cmd ??= getBaseMrt().runSync(makeCommand)
|
|
1238
|
-
let mut: Effect.Success<typeof makeMutation>
|
|
1239
|
-
const getMutation = () => mut ??= getBaseMrt().runSync(makeMutation)
|
|
1240
551
|
|
|
1241
552
|
let m: ReturnType<typeof useMutationInt>
|
|
1242
553
|
const useMutation = () => m ??= useMutationInt()
|
|
1243
554
|
|
|
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
555
|
const query = new QueryImpl(getBaseRt)
|
|
1268
556
|
const useQuery = query.useQuery
|
|
1269
557
|
const useSuspenseQuery = query.useSuspenseQuery
|
|
1270
558
|
|
|
1271
|
-
const
|
|
559
|
+
const mergeInvalidation = (
|
|
560
|
+
a?: MutationOptionsBase["queryInvalidation"],
|
|
561
|
+
b?: MutationOptionsBase["queryInvalidation"]
|
|
562
|
+
): MutationOptionsBase["queryInvalidation"] | undefined => {
|
|
563
|
+
if (!a && !b) {
|
|
564
|
+
return undefined
|
|
565
|
+
}
|
|
566
|
+
return (defaultKey, name, input, output) => [
|
|
567
|
+
...(a?.(defaultKey, name, input, output) ?? []),
|
|
568
|
+
...(b?.(defaultKey, name, input, output) ?? [])
|
|
569
|
+
]
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const makeQueryResources = <Resources extends InvalidationResources>(resources: Resources | undefined) => {
|
|
573
|
+
if (!resources) {
|
|
574
|
+
return {} as Record<string, Record<string, unknown>>
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return Struct.keys(resources).reduce((acc, resourceName) => {
|
|
578
|
+
const resource = resources[resourceName]!
|
|
579
|
+
;(acc as any)[resourceName] = Struct.keys(resource).reduce((moduleAcc, requestName) => {
|
|
580
|
+
const request = resource[requestName]!
|
|
581
|
+
if (
|
|
582
|
+
typeof request === "object"
|
|
583
|
+
&& request !== null
|
|
584
|
+
&& "type" in request
|
|
585
|
+
&& (request as { readonly type?: unknown }).type === "query"
|
|
586
|
+
) {
|
|
587
|
+
;(moduleAcc as any)[requestName] = request
|
|
588
|
+
}
|
|
589
|
+
return moduleAcc
|
|
590
|
+
}, {} as Record<string, unknown>)
|
|
591
|
+
return acc
|
|
592
|
+
}, {} as Record<string, Record<string, unknown>>)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const mapQuery = <M extends RequestsAny>(
|
|
1272
596
|
client: ClientFrom<M>
|
|
1273
597
|
) => {
|
|
1274
598
|
const queries = Struct.keys(client).reduce(
|
|
1275
599
|
(acc, key) => {
|
|
600
|
+
if (client[key].Request.type !== "query") {
|
|
601
|
+
return acc
|
|
602
|
+
}
|
|
1276
603
|
;(acc as any)[camelCase(key) + "Query"] = Object.assign(useQuery(client[key] as any), {
|
|
1277
604
|
id: client[key].id
|
|
1278
605
|
})
|
|
@@ -1284,26 +611,35 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1284
611
|
{} as
|
|
1285
612
|
& {
|
|
1286
613
|
// apparently can't get JSDoc in here..
|
|
1287
|
-
[
|
|
614
|
+
[
|
|
615
|
+
Key in keyof typeof client as QueryHandler<typeof client[Key]> extends never ? never
|
|
616
|
+
: `${ToCamel<string & Key>}Query`
|
|
617
|
+
]: Queries<RT, QueryHandler<typeof client[Key]>>["query"]
|
|
1288
618
|
}
|
|
1289
619
|
// todo: or suspense as an Option?
|
|
1290
620
|
& {
|
|
1291
621
|
// apparently can't get JSDoc in here..
|
|
1292
|
-
[
|
|
622
|
+
[
|
|
623
|
+
Key in keyof typeof client as QueryHandler<typeof client[Key]> extends never ? never
|
|
624
|
+
: `${ToCamel<string & Key>}SuspenseQuery`
|
|
625
|
+
]: Queries<
|
|
1293
626
|
RT,
|
|
1294
|
-
typeof client[Key]
|
|
627
|
+
QueryHandler<typeof client[Key]>
|
|
1295
628
|
>["suspense"]
|
|
1296
629
|
}
|
|
1297
630
|
)
|
|
1298
631
|
return queries
|
|
1299
632
|
}
|
|
1300
633
|
|
|
1301
|
-
const mapRequest = <M extends
|
|
634
|
+
const mapRequest = <M extends RequestsAny>(
|
|
1302
635
|
client: ClientFrom<M>
|
|
1303
636
|
) => {
|
|
1304
637
|
const Command = useCommand()
|
|
1305
638
|
const mutations = Struct.keys(client).reduce(
|
|
1306
639
|
(acc, key) => {
|
|
640
|
+
if (client[key].Request.type !== "command") {
|
|
641
|
+
return acc
|
|
642
|
+
}
|
|
1307
643
|
const mut = client[key].handler
|
|
1308
644
|
const fn = Command.fn(client[key].id)
|
|
1309
645
|
const wrap = Command.wrap({ mutate: Effect.isEffect(mut) ? () => mut : mut, id: client[key].id })
|
|
@@ -1315,36 +651,70 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1315
651
|
return acc
|
|
1316
652
|
},
|
|
1317
653
|
{} as {
|
|
1318
|
-
[
|
|
654
|
+
[
|
|
655
|
+
Key in keyof typeof client as CommandHandler<typeof client[Key]> extends never ? never
|
|
656
|
+
: `${ToCamel<string & Key>}Request`
|
|
657
|
+
]: CommandRequestWithExtensions<
|
|
1319
658
|
RT | RTHooks,
|
|
1320
|
-
typeof client[Key]
|
|
659
|
+
CommandHandler<typeof client[Key]>
|
|
1321
660
|
>
|
|
1322
661
|
}
|
|
1323
662
|
)
|
|
1324
663
|
return mutations
|
|
1325
664
|
}
|
|
1326
665
|
|
|
1327
|
-
const mapMutation = <M extends
|
|
1328
|
-
client: ClientFrom<M
|
|
666
|
+
const mapMutation = <M extends RequestsAny>(
|
|
667
|
+
client: ClientFrom<M>,
|
|
668
|
+
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>,
|
|
669
|
+
invalidationResources?: InvalidationResourcesFor<M>
|
|
1329
670
|
) => {
|
|
1330
671
|
const Command = useCommand()
|
|
1331
672
|
const mutation = useMutation()
|
|
673
|
+
const invalidation = queryInvalidation?.(client)
|
|
674
|
+
const queryResources = makeQueryResources(invalidationResources)
|
|
1332
675
|
const mutations = Struct.keys(client).reduce(
|
|
1333
676
|
(acc, key) => {
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
677
|
+
if (client[key].Request.type !== "command") {
|
|
678
|
+
return acc
|
|
679
|
+
}
|
|
680
|
+
const fromRequestConfig = client[key].Request.config?.invalidatesQueries as
|
|
681
|
+
| InvalidationCallback<InvalidationResourcesFor<M>>
|
|
682
|
+
| undefined
|
|
683
|
+
const fromRequest = fromRequestConfig
|
|
684
|
+
? ((defaultKey: string[], _name: string, input?: unknown, output?: unknown) =>
|
|
685
|
+
fromRequestConfig(defaultKey, queryResources as never, input as never, output as never).map((entry) => ({
|
|
686
|
+
filters: entry.filters as InvalidateQueryFilters | undefined,
|
|
687
|
+
options: entry.options as InvalidateOptions | undefined
|
|
688
|
+
})))
|
|
689
|
+
: undefined
|
|
690
|
+
const mergedInvalidation = mergeInvalidation(fromRequest, invalidation?.[key])
|
|
691
|
+
const makeProjectedMutation = (handler: any): any => {
|
|
692
|
+
const mut: any = mutation(
|
|
693
|
+
handler,
|
|
694
|
+
mergedInvalidation ? { queryInvalidation: mergedInvalidation } : undefined
|
|
695
|
+
)
|
|
696
|
+
const wrap = Command.wrap({ mutate: Effect.isEffect(mut) ? () => mut : mut, id: client[key].id })
|
|
697
|
+
return Object.assign(mut, {
|
|
698
|
+
wrap,
|
|
699
|
+
project: (projectionSchema: any) => {
|
|
700
|
+
const projected = {
|
|
701
|
+
...handler,
|
|
702
|
+
handler: projectHandler(handler.handler, client[key].Request.success, projectionSchema)
|
|
703
|
+
}
|
|
704
|
+
return makeProjectedMutation(projected)
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
}
|
|
708
|
+
;(acc as any)[camelCase(key) + "Mutation"] = makeProjectedMutation(client[key] as any)
|
|
1342
709
|
return acc
|
|
1343
710
|
},
|
|
1344
711
|
{} as {
|
|
1345
|
-
[
|
|
712
|
+
[
|
|
713
|
+
Key in keyof typeof client as CommandHandler<typeof client[Key]> extends never ? never
|
|
714
|
+
: `${ToCamel<string & Key>}Mutation`
|
|
715
|
+
]: MutationWithExtensions<
|
|
1346
716
|
RT | RTHooks,
|
|
1347
|
-
typeof client[Key]
|
|
717
|
+
CommandHandler<typeof client[Key]>
|
|
1348
718
|
>
|
|
1349
719
|
}
|
|
1350
720
|
)
|
|
@@ -1353,8 +723,9 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1353
723
|
|
|
1354
724
|
// make available .query, .suspense and .mutate for each operation
|
|
1355
725
|
// and a .helpers with all mutations and queries
|
|
1356
|
-
const mapClient = <M extends
|
|
1357
|
-
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M
|
|
726
|
+
const mapClient = <M extends RequestsAny>(
|
|
727
|
+
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>,
|
|
728
|
+
invalidationResources?: InvalidationResourcesFor<M>
|
|
1358
729
|
) =>
|
|
1359
730
|
(
|
|
1360
731
|
client: ClientFrom<M>
|
|
@@ -1362,71 +733,138 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1362
733
|
const Command = useCommand()
|
|
1363
734
|
const mutation = useMutation()
|
|
1364
735
|
const invalidation = queryInvalidation?.(client)
|
|
736
|
+
const queryResources = makeQueryResources(invalidationResources)
|
|
1365
737
|
const extended = Struct.keys(client).reduce(
|
|
1366
738
|
(acc, key) => {
|
|
739
|
+
const requestType = client[key].Request.type
|
|
1367
740
|
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
741
|
const h_ = client[key].handler
|
|
1385
|
-
const
|
|
742
|
+
const wrapInput = Effect.isEffect(h_)
|
|
1386
743
|
? () => h_
|
|
1387
744
|
: (...args: [any]) => h_(...args)
|
|
745
|
+
const request = Effect.isEffect(h_) ? h_ : wrapInput
|
|
1388
746
|
;(acc as any)[key] = Object.assign(
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
747
|
+
requestType === "query"
|
|
748
|
+
? {
|
|
749
|
+
...client[key],
|
|
750
|
+
request,
|
|
751
|
+
query: useQuery(client[key] as any),
|
|
752
|
+
suspense: useSuspenseQuery(client[key] as any),
|
|
753
|
+
project: (projectionSchema: any) => {
|
|
754
|
+
const successSchema = client[key].Request.success
|
|
755
|
+
const projectionHash = projectionSchemaHash(projectionSchema)
|
|
756
|
+
const projected = projectHandler(h_ as any, successSchema, projectionSchema)
|
|
757
|
+
const fakeHandler = {
|
|
758
|
+
handler: projected,
|
|
759
|
+
id: client[key].id,
|
|
760
|
+
Request: client[key].Request,
|
|
761
|
+
options: client[key].options,
|
|
762
|
+
queryKeyProjectionHash: projectionHash
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
request: projected,
|
|
766
|
+
query: useQuery(fakeHandler as any),
|
|
767
|
+
suspense: useSuspenseQuery(fakeHandler as any)
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
: {
|
|
772
|
+
mutate: ((handler: any) => {
|
|
773
|
+
const fromRequestConfig = client[key].Request.config?.invalidatesQueries as
|
|
774
|
+
| InvalidationCallback<InvalidationResourcesFor<M>>
|
|
775
|
+
| undefined
|
|
776
|
+
const fromRequest = fromRequestConfig
|
|
777
|
+
? ((defaultKey: string[], _name: string, input?: unknown, output?: unknown) =>
|
|
778
|
+
fromRequestConfig(defaultKey, queryResources as never, input as never, output as never).map((
|
|
779
|
+
entry
|
|
780
|
+
) => ({
|
|
781
|
+
filters: entry.filters as InvalidateQueryFilters | undefined,
|
|
782
|
+
options: entry.options as InvalidateOptions | undefined
|
|
783
|
+
})))
|
|
784
|
+
: undefined
|
|
785
|
+
const mergedInvalidation = mergeInvalidation(fromRequest, invalidation?.[key])
|
|
786
|
+
const makeProjectedMutation = (h: any): any => {
|
|
787
|
+
const mutate = mutation(
|
|
788
|
+
h,
|
|
789
|
+
mergedInvalidation ? { queryInvalidation: mergedInvalidation } : undefined
|
|
790
|
+
) as any
|
|
791
|
+
return Object.assign(
|
|
792
|
+
mutate,
|
|
793
|
+
{
|
|
794
|
+
wrap: Command.wrap({
|
|
795
|
+
mutate: Effect.isEffect(mutate) ? () => mutate : mutate,
|
|
796
|
+
id: client[key].id
|
|
797
|
+
}),
|
|
798
|
+
project: (projectionSchema: any) => {
|
|
799
|
+
const projected = {
|
|
800
|
+
...h,
|
|
801
|
+
handler: projectHandler(h.handler, client[key].Request.success, projectionSchema)
|
|
802
|
+
}
|
|
803
|
+
return makeProjectedMutation(projected)
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
)
|
|
807
|
+
}
|
|
808
|
+
return makeProjectedMutation(handler)
|
|
809
|
+
})(client[key] as any),
|
|
810
|
+
...client[key],
|
|
811
|
+
...fn, // to get the i18n key etc.
|
|
812
|
+
request,
|
|
813
|
+
fn,
|
|
814
|
+
wrap: Command.wrap({ mutate: wrapInput, id: client[key].id })
|
|
815
|
+
}
|
|
1399
816
|
)
|
|
1400
817
|
return acc
|
|
1401
818
|
},
|
|
1402
819
|
{} as {
|
|
1403
820
|
[Key in keyof typeof client]:
|
|
1404
821
|
& typeof client[Key]
|
|
1405
|
-
&
|
|
1406
|
-
|
|
1407
|
-
|
|
822
|
+
& (QueryHandler<typeof client[Key]> extends never ? {}
|
|
823
|
+
:
|
|
824
|
+
& QueryRequestWithExtensions<QueryHandler<typeof client[Key]>>
|
|
825
|
+
& Queries<RT, QueryHandler<typeof client[Key]>>
|
|
826
|
+
& QueryProjection<RT, QueryHandler<typeof client[Key]>>)
|
|
827
|
+
& (CommandHandler<typeof client[Key]> extends never ? {}
|
|
828
|
+
: CommandRequestWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>>)
|
|
829
|
+
& (CommandHandler<typeof client[Key]> extends never ? {}
|
|
830
|
+
: { mutate: MutationWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>> })
|
|
831
|
+
& { Input: typeof client[Key] extends RequestHandlerWithInput<infer I, any, any, any, any, any> ? I : never }
|
|
1408
832
|
}
|
|
1409
833
|
)
|
|
1410
|
-
return Object.assign(extended, {
|
|
834
|
+
return Object.assign(extended, {
|
|
835
|
+
helpers: {
|
|
836
|
+
...mapRequest(client),
|
|
837
|
+
...mapMutation(client, queryInvalidation, invalidationResources),
|
|
838
|
+
...mapQuery(client)
|
|
839
|
+
}
|
|
840
|
+
})
|
|
1411
841
|
}
|
|
1412
842
|
|
|
1413
843
|
// TODO: Clean up this delay initialisation messs
|
|
1414
844
|
// TODO; invalidateQueries should perhaps be configured in the Request impl themselves?
|
|
1415
|
-
const clientFor__ = <M extends
|
|
845
|
+
const clientFor__ = <M extends RequestsAny>(
|
|
1416
846
|
m: M,
|
|
1417
|
-
queryInvalidation?:
|
|
1418
|
-
|
|
847
|
+
queryInvalidation?: QueryInvalidationFactory<M>,
|
|
848
|
+
invalidationResources?: InvalidationResourcesFor<M>
|
|
849
|
+
) => getBaseMrt().runSync(clientFor_(m).pipe(Effect.map(mapClient(queryInvalidation, invalidationResources))))
|
|
1419
850
|
|
|
1420
851
|
// delay client creation until first access
|
|
1421
852
|
// the idea is that we don't need the useNuxtApp().$runtime (only available at later initialisation stage)
|
|
1422
853
|
// until we are at a place where it is available..
|
|
1423
|
-
const clientFor = <
|
|
854
|
+
const clientFor = <
|
|
855
|
+
M extends RequestsAny,
|
|
856
|
+
Resources extends InvalidationResourcesFor<M> = InvalidationResourcesFor<M>
|
|
857
|
+
>(
|
|
1424
858
|
m: M,
|
|
1425
|
-
|
|
859
|
+
...args: ClientForArgs<M, Resources>
|
|
1426
860
|
) => {
|
|
861
|
+
const [queryInvalidation, invalidationResources] = args as [
|
|
862
|
+
QueryInvalidationFactory<M> | undefined,
|
|
863
|
+
InvalidationResourcesFor<M> | undefined
|
|
864
|
+
]
|
|
1427
865
|
type Client = ReturnType<typeof clientFor__<M>>
|
|
1428
866
|
let client: Client | undefined = undefined
|
|
1429
|
-
const getOrMakeClient = () => (client ??= clientFor__(m, queryInvalidation))
|
|
867
|
+
const getOrMakeClient = () => (client ??= clientFor__(m, queryInvalidation, invalidationResources))
|
|
1430
868
|
|
|
1431
869
|
// initialize on first use..
|
|
1432
870
|
const proxy = Struct.keys(m).concat(["helpers"]).reduce((acc, key) => {
|
|
@@ -1444,11 +882,6 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1444
882
|
return proxy
|
|
1445
883
|
}
|
|
1446
884
|
|
|
1447
|
-
const legacy: Legacy<RT> = {
|
|
1448
|
-
...mutations,
|
|
1449
|
-
...query
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
885
|
const Command: CommanderResolved<RT, RTHooks> = {
|
|
1453
886
|
...{
|
|
1454
887
|
// delay initialisation until first use...
|
|
@@ -1463,19 +896,17 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
1463
896
|
return {
|
|
1464
897
|
Command,
|
|
1465
898
|
useCommand,
|
|
1466
|
-
clientFor
|
|
1467
|
-
legacy
|
|
899
|
+
clientFor
|
|
1468
900
|
}
|
|
1469
901
|
}
|
|
1470
902
|
|
|
1471
|
-
export interface Legacy<R>
|
|
1472
|
-
extends
|
|
1473
|
-
Pick<QueryImpl<R>, "useQuery" | "useSuspenseQuery">,
|
|
1474
|
-
Omit<LegacyMutationImpl<R>, "getRuntime" | "toast" | "intl">
|
|
1475
|
-
{}
|
|
1476
|
-
|
|
1477
903
|
export type QueryInvalidation<M> = {
|
|
1478
|
-
[K in keyof M]?: (
|
|
904
|
+
[K in keyof M]?: (
|
|
905
|
+
defaultKey: string[],
|
|
906
|
+
name: string,
|
|
907
|
+
input?: unknown,
|
|
908
|
+
output?: ExitResult.Exit<unknown, unknown>
|
|
909
|
+
) => {
|
|
1479
910
|
filters?: InvalidateQueryFilters | undefined
|
|
1480
911
|
options?: InvalidateOptions | undefined
|
|
1481
912
|
}[]
|
|
@@ -1497,6 +928,6 @@ export interface CommandBase<I = void, A = void> {
|
|
|
1497
928
|
|
|
1498
929
|
export interface EffectCommand<I = void, A = unknown, E = unknown> extends CommandBase<I, Fiber<A, E>> {}
|
|
1499
930
|
|
|
1500
|
-
export interface CommandFromRequest<I extends
|
|
1501
|
-
extends EffectCommand<
|
|
931
|
+
export interface CommandFromRequest<I extends { readonly make: (...args: any[]) => any }, A = unknown, E = unknown>
|
|
932
|
+
extends EffectCommand<RequestInputFromMake<I>, A, E>
|
|
1502
933
|
{}
|