@effect/platform 0.62.5 → 0.63.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/HttpApi/package.json +6 -0
- package/HttpApiBuilder/package.json +6 -0
- package/HttpApiClient/package.json +6 -0
- package/HttpApiEndpoint/package.json +6 -0
- package/HttpApiError/package.json +6 -0
- package/HttpApiGroup/package.json +6 -0
- package/HttpApiSchema/package.json +6 -0
- package/HttpApiSecurity/package.json +6 -0
- package/HttpApiSwagger/package.json +6 -0
- package/OpenApi/package.json +6 -0
- package/README.md +863 -302
- package/dist/cjs/HttpApi.js +168 -0
- package/dist/cjs/HttpApi.js.map +1 -0
- package/dist/cjs/HttpApiBuilder.js +471 -0
- package/dist/cjs/HttpApiBuilder.js.map +1 -0
- package/dist/cjs/HttpApiClient.js +134 -0
- package/dist/cjs/HttpApiClient.js.map +1 -0
- package/dist/cjs/HttpApiEndpoint.js +181 -0
- package/dist/cjs/HttpApiEndpoint.js.map +1 -0
- package/dist/cjs/HttpApiError.js +69 -0
- package/dist/cjs/HttpApiError.js.map +1 -0
- package/dist/cjs/HttpApiGroup.js +151 -0
- package/dist/cjs/HttpApiGroup.js.map +1 -0
- package/dist/cjs/HttpApiSchema.js +241 -0
- package/dist/cjs/HttpApiSchema.js.map +1 -0
- package/dist/cjs/HttpApiSecurity.js +83 -0
- package/dist/cjs/HttpApiSecurity.js.map +1 -0
- package/dist/cjs/HttpApiSwagger.js +50 -0
- package/dist/cjs/HttpApiSwagger.js.map +1 -0
- package/dist/cjs/HttpMethod.js +1 -1
- package/dist/cjs/HttpMethod.js.map +1 -1
- package/dist/cjs/HttpRouter.js +6 -1
- package/dist/cjs/HttpRouter.js.map +1 -1
- package/dist/cjs/OpenApi.js +317 -0
- package/dist/cjs/OpenApi.js.map +1 -0
- package/dist/cjs/index.js +21 -1
- package/dist/cjs/internal/apiSwagger.js +2 -0
- package/dist/cjs/internal/apiSwagger.js.map +1 -0
- package/dist/cjs/internal/httpRouter.js +6 -1
- package/dist/cjs/internal/httpRouter.js.map +1 -1
- package/dist/cjs/internal/multipart.js +5 -1
- package/dist/cjs/internal/multipart.js.map +1 -1
- package/dist/dts/HttpApi.d.ts +156 -0
- package/dist/dts/HttpApi.d.ts.map +1 -0
- package/dist/dts/HttpApiBuilder.d.ts +296 -0
- package/dist/dts/HttpApiBuilder.d.ts.map +1 -0
- package/dist/dts/HttpApiClient.d.ts +31 -0
- package/dist/dts/HttpApiClient.d.ts.map +1 -0
- package/dist/dts/HttpApiEndpoint.d.ts +350 -0
- package/dist/dts/HttpApiEndpoint.d.ts.map +1 -0
- package/dist/dts/HttpApiError.d.ts +70 -0
- package/dist/dts/HttpApiError.d.ts.map +1 -0
- package/dist/dts/HttpApiGroup.d.ts +196 -0
- package/dist/dts/HttpApiGroup.d.ts.map +1 -0
- package/dist/dts/HttpApiSchema.d.ts +223 -0
- package/dist/dts/HttpApiSchema.d.ts.map +1 -0
- package/dist/dts/HttpApiSecurity.d.ts +122 -0
- package/dist/dts/HttpApiSecurity.d.ts.map +1 -0
- package/dist/dts/HttpApiSwagger.d.ts +10 -0
- package/dist/dts/HttpApiSwagger.d.ts.map +1 -0
- package/dist/dts/HttpMethod.d.ts +16 -0
- package/dist/dts/HttpMethod.d.ts.map +1 -1
- package/dist/dts/HttpRouter.d.ts +8 -0
- package/dist/dts/HttpRouter.d.ts.map +1 -1
- package/dist/dts/HttpServerResponse.d.ts +3 -3
- package/dist/dts/HttpServerResponse.d.ts.map +1 -1
- package/dist/dts/OpenApi.d.ts +348 -0
- package/dist/dts/OpenApi.d.ts.map +1 -0
- package/dist/dts/index.d.ts +40 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/apiSwagger.d.ts +2 -0
- package/dist/dts/internal/apiSwagger.d.ts.map +1 -0
- package/dist/dts/internal/httpRouter.d.ts.map +1 -1
- package/dist/esm/HttpApi.js +157 -0
- package/dist/esm/HttpApi.js.map +1 -0
- package/dist/esm/HttpApiBuilder.js +447 -0
- package/dist/esm/HttpApiBuilder.js.map +1 -0
- package/dist/esm/HttpApiClient.js +124 -0
- package/dist/esm/HttpApiClient.js.map +1 -0
- package/dist/esm/HttpApiEndpoint.js +169 -0
- package/dist/esm/HttpApiEndpoint.js.map +1 -0
- package/dist/esm/HttpApiError.js +59 -0
- package/dist/esm/HttpApiError.js.map +1 -0
- package/dist/esm/HttpApiGroup.js +140 -0
- package/dist/esm/HttpApiGroup.js.map +1 -0
- package/dist/esm/HttpApiSchema.js +217 -0
- package/dist/esm/HttpApiSchema.js.map +1 -0
- package/dist/esm/HttpApiSecurity.js +73 -0
- package/dist/esm/HttpApiSecurity.js.map +1 -0
- package/dist/esm/HttpApiSwagger.js +40 -0
- package/dist/esm/HttpApiSwagger.js.map +1 -0
- package/dist/esm/HttpMethod.js +1 -1
- package/dist/esm/HttpMethod.js.map +1 -1
- package/dist/esm/HttpRouter.js +5 -0
- package/dist/esm/HttpRouter.js.map +1 -1
- package/dist/esm/OpenApi.js +299 -0
- package/dist/esm/OpenApi.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/apiSwagger.js +2 -0
- package/dist/esm/internal/apiSwagger.js.map +1 -0
- package/dist/esm/internal/httpRouter.js +5 -0
- package/dist/esm/internal/httpRouter.js.map +1 -1
- package/dist/esm/internal/multipart.js +5 -1
- package/dist/esm/internal/multipart.js.map +1 -1
- package/package.json +83 -3
- package/src/HttpApi.ts +342 -0
- package/src/HttpApiBuilder.ts +869 -0
- package/src/HttpApiClient.ts +228 -0
- package/src/HttpApiEndpoint.ts +818 -0
- package/src/HttpApiError.ts +113 -0
- package/src/HttpApiGroup.ts +365 -0
- package/src/HttpApiSchema.ts +384 -0
- package/src/HttpApiSecurity.ts +169 -0
- package/src/HttpApiSwagger.ts +46 -0
- package/src/HttpMethod.ts +19 -1
- package/src/HttpRouter.ts +9 -0
- package/src/HttpServerResponse.ts +3 -3
- package/src/OpenApi.ts +665 -0
- package/src/index.ts +50 -0
- package/src/internal/apiSwagger.ts +7 -0
- package/src/internal/httpRouter.ts +9 -0
- package/src/internal/multipart.ts +5 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.reflect = exports.isHttpApi = exports.empty = exports.annotateMerge = exports.annotate = exports.addGroup = exports.addError = exports.TypeId = exports.HttpApi = void 0;
|
|
7
|
+
var AST = _interopRequireWildcard(require("@effect/schema/AST"));
|
|
8
|
+
var Chunk = _interopRequireWildcard(require("effect/Chunk"));
|
|
9
|
+
var Context = _interopRequireWildcard(require("effect/Context"));
|
|
10
|
+
var _Function = require("effect/Function");
|
|
11
|
+
var Option = _interopRequireWildcard(require("effect/Option"));
|
|
12
|
+
var _Pipeable = require("effect/Pipeable");
|
|
13
|
+
var Predicate = _interopRequireWildcard(require("effect/Predicate"));
|
|
14
|
+
var HttpApiEndpoint = _interopRequireWildcard(require("./HttpApiEndpoint.js"));
|
|
15
|
+
var _HttpApiError = require("./HttpApiError.js");
|
|
16
|
+
var HttpApiGroup = _interopRequireWildcard(require("./HttpApiGroup.js"));
|
|
17
|
+
var HttpApiSchema = _interopRequireWildcard(require("./HttpApiSchema.js"));
|
|
18
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
19
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
20
|
+
/**
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
* @category type ids
|
|
27
|
+
*/
|
|
28
|
+
const TypeId = exports.TypeId = /*#__PURE__*/Symbol.for("@effect/platform/HttpApi");
|
|
29
|
+
/**
|
|
30
|
+
* @since 1.0.0
|
|
31
|
+
* @category guards
|
|
32
|
+
*/
|
|
33
|
+
const isHttpApi = u => Predicate.hasProperty(u, TypeId);
|
|
34
|
+
/**
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
* @category tags
|
|
37
|
+
*/
|
|
38
|
+
exports.isHttpApi = isHttpApi;
|
|
39
|
+
const HttpApi = exports.HttpApi = /*#__PURE__*/Context.GenericTag("@effect/platform/HttpApi");
|
|
40
|
+
const Proto = {
|
|
41
|
+
[TypeId]: TypeId,
|
|
42
|
+
pipe() {
|
|
43
|
+
return (0, _Pipeable.pipeArguments)(this, arguments);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const makeProto = options => {
|
|
47
|
+
function HttpApi() {}
|
|
48
|
+
Object.setPrototypeOf(HttpApi, Proto);
|
|
49
|
+
return Object.assign(HttpApi, options);
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* An empty `HttpApi`. You can use this to start building your `HttpApi`.
|
|
53
|
+
*
|
|
54
|
+
* You can add groups to this `HttpApi` using the `addGroup` function.
|
|
55
|
+
*
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
* @category constructors
|
|
58
|
+
*/
|
|
59
|
+
const empty = exports.empty = /*#__PURE__*/makeProto({
|
|
60
|
+
groups: /*#__PURE__*/Chunk.empty(),
|
|
61
|
+
errorSchema: _HttpApiError.HttpApiDecodeError,
|
|
62
|
+
annotations: /*#__PURE__*/Context.empty()
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Add a `HttpApiGroup` to an `HttpApi`.
|
|
66
|
+
*
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
* @category constructors
|
|
69
|
+
*/
|
|
70
|
+
const addGroup = exports.addGroup = /*#__PURE__*/(0, _Function.dual)(args => isHttpApi(args[0]), (self, ...args) => {
|
|
71
|
+
const group = args.length === 1 ? args[0] : HttpApiGroup.prefix(args[1], args[0]);
|
|
72
|
+
return makeProto({
|
|
73
|
+
errorSchema: self.errorSchema,
|
|
74
|
+
annotations: self.annotations,
|
|
75
|
+
groups: Chunk.append(self.groups, group)
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Add an error schema to an `HttpApi`, which is shared by all endpoints in the
|
|
80
|
+
* `HttpApi`.
|
|
81
|
+
*
|
|
82
|
+
* Useful for adding error types from middleware or other shared error types.
|
|
83
|
+
*
|
|
84
|
+
* @since 1.0.0
|
|
85
|
+
* @category errors
|
|
86
|
+
*/
|
|
87
|
+
const addError = exports.addError = /*#__PURE__*/(0, _Function.dual)(args => isHttpApi(args[0]), (self, schema, annotations) => makeProto({
|
|
88
|
+
groups: self.groups,
|
|
89
|
+
annotations: self.annotations,
|
|
90
|
+
errorSchema: HttpApiSchema.UnionUnify(self.errorSchema, schema.annotations(HttpApiSchema.annotations({
|
|
91
|
+
status: annotations?.status ?? HttpApiSchema.getStatusError(schema)
|
|
92
|
+
})))
|
|
93
|
+
}));
|
|
94
|
+
/**
|
|
95
|
+
* @since 1.0.0
|
|
96
|
+
* @category annotations
|
|
97
|
+
*/
|
|
98
|
+
const annotateMerge = exports.annotateMerge = /*#__PURE__*/(0, _Function.dual)(2, (self, context) => makeProto({
|
|
99
|
+
groups: self.groups,
|
|
100
|
+
errorSchema: self.errorSchema,
|
|
101
|
+
annotations: Context.merge(self.annotations, context)
|
|
102
|
+
}));
|
|
103
|
+
/**
|
|
104
|
+
* @since 1.0.0
|
|
105
|
+
* @category annotations
|
|
106
|
+
*/
|
|
107
|
+
const annotate = exports.annotate = /*#__PURE__*/(0, _Function.dual)(3, (self, tag, value) => makeProto({
|
|
108
|
+
groups: self.groups,
|
|
109
|
+
errorSchema: self.errorSchema,
|
|
110
|
+
annotations: Context.add(self.annotations, tag, value)
|
|
111
|
+
}));
|
|
112
|
+
/**
|
|
113
|
+
* Extract metadata from an `HttpApi`, which can be used to generate documentation
|
|
114
|
+
* or other tooling.
|
|
115
|
+
*
|
|
116
|
+
* See the `OpenApi` & `HttpApiClient` modules for examples of how to use this function.
|
|
117
|
+
*
|
|
118
|
+
* @since 1.0.0
|
|
119
|
+
* @category reflection
|
|
120
|
+
*/
|
|
121
|
+
const reflect = (self, options) => {
|
|
122
|
+
const apiErrors = extractErrors(self.errorSchema.ast, new Map());
|
|
123
|
+
const groups = self.groups;
|
|
124
|
+
for (const group of groups) {
|
|
125
|
+
const groupErrors = extractErrors(group.errorSchema.ast, apiErrors);
|
|
126
|
+
const groupAnnotations = Context.merge(self.annotations, group.annotations);
|
|
127
|
+
options.onGroup({
|
|
128
|
+
group,
|
|
129
|
+
mergedAnnotations: groupAnnotations
|
|
130
|
+
});
|
|
131
|
+
const endpoints = group.endpoints;
|
|
132
|
+
for (const endpoint of endpoints) {
|
|
133
|
+
options.onEndpoint({
|
|
134
|
+
group,
|
|
135
|
+
endpoint,
|
|
136
|
+
mergedAnnotations: Context.merge(groupAnnotations, endpoint.annotations),
|
|
137
|
+
successAST: HttpApiEndpoint.schemaSuccess(endpoint).pipe(Option.map(schema => schema.ast)),
|
|
138
|
+
successStatus: HttpApiSchema.getStatusSuccess(endpoint.successSchema),
|
|
139
|
+
successEncoding: HttpApiSchema.getEncoding(endpoint.successSchema.ast),
|
|
140
|
+
errors: extractErrors(endpoint.errorSchema.ast, groupErrors)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
// -------------------------------------------------------------------------------------
|
|
146
|
+
exports.reflect = reflect;
|
|
147
|
+
const extractErrors = (ast, inherited) => {
|
|
148
|
+
const topStatus = HttpApiSchema.getStatusErrorAST(ast);
|
|
149
|
+
const errors = new Map(inherited);
|
|
150
|
+
function process(ast) {
|
|
151
|
+
if (ast._tag === "NeverKeyword") {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const status = HttpApiSchema.getStatus(ast, topStatus);
|
|
155
|
+
const emptyDecodeable = HttpApiSchema.getEmptyDecodeable(ast);
|
|
156
|
+
const current = errors.get(status) ?? Option.none();
|
|
157
|
+
errors.set(status, current.pipe(Option.map(current => AST.Union.make(current._tag === "Union" ? [...current.types, ast] : [current, ast])), Option.orElse(() => !emptyDecodeable && AST.encodedAST(ast)._tag === "VoidKeyword" ? Option.none() : Option.some(ast))));
|
|
158
|
+
}
|
|
159
|
+
if (ast._tag === "Union") {
|
|
160
|
+
for (const type of ast.types) {
|
|
161
|
+
process(type);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
process(ast);
|
|
165
|
+
}
|
|
166
|
+
return errors;
|
|
167
|
+
};
|
|
168
|
+
//# sourceMappingURL=HttpApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpApi.js","names":["AST","_interopRequireWildcard","require","Chunk","Context","_Function","Option","_Pipeable","Predicate","HttpApiEndpoint","_HttpApiError","HttpApiGroup","HttpApiSchema","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","TypeId","exports","Symbol","for","isHttpApi","hasProperty","HttpApi","GenericTag","Proto","pipe","pipeArguments","arguments","makeProto","options","setPrototypeOf","assign","empty","groups","errorSchema","HttpApiDecodeError","annotations","addGroup","dual","args","self","group","length","prefix","append","addError","schema","UnionUnify","status","getStatusError","annotateMerge","context","merge","annotate","tag","value","add","reflect","apiErrors","extractErrors","ast","Map","groupErrors","groupAnnotations","onGroup","mergedAnnotations","endpoints","endpoint","onEndpoint","successAST","schemaSuccess","map","successStatus","getStatusSuccess","successSchema","successEncoding","getEncoding","errors","inherited","topStatus","getStatusErrorAST","process","_tag","getStatus","emptyDecodeable","getEmptyDecodeable","current","none","Union","make","types","orElse","encodedAST","some","type"],"sources":["../../src/HttpApi.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.serve = exports.securitySetCookie = exports.securityDecode = exports.middlewareSecurityVoid = exports.middlewareSecurity = exports.middlewareOpenApi = exports.middlewareLayerScoped = exports.middlewareLayer = exports.middlewareCors = exports.middleware = exports.httpApp = exports.handle = exports.group = exports.api = exports.Router = exports.Middleware = exports.HandlersTypeId = void 0;
|
|
7
|
+
var AST = _interopRequireWildcard(require("@effect/schema/AST"));
|
|
8
|
+
var ParseResult = _interopRequireWildcard(require("@effect/schema/ParseResult"));
|
|
9
|
+
var Schema = _interopRequireWildcard(require("@effect/schema/Schema"));
|
|
10
|
+
var Chunk = _interopRequireWildcard(require("effect/Chunk"));
|
|
11
|
+
var Context = _interopRequireWildcard(require("effect/Context"));
|
|
12
|
+
var Effect = _interopRequireWildcard(require("effect/Effect"));
|
|
13
|
+
var Encoding = _interopRequireWildcard(require("effect/Encoding"));
|
|
14
|
+
var FiberRef = _interopRequireWildcard(require("effect/FiberRef"));
|
|
15
|
+
var _Function = require("effect/Function");
|
|
16
|
+
var _GlobalValue = require("effect/GlobalValue");
|
|
17
|
+
var Layer = _interopRequireWildcard(require("effect/Layer"));
|
|
18
|
+
var Option = _interopRequireWildcard(require("effect/Option"));
|
|
19
|
+
var _Pipeable = require("effect/Pipeable");
|
|
20
|
+
var Redacted = _interopRequireWildcard(require("effect/Redacted"));
|
|
21
|
+
var _Unify = require("effect/Unify");
|
|
22
|
+
var HttpApi = _interopRequireWildcard(require("./HttpApi.js"));
|
|
23
|
+
var HttpApiEndpoint = _interopRequireWildcard(require("./HttpApiEndpoint.js"));
|
|
24
|
+
var _HttpApiError = require("./HttpApiError.js");
|
|
25
|
+
var HttpApiSchema = _interopRequireWildcard(require("./HttpApiSchema.js"));
|
|
26
|
+
var HttpApp = _interopRequireWildcard(require("./HttpApp.js"));
|
|
27
|
+
var HttpMethod = _interopRequireWildcard(require("./HttpMethod.js"));
|
|
28
|
+
var HttpMiddleware = _interopRequireWildcard(require("./HttpMiddleware.js"));
|
|
29
|
+
var HttpRouter = _interopRequireWildcard(require("./HttpRouter.js"));
|
|
30
|
+
var HttpServer = _interopRequireWildcard(require("./HttpServer.js"));
|
|
31
|
+
var HttpServerRequest = _interopRequireWildcard(require("./HttpServerRequest.js"));
|
|
32
|
+
var HttpServerResponse = _interopRequireWildcard(require("./HttpServerResponse.js"));
|
|
33
|
+
var OpenApi = _interopRequireWildcard(require("./OpenApi.js"));
|
|
34
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
35
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
36
|
+
/**
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The router that the API endpoints are attached to.
|
|
42
|
+
*
|
|
43
|
+
* @since 1.0.0
|
|
44
|
+
* @category router
|
|
45
|
+
*/
|
|
46
|
+
class Router extends /*#__PURE__*/HttpRouter.Tag("@effect/platform/HttpApiBuilder/Router")() {}
|
|
47
|
+
/**
|
|
48
|
+
* Build an `HttpApp` from an `HttpApi` instance, and serve it using an
|
|
49
|
+
* `HttpServer`.
|
|
50
|
+
*
|
|
51
|
+
* Optionally, you can provide a middleware function that will be applied to
|
|
52
|
+
* the `HttpApp` before serving.
|
|
53
|
+
*
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
* @category constructors
|
|
56
|
+
*/
|
|
57
|
+
exports.Router = Router;
|
|
58
|
+
const serve = middleware => httpApp.pipe(Effect.map(HttpServer.serve(middleware)), Layer.unwrapEffect, Layer.provide(Router.Live));
|
|
59
|
+
/**
|
|
60
|
+
* Construct an `HttpApp` from an `HttpApi` instance.
|
|
61
|
+
*
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
* @category constructors
|
|
64
|
+
*/
|
|
65
|
+
exports.serve = serve;
|
|
66
|
+
const httpApp = exports.httpApp = /*#__PURE__*/Effect.gen(function* () {
|
|
67
|
+
const api = yield* HttpApi.HttpApi;
|
|
68
|
+
const router = yield* Router.router;
|
|
69
|
+
const apiMiddleware = yield* Effect.serviceOption(Middleware);
|
|
70
|
+
const errorSchema = makeErrorSchema(api);
|
|
71
|
+
const encodeError = Schema.encodeUnknown(errorSchema);
|
|
72
|
+
return router.pipe(apiMiddleware._tag === "Some" ? apiMiddleware.value : _Function.identity, Effect.catchAll(error => Effect.matchEffect(encodeError(error), {
|
|
73
|
+
onFailure: () => Effect.die(error),
|
|
74
|
+
onSuccess: Effect.succeed
|
|
75
|
+
})));
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Build a root level `Layer` from an `HttpApi` instance.
|
|
79
|
+
*
|
|
80
|
+
* The `Layer` will provide the `HttpApi` service, and will require the
|
|
81
|
+
* implementation for all the `HttpApiGroup`'s contained in the `HttpApi`.
|
|
82
|
+
*
|
|
83
|
+
* The resulting `Layer` can be provided to the `HttpApiBuilder.serve` layer.
|
|
84
|
+
*
|
|
85
|
+
* @since 1.0.0
|
|
86
|
+
* @category constructors
|
|
87
|
+
*/
|
|
88
|
+
const api = self => Layer.succeed(HttpApi.HttpApi, self);
|
|
89
|
+
/**
|
|
90
|
+
* @since 1.0.0
|
|
91
|
+
* @category handlers
|
|
92
|
+
*/
|
|
93
|
+
exports.api = api;
|
|
94
|
+
const HandlersTypeId = exports.HandlersTypeId = /*#__PURE__*/Symbol.for("@effect/platform/HttpApiBuilder/Handlers");
|
|
95
|
+
const HandlersProto = {
|
|
96
|
+
[HandlersTypeId]: {
|
|
97
|
+
_Endpoints: _Function.identity
|
|
98
|
+
},
|
|
99
|
+
pipe() {
|
|
100
|
+
return (0, _Pipeable.pipeArguments)(this, arguments);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const makeHandlers = options => {
|
|
104
|
+
const self = Object.create(HandlersProto);
|
|
105
|
+
self.group = options.group;
|
|
106
|
+
self.handlers = options.handlers;
|
|
107
|
+
return self;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Create a `Layer` that will implement all the endpoints in an `HttpApiGroup`.
|
|
111
|
+
*
|
|
112
|
+
* An unimplemented `Handlers` instance is passed to the `build` function, which
|
|
113
|
+
* you can use to add handlers to the group.
|
|
114
|
+
*
|
|
115
|
+
* You can implement endpoints using the `HttpApiBuilder.handle` api.
|
|
116
|
+
*
|
|
117
|
+
* @since 1.0.0
|
|
118
|
+
* @category handlers
|
|
119
|
+
*/
|
|
120
|
+
const group = (api, groupName, build) => Router.use(router => Effect.gen(function* () {
|
|
121
|
+
const context = yield* Effect.context();
|
|
122
|
+
const group = Chunk.findFirst(api.groups, group => group.identifier === groupName);
|
|
123
|
+
if (group._tag === "None") {
|
|
124
|
+
throw new Error(`Group "${groupName}" not found in API`);
|
|
125
|
+
}
|
|
126
|
+
const result = build(makeHandlers({
|
|
127
|
+
group: group.value,
|
|
128
|
+
handlers: Chunk.empty()
|
|
129
|
+
}));
|
|
130
|
+
const handlers = Effect.isEffect(result) ? yield* result : result;
|
|
131
|
+
const routes = [];
|
|
132
|
+
for (const item of handlers.handlers) {
|
|
133
|
+
if (item._tag === "Middleware") {
|
|
134
|
+
for (const route of routes) {
|
|
135
|
+
;
|
|
136
|
+
route.handler = item.middleware(route.handler);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
routes.push(handlerToRoute(item.endpoint, function (request) {
|
|
140
|
+
return Effect.mapInputContext(item.handler(request), input => Context.merge(context, input));
|
|
141
|
+
}, item.withFullResponse));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
yield* router.concat(HttpRouter.fromIterable(routes));
|
|
145
|
+
}));
|
|
146
|
+
/**
|
|
147
|
+
* Add the implementation for an `HttpApiEndpoint` to a `Handlers` group.
|
|
148
|
+
*
|
|
149
|
+
* @since 1.0.0
|
|
150
|
+
* @category handlers
|
|
151
|
+
*/
|
|
152
|
+
exports.group = group;
|
|
153
|
+
const handle = (name, handler, options) => self => {
|
|
154
|
+
const o = Chunk.findFirst(self.group.endpoints, endpoint => endpoint.name === name);
|
|
155
|
+
if (o._tag === "None") {
|
|
156
|
+
throw new Error(`Endpoint "${name}" not found in group "${self.group.identifier}"`);
|
|
157
|
+
}
|
|
158
|
+
const endpoint = o.value;
|
|
159
|
+
return makeHandlers({
|
|
160
|
+
group: self.group,
|
|
161
|
+
handlers: Chunk.append(self.handlers, {
|
|
162
|
+
_tag: "Handler",
|
|
163
|
+
endpoint,
|
|
164
|
+
handler,
|
|
165
|
+
withFullResponse: options?.withFullResponse === true
|
|
166
|
+
})
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Add `HttpMiddleware` to a `Handlers` group.
|
|
171
|
+
*
|
|
172
|
+
* Any errors are required to have a corresponding schema in the API.
|
|
173
|
+
* You can add middleware errors to an `HttpApiGroup` using the `HttpApiGroup.addError`
|
|
174
|
+
* api.
|
|
175
|
+
*
|
|
176
|
+
* @since 1.0.0
|
|
177
|
+
* @category middleware
|
|
178
|
+
*/
|
|
179
|
+
exports.handle = handle;
|
|
180
|
+
const middleware = middleware => self => makeHandlers({
|
|
181
|
+
...self,
|
|
182
|
+
handlers: Chunk.append(self.handlers, {
|
|
183
|
+
_tag: "Middleware",
|
|
184
|
+
middleware
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
/**
|
|
188
|
+
* @since 1.0.0
|
|
189
|
+
* @category middleware
|
|
190
|
+
*/
|
|
191
|
+
exports.middleware = middleware;
|
|
192
|
+
class Middleware extends /*#__PURE__*/Context.Tag("@effect/platform/HttpApiBuilder/Middleware")() {}
|
|
193
|
+
exports.Middleware = Middleware;
|
|
194
|
+
const middlewareAdd = middleware => Effect.map(Effect.context(), context => {
|
|
195
|
+
const current = Context.getOption(context, Middleware);
|
|
196
|
+
const withContext = httpApp => Effect.mapInputContext(middleware(httpApp), input => Context.merge(context, input));
|
|
197
|
+
return current._tag === "None" ? withContext : httpApp => withContext(current.value(httpApp));
|
|
198
|
+
});
|
|
199
|
+
const middlewareAddNoContext = middleware => Effect.map(Effect.serviceOption(Middleware), current => {
|
|
200
|
+
return current._tag === "None" ? middleware : httpApp => middleware(current.value(httpApp));
|
|
201
|
+
});
|
|
202
|
+
/**
|
|
203
|
+
* Create an `HttpApi` level middleware `Layer`.
|
|
204
|
+
*
|
|
205
|
+
* @since 1.0.0
|
|
206
|
+
* @category middleware
|
|
207
|
+
*/
|
|
208
|
+
const middlewareLayer = (...args) => {
|
|
209
|
+
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
210
|
+
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
211
|
+
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
212
|
+
const middleware = apiFirst ? args[1] : args[0];
|
|
213
|
+
return Effect.isEffect(middleware) ? Layer.effect(Middleware, Effect.flatMap(middleware, add)) : Layer.effect(Middleware, add(middleware));
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Create an `HttpApi` level middleware `Layer`, that has a `Scope` provided to
|
|
217
|
+
* the constructor.
|
|
218
|
+
*
|
|
219
|
+
* @since 1.0.0
|
|
220
|
+
* @category middleware
|
|
221
|
+
*/
|
|
222
|
+
exports.middlewareLayer = middlewareLayer;
|
|
223
|
+
const middlewareLayerScoped = (...args) => {
|
|
224
|
+
const apiFirst = HttpApi.isHttpApi(args[0]);
|
|
225
|
+
const withContext = apiFirst ? args[2]?.withContext === true : args[1]?.withContext === true;
|
|
226
|
+
const add = withContext ? middlewareAdd : middlewareAddNoContext;
|
|
227
|
+
const middleware = apiFirst ? args[1] : args[0];
|
|
228
|
+
return Layer.scoped(Middleware, Effect.flatMap(middleware, add));
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* A CORS middleware layer that can be provided to the `HttpApiBuilder.serve` layer.
|
|
232
|
+
*
|
|
233
|
+
* @since 1.0.0
|
|
234
|
+
* @category middleware
|
|
235
|
+
*/
|
|
236
|
+
exports.middlewareLayerScoped = middlewareLayerScoped;
|
|
237
|
+
const middlewareCors = options => middlewareLayer(HttpMiddleware.cors(options));
|
|
238
|
+
/**
|
|
239
|
+
* A middleware that adds an openapi.json endpoint to the API.
|
|
240
|
+
*
|
|
241
|
+
* @since 1.0.0
|
|
242
|
+
* @category middleware
|
|
243
|
+
*/
|
|
244
|
+
exports.middlewareCors = middlewareCors;
|
|
245
|
+
const middlewareOpenApi = options => Router.use(router => Effect.gen(function* () {
|
|
246
|
+
const api = yield* HttpApi.HttpApi;
|
|
247
|
+
const spec = OpenApi.fromApi(api);
|
|
248
|
+
const response = yield* HttpServerResponse.json(spec).pipe(Effect.orDie);
|
|
249
|
+
yield* router.get(options?.path ?? "/openapi.json", Effect.succeed(response));
|
|
250
|
+
}));
|
|
251
|
+
exports.middlewareOpenApi = middlewareOpenApi;
|
|
252
|
+
const bearerLen = `Bearer `.length;
|
|
253
|
+
/**
|
|
254
|
+
* @since 1.0.0
|
|
255
|
+
* @category middleware
|
|
256
|
+
*/
|
|
257
|
+
const securityDecode = self => {
|
|
258
|
+
switch (self._tag) {
|
|
259
|
+
case "Bearer":
|
|
260
|
+
{
|
|
261
|
+
return Effect.map(HttpServerRequest.HttpServerRequest, request => Redacted.make((request.headers.authorization ?? "").slice(bearerLen)));
|
|
262
|
+
}
|
|
263
|
+
case "ApiKey":
|
|
264
|
+
{
|
|
265
|
+
const schema = Schema.Struct({
|
|
266
|
+
[self.key]: Schema.String
|
|
267
|
+
});
|
|
268
|
+
const decode = (0, _Unify.unify)(self.in === "query" ? HttpServerRequest.schemaSearchParams(schema) : self.in === "cookie" ? HttpServerRequest.schemaCookies(schema) : HttpServerRequest.schemaHeaders(schema));
|
|
269
|
+
return Effect.match(decode, {
|
|
270
|
+
onFailure: () => Redacted.make(""),
|
|
271
|
+
onSuccess: match => Redacted.make(match[self.key])
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
case "Basic":
|
|
275
|
+
{
|
|
276
|
+
const empty = {
|
|
277
|
+
username: "",
|
|
278
|
+
password: Redacted.make("")
|
|
279
|
+
};
|
|
280
|
+
return HttpServerRequest.HttpServerRequest.pipe(Effect.flatMap(request => Encoding.decodeBase64String(request.headers.authorization ?? "")), Effect.match({
|
|
281
|
+
onFailure: () => empty,
|
|
282
|
+
onSuccess: header => {
|
|
283
|
+
const parts = header.split(":");
|
|
284
|
+
if (parts.length !== 2) {
|
|
285
|
+
return empty;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
username: parts[0],
|
|
289
|
+
password: Redacted.make(parts[1])
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
/**
|
|
297
|
+
* Set a cookie from an `HttpApiSecurity.HttpApiKey` instance.
|
|
298
|
+
*
|
|
299
|
+
* You can use this api before returning a response from an endpoint handler.
|
|
300
|
+
*
|
|
301
|
+
* ```ts
|
|
302
|
+
* ApiBuilder.handle(
|
|
303
|
+
* "authenticate",
|
|
304
|
+
* (_) => ApiBuilder.securitySetCookie(security, "secret123")
|
|
305
|
+
* )
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* @since 1.0.0
|
|
309
|
+
* @category middleware
|
|
310
|
+
*/
|
|
311
|
+
exports.securityDecode = securityDecode;
|
|
312
|
+
const securitySetCookie = (self, value, options) => {
|
|
313
|
+
const stringValue = typeof value === "string" ? value : Redacted.value(value);
|
|
314
|
+
return HttpApp.appendPreResponseHandler((_req, response) => Effect.orDie(HttpServerResponse.setCookie(response, self.key, stringValue, {
|
|
315
|
+
secure: true,
|
|
316
|
+
httpOnly: true,
|
|
317
|
+
...options
|
|
318
|
+
})));
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Make a middleware from an `HttpApiSecurity` instance, that can be used when
|
|
322
|
+
* constructing a `Handlers` group.
|
|
323
|
+
*
|
|
324
|
+
* @since 1.0.0
|
|
325
|
+
* @category middleware
|
|
326
|
+
* @example
|
|
327
|
+
* import { HttpApiBuilder, HttpApiSecurity } from "@effect/platform"
|
|
328
|
+
* import { Schema } from "@effect/schema"
|
|
329
|
+
* import { Context, Effect, Redacted } from "effect"
|
|
330
|
+
*
|
|
331
|
+
* class User extends Schema.Class<User>("User")({
|
|
332
|
+
* id: Schema.Number
|
|
333
|
+
* }) {}
|
|
334
|
+
*
|
|
335
|
+
* class CurrentUser extends Context.Tag("CurrentUser")<CurrentUser, User>() {}
|
|
336
|
+
*
|
|
337
|
+
* class Accounts extends Context.Tag("Accounts")<Accounts, {
|
|
338
|
+
* readonly findUserByAccessToken: (accessToken: string) => Effect.Effect<User>
|
|
339
|
+
* }>() {}
|
|
340
|
+
*
|
|
341
|
+
* const securityMiddleware = Effect.gen(function*() {
|
|
342
|
+
* const accounts = yield* Accounts
|
|
343
|
+
* return HttpApiBuilder.middlewareSecurity(
|
|
344
|
+
* HttpApiSecurity.bearer,
|
|
345
|
+
* CurrentUser,
|
|
346
|
+
* (token) => accounts.findUserByAccessToken(Redacted.value(token))
|
|
347
|
+
* )
|
|
348
|
+
* })
|
|
349
|
+
*/
|
|
350
|
+
exports.securitySetCookie = securitySetCookie;
|
|
351
|
+
const middlewareSecurity = (self, tag, f) => middleware(Effect.provideServiceEffect(tag, Effect.flatMap(securityDecode(self), f)));
|
|
352
|
+
/**
|
|
353
|
+
* Make a middleware from an `HttpApiSecurity` instance, that can be used when
|
|
354
|
+
* constructing a `Handlers` group.
|
|
355
|
+
*
|
|
356
|
+
* This version does not supply any context to the handlers.
|
|
357
|
+
*
|
|
358
|
+
* @since 1.0.0
|
|
359
|
+
* @category middleware
|
|
360
|
+
*/
|
|
361
|
+
exports.middlewareSecurity = middlewareSecurity;
|
|
362
|
+
const middlewareSecurityVoid = (self, f) => middleware(httpApp => securityDecode(self).pipe(Effect.flatMap(f), Effect.zipRight(httpApp)));
|
|
363
|
+
// internal
|
|
364
|
+
exports.middlewareSecurityVoid = middlewareSecurityVoid;
|
|
365
|
+
const requestPayload = (request, urlParams, isMultipart) => HttpMethod.hasBody(request.method) ? isMultipart ? Effect.orDie(request.multipart) : Effect.orDie(request.json) : Effect.succeed(urlParams);
|
|
366
|
+
const handlerToRoute = (endpoint, handler, isFullResponse) => {
|
|
367
|
+
const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown);
|
|
368
|
+
const isMultipart = endpoint.payloadSchema.pipe(Option.map(schema => HttpApiSchema.getMultipart(schema.ast)), Option.getOrElse(() => false));
|
|
369
|
+
const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown);
|
|
370
|
+
const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown);
|
|
371
|
+
const encoding = HttpApiSchema.getEncoding(endpoint.successSchema.ast);
|
|
372
|
+
const successStatus = HttpApiSchema.getStatusSuccess(endpoint.successSchema);
|
|
373
|
+
const encodeSuccess = Option.map(HttpApiEndpoint.schemaSuccess(endpoint), schema => {
|
|
374
|
+
const encode = Schema.encodeUnknown(schema);
|
|
375
|
+
switch (encoding.kind) {
|
|
376
|
+
case "Json":
|
|
377
|
+
{
|
|
378
|
+
return body => Effect.orDie(Effect.flatMap(encode(body), json => HttpServerResponse.json(json, {
|
|
379
|
+
status: successStatus,
|
|
380
|
+
contentType: encoding.contentType
|
|
381
|
+
})));
|
|
382
|
+
}
|
|
383
|
+
case "Text":
|
|
384
|
+
{
|
|
385
|
+
return body => Effect.map(Effect.orDie(encode(body)), text => HttpServerResponse.text(text, {
|
|
386
|
+
status: successStatus,
|
|
387
|
+
contentType: encoding.contentType
|
|
388
|
+
}));
|
|
389
|
+
}
|
|
390
|
+
case "Uint8Array":
|
|
391
|
+
{
|
|
392
|
+
return body => Effect.map(Effect.orDie(encode(body)), data => HttpServerResponse.uint8Array(data, {
|
|
393
|
+
status: successStatus,
|
|
394
|
+
contentType: encoding.contentType
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
case "UrlParams":
|
|
398
|
+
{
|
|
399
|
+
return body => Effect.map(Effect.orDie(encode(body)), params => HttpServerResponse.urlParams(params, {
|
|
400
|
+
status: successStatus,
|
|
401
|
+
contentType: encoding.contentType
|
|
402
|
+
}));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
return HttpRouter.makeRoute(endpoint.method, endpoint.path, Effect.withFiberRuntime(fiber => {
|
|
407
|
+
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
408
|
+
const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest);
|
|
409
|
+
const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext);
|
|
410
|
+
const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams);
|
|
411
|
+
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 => {
|
|
412
|
+
const request = {
|
|
413
|
+
path: input.pathParams
|
|
414
|
+
};
|
|
415
|
+
if ("payload" in input) {
|
|
416
|
+
request.payload = input.payload;
|
|
417
|
+
}
|
|
418
|
+
if ("headers" in input) {
|
|
419
|
+
request.headers = input.headers;
|
|
420
|
+
}
|
|
421
|
+
return handler(request);
|
|
422
|
+
}), isFullResponse ? _Function.identity : encodeSuccess._tag === "Some" ? Effect.flatMap(encodeSuccess.value) : Effect.as(HttpServerResponse.empty({
|
|
423
|
+
status: successStatus
|
|
424
|
+
})));
|
|
425
|
+
}));
|
|
426
|
+
};
|
|
427
|
+
const astCache = /*#__PURE__*/(0, _GlobalValue.globalValue)("@effect/platform/HttpApiBuilder/astCache", () => new WeakMap());
|
|
428
|
+
const makeErrorSchema = api => {
|
|
429
|
+
const schemas = new Set();
|
|
430
|
+
function processSchema(schema) {
|
|
431
|
+
if (astCache.has(schema.ast)) {
|
|
432
|
+
schemas.add(astCache.get(schema.ast));
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const ast = schema.ast;
|
|
436
|
+
if (ast._tag === "Union") {
|
|
437
|
+
for (const astType of ast.types) {
|
|
438
|
+
const errorSchema = Schema.make(astType).annotations({
|
|
439
|
+
...ast.annotations,
|
|
440
|
+
...astType.annotations
|
|
441
|
+
});
|
|
442
|
+
astCache.set(astType, errorSchema);
|
|
443
|
+
schemas.add(errorSchema);
|
|
444
|
+
}
|
|
445
|
+
} else {
|
|
446
|
+
astCache.set(ast, schema);
|
|
447
|
+
schemas.add(schema);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
processSchema(api.errorSchema);
|
|
451
|
+
for (const group of api.groups) {
|
|
452
|
+
for (const endpoint of group.endpoints) {
|
|
453
|
+
processSchema(endpoint.errorSchema);
|
|
454
|
+
}
|
|
455
|
+
processSchema(group.errorSchema);
|
|
456
|
+
}
|
|
457
|
+
return Schema.Union(...[...schemas].map(schema => {
|
|
458
|
+
const status = HttpApiSchema.getStatusError(schema);
|
|
459
|
+
const encoded = AST.encodedAST(schema.ast);
|
|
460
|
+
const isEmpty = encoded._tag === "VoidKeyword";
|
|
461
|
+
return Schema.transformOrFail(Schema.Any, schema, {
|
|
462
|
+
decode: (_, __, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema")),
|
|
463
|
+
encode: (error, _, ast) => isEmpty ? HttpServerResponse.empty({
|
|
464
|
+
status
|
|
465
|
+
}) : HttpServerResponse.json(error, {
|
|
466
|
+
status
|
|
467
|
+
}).pipe(Effect.mapError(error => new ParseResult.Type(ast, error, "Could not encode to JSON")))
|
|
468
|
+
});
|
|
469
|
+
}));
|
|
470
|
+
};
|
|
471
|
+
//# sourceMappingURL=HttpApiBuilder.js.map
|