effect-app 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/_cjs/client/clientFor.cjs +147 -96
- package/_cjs/client/clientFor.cjs.map +1 -1
- package/_cjs/client.cjs +0 -11
- package/_cjs/client.cjs.map +1 -1
- package/dist/client/clientFor.d.ts +38 -28
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/clientFor.js +115 -97
- package/dist/client.d.ts +0 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -2
- package/package.json +2 -32
- package/src/client/clientFor.ts +241 -158
- package/src/client.ts +0 -1
- package/vitest.config.ts.timestamp-1670862388823.mjs +23 -0
- package/_cjs/client/clientFor2.cjs +0 -197
- package/_cjs/client/clientFor2.cjs.map +0 -1
- package/_cjs/client/fetch.cjs +0 -176
- package/_cjs/client/fetch.cjs.map +0 -1
- package/_cjs/client/router.cjs +0 -31
- package/_cjs/client/router.cjs.map +0 -1
- package/dist/client/clientFor2.d.ts +0 -49
- package/dist/client/clientFor2.d.ts.map +0 -1
- package/dist/client/clientFor2.js +0 -165
- package/dist/client/fetch.d.ts +0 -56
- package/dist/client/fetch.d.ts.map +0 -1
- package/dist/client/fetch.js +0 -158
- package/dist/client/router.d.ts +0 -32
- package/dist/client/router.d.ts.map +0 -1
- package/dist/client/router.js +0 -17
- package/src/client/clientFor2.ts +0 -339
- package/src/client/fetch.ts +0 -299
- package/src/client/router.ts +0 -87
- package/vitest.config.ts.timestamp-1709838418683-4e8d39caec6be.mjs +0 -33
- package/vitest.config.ts.timestamp-1711656440837-b61cd88636759.mjs +0 -37
- package/vitest.config.ts.timestamp-1711724061890-f88ec51585e5c.mjs +0 -37
- package/vitest.config.ts.timestamp-1711743471020-0a3f182bca84f.mjs +0 -0
- package/vitest.config.ts.timestamp-1711743489536-f03d3db08b368.mjs +0 -37
- package/vitest.config.ts.timestamp-1711743593445-f537ce2bb2c6a.mjs +0 -0
package/src/client/clientFor.ts
CHANGED
|
@@ -1,238 +1,316 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
|
|
4
|
-
import { Effect, flow, Predicate } from "@effect-app/core"
|
|
4
|
+
import { Effect, flow, HashMap, Layer, Option, Predicate, Struct } from "@effect-app/core"
|
|
5
|
+
import { RpcResolver } from "@effect/rpc"
|
|
6
|
+
import { HttpRpcResolver } from "@effect/rpc-http"
|
|
7
|
+
import type { RpcRouter } from "@effect/rpc/RpcRouter"
|
|
8
|
+
import type * as Serializable from "@effect/schema/Serializable"
|
|
9
|
+
import { Record } from "effect"
|
|
10
|
+
import { S } from "effect-app"
|
|
11
|
+
import { ApiConfig } from "effect-app/client"
|
|
12
|
+
import { HttpClient, HttpClientRequest } from "effect-app/http"
|
|
5
13
|
import type { Schema } from "effect-app/schema"
|
|
6
|
-
import {
|
|
14
|
+
import { typedKeysOf } from "effect-app/utils"
|
|
15
|
+
import type * as Request from "effect/Request"
|
|
7
16
|
import { Path } from "path-parser"
|
|
8
|
-
import
|
|
9
|
-
import { S } from "../lib.js"
|
|
10
|
-
import { typedKeysOf } from "../utils.js"
|
|
11
|
-
import type { ApiConfig } from "./config.js"
|
|
12
|
-
import type { SupportedErrors } from "./errors.js"
|
|
13
|
-
import type { FetchError, FetchResponse } from "./fetch.js"
|
|
14
|
-
import {
|
|
15
|
-
fetchApi,
|
|
16
|
-
fetchApi3S,
|
|
17
|
-
fetchApi3SE,
|
|
18
|
-
makePathWithBody,
|
|
19
|
-
makePathWithQuery,
|
|
20
|
-
mapResponseM,
|
|
21
|
-
ResError
|
|
22
|
-
} from "./fetch.js"
|
|
23
|
-
|
|
24
|
-
export * from "./config.js"
|
|
17
|
+
import qs from "query-string"
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
export function makePathWithQuery(
|
|
20
|
+
path: Path,
|
|
21
|
+
pars: Record<
|
|
22
|
+
string,
|
|
23
|
+
| string
|
|
24
|
+
| number
|
|
25
|
+
| boolean
|
|
26
|
+
| readonly string[]
|
|
27
|
+
| readonly number[]
|
|
28
|
+
| readonly boolean[]
|
|
29
|
+
| null
|
|
30
|
+
>
|
|
31
|
+
) {
|
|
32
|
+
const forQs = Record.filter(pars, (_, k) => !path.params.includes(k))
|
|
33
|
+
const q = forQs // { ...forQs, _: JSON.stringify(forQs) } // TODO: drop completely individual keys from query?, sticking to json only
|
|
34
|
+
return (
|
|
35
|
+
path.build(pars, { ignoreSearch: true, ignoreConstraints: true })
|
|
36
|
+
+ (Object.keys(q).length
|
|
37
|
+
? "?" + qs.stringify(q)
|
|
38
|
+
: "")
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function makePathWithBody(
|
|
43
|
+
path: Path,
|
|
44
|
+
pars: Record<
|
|
45
|
+
string,
|
|
46
|
+
| string
|
|
47
|
+
| number
|
|
48
|
+
| boolean
|
|
49
|
+
| readonly string[]
|
|
50
|
+
| readonly number[]
|
|
51
|
+
| readonly boolean[]
|
|
52
|
+
| null
|
|
31
53
|
>
|
|
32
|
-
|
|
54
|
+
) {
|
|
55
|
+
return path.build(pars, { ignoreSearch: true, ignoreConstraints: true })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @deprecated will be removed in favour of directly using A/E */
|
|
59
|
+
export interface FetchResponse<T> {
|
|
60
|
+
body: T
|
|
61
|
+
headers: Headers
|
|
62
|
+
status: number
|
|
63
|
+
}
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
type Requests = Record<string, any>
|
|
66
|
+
|
|
67
|
+
const apiClient = Effect.gen(function*() {
|
|
68
|
+
const client = yield* HttpClient.HttpClient
|
|
69
|
+
const config = yield* ApiConfig.Tag
|
|
70
|
+
return client.pipe(
|
|
71
|
+
HttpClient.mapRequest(HttpClientRequest.prependUrl(config.apiUrl + "/rpc")),
|
|
72
|
+
HttpClient.mapRequest(
|
|
73
|
+
HttpClientRequest.setHeaders(config.headers.pipe(Option.getOrElse(() => HashMap.empty())))
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
})
|
|
35
77
|
|
|
36
78
|
export type Client<M extends Requests> =
|
|
37
79
|
& RequestHandlers<
|
|
38
80
|
ApiConfig | HttpClient.HttpClient.Service,
|
|
39
|
-
SupportedErrors | FetchError | ResError,
|
|
81
|
+
never, // SupportedErrors | FetchError | ResError,
|
|
40
82
|
M
|
|
41
83
|
>
|
|
42
84
|
& RequestHandlersE<
|
|
43
85
|
ApiConfig | HttpClient.HttpClient.Service,
|
|
44
|
-
SupportedErrors | FetchError | ResError,
|
|
86
|
+
never, // SupportedErrors | FetchError | ResError,
|
|
45
87
|
M
|
|
46
88
|
>
|
|
47
89
|
|
|
48
|
-
export function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
export function makeClientFor(layers: Layer.Layer<never, never, never>) {
|
|
91
|
+
const cache = new Map<any, Client<any>>()
|
|
92
|
+
|
|
93
|
+
return <M extends Requests>(
|
|
94
|
+
models: M
|
|
95
|
+
): Client<Omit<M, "meta">> => {
|
|
96
|
+
const found = cache.get(models)
|
|
97
|
+
if (found) {
|
|
98
|
+
return found
|
|
99
|
+
}
|
|
100
|
+
const m = clientFor_(models, layers)
|
|
101
|
+
cache.set(models, m)
|
|
102
|
+
return m
|
|
54
103
|
}
|
|
55
|
-
const m = clientFor_(models)
|
|
56
|
-
cache.set(models, m)
|
|
57
|
-
return m
|
|
58
104
|
}
|
|
59
105
|
|
|
60
|
-
|
|
106
|
+
type Req = S.Schema.All & {
|
|
107
|
+
new(...args: any[]): any
|
|
108
|
+
_tag: string
|
|
109
|
+
fields: S.Struct.Fields
|
|
110
|
+
success: S.Schema.Any
|
|
111
|
+
failure: S.Schema.Any
|
|
112
|
+
config?: Record<string, any>
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function clientFor_<M extends Requests>(models: M, layers = Layer.empty) {
|
|
61
116
|
type Filtered = {
|
|
62
|
-
[K in keyof Requests as Requests[K] extends
|
|
63
|
-
? Requests[K]
|
|
64
|
-
: never
|
|
117
|
+
[K in keyof Requests as Requests[K] extends Req ? K : never]: Requests[K] extends Req ? Requests[K] : never
|
|
65
118
|
}
|
|
66
119
|
const filtered = typedKeysOf(models).reduce((acc, cur) => {
|
|
67
120
|
if (
|
|
68
121
|
Predicate.isObject(models[cur])
|
|
69
|
-
&& (models[cur].
|
|
122
|
+
&& (models[cur].success)
|
|
70
123
|
) {
|
|
71
124
|
acc[cur as keyof Filtered] = models[cur]
|
|
72
125
|
}
|
|
73
126
|
return acc
|
|
74
|
-
}, {} as Filtered)
|
|
127
|
+
}, {} as Record<keyof Filtered, Req>)
|
|
128
|
+
|
|
129
|
+
const meta = (models as any).meta as { moduleName: string }
|
|
130
|
+
if (!meta) throw new Error("No meta defined in Resource!")
|
|
131
|
+
|
|
132
|
+
const resolver = flow(
|
|
133
|
+
HttpRpcResolver.make<RpcRouter<any, any>>,
|
|
134
|
+
(_) => RpcResolver.toClient(_ as any)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
const baseClient = apiClient.pipe(
|
|
138
|
+
Effect.andThen(HttpClient.mapRequest(HttpClientRequest.appendUrl("/" + meta.moduleName)))
|
|
139
|
+
)
|
|
140
|
+
|
|
75
141
|
return (typedKeysOf(filtered)
|
|
76
|
-
// ignore module interop with automatic default exports..
|
|
77
|
-
.filter((x) => x !== "default" && x !== "meta")
|
|
78
142
|
.reduce((prev, cur) => {
|
|
79
|
-
const h = filtered[cur]
|
|
143
|
+
const h = filtered[cur]!
|
|
80
144
|
|
|
81
|
-
const
|
|
82
|
-
const Response =
|
|
145
|
+
const Request = h
|
|
146
|
+
const Response = h.success
|
|
83
147
|
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.replaceAll(".js", "")
|
|
88
|
-
|
|
89
|
-
const Request = class extends (Request_ as any) {
|
|
90
|
-
static path = "/" + requestName + (Request_.path === "/" ? "" : Request_.path)
|
|
91
|
-
static method = Request_.method as REST.SupportedMethods === "AUTO"
|
|
92
|
-
? REST.determineMethod(cur as string, Request_)
|
|
93
|
-
: Request_.method
|
|
94
|
-
} as unknown as AnyRequest
|
|
95
|
-
|
|
96
|
-
if ((Request_ as any).method === "AUTO") {
|
|
97
|
-
Object.assign(Request, {
|
|
98
|
-
[Request.method === "GET" || Request.method === "DELETE" ? "Query" : "Body"]: (Request_ as any).Auto
|
|
99
|
-
})
|
|
100
|
-
}
|
|
148
|
+
const encodeRequest = S.encodeSync(
|
|
149
|
+
Request as unknown as S.Schema<any, any>
|
|
150
|
+
)
|
|
101
151
|
|
|
102
|
-
const
|
|
152
|
+
const requestName = `${meta.moduleName}.${cur as string}`
|
|
153
|
+
.replaceAll(".js", "")
|
|
103
154
|
|
|
104
|
-
const
|
|
155
|
+
const requestMeta = {
|
|
156
|
+
method: "POST", // TODO
|
|
105
157
|
Request,
|
|
106
158
|
Response,
|
|
107
|
-
mapPath:
|
|
159
|
+
mapPath: requestName,
|
|
108
160
|
name: requestName
|
|
109
161
|
}
|
|
110
162
|
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
S.decodeUnknown(S.encodedSchema(res)),
|
|
115
|
-
(_) => Effect.mapError(_, (err) => new ResError(err))
|
|
163
|
+
const client = baseClient.pipe(
|
|
164
|
+
Effect.andThen(HttpClient.mapRequest(HttpClientRequest.appendUrlParam("action", cur as string))),
|
|
165
|
+
Effect.andThen(resolver)
|
|
116
166
|
)
|
|
117
167
|
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
// TODO: look into ast, look for propertySignatures, etc.
|
|
123
|
-
// TODO: and fix type wise
|
|
124
|
-
// if we don't need fields, then also dont require an argument.
|
|
125
|
-
const fields = [Request.Body, Request.Query, Request.Path]
|
|
126
|
-
.filter((x) => x)
|
|
127
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
128
|
-
.flatMap((x) => x.ast.propertySignatures)
|
|
168
|
+
const fields = Struct.omit(Request.fields, "_tag")
|
|
169
|
+
const p = requestName
|
|
170
|
+
const path = new Path(p) // TODO
|
|
129
171
|
// @ts-expect-error doc
|
|
130
|
-
prev[cur] =
|
|
131
|
-
? fields.length === 0
|
|
172
|
+
prev[cur] = requestMeta.method === "GET"
|
|
173
|
+
? Object.keys(fields).length === 0
|
|
132
174
|
? {
|
|
133
|
-
handler:
|
|
175
|
+
handler: client
|
|
134
176
|
.pipe(
|
|
135
|
-
Effect.
|
|
177
|
+
Effect.andThen((cl) => cl(new Request())),
|
|
178
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO
|
|
136
179
|
Effect
|
|
137
180
|
.withSpan("client.request " + requestName, {
|
|
138
181
|
captureStackTrace: false,
|
|
139
182
|
attributes: { "request.name": requestName }
|
|
140
|
-
})
|
|
183
|
+
}),
|
|
184
|
+
Effect.provide(layers)
|
|
141
185
|
),
|
|
142
|
-
...
|
|
186
|
+
...requestMeta
|
|
143
187
|
}
|
|
144
188
|
: {
|
|
145
189
|
handler: (req: any) =>
|
|
146
|
-
|
|
190
|
+
client
|
|
147
191
|
.pipe(
|
|
148
|
-
Effect.
|
|
192
|
+
Effect.andThen((cl) => cl(new Request(req))),
|
|
193
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO
|
|
149
194
|
Effect
|
|
150
195
|
.withSpan("client.request " + requestName, {
|
|
151
196
|
captureStackTrace: false,
|
|
152
197
|
attributes: { "request.name": requestName }
|
|
153
|
-
})
|
|
198
|
+
}),
|
|
199
|
+
Effect.provide(layers)
|
|
154
200
|
),
|
|
155
|
-
...
|
|
156
|
-
mapPath: (req: any) => req ? makePathWithQuery(path,
|
|
201
|
+
...requestMeta,
|
|
202
|
+
mapPath: (req: any) => req ? makePathWithQuery(path, encodeRequest(req)) : p
|
|
157
203
|
}
|
|
158
|
-
: fields.length === 0
|
|
204
|
+
: Object.keys(fields).length === 0
|
|
159
205
|
? {
|
|
160
|
-
handler:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
206
|
+
handler: client
|
|
207
|
+
.pipe(
|
|
208
|
+
Effect.andThen((cl) => cl(new Request())),
|
|
209
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO
|
|
210
|
+
Effect.withSpan("client.request " + requestName, {
|
|
211
|
+
captureStackTrace: false,
|
|
212
|
+
attributes: { "request.name": requestName }
|
|
213
|
+
}),
|
|
214
|
+
Effect.provide(layers)
|
|
215
|
+
),
|
|
216
|
+
...requestMeta
|
|
165
217
|
}
|
|
166
218
|
: {
|
|
167
219
|
handler: (req: any) =>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
220
|
+
client
|
|
221
|
+
.pipe(
|
|
222
|
+
Effect.andThen((cl) => cl(new Request(req))),
|
|
223
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO
|
|
224
|
+
Effect.withSpan("client.request " + requestName, {
|
|
225
|
+
captureStackTrace: false,
|
|
226
|
+
attributes: { "request.name": requestName }
|
|
227
|
+
}),
|
|
228
|
+
Effect.provide(layers)
|
|
229
|
+
),
|
|
172
230
|
|
|
173
|
-
...
|
|
231
|
+
...requestMeta,
|
|
174
232
|
mapPath: (req: any) =>
|
|
175
233
|
req
|
|
176
|
-
?
|
|
177
|
-
? makePathWithQuery(path,
|
|
178
|
-
: makePathWithBody(path,
|
|
179
|
-
:
|
|
234
|
+
? requestMeta.method === "DELETE"
|
|
235
|
+
? makePathWithQuery(path, encodeRequest(req))
|
|
236
|
+
: makePathWithBody(path, encodeRequest(req))
|
|
237
|
+
: p
|
|
180
238
|
}
|
|
181
239
|
|
|
182
240
|
// generate handler
|
|
183
241
|
|
|
184
242
|
// @ts-expect-error doc
|
|
185
|
-
prev[`${cur}E`] =
|
|
186
|
-
? fields.length === 0
|
|
243
|
+
prev[`${cur}E`] = requestMeta.method === "GET"
|
|
244
|
+
? Object.keys(fields).length === 0
|
|
187
245
|
? {
|
|
188
|
-
handler:
|
|
246
|
+
handler: client
|
|
189
247
|
.pipe(
|
|
190
|
-
Effect.
|
|
248
|
+
Effect.andThen((cl) => cl(new Request())),
|
|
249
|
+
Effect.flatMap((res) => S.encode(Response)(res)), // TODO
|
|
250
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO,
|
|
191
251
|
Effect
|
|
192
252
|
.withSpan("client.request " + requestName, {
|
|
193
253
|
captureStackTrace: false,
|
|
194
254
|
attributes: { "request.name": requestName }
|
|
195
|
-
})
|
|
255
|
+
}),
|
|
256
|
+
Effect.provide(layers)
|
|
196
257
|
),
|
|
197
|
-
...
|
|
258
|
+
...requestMeta
|
|
198
259
|
}
|
|
199
260
|
: {
|
|
200
261
|
handler: (req: any) =>
|
|
201
|
-
|
|
262
|
+
client
|
|
202
263
|
.pipe(
|
|
203
|
-
Effect.
|
|
264
|
+
Effect.andThen((cl) => cl(new Request(req))),
|
|
265
|
+
Effect.flatMap((res) => S.encode(Response)(res)), // TODO
|
|
266
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO,
|
|
204
267
|
Effect
|
|
205
268
|
.withSpan("client.request " + requestName, {
|
|
206
269
|
captureStackTrace: false,
|
|
207
270
|
attributes: { "request.name": requestName }
|
|
208
|
-
})
|
|
271
|
+
}),
|
|
272
|
+
Effect.provide(layers)
|
|
209
273
|
),
|
|
210
274
|
|
|
211
|
-
...
|
|
212
|
-
mapPath: (req: any) => req ? makePathWithQuery(path,
|
|
275
|
+
...requestMeta,
|
|
276
|
+
mapPath: (req: any) => req ? makePathWithQuery(path, encodeRequest(req)) : p
|
|
213
277
|
}
|
|
214
|
-
: fields.length === 0
|
|
278
|
+
: Object.keys(fields).length === 0
|
|
215
279
|
? {
|
|
216
|
-
handler:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
280
|
+
handler: client
|
|
281
|
+
.pipe(
|
|
282
|
+
Effect.andThen((cl) => cl(new Request())),
|
|
283
|
+
Effect.flatMap((res) => S.encode(Response)(res)), // TODO
|
|
284
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO,
|
|
285
|
+
Effect.withSpan("client.request " + requestName, {
|
|
286
|
+
captureStackTrace: false,
|
|
287
|
+
attributes: { "request.name": requestName }
|
|
288
|
+
}),
|
|
289
|
+
Effect.provide(layers)
|
|
290
|
+
),
|
|
291
|
+
...requestMeta
|
|
221
292
|
}
|
|
222
293
|
: {
|
|
223
294
|
handler: (req: any) =>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
295
|
+
client
|
|
296
|
+
.pipe(
|
|
297
|
+
Effect.andThen((cl) => cl(new Request(req))),
|
|
298
|
+
Effect.flatMap((res) => S.encode(Response)(res)), // TODO
|
|
299
|
+
Effect.map((_) => ({ body: _, status: 200, headers: {} })), // TODO,
|
|
300
|
+
Effect.withSpan("client.request " + requestName, {
|
|
301
|
+
captureStackTrace: false,
|
|
302
|
+
attributes: { "request.name": requestName }
|
|
303
|
+
}),
|
|
304
|
+
Effect.provide(layers)
|
|
305
|
+
),
|
|
228
306
|
|
|
229
|
-
...
|
|
307
|
+
...requestMeta,
|
|
230
308
|
mapPath: (req: any) =>
|
|
231
309
|
req
|
|
232
|
-
?
|
|
233
|
-
? makePathWithQuery(path,
|
|
234
|
-
: makePathWithBody(path,
|
|
235
|
-
:
|
|
310
|
+
? requestMeta.method === "DELETE"
|
|
311
|
+
? makePathWithQuery(path, encodeRequest(req))
|
|
312
|
+
: makePathWithBody(path, encodeRequest(req))
|
|
313
|
+
: p
|
|
236
314
|
}
|
|
237
315
|
// generate handler
|
|
238
316
|
|
|
@@ -248,56 +326,61 @@ export type ExtractEResponse<T> = T extends Schema<any, any, any> ? Schema.Encod
|
|
|
248
326
|
: T extends unknown ? void
|
|
249
327
|
: never
|
|
250
328
|
|
|
251
|
-
type
|
|
329
|
+
type IsEmpty<T> = keyof T extends never ? true
|
|
252
330
|
: false
|
|
253
331
|
|
|
332
|
+
type Cruft = "_tag" | Request.RequestTypeId | typeof Serializable.symbol | typeof Serializable.symbolResult
|
|
333
|
+
|
|
254
334
|
// TODO: refactor to new Request pattern, then filter out non-requests similar to the runtime changes in clientFor, and matchFor (boilerplate)
|
|
255
335
|
type RequestHandlers<R, E, M extends Requests> = {
|
|
256
|
-
[K in keyof M]:
|
|
257
|
-
handler: Effect<FetchResponse<
|
|
258
|
-
Request:
|
|
259
|
-
Reponse:
|
|
336
|
+
[K in keyof M]: IsEmpty<Omit<S.Schema.Type<M[K]>, Cruft>> extends true ? {
|
|
337
|
+
handler: Effect<FetchResponse<Schema.Type<M[K]["success"]>>, Schema.Type<M[K]["failure"]> | E, R>
|
|
338
|
+
Request: M[K]
|
|
339
|
+
Reponse: Schema.Type<M[K]["success"]>
|
|
260
340
|
mapPath: string
|
|
261
341
|
name: string
|
|
262
342
|
}
|
|
263
343
|
: {
|
|
264
344
|
handler: (
|
|
265
|
-
req: S.Schema.Type<
|
|
345
|
+
req: Omit<S.Schema.Type<M[K]>, Cruft>
|
|
266
346
|
) => Effect<
|
|
267
|
-
FetchResponse<
|
|
268
|
-
E,
|
|
347
|
+
FetchResponse<Schema.Type<M[K]["success"]>>,
|
|
348
|
+
Schema.Type<M[K]["failure"]> | E,
|
|
269
349
|
R
|
|
270
350
|
>
|
|
271
|
-
Request:
|
|
272
|
-
Reponse:
|
|
273
|
-
mapPath: (req: S.Schema.Type<
|
|
351
|
+
Request: M[K]
|
|
352
|
+
Reponse: Schema.Type<M[K]["success"]>
|
|
353
|
+
mapPath: (req: Omit<S.Schema.Type<M[K]>, Cruft>) => string
|
|
274
354
|
name: string
|
|
275
355
|
}
|
|
276
356
|
}
|
|
277
357
|
|
|
278
358
|
type RequestHandlersE<R, E, M extends Requests> = {
|
|
279
|
-
[K in keyof M & string as `${K}E`]:
|
|
359
|
+
[K in keyof M & string as `${K}E`]: IsEmpty<Omit<S.Schema.Type<M[K]>, Cruft>> extends true ? {
|
|
280
360
|
handler: Effect<
|
|
281
|
-
FetchResponse<
|
|
282
|
-
E,
|
|
361
|
+
FetchResponse<Schema.Encoded<M[K]["success"]>>,
|
|
362
|
+
Schema.Type<M[K]["failure"]> | E,
|
|
283
363
|
R
|
|
284
364
|
>
|
|
285
|
-
Request:
|
|
286
|
-
Reponse:
|
|
365
|
+
Request: M[K]
|
|
366
|
+
Reponse: Schema.Type<M[K]["success"]>
|
|
287
367
|
mapPath: string
|
|
288
368
|
name: string
|
|
289
369
|
}
|
|
290
370
|
: {
|
|
291
371
|
handler: (
|
|
292
|
-
req:
|
|
372
|
+
req: Omit<
|
|
373
|
+
S.Schema.Type<M[K]>,
|
|
374
|
+
Cruft
|
|
375
|
+
>
|
|
293
376
|
) => Effect<
|
|
294
|
-
FetchResponse<
|
|
295
|
-
E,
|
|
377
|
+
FetchResponse<Schema.Encoded<M[K]["success"]>>,
|
|
378
|
+
Schema.Type<M[K]["failure"]> | E,
|
|
296
379
|
R
|
|
297
380
|
>
|
|
298
|
-
Request:
|
|
299
|
-
Reponse:
|
|
300
|
-
mapPath: (req: S.Schema.Type<
|
|
381
|
+
Request: M[K]
|
|
382
|
+
Reponse: Schema.Type<M[K]["success"]>
|
|
383
|
+
mapPath: (req: Omit<S.Schema.Type<M[K]>, Cruft>) => string
|
|
301
384
|
name: string
|
|
302
385
|
}
|
|
303
386
|
}
|
package/src/client.ts
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// vitest.config.ts
|
|
2
|
+
import { defineConfig } from "file:///Users/patrickroza/Projects/Personal/effect-ts-app/libs/node_modules/.pnpm/vite@4.0.0_@types+node@18.11.12/node_modules/vite/dist/node/index.js";
|
|
3
|
+
|
|
4
|
+
// ../../vite.config.base.ts
|
|
5
|
+
import { tsPlugin } from "file:///Users/patrickroza/Projects/Personal/effect-ts-app/libs/packages/compiler/dist/vitePlugin.js";
|
|
6
|
+
function makeConfig() {
|
|
7
|
+
return {
|
|
8
|
+
plugins: [tsPlugin({})],
|
|
9
|
+
test: {
|
|
10
|
+
include: ["./_src/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
11
|
+
exclude: ["./_test/**/*"],
|
|
12
|
+
reporters: "verbose",
|
|
13
|
+
globals: true
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// vitest.config.ts
|
|
19
|
+
var vitest_config_default = defineConfig(makeConfig());
|
|
20
|
+
export {
|
|
21
|
+
vitest_config_default as default
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZXN0LmNvbmZpZy50cyIsICIuLi8uLi92aXRlLmNvbmZpZy5iYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL1Byb2plY3RzL1BlcnNvbmFsL2VmZmVjdC10cy1hcHAvbGlicy9wYWNrYWdlcy9ib2lsZXJwbGF0ZS1wcmVsdWRlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMvcGF0cmlja3JvemEvUHJvamVjdHMvUGVyc29uYWwvZWZmZWN0LXRzLWFwcC9saWJzL3BhY2thZ2VzL2JvaWxlcnBsYXRlLXByZWx1ZGUvdml0ZXN0LmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvcGF0cmlja3JvemEvUHJvamVjdHMvUGVyc29uYWwvZWZmZWN0LXRzLWFwcC9saWJzL3BhY2thZ2VzL2JvaWxlcnBsYXRlLXByZWx1ZGUvdml0ZXN0LmNvbmZpZy50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlXCJcbmltcG9ydCBtYWtlQ29uZmlnIGZyb20gXCIuLi8uLi92aXRlLmNvbmZpZy5iYXNlXCJcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKG1ha2VDb25maWcoKSlcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL1Byb2plY3RzL1BlcnNvbmFsL2VmZmVjdC10cy1hcHAvbGlic1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL1Byb2plY3RzL1BlcnNvbmFsL2VmZmVjdC10cy1hcHAvbGlicy92aXRlLmNvbmZpZy5iYXNlLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9Qcm9qZWN0cy9QZXJzb25hbC9lZmZlY3QtdHMtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCB7IHRzUGx1Z2luIH0gZnJvbSBcIkBlZmZlY3QtdHMtYXBwL2NvbXBpbGVyL3ZpdGVQbHVnaW5cIlxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gbWFrZUNvbmZpZygpIHtcbiAgcmV0dXJuIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIHBsdWdpbnM6IFt0c1BsdWdpbih7fSldLFxuICAgIHRlc3Q6IHtcbiAgICAgIGluY2x1ZGU6IFtcIi4vX3NyYy8qKi8qLnRlc3Que2pzLG1qcyxjanMsdHMsbXRzLGN0cyxqc3gsdHN4fVwiXSxcbiAgICAgIGV4Y2x1ZGU6IFtcIi4vX3Rlc3QvKiovKlwiXSxcbiAgICAgIHJlcG9ydGVyczogXCJ2ZXJib3NlXCIsXG4gICAgICBnbG9iYWxzOiB0cnVlXG4gICAgfSxcbiAgICAvLyByZXNvbHZlOiB7XG4gICAgLy8gICBhbGlhczoge1xuICAgIC8vICAgICBcIkBlZmZlY3QvaW8vdGVzdFwiOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcIi90ZXN0XCIpLFxuICAgIC8vICAgICBcIkBlZmZlY3QvaW9cIjogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCIvc3JjXCIpXG4gICAgLy8gICB9XG4gICAgLy8gfVxuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUyxvQkFBb0I7OztBQ0E3QixTQUFTLGdCQUFnQjtBQUNWLFNBQVIsYUFBOEI7QUFDbkMsU0FBTztBQUFBLElBRUwsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7QUFBQSxJQUN0QixNQUFNO0FBQUEsTUFDSixTQUFTLENBQUMsa0RBQWtEO0FBQUEsTUFDNUQsU0FBUyxDQUFDLGNBQWM7QUFBQSxNQUN4QixXQUFXO0FBQUEsTUFDWCxTQUFTO0FBQUEsSUFDWDtBQUFBLEVBT0Y7QUFDRjs7O0FEZkEsSUFBTyx3QkFBUSxhQUFhLFdBQVcsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
|