@effect-app/infra 0.85.0-next.4 → 0.85.1
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 +5 -32
- package/_cjs/_ext/Array.cjs +2 -3
- package/_cjs/_ext/Array.cjs.map +1 -1
- package/_cjs/api/defaultErrorHandler.cjs +10 -11
- package/_cjs/api/defaultErrorHandler.cjs.map +1 -1
- package/_cjs/api/express/makeJsonSchema.cjs +2 -3
- package/_cjs/api/express/makeJsonSchema.cjs.map +1 -1
- package/_cjs/api/express/makeJsonSchema.test.cjs +2 -2
- package/_cjs/api/express/makeJsonSchema.test.cjs.map +1 -1
- package/_cjs/api/express/makeOpenApiSpecs.cjs +4 -6
- package/_cjs/api/express/makeOpenApiSpecs.cjs.map +1 -1
- package/_cjs/api/express/schema/routing.cjs +22 -23
- package/_cjs/api/express/schema/routing.cjs.map +1 -1
- package/_cjs/api/reportError.cjs +2 -2
- package/_cjs/api/setupRequest.cjs +4 -5
- package/_cjs/api/setupRequest.cjs.map +1 -1
- package/_cjs/api/writeDocs.cjs +4 -6
- package/_cjs/api/writeDocs.cjs.map +1 -1
- package/_cjs/errorReporter.cjs +11 -12
- package/_cjs/errorReporter.cjs.map +1 -1
- package/_cjs/errors.cjs +8 -8
- package/_cjs/errors.cjs.map +1 -1
- package/_cjs/instrument.cjs +1 -2
- package/_cjs/instrument.cjs.map +1 -1
- package/_cjs/logger/jsonLogger.cjs +10 -11
- package/_cjs/logger/jsonLogger.cjs.map +1 -1
- package/_cjs/logger/logFmtLogger.cjs +5 -5
- package/_cjs/logger/logFmtLogger.cjs.map +1 -1
- package/_cjs/logger/shared.cjs +4 -4
- package/_cjs/logger/shared.cjs.map +1 -1
- package/_cjs/rateLimit.cjs +7 -8
- package/_cjs/rateLimit.cjs.map +1 -1
- package/_cjs/services/Emailer/Sendgrid.cjs +12 -14
- package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -1
- package/_cjs/services/Emailer/fake.cjs +4 -5
- package/_cjs/services/Emailer/fake.cjs.map +1 -1
- package/_cjs/services/Operations/live.cjs +29 -31
- package/_cjs/services/Operations/live.cjs.map +1 -1
- package/_cjs/services/Operations/service.cjs +5 -6
- package/_cjs/services/Operations/service.cjs.map +1 -1
- package/_cjs/services/QueueMaker/errors.cjs +6 -7
- package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
- package/_cjs/services/QueueMaker/memQueue.cjs +17 -18
- package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
- package/_cjs/services/QueueMaker/sbqueue.cjs +15 -16
- package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
- package/_cjs/services/Repository.cjs +16 -17
- package/_cjs/services/Repository.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs +33 -35
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/RequestContextContainer.cjs +20 -15
- package/_cjs/services/RequestContextContainer.cjs.map +1 -1
- package/_cjs/services/Store/Cosmos.cjs +46 -49
- package/_cjs/services/Store/Cosmos.cjs.map +1 -1
- package/_cjs/services/Store/Disk.cjs +18 -19
- package/_cjs/services/Store/Disk.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs +39 -43
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/Redis.cjs +14 -16
- package/_cjs/services/Store/Redis.cjs.map +1 -1
- package/_cjs/services/Store/codeFilter.test.cjs +1 -1
- package/_cjs/services/Store/index.cjs +6 -7
- package/_cjs/services/Store/index.cjs.map +1 -1
- package/_cjs/services/Store/service.cjs +1 -1
- package/_cjs/services/Store/service.cjs.map +1 -1
- package/_cjs/services/Store/utils.cjs +13 -13
- package/_cjs/services/Store/utils.cjs.map +1 -1
- package/_cjs/services/simpledb/cosmosdb.cjs +17 -19
- package/_cjs/services/simpledb/cosmosdb.cjs.map +1 -1
- package/_cjs/services/simpledb/diskdb.cjs +8 -9
- package/_cjs/services/simpledb/diskdb.cjs.map +1 -1
- package/_cjs/services/simpledb/memdb.cjs +9 -11
- package/_cjs/services/simpledb/memdb.cjs.map +1 -1
- package/_cjs/services/simpledb/mongodb.cjs +18 -20
- package/_cjs/services/simpledb/mongodb.cjs.map +1 -1
- package/_cjs/services/simpledb/redisdb.cjs +10 -11
- package/_cjs/services/simpledb/redisdb.cjs.map +1 -1
- package/_cjs/services/simpledb/shared.cjs +5 -5
- package/_cjs/services/simpledb/shared.cjs.map +1 -1
- package/_cjs/services/simpledb/simpledb.cjs +17 -18
- package/_cjs/services/simpledb/simpledb.cjs.map +1 -1
- package/_src/api/authorization.jwt.ts +1 -1
- package/_src/api/defaultErrorHandler.ts +2 -2
- package/_src/api/express/routing.ts.bak +8 -8
- package/_src/api/express/schema/routing.ts +59 -37
- package/_src/api/setupRequest.ts +11 -10
- package/_src/errorReporter.ts +1 -1
- package/_src/services/Emailer/Sendgrid.ts +1 -1
- package/_src/services/Operations/live.ts +5 -5
- package/_src/services/QueueMaker/errors.ts +1 -1
- package/_src/services/QueueMaker/memQueue.ts +2 -2
- package/_src/services/QueueMaker/sbqueue.ts +1 -1
- package/_src/services/Repository.ts +10 -11
- package/_src/services/RepositoryBase.ts +8 -11
- package/_src/services/RequestContextContainer.ts +12 -7
- package/_src/services/Store/Cosmos.ts +12 -17
- package/_src/services/Store/Disk.ts +4 -4
- package/_src/services/Store/Memory.ts +4 -4
- package/_src/services/Store/Redis.ts +1 -1
- package/_src/services/Store/index.test.ts.bak +5 -5
- package/_src/services/Store/index.ts +1 -1
- package/_src/services/Store/utils.ts +16 -16
- package/_src/services/simpledb/diskdb.ts +1 -1
- package/_src/services/simpledb/memdb.ts +1 -1
- package/_src/services/simpledb/redisdb.ts +1 -1
- package/_src/services/simpledb/shared.ts +1 -1
- package/_src/services/simpledb/simpledb.ts +3 -3
- package/dist/RequestContext.d.ts +4 -4
- package/dist/_ext/Array.d.ts +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/Array.js +3 -4
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/codec.d.ts.map +1 -1
- package/dist/api/defaultErrorHandler.d.ts +2 -2
- package/dist/api/defaultErrorHandler.d.ts.map +1 -1
- package/dist/api/defaultErrorHandler.js +11 -13
- package/dist/api/express/makeJsonSchema.d.ts +2 -2
- package/dist/api/express/makeJsonSchema.d.ts.map +1 -1
- package/dist/api/express/makeJsonSchema.js +3 -4
- package/dist/api/express/makeOpenApiSpecs.d.ts +1 -1
- package/dist/api/express/makeOpenApiSpecs.js +5 -7
- package/dist/api/express/schema/routing.d.ts +22 -7
- package/dist/api/express/schema/routing.d.ts.map +1 -1
- package/dist/api/express/schema/routing.js +23 -24
- package/dist/api/reportError.d.ts +5 -5
- package/dist/api/reportError.d.ts.map +1 -1
- package/dist/api/reportError.js +2 -2
- package/dist/api/setupRequest.d.ts +2 -2
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +7 -7
- package/dist/api/writeDocs.d.ts +1 -1
- package/dist/api/writeDocs.d.ts.map +1 -1
- package/dist/api/writeDocs.js +5 -7
- package/dist/errorReporter.d.ts +3 -3
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +12 -13
- package/dist/errors.d.ts +7 -7
- package/dist/errors.js +9 -9
- package/dist/instrument.d.ts +1 -1
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +2 -3
- package/dist/logger/jsonLogger.d.ts +2 -2
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +11 -12
- package/dist/logger/logFmtLogger.d.ts +2 -2
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +6 -6
- package/dist/logger/shared.d.ts +1 -1
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +5 -5
- package/dist/rateLimit.d.ts +3 -3
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +8 -9
- package/dist/services/Emailer/Sendgrid.d.ts +1 -1
- package/dist/services/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/services/Emailer/Sendgrid.js +15 -17
- package/dist/services/Emailer/fake.d.ts +1 -1
- package/dist/services/Emailer/fake.d.ts.map +1 -1
- package/dist/services/Emailer/fake.js +5 -6
- package/dist/services/Emailer/service.d.ts +3 -3
- package/dist/services/Operations/live.d.ts +1 -1
- package/dist/services/Operations/live.d.ts.map +1 -1
- package/dist/services/Operations/live.js +37 -39
- package/dist/services/Operations/service.d.ts +8 -8
- package/dist/services/Operations/service.d.ts.map +1 -1
- package/dist/services/Operations/service.js +12 -13
- package/dist/services/QueueMaker/errors.d.ts +3 -3
- package/dist/services/QueueMaker/errors.d.ts.map +1 -1
- package/dist/services/QueueMaker/errors.js +6 -7
- package/dist/services/QueueMaker/memQueue.d.ts +3 -3
- package/dist/services/QueueMaker/memQueue.js +16 -17
- package/dist/services/QueueMaker/sbqueue.d.ts +4 -4
- package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/services/QueueMaker/sbqueue.js +15 -16
- package/dist/services/Repository.d.ts +43 -44
- package/dist/services/Repository.d.ts.map +1 -1
- package/dist/services/Repository.js +17 -18
- package/dist/services/RepositoryBase.d.ts +15 -15
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +35 -37
- package/dist/services/RequestContextContainer.d.ts +14 -11
- package/dist/services/RequestContextContainer.d.ts.map +1 -1
- package/dist/services/RequestContextContainer.js +19 -18
- package/dist/services/Store/Cosmos.d.ts +3 -3
- package/dist/services/Store/Cosmos.d.ts.map +1 -1
- package/dist/services/Store/Cosmos.js +51 -54
- package/dist/services/Store/Disk.d.ts +3 -3
- package/dist/services/Store/Disk.d.ts.map +1 -1
- package/dist/services/Store/Disk.js +19 -20
- package/dist/services/Store/Memory.d.ts +5 -5
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +41 -45
- package/dist/services/Store/Redis.d.ts +3 -3
- package/dist/services/Store/Redis.d.ts.map +1 -1
- package/dist/services/Store/Redis.js +15 -17
- package/dist/services/Store/index.d.ts +1 -1
- package/dist/services/Store/index.d.ts.map +1 -1
- package/dist/services/Store/index.js +7 -8
- package/dist/services/Store/service.d.ts +8 -8
- package/dist/services/Store/service.d.ts.map +1 -1
- package/dist/services/Store/service.js +2 -2
- package/dist/services/Store/utils.d.ts +2 -2
- package/dist/services/Store/utils.d.ts.map +1 -1
- package/dist/services/Store/utils.js +21 -21
- package/dist/services/simpledb/cosmosdb.d.ts +5 -5
- package/dist/services/simpledb/cosmosdb.js +17 -19
- package/dist/services/simpledb/diskdb.d.ts +4 -4
- package/dist/services/simpledb/diskdb.js +9 -10
- package/dist/services/simpledb/memdb.d.ts +4 -4
- package/dist/services/simpledb/memdb.js +11 -13
- package/dist/services/simpledb/mongodb.d.ts +5 -5
- package/dist/services/simpledb/mongodb.js +14 -16
- package/dist/services/simpledb/redisdb.d.ts +4 -4
- package/dist/services/simpledb/redisdb.js +11 -12
- package/dist/services/simpledb/shared.d.ts +4 -4
- package/dist/services/simpledb/shared.js +6 -6
- package/dist/services/simpledb/simpledb.d.ts +6 -6
- package/dist/services/simpledb/simpledb.d.ts.map +1 -1
- package/dist/services/simpledb/simpledb.js +15 -16
- package/package.json +5 -25
- package/_cjs/api/express/schema/requestHandler.cjs +0 -172
- package/_cjs/api/express/schema/requestHandler.cjs.map +0 -1
- package/_cjs/api/routing.cjs +0 -278
- package/_cjs/api/routing.cjs.map +0 -1
- package/_src/api/express/schema/requestHandler.ts +0 -372
- package/_src/api/routing.ts +0 -660
- package/dist/api/express/schema/requestHandler.d.ts +0 -71
- package/dist/api/express/schema/requestHandler.d.ts.map +0 -1
- package/dist/api/express/schema/requestHandler.js +0 -140
- package/dist/api/routing.d.ts +0 -103
- package/dist/api/routing.d.ts.map +0 -1
- package/dist/api/routing.js +0 -265
package/_src/api/routing.ts
DELETED
|
@@ -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>>
|