@effect/platform 0.68.6 → 0.69.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/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 +245 -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 +86 -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 +228 -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 +238 -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 +534 -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 +317 -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,47 @@ 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
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* ).pipe(
|
|
97
|
-
* Layer.provideMerge(NodeContext.layer)
|
|
109
|
+
* MyApiLive,
|
|
110
|
+
* // you could also use NodeHttpServer.layerContext, depending on your
|
|
111
|
+
* // server's platform
|
|
112
|
+
* HttpServer.layerContext
|
|
98
113
|
* )
|
|
99
114
|
* )
|
|
100
|
-
*
|
|
101
|
-
* const handler = HttpApiBuilder.toWebHandler(runtime, HttpMiddleware.logger)
|
|
102
115
|
*/
|
|
103
|
-
const toWebHandler = (
|
|
116
|
+
const toWebHandler = (layer, options) => {
|
|
117
|
+
const runtime = ManagedRuntime.make(Layer.merge(layer, Router.Live), options?.memoMap);
|
|
118
|
+
let handlerCached;
|
|
104
119
|
const handlerPromise = httpApp.pipe(Effect.bindTo("httpApp"), Effect.bind("runtime", () => runtime.runtimeEffect), Effect.map(({
|
|
105
120
|
httpApp,
|
|
106
121
|
runtime
|
|
107
|
-
}) => HttpApp.toWebHandlerRuntime(runtime)(middleware ? middleware(httpApp) : httpApp)),
|
|
108
|
-
|
|
122
|
+
}) => HttpApp.toWebHandlerRuntime(runtime)(options?.middleware ? options.middleware(httpApp) : httpApp)), Effect.tap(handler => {
|
|
123
|
+
handlerCached = handler;
|
|
124
|
+
}), runtime.runPromise);
|
|
125
|
+
function handler(request) {
|
|
126
|
+
if (handlerCached !== undefined) {
|
|
127
|
+
return handlerCached(request);
|
|
128
|
+
}
|
|
129
|
+
return handlerPromise.then(handler => handler(request));
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
handler,
|
|
133
|
+
dispose: runtime.dispose
|
|
134
|
+
};
|
|
109
135
|
};
|
|
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
136
|
/**
|
|
124
137
|
* @since 1.0.0
|
|
125
138
|
* @category handlers
|
|
126
139
|
*/
|
|
127
|
-
exports.
|
|
140
|
+
exports.toWebHandler = toWebHandler;
|
|
128
141
|
const HandlersTypeId = exports.HandlersTypeId = /*#__PURE__*/Symbol.for("@effect/platform/HttpApiBuilder/Handlers");
|
|
129
142
|
const HandlersProto = {
|
|
130
143
|
[HandlersTypeId]: {
|
|
@@ -132,6 +145,28 @@ const HandlersProto = {
|
|
|
132
145
|
},
|
|
133
146
|
pipe() {
|
|
134
147
|
return (0, _Pipeable.pipeArguments)(this, arguments);
|
|
148
|
+
},
|
|
149
|
+
handle(name, handler) {
|
|
150
|
+
const endpoint = HashMap.unsafeGet(this.group.endpoints, name);
|
|
151
|
+
return makeHandlers({
|
|
152
|
+
group: this.group,
|
|
153
|
+
handlers: Chunk.append(this.handlers, {
|
|
154
|
+
endpoint,
|
|
155
|
+
handler,
|
|
156
|
+
withFullResponse: false
|
|
157
|
+
})
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
handleRaw(name, handler) {
|
|
161
|
+
const endpoint = HashMap.unsafeGet(this.group.endpoints, name);
|
|
162
|
+
return makeHandlers({
|
|
163
|
+
group: this.group,
|
|
164
|
+
handlers: Chunk.append(this.handlers, {
|
|
165
|
+
endpoint,
|
|
166
|
+
handler,
|
|
167
|
+
withFullResponse: true
|
|
168
|
+
})
|
|
169
|
+
});
|
|
135
170
|
}
|
|
136
171
|
};
|
|
137
172
|
const makeHandlers = options => {
|
|
@@ -141,88 +176,191 @@ const makeHandlers = options => {
|
|
|
141
176
|
return self;
|
|
142
177
|
};
|
|
143
178
|
/**
|
|
144
|
-
* Create a `Layer` that will implement all the endpoints in an `
|
|
179
|
+
* Create a `Layer` that will implement all the endpoints in an `HttpApi`.
|
|
145
180
|
*
|
|
146
181
|
* An unimplemented `Handlers` instance is passed to the `build` function, which
|
|
147
182
|
* you can use to add handlers to the group.
|
|
148
183
|
*
|
|
149
|
-
* You can implement endpoints using the `
|
|
184
|
+
* You can implement endpoints using the `handlers.handle` api.
|
|
150
185
|
*
|
|
151
186
|
* @since 1.0.0
|
|
152
187
|
* @category handlers
|
|
153
188
|
*/
|
|
154
189
|
const group = (api, groupName, build) => Router.use(router => Effect.gen(function* () {
|
|
155
190
|
const context = yield* Effect.context();
|
|
156
|
-
const group =
|
|
157
|
-
if (group._tag === "None") {
|
|
158
|
-
throw new Error(`Group "${groupName}" not found in API`);
|
|
159
|
-
}
|
|
191
|
+
const group = HashMap.unsafeGet(api.groups, groupName);
|
|
160
192
|
const result = build(makeHandlers({
|
|
161
|
-
group
|
|
193
|
+
group,
|
|
162
194
|
handlers: Chunk.empty()
|
|
163
195
|
}));
|
|
164
196
|
const handlers = Effect.isEffect(result) ? yield* result : result;
|
|
197
|
+
const groupMiddleware = makeMiddlewareMap(group.middlewares, context);
|
|
165
198
|
const routes = [];
|
|
166
199
|
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
|
-
}
|
|
200
|
+
const middleware = makeMiddlewareMap(item.endpoint.middlewares, context, groupMiddleware);
|
|
201
|
+
routes.push(handlerToRoute(item.endpoint, middleware, function (request) {
|
|
202
|
+
return Effect.mapInputContext(item.handler(request), input => Context.merge(context, input));
|
|
203
|
+
}, item.withFullResponse));
|
|
177
204
|
}
|
|
178
205
|
yield* router.concat(HttpRouter.fromIterable(routes));
|
|
179
206
|
}));
|
|
180
|
-
|
|
181
|
-
* Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
|
|
182
|
-
*
|
|
183
|
-
* @since 1.0.0
|
|
184
|
-
* @category handlers
|
|
185
|
-
*/
|
|
207
|
+
// internal
|
|
186
208
|
exports.group = group;
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
209
|
+
const requestPayload = (request, urlParams, isMultipart) => HttpMethod.hasBody(request.method) ? isMultipart ? Effect.orDie(request.multipart) : Effect.orDie(request.json) : Effect.succeed(urlParams);
|
|
210
|
+
const makeMiddlewareMap = (middleware, context, initial) => {
|
|
211
|
+
const map = new Map(initial);
|
|
212
|
+
HashSet.forEach(middleware, tag => {
|
|
213
|
+
map.set(tag.key, {
|
|
214
|
+
tag,
|
|
215
|
+
effect: Context.unsafeGet(context, tag)
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
return map;
|
|
219
|
+
};
|
|
220
|
+
const handlerToRoute = (endpoint_, middleware, handler, isFullResponse) => {
|
|
221
|
+
const endpoint = endpoint_;
|
|
222
|
+
const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown);
|
|
223
|
+
const isMultipart = endpoint.payloadSchema.pipe(Option.map(schema => HttpApiSchema.getMultipart(schema.ast)), Option.getOrElse(() => false));
|
|
224
|
+
const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown);
|
|
225
|
+
const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown);
|
|
226
|
+
const decodeUrlParams = Option.map(endpoint.urlParamsSchema, Schema.decodeUnknown);
|
|
227
|
+
const encodeSuccess = Schema.encode(makeSuccessSchema(endpoint.successSchema));
|
|
228
|
+
return HttpRouter.makeRoute(endpoint.method, endpoint.path, applyMiddleware(middleware, Effect.withFiberRuntime(fiber => {
|
|
229
|
+
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
230
|
+
const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest);
|
|
231
|
+
const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext);
|
|
232
|
+
const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams);
|
|
233
|
+
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 => {
|
|
234
|
+
const request = {
|
|
235
|
+
path: input.pathParams
|
|
236
|
+
};
|
|
237
|
+
if ("payload" in input) {
|
|
238
|
+
request.payload = input.payload;
|
|
239
|
+
}
|
|
240
|
+
if ("headers" in input) {
|
|
241
|
+
request.headers = input.headers;
|
|
242
|
+
}
|
|
243
|
+
if ("urlParams" in input) {
|
|
244
|
+
request.urlParams = input.urlParams;
|
|
245
|
+
}
|
|
246
|
+
return handler(request);
|
|
247
|
+
}), isFullResponse ? _Function.identity : Effect.flatMap(encodeSuccess), Effect.catchIf(ParseResult.isParseError, _HttpApiError.HttpApiDecodeError.refailParseError));
|
|
248
|
+
})));
|
|
249
|
+
};
|
|
250
|
+
const applyMiddleware = (middleware, handler) => {
|
|
251
|
+
for (const entry of middleware.values()) {
|
|
252
|
+
const effect = HttpApiMiddleware.SecurityTypeId in entry.tag ? makeSecurityMiddleware(entry) : entry.effect;
|
|
253
|
+
if (entry.tag.optional) {
|
|
254
|
+
const previous = handler;
|
|
255
|
+
handler = Effect.matchEffect(effect, {
|
|
256
|
+
onFailure: () => previous,
|
|
257
|
+
onSuccess: entry.tag.provides !== undefined ? value => Effect.provideService(previous, entry.tag.provides, value) : _ => previous
|
|
258
|
+
});
|
|
259
|
+
} else {
|
|
260
|
+
handler = entry.tag.provides !== undefined ? Effect.provideServiceEffect(handler, entry.tag.provides, effect) : Effect.zipRight(effect, handler);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return handler;
|
|
264
|
+
};
|
|
265
|
+
const securityMiddlewareCache = /*#__PURE__*/(0, _GlobalValue.globalValue)("securityMiddlewareCache", () => new WeakMap());
|
|
266
|
+
const makeSecurityMiddleware = entry => {
|
|
267
|
+
if (securityMiddlewareCache.has(entry.tag)) {
|
|
268
|
+
return securityMiddlewareCache.get(entry.tag);
|
|
191
269
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
270
|
+
let effect;
|
|
271
|
+
for (const [key, security] of Object.entries(entry.tag.security)) {
|
|
272
|
+
const decode = securityDecode(security);
|
|
273
|
+
const handler = entry.effect[key];
|
|
274
|
+
const middleware = Effect.flatMap(decode, handler);
|
|
275
|
+
effect = effect === undefined ? middleware : Effect.catchAll(effect, () => middleware);
|
|
276
|
+
}
|
|
277
|
+
if (effect === undefined) {
|
|
278
|
+
effect = Effect.void;
|
|
279
|
+
}
|
|
280
|
+
securityMiddlewareCache.set(entry.tag, effect);
|
|
281
|
+
return effect;
|
|
282
|
+
};
|
|
283
|
+
const responseSchema = /*#__PURE__*/Schema.declare(HttpServerResponse.isServerResponse);
|
|
284
|
+
const makeSuccessSchema = schema => {
|
|
285
|
+
const schemas = new Set();
|
|
286
|
+
HttpApiSchema.deunionize(schemas, schema);
|
|
287
|
+
return Schema.Union(...Array.from(schemas, toResponseSuccess));
|
|
288
|
+
};
|
|
289
|
+
const makeErrorSchema = api => {
|
|
290
|
+
const schemas = new Set();
|
|
291
|
+
HttpApiSchema.deunionize(schemas, api.errorSchema);
|
|
292
|
+
HashMap.forEach(api.groups, group => {
|
|
293
|
+
HashMap.forEach(group.endpoints, endpoint => {
|
|
294
|
+
HttpApiSchema.deunionize(schemas, endpoint.errorSchema);
|
|
295
|
+
});
|
|
296
|
+
HttpApiSchema.deunionize(schemas, group.errorSchema);
|
|
201
297
|
});
|
|
298
|
+
return Schema.Union(...Array.from(schemas, toResponseError));
|
|
202
299
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
300
|
+
const decodeForbidden = (_, __, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema"));
|
|
301
|
+
const toResponseSchema = getStatus => {
|
|
302
|
+
const cache = new WeakMap();
|
|
303
|
+
const schemaToResponse = (data, _, ast) => {
|
|
304
|
+
const isEmpty = HttpApiSchema.isVoid(ast.to);
|
|
305
|
+
const status = getStatus(ast.to);
|
|
306
|
+
if (isEmpty) {
|
|
307
|
+
return HttpServerResponse.empty({
|
|
308
|
+
status
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
const encoding = HttpApiSchema.getEncoding(ast.to);
|
|
312
|
+
switch (encoding.kind) {
|
|
313
|
+
case "Json":
|
|
314
|
+
{
|
|
315
|
+
return Effect.mapError(HttpServerResponse.json(data, {
|
|
316
|
+
status,
|
|
317
|
+
contentType: encoding.contentType
|
|
318
|
+
}), error => new ParseResult.Type(ast, error, "Could not encode to JSON"));
|
|
319
|
+
}
|
|
320
|
+
case "Text":
|
|
321
|
+
{
|
|
322
|
+
return ParseResult.succeed(HttpServerResponse.text(data, {
|
|
323
|
+
status,
|
|
324
|
+
contentType: encoding.contentType
|
|
325
|
+
}));
|
|
326
|
+
}
|
|
327
|
+
case "Uint8Array":
|
|
328
|
+
{
|
|
329
|
+
return ParseResult.succeed(HttpServerResponse.uint8Array(data, {
|
|
330
|
+
status,
|
|
331
|
+
contentType: encoding.contentType
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
case "UrlParams":
|
|
335
|
+
{
|
|
336
|
+
return ParseResult.succeed(HttpServerResponse.urlParams(data, {
|
|
337
|
+
status,
|
|
338
|
+
contentType: encoding.contentType
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
return schema => {
|
|
344
|
+
if (cache.has(schema.ast)) {
|
|
345
|
+
return cache.get(schema.ast);
|
|
346
|
+
}
|
|
347
|
+
const transform = Schema.transformOrFail(responseSchema, schema, {
|
|
348
|
+
decode: decodeForbidden,
|
|
349
|
+
encode: schemaToResponse
|
|
350
|
+
});
|
|
351
|
+
cache.set(transform.ast, transform);
|
|
352
|
+
return transform;
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
const toResponseSuccess = /*#__PURE__*/toResponseSchema(HttpApiSchema.getStatusSuccessAST);
|
|
356
|
+
const toResponseError = /*#__PURE__*/toResponseSchema(HttpApiSchema.getStatusErrorAST);
|
|
357
|
+
// ----------------------------------------------------------------------------
|
|
358
|
+
// Global middleware
|
|
359
|
+
// ----------------------------------------------------------------------------
|
|
221
360
|
/**
|
|
222
361
|
* @since 1.0.0
|
|
223
362
|
* @category middleware
|
|
224
363
|
*/
|
|
225
|
-
exports.middleware = middleware;
|
|
226
364
|
class Middleware extends /*#__PURE__*/Context.Tag("@effect/platform/HttpApiBuilder/Middleware")() {}
|
|
227
365
|
exports.Middleware = Middleware;
|
|
228
366
|
const middlewareAdd = middleware => Effect.map(Effect.context(), context => {
|
|
@@ -239,7 +377,7 @@ const middlewareAddNoContext = middleware => Effect.map(Effect.serviceOption(Mid
|
|
|
239
377
|
* @since 1.0.0
|
|
240
378
|
* @category middleware
|
|
241
379
|
*/
|
|
242
|
-
const
|
|
380
|
+
const middleware = (...args) => {
|
|
243
381
|
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
244
382
|
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
245
383
|
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
@@ -253,8 +391,8 @@ const middlewareLayer = (...args) => {
|
|
|
253
391
|
* @since 1.0.0
|
|
254
392
|
* @category middleware
|
|
255
393
|
*/
|
|
256
|
-
exports.
|
|
257
|
-
const
|
|
394
|
+
exports.middleware = middleware;
|
|
395
|
+
const middlewareScoped = (...args) => {
|
|
258
396
|
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
259
397
|
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
260
398
|
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
@@ -267,8 +405,8 @@ const middlewareLayerScoped = (...args) => {
|
|
|
267
405
|
* @since 1.0.0
|
|
268
406
|
* @category middleware
|
|
269
407
|
*/
|
|
270
|
-
exports.
|
|
271
|
-
const middlewareCors = options =>
|
|
408
|
+
exports.middlewareScoped = middlewareScoped;
|
|
409
|
+
const middlewareCors = options => middleware(HttpMiddleware.cors(options));
|
|
272
410
|
/**
|
|
273
411
|
* A middleware that adds an openapi.json endpoint to the API.
|
|
274
412
|
*
|
|
@@ -277,7 +415,9 @@ const middlewareCors = options => middlewareLayer(HttpMiddleware.cors(options));
|
|
|
277
415
|
*/
|
|
278
416
|
exports.middlewareCors = middlewareCors;
|
|
279
417
|
const middlewareOpenApi = options => Router.use(router => Effect.gen(function* () {
|
|
280
|
-
const
|
|
418
|
+
const {
|
|
419
|
+
api
|
|
420
|
+
} = yield* HttpApi.Api;
|
|
281
421
|
const spec = OpenApi.fromApi(api);
|
|
282
422
|
const response = yield* HttpServerResponse.json(spec).pipe(Effect.orDie);
|
|
283
423
|
yield* router.get(options?.path ?? "/openapi.json", Effect.succeed(response));
|
|
@@ -286,7 +426,7 @@ exports.middlewareOpenApi = middlewareOpenApi;
|
|
|
286
426
|
const bearerLen = `Bearer `.length;
|
|
287
427
|
/**
|
|
288
428
|
* @since 1.0.0
|
|
289
|
-
* @category
|
|
429
|
+
* @category security
|
|
290
430
|
*/
|
|
291
431
|
const securityDecode = self => {
|
|
292
432
|
switch (self._tag) {
|
|
@@ -333,9 +473,9 @@ const securityDecode = self => {
|
|
|
333
473
|
* You can use this api before returning a response from an endpoint handler.
|
|
334
474
|
*
|
|
335
475
|
* ```ts
|
|
336
|
-
*
|
|
476
|
+
* handlers.handle(
|
|
337
477
|
* "authenticate",
|
|
338
|
-
* (_) =>
|
|
478
|
+
* (_) => HttpApiBuilder.securitySetCookie(security, "secret123")
|
|
339
479
|
* )
|
|
340
480
|
* ```
|
|
341
481
|
*
|
|
@@ -351,155 +491,5 @@ const securitySetCookie = (self, value, options) => {
|
|
|
351
491
|
...options
|
|
352
492
|
})));
|
|
353
493
|
};
|
|
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
494
|
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
495
|
//# sourceMappingURL=HttpApiBuilder.js.map
|