@effect/platform 0.68.6 → 0.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HttpApiMiddleware/package.json +6 -0
- package/README.md +306 -233
- package/dist/cjs/Headers.js +7 -2
- package/dist/cjs/Headers.js.map +1 -1
- package/dist/cjs/HttpApi.js +90 -78
- package/dist/cjs/HttpApi.js.map +1 -1
- package/dist/cjs/HttpApiBuilder.js +243 -255
- package/dist/cjs/HttpApiBuilder.js.map +1 -1
- package/dist/cjs/HttpApiClient.js +64 -59
- package/dist/cjs/HttpApiClient.js.map +1 -1
- package/dist/cjs/HttpApiEndpoint.js +74 -109
- package/dist/cjs/HttpApiEndpoint.js.map +1 -1
- package/dist/cjs/HttpApiError.js +3 -4
- package/dist/cjs/HttpApiError.js.map +1 -1
- package/dist/cjs/HttpApiGroup.js +103 -100
- package/dist/cjs/HttpApiGroup.js.map +1 -1
- package/dist/cjs/HttpApiMiddleware.js +67 -0
- package/dist/cjs/HttpApiMiddleware.js.map +1 -0
- package/dist/cjs/HttpApiSchema.js +33 -7
- package/dist/cjs/HttpApiSchema.js.map +1 -1
- package/dist/cjs/HttpApiSecurity.js +2 -2
- package/dist/cjs/HttpApiSecurity.js.map +1 -1
- package/dist/cjs/HttpApiSwagger.js +3 -1
- package/dist/cjs/HttpApiSwagger.js.map +1 -1
- package/dist/cjs/HttpBody.js.map +1 -1
- package/dist/cjs/HttpIncomingMessage.js +5 -1
- package/dist/cjs/HttpIncomingMessage.js.map +1 -1
- package/dist/cjs/HttpServer.js +12 -1
- package/dist/cjs/HttpServer.js.map +1 -1
- package/dist/cjs/HttpServerRespondable.js +1 -1
- package/dist/cjs/HttpServerRespondable.js.map +1 -1
- package/dist/cjs/OpenApi.js +102 -63
- package/dist/cjs/OpenApi.js.map +1 -1
- package/dist/cjs/OpenApiJsonSchema.js +58 -47
- package/dist/cjs/OpenApiJsonSchema.js.map +1 -1
- package/dist/cjs/Transferable.js +2 -2
- package/dist/cjs/Transferable.js.map +1 -1
- package/dist/cjs/UrlParams.js +5 -1
- package/dist/cjs/UrlParams.js.map +1 -1
- package/dist/cjs/Worker.js.map +1 -1
- package/dist/cjs/WorkerError.js +1 -5
- package/dist/cjs/WorkerError.js.map +1 -1
- package/dist/cjs/WorkerRunner.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/internal/httpBody.js +1 -1
- package/dist/cjs/internal/httpBody.js.map +1 -1
- package/dist/cjs/internal/httpClientRequest.js.map +1 -1
- package/dist/cjs/internal/httpClientResponse.js +1 -1
- package/dist/cjs/internal/httpClientResponse.js.map +1 -1
- package/dist/cjs/internal/httpRouter.js +1 -1
- package/dist/cjs/internal/httpRouter.js.map +1 -1
- package/dist/cjs/internal/httpServer.js +7 -1
- package/dist/cjs/internal/httpServer.js.map +1 -1
- package/dist/cjs/internal/httpServerRequest.js +1 -1
- package/dist/cjs/internal/httpServerRequest.js.map +1 -1
- package/dist/cjs/internal/httpServerResponse.js.map +1 -1
- package/dist/cjs/internal/keyValueStore.js +1 -1
- package/dist/cjs/internal/keyValueStore.js.map +1 -1
- package/dist/cjs/internal/multipart.js +1 -1
- package/dist/cjs/internal/multipart.js.map +1 -1
- package/dist/cjs/internal/worker.js +6 -7
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/cjs/internal/workerRunner.js +3 -4
- package/dist/cjs/internal/workerRunner.js.map +1 -1
- package/dist/dts/Headers.d.ts +4 -6
- package/dist/dts/Headers.d.ts.map +1 -1
- package/dist/dts/HttpApi.d.ts +64 -140
- package/dist/dts/HttpApi.d.ts.map +1 -1
- package/dist/dts/HttpApiBuilder.d.ts +84 -167
- package/dist/dts/HttpApiBuilder.d.ts.map +1 -1
- package/dist/dts/HttpApiClient.d.ts +34 -11
- package/dist/dts/HttpApiClient.d.ts.map +1 -1
- package/dist/dts/HttpApiEndpoint.d.ts +119 -273
- package/dist/dts/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/dts/HttpApiError.d.ts +5 -2
- package/dist/dts/HttpApiError.d.ts.map +1 -1
- package/dist/dts/HttpApiGroup.d.ts +96 -194
- package/dist/dts/HttpApiGroup.d.ts.map +1 -1
- package/dist/dts/HttpApiMiddleware.d.ts +231 -0
- package/dist/dts/HttpApiMiddleware.d.ts.map +1 -0
- package/dist/dts/HttpApiSchema.d.ts +6 -2
- package/dist/dts/HttpApiSchema.d.ts.map +1 -1
- package/dist/dts/HttpApiSecurity.d.ts +1 -1
- package/dist/dts/HttpApiSecurity.d.ts.map +1 -1
- package/dist/dts/HttpApiSwagger.d.ts +2 -2
- package/dist/dts/HttpApiSwagger.d.ts.map +1 -1
- package/dist/dts/HttpBody.d.ts +2 -2
- package/dist/dts/HttpBody.d.ts.map +1 -1
- package/dist/dts/HttpClientRequest.d.ts +2 -2
- package/dist/dts/HttpClientRequest.d.ts.map +1 -1
- package/dist/dts/HttpClientResponse.d.ts +3 -3
- package/dist/dts/HttpClientResponse.d.ts.map +1 -1
- package/dist/dts/HttpIncomingMessage.d.ts +3 -3
- package/dist/dts/HttpIncomingMessage.d.ts.map +1 -1
- package/dist/dts/HttpRouter.d.ts +3 -3
- package/dist/dts/HttpRouter.d.ts.map +1 -1
- package/dist/dts/HttpServer.d.ts +15 -0
- package/dist/dts/HttpServer.d.ts.map +1 -1
- package/dist/dts/HttpServerRequest.d.ts +3 -3
- package/dist/dts/HttpServerRequest.d.ts.map +1 -1
- package/dist/dts/HttpServerRespondable.d.ts.map +1 -1
- package/dist/dts/HttpServerResponse.d.ts +2 -2
- package/dist/dts/HttpServerResponse.d.ts.map +1 -1
- package/dist/dts/KeyValueStore.d.ts +2 -2
- package/dist/dts/KeyValueStore.d.ts.map +1 -1
- package/dist/dts/Multipart.d.ts +3 -3
- package/dist/dts/Multipart.d.ts.map +1 -1
- package/dist/dts/OpenApi.d.ts +17 -39
- package/dist/dts/OpenApi.d.ts.map +1 -1
- package/dist/dts/OpenApiJsonSchema.d.ts +10 -5
- package/dist/dts/OpenApiJsonSchema.d.ts.map +1 -1
- package/dist/dts/Transferable.d.ts +4 -1
- package/dist/dts/Transferable.d.ts.map +1 -1
- package/dist/dts/UrlParams.d.ts +3 -6
- package/dist/dts/UrlParams.d.ts.map +1 -1
- package/dist/dts/Worker.d.ts +7 -8
- package/dist/dts/Worker.d.ts.map +1 -1
- package/dist/dts/WorkerError.d.ts +1 -1
- package/dist/dts/WorkerError.d.ts.map +1 -1
- package/dist/dts/WorkerRunner.d.ts +2 -3
- package/dist/dts/WorkerRunner.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/httpRouter.d.ts.map +1 -1
- package/dist/esm/Headers.js +7 -2
- package/dist/esm/Headers.js.map +1 -1
- package/dist/esm/HttpApi.js +88 -77
- package/dist/esm/HttpApi.js.map +1 -1
- package/dist/esm/HttpApiBuilder.js +236 -244
- package/dist/esm/HttpApiBuilder.js.map +1 -1
- package/dist/esm/HttpApiClient.js +64 -59
- package/dist/esm/HttpApiClient.js.map +1 -1
- package/dist/esm/HttpApiEndpoint.js +73 -106
- package/dist/esm/HttpApiEndpoint.js.map +1 -1
- package/dist/esm/HttpApiError.js +3 -4
- package/dist/esm/HttpApiError.js.map +1 -1
- package/dist/esm/HttpApiGroup.js +102 -99
- package/dist/esm/HttpApiGroup.js.map +1 -1
- package/dist/esm/HttpApiMiddleware.js +56 -0
- package/dist/esm/HttpApiMiddleware.js.map +1 -0
- package/dist/esm/HttpApiSchema.js +31 -5
- package/dist/esm/HttpApiSchema.js.map +1 -1
- package/dist/esm/HttpApiSecurity.js +1 -1
- package/dist/esm/HttpApiSecurity.js.map +1 -1
- package/dist/esm/HttpApiSwagger.js +4 -2
- package/dist/esm/HttpApiSwagger.js.map +1 -1
- package/dist/esm/HttpBody.js.map +1 -1
- package/dist/esm/HttpIncomingMessage.js +4 -1
- package/dist/esm/HttpIncomingMessage.js.map +1 -1
- package/dist/esm/HttpServer.js +11 -0
- package/dist/esm/HttpServer.js.map +1 -1
- package/dist/esm/HttpServerRespondable.js +1 -1
- package/dist/esm/HttpServerRespondable.js.map +1 -1
- package/dist/esm/OpenApi.js +97 -59
- package/dist/esm/OpenApi.js.map +1 -1
- package/dist/esm/OpenApiJsonSchema.js +56 -46
- package/dist/esm/OpenApiJsonSchema.js.map +1 -1
- package/dist/esm/Transferable.js +2 -2
- package/dist/esm/Transferable.js.map +1 -1
- package/dist/esm/UrlParams.js +4 -1
- package/dist/esm/UrlParams.js.map +1 -1
- package/dist/esm/Worker.js.map +1 -1
- package/dist/esm/WorkerError.js +1 -4
- package/dist/esm/WorkerError.js.map +1 -1
- package/dist/esm/WorkerRunner.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/httpBody.js +1 -1
- package/dist/esm/internal/httpBody.js.map +1 -1
- package/dist/esm/internal/httpClientRequest.js.map +1 -1
- package/dist/esm/internal/httpClientResponse.js +1 -1
- package/dist/esm/internal/httpClientResponse.js.map +1 -1
- package/dist/esm/internal/httpRouter.js +1 -1
- package/dist/esm/internal/httpRouter.js.map +1 -1
- package/dist/esm/internal/httpServer.js +6 -0
- package/dist/esm/internal/httpServer.js.map +1 -1
- package/dist/esm/internal/httpServerRequest.js +1 -1
- package/dist/esm/internal/httpServerRequest.js.map +1 -1
- package/dist/esm/internal/httpServerResponse.js.map +1 -1
- package/dist/esm/internal/keyValueStore.js +1 -1
- package/dist/esm/internal/keyValueStore.js.map +1 -1
- package/dist/esm/internal/multipart.js +1 -1
- package/dist/esm/internal/multipart.js.map +1 -1
- package/dist/esm/internal/worker.js +6 -7
- package/dist/esm/internal/worker.js.map +1 -1
- package/dist/esm/internal/workerRunner.js +3 -4
- package/dist/esm/internal/workerRunner.js.map +1 -1
- package/package.json +10 -3
- package/src/Headers.ts +12 -4
- package/src/HttpApi.ts +183 -258
- package/src/HttpApiBuilder.ts +532 -481
- package/src/HttpApiClient.ts +163 -112
- package/src/HttpApiEndpoint.ts +443 -564
- package/src/HttpApiError.ts +4 -6
- package/src/HttpApiGroup.ts +277 -325
- package/src/HttpApiMiddleware.ts +318 -0
- package/src/HttpApiSchema.ts +39 -2
- package/src/HttpApiSecurity.ts +1 -1
- package/src/HttpApiSwagger.ts +3 -3
- package/src/HttpBody.ts +2 -2
- package/src/HttpClientRequest.ts +2 -2
- package/src/HttpClientResponse.ts +3 -3
- package/src/HttpIncomingMessage.ts +3 -3
- package/src/HttpRouter.ts +3 -3
- package/src/HttpServer.ts +21 -0
- package/src/HttpServerRequest.ts +3 -3
- package/src/HttpServerRespondable.ts +1 -1
- package/src/HttpServerResponse.ts +2 -2
- package/src/KeyValueStore.ts +2 -2
- package/src/Multipart.ts +3 -3
- package/src/OpenApi.ts +113 -104
- package/src/OpenApiJsonSchema.ts +67 -53
- package/src/Transferable.ts +2 -2
- package/src/UrlParams.ts +3 -3
- package/src/Worker.ts +7 -8
- package/src/WorkerError.ts +1 -1
- package/src/WorkerRunner.ts +2 -3
- package/src/index.ts +5 -0
- package/src/internal/httpBody.ts +2 -2
- package/src/internal/httpClientRequest.ts +2 -2
- package/src/internal/httpClientResponse.ts +3 -3
- package/src/internal/httpRouter.ts +2 -2
- package/src/internal/httpServer.ts +13 -0
- package/src/internal/httpServerRequest.ts +3 -3
- package/src/internal/httpServerResponse.ts +2 -2
- package/src/internal/keyValueStore.ts +1 -1
- package/src/internal/multipart.ts +3 -3
- package/src/internal/worker.ts +6 -7
- package/src/internal/workerRunner.ts +3 -4
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.toWebHandler = exports.serve = exports.securitySetCookie = exports.securityDecode = exports.
|
|
7
|
-
var AST = _interopRequireWildcard(require("@effect/schema/AST"));
|
|
8
|
-
var ParseResult = _interopRequireWildcard(require("@effect/schema/ParseResult"));
|
|
9
|
-
var Schema = _interopRequireWildcard(require("@effect/schema/Schema"));
|
|
6
|
+
exports.toWebHandler = exports.serve = exports.securitySetCookie = exports.securityDecode = exports.middlewareScoped = exports.middlewareOpenApi = exports.middlewareCors = exports.middleware = exports.httpApp = exports.group = exports.api = exports.Router = exports.Middleware = exports.HandlersTypeId = void 0;
|
|
10
7
|
var Chunk = _interopRequireWildcard(require("effect/Chunk"));
|
|
11
8
|
var Context = _interopRequireWildcard(require("effect/Context"));
|
|
12
9
|
var Effect = _interopRequireWildcard(require("effect/Effect"));
|
|
@@ -14,14 +11,19 @@ var Encoding = _interopRequireWildcard(require("effect/Encoding"));
|
|
|
14
11
|
var FiberRef = _interopRequireWildcard(require("effect/FiberRef"));
|
|
15
12
|
var _Function = require("effect/Function");
|
|
16
13
|
var _GlobalValue = require("effect/GlobalValue");
|
|
14
|
+
var HashMap = _interopRequireWildcard(require("effect/HashMap"));
|
|
15
|
+
var HashSet = _interopRequireWildcard(require("effect/HashSet"));
|
|
17
16
|
var Layer = _interopRequireWildcard(require("effect/Layer"));
|
|
17
|
+
var ManagedRuntime = _interopRequireWildcard(require("effect/ManagedRuntime"));
|
|
18
18
|
var Option = _interopRequireWildcard(require("effect/Option"));
|
|
19
|
+
var ParseResult = _interopRequireWildcard(require("effect/ParseResult"));
|
|
19
20
|
var _Pipeable = require("effect/Pipeable");
|
|
20
21
|
var Redacted = _interopRequireWildcard(require("effect/Redacted"));
|
|
22
|
+
var Schema = _interopRequireWildcard(require("effect/Schema"));
|
|
21
23
|
var _Unify = require("effect/Unify");
|
|
22
24
|
var HttpApi = _interopRequireWildcard(require("./HttpApi.js"));
|
|
23
|
-
var HttpApiEndpoint = _interopRequireWildcard(require("./HttpApiEndpoint.js"));
|
|
24
25
|
var _HttpApiError = require("./HttpApiError.js");
|
|
26
|
+
var HttpApiMiddleware = _interopRequireWildcard(require("./HttpApiMiddleware.js"));
|
|
25
27
|
var HttpApiSchema = _interopRequireWildcard(require("./HttpApiSchema.js"));
|
|
26
28
|
var HttpApp = _interopRequireWildcard(require("./HttpApp.js"));
|
|
27
29
|
var HttpMethod = _interopRequireWildcard(require("./HttpMethod.js"));
|
|
@@ -44,6 +46,17 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
44
46
|
* @category router
|
|
45
47
|
*/
|
|
46
48
|
class Router extends /*#__PURE__*/HttpRouter.Tag("@effect/platform/HttpApiBuilder/Router")() {}
|
|
49
|
+
/**
|
|
50
|
+
* Create a top-level `HttpApi` layer.
|
|
51
|
+
*
|
|
52
|
+
* @since 1.0.0
|
|
53
|
+
* @category constructors
|
|
54
|
+
*/
|
|
55
|
+
exports.Router = Router;
|
|
56
|
+
const api = api => Layer.effect(HttpApi.Api, Effect.map(Effect.context(), context => ({
|
|
57
|
+
api: api,
|
|
58
|
+
context
|
|
59
|
+
})));
|
|
47
60
|
/**
|
|
48
61
|
* Build an `HttpApp` from an `HttpApi` instance, and serve it using an
|
|
49
62
|
* `HttpServer`.
|
|
@@ -54,8 +67,8 @@ class Router extends /*#__PURE__*/HttpRouter.Tag("@effect/platform/HttpApiBuilde
|
|
|
54
67
|
* @since 1.0.0
|
|
55
68
|
* @category constructors
|
|
56
69
|
*/
|
|
57
|
-
exports.
|
|
58
|
-
const serve = middleware => httpApp.pipe(Effect.map(HttpServer.serve(middleware)), Layer.unwrapEffect, Layer.provide(Router.Live));
|
|
70
|
+
exports.api = api;
|
|
71
|
+
const serve = middleware => httpApp.pipe(Effect.map(app => HttpServer.serve(app, middleware)), Layer.unwrapEffect, Layer.provide(Router.Live));
|
|
59
72
|
/**
|
|
60
73
|
* Construct an `HttpApp` from an `HttpApi` instance.
|
|
61
74
|
*
|
|
@@ -64,12 +77,16 @@ const serve = middleware => httpApp.pipe(Effect.map(HttpServer.serve(middleware)
|
|
|
64
77
|
*/
|
|
65
78
|
exports.serve = serve;
|
|
66
79
|
const httpApp = exports.httpApp = /*#__PURE__*/Effect.gen(function* () {
|
|
67
|
-
const
|
|
68
|
-
|
|
80
|
+
const {
|
|
81
|
+
api,
|
|
82
|
+
context
|
|
83
|
+
} = yield* HttpApi.Api;
|
|
84
|
+
const middleware = makeMiddlewareMap(api.middlewares, context);
|
|
85
|
+
const router = applyMiddleware(middleware, yield* Router.router);
|
|
69
86
|
const apiMiddleware = yield* Effect.serviceOption(Middleware);
|
|
70
87
|
const errorSchema = makeErrorSchema(api);
|
|
71
88
|
const encodeError = Schema.encodeUnknown(errorSchema);
|
|
72
|
-
return router.pipe(apiMiddleware._tag === "Some" ? apiMiddleware.value : _Function.identity, Effect.catchAll(error => Effect.matchEffect(encodeError(error), {
|
|
89
|
+
return router.pipe(apiMiddleware._tag === "Some" ? apiMiddleware.value : _Function.identity, Effect.catchAll(error => Effect.matchEffect(Effect.provide(encodeError(error), context), {
|
|
73
90
|
onFailure: () => Effect.die(error),
|
|
74
91
|
onSuccess: Effect.succeed
|
|
75
92
|
})));
|
|
@@ -80,51 +97,45 @@ const httpApp = exports.httpApp = /*#__PURE__*/Effect.gen(function* () {
|
|
|
80
97
|
* @since 1.0.0
|
|
81
98
|
* @category constructors
|
|
82
99
|
* @example
|
|
83
|
-
* import { HttpApi } from "@effect/platform"
|
|
84
|
-
* import {
|
|
85
|
-
*
|
|
86
|
-
*
|
|
100
|
+
* import { HttpApi, HttpApiBuilder, HttpServer } from "@effect/platform"
|
|
101
|
+
* import { Layer } from "effect"
|
|
102
|
+
*
|
|
103
|
+
* class MyApi extends HttpApi.empty {}
|
|
87
104
|
*
|
|
88
|
-
* const
|
|
105
|
+
* const MyApiLive = HttpApiBuilder.api(MyApi)
|
|
89
106
|
*
|
|
90
|
-
* const
|
|
107
|
+
* const { dispose, handler } = HttpApiBuilder.toWebHandler(
|
|
91
108
|
* Layer.mergeAll(
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* HttpPlatform.layer,
|
|
95
|
-
* Etag.layerWeak
|
|
96
|
-
* ).pipe(
|
|
97
|
-
* Layer.provideMerge(NodeContext.layer)
|
|
109
|
+
* MyApiLive,
|
|
110
|
+
* HttpServer.layerContext
|
|
98
111
|
* )
|
|
99
112
|
* )
|
|
100
|
-
*
|
|
101
|
-
* const handler = HttpApiBuilder.toWebHandler(runtime, HttpMiddleware.logger)
|
|
102
113
|
*/
|
|
103
|
-
const toWebHandler = (
|
|
114
|
+
const toWebHandler = (layer, options) => {
|
|
115
|
+
const runtime = ManagedRuntime.make(Layer.merge(layer, Router.Live), options?.memoMap);
|
|
116
|
+
let handlerCached;
|
|
104
117
|
const handlerPromise = httpApp.pipe(Effect.bindTo("httpApp"), Effect.bind("runtime", () => runtime.runtimeEffect), Effect.map(({
|
|
105
118
|
httpApp,
|
|
106
119
|
runtime
|
|
107
|
-
}) => HttpApp.toWebHandlerRuntime(runtime)(middleware ? middleware(httpApp) : httpApp)),
|
|
108
|
-
|
|
120
|
+
}) => HttpApp.toWebHandlerRuntime(runtime)(options?.middleware ? options.middleware(httpApp) : httpApp)), Effect.tap(handler => {
|
|
121
|
+
handlerCached = handler;
|
|
122
|
+
}), runtime.runPromise);
|
|
123
|
+
function handler(request) {
|
|
124
|
+
if (handlerCached !== undefined) {
|
|
125
|
+
return handlerCached(request);
|
|
126
|
+
}
|
|
127
|
+
return handlerPromise.then(handler => handler(request));
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
handler,
|
|
131
|
+
dispose: runtime.dispose
|
|
132
|
+
};
|
|
109
133
|
};
|
|
110
|
-
/**
|
|
111
|
-
* Build a root level `Layer` from an `HttpApi` instance.
|
|
112
|
-
*
|
|
113
|
-
* The `Layer` will provide the `HttpApi` service, and will require the
|
|
114
|
-
* implementation for all the `HttpApiGroup`'s contained in the `HttpApi`.
|
|
115
|
-
*
|
|
116
|
-
* The resulting `Layer` can be provided to the `HttpApiBuilder.serve` layer.
|
|
117
|
-
*
|
|
118
|
-
* @since 1.0.0
|
|
119
|
-
* @category constructors
|
|
120
|
-
*/
|
|
121
|
-
exports.toWebHandler = toWebHandler;
|
|
122
|
-
const api = self => Layer.succeed(HttpApi.HttpApi, self);
|
|
123
134
|
/**
|
|
124
135
|
* @since 1.0.0
|
|
125
136
|
* @category handlers
|
|
126
137
|
*/
|
|
127
|
-
exports.
|
|
138
|
+
exports.toWebHandler = toWebHandler;
|
|
128
139
|
const HandlersTypeId = exports.HandlersTypeId = /*#__PURE__*/Symbol.for("@effect/platform/HttpApiBuilder/Handlers");
|
|
129
140
|
const HandlersProto = {
|
|
130
141
|
[HandlersTypeId]: {
|
|
@@ -132,6 +143,28 @@ const HandlersProto = {
|
|
|
132
143
|
},
|
|
133
144
|
pipe() {
|
|
134
145
|
return (0, _Pipeable.pipeArguments)(this, arguments);
|
|
146
|
+
},
|
|
147
|
+
handle(name, handler) {
|
|
148
|
+
const endpoint = HashMap.unsafeGet(this.group.endpoints, name);
|
|
149
|
+
return makeHandlers({
|
|
150
|
+
group: this.group,
|
|
151
|
+
handlers: Chunk.append(this.handlers, {
|
|
152
|
+
endpoint,
|
|
153
|
+
handler,
|
|
154
|
+
withFullResponse: false
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
handleRaw(name, handler) {
|
|
159
|
+
const endpoint = HashMap.unsafeGet(this.group.endpoints, name);
|
|
160
|
+
return makeHandlers({
|
|
161
|
+
group: this.group,
|
|
162
|
+
handlers: Chunk.append(this.handlers, {
|
|
163
|
+
endpoint,
|
|
164
|
+
handler,
|
|
165
|
+
withFullResponse: true
|
|
166
|
+
})
|
|
167
|
+
});
|
|
135
168
|
}
|
|
136
169
|
};
|
|
137
170
|
const makeHandlers = options => {
|
|
@@ -141,88 +174,191 @@ const makeHandlers = options => {
|
|
|
141
174
|
return self;
|
|
142
175
|
};
|
|
143
176
|
/**
|
|
144
|
-
* Create a `Layer` that will implement all the endpoints in an `
|
|
177
|
+
* Create a `Layer` that will implement all the endpoints in an `HttpApi`.
|
|
145
178
|
*
|
|
146
179
|
* An unimplemented `Handlers` instance is passed to the `build` function, which
|
|
147
180
|
* you can use to add handlers to the group.
|
|
148
181
|
*
|
|
149
|
-
* You can implement endpoints using the `
|
|
182
|
+
* You can implement endpoints using the `handlers.handle` api.
|
|
150
183
|
*
|
|
151
184
|
* @since 1.0.0
|
|
152
185
|
* @category handlers
|
|
153
186
|
*/
|
|
154
187
|
const group = (api, groupName, build) => Router.use(router => Effect.gen(function* () {
|
|
155
188
|
const context = yield* Effect.context();
|
|
156
|
-
const group =
|
|
157
|
-
if (group._tag === "None") {
|
|
158
|
-
throw new Error(`Group "${groupName}" not found in API`);
|
|
159
|
-
}
|
|
189
|
+
const group = HashMap.unsafeGet(api.groups, groupName);
|
|
160
190
|
const result = build(makeHandlers({
|
|
161
|
-
group
|
|
191
|
+
group,
|
|
162
192
|
handlers: Chunk.empty()
|
|
163
193
|
}));
|
|
164
194
|
const handlers = Effect.isEffect(result) ? yield* result : result;
|
|
195
|
+
const groupMiddleware = makeMiddlewareMap(group.middlewares, context);
|
|
165
196
|
const routes = [];
|
|
166
197
|
for (const item of handlers.handlers) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
routes.push(handlerToRoute(item.endpoint, function (request) {
|
|
174
|
-
return Effect.mapInputContext(item.handler(request), input => Context.merge(context, input));
|
|
175
|
-
}, item.withFullResponse));
|
|
176
|
-
}
|
|
198
|
+
const middleware = makeMiddlewareMap(item.endpoint.middlewares, context, groupMiddleware);
|
|
199
|
+
routes.push(handlerToRoute(item.endpoint, middleware, function (request) {
|
|
200
|
+
return Effect.mapInputContext(item.handler(request), input => Context.merge(context, input));
|
|
201
|
+
}, item.withFullResponse));
|
|
177
202
|
}
|
|
178
203
|
yield* router.concat(HttpRouter.fromIterable(routes));
|
|
179
204
|
}));
|
|
180
|
-
|
|
181
|
-
* Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
|
|
182
|
-
*
|
|
183
|
-
* @since 1.0.0
|
|
184
|
-
* @category handlers
|
|
185
|
-
*/
|
|
205
|
+
// internal
|
|
186
206
|
exports.group = group;
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
207
|
+
const requestPayload = (request, urlParams, isMultipart) => HttpMethod.hasBody(request.method) ? isMultipart ? Effect.orDie(request.multipart) : Effect.orDie(request.json) : Effect.succeed(urlParams);
|
|
208
|
+
const makeMiddlewareMap = (middleware, context, initial) => {
|
|
209
|
+
const map = new Map(initial);
|
|
210
|
+
HashSet.forEach(middleware, tag => {
|
|
211
|
+
map.set(tag.key, {
|
|
212
|
+
tag,
|
|
213
|
+
effect: Context.unsafeGet(context, tag)
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
return map;
|
|
217
|
+
};
|
|
218
|
+
const handlerToRoute = (endpoint_, middleware, handler, isFullResponse) => {
|
|
219
|
+
const endpoint = endpoint_;
|
|
220
|
+
const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown);
|
|
221
|
+
const isMultipart = endpoint.payloadSchema.pipe(Option.map(schema => HttpApiSchema.getMultipart(schema.ast)), Option.getOrElse(() => false));
|
|
222
|
+
const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown);
|
|
223
|
+
const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown);
|
|
224
|
+
const decodeUrlParams = Option.map(endpoint.urlParamsSchema, Schema.decodeUnknown);
|
|
225
|
+
const encodeSuccess = Schema.encode(makeSuccessSchema(endpoint.successSchema));
|
|
226
|
+
return HttpRouter.makeRoute(endpoint.method, endpoint.path, applyMiddleware(middleware, Effect.withFiberRuntime(fiber => {
|
|
227
|
+
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
228
|
+
const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest);
|
|
229
|
+
const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext);
|
|
230
|
+
const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams);
|
|
231
|
+
return (decodePath._tag === "Some" ? decodePath.value(routeContext.params) : Effect.succeed(routeContext.params)).pipe(Effect.bindTo("pathParams"), decodePayload._tag === "Some" ? Effect.bind("payload", _ => Effect.flatMap(requestPayload(request, urlParams, isMultipart), decodePayload.value)) : _Function.identity, decodeHeaders._tag === "Some" ? Effect.bind("headers", _ => decodeHeaders.value(request.headers)) : _Function.identity, decodeUrlParams._tag === "Some" ? Effect.bind("urlParams", _ => decodeUrlParams.value(urlParams)) : _Function.identity, Effect.flatMap(input => {
|
|
232
|
+
const request = {
|
|
233
|
+
path: input.pathParams
|
|
234
|
+
};
|
|
235
|
+
if ("payload" in input) {
|
|
236
|
+
request.payload = input.payload;
|
|
237
|
+
}
|
|
238
|
+
if ("headers" in input) {
|
|
239
|
+
request.headers = input.headers;
|
|
240
|
+
}
|
|
241
|
+
if ("urlParams" in input) {
|
|
242
|
+
request.urlParams = input.urlParams;
|
|
243
|
+
}
|
|
244
|
+
return handler(request);
|
|
245
|
+
}), isFullResponse ? _Function.identity : Effect.flatMap(encodeSuccess), Effect.catchIf(ParseResult.isParseError, _HttpApiError.HttpApiDecodeError.refailParseError));
|
|
246
|
+
})));
|
|
247
|
+
};
|
|
248
|
+
const applyMiddleware = (middleware, handler) => {
|
|
249
|
+
for (const entry of middleware.values()) {
|
|
250
|
+
const effect = HttpApiMiddleware.SecurityTypeId in entry.tag ? makeSecurityMiddleware(entry) : entry.effect;
|
|
251
|
+
if (entry.tag.optional) {
|
|
252
|
+
const previous = handler;
|
|
253
|
+
handler = Effect.matchEffect(effect, {
|
|
254
|
+
onFailure: () => previous,
|
|
255
|
+
onSuccess: entry.tag.provides !== undefined ? value => Effect.provideService(previous, entry.tag.provides, value) : _ => previous
|
|
256
|
+
});
|
|
257
|
+
} else {
|
|
258
|
+
handler = entry.tag.provides !== undefined ? Effect.provideServiceEffect(handler, entry.tag.provides, effect) : Effect.zipRight(effect, handler);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return handler;
|
|
262
|
+
};
|
|
263
|
+
const securityMiddlewareCache = /*#__PURE__*/(0, _GlobalValue.globalValue)("securityMiddlewareCache", () => new WeakMap());
|
|
264
|
+
const makeSecurityMiddleware = entry => {
|
|
265
|
+
if (securityMiddlewareCache.has(entry.tag)) {
|
|
266
|
+
return securityMiddlewareCache.get(entry.tag);
|
|
191
267
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
268
|
+
let effect;
|
|
269
|
+
for (const [key, security] of Object.entries(entry.tag.security)) {
|
|
270
|
+
const decode = securityDecode(security);
|
|
271
|
+
const handler = entry.effect[key];
|
|
272
|
+
const middleware = Effect.flatMap(decode, handler);
|
|
273
|
+
effect = effect === undefined ? middleware : Effect.catchAll(effect, () => middleware);
|
|
274
|
+
}
|
|
275
|
+
if (effect === undefined) {
|
|
276
|
+
effect = Effect.void;
|
|
277
|
+
}
|
|
278
|
+
securityMiddlewareCache.set(entry.tag, effect);
|
|
279
|
+
return effect;
|
|
280
|
+
};
|
|
281
|
+
const responseSchema = /*#__PURE__*/Schema.declare(HttpServerResponse.isServerResponse);
|
|
282
|
+
const makeSuccessSchema = schema => {
|
|
283
|
+
const schemas = new Set();
|
|
284
|
+
HttpApiSchema.deunionize(schemas, schema);
|
|
285
|
+
return Schema.Union(...Array.from(schemas, toResponseSuccess));
|
|
286
|
+
};
|
|
287
|
+
const makeErrorSchema = api => {
|
|
288
|
+
const schemas = new Set();
|
|
289
|
+
HttpApiSchema.deunionize(schemas, api.errorSchema);
|
|
290
|
+
HashMap.forEach(api.groups, group => {
|
|
291
|
+
HashMap.forEach(group.endpoints, endpoint => {
|
|
292
|
+
HttpApiSchema.deunionize(schemas, endpoint.errorSchema);
|
|
293
|
+
});
|
|
294
|
+
HttpApiSchema.deunionize(schemas, group.errorSchema);
|
|
201
295
|
});
|
|
296
|
+
return Schema.Union(...Array.from(schemas, toResponseError));
|
|
202
297
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
298
|
+
const decodeForbidden = (_, __, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema"));
|
|
299
|
+
const toResponseSchema = getStatus => {
|
|
300
|
+
const cache = new WeakMap();
|
|
301
|
+
const schemaToResponse = (data, _, ast) => {
|
|
302
|
+
const isEmpty = HttpApiSchema.isVoid(ast.to);
|
|
303
|
+
const status = getStatus(ast.to);
|
|
304
|
+
if (isEmpty) {
|
|
305
|
+
return HttpServerResponse.empty({
|
|
306
|
+
status
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
const encoding = HttpApiSchema.getEncoding(ast.to);
|
|
310
|
+
switch (encoding.kind) {
|
|
311
|
+
case "Json":
|
|
312
|
+
{
|
|
313
|
+
return Effect.mapError(HttpServerResponse.json(data, {
|
|
314
|
+
status,
|
|
315
|
+
contentType: encoding.contentType
|
|
316
|
+
}), error => new ParseResult.Type(ast, error, "Could not encode to JSON"));
|
|
317
|
+
}
|
|
318
|
+
case "Text":
|
|
319
|
+
{
|
|
320
|
+
return ParseResult.succeed(HttpServerResponse.text(data, {
|
|
321
|
+
status,
|
|
322
|
+
contentType: encoding.contentType
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
case "Uint8Array":
|
|
326
|
+
{
|
|
327
|
+
return ParseResult.succeed(HttpServerResponse.uint8Array(data, {
|
|
328
|
+
status,
|
|
329
|
+
contentType: encoding.contentType
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
case "UrlParams":
|
|
333
|
+
{
|
|
334
|
+
return ParseResult.succeed(HttpServerResponse.urlParams(data, {
|
|
335
|
+
status,
|
|
336
|
+
contentType: encoding.contentType
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
return schema => {
|
|
342
|
+
if (cache.has(schema.ast)) {
|
|
343
|
+
return cache.get(schema.ast);
|
|
344
|
+
}
|
|
345
|
+
const transform = Schema.transformOrFail(responseSchema, schema, {
|
|
346
|
+
decode: decodeForbidden,
|
|
347
|
+
encode: schemaToResponse
|
|
348
|
+
});
|
|
349
|
+
cache.set(transform.ast, transform);
|
|
350
|
+
return transform;
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
const toResponseSuccess = /*#__PURE__*/toResponseSchema(HttpApiSchema.getStatusSuccessAST);
|
|
354
|
+
const toResponseError = /*#__PURE__*/toResponseSchema(HttpApiSchema.getStatusErrorAST);
|
|
355
|
+
// ----------------------------------------------------------------------------
|
|
356
|
+
// Global middleware
|
|
357
|
+
// ----------------------------------------------------------------------------
|
|
221
358
|
/**
|
|
222
359
|
* @since 1.0.0
|
|
223
360
|
* @category middleware
|
|
224
361
|
*/
|
|
225
|
-
exports.middleware = middleware;
|
|
226
362
|
class Middleware extends /*#__PURE__*/Context.Tag("@effect/platform/HttpApiBuilder/Middleware")() {}
|
|
227
363
|
exports.Middleware = Middleware;
|
|
228
364
|
const middlewareAdd = middleware => Effect.map(Effect.context(), context => {
|
|
@@ -239,7 +375,7 @@ const middlewareAddNoContext = middleware => Effect.map(Effect.serviceOption(Mid
|
|
|
239
375
|
* @since 1.0.0
|
|
240
376
|
* @category middleware
|
|
241
377
|
*/
|
|
242
|
-
const
|
|
378
|
+
const middleware = (...args) => {
|
|
243
379
|
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
244
380
|
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
245
381
|
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
@@ -253,8 +389,8 @@ const middlewareLayer = (...args) => {
|
|
|
253
389
|
* @since 1.0.0
|
|
254
390
|
* @category middleware
|
|
255
391
|
*/
|
|
256
|
-
exports.
|
|
257
|
-
const
|
|
392
|
+
exports.middleware = middleware;
|
|
393
|
+
const middlewareScoped = (...args) => {
|
|
258
394
|
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
259
395
|
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
260
396
|
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
@@ -267,8 +403,8 @@ const middlewareLayerScoped = (...args) => {
|
|
|
267
403
|
* @since 1.0.0
|
|
268
404
|
* @category middleware
|
|
269
405
|
*/
|
|
270
|
-
exports.
|
|
271
|
-
const middlewareCors = options =>
|
|
406
|
+
exports.middlewareScoped = middlewareScoped;
|
|
407
|
+
const middlewareCors = options => middleware(HttpMiddleware.cors(options));
|
|
272
408
|
/**
|
|
273
409
|
* A middleware that adds an openapi.json endpoint to the API.
|
|
274
410
|
*
|
|
@@ -277,7 +413,9 @@ const middlewareCors = options => middlewareLayer(HttpMiddleware.cors(options));
|
|
|
277
413
|
*/
|
|
278
414
|
exports.middlewareCors = middlewareCors;
|
|
279
415
|
const middlewareOpenApi = options => Router.use(router => Effect.gen(function* () {
|
|
280
|
-
const
|
|
416
|
+
const {
|
|
417
|
+
api
|
|
418
|
+
} = yield* HttpApi.Api;
|
|
281
419
|
const spec = OpenApi.fromApi(api);
|
|
282
420
|
const response = yield* HttpServerResponse.json(spec).pipe(Effect.orDie);
|
|
283
421
|
yield* router.get(options?.path ?? "/openapi.json", Effect.succeed(response));
|
|
@@ -286,7 +424,7 @@ exports.middlewareOpenApi = middlewareOpenApi;
|
|
|
286
424
|
const bearerLen = `Bearer `.length;
|
|
287
425
|
/**
|
|
288
426
|
* @since 1.0.0
|
|
289
|
-
* @category
|
|
427
|
+
* @category security
|
|
290
428
|
*/
|
|
291
429
|
const securityDecode = self => {
|
|
292
430
|
switch (self._tag) {
|
|
@@ -333,9 +471,9 @@ const securityDecode = self => {
|
|
|
333
471
|
* You can use this api before returning a response from an endpoint handler.
|
|
334
472
|
*
|
|
335
473
|
* ```ts
|
|
336
|
-
*
|
|
474
|
+
* handlers.handle(
|
|
337
475
|
* "authenticate",
|
|
338
|
-
* (_) =>
|
|
476
|
+
* (_) => HttpApiBuilder.securitySetCookie(security, "secret123")
|
|
339
477
|
* )
|
|
340
478
|
* ```
|
|
341
479
|
*
|
|
@@ -351,155 +489,5 @@ const securitySetCookie = (self, value, options) => {
|
|
|
351
489
|
...options
|
|
352
490
|
})));
|
|
353
491
|
};
|
|
354
|
-
/**
|
|
355
|
-
* Make a middleware from an `HttpApiSecurity` instance, that can be used when
|
|
356
|
-
* constructing a `Handlers` group.
|
|
357
|
-
*
|
|
358
|
-
* @since 1.0.0
|
|
359
|
-
* @category middleware
|
|
360
|
-
* @example
|
|
361
|
-
* import { HttpApiBuilder, HttpApiSecurity } from "@effect/platform"
|
|
362
|
-
* import { Schema } from "@effect/schema"
|
|
363
|
-
* import { Context, Effect, Redacted } from "effect"
|
|
364
|
-
*
|
|
365
|
-
* class User extends Schema.Class<User>("User")({
|
|
366
|
-
* id: Schema.Number
|
|
367
|
-
* }) {}
|
|
368
|
-
*
|
|
369
|
-
* class CurrentUser extends Context.Tag("CurrentUser")<CurrentUser, User>() {}
|
|
370
|
-
*
|
|
371
|
-
* class Accounts extends Context.Tag("Accounts")<Accounts, {
|
|
372
|
-
* readonly findUserByAccessToken: (accessToken: string) => Effect.Effect<User>
|
|
373
|
-
* }>() {}
|
|
374
|
-
*
|
|
375
|
-
* const securityMiddleware = Effect.gen(function*() {
|
|
376
|
-
* const accounts = yield* Accounts
|
|
377
|
-
* return HttpApiBuilder.middlewareSecurity(
|
|
378
|
-
* HttpApiSecurity.bearer,
|
|
379
|
-
* CurrentUser,
|
|
380
|
-
* (token) => accounts.findUserByAccessToken(Redacted.value(token))
|
|
381
|
-
* )
|
|
382
|
-
* })
|
|
383
|
-
*/
|
|
384
492
|
exports.securitySetCookie = securitySetCookie;
|
|
385
|
-
const middlewareSecurity = (self, tag, f) => middleware(Effect.provideServiceEffect(tag, Effect.flatMap(securityDecode(self), f)));
|
|
386
|
-
/**
|
|
387
|
-
* Make a middleware from an `HttpApiSecurity` instance, that can be used when
|
|
388
|
-
* constructing a `Handlers` group.
|
|
389
|
-
*
|
|
390
|
-
* This version does not supply any context to the handlers.
|
|
391
|
-
*
|
|
392
|
-
* @since 1.0.0
|
|
393
|
-
* @category middleware
|
|
394
|
-
*/
|
|
395
|
-
exports.middlewareSecurity = middlewareSecurity;
|
|
396
|
-
const middlewareSecurityVoid = (self, f) => middleware(httpApp => securityDecode(self).pipe(Effect.flatMap(f), Effect.zipRight(httpApp)));
|
|
397
|
-
// internal
|
|
398
|
-
exports.middlewareSecurityVoid = middlewareSecurityVoid;
|
|
399
|
-
const requestPayload = (request, urlParams, isMultipart) => HttpMethod.hasBody(request.method) ? isMultipart ? Effect.orDie(request.multipart) : Effect.orDie(request.json) : Effect.succeed(urlParams);
|
|
400
|
-
const handlerToRoute = (endpoint, handler, isFullResponse) => {
|
|
401
|
-
const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown);
|
|
402
|
-
const isMultipart = endpoint.payloadSchema.pipe(Option.map(schema => HttpApiSchema.getMultipart(schema.ast)), Option.getOrElse(() => false));
|
|
403
|
-
const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown);
|
|
404
|
-
const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown);
|
|
405
|
-
const encoding = HttpApiSchema.getEncoding(endpoint.successSchema.ast);
|
|
406
|
-
const successStatus = HttpApiSchema.getStatusSuccess(endpoint.successSchema);
|
|
407
|
-
const encodeSuccess = Option.map(HttpApiEndpoint.schemaSuccess(endpoint), schema => {
|
|
408
|
-
const encode = Schema.encodeUnknown(schema);
|
|
409
|
-
switch (encoding.kind) {
|
|
410
|
-
case "Json":
|
|
411
|
-
{
|
|
412
|
-
return body => Effect.orDie(Effect.flatMap(encode(body), json => HttpServerResponse.json(json, {
|
|
413
|
-
status: successStatus,
|
|
414
|
-
contentType: encoding.contentType
|
|
415
|
-
})));
|
|
416
|
-
}
|
|
417
|
-
case "Text":
|
|
418
|
-
{
|
|
419
|
-
return body => Effect.map(Effect.orDie(encode(body)), text => HttpServerResponse.text(text, {
|
|
420
|
-
status: successStatus,
|
|
421
|
-
contentType: encoding.contentType
|
|
422
|
-
}));
|
|
423
|
-
}
|
|
424
|
-
case "Uint8Array":
|
|
425
|
-
{
|
|
426
|
-
return body => Effect.map(Effect.orDie(encode(body)), data => HttpServerResponse.uint8Array(data, {
|
|
427
|
-
status: successStatus,
|
|
428
|
-
contentType: encoding.contentType
|
|
429
|
-
}));
|
|
430
|
-
}
|
|
431
|
-
case "UrlParams":
|
|
432
|
-
{
|
|
433
|
-
return body => Effect.map(Effect.orDie(encode(body)), params => HttpServerResponse.urlParams(params, {
|
|
434
|
-
status: successStatus,
|
|
435
|
-
contentType: encoding.contentType
|
|
436
|
-
}));
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
return HttpRouter.makeRoute(endpoint.method, endpoint.path, Effect.withFiberRuntime(fiber => {
|
|
441
|
-
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
442
|
-
const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest);
|
|
443
|
-
const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext);
|
|
444
|
-
const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams);
|
|
445
|
-
return (decodePath._tag === "Some" ? Effect.catchAll(decodePath.value(routeContext.params), _HttpApiError.HttpApiDecodeError.refailParseError) : Effect.succeed(routeContext.params)).pipe(Effect.bindTo("pathParams"), decodePayload._tag === "Some" ? Effect.bind("payload", _ => requestPayload(request, urlParams, isMultipart).pipe(Effect.orDie, Effect.flatMap(raw => Effect.catchAll(decodePayload.value(raw), _HttpApiError.HttpApiDecodeError.refailParseError)))) : _Function.identity, decodeHeaders._tag === "Some" ? Effect.bind("headers", _ => Effect.orDie(decodeHeaders.value(request.headers))) : _Function.identity, Effect.flatMap(input => {
|
|
446
|
-
const request = {
|
|
447
|
-
path: input.pathParams
|
|
448
|
-
};
|
|
449
|
-
if ("payload" in input) {
|
|
450
|
-
request.payload = input.payload;
|
|
451
|
-
}
|
|
452
|
-
if ("headers" in input) {
|
|
453
|
-
request.headers = input.headers;
|
|
454
|
-
}
|
|
455
|
-
return handler(request);
|
|
456
|
-
}), isFullResponse ? _Function.identity : encodeSuccess._tag === "Some" ? Effect.flatMap(encodeSuccess.value) : Effect.as(HttpServerResponse.empty({
|
|
457
|
-
status: successStatus
|
|
458
|
-
})));
|
|
459
|
-
}));
|
|
460
|
-
};
|
|
461
|
-
const astCache = /*#__PURE__*/(0, _GlobalValue.globalValue)("@effect/platform/HttpApiBuilder/astCache", () => new WeakMap());
|
|
462
|
-
const makeErrorSchema = api => {
|
|
463
|
-
const schemas = new Set();
|
|
464
|
-
function processSchema(schema) {
|
|
465
|
-
if (astCache.has(schema.ast)) {
|
|
466
|
-
schemas.add(astCache.get(schema.ast));
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
const ast = schema.ast;
|
|
470
|
-
if (ast._tag === "Union") {
|
|
471
|
-
for (const astType of ast.types) {
|
|
472
|
-
const errorSchema = Schema.make(astType).annotations({
|
|
473
|
-
...ast.annotations,
|
|
474
|
-
...astType.annotations
|
|
475
|
-
});
|
|
476
|
-
astCache.set(astType, errorSchema);
|
|
477
|
-
schemas.add(errorSchema);
|
|
478
|
-
}
|
|
479
|
-
} else {
|
|
480
|
-
astCache.set(ast, schema);
|
|
481
|
-
schemas.add(schema);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
processSchema(api.errorSchema);
|
|
485
|
-
for (const group of api.groups) {
|
|
486
|
-
for (const endpoint of group.endpoints) {
|
|
487
|
-
processSchema(endpoint.errorSchema);
|
|
488
|
-
}
|
|
489
|
-
processSchema(group.errorSchema);
|
|
490
|
-
}
|
|
491
|
-
return Schema.Union(...[...schemas].map(schema => {
|
|
492
|
-
const status = HttpApiSchema.getStatusError(schema);
|
|
493
|
-
const encoded = AST.encodedAST(schema.ast);
|
|
494
|
-
const isEmpty = encoded._tag === "VoidKeyword";
|
|
495
|
-
return Schema.transformOrFail(Schema.Any, schema, {
|
|
496
|
-
decode: (_, __, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema")),
|
|
497
|
-
encode: (error, _, ast) => isEmpty ? HttpServerResponse.empty({
|
|
498
|
-
status
|
|
499
|
-
}) : HttpServerResponse.json(error, {
|
|
500
|
-
status
|
|
501
|
-
}).pipe(Effect.mapError(error => new ParseResult.Type(ast, error, "Could not encode to JSON")))
|
|
502
|
-
});
|
|
503
|
-
}));
|
|
504
|
-
};
|
|
505
493
|
//# sourceMappingURL=HttpApiBuilder.js.map
|