@effect-app/infra 0.133.0-next.8 → 0.133.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +494 -0
  2. package/_cjs/RequestContext.cjs +8 -9
  3. package/_cjs/RequestContext.cjs.map +1 -1
  4. package/_cjs/_ext/Array.cjs +4 -3
  5. package/_cjs/_ext/Array.cjs.map +1 -1
  6. package/_cjs/_global.ext.cjs +0 -25
  7. package/_cjs/_global.ext.cjs.map +1 -1
  8. package/_cjs/api/codec.cjs +1 -1
  9. package/_cjs/api/codec.cjs.map +1 -1
  10. package/_cjs/api/http.cjs +42 -0
  11. package/_cjs/api/http.cjs.map +1 -0
  12. package/_cjs/api/routing/base.cjs +169 -0
  13. package/_cjs/api/routing/base.cjs.map +1 -0
  14. package/_cjs/api/routing/defaultErrorHandler.cjs +50 -0
  15. package/_cjs/api/routing/defaultErrorHandler.cjs.map +1 -0
  16. package/_cjs/api/routing/makeRequestHandler.cjs +134 -0
  17. package/_cjs/api/routing/makeRequestHandler.cjs.map +1 -0
  18. package/_cjs/api/routing/match.cjs +45 -0
  19. package/_cjs/api/routing/match.cjs.map +1 -0
  20. package/_cjs/api/routing.cjs +50 -0
  21. package/_cjs/api/routing.cjs.map +1 -0
  22. package/_cjs/api/setupRequest.cjs +31 -30
  23. package/_cjs/api/setupRequest.cjs.map +1 -1
  24. package/_cjs/errorReporter.cjs +4 -2
  25. package/_cjs/errorReporter.cjs.map +1 -1
  26. package/_cjs/errors.cjs +18 -66
  27. package/_cjs/errors.cjs.map +1 -1
  28. package/_cjs/services/Operations/live.cjs +11 -12
  29. package/_cjs/services/Operations/live.cjs.map +1 -1
  30. package/_cjs/services/QueueMaker/memQueue.cjs +9 -10
  31. package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
  32. package/_cjs/services/QueueMaker/sbqueue.cjs +4 -4
  33. package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
  34. package/_cjs/services/Repository.cjs +3 -3
  35. package/_cjs/services/Repository.cjs.map +1 -1
  36. package/_cjs/services/RepositoryBase.cjs +14 -6
  37. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  38. package/_cjs/services/RequestContextContainer.cjs +3 -3
  39. package/_cjs/services/RequestContextContainer.cjs.map +1 -1
  40. package/_cjs/services/Store/Redis.cjs.map +1 -1
  41. package/_cjs/test.arbs.cjs +24 -1
  42. package/_cjs/test.arbs.cjs.map +1 -1
  43. package/_src/RequestContext.ts +9 -12
  44. package/_src/_ext/Array.ts +4 -4
  45. package/_src/_global.ext.ts +0 -23
  46. package/_src/api/codec.ts +1 -1
  47. package/_src/api/http.ts +26 -0
  48. package/_src/api/routing/base.ts +476 -0
  49. package/_src/api/routing/defaultErrorHandler.ts +83 -0
  50. package/_src/api/routing/makeRequestHandler.ts +278 -0
  51. package/_src/api/routing/match.ts +119 -0
  52. package/_src/api/routing.ts +11 -0
  53. package/_src/api/setupRequest.ts +39 -34
  54. package/_src/errorReporter.ts +4 -2
  55. package/_src/errors.ts +1 -58
  56. package/_src/services/QueueMaker/memQueue.ts +3 -3
  57. package/_src/services/QueueMaker/sbqueue.ts +3 -3
  58. package/_src/services/Repository.ts +40 -43
  59. package/_src/services/RepositoryBase.ts +26 -20
  60. package/_src/services/Store/Redis.ts +1 -1
  61. package/_src/services/Store/service.ts +4 -4
  62. package/_src/test.arbs.ts +17 -14
  63. package/dist/RequestContext.d.ts +72 -24
  64. package/dist/RequestContext.d.ts.map +1 -1
  65. package/dist/RequestContext.js +10 -11
  66. package/dist/_ext/Array.d.ts +2 -2
  67. package/dist/_ext/Array.d.ts.map +1 -1
  68. package/dist/_ext/Array.js +5 -4
  69. package/dist/_global.ext.d.ts +0 -22
  70. package/dist/_global.ext.d.ts.map +1 -1
  71. package/dist/_global.ext.js +1 -18
  72. package/dist/api/codec.d.ts +1 -1
  73. package/dist/api/codec.d.ts.map +1 -1
  74. package/dist/api/codec.js +2 -2
  75. package/dist/api/http.d.ts +16 -0
  76. package/dist/api/http.d.ts.map +1 -0
  77. package/dist/api/http.js +12 -0
  78. package/dist/api/routing/base.d.ts +117 -0
  79. package/dist/api/routing/base.d.ts.map +1 -0
  80. package/dist/api/routing/base.js +137 -0
  81. package/dist/api/routing/defaultErrorHandler.d.ts +16 -0
  82. package/dist/api/routing/defaultErrorHandler.d.ts.map +1 -0
  83. package/dist/api/routing/defaultErrorHandler.js +42 -0
  84. package/dist/api/routing/makeRequestHandler.d.ts +20 -0
  85. package/dist/api/routing/makeRequestHandler.d.ts.map +1 -0
  86. package/dist/api/routing/makeRequestHandler.js +121 -0
  87. package/dist/api/routing/match.d.ts +12 -0
  88. package/dist/api/routing/match.d.ts.map +1 -0
  89. package/dist/api/routing/match.js +31 -0
  90. package/dist/api/routing.d.ts +5 -0
  91. package/dist/api/routing.d.ts.map +1 -0
  92. package/dist/api/routing.js +8 -0
  93. package/dist/api/setupRequest.d.ts +4 -4
  94. package/dist/api/setupRequest.d.ts.map +1 -1
  95. package/dist/api/setupRequest.js +31 -37
  96. package/dist/errorReporter.d.ts.map +1 -1
  97. package/dist/errorReporter.js +5 -3
  98. package/dist/errors.d.ts +1 -81
  99. package/dist/errors.d.ts.map +1 -1
  100. package/dist/errors.js +4 -46
  101. package/dist/services/Operations/live.js +16 -17
  102. package/dist/services/QueueMaker/memQueue.d.ts +3 -3
  103. package/dist/services/QueueMaker/memQueue.d.ts.map +1 -1
  104. package/dist/services/QueueMaker/memQueue.js +9 -10
  105. package/dist/services/QueueMaker/sbqueue.d.ts +3 -3
  106. package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
  107. package/dist/services/QueueMaker/sbqueue.js +4 -4
  108. package/dist/services/QueueMaker/service.d.ts +1 -1
  109. package/dist/services/Repository.d.ts +37 -38
  110. package/dist/services/Repository.d.ts.map +1 -1
  111. package/dist/services/Repository.js +4 -4
  112. package/dist/services/RepositoryBase.d.ts +15 -15
  113. package/dist/services/RepositoryBase.d.ts.map +1 -1
  114. package/dist/services/RepositoryBase.js +12 -7
  115. package/dist/services/RequestContextContainer.d.ts +1 -1
  116. package/dist/services/RequestContextContainer.js +3 -3
  117. package/dist/services/Store/Redis.js +1 -1
  118. package/dist/services/Store/service.d.ts +4 -4
  119. package/dist/services/Store/service.d.ts.map +1 -1
  120. package/dist/services/simpledb/redisdb.d.ts +5 -1
  121. package/dist/services/simpledb/redisdb.d.ts.map +1 -1
  122. package/dist/services/simpledb/shared.d.ts +5 -1
  123. package/dist/services/simpledb/shared.d.ts.map +1 -1
  124. package/dist/test.arbs.d.ts +12 -1
  125. package/dist/test.arbs.d.ts.map +1 -1
  126. package/dist/test.arbs.js +18 -2
  127. package/package.json +73 -11
@@ -0,0 +1,278 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/ban-types */
3
+ import type { EnforceNonEmptyRecord } from "@effect-app/core/utils"
4
+ import { pretty } from "@effect-app/core/utils"
5
+ import { snipString } from "@effect-app/infra/api/util"
6
+ import { reportError } from "@effect-app/infra/errorReporter"
7
+ import type { ValidationError } from "@effect-app/infra/errors"
8
+ import type { RequestContextContainer } from "@effect-app/infra/services/RequestContextContainer"
9
+ import type { ContextMapContainer } from "@effect-app/infra/services/Store/ContextMapContainer"
10
+ import type { REST, StructFields } from "@effect-app/schema"
11
+ import { AST } from "@effect-app/schema"
12
+ import type { HttpRequestError } from "../http.js"
13
+ import { HttpBody, HttpRouteContext, HttpServerRequest, HttpServerResponse } from "../http.js"
14
+ import { makeRequestParsers, parseRequestParams } from "./base.js"
15
+ import type { RequestHandler, RequestHandlerBase } from "./base.js"
16
+
17
+ export const RequestSettings = FiberRef.unsafeMake({
18
+ verbose: false
19
+ })
20
+
21
+ export type Middleware<
22
+ R,
23
+ M,
24
+ PathA extends StructFields,
25
+ CookieA extends StructFields,
26
+ QueryA extends StructFields,
27
+ BodyA extends StructFields,
28
+ HeaderA extends StructFields,
29
+ ReqA extends PathA & QueryA & BodyA,
30
+ ResA extends StructFields,
31
+ ResE,
32
+ MiddlewareE,
33
+ PPath extends `/${string}`,
34
+ R2,
35
+ PR,
36
+ CTX,
37
+ Context,
38
+ Config
39
+ > = (
40
+ handler: RequestHandler<R, M, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE, PPath, CTX, Context, Config>
41
+ ) => {
42
+ handler: RequestHandler<
43
+ Exclude<R2, HttpServerRequest> | PR | RequestContextContainer | ContextMapContainer,
44
+ M,
45
+ PathA,
46
+ CookieA,
47
+ QueryA,
48
+ BodyA,
49
+ HeaderA,
50
+ ReqA,
51
+ ResA,
52
+ ResE,
53
+ PPath,
54
+ CTX,
55
+ Context,
56
+ Config
57
+ >
58
+ makeRequestLayer: Layer<R2, MiddlewareE, PR>
59
+ }
60
+
61
+ export function makeRequestHandler<
62
+ R,
63
+ M,
64
+ PathA extends StructFields,
65
+ CookieA extends StructFields,
66
+ QueryA extends StructFields,
67
+ BodyA extends StructFields,
68
+ HeaderA extends StructFields,
69
+ ReqA extends PathA & QueryA & BodyA,
70
+ ResA extends StructFields,
71
+ ResE,
72
+ MiddlewareE,
73
+ R2,
74
+ PR,
75
+ RErr,
76
+ PPath extends `/${string}`,
77
+ Config
78
+ >(
79
+ handler: RequestHandlerBase<
80
+ R,
81
+ M,
82
+ PathA,
83
+ CookieA,
84
+ QueryA,
85
+ BodyA,
86
+ HeaderA,
87
+ ReqA,
88
+ ResA,
89
+ ResE,
90
+ PPath,
91
+ Config
92
+ >,
93
+ errorHandler: <R>(
94
+ req: HttpServerRequest,
95
+ res: HttpServerResponse,
96
+ r2: Effect<R, ValidationError | ResE | MiddlewareE, HttpServerResponse>
97
+ ) => Effect<RErr | R, never, HttpServerResponse>,
98
+ middlewareLayer?: Layer<R2, MiddlewareE, PR>
99
+ ): Effect<
100
+ | HttpRouteContext
101
+ | HttpServerRequest
102
+ | RequestContextContainer
103
+ | ContextMapContainer
104
+ | RErr
105
+ | Exclude<Exclude<R, EnforceNonEmptyRecord<M>>, PR>
106
+ | R2,
107
+ HttpRequestError,
108
+ HttpServerResponse
109
+ > {
110
+ const { Request, Response, h: handle } = handler
111
+
112
+ const response: REST.ReqRes<any, any> = Response ? Response : Void
113
+ const resp = response as typeof response & { struct?: Schema<any, any> }
114
+ // TODO: consider if the alternative of using the struct schema is perhaps just better.
115
+ const encoder = "struct" in resp && resp.struct
116
+ ? resp.struct.encodeSync
117
+ // ? (i: any) => {
118
+ // if (i instanceof (response as any)) return response.encodeSync(i)
119
+ // else return response.encodeSync(new (response as any)(i))
120
+ // }
121
+ : resp.encodeSync
122
+ // const encodeResponse = adaptResponse
123
+ // ? (req: ReqA) => Encoder.for(adaptResponse(req))
124
+ // : () => encoder
125
+
126
+ const requestParsers = makeRequestParsers(Request)
127
+ const parseRequest = parseRequestParams(requestParsers)
128
+
129
+ const getParams = Effect
130
+ .all({
131
+ rcx: HttpRouteContext,
132
+ req: HttpServerRequest.flatMap((req) => req.json.map((body) => ({ body, headers: req.headers })))
133
+ })
134
+ .map((
135
+ { rcx, req }
136
+ ) => ({
137
+ params: rcx.params,
138
+ query: rcx.searchParams,
139
+ body: req.body,
140
+ headers: req.headers,
141
+ cookies: {} // req.cookies
142
+ }))
143
+
144
+ return Effect
145
+ .gen(function*($) {
146
+ const req = yield* $(HttpServerRequest)
147
+ const res = HttpServerResponse
148
+ .empty()
149
+ .pipe((_) => req.method === "GET" ? _.setHeader("Cache-Control", "no-store") : _)
150
+
151
+ const pars = yield* $(getParams)
152
+
153
+ const settings = yield* $(RequestSettings.get)
154
+
155
+ const eff =
156
+ // TODO: we don;t have access to user id here cause context is not yet created
157
+ Effect
158
+ .logInfo("Incoming request")
159
+ .annotateLogs({
160
+ method: req.method,
161
+ path: req.originalUrl,
162
+ ...settings.verbose
163
+ ? {
164
+ reqPath: pars.params.$$.pretty,
165
+ reqQuery: pars.query.$$.pretty,
166
+ reqBody: pretty(pars.body),
167
+ reqCookies: pretty(pars.cookies),
168
+ reqHeaders: pretty(pars.headers)
169
+ }
170
+ : undefined
171
+ })
172
+ .andThen(
173
+ Effect.suspend(() => {
174
+ const handleRequest = parseRequest(pars)
175
+ .map(({ body, path, query }) => {
176
+ const hn = {
177
+ ...body.value as any,
178
+ ...query.value as any,
179
+ ...path.value as any
180
+ } as unknown as ReqA
181
+ return hn
182
+ })
183
+ .flatMap((parsedReq) =>
184
+ handle(parsedReq as any)
185
+ .provideService(handler.Request.Tag, parsedReq as any)
186
+ .map(encoder)
187
+ .map((r) =>
188
+ res
189
+ .setBody(HttpBody.unsafeJson(r))
190
+ .setStatus(r === undefined ? 204 : 200)
191
+ )
192
+ ) as Effect<
193
+ Exclude<R, EnforceNonEmptyRecord<M>>,
194
+ ValidationError | ResE,
195
+ HttpServerResponse
196
+ >
197
+
198
+ // Commands should not be interruptable.
199
+ const r = req.method !== "GET" ? handleRequest.uninterruptible : handleRequest // .instrument("Performance.RequestResponse")
200
+ const r2 = middlewareLayer
201
+ ? r.provide(middlewareLayer)
202
+ // PR is not relevant here
203
+ : (r as Effect<
204
+ Exclude<Exclude<R, EnforceNonEmptyRecord<M>>, PR>,
205
+ ResE | MiddlewareE | ValidationError,
206
+ HttpServerResponse
207
+ >)
208
+ return errorHandler(
209
+ req,
210
+ res,
211
+ r2
212
+ )
213
+ })
214
+ )
215
+ .catchAllCause((cause) =>
216
+ Effect
217
+ .sync(() => res.setStatus(500))
218
+ .tap((res) =>
219
+ Effect
220
+ .all([
221
+ reportError("request")(cause, {
222
+ path: req.originalUrl,
223
+ method: req.method
224
+ }),
225
+ Effect.suspend(() => {
226
+ const headers = res.headers
227
+ return Effect
228
+ .logError("Finished request", cause)
229
+ .annotateLogs({
230
+ method: req.method,
231
+ path: req.originalUrl,
232
+ statusCode: res.status.toString(),
233
+
234
+ reqPath: pars.params.$$.pretty,
235
+ reqQuery: pars.query.$$.pretty,
236
+ reqBody: pretty(pars.body),
237
+ reqCookies: pretty(pars.cookies),
238
+ reqHeaders: pretty(pars.headers),
239
+
240
+ resHeaders: Object
241
+ .entries(headers)
242
+ .reduce((prev, [key, value]) => {
243
+ prev[key] = value && typeof value === "string" ? snipString(value) : value
244
+ return prev
245
+ }, {} as Record<string, any>)
246
+ .$$
247
+ .pretty
248
+ })
249
+ })
250
+ ], { concurrency: "inherit" })
251
+ )
252
+ .tapErrorCause((cause) => Effect(console.error("Error occurred while reporting error", cause)))
253
+ )
254
+ .tap(
255
+ Effect
256
+ .logInfo("Finished request")
257
+ .annotateLogs({
258
+ method: req.method,
259
+ path: req.originalUrl,
260
+ statusCode: res.status.toString(),
261
+ ...settings.verbose
262
+ ? {
263
+ resHeaders: pretty(res.headers)
264
+ }
265
+ : undefined
266
+ })
267
+ )
268
+
269
+ return yield* $(eff)
270
+ })
271
+ .updateRequestContext((_) =>
272
+ _.$$.copy({
273
+ name: NonEmptyString255(
274
+ AST.getTitleAnnotation(Request.ast).value ?? "TODO"
275
+ )
276
+ })
277
+ )
278
+ }
@@ -0,0 +1,119 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/ban-types */
3
+ import { type RouteDescriptorAny } from "@effect-app/infra/api/express/schema/routing"
4
+ import type { ValidationError } from "@effect-app/infra/errors"
5
+ import type { StructFields } from "@effect-app/schema"
6
+ import { HttpRouter, type HttpServerRequest, type HttpServerResponse } from "../http.js"
7
+ import type { RequestHandler } from "./base.js"
8
+ import { makeRequestHandler } from "./makeRequestHandler.js"
9
+ import type { Middleware } from "./makeRequestHandler.js"
10
+
11
+ export const RouteDescriptors = Tag<Ref<RouteDescriptorAny[]>>()
12
+
13
+ export function match<
14
+ R,
15
+ M,
16
+ PathA extends StructFields,
17
+ CookieA extends StructFields,
18
+ QueryA extends StructFields,
19
+ BodyA extends StructFields,
20
+ HeaderA extends StructFields,
21
+ ReqA extends PathA & QueryA & BodyA,
22
+ ResA extends StructFields,
23
+ ResE,
24
+ MiddlewareE,
25
+ PPath extends `/${string}`,
26
+ R2,
27
+ PR,
28
+ RErr,
29
+ CTX,
30
+ Context,
31
+ Config
32
+ >(
33
+ requestHandler: RequestHandler<
34
+ R,
35
+ M,
36
+ PathA,
37
+ CookieA,
38
+ QueryA,
39
+ BodyA,
40
+ HeaderA,
41
+ ReqA,
42
+ ResA,
43
+ ResE,
44
+ PPath,
45
+ CTX,
46
+ Context,
47
+ Config
48
+ >,
49
+ errorHandler: <R>(
50
+ req: HttpServerRequest,
51
+ res: HttpServerResponse,
52
+ r2: Effect<R, ValidationError | MiddlewareE | ResE, HttpServerResponse>
53
+ ) => Effect<RErr | R, never, HttpServerResponse>,
54
+ middleware?: Middleware<
55
+ R,
56
+ M,
57
+ PathA,
58
+ CookieA,
59
+ QueryA,
60
+ BodyA,
61
+ HeaderA,
62
+ ReqA,
63
+ ResA,
64
+ ResE,
65
+ MiddlewareE,
66
+ PPath,
67
+ R2,
68
+ PR,
69
+ CTX,
70
+ Context,
71
+ Config
72
+ >
73
+ ) {
74
+ let middlewareLayer: Layer<R2, MiddlewareE, PR> | undefined = undefined
75
+ if (middleware) {
76
+ const { handler, makeRequestLayer } = middleware(requestHandler)
77
+ requestHandler = handler as any // todo
78
+ middlewareLayer = makeRequestLayer
79
+ }
80
+ return Effect.gen(function*() {
81
+ // const rdesc = yield* $(RouteDescriptors.flatMap((_) => _.get))
82
+
83
+ const handler = makeRequestHandler<
84
+ R,
85
+ M,
86
+ PathA,
87
+ CookieA,
88
+ QueryA,
89
+ BodyA,
90
+ HeaderA,
91
+ ReqA,
92
+ ResA,
93
+ ResE,
94
+ MiddlewareE,
95
+ R2,
96
+ PR,
97
+ RErr,
98
+ PPath,
99
+ Config
100
+ >(
101
+ requestHandler as any, // one argument if no middleware, 2 if has middleware. TODO: clean this shit up
102
+ errorHandler,
103
+ middlewareLayer
104
+ )
105
+
106
+ const route = HttpRouter.makeRoute(
107
+ requestHandler.Request.method,
108
+ requestHandler.Request.path,
109
+ handler
110
+ )
111
+ // TODO
112
+ // rdesc.push(makeRouteDescriptor(
113
+ // requestHandler.Request.path,
114
+ // requestHandler.Request.method,
115
+ // requestHandler
116
+ // ))
117
+ return route
118
+ })
119
+ }
@@ -0,0 +1,11 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/ban-types */
3
+
4
+ // codegen:start {preset: barrel, include: routing/*.ts }
5
+ export * from "./routing/base.js"
6
+ export * from "./routing/defaultErrorHandler.js"
7
+ export * from "./routing/makeRequestHandler.js"
8
+ export * from "./routing/match.js"
9
+ // codegen:end
10
+
11
+ // export * from "@effect-app/infra/api/routing"
@@ -3,13 +3,6 @@ import { RequestContext } from "../RequestContext.js"
3
3
  import { RequestContextContainer } from "../services/RequestContextContainer.js"
4
4
  import { ContextMapContainer } from "../services/Store/ContextMapContainer.js"
5
5
 
6
- /**
7
- * @tsplus fluent effect/io/Effect setupRequestContextFromName
8
- */
9
- export function setupRequestContextFromName<R, E, A>(self: Effect<R, E, A>, name: string) {
10
- return makeInternalRequestContext(name).flatMap((rc) => setupRequestContext(self, rc))
11
- }
12
-
13
6
  function makeInternalRequestContext(name: string) {
14
7
  return Effect.sync(() => {
15
8
  const id = RequestId.make()
@@ -25,40 +18,52 @@ function makeInternalRequestContext(name: string) {
25
18
  const withRequestSpan = <R, E, A>(f: Effect<R, E, A>) =>
26
19
  RequestContextContainer
27
20
  .get
28
- .flatMap((ctx) =>
21
+ .andThen((ctx) =>
29
22
  f
30
- .withSpan("request", {
31
- attributes: {
32
- "request.id": ctx.id,
33
- "request.name": ctx.name,
34
- "request.locale": ctx.locale,
35
- "request.namespace": ctx.namespace,
36
- ...ctx.userProfile?.sub
37
- ? {
38
- "request.user.sub": ctx
39
- .userProfile
40
- .sub,
41
- "request.user.roles": "roles" in ctx
42
- .userProfile
43
- ? ctx.userProfile.roles
44
- : undefined
45
- }
46
- : {}
47
- }
48
- })
23
+ .withSpan("request", { attributes: ctx.spanAttributes })
49
24
  // request context info is picked up directly in the logger for annotations.
50
25
  .withLogSpan("request")
51
26
  )
52
27
 
53
- function setupContextMap<R, E, A>(self: Effect<R, E, A>) {
54
- return (ContextMapContainer.flatMap((_) => _.start)
55
- > self)
56
- }
28
+ const setupContextMap = ContextMapContainer.andThen((_) => _.start).toLayerDiscard
29
+
30
+ // const RequestContextLiveFromRequestContext = (requestContext: RequestContext) =>
31
+ // RequestContext.Tag.makeLayer(requestContext)
32
+ // memoization problem
33
+ // const RequestContextLive = RequestContextContainer.get.toLayer(RequestContext.Tag)
34
+ const RequestContextStartLiveFromRequestContext = (requestContext: RequestContext) =>
35
+ setupContextMap
36
+ // .provideMerge(RequestContextLiveFromRequestContext(requestContext))
37
+ .provideMerge(
38
+ RequestContextContainer
39
+ .andThen((_) => _.start(requestContext))
40
+ .toLayerDiscard
41
+ )
42
+
43
+ const RequestContextStartLive = (requestContext: RequestContext | string) =>
44
+ typeof requestContext === "string"
45
+ ? makeInternalRequestContext(requestContext)
46
+ .andThen(RequestContextStartLiveFromRequestContext)
47
+ .unwrapLayer
48
+ : RequestContextStartLiveFromRequestContext(requestContext)
57
49
 
58
50
  /**
59
51
  * @tsplus fluent effect/io/Effect setupRequestContext
60
52
  */
61
- export function setupRequestContext<R, E, A>(self: Effect<R, E, A>, requestContext: RequestContext) {
62
- return RequestContextContainer.flatMap((_) => _.start(requestContext))
63
- > withRequestSpan(setupContextMap(self))
53
+ export function setupRequestContext<R, E, A>(self: Effect<R, E, A>, requestContext: RequestContext | string) {
54
+ return self
55
+ .pipe(withRequestSpan)
56
+ .provide(RequestContextStartLive(requestContext))
57
+ }
58
+
59
+ const UpdateRequestContextLive = (f: (rc: RequestContext) => RequestContext) =>
60
+ RequestContextContainer.andThen((rcc) => rcc.update(f)).toLayerDiscard
61
+
62
+ /**
63
+ * @tsplus fluent effect/io/Effect updateRequestContext
64
+ */
65
+ export function updateRequestContext<R, E, A>(self: Effect<R, E, A>, f: (rc: RequestContext) => RequestContext) {
66
+ return self
67
+ // .provideServiceEffect(RequestContext.Tag, RequestContextContainer.get)
68
+ .provide(UpdateRequestContextLive(f))
64
69
  }
@@ -13,12 +13,13 @@ export function reportError(
13
13
  return
14
14
  }
15
15
  yield* $(reportSentry(cause, name, extras))
16
+ const error = new CauseException(cause, name)
16
17
  yield* $(
17
18
  Effect
18
19
  .logError("Reporting error", cause)
19
20
  .annotateLogs(dropUndefined({
20
21
  extras,
21
- // __cause__: error.toJSON(), // logs too much garbage
22
+ __cause__: error.toJSON(),
22
23
  __error_name__: name
23
24
  }))
24
25
  )
@@ -50,12 +51,13 @@ export function logError<E>(
50
51
  yield* $(Effect.logDebug("Interrupted").annotateLogs(dropUndefined({ extras })))
51
52
  return
52
53
  }
54
+ const error = new CauseException(cause, name)
53
55
  yield* $(
54
56
  Effect
55
57
  .logWarning("Logging error", cause)
56
58
  .annotateLogs(dropUndefined({
57
59
  extras,
58
- // __cause__: error.toJSON(), // logs too much garbage
60
+ __cause__: error.toJSON(),
59
61
  __error_name__: name
60
62
  }))
61
63
  )
package/_src/errors.ts CHANGED
@@ -1,48 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/ban-types */
2
2
  import { makeFiberFailure } from "effect/Runtime"
3
3
 
4
- /** @tsplus type NotFoundError */
5
- export class NotFoundError<T extends string = string>
6
- extends Data.TaggedError("NotFoundError")<{ message: string; type: T; id: string }>
7
- {
8
- constructor(args: { readonly type: T; readonly id: string }) {
9
- super({ ...args, message: `Didn't find ${args.type}#${args.id}` })
10
- }
11
- }
12
-
13
- /** @tsplus type ValidationError */
14
- export class ValidationError extends Data.TaggedError("ValidationError")<{ errors: ReadonlyArray<unknown> }> {}
15
-
16
- /** @tsplus type NotLoggedInError */
17
- export class NotLoggedInError extends Data.TaggedError("NotLoggedInError")<{ message?: string | undefined }> {
18
- constructor(message?: string) {
19
- super({ message })
20
- }
21
- }
22
-
23
- /** @tsplus type UnauthorizedError */
24
- export class UnauthorizedError extends Data.TaggedError("UnauthorizedError")<{ message?: string | undefined }> {
25
- constructor(message?: string) {
26
- super({ message })
27
- }
28
- }
29
-
30
- /**
31
- * The user carries a valid Userprofile, but there is a problem with the login none the less.
32
- */
33
- /** @tsplus type LoginError */
34
- export class LoginError extends Data.TaggedError("NotLoggeInError")<{ message: string }> {
35
- constructor(message: string) {
36
- super({ message })
37
- }
38
- }
39
-
40
- /** @tsplus type InvalidStateError */
41
- export class InvalidStateError extends Data.TaggedError("InvalidStateError")<{ message: string }> {
42
- constructor(message: string) {
43
- super({ message })
44
- }
45
- }
4
+ export * from "@effect-app/prelude/client/errors"
46
5
 
47
6
  /** @tsplus type CauseException */
48
7
  export class CauseException<E> extends Error {
@@ -75,19 +34,3 @@ export class CauseException<E> extends Error {
75
34
  return `[${this._tag}] ` + Cause.pretty(this.originalCause)
76
35
  }
77
36
  }
78
-
79
- /** @tsplus type OptimisticConcurrencyException */
80
- export class OptimisticConcurrencyException extends Data.TaggedError("OptimisticConcurrencyException")<
81
- { type: string; id: string; current?: string | undefined; found?: string | undefined; message: string }
82
- > {
83
- constructor(
84
- args: {
85
- readonly type: string
86
- readonly id: string
87
- readonly current?: string | undefined
88
- readonly found?: string | undefined
89
- }
90
- ) {
91
- super({ ...args, message: `Existing ${args.type} ${args.id} record changed` })
92
- }
93
- }
@@ -1,6 +1,6 @@
1
1
  import { MemQueue } from "@effect-app/infra-adapters/memQueue"
2
2
  import { RequestContext } from "@effect-app/infra/RequestContext"
3
- import type { Schema2 } from "@effect-app/prelude"
3
+ import type { S } from "@effect-app/prelude"
4
4
  import { RequestId } from "@effect-app/prelude/ids"
5
5
  import { Tracer } from "effect"
6
6
  import { RequestContextContainer } from "../RequestContextContainer.js"
@@ -17,8 +17,8 @@ export function makeMemQueue<
17
17
  >(
18
18
  queueName: string,
19
19
  queueDrainName: string,
20
- schema: Schema2.Schema<EvtE, Evt>,
21
- drainSchema: Schema2.Schema<unknown, DrainEvt>
20
+ schema: S.Schema<EvtE, Evt>,
21
+ drainSchema: S.Schema<unknown, DrainEvt>
22
22
  ) {
23
23
  return Effect.gen(function*($) {
24
24
  const mem = yield* $(MemQueue)
@@ -9,7 +9,7 @@ import {
9
9
  import type {} from "@azure/service-bus"
10
10
  import { captureException } from "@effect-app/infra/errorReporter"
11
11
  import { RequestContext } from "@effect-app/infra/RequestContext"
12
- import type { Schema2 } from "@effect-app/prelude"
12
+ import type { S } from "@effect-app/prelude"
13
13
  import { RequestId } from "@effect-app/prelude/ids"
14
14
  import { struct } from "@effect-app/schema"
15
15
  import { Tracer } from "effect"
@@ -27,8 +27,8 @@ export function makeServiceBusQueue<
27
27
  >(
28
28
  _queueName: string,
29
29
  queueDrainName: string,
30
- schema: Schema2.Schema<EvtE, Evt>,
31
- drainSchema: Schema2.Schema<unknown, DrainEvt>
30
+ schema: S.Schema<EvtE, Evt>,
31
+ drainSchema: S.Schema<unknown, DrainEvt>
32
32
  ) {
33
33
  const wireSchema = struct({
34
34
  body: schema,