@effect-app/infra 0.85.0-next.4 → 0.85.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 (232) hide show
  1. package/CHANGELOG.md +3 -36
  2. package/_cjs/_ext/Array.cjs +2 -3
  3. package/_cjs/_ext/Array.cjs.map +1 -1
  4. package/_cjs/api/defaultErrorHandler.cjs +10 -11
  5. package/_cjs/api/defaultErrorHandler.cjs.map +1 -1
  6. package/_cjs/api/express/makeJsonSchema.cjs +2 -3
  7. package/_cjs/api/express/makeJsonSchema.cjs.map +1 -1
  8. package/_cjs/api/express/makeJsonSchema.test.cjs +2 -2
  9. package/_cjs/api/express/makeJsonSchema.test.cjs.map +1 -1
  10. package/_cjs/api/express/makeOpenApiSpecs.cjs +4 -6
  11. package/_cjs/api/express/makeOpenApiSpecs.cjs.map +1 -1
  12. package/_cjs/api/express/schema/routing.cjs +22 -23
  13. package/_cjs/api/express/schema/routing.cjs.map +1 -1
  14. package/_cjs/api/reportError.cjs +2 -2
  15. package/_cjs/api/setupRequest.cjs +4 -5
  16. package/_cjs/api/setupRequest.cjs.map +1 -1
  17. package/_cjs/api/writeDocs.cjs +4 -6
  18. package/_cjs/api/writeDocs.cjs.map +1 -1
  19. package/_cjs/errorReporter.cjs +11 -12
  20. package/_cjs/errorReporter.cjs.map +1 -1
  21. package/_cjs/errors.cjs +8 -8
  22. package/_cjs/errors.cjs.map +1 -1
  23. package/_cjs/instrument.cjs +1 -2
  24. package/_cjs/instrument.cjs.map +1 -1
  25. package/_cjs/logger/jsonLogger.cjs +10 -11
  26. package/_cjs/logger/jsonLogger.cjs.map +1 -1
  27. package/_cjs/logger/logFmtLogger.cjs +5 -5
  28. package/_cjs/logger/logFmtLogger.cjs.map +1 -1
  29. package/_cjs/logger/shared.cjs +4 -4
  30. package/_cjs/logger/shared.cjs.map +1 -1
  31. package/_cjs/rateLimit.cjs +7 -8
  32. package/_cjs/rateLimit.cjs.map +1 -1
  33. package/_cjs/services/Emailer/Sendgrid.cjs +12 -14
  34. package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -1
  35. package/_cjs/services/Emailer/fake.cjs +4 -5
  36. package/_cjs/services/Emailer/fake.cjs.map +1 -1
  37. package/_cjs/services/Operations/live.cjs +29 -31
  38. package/_cjs/services/Operations/live.cjs.map +1 -1
  39. package/_cjs/services/Operations/service.cjs +5 -6
  40. package/_cjs/services/Operations/service.cjs.map +1 -1
  41. package/_cjs/services/QueueMaker/errors.cjs +6 -7
  42. package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
  43. package/_cjs/services/QueueMaker/memQueue.cjs +17 -18
  44. package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
  45. package/_cjs/services/QueueMaker/sbqueue.cjs +15 -16
  46. package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
  47. package/_cjs/services/Repository.cjs +16 -17
  48. package/_cjs/services/Repository.cjs.map +1 -1
  49. package/_cjs/services/RepositoryBase.cjs +33 -35
  50. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  51. package/_cjs/services/RequestContextContainer.cjs +20 -15
  52. package/_cjs/services/RequestContextContainer.cjs.map +1 -1
  53. package/_cjs/services/Store/Cosmos.cjs +46 -49
  54. package/_cjs/services/Store/Cosmos.cjs.map +1 -1
  55. package/_cjs/services/Store/Disk.cjs +18 -19
  56. package/_cjs/services/Store/Disk.cjs.map +1 -1
  57. package/_cjs/services/Store/Memory.cjs +39 -43
  58. package/_cjs/services/Store/Memory.cjs.map +1 -1
  59. package/_cjs/services/Store/Redis.cjs +14 -16
  60. package/_cjs/services/Store/Redis.cjs.map +1 -1
  61. package/_cjs/services/Store/codeFilter.test.cjs +1 -1
  62. package/_cjs/services/Store/index.cjs +6 -7
  63. package/_cjs/services/Store/index.cjs.map +1 -1
  64. package/_cjs/services/Store/service.cjs +1 -1
  65. package/_cjs/services/Store/service.cjs.map +1 -1
  66. package/_cjs/services/Store/utils.cjs +13 -13
  67. package/_cjs/services/Store/utils.cjs.map +1 -1
  68. package/_cjs/services/simpledb/cosmosdb.cjs +17 -19
  69. package/_cjs/services/simpledb/cosmosdb.cjs.map +1 -1
  70. package/_cjs/services/simpledb/diskdb.cjs +8 -9
  71. package/_cjs/services/simpledb/diskdb.cjs.map +1 -1
  72. package/_cjs/services/simpledb/memdb.cjs +9 -11
  73. package/_cjs/services/simpledb/memdb.cjs.map +1 -1
  74. package/_cjs/services/simpledb/mongodb.cjs +18 -20
  75. package/_cjs/services/simpledb/mongodb.cjs.map +1 -1
  76. package/_cjs/services/simpledb/redisdb.cjs +10 -11
  77. package/_cjs/services/simpledb/redisdb.cjs.map +1 -1
  78. package/_cjs/services/simpledb/shared.cjs +5 -5
  79. package/_cjs/services/simpledb/shared.cjs.map +1 -1
  80. package/_cjs/services/simpledb/simpledb.cjs +17 -18
  81. package/_cjs/services/simpledb/simpledb.cjs.map +1 -1
  82. package/_src/api/authorization.jwt.ts +1 -1
  83. package/_src/api/defaultErrorHandler.ts +2 -2
  84. package/_src/api/express/routing.ts.bak +8 -8
  85. package/_src/api/express/schema/routing.ts +59 -37
  86. package/_src/api/setupRequest.ts +11 -10
  87. package/_src/errorReporter.ts +1 -1
  88. package/_src/services/Emailer/Sendgrid.ts +1 -1
  89. package/_src/services/Operations/live.ts +5 -5
  90. package/_src/services/QueueMaker/errors.ts +1 -1
  91. package/_src/services/QueueMaker/memQueue.ts +2 -2
  92. package/_src/services/QueueMaker/sbqueue.ts +1 -1
  93. package/_src/services/Repository.ts +9 -9
  94. package/_src/services/RepositoryBase.ts +6 -8
  95. package/_src/services/RequestContextContainer.ts +12 -7
  96. package/_src/services/Store/Cosmos.ts +12 -17
  97. package/_src/services/Store/Disk.ts +4 -4
  98. package/_src/services/Store/Memory.ts +4 -4
  99. package/_src/services/Store/Redis.ts +1 -1
  100. package/_src/services/Store/index.test.ts.bak +5 -5
  101. package/_src/services/Store/index.ts +1 -1
  102. package/_src/services/Store/utils.ts +16 -16
  103. package/_src/services/simpledb/diskdb.ts +1 -1
  104. package/_src/services/simpledb/memdb.ts +1 -1
  105. package/_src/services/simpledb/redisdb.ts +1 -1
  106. package/_src/services/simpledb/shared.ts +1 -1
  107. package/_src/services/simpledb/simpledb.ts +3 -3
  108. package/dist/RequestContext.d.ts +4 -4
  109. package/dist/_ext/Array.d.ts +1 -1
  110. package/dist/_ext/Array.d.ts.map +1 -1
  111. package/dist/_ext/Array.js +3 -4
  112. package/dist/api/codec.d.ts +1 -1
  113. package/dist/api/codec.d.ts.map +1 -1
  114. package/dist/api/defaultErrorHandler.d.ts +2 -2
  115. package/dist/api/defaultErrorHandler.d.ts.map +1 -1
  116. package/dist/api/defaultErrorHandler.js +11 -13
  117. package/dist/api/express/makeJsonSchema.d.ts +2 -2
  118. package/dist/api/express/makeJsonSchema.d.ts.map +1 -1
  119. package/dist/api/express/makeJsonSchema.js +3 -4
  120. package/dist/api/express/makeOpenApiSpecs.d.ts +1 -1
  121. package/dist/api/express/makeOpenApiSpecs.js +5 -7
  122. package/dist/api/express/schema/routing.d.ts +22 -7
  123. package/dist/api/express/schema/routing.d.ts.map +1 -1
  124. package/dist/api/express/schema/routing.js +23 -24
  125. package/dist/api/reportError.d.ts +5 -5
  126. package/dist/api/reportError.d.ts.map +1 -1
  127. package/dist/api/reportError.js +2 -2
  128. package/dist/api/setupRequest.d.ts +2 -2
  129. package/dist/api/setupRequest.d.ts.map +1 -1
  130. package/dist/api/setupRequest.js +7 -7
  131. package/dist/api/writeDocs.d.ts +1 -1
  132. package/dist/api/writeDocs.d.ts.map +1 -1
  133. package/dist/api/writeDocs.js +5 -7
  134. package/dist/errorReporter.d.ts +3 -3
  135. package/dist/errorReporter.d.ts.map +1 -1
  136. package/dist/errorReporter.js +12 -13
  137. package/dist/errors.d.ts +7 -7
  138. package/dist/errors.js +9 -9
  139. package/dist/instrument.d.ts +1 -1
  140. package/dist/instrument.d.ts.map +1 -1
  141. package/dist/instrument.js +2 -3
  142. package/dist/logger/jsonLogger.d.ts +2 -2
  143. package/dist/logger/jsonLogger.d.ts.map +1 -1
  144. package/dist/logger/jsonLogger.js +11 -12
  145. package/dist/logger/logFmtLogger.d.ts +2 -2
  146. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  147. package/dist/logger/logFmtLogger.js +6 -6
  148. package/dist/logger/shared.d.ts +1 -1
  149. package/dist/logger/shared.d.ts.map +1 -1
  150. package/dist/logger/shared.js +5 -5
  151. package/dist/rateLimit.d.ts +3 -3
  152. package/dist/rateLimit.d.ts.map +1 -1
  153. package/dist/rateLimit.js +8 -9
  154. package/dist/services/Emailer/Sendgrid.d.ts +1 -1
  155. package/dist/services/Emailer/Sendgrid.d.ts.map +1 -1
  156. package/dist/services/Emailer/Sendgrid.js +15 -17
  157. package/dist/services/Emailer/fake.d.ts +1 -1
  158. package/dist/services/Emailer/fake.d.ts.map +1 -1
  159. package/dist/services/Emailer/fake.js +5 -6
  160. package/dist/services/Emailer/service.d.ts +3 -3
  161. package/dist/services/Operations/live.d.ts +1 -1
  162. package/dist/services/Operations/live.d.ts.map +1 -1
  163. package/dist/services/Operations/live.js +37 -39
  164. package/dist/services/Operations/service.d.ts +8 -8
  165. package/dist/services/Operations/service.d.ts.map +1 -1
  166. package/dist/services/Operations/service.js +12 -13
  167. package/dist/services/QueueMaker/errors.d.ts +3 -3
  168. package/dist/services/QueueMaker/errors.d.ts.map +1 -1
  169. package/dist/services/QueueMaker/errors.js +6 -7
  170. package/dist/services/QueueMaker/memQueue.d.ts +3 -3
  171. package/dist/services/QueueMaker/memQueue.js +16 -17
  172. package/dist/services/QueueMaker/sbqueue.d.ts +4 -4
  173. package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
  174. package/dist/services/QueueMaker/sbqueue.js +15 -16
  175. package/dist/services/Repository.d.ts +42 -42
  176. package/dist/services/Repository.d.ts.map +1 -1
  177. package/dist/services/Repository.js +17 -18
  178. package/dist/services/RepositoryBase.d.ts +12 -11
  179. package/dist/services/RepositoryBase.d.ts.map +1 -1
  180. package/dist/services/RepositoryBase.js +35 -37
  181. package/dist/services/RequestContextContainer.d.ts +14 -11
  182. package/dist/services/RequestContextContainer.d.ts.map +1 -1
  183. package/dist/services/RequestContextContainer.js +19 -18
  184. package/dist/services/Store/Cosmos.d.ts +3 -3
  185. package/dist/services/Store/Cosmos.d.ts.map +1 -1
  186. package/dist/services/Store/Cosmos.js +51 -54
  187. package/dist/services/Store/Disk.d.ts +3 -3
  188. package/dist/services/Store/Disk.d.ts.map +1 -1
  189. package/dist/services/Store/Disk.js +19 -20
  190. package/dist/services/Store/Memory.d.ts +5 -5
  191. package/dist/services/Store/Memory.d.ts.map +1 -1
  192. package/dist/services/Store/Memory.js +41 -45
  193. package/dist/services/Store/Redis.d.ts +3 -3
  194. package/dist/services/Store/Redis.d.ts.map +1 -1
  195. package/dist/services/Store/Redis.js +15 -17
  196. package/dist/services/Store/index.d.ts +1 -1
  197. package/dist/services/Store/index.d.ts.map +1 -1
  198. package/dist/services/Store/index.js +7 -8
  199. package/dist/services/Store/service.d.ts +8 -8
  200. package/dist/services/Store/service.d.ts.map +1 -1
  201. package/dist/services/Store/service.js +2 -2
  202. package/dist/services/Store/utils.d.ts +2 -2
  203. package/dist/services/Store/utils.d.ts.map +1 -1
  204. package/dist/services/Store/utils.js +21 -21
  205. package/dist/services/simpledb/cosmosdb.d.ts +5 -5
  206. package/dist/services/simpledb/cosmosdb.js +17 -19
  207. package/dist/services/simpledb/diskdb.d.ts +4 -4
  208. package/dist/services/simpledb/diskdb.js +9 -10
  209. package/dist/services/simpledb/memdb.d.ts +4 -4
  210. package/dist/services/simpledb/memdb.js +11 -13
  211. package/dist/services/simpledb/mongodb.d.ts +5 -5
  212. package/dist/services/simpledb/mongodb.js +14 -16
  213. package/dist/services/simpledb/redisdb.d.ts +4 -4
  214. package/dist/services/simpledb/redisdb.js +11 -12
  215. package/dist/services/simpledb/shared.d.ts +4 -4
  216. package/dist/services/simpledb/shared.js +6 -6
  217. package/dist/services/simpledb/simpledb.d.ts +6 -6
  218. package/dist/services/simpledb/simpledb.d.ts.map +1 -1
  219. package/dist/services/simpledb/simpledb.js +15 -16
  220. package/package.json +5 -25
  221. package/_cjs/api/express/schema/requestHandler.cjs +0 -172
  222. package/_cjs/api/express/schema/requestHandler.cjs.map +0 -1
  223. package/_cjs/api/routing.cjs +0 -278
  224. package/_cjs/api/routing.cjs.map +0 -1
  225. package/_src/api/express/schema/requestHandler.ts +0 -372
  226. package/_src/api/routing.ts +0 -660
  227. package/dist/api/express/schema/requestHandler.d.ts +0 -71
  228. package/dist/api/express/schema/requestHandler.d.ts.map +0 -1
  229. package/dist/api/express/schema/requestHandler.js +0 -140
  230. package/dist/api/routing.d.ts +0 -103
  231. package/dist/api/routing.d.ts.map +0 -1
  232. package/dist/api/routing.js +0 -265
@@ -1,660 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import * as Ex from "@effect-app/infra-adapters/express"
3
- import type { _E, _R } from "@effect-app/prelude/_ext/misc"
4
- import type { SupportedErrors } from "@effect-app/prelude/client/errors"
5
- import { RequestId } from "@effect-app/prelude/ids"
6
- import type { GetRequest, GetResponse } from "@effect-app/prelude/schema"
7
- import { extractSchema, SchemaNamed } from "@effect-app/prelude/schema"
8
- import * as MO from "@effect-app/prelude/schema"
9
- import { pretty } from "@effect-app/prelude/utils"
10
- import type express from "express"
11
- import type { ValidationError } from "../errors.js"
12
- import { RequestContext } from "../RequestContext.js"
13
- import { RequestContextContainer, RequestContextContainerImpl } from "../services/RequestContextContainer.js"
14
- import { restoreFromRequestContext } from "../services/Store/Memory.js"
15
- import { defaultBasicErrorHandler } from "./defaultErrorHandler.js"
16
- import type { Encode, RequestHandler, RequestHandlerOptRes, RequestParsers } from "./express/schema/requestHandler.js"
17
- import { parseRequestParams } from "./express/schema/requestHandler.js"
18
- import type { RouteDescriptorAny } from "./express/schema/routing.js"
19
- import { makeRouteDescriptor } from "./express/schema/routing.js"
20
- import { reportRequestError } from "./reportError.js"
21
- import { snipString } from "./util.js"
22
-
23
- export const RequestSettings = FiberRef.unsafeMake({
24
- verbose: false
25
- })
26
-
27
- export function makeRequestParsers<
28
- R,
29
- PathA,
30
- CookieA,
31
- QueryA,
32
- BodyA,
33
- HeaderA,
34
- ReqA extends PathA & QueryA & BodyA,
35
- ResA,
36
- Errors
37
- >(
38
- Request: RequestHandler<
39
- R,
40
- PathA,
41
- CookieA,
42
- QueryA,
43
- BodyA,
44
- HeaderA,
45
- ReqA,
46
- ResA,
47
- Errors
48
- >["Request"]
49
- ): RequestParsers<PathA, CookieA, QueryA, BodyA, HeaderA> {
50
- const ph = Effect.sync(() =>
51
- Option
52
- .fromNullable(Request.Headers)
53
- .map((s) => s)
54
- .map(Parser.for)
55
- .map(MO.condemnFail)
56
- )
57
- const parseHeaders = (u: unknown) => ph.flatMapOpt((d) => d(u))
58
-
59
- const pq = Effect.sync(() =>
60
- Option
61
- .fromNullable(Request.Query)
62
- .map((s) => s)
63
- .map(Parser.for)
64
- .map(MO.condemnFail)
65
- )
66
- const parseQuery = (u: unknown) => pq.flatMapOpt((d) => d(u))
67
-
68
- const pb = Effect.sync(() =>
69
- Option
70
- .fromNullable(Request.Body)
71
- .map((s) => s)
72
- .map(Parser.for)
73
- .map(MO.condemnFail)
74
- )
75
- const parseBody = (u: unknown) => pb.flatMapOpt((d) => d(u))
76
-
77
- const pp = Effect.sync(() =>
78
- Option
79
- .fromNullable(Request.Path)
80
- .map((s) => s)
81
- .map(Parser.for)
82
- .map(MO.condemnFail)
83
- )
84
- const parsePath = (u: unknown) => pp.flatMapOpt((d) => d(u))
85
-
86
- const pc = Effect.sync(() =>
87
- Option
88
- .fromNullable(Request.Cookie)
89
- .map((s) => s)
90
- .map(Parser.for)
91
- .map(MO.condemnFail)
92
- )
93
- const parseCookie = (u: unknown) => pc.flatMapOpt((d) => d(u))
94
-
95
- return {
96
- parseBody,
97
- parseCookie,
98
- parseHeaders,
99
- parsePath,
100
- parseQuery
101
- }
102
- }
103
-
104
- export type MakeMiddlewareContext<ResE, R2 = never, PR = never> = (
105
- req: express.Request,
106
- res: express.Response
107
- ) => Effect<R2 | RequestContextContainer, ResE, Context<PR>>
108
-
109
- export type Middleware<
110
- R,
111
- PathA,
112
- CookieA,
113
- QueryA,
114
- BodyA,
115
- HeaderA,
116
- ReqA extends PathA & QueryA & BodyA,
117
- ResA,
118
- ResE,
119
- R2 = never,
120
- PR = never
121
- > = (
122
- handler: RequestHandler<R, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE>
123
- ) => {
124
- handler: typeof handler
125
- makeContext: MakeMiddlewareContext<ResE, R2, PR>
126
- }
127
-
128
- export function match<
129
- R,
130
- E,
131
- PathA,
132
- CookieA,
133
- QueryA,
134
- BodyA,
135
- HeaderA,
136
- ReqA extends PathA & QueryA & BodyA,
137
- ResA,
138
- R2 = never,
139
- PR = never,
140
- RErr = never
141
- >(
142
- requestHandler: RequestHandler<
143
- R,
144
- PathA,
145
- CookieA,
146
- QueryA,
147
- BodyA,
148
- HeaderA,
149
- ReqA,
150
- ResA,
151
- E
152
- >,
153
- errorHandler: <R>(
154
- req: express.Request,
155
- res: express.Response,
156
- r2: Effect<R, E | ValidationError, void>
157
- ) => Effect<RErr, never, void>,
158
- middleware?: Middleware<
159
- R,
160
- PathA,
161
- CookieA,
162
- QueryA,
163
- BodyA,
164
- HeaderA,
165
- ReqA,
166
- ResA,
167
- E,
168
- R2,
169
- PR
170
- >
171
- ) {
172
- let makeMiddlewareContext = undefined
173
- if (middleware) {
174
- const { handler, makeContext } = middleware(requestHandler)
175
- requestHandler = handler
176
- makeMiddlewareContext = makeContext
177
- }
178
- return Ex
179
- .match(requestHandler.Request.method.toLowerCase() as any)(
180
- requestHandler.Request.path.split("?")[0],
181
- makeRequestHandler<R, E, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, R2, PR, RErr>(
182
- requestHandler,
183
- errorHandler,
184
- makeMiddlewareContext
185
- )
186
- )
187
- .zipRight(
188
- Effect.sync(() =>
189
- makeRouteDescriptor(
190
- requestHandler.Request.path,
191
- requestHandler.Request.method,
192
- requestHandler
193
- )
194
- )
195
- )
196
- }
197
-
198
- export function respondSuccess<ReqA, A, E>(
199
- encodeResponse: (req: ReqA) => Encode<A, E>
200
- ) {
201
- return (req: ReqA, res: express.Response, a: A) =>
202
- Effect
203
- .sync(() => encodeResponse(req)(a))
204
- .flatMap((r) =>
205
- Effect.sync(() => {
206
- r === undefined
207
- ? res.status(204).send()
208
- : res
209
- .status(200)
210
- .send(JSON.stringify(r))
211
- })
212
- )
213
- }
214
-
215
- export function makeRequestHandler<
216
- R,
217
- E,
218
- PathA,
219
- CookieA,
220
- QueryA,
221
- BodyA,
222
- HeaderA,
223
- ReqA extends PathA & QueryA & BodyA,
224
- ResA = void,
225
- R2 = never,
226
- PR = never,
227
- RErr = never
228
- >(
229
- handler: RequestHandlerOptRes<
230
- R | PR,
231
- PathA,
232
- CookieA,
233
- QueryA,
234
- BodyA,
235
- HeaderA,
236
- ReqA,
237
- ResA,
238
- E
239
- >,
240
- errorHandler: <R>(
241
- req: express.Request,
242
- res: express.Response,
243
- r2: Effect<R, E | ValidationError, void>
244
- ) => Effect<RErr | R | RequestContextContainer, never, void>,
245
- makeMiddlewareContext?: MakeMiddlewareContext<E, R2, PR>
246
- ): (
247
- req: express.Request,
248
- res: express.Response
249
- ) => Effect<Exclude<RErr | R | R2, RequestContextContainer>, never, void> {
250
- const { Request, Response, adaptResponse, h: handle } = handler
251
- const response = Response ? extractSchema(Response) : Void
252
- const encoder = Encoder.for(response as any)
253
- const encodeResponse = adaptResponse
254
- ? (req: ReqA) => Encoder.for(adaptResponse(req))
255
- : () => encoder
256
-
257
- const requestParsers = makeRequestParsers(Request)
258
- const parseRequest = parseRequestParams(requestParsers)
259
- const respond = respondSuccess(encodeResponse)
260
-
261
- function getParams(req: express.Request) {
262
- return Effect.sync(() => ({
263
- path: req.params,
264
- query: req.query,
265
- body: req.body,
266
- headers: req.headers,
267
- cookies: req.cookies
268
- }))
269
- }
270
-
271
- function makeContext(req: express.Request) {
272
- const start = new Date()
273
- const supported = ["en", "de"] as const
274
- const desiredLocale = req.headers["x-locale"]
275
- const locale = desiredLocale && supported.includes(desiredLocale as any)
276
- ? (desiredLocale as typeof supported[number])
277
- : ("en" as const)
278
-
279
- // const context = getAppInsightsContext()
280
- // if (!context) {
281
- // throw new Error("AI Context missing")
282
- // }
283
-
284
- const requestId = req.headers["request-id"]
285
- const rootId = requestId ? RequestId.parseUnsafe(requestId) : RequestId.make()
286
-
287
- const storeId = req.headers["x-store-id"]
288
- const namespace = ReasonableString((storeId && (Array.isArray(storeId) ? storeId[0] : storeId)) || "primary")
289
-
290
- const requestContext = new RequestContext({
291
- rootId,
292
- name: ReasonableString(
293
- Request.Model instanceof SchemaNamed ? Request.Model.name : Request.name
294
- ),
295
- locale,
296
- createdAt: start,
297
- namespace
298
- // ...(context.operation.parentId
299
- // ? {
300
- // parent: new RequestContextParent({
301
- // id: RequestId(context.operation.parentId),
302
- // locale,
303
- // name: ReasonableString("API Request")
304
- // })
305
- // }
306
- // : {})
307
- })
308
- // context.requestContext = requestContext
309
- return requestContext
310
- }
311
-
312
- return (req: express.Request, res: express.Response) => {
313
- return Effect
314
- .all({
315
- requestContext: Effect.sync(() => {
316
- const requestContext = makeContext(req)
317
- if (req.method === "GET") {
318
- res.setHeader("Cache-Control", "no-store")
319
- }
320
- res.setHeader("Content-Language", requestContext.locale)
321
- return requestContext
322
- }),
323
- pars: getParams(req)
324
- })
325
- .flatMap(({ pars, requestContext }) =>
326
- RequestSettings
327
- .get
328
- .flatMap((s) =>
329
- // TODO: we don;t have access to user id here cause context is not yet created
330
- Effect.logInfo("Incoming request").apply(
331
- Effect.annotateLogs({
332
- method: req.method,
333
- path: req.originalUrl,
334
- ...s.verbose
335
- ? {
336
- reqPath: pars.path.$$.pretty,
337
- reqQuery: pars.query.$$.pretty,
338
- reqBody: pretty(pars.body),
339
- reqCookies: pretty(pars.cookies),
340
- reqHeaders: pars.headers.$$.pretty
341
- }
342
- : undefined
343
- })
344
- )
345
- )
346
- .zipRight(
347
- Effect.suspend(() => {
348
- const handleRequest = parseRequest(req)
349
- .map(({ body, path, query }) => {
350
- const hn = {
351
- ...body.value,
352
- ...query.value,
353
- ...path.value
354
- } as unknown as ReqA
355
- return hn
356
- })
357
- .flatMap((parsedReq) =>
358
- handle(parsedReq as any)
359
- .flatMap((r) => respond(parsedReq, res, r))
360
- )
361
-
362
- // Commands should not be interruptable.
363
- const r = req.method !== "GET" ? handleRequest.uninterruptible : handleRequest // .instrument("Performance.RequestResponse")
364
- // the first log entry should be of the request start.
365
- const r2 = makeMiddlewareContext
366
- ? restoreFromRequestContext
367
- .zipRight(r
368
- // the db namespace must be restored, before calling provide here
369
- .provideSomeContextEffect(makeMiddlewareContext(req, res)))
370
- : restoreFromRequestContext
371
- // PR is not relevant here
372
- .zipRight(r) as Effect<R, E | ValidationError, void>
373
- return errorHandler(
374
- req,
375
- res,
376
- r2
377
- )
378
- })
379
- )
380
- .tapErrorCause((cause) =>
381
- Effect
382
- .all(
383
- [
384
- Effect.sync(() => res.status(500).send()),
385
- Effect.sync(() =>
386
- reportRequestError(cause, {
387
- path: req.originalUrl,
388
- method: req.method
389
- })
390
- ),
391
- Effect.suspend(() => {
392
- const headers = res.getHeaders()
393
- return Effect
394
- .logError(
395
- "Finished request",
396
- cause
397
- )
398
- .apply(Effect.annotateLogs({
399
- method: req.method,
400
- path: req.originalUrl,
401
- statusCode: res.statusCode.toString(),
402
-
403
- reqPath: pars.path.$$.pretty,
404
- reqQuery: pars.query.$$.pretty,
405
- reqBody: pretty(pars.body),
406
- reqCookies: pretty(pars.cookies),
407
- reqHeaders: pars.headers.$$.pretty,
408
-
409
- resHeaders: Object
410
- .entries(headers)
411
- .reduce((prev, [key, value]) => {
412
- prev[key] = value && typeof value === "string" ? snipString(value) : value
413
- return prev
414
- }, {} as Record<string, any>)
415
- .$$
416
- .pretty
417
- }))
418
- })
419
- ],
420
- { concurrency: "inherit" }
421
- )
422
- .tapErrorCause((cause) => Effect.sync(() => console.error("Error occurred while reporting error", cause)))
423
- )
424
- .tap(() =>
425
- RequestSettings
426
- .get
427
- .flatMap((s) => {
428
- const headers = res.getHeaders()
429
- return Effect.logInfo("Finished request").apply(Effect.annotateLogs({
430
- method: req.method,
431
- path: req.originalUrl,
432
- statusCode: res.statusCode.toString(),
433
- ...s.verbose
434
- ? {
435
- resHeaders: headers.$$.pretty
436
- }
437
- : undefined
438
- }))
439
- })
440
- )
441
- .withRequestSpan
442
- .provideService(RequestContextContainer, new RequestContextContainerImpl(requestContext)) // otherwise external error reporter breaks.
443
- )
444
- }
445
- }
446
-
447
- export type RequestHandlers = { [key: string]: BasicRequestHandler }
448
- export type BasicRequestHandler = RequestHandler<any, any, any, any, any, any, any, any, ValidationError>
449
-
450
- export type AnyRequestHandler = RequestHandler<any, any, any, any, any, any, any, any, any>
451
-
452
- type RouteAll<T extends RequestHandlers> = {
453
- [K in keyof T]: T[K] extends RequestHandler<
454
- infer R,
455
- any, // infer PathA,
456
- any, // infer CookieA,
457
- any, // infer QueryA,
458
- any, // infer BodyA,
459
- any, // infer HeaderA,
460
- any, // infer ReqA,
461
- any, // infer ResA,
462
- ValidationError // infer ResE
463
- > ? RouteMatch<R, never>
464
- : never
465
- }
466
-
467
- export type RouteMatch<
468
- R,
469
- // PathA,
470
- // CookieA,
471
- // QueryA,
472
- // BodyA,
473
- // HeaderA,
474
- // ReqA extends PathA & QueryA & BodyA,
475
- // ResA,
476
- PR = never
477
- > = Effect<
478
- | Ex.ExpressAppConfig
479
- | Ex.ExpressApp
480
- | Exclude<
481
- R,
482
- PR | RequestContextContainer
483
- >,
484
- never,
485
- RouteDescriptorAny // RouteDescriptor<R, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, SupportedErrors, Methods>
486
- >
487
-
488
- /**
489
- * Gather all handlers of a module and attach them to the Server.
490
- * Requires no login.
491
- */
492
- export function matchAll<T extends RequestHandlers>(handlers: T) {
493
- const mapped = handlers.$$.keys.reduce((prev, cur) => {
494
- prev[cur] = match(handlers[cur] as AnyRequestHandler, defaultBasicErrorHandler)
495
- return prev
496
- }, {} as any) as RouteAll<typeof handlers>
497
-
498
- return mapped
499
- }
500
-
501
- /**
502
- * Gather all handlers of a module and attach them to the Server.
503
- * Requires no login.
504
- */
505
- export function matchAllAlt<T extends RequestHandlersTest>(handlers: T) {
506
- const mapped = handlers.$$.keys.reduce((prev, cur) => {
507
- const matches = matchAll(handlers[cur])
508
- matches.$$.keys.forEach((key) => prev[`${cur as string}.${key as string}`] = matches[key])
509
- return prev
510
- }, {} as any) as Flatten<RouteAllTest<typeof handlers>>
511
-
512
- return mapped
513
- }
514
-
515
- export type RequestHandlersTest = {
516
- [key: string]: Record<string, BasicRequestHandler>
517
- }
518
-
519
- export type RouteAllTest<T extends RequestHandlersTest> = {
520
- [K in keyof T]: RouteAll<T[K]>
521
- }
522
-
523
- // type JoinObjects<T extends Record<string, Record<string, any>> = { [`${K in keyof T }`]: RouteAll<T[K]> }
524
-
525
- export type Flatten<T extends object> = object extends T ? object : {
526
- [K in keyof T]-?: (
527
- x: NonNullable<T[K]> extends infer V ? V extends object ? V extends readonly any[] ? Pick<T, K>
528
- : FlattenLVL1<V> extends infer FV ? ({
529
- [P in keyof FV as `${Extract<K, string | number>}.${Extract<P, string | number>}`]: FV[P]
530
- })
531
- : never
532
- : Pick<T, K>
533
- : never
534
- ) => void
535
- } extends Record<keyof T, (y: infer O) => void> ? O extends unknown /* infer U */ ? { [K in keyof O]: O[K] } : never
536
- : never
537
-
538
- type FlattenLVL1<T extends object> = object extends T ? object : {
539
- [K in keyof T]-?: (
540
- x: NonNullable<T[K]> extends infer V ? V extends object ? V extends readonly any[] ? Pick<T, K>
541
- /*: Flatten<V> extends infer FV ? ({
542
- [P in keyof FV as `${Extract<K, string | number>}.${Extract<P, string | number>}`]: FV[P]
543
- })
544
- : never
545
- */
546
- : Pick<T, K>
547
- : never
548
- : never
549
- ) => void
550
- } extends Record<keyof T, (y: infer O) => void> ? O extends unknown /* infer U */ ? { [K in keyof O]: O[K] } : never
551
- : never
552
-
553
- export function handle<
554
- TModule extends Record<
555
- string,
556
- any // { Model: MO.SchemaAny; new (...args: any[]): any } | MO.SchemaAny
557
- >
558
- >(
559
- _: TModule & { ResponseOpenApi?: any },
560
- adaptResponse?: any
561
- ) {
562
- // TODO: Prevent over providing // no strict/shrink yet.
563
- const Request = MO.extractRequest(_)
564
- const Response = MO.extractResponse(_)
565
-
566
- type ReqSchema = MO.GetRequest<TModule>
567
- type ResSchema = MO.GetResponse<TModule>
568
- type Req = InstanceType<
569
- ReqSchema extends { new(...args: any[]): any } ? ReqSchema
570
- : never
571
- >
572
- type Res = MO.ParsedShapeOf<Extr<ResSchema>>
573
-
574
- return <R, E>(
575
- h: (r: Req) => Effect<R, E, Res>
576
- ) => ({
577
- adaptResponse,
578
- h,
579
- Request,
580
- Response,
581
- ResponseOpenApi: _.ResponseOpenApi ?? Response
582
- } as ReqHandler<
583
- Req,
584
- R,
585
- E,
586
- Res,
587
- ReqSchema,
588
- ResSchema
589
- >)
590
- }
591
-
592
- export type Extr<T> = T extends { Model: MO.SchemaAny } ? T["Model"]
593
- : T extends MO.SchemaAny ? T
594
- : never
595
-
596
- export interface ReqHandler<
597
- Req,
598
- R,
599
- E,
600
- Res,
601
- ReqSchema extends MO.SchemaAny,
602
- ResSchema extends MO.SchemaAny,
603
- CTX = any
604
- > {
605
- h: (r: Req, ctx: CTX) => Effect<R, E, Res>
606
- Request: ReqSchema
607
- Response: ResSchema
608
- ResponseOpenApi: any
609
- }
610
-
611
- /**
612
- * Provided a module with resources, and provided an Object with resource handlers, will prepare route handlers to be attached to server.
613
- * @param mod The module with Resources you want to match.
614
- * @returns A function that must be called with an Object with a handler "Request -> Effect<R, E, Response>" for each resource defined in the Module.
615
- *
616
- * Example:
617
- * ```
618
- * class SayHelloRequest extends Get("/say-hello")<SayHelloRequest>()({ name: prop(ReasonableString) }) {}
619
- * class SayHelloResponse extends Model<SayHelloRequest>()({ message: prop(LongString) }) {}
620
- *
621
- * export const SayHelloControllers = matchResource({ SayHello: { SayHelloRequest, SayHelloResponse } })({
622
- * SayHello: (req) => Effect.sync(() => { message: `Hi ${req.name}` })
623
- * })
624
- * ```
625
- */
626
- export function matchResource<TModules extends Record<string, Record<string, any>>>(mod: TModules) {
627
- type Keys = keyof TModules
628
- return <
629
- THandlers extends {
630
- [K in Keys]: (
631
- req: ReqFromSchema<GetRequest<TModules[K]>>
632
- ) => Effect<any, SupportedErrors, ResFromSchema<GetResponse<TModules[K]>>>
633
- }
634
- >(
635
- handlers: THandlers
636
- ) => {
637
- const handler = mod.$$.keys.reduce((prev, cur) => {
638
- prev[cur] = handle(mod[cur])(handlers[cur] as any)
639
- return prev
640
- }, {} as any)
641
- type HNDLRS = typeof handlers
642
- return handler as {
643
- [K in Keys]: ReqHandler<
644
- ReqFromSchema<GetRequest<TModules[K]>>,
645
- _R<ReturnType<HNDLRS[K]>>,
646
- _E<ReturnType<HNDLRS[K]>>,
647
- ResFromSchema<GetResponse<TModules[K]>>,
648
- GetRequest<TModules[K]>,
649
- GetResponse<TModules[K]>
650
- >
651
- }
652
- }
653
- }
654
-
655
- export type ReqFromSchema<ReqSchema> = InstanceType<
656
- ReqSchema extends { new(...args: any[]): any } ? ReqSchema
657
- : never
658
- >
659
-
660
- export type ResFromSchema<ResSchema> = ParsedShapeOf<Extr<ResSchema>>