effect-app 4.0.0-beta.15 → 4.0.0-beta.151
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 +595 -0
- package/dist/Array.d.ts +1 -1
- package/dist/Chunk.d.ts +1 -1
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Config/SecretURL.d.ts +1 -1
- package/dist/Config/SecretURL.d.ts.map +1 -1
- package/dist/Config/SecretURL.js +2 -2
- package/dist/Config/internal/configSecretURL.d.ts +1 -1
- package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
- package/dist/Config.d.ts +7 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +6 -0
- package/dist/ConfigProvider.d.ts +39 -0
- package/dist/ConfigProvider.d.ts.map +1 -0
- package/dist/ConfigProvider.js +42 -0
- package/dist/Context.d.ts +40 -0
- package/dist/Context.d.ts.map +1 -0
- package/dist/Context.js +67 -0
- package/dist/Effect.d.ts +9 -10
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +3 -6
- package/dist/Function.d.ts +1 -1
- package/dist/Function.d.ts.map +1 -1
- package/dist/Inputify.type.d.ts +1 -1
- package/dist/Layer.d.ts +6 -5
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +1 -1
- package/dist/NonEmptySet.d.ts +1 -1
- package/dist/NonEmptySet.d.ts.map +1 -1
- package/dist/Operations.d.ts +372 -50
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Operations.js +9 -9
- package/dist/Option.d.ts +1 -1
- package/dist/Option.d.ts.map +1 -1
- package/dist/Pure.d.ts +5 -5
- package/dist/Pure.d.ts.map +1 -1
- package/dist/Pure.js +13 -13
- package/dist/Schema/Class.d.ts +69 -20
- package/dist/Schema/Class.d.ts.map +1 -1
- package/dist/Schema/Class.js +193 -22
- package/dist/Schema/FastCheck.d.ts +1 -1
- package/dist/Schema/FastCheck.d.ts.map +1 -1
- package/dist/Schema/Methods.d.ts +1 -1
- package/dist/Schema/SpecialJsonSchema.d.ts +33 -0
- package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
- package/dist/Schema/SpecialJsonSchema.js +122 -0
- package/dist/Schema/SpecialOpenApi.d.ts +32 -0
- package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
- package/dist/Schema/SpecialOpenApi.js +123 -0
- package/dist/Schema/brand.d.ts +7 -2
- package/dist/Schema/brand.d.ts.map +1 -1
- package/dist/Schema/brand.js +1 -1
- package/dist/Schema/email.d.ts +1 -1
- package/dist/Schema/email.d.ts.map +1 -1
- package/dist/Schema/email.js +7 -4
- package/dist/Schema/ext.d.ts +113 -48
- package/dist/Schema/ext.d.ts.map +1 -1
- package/dist/Schema/ext.js +115 -53
- package/dist/Schema/moreStrings.d.ts +111 -11
- package/dist/Schema/moreStrings.d.ts.map +1 -1
- package/dist/Schema/moreStrings.js +14 -15
- package/dist/Schema/numbers.d.ts +127 -15
- package/dist/Schema/numbers.d.ts.map +1 -1
- package/dist/Schema/numbers.js +10 -12
- package/dist/Schema/phoneNumber.d.ts +1 -1
- package/dist/Schema/phoneNumber.d.ts.map +1 -1
- package/dist/Schema/phoneNumber.js +6 -3
- package/dist/Schema/schema.d.ts +1 -1
- package/dist/Schema/strings.d.ts +37 -5
- package/dist/Schema/strings.d.ts.map +1 -1
- package/dist/Schema/strings.js +1 -5
- package/dist/Schema.d.ts +88 -53
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +125 -63
- package/dist/Set.d.ts +1 -1
- package/dist/Set.d.ts.map +1 -1
- package/dist/TypeTest.d.ts +1 -1
- package/dist/Types.d.ts +1 -1
- package/dist/Widen.type.d.ts +1 -1
- package/dist/_ext/Array.d.ts +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/date.d.ts +1 -1
- package/dist/_ext/misc.d.ts +1 -1
- package/dist/_ext/ord.ext.d.ts +1 -1
- package/dist/_ext/ord.ext.d.ts.map +1 -1
- package/dist/builtin.d.ts +1 -1
- package/dist/builtin.d.ts.map +1 -1
- package/dist/client/apiClientFactory.d.ts +14 -30
- package/dist/client/apiClientFactory.d.ts.map +1 -1
- package/dist/client/apiClientFactory.js +18 -19
- package/dist/client/clientFor.d.ts +7 -6
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/errors.d.ts +44 -19
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +35 -10
- package/dist/client/makeClient.d.ts +77 -29
- package/dist/client/makeClient.d.ts.map +1 -1
- package/dist/client/makeClient.js +49 -23
- package/dist/client.d.ts +1 -1
- package/dist/faker.d.ts +1 -1
- package/dist/faker.d.ts.map +1 -1
- package/dist/http/Request.d.ts +2 -2
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +5 -5
- package/dist/http/internal/lib.d.ts +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/ids.d.ts +3 -3
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +3 -2
- package/dist/index.d.ts +5 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/logger.d.ts +1 -1
- package/dist/middleware.d.ts +8 -8
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +8 -8
- package/dist/rpc/MiddlewareMaker.d.ts +5 -4
- package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
- package/dist/rpc/MiddlewareMaker.js +26 -27
- package/dist/rpc/RpcContextMap.d.ts +3 -3
- package/dist/rpc/RpcContextMap.d.ts.map +1 -1
- package/dist/rpc/RpcContextMap.js +4 -4
- package/dist/rpc/RpcMiddleware.d.ts +5 -4
- package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/rpc/RpcMiddleware.js +1 -1
- package/dist/rpc.d.ts +1 -2
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +1 -2
- package/dist/transform.d.ts +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +3 -3
- package/dist/utils/effectify.d.ts +1 -1
- package/dist/utils/extend.d.ts +1 -1
- package/dist/utils/extend.d.ts.map +1 -1
- package/dist/utils/gen.d.ts +2 -2
- package/dist/utils/gen.d.ts.map +1 -1
- package/dist/utils/logLevel.d.ts +2 -2
- package/dist/utils/logLevel.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +3 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +3 -3
- package/dist/utils.d.ts +30 -10
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -4
- package/dist/validation/validators.d.ts +1 -1
- package/dist/validation/validators.d.ts.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/eslint.config.mjs +1 -1
- package/package.json +35 -19
- package/src/Config/SecretURL.ts +2 -1
- package/src/Config.ts +14 -0
- package/src/ConfigProvider.ts +48 -0
- package/src/{ServiceMap.ts → Context.ts} +52 -59
- package/src/Effect.ts +12 -14
- package/src/Layer.ts +5 -4
- package/src/Operations.ts +9 -9
- package/src/Pure.ts +17 -18
- package/src/Schema/Class.ts +281 -62
- package/src/Schema/SpecialJsonSchema.ts +137 -0
- package/src/Schema/SpecialOpenApi.ts +130 -0
- package/src/Schema/brand.ts +9 -1
- package/src/Schema/email.ts +7 -2
- package/src/Schema/ext.ts +196 -87
- package/src/Schema/moreStrings.ts +22 -20
- package/src/Schema/numbers.ts +14 -16
- package/src/Schema/phoneNumber.ts +5 -1
- package/src/Schema/strings.ts +4 -8
- package/src/Schema.ts +256 -98
- package/src/client/apiClientFactory.ts +107 -113
- package/src/client/clientFor.ts +6 -1
- package/src/client/errors.ts +42 -17
- package/src/client/makeClient.ts +156 -63
- package/src/http/Request.ts +7 -4
- package/src/ids.ts +2 -1
- package/src/index.ts +5 -10
- package/src/middleware.ts +7 -9
- package/src/rpc/MiddlewareMaker.ts +36 -47
- package/src/rpc/RpcContextMap.ts +6 -5
- package/src/rpc/RpcMiddleware.ts +5 -4
- package/src/rpc.ts +0 -1
- package/src/transform.ts +2 -2
- package/src/utils/gen.ts +1 -1
- package/src/utils/logger.ts +2 -2
- package/src/utils.ts +47 -11
- package/test/dist/rpc.test.d.ts.map +1 -1
- package/test/dist/secretURL.test.d.ts.map +1 -0
- package/test/dist/special.test.d.ts.map +1 -0
- package/test/rpc.test.ts +38 -6
- package/test/schema.test.ts +594 -4
- package/test/secretURL.test.ts +157 -0
- package/test/special.test.ts +1005 -0
- package/test/utils.test.ts +6 -6
- package/tsconfig.base.json +0 -1
- package/tsconfig.json +0 -1
- package/dist/ServiceMap.d.ts +0 -44
- package/dist/ServiceMap.d.ts.map +0 -1
- package/dist/ServiceMap.js +0 -91
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import * as Config from "effect/Config"
|
|
3
2
|
import { flow } from "effect/Function"
|
|
4
3
|
import * as Layer from "effect/Layer"
|
|
5
4
|
import * as ManagedRuntime from "effect/ManagedRuntime"
|
|
@@ -7,13 +6,14 @@ import * as Predicate from "effect/Predicate"
|
|
|
7
6
|
import * as Schema from "effect/Schema"
|
|
8
7
|
import * as Struct from "effect/Struct"
|
|
9
8
|
import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/unstable/rpc"
|
|
9
|
+
import * as Config from "../Config.js"
|
|
10
|
+
import * as Context from "../Context.js"
|
|
10
11
|
import * as Effect from "../Effect.js"
|
|
11
12
|
import { HttpClient, HttpClientRequest } from "../http.js"
|
|
12
13
|
import * as Option from "../Option.js"
|
|
13
14
|
import type * as S from "../Schema.js"
|
|
14
|
-
import * as ServiceMap from "../ServiceMap.js"
|
|
15
15
|
import { typedKeysOf, typedValuesOf } from "../utils.js"
|
|
16
|
-
import type { Client, ClientForOptions,
|
|
16
|
+
import type { Client, ClientForOptions, ExtractModuleName, RequestsAny } from "./clientFor.js"
|
|
17
17
|
|
|
18
18
|
export interface ApiConfig {
|
|
19
19
|
url: string
|
|
@@ -31,16 +31,19 @@ export const DefaultApiConfig = Config.all({
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
export type Req = S.Top & {
|
|
34
|
-
|
|
34
|
+
readonly make: (...args: any[]) => any
|
|
35
35
|
_tag: string
|
|
36
36
|
fields: S.Struct.Fields
|
|
37
37
|
success: S.Top
|
|
38
38
|
error: S.Top
|
|
39
39
|
config?: Record<string, any>
|
|
40
|
+
readonly id: string
|
|
41
|
+
readonly moduleName: string
|
|
42
|
+
readonly type: "command" | "query"
|
|
40
43
|
readonly "~decodingServices"?: unknown
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
class RequestName extends
|
|
46
|
+
class RequestName extends Context.Reference("RequestName", {
|
|
44
47
|
defaultValue: () => ({ requestName: "Unspecified", moduleName: "Error" })
|
|
45
48
|
}) {}
|
|
46
49
|
|
|
@@ -84,7 +87,7 @@ type RpcHandlers<M extends RequestsAny> = {
|
|
|
84
87
|
[K in keyof M]: Rpc.Rpc<M[K]["_tag"], M[K], M[K]["success"], M[K]["error"]>
|
|
85
88
|
}
|
|
86
89
|
|
|
87
|
-
const getFiltered = <M extends
|
|
90
|
+
const getFiltered = <M extends RequestsAny>(resource: M) => {
|
|
88
91
|
type Filtered = {
|
|
89
92
|
[K in keyof M as M[K] extends Req ? K : never]: M[K] extends Req ? M[K] : never
|
|
90
93
|
}
|
|
@@ -102,13 +105,13 @@ const getFiltered = <M extends Requests>(resource: M) => {
|
|
|
102
105
|
return filtered as unknown as Filtered
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
export const getMeta = <M extends
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
|
|
108
|
+
export const getMeta = <M extends RequestsAny>(resource: M): { moduleName: ExtractModuleName<M> } => {
|
|
109
|
+
const first = typedValuesOf(getFiltered(resource))[0]
|
|
110
|
+
if (first && "moduleName" in first) return { moduleName: first.moduleName }
|
|
111
|
+
throw new Error("No moduleName on requests!")
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
export const makeRpcGroupFromRequestsAndModuleName = <M extends
|
|
114
|
+
export const makeRpcGroupFromRequestsAndModuleName = <M extends RequestsAny, const ModuleName extends string>(
|
|
112
115
|
resource: M,
|
|
113
116
|
moduleName: ModuleName
|
|
114
117
|
) => {
|
|
@@ -126,20 +129,13 @@ export const makeRpcGroupFromRequestsAndModuleName = <M extends Requests, const
|
|
|
126
129
|
return rpcs
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
|
|
130
|
-
M extends Requests,
|
|
131
|
-
const ModuleName extends string
|
|
132
|
-
>(
|
|
133
|
-
resource: M & { meta: { moduleName: ModuleName } }
|
|
134
|
-
) => makeRpcGroupFromRequestsAndModuleName(resource, resource.meta.moduleName)
|
|
135
|
-
|
|
136
|
-
const makeRpcTag = <M extends Requests>(resource: M) => {
|
|
132
|
+
const makeRpcTag = <M extends RequestsAny>(resource: M) => {
|
|
137
133
|
const meta = getMeta(resource)
|
|
138
134
|
const rpcs = makeRpcGroupFromRequestsAndModuleName(resource, meta.moduleName)
|
|
139
135
|
|
|
140
136
|
// Use Object.assign instead of class extension to avoid TS2509 with complex generic return types.
|
|
141
137
|
// The first type arg is `any` because this is a dynamically created tag — its identity is the string key.
|
|
142
|
-
const TheClient =
|
|
138
|
+
const TheClient = Context.Opaque<
|
|
143
139
|
any,
|
|
144
140
|
RpcClient.RpcClient<RpcGroup.Rpcs<typeof rpcs>>
|
|
145
141
|
>()(`RpcClient.${meta.moduleName}`)
|
|
@@ -153,99 +149,100 @@ const makeRpcTag = <M extends Requests>(resource: M) => {
|
|
|
153
149
|
|
|
154
150
|
const makeApiClientFactory = Effect
|
|
155
151
|
.gen(function*() {
|
|
156
|
-
const ctx = yield* Effect.
|
|
157
|
-
const makeClientFor =
|
|
152
|
+
const ctx = yield* Effect.context<RpcSerialization.RpcSerialization | HttpClient.HttpClient>()
|
|
153
|
+
const makeClientFor = Effect.fnUntraced(function*<M extends RequestsAny>(
|
|
158
154
|
resource: M,
|
|
159
155
|
requestLevelLayers = Layer.empty,
|
|
160
156
|
options?: ClientForOptions
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
.
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
)
|
|
157
|
+
) {
|
|
158
|
+
const TheClient = makeRpcTag(resource)
|
|
159
|
+
|
|
160
|
+
const meta = getMeta(resource)
|
|
161
|
+
|
|
162
|
+
// TODO: somehow we need a protocol per REQUEST kind of it seems ...
|
|
163
|
+
// otherwise it locks up on the client, navigation remains empty...
|
|
164
|
+
const clientLayer = TheClient.layer.pipe(
|
|
165
|
+
// add ApiClientFactory for nested schemas
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
167
|
+
Layer.provide(Layer.succeed(ApiClientFactory, makeClientForCached as any)),
|
|
168
|
+
Layer.provide(
|
|
169
|
+
RpcClient
|
|
170
|
+
.layerProtocolHttp({
|
|
171
|
+
url: "" // why not here set meta.moduleName as root?
|
|
172
|
+
})
|
|
173
|
+
.pipe(
|
|
174
|
+
Layer.provideMerge(Layer.succeedContext(ctx))
|
|
175
|
+
)
|
|
182
176
|
)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
177
|
+
)
|
|
178
|
+
const mr = ManagedRuntime.make(clientLayer)
|
|
179
|
+
|
|
180
|
+
const filtered = getFiltered(resource)
|
|
181
|
+
return {
|
|
182
|
+
mr,
|
|
183
|
+
client: typedKeysOf(filtered)
|
|
184
|
+
.reduce((prev, cur) => {
|
|
185
|
+
const h = filtered[cur]!
|
|
186
|
+
|
|
187
|
+
const Request = h
|
|
188
|
+
|
|
189
|
+
const id = `${meta.moduleName}.${cur as string}`
|
|
190
|
+
.replaceAll(".js", "")
|
|
191
|
+
|
|
192
|
+
const requestMeta = {
|
|
193
|
+
Request,
|
|
194
|
+
id,
|
|
195
|
+
options
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const requestNameLayer = Layer.succeed(RequestName, {
|
|
199
|
+
requestName: cur as string,
|
|
200
|
+
moduleName: meta.moduleName
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
const layers = requestLevelLayers.pipe(Layer.provideMerge(requestNameLayer))
|
|
204
|
+
|
|
205
|
+
const fields = Struct.omit(Request.fields, ["_tag"] as const)
|
|
206
|
+
const requestAttr = `${meta.moduleName}.${h._tag}`
|
|
207
|
+
// @ts-expect-error doc
|
|
208
|
+
prev[cur] = Object.keys(fields).length === 0
|
|
209
|
+
? {
|
|
210
|
+
handler: mr.contextEffect.pipe(
|
|
211
|
+
Effect.flatMap((svcs) =>
|
|
212
|
+
TheClient
|
|
213
|
+
.use((client) =>
|
|
214
|
+
(client as any)[requestAttr]!(Request.make({})) as Effect.Effect<any, any, never>
|
|
215
|
+
)
|
|
216
|
+
.pipe(
|
|
217
|
+
Effect.provide(layers),
|
|
218
|
+
Effect.provide(svcs)
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
),
|
|
222
|
+
...requestMeta
|
|
201
223
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
moduleName: meta.moduleName
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
const layers = requestLevelLayers.pipe(Layer.provideMerge(requestNameLayer))
|
|
209
|
-
|
|
210
|
-
const fields = Struct.omit(Request.fields, ["_tag"] as const)
|
|
211
|
-
const requestAttr = `${meta.moduleName}.${h._tag}`
|
|
212
|
-
// @ts-expect-error doc
|
|
213
|
-
prev[cur] = Object.keys(fields).length === 0
|
|
214
|
-
? {
|
|
215
|
-
handler: mr.servicesEffect.pipe(
|
|
224
|
+
: {
|
|
225
|
+
handler: (req: any) =>
|
|
226
|
+
mr.contextEffect.pipe(
|
|
216
227
|
Effect.flatMap((svcs) =>
|
|
217
228
|
TheClient
|
|
218
|
-
.use((client) =>
|
|
229
|
+
.use((client) =>
|
|
230
|
+
(client as any)[requestAttr]!(Request.make(req)) as Effect.Effect<any, any, never>
|
|
231
|
+
)
|
|
219
232
|
.pipe(
|
|
220
233
|
Effect.provide(layers),
|
|
221
234
|
Effect.provide(svcs)
|
|
222
235
|
)
|
|
223
236
|
)
|
|
224
237
|
),
|
|
225
|
-
...requestMeta
|
|
226
|
-
}
|
|
227
|
-
: {
|
|
228
|
-
handler: (req: any) =>
|
|
229
|
-
mr.servicesEffect.pipe(
|
|
230
|
-
Effect.flatMap((svcs) =>
|
|
231
|
-
TheClient
|
|
232
|
-
.use((client) =>
|
|
233
|
-
(client as any)[requestAttr]!(new Request(req)) as Effect.Effect<any, any, never>
|
|
234
|
-
)
|
|
235
|
-
.pipe(
|
|
236
|
-
Effect.provide(layers),
|
|
237
|
-
Effect.provide(svcs)
|
|
238
|
-
)
|
|
239
|
-
)
|
|
240
|
-
),
|
|
241
238
|
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
...requestMeta
|
|
240
|
+
}
|
|
244
241
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
242
|
+
return prev
|
|
243
|
+
}, {} as Client<M, ExtractModuleName<M>>)
|
|
244
|
+
}
|
|
245
|
+
})
|
|
249
246
|
|
|
250
247
|
const register: ManagedRuntime.ManagedRuntime<any, any>[] = []
|
|
251
248
|
yield* Effect.addFinalizer(() => Effect.forEach(register, (mr) => mr.disposeEffect))
|
|
@@ -259,19 +256,16 @@ const makeApiClientFactory = Effect
|
|
|
259
256
|
cacheL.set(requestLevelLayers, cache)
|
|
260
257
|
}
|
|
261
258
|
|
|
262
|
-
return
|
|
263
|
-
models
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
register.push(m.mr)
|
|
273
|
-
return m.client
|
|
274
|
-
})
|
|
259
|
+
return Effect.fnUntraced(function*<M extends RequestsAny>(models: M) {
|
|
260
|
+
const found = cache.get(models) as Client<M, ExtractModuleName<M>> | undefined
|
|
261
|
+
if (found) {
|
|
262
|
+
return found
|
|
263
|
+
}
|
|
264
|
+
const m = yield* makeClientFor(models, requestLevelLayers, options)
|
|
265
|
+
cache.set(models, m.client)
|
|
266
|
+
register.push(m.mr)
|
|
267
|
+
return m.client
|
|
268
|
+
})
|
|
275
269
|
}
|
|
276
270
|
|
|
277
271
|
return makeClientForCached
|
|
@@ -281,7 +275,7 @@ const makeApiClientFactory = Effect
|
|
|
281
275
|
* Used to create clients for resource modules.
|
|
282
276
|
*/
|
|
283
277
|
export class ApiClientFactory
|
|
284
|
-
extends
|
|
278
|
+
extends Context.Opaque<ApiClientFactory, Effect.Success<typeof makeApiClientFactory>>()("ApiClientFactory")
|
|
285
279
|
{
|
|
286
280
|
static readonly layer = (config: ApiConfig) =>
|
|
287
281
|
ApiClientFactory.toLayer(makeApiClientFactory).pipe(Layer.provide(RpcSerializationLayer(config)))
|
|
@@ -294,7 +288,7 @@ export class ApiClientFactory
|
|
|
294
288
|
|
|
295
289
|
static readonly makeFor =
|
|
296
290
|
(requestLevelLayers: Layer.Layer<never, never, never>, options?: ClientForOptions) =>
|
|
297
|
-
<M extends
|
|
291
|
+
<M extends RequestsAny>(
|
|
298
292
|
resource: M
|
|
299
293
|
) =>
|
|
300
294
|
ApiClientFactory.use((apiClientFactory) => {
|
package/src/client/clientFor.ts
CHANGED
|
@@ -48,9 +48,14 @@ export function makePathWithBody(
|
|
|
48
48
|
return path.build(pars, { ignoreSearch: true, ignoreConstraints: true })
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export type Requests
|
|
51
|
+
export type Requests = RequestsAny
|
|
52
52
|
export type RequestsAny = Record<string, any>
|
|
53
53
|
|
|
54
|
+
export type ExtractModuleName<M extends RequestsAny> =
|
|
55
|
+
{ [K in keyof M]: M[K] extends { moduleName: infer N extends string } ? N : never }[keyof M] extends
|
|
56
|
+
infer R extends string ? R
|
|
57
|
+
: string
|
|
58
|
+
|
|
54
59
|
export type Client<M extends RequestsAny, ModuleName extends string> = RequestHandlers<
|
|
55
60
|
never,
|
|
56
61
|
never,
|
package/src/client/errors.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @effect-diagnostics overriddenSchemaConstructor:skip-file */
|
|
2
|
-
import {
|
|
2
|
+
import { TaggedErrorClass } from "effect-app/Schema"
|
|
3
3
|
import * as Cause from "effect/Cause"
|
|
4
4
|
import * as S from "../Schema.js"
|
|
5
5
|
|
|
@@ -21,7 +21,7 @@ export const tryToJson = (error: { toJSON(): unknown; toString(): string }) => {
|
|
|
21
21
|
|
|
22
22
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
23
23
|
// @ts-expect-error type not used
|
|
24
|
-
export class NotFoundError<ItemType = string> extends
|
|
24
|
+
export class NotFoundError<ItemType = string> extends TaggedErrorClass<NotFoundError<ItemType>>()("NotFoundError", {
|
|
25
25
|
type: S.String,
|
|
26
26
|
id: S.Unknown
|
|
27
27
|
}) {
|
|
@@ -29,76 +29,97 @@ export class NotFoundError<ItemType = string> extends TaggedError<NotFoundError<
|
|
|
29
29
|
props: { type: string; id: unknown; cause?: unknown },
|
|
30
30
|
disableValidation?: boolean
|
|
31
31
|
) {
|
|
32
|
-
super(props
|
|
32
|
+
super(props, disableValidation as any)
|
|
33
33
|
}
|
|
34
34
|
override get message() {
|
|
35
35
|
return `Didn't find ${(this as any).type}#${JSON.stringify((this as any).id)}`
|
|
36
36
|
}
|
|
37
|
+
override toString() {
|
|
38
|
+
return `NotFoundError: ${this.message}`
|
|
39
|
+
}
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
const messageFallback = (messageOrObject?: string | { message: string }) =>
|
|
40
43
|
typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject ?? "" }
|
|
41
44
|
|
|
42
|
-
export class InvalidStateError extends
|
|
45
|
+
export class InvalidStateError extends TaggedErrorClass<InvalidStateError>()("InvalidStateError", {
|
|
43
46
|
message: S.String
|
|
44
47
|
}) {
|
|
45
48
|
constructor(messageOrObject: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
|
|
46
49
|
super(
|
|
47
|
-
typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject }
|
|
50
|
+
typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject },
|
|
48
51
|
disableValidation as any
|
|
49
52
|
)
|
|
50
53
|
}
|
|
54
|
+
override toString() {
|
|
55
|
+
return `InvalidStateError: ${this.message}`
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
export class ServiceUnavailableError extends
|
|
59
|
+
export class ServiceUnavailableError extends TaggedErrorClass<ServiceUnavailableError>()("ServiceUnavailableError", {
|
|
54
60
|
message: S.String
|
|
55
61
|
}) {
|
|
56
62
|
constructor(messageOrObject: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
|
|
57
63
|
super(
|
|
58
|
-
typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject }
|
|
64
|
+
typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject },
|
|
59
65
|
disableValidation as any
|
|
60
66
|
)
|
|
61
67
|
}
|
|
68
|
+
override toString() {
|
|
69
|
+
return `ServiceUnavailableError: ${this.message}`
|
|
70
|
+
}
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
export class ValidationError extends
|
|
73
|
+
export class ValidationError extends TaggedErrorClass<ValidationError>()("ValidationError", {
|
|
65
74
|
errors: S.Array(S.Unknown)
|
|
66
75
|
}) {
|
|
67
76
|
constructor(
|
|
68
77
|
props: { errors: ReadonlyArray<unknown>; cause?: unknown },
|
|
69
78
|
disableValidation?: boolean
|
|
70
79
|
) {
|
|
71
|
-
super(props
|
|
80
|
+
super(props, disableValidation as any)
|
|
72
81
|
}
|
|
73
82
|
override get message() {
|
|
74
83
|
return `Validation failed: ${(this as any).errors.map((e: any) => JSON.stringify(e, undefined, 2)).join(",\n")}`
|
|
75
84
|
}
|
|
85
|
+
override toString() {
|
|
86
|
+
return `ValidationError: ${this.message}`
|
|
87
|
+
}
|
|
76
88
|
}
|
|
77
89
|
|
|
78
|
-
export class NotLoggedInError extends
|
|
90
|
+
export class NotLoggedInError extends TaggedErrorClass<NotLoggedInError>()("NotLoggedInError", {
|
|
79
91
|
message: S.String
|
|
80
92
|
}) {
|
|
81
93
|
constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
|
|
82
|
-
super(messageFallback(messageOrObject)
|
|
94
|
+
super(messageFallback(messageOrObject), disableValidation as any)
|
|
95
|
+
}
|
|
96
|
+
override toString() {
|
|
97
|
+
return `NotLoggedInError: ${this.message}`
|
|
83
98
|
}
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
/**
|
|
87
102
|
* The user carries a valid Userprofile, but there is a problem with the login none the less.
|
|
88
103
|
*/
|
|
89
|
-
export class LoginError extends
|
|
104
|
+
export class LoginError extends TaggedErrorClass<LoginError>()("NotLoggedInError", {
|
|
90
105
|
message: S.String
|
|
91
106
|
}) {
|
|
92
107
|
constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
|
|
93
|
-
super(messageFallback(messageOrObject)
|
|
108
|
+
super(messageFallback(messageOrObject), disableValidation as any)
|
|
109
|
+
}
|
|
110
|
+
override toString() {
|
|
111
|
+
return `LoginError: ${this.message}`
|
|
94
112
|
}
|
|
95
113
|
}
|
|
96
114
|
|
|
97
|
-
export class UnauthorizedError extends
|
|
115
|
+
export class UnauthorizedError extends TaggedErrorClass<UnauthorizedError>()("UnauthorizedError", {
|
|
98
116
|
message: S.String
|
|
99
117
|
}) {
|
|
100
118
|
constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
|
|
101
|
-
super(messageFallback(messageOrObject)
|
|
119
|
+
super(messageFallback(messageOrObject), disableValidation as any)
|
|
120
|
+
}
|
|
121
|
+
override toString() {
|
|
122
|
+
return `UnauthorizedError: ${this.message}`
|
|
102
123
|
}
|
|
103
124
|
}
|
|
104
125
|
|
|
@@ -110,7 +131,7 @@ type OptimisticConcurrencyDetails = {
|
|
|
110
131
|
readonly found?: string | undefined
|
|
111
132
|
}
|
|
112
133
|
|
|
113
|
-
export class OptimisticConcurrencyException extends
|
|
134
|
+
export class OptimisticConcurrencyException extends TaggedErrorClass<OptimisticConcurrencyException>()(
|
|
114
135
|
"OptimisticConcurrencyException",
|
|
115
136
|
{ message: S.String }
|
|
116
137
|
) {
|
|
@@ -123,13 +144,16 @@ export class OptimisticConcurrencyException extends TaggedError<OptimisticConcur
|
|
|
123
144
|
disableValidation?: boolean
|
|
124
145
|
) {
|
|
125
146
|
super(
|
|
126
|
-
"message" in args ? args : { message: `Existing ${args.type} ${args.id} record changed` }
|
|
147
|
+
"message" in args ? args : { message: `Existing ${args.type} ${args.id} record changed` },
|
|
127
148
|
disableValidation as any
|
|
128
149
|
)
|
|
129
150
|
if (!("message" in args)) {
|
|
130
151
|
this.details = args
|
|
131
152
|
}
|
|
132
153
|
}
|
|
154
|
+
override toString() {
|
|
155
|
+
return `OptimisticConcurrencyException: ${this.message}`
|
|
156
|
+
}
|
|
133
157
|
}
|
|
134
158
|
|
|
135
159
|
const MutationOnlyErrors = [
|
|
@@ -183,6 +207,7 @@ export class CauseException<E> extends Error {
|
|
|
183
207
|
Error.stackTraceLimit = 0
|
|
184
208
|
super()
|
|
185
209
|
Error.stackTraceLimit = limit
|
|
210
|
+
this.cause = Cause.squash(originalCause)
|
|
186
211
|
// v4: makeFiberFailure removed — use Cause.prettyErrors instead
|
|
187
212
|
const errors = Cause.prettyErrors(originalCause)
|
|
188
213
|
const first = errors[0]
|