@effect-app/infra 1.18.3 → 1.20.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/CHANGELOG.md +12 -0
- package/_cjs/api/internal/events.cjs +32 -0
- package/_cjs/api/internal/events.cjs.map +1 -0
- package/_cjs/api/internal/middlewares.cjs +196 -0
- package/_cjs/api/internal/middlewares.cjs.map +1 -0
- package/_cjs/api/middlewares.cjs +79 -0
- package/_cjs/api/middlewares.cjs.map +1 -0
- package/dist/api/internal/events.d.ts +9 -0
- package/dist/api/internal/events.d.ts.map +1 -0
- package/dist/api/internal/events.js +28 -0
- package/dist/api/internal/middlewares.d.ts +16 -0
- package/dist/api/internal/middlewares.d.ts.map +1 -0
- package/dist/api/internal/middlewares.js +168 -0
- package/dist/api/middlewares.d.ts +82 -0
- package/dist/api/middlewares.d.ts.map +1 -0
- package/dist/api/middlewares.js +52 -0
- package/package.json +13 -3
- package/src/api/internal/events.ts +47 -0
- package/src/api/internal/middlewares.ts +286 -0
- package/src/api/middlewares.ts +104 -0
- package/vitest.config.ts.timestamp-1711656440838-19c636fe320df.mjs +0 -0
- package/vitest.config.ts.timestamp-1711724061890-6ecedb0a07fdd.mjs +0 -0
- package/vitest.config.ts.timestamp-1711743489537-da8d9e5f66c9f.mjs +0 -0
- package/vitest.config.ts.timestamp-1711744615239-dcf257a844e01.mjs +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.makeSSE = void 0;
|
|
7
|
+
var _setupRequest = require("@effect-app/infra/api/setupRequest");
|
|
8
|
+
var _errorReporter = require("@effect-app/infra/errorReporter");
|
|
9
|
+
var _effectApp = require("effect-app");
|
|
10
|
+
var _http = require("effect-app/http");
|
|
11
|
+
// Tell the client to retry every 10 seconds if connectivity is lost
|
|
12
|
+
const setRetry = _effectApp.Stream.succeed("retry: 10000");
|
|
13
|
+
const keepAlive = _effectApp.Stream.schedule(_effectApp.Effect.succeed(":keep-alive"), _effectApp.Schedule.fixed(_effectApp.Duration.seconds(15)));
|
|
14
|
+
const makeSSE = (events, schema) => _effectApp.Effect.gen(function* () {
|
|
15
|
+
yield* _effectApp.Effect.logInfo("$ start listening to events");
|
|
16
|
+
const enc = new TextEncoder();
|
|
17
|
+
const eventStream = _effectApp.Stream.map(events, _ => `id: ${_.evt.id}\ndata: ${JSON.stringify(_effectApp.S.encodeSync(schema)(_.evt))}`);
|
|
18
|
+
const stream = (0, _effectApp.pipe)(setRetry, _effectApp.Stream.merge(keepAlive), _effectApp.Stream.merge(eventStream), _effectApp.Stream.map(_ => enc.encode(_ + "\n\n")));
|
|
19
|
+
const ctx = yield* _effectApp.Effect.context();
|
|
20
|
+
const res = _http.HttpServerResponse.stream(stream.pipe(_effectApp.Stream.tapErrorCause((0, _errorReporter.reportError)("Request")), _effectApp.Stream.provideContext(ctx)), {
|
|
21
|
+
contentType: "text/event-stream",
|
|
22
|
+
headers: _http.HttpHeaders.fromInput({
|
|
23
|
+
"content-type": "text/event-stream",
|
|
24
|
+
"cache-control": "no-cache",
|
|
25
|
+
"x-accel-buffering": "no",
|
|
26
|
+
"connection": "keep-alive" // if (req.httpVersion !== "2.0")
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
return res;
|
|
30
|
+
}).pipe(_effectApp.Effect.tapErrorCause((0, _errorReporter.reportError)("Request")), _ => (0, _setupRequest.setupRequestContext)(_, "events"));
|
|
31
|
+
exports.makeSSE = makeSSE;
|
|
32
|
+
//# sourceMappingURL=events.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.cjs","names":["_setupRequest","require","_errorReporter","_effectApp","_http","setRetry","Stream","succeed","keepAlive","schedule","Effect","Schedule","fixed","Duration","seconds","makeSSE","events","schema","gen","logInfo","enc","TextEncoder","eventStream","map","_","evt","id","JSON","stringify","S","encodeSync","stream","pipe","merge","encode","ctx","context","res","HttpServerResponse","tapErrorCause","reportError","provideContext","contentType","headers","HttpHeaders","fromInput","setupRequestContext","exports"],"sources":["../../../src/api/internal/events.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AACA,IAAAG,KAAA,GAAAH,OAAA;AAEA;AACA,MAAMI,QAAQ,GAAGC,iBAAM,CAACC,OAAO,CAAC,cAAc,CAAC;AAC/C,MAAMC,SAAS,GAAGF,iBAAM,CAACG,QAAQ,CAACC,iBAAM,CAACH,OAAO,CAAC,aAAa,CAAC,EAAEI,mBAAQ,CAACC,KAAK,CAACC,mBAAQ,CAACC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AAE/F,MAAMC,OAAO,GAAGA,CAAiCC,MAAyD,EAAEC,MAAuB,KAAKP,iBAAM,CAClJQ,GAAG,CAAC,aAAS;EACZ,OAAOR,iBAAM,CAACS,OAAO,CAAC,6BAA6B,CAAC;EAEpD,MAAMC,GAAG,GAAG,IAAIC,WAAW,EAAE;EAE7B,MAAMC,WAAW,GAAGhB,iBAAM,CAACiB,GAAG,CAC5BP,MAAM,EACLQ,CAAC,IAAK,OAAOA,CAAC,CAACC,GAAG,CAACC,EAAE,WAAWC,IAAI,CAACC,SAAS,CAACC,YAAC,CAACC,UAAU,CAACb,MAAM,CAAC,CAACO,CAAC,CAACC,GAAG,CAAC,CAAC,EAAE,CAC/E;EAED,MAAMM,MAAM,GAAG,IAAAC,eAAI,EACjB3B,QAAQ,EACRC,iBAAM,CAAC2B,KAAK,CAACzB,SAAS,CAAC,EACvBF,iBAAM,CAAC2B,KAAK,CAACX,WAAW,CAAC,EACzBhB,iBAAM,CAACiB,GAAG,CAAEC,CAAC,IAAKJ,GAAG,CAACc,MAAM,CAACV,CAAC,GAAG,MAAM,CAAC,CAAC,CAC1C;EAED,MAAMW,GAAG,GAAG,OAAOzB,iBAAM,CAAC0B,OAAO,EAAK;EACtC,MAAMC,GAAG,GAAGC,wBAAkB,CAACP,MAAM,CACnCA,MAAM,CACHC,IAAI,CACH1B,iBAAM,CAACiC,aAAa,CAAC,IAAAC,0BAAW,EAAC,SAAS,CAAC,CAAC,EAC5ClC,iBAAM,CAACmC,cAAc,CAACN,GAAG,CAAC,CAC3B,EACH;IACEO,WAAW,EAAE,mBAAmB;IAChCC,OAAO,EAAEC,iBAAW,CAACC,SAAS,CAAC;MAC7B,cAAc,EAAE,mBAAmB;MACnC,eAAe,EAAE,UAAU;MAC3B,mBAAmB,EAAE,IAAI;MACzB,YAAY,EAAE,YAAY,CAAC;KAC5B;GACF,CACF;EACD,OAAOR,GAAG;AACZ,CAAC,CAAC,CACDL,IAAI,CAACtB,iBAAM,CAAC6B,aAAa,CAAC,IAAAC,0BAAW,EAAC,SAAS,CAAC,CAAC,EAAGhB,CAAC,IAAK,IAAAsB,iCAAmB,EAACtB,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAAuB,OAAA,CAAAhC,OAAA,GAAAA,OAAA","ignoreList":[]}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.uuidLogAnnotation = exports.toServerResponse = exports.errorLog = exports.endpointCallsMetric = exports.cors = exports.basicAuth = exports.accessLog = void 0;
|
|
7
|
+
var crypto = _interopRequireWildcard(require("crypto"));
|
|
8
|
+
var _utils = require("@effect-app/core/utils");
|
|
9
|
+
var _errors = require("@effect-app/infra/errors");
|
|
10
|
+
var Middleware = _interopRequireWildcard(require("@effect/platform/HttpMiddleware"));
|
|
11
|
+
var HttpServerRequest = _interopRequireWildcard(require("@effect/platform/HttpServerRequest"));
|
|
12
|
+
var ServerResponse = _interopRequireWildcard(require("@effect/platform/HttpServerResponse"));
|
|
13
|
+
var _effectApp = require("effect-app");
|
|
14
|
+
var _http = require("effect-app/http");
|
|
15
|
+
var Either = _interopRequireWildcard(require("effect/Either"));
|
|
16
|
+
var FiberRef = _interopRequireWildcard(require("effect/FiberRef"));
|
|
17
|
+
var _Function = require("effect/Function");
|
|
18
|
+
var HashMap = _interopRequireWildcard(require("effect/HashMap"));
|
|
19
|
+
var Metric = _interopRequireWildcard(require("effect/Metric"));
|
|
20
|
+
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); }
|
|
21
|
+
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; }
|
|
22
|
+
/**
|
|
23
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
24
|
+
*
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const accessLog = (level = "Info") => Middleware.make(app => (0, _Function.pipe)(HttpServerRequest.HttpServerRequest, _effectApp.Effect.flatMap(request => _effectApp.Effect[`log${level}`](`${request.method} ${request.url}`)), _effectApp.Effect.flatMap(() => app)));
|
|
29
|
+
exports.accessLog = accessLog;
|
|
30
|
+
const uuidLogAnnotation = (logAnnotationKey = "requestId") => Middleware.make(app => (0, _Function.pipe)(_effectApp.Effect.sync(() => crypto.randomUUID()), _effectApp.Effect.flatMap(uuid => FiberRef.update(FiberRef.currentLogAnnotations, HashMap.set(logAnnotationKey, uuid))), _effectApp.Effect.flatMap(() => app)));
|
|
31
|
+
exports.uuidLogAnnotation = uuidLogAnnotation;
|
|
32
|
+
const endpointCallsMetric = () => {
|
|
33
|
+
const endpointCalledCounter = Metric.counter("server.endpoint_calls");
|
|
34
|
+
return Middleware.make(app => _effectApp.Effect.gen(function* (_) {
|
|
35
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
36
|
+
yield* _(Metric.increment(endpointCalledCounter), _effectApp.Effect.tagMetrics("path", request.url));
|
|
37
|
+
return yield* _(app);
|
|
38
|
+
}));
|
|
39
|
+
};
|
|
40
|
+
exports.endpointCallsMetric = endpointCallsMetric;
|
|
41
|
+
const errorLog = exports.errorLog = Middleware.make(app => _effectApp.Effect.gen(function* (_) {
|
|
42
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
43
|
+
const response = yield* _(app);
|
|
44
|
+
if (response.status >= 400 && response.status < 500) {
|
|
45
|
+
yield* _(_effectApp.Effect.logWarning(`${request.method.toUpperCase()} ${request.url} client error ${response.status}`));
|
|
46
|
+
} else if (response.status >= 500) {
|
|
47
|
+
yield* _(_effectApp.Effect.logError(`${request.method.toUpperCase()} ${request.url} server error ${response.status}`));
|
|
48
|
+
}
|
|
49
|
+
return response;
|
|
50
|
+
}));
|
|
51
|
+
const toServerResponse = err => _http.HttpServerResponse.empty().pipe(_http.HttpServerResponse.setStatus(401), _http.HttpServerResponse.setBody(_http.HttpBody.unsafeJson({
|
|
52
|
+
message: err.message
|
|
53
|
+
})));
|
|
54
|
+
exports.toServerResponse = toServerResponse;
|
|
55
|
+
const basicAuth = (checkCredentials, options) => Middleware.make(app => _effectApp.Effect.gen(function* (_) {
|
|
56
|
+
const headerName = options?.headerName ?? "Authorization";
|
|
57
|
+
const skippedPaths = options?.skipPaths ?? [];
|
|
58
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
59
|
+
if (skippedPaths.includes(request.url)) {
|
|
60
|
+
return yield* _(app);
|
|
61
|
+
}
|
|
62
|
+
const authHeader = request.headers[headerName.toLowerCase()];
|
|
63
|
+
if (authHeader === undefined) {
|
|
64
|
+
return toServerResponse(new _errors.NotLoggedInError(`Expected header ${headerName}`));
|
|
65
|
+
}
|
|
66
|
+
const authorizationParts = authHeader.split(" ");
|
|
67
|
+
if (authorizationParts.length !== 2) {
|
|
68
|
+
return toServerResponse(new _errors.NotLoggedInError("Incorrect auhorization scheme. Expected \"Basic <credentials>\""));
|
|
69
|
+
}
|
|
70
|
+
if (authorizationParts[0] !== "Basic") {
|
|
71
|
+
return toServerResponse(new _errors.NotLoggedInError(`Incorrect auhorization type. Expected "Basic", got "${authorizationParts[0]}"`));
|
|
72
|
+
}
|
|
73
|
+
const credentialsBuffer = Buffer.from(authorizationParts[1], "base64");
|
|
74
|
+
const credentialsText = credentialsBuffer.toString("utf-8");
|
|
75
|
+
const credentialsParts = credentialsText.split(":");
|
|
76
|
+
if (credentialsParts.length !== 2) {
|
|
77
|
+
return toServerResponse(new _errors.NotLoggedInError("Incorrect basic auth credentials format. Expected base64 encoded \"<user>:<pass>\"."));
|
|
78
|
+
}
|
|
79
|
+
const check = yield* _(checkCredentials({
|
|
80
|
+
user: credentialsParts[0],
|
|
81
|
+
password: credentialsParts[1]
|
|
82
|
+
}), _effectApp.Effect.either);
|
|
83
|
+
if (Either.isLeft(check)) {
|
|
84
|
+
return toServerResponse(check.left);
|
|
85
|
+
}
|
|
86
|
+
return yield* _(app);
|
|
87
|
+
}));
|
|
88
|
+
exports.basicAuth = basicAuth;
|
|
89
|
+
const cors = _options => {
|
|
90
|
+
const DEFAULTS = {
|
|
91
|
+
allowedOrigins: ["*"],
|
|
92
|
+
allowedMethods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
|
93
|
+
allowedHeaders: [],
|
|
94
|
+
exposedHeaders: [],
|
|
95
|
+
credentials: false
|
|
96
|
+
};
|
|
97
|
+
const options = {
|
|
98
|
+
...DEFAULTS,
|
|
99
|
+
..._options
|
|
100
|
+
};
|
|
101
|
+
const isAllowedOrigin = origin => {
|
|
102
|
+
return options.allowedOrigins.includes(origin);
|
|
103
|
+
};
|
|
104
|
+
const allowOrigin = originHeader => {
|
|
105
|
+
if (options.allowedOrigins.length === 0) {
|
|
106
|
+
return {
|
|
107
|
+
"Access-Control-Allow-Origin": "*"
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (options.allowedOrigins.length === 1) {
|
|
111
|
+
return {
|
|
112
|
+
"Access-Control-Allow-Origin": options.allowedOrigins[0],
|
|
113
|
+
Vary: "Origin"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (isAllowedOrigin(originHeader)) {
|
|
117
|
+
return {
|
|
118
|
+
"Access-Control-Allow-Origin": originHeader,
|
|
119
|
+
Vary: "Origin"
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
};
|
|
124
|
+
const allowMethods = (() => {
|
|
125
|
+
if (options.allowedMethods.length > 0) {
|
|
126
|
+
return {
|
|
127
|
+
"Access-Control-Allow-Methods": options.allowedMethods.join(", ")
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
})();
|
|
132
|
+
const allowCredentials = (() => {
|
|
133
|
+
if (options.credentials) {
|
|
134
|
+
return {
|
|
135
|
+
"Access-Control-Allow-Credentials": "true"
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
})();
|
|
140
|
+
const allowHeaders = accessControlRequestHeaders => {
|
|
141
|
+
if (options.allowedHeaders.length === 0 && accessControlRequestHeaders) {
|
|
142
|
+
return {
|
|
143
|
+
Vary: "Access-Control-Request-Headers",
|
|
144
|
+
"Access-Control-Allow-Headers": accessControlRequestHeaders
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (options.allowedHeaders) {
|
|
148
|
+
return {
|
|
149
|
+
"Access-Control-Allow-Headers": options.allowedHeaders.join(",")
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
};
|
|
154
|
+
const exposeHeaders = (() => {
|
|
155
|
+
if (options.exposedHeaders.length > 0) {
|
|
156
|
+
return {
|
|
157
|
+
"Access-Control-Expose-Headers": options.exposedHeaders.join(",")
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
})();
|
|
162
|
+
const maxAge = (() => {
|
|
163
|
+
if (options.maxAge) {
|
|
164
|
+
return {
|
|
165
|
+
"Access-Control-Max-Age": options.maxAge.toString()
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return undefined;
|
|
169
|
+
})();
|
|
170
|
+
return Middleware.make(app => _effectApp.Effect.gen(function* (_) {
|
|
171
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
172
|
+
const origin = request.headers["origin"];
|
|
173
|
+
const accessControlRequestHeaders = request.headers["access-control-request-headers"];
|
|
174
|
+
let corsHeaders = {
|
|
175
|
+
...allowOrigin(origin ?? ""),
|
|
176
|
+
...allowCredentials,
|
|
177
|
+
...exposeHeaders
|
|
178
|
+
};
|
|
179
|
+
if (request.method === "OPTIONS") {
|
|
180
|
+
corsHeaders = {
|
|
181
|
+
...corsHeaders,
|
|
182
|
+
...allowMethods,
|
|
183
|
+
...allowHeaders(accessControlRequestHeaders),
|
|
184
|
+
...maxAge
|
|
185
|
+
};
|
|
186
|
+
return ServerResponse.empty({
|
|
187
|
+
status: 204,
|
|
188
|
+
headers: _http.HttpHeaders.fromInput((0, _utils.dropUndefined)(corsHeaders))
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const response = yield* _(app);
|
|
192
|
+
return response.pipe(ServerResponse.setHeaders((0, _utils.dropUndefined)(corsHeaders)));
|
|
193
|
+
}));
|
|
194
|
+
};
|
|
195
|
+
exports.cors = cors;
|
|
196
|
+
//# sourceMappingURL=middlewares.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.cjs","names":["crypto","_interopRequireWildcard","require","_utils","_errors","Middleware","HttpServerRequest","ServerResponse","_effectApp","_http","Either","FiberRef","_Function","HashMap","Metric","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","accessLog","level","make","app","pipe","Effect","flatMap","request","method","url","exports","uuidLogAnnotation","logAnnotationKey","sync","randomUUID","uuid","update","currentLogAnnotations","endpointCallsMetric","endpointCalledCounter","counter","gen","_","increment","tagMetrics","errorLog","response","status","logWarning","toUpperCase","logError","toServerResponse","err","HttpServerResponse","empty","setStatus","setBody","HttpBody","unsafeJson","message","basicAuth","checkCredentials","options","headerName","skippedPaths","skipPaths","includes","authHeader","headers","toLowerCase","undefined","NotLoggedInError","authorizationParts","split","length","credentialsBuffer","Buffer","from","credentialsText","toString","credentialsParts","check","user","password","either","isLeft","left","cors","_options","DEFAULTS","allowedOrigins","allowedMethods","allowedHeaders","exposedHeaders","credentials","isAllowedOrigin","origin","allowOrigin","originHeader","Vary","allowMethods","join","allowCredentials","allowHeaders","accessControlRequestHeaders","exposeHeaders","maxAge","corsHeaders","HttpHeaders","fromInput","dropUndefined","setHeaders"],"sources":["../../../src/api/internal/middlewares.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
accessLog: true,
|
|
8
|
+
uuidLogAnnotation: true,
|
|
9
|
+
endpointCallsMetric: true,
|
|
10
|
+
errorLog: true,
|
|
11
|
+
basicAuth: true,
|
|
12
|
+
cors: true
|
|
13
|
+
};
|
|
14
|
+
exports.uuidLogAnnotation = exports.errorLog = exports.endpointCallsMetric = exports.cors = exports.basicAuth = exports.accessLog = void 0;
|
|
15
|
+
var internal = _interopRequireWildcard(require("./internal/middlewares.cjs"));
|
|
16
|
+
var _events = require("./internal/events.cjs");
|
|
17
|
+
Object.keys(_events).forEach(function (key) {
|
|
18
|
+
if (key === "default" || key === "__esModule") return;
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
20
|
+
if (key in exports && exports[key] === _events[key]) return;
|
|
21
|
+
Object.defineProperty(exports, key, {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return _events[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
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); }
|
|
29
|
+
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; }
|
|
30
|
+
/**
|
|
31
|
+
* Add access logs for handled requests. The log runs before each request.
|
|
32
|
+
* Optionally configure log level using the first argument. The default log level
|
|
33
|
+
* is `Debug`.
|
|
34
|
+
*
|
|
35
|
+
* @category logging
|
|
36
|
+
* @since 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
const accessLog = exports.accessLog = internal.accessLog;
|
|
39
|
+
/**
|
|
40
|
+
* Annotate request logs using generated UUID. The default annotation key is `requestId`.
|
|
41
|
+
* The annotation key is configurable using the first argument.
|
|
42
|
+
*
|
|
43
|
+
* Note that in order to apply the annotation also for access logging, you should
|
|
44
|
+
* make sure the `accessLog` middleware is plugged after the `uuidLogAnnotation`.
|
|
45
|
+
*
|
|
46
|
+
* @category logging
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
const uuidLogAnnotation = exports.uuidLogAnnotation = internal.uuidLogAnnotation;
|
|
50
|
+
/**
|
|
51
|
+
* Measure how many times each endpoint was called in a
|
|
52
|
+
* `server.endpoint_calls` counter metrics.
|
|
53
|
+
*
|
|
54
|
+
* @category metrics
|
|
55
|
+
* @since 1.0.0
|
|
56
|
+
*/
|
|
57
|
+
const endpointCallsMetric = exports.endpointCallsMetric = internal.endpointCallsMetric;
|
|
58
|
+
/**
|
|
59
|
+
* Logs out a handler failure.
|
|
60
|
+
*
|
|
61
|
+
* @category logging
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
*/
|
|
64
|
+
const errorLog = exports.errorLog = internal.errorLog;
|
|
65
|
+
/**
|
|
66
|
+
* Basic auth middleware.
|
|
67
|
+
*
|
|
68
|
+
* @category authorization
|
|
69
|
+
* @since 1.0.0
|
|
70
|
+
*/
|
|
71
|
+
const basicAuth = exports.basicAuth = internal.basicAuth;
|
|
72
|
+
/**
|
|
73
|
+
* Basic auth middleware.
|
|
74
|
+
*
|
|
75
|
+
* @category authorization
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
*/
|
|
78
|
+
const cors = exports.cors = internal.cors;
|
|
79
|
+
//# sourceMappingURL=middlewares.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.cjs","names":["internal","_interopRequireWildcard","require","_events","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","n","__proto__","a","getOwnPropertyDescriptor","u","i","set","accessLog","uuidLogAnnotation","endpointCallsMetric","errorLog","basicAuth","cors"],"sources":["../../src/api/middlewares.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;AAQA,IAAAA,QAAA,GAAAC,uBAAA,CAAAC,OAAA;AAEA,IAAAC,OAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,OAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,OAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,OAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAAoC,SAAAS,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAhB,wBAAAgB,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAK,OAAA,EAAAL,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAG,GAAA,CAAAN,CAAA,UAAAG,CAAA,CAAAL,GAAA,CAAAE,CAAA,OAAAO,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAtB,MAAA,CAAAS,cAAA,IAAAT,MAAA,CAAAuB,wBAAA,WAAAC,CAAA,IAAAX,CAAA,oBAAAW,CAAA,OAAAnB,cAAA,CAAAC,IAAA,CAAAO,CAAA,EAAAW,CAAA,SAAAC,CAAA,GAAAH,CAAA,GAAAtB,MAAA,CAAAuB,wBAAA,CAAAV,CAAA,EAAAW,CAAA,UAAAC,CAAA,KAAAA,CAAA,CAAAd,GAAA,IAAAc,CAAA,CAAAC,GAAA,IAAA1B,MAAA,CAAAS,cAAA,CAAAW,CAAA,EAAAI,CAAA,EAAAC,CAAA,IAAAL,CAAA,CAAAI,CAAA,IAAAX,CAAA,CAAAW,CAAA,YAAAJ,CAAA,CAAAF,OAAA,GAAAL,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAU,GAAA,CAAAb,CAAA,EAAAO,CAAA,GAAAA,CAAA;AAEpC;;;;;;;;AAQO,MAAMO,SAAS,GAAAnB,OAAA,CAAAmB,SAAA,GAEqC/B,QAAQ,CAAC+B,SAAS;AAE7E;;;;;;;;;;AAUO,MAAMC,iBAAiB,GAAApB,OAAA,CAAAoB,iBAAA,GAE6BhC,QAAQ,CAACgC,iBAAiB;AAErF;;;;;;;AAOO,MAAMC,mBAAmB,GAAArB,OAAA,CAAAqB,mBAAA,GAEPjC,QAAQ,CAACiC,mBAAmB;AAErD;;;;;;AAMO,MAAMC,QAAQ,GAAAtB,OAAA,CAAAsB,QAAA,GAAwDlC,QAAQ,CAACkC,QAAQ;AAW9F;;;;;;AAMO,MAAMC,SAAS,GAAAvB,OAAA,CAAAuB,SAAA,GAQ6CnC,QAAQ,CAACmC,SAAS;AAerF;;;;;;AAMO,MAAMC,IAAI,GAAAxB,OAAA,CAAAwB,IAAA,GAE0CpC,QAAQ,CAACoC,IAAI","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Effect, S, Stream } from "effect-app";
|
|
2
|
+
import { HttpServerResponse } from "effect-app/http";
|
|
3
|
+
export declare const makeSSE: <A extends {
|
|
4
|
+
id: any;
|
|
5
|
+
}, E, R, SI>(events: Stream.Stream<{
|
|
6
|
+
evt: A;
|
|
7
|
+
namespace: string;
|
|
8
|
+
}, E, R>, schema: S.Schema<A, SI>) => Effect.Effect<HttpServerResponse.HttpServerResponse, never, import("../../services/RequestContextContainer.js").RequestContextContainer | import("../../services/Store/ContextMapContainer.js").ContextMapContainer | Exclude<Exclude<R, import("effect/Tracer").ParentSpan>, never>>;
|
|
9
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/api/internal/events.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,MAAM,EAAQ,CAAC,EAAY,MAAM,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,EAAe,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAMjE,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS;IAAE,EAAE,EAAE,GAAG,CAAA;CAAE,EAAE,CAAC,EAAC,CAAC,EAAE,EAAE,UAAU,MAAM,CAAC,MAAM,CAAC;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,0RAqC5C,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { setupRequestContext } from "@effect-app/infra/api/setupRequest";
|
|
2
|
+
import { reportError } from "@effect-app/infra/errorReporter";
|
|
3
|
+
import { Duration, Effect, pipe, S, Schedule, Stream } from "effect-app";
|
|
4
|
+
import { HttpHeaders, HttpServerResponse } from "effect-app/http";
|
|
5
|
+
// Tell the client to retry every 10 seconds if connectivity is lost
|
|
6
|
+
const setRetry = Stream.succeed("retry: 10000");
|
|
7
|
+
const keepAlive = Stream.schedule(Effect.succeed(":keep-alive"), Schedule.fixed(Duration.seconds(15)));
|
|
8
|
+
export const makeSSE = (events, schema) => Effect
|
|
9
|
+
.gen(function* () {
|
|
10
|
+
yield* Effect.logInfo("$ start listening to events");
|
|
11
|
+
const enc = new TextEncoder();
|
|
12
|
+
const eventStream = Stream.map(events, (_) => `id: ${_.evt.id}\ndata: ${JSON.stringify(S.encodeSync(schema)(_.evt))}`);
|
|
13
|
+
const stream = pipe(setRetry, Stream.merge(keepAlive), Stream.merge(eventStream), Stream.map((_) => enc.encode(_ + "\n\n")));
|
|
14
|
+
const ctx = yield* Effect.context();
|
|
15
|
+
const res = HttpServerResponse.stream(stream
|
|
16
|
+
.pipe(Stream.tapErrorCause(reportError("Request")), Stream.provideContext(ctx)), {
|
|
17
|
+
contentType: "text/event-stream",
|
|
18
|
+
headers: HttpHeaders.fromInput({
|
|
19
|
+
"content-type": "text/event-stream",
|
|
20
|
+
"cache-control": "no-cache",
|
|
21
|
+
"x-accel-buffering": "no",
|
|
22
|
+
"connection": "keep-alive" // if (req.httpVersion !== "2.0")
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
return res;
|
|
26
|
+
})
|
|
27
|
+
.pipe(Effect.tapErrorCause(reportError("Request")), (_) => setupRequestContext(_, "events"));
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9pbnRlcm5hbC9ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0NBQW9DLENBQUE7QUFDeEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFBO0FBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUN4RSxPQUFPLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFFakUsb0VBQW9FO0FBQ3BFLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7QUFDL0MsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFFdEcsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLENBQWlDLE1BQXlELEVBQUUsTUFBdUIsRUFBRSxFQUFFLENBQUMsTUFBTTtLQUNsSixHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ1osS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFBO0lBRXBELE1BQU0sR0FBRyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUE7SUFFN0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FDNUIsTUFBTSxFQUNOLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxXQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUMvRSxDQUFBO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUNqQixRQUFRLEVBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFDdkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFDekIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FDMUMsQ0FBQTtJQUVELE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUssQ0FBQTtJQUN0QyxNQUFNLEdBQUcsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQ25DLE1BQU07U0FDSCxJQUFJLENBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsRUFDNUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FDM0IsRUFDSDtRQUNFLFdBQVcsRUFBRSxtQkFBbUI7UUFDaEMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxTQUFTLENBQUM7WUFDN0IsY0FBYyxFQUFFLG1CQUFtQjtZQUNuQyxlQUFlLEVBQUUsVUFBVTtZQUMzQixtQkFBbUIsRUFBRSxJQUFJO1lBQ3pCLFlBQVksRUFBRSxZQUFZLENBQUMsaUNBQWlDO1NBQzdELENBQUM7S0FDSCxDQUNGLENBQUE7SUFDRCxPQUFPLEdBQUcsQ0FBQTtBQUNaLENBQUMsQ0FBQztLQUNELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQSJ9
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NotLoggedInError } from "@effect-app/infra/errors";
|
|
2
|
+
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
3
|
+
import * as ServerResponse from "@effect/platform/HttpServerResponse";
|
|
4
|
+
import { Effect } from "effect-app";
|
|
5
|
+
import type * as Middlewares from "../middlewares.js";
|
|
6
|
+
export declare const accessLog: (level?: "Info" | "Warning" | "Debug") => <E, R>(app: import("@effect/platform/HttpApp").Default<E, R>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R>;
|
|
7
|
+
export declare const uuidLogAnnotation: (logAnnotationKey?: string) => <E, R>(app: import("@effect/platform/HttpApp").Default<E, R>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R>;
|
|
8
|
+
export declare const endpointCallsMetric: () => <E, R>(app: import("@effect/platform/HttpApp").Default<E, R>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R>;
|
|
9
|
+
export declare const errorLog: <E, R>(app: import("@effect/platform/HttpApp").Default<E, R>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R>;
|
|
10
|
+
export declare const toServerResponse: (err: NotLoggedInError) => ServerResponse.HttpServerResponse;
|
|
11
|
+
export declare const basicAuth: <_, R>(checkCredentials: (credentials: Middlewares.BasicAuthCredentials) => Effect<_, NotLoggedInError, R>, options?: Partial<{
|
|
12
|
+
headerName: string;
|
|
13
|
+
skipPaths: readonly string[];
|
|
14
|
+
}>) => <E, R_1>(app: import("@effect/platform/HttpApp").Default<E, R_1>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R | R_1>;
|
|
15
|
+
export declare const cors: (_options?: Partial<Middlewares.CorsOptions>) => <E, R>(app: import("@effect/platform/HttpApp").Default<E, R>) => Effect.Effect<ServerResponse.HttpServerResponse, E, HttpServerRequest.HttpServerRequest | R>;
|
|
16
|
+
//# sourceMappingURL=middlewares.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../../src/api/internal/middlewares.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,iBAAiB,MAAM,oCAAoC,CAAA;AACvE,OAAO,KAAK,cAAc,MAAM,qCAAqC,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAOnC,OAAO,KAAK,KAAK,WAAW,MAAM,mBAAmB,CAAA;AAErD,eAAO,MAAM,SAAS,WAAW,MAAM,GAAG,SAAS,GAAG,OAAO,kKAO1D,CAAA;AAEH,eAAO,MAAM,iBAAiB,8LAY3B,CAAA;AAEH,eAAO,MAAM,mBAAmB,qKAe/B,CAAA;AAED,eAAO,MAAM,QAAQ,+JAsBpB,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAS,gBAAgB,sCAInD,CAAA;AAEH,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,oBACV,CAChB,WAAW,EAAE,WAAW,CAAC,oBAAoB,KAC1C,MAAM,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,YACzB,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B,CAAC,4KAkED,CAAA;AAEH,eAAO,MAAM,IAAI,cAAe,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,kKAuH/D,CAAA"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from "crypto";
|
|
7
|
+
import { dropUndefined } from "@effect-app/core/utils";
|
|
8
|
+
import { NotLoggedInError } from "@effect-app/infra/errors";
|
|
9
|
+
import * as Middleware from "@effect/platform/HttpMiddleware";
|
|
10
|
+
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
11
|
+
import * as ServerResponse from "@effect/platform/HttpServerResponse";
|
|
12
|
+
import { Effect } from "effect-app";
|
|
13
|
+
import { HttpBody, HttpHeaders, HttpServerResponse } from "effect-app/http";
|
|
14
|
+
import * as Either from "effect/Either";
|
|
15
|
+
import * as FiberRef from "effect/FiberRef";
|
|
16
|
+
import { pipe } from "effect/Function";
|
|
17
|
+
import * as HashMap from "effect/HashMap";
|
|
18
|
+
import * as Metric from "effect/Metric";
|
|
19
|
+
export const accessLog = (level = "Info") => Middleware.make((app) => pipe(HttpServerRequest.HttpServerRequest, Effect.flatMap((request) => Effect[`log${level}`](`${request.method} ${request.url}`)), Effect.flatMap(() => app)));
|
|
20
|
+
export const uuidLogAnnotation = (logAnnotationKey = "requestId") => Middleware.make((app) => pipe(Effect.sync(() => crypto.randomUUID()), Effect.flatMap((uuid) => FiberRef.update(FiberRef.currentLogAnnotations, HashMap.set(logAnnotationKey, uuid))), Effect.flatMap(() => app)));
|
|
21
|
+
export const endpointCallsMetric = () => {
|
|
22
|
+
const endpointCalledCounter = Metric.counter("server.endpoint_calls");
|
|
23
|
+
return Middleware.make((app) => Effect.gen(function* (_) {
|
|
24
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
25
|
+
yield* _(Metric.increment(endpointCalledCounter), Effect.tagMetrics("path", request.url));
|
|
26
|
+
return yield* _(app);
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
export const errorLog = Middleware.make((app) => Effect.gen(function* (_) {
|
|
30
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
31
|
+
const response = yield* _(app);
|
|
32
|
+
if (response.status >= 400 && response.status < 500) {
|
|
33
|
+
yield* _(Effect.logWarning(`${request.method.toUpperCase()} ${request.url} client error ${response.status}`));
|
|
34
|
+
}
|
|
35
|
+
else if (response.status >= 500) {
|
|
36
|
+
yield* _(Effect.logError(`${request.method.toUpperCase()} ${request.url} server error ${response.status}`));
|
|
37
|
+
}
|
|
38
|
+
return response;
|
|
39
|
+
}));
|
|
40
|
+
export const toServerResponse = (err) => HttpServerResponse.empty().pipe(HttpServerResponse.setStatus(401), HttpServerResponse.setBody(HttpBody.unsafeJson({ message: err.message })));
|
|
41
|
+
export const basicAuth = (checkCredentials, options) => Middleware.make((app) => Effect.gen(function* (_) {
|
|
42
|
+
const headerName = options?.headerName ?? "Authorization";
|
|
43
|
+
const skippedPaths = options?.skipPaths ?? [];
|
|
44
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
45
|
+
if (skippedPaths.includes(request.url)) {
|
|
46
|
+
return yield* _(app);
|
|
47
|
+
}
|
|
48
|
+
const authHeader = request.headers[headerName.toLowerCase()];
|
|
49
|
+
if (authHeader === undefined) {
|
|
50
|
+
return toServerResponse(new NotLoggedInError(`Expected header ${headerName}`));
|
|
51
|
+
}
|
|
52
|
+
const authorizationParts = authHeader.split(" ");
|
|
53
|
+
if (authorizationParts.length !== 2) {
|
|
54
|
+
return toServerResponse(new NotLoggedInError("Incorrect auhorization scheme. Expected \"Basic <credentials>\""));
|
|
55
|
+
}
|
|
56
|
+
if (authorizationParts[0] !== "Basic") {
|
|
57
|
+
return toServerResponse(new NotLoggedInError(`Incorrect auhorization type. Expected "Basic", got "${authorizationParts[0]}"`));
|
|
58
|
+
}
|
|
59
|
+
const credentialsBuffer = Buffer.from(authorizationParts[1], "base64");
|
|
60
|
+
const credentialsText = credentialsBuffer.toString("utf-8");
|
|
61
|
+
const credentialsParts = credentialsText.split(":");
|
|
62
|
+
if (credentialsParts.length !== 2) {
|
|
63
|
+
return toServerResponse(new NotLoggedInError("Incorrect basic auth credentials format. Expected base64 encoded \"<user>:<pass>\"."));
|
|
64
|
+
}
|
|
65
|
+
const check = yield* _(checkCredentials({
|
|
66
|
+
user: credentialsParts[0],
|
|
67
|
+
password: credentialsParts[1]
|
|
68
|
+
}), Effect.either);
|
|
69
|
+
if (Either.isLeft(check)) {
|
|
70
|
+
return toServerResponse(check.left);
|
|
71
|
+
}
|
|
72
|
+
return yield* _(app);
|
|
73
|
+
}));
|
|
74
|
+
export const cors = (_options) => {
|
|
75
|
+
const DEFAULTS = {
|
|
76
|
+
allowedOrigins: ["*"],
|
|
77
|
+
allowedMethods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
|
78
|
+
allowedHeaders: [],
|
|
79
|
+
exposedHeaders: [],
|
|
80
|
+
credentials: false
|
|
81
|
+
};
|
|
82
|
+
const options = { ...DEFAULTS, ..._options };
|
|
83
|
+
const isAllowedOrigin = (origin) => {
|
|
84
|
+
return options.allowedOrigins.includes(origin);
|
|
85
|
+
};
|
|
86
|
+
const allowOrigin = (originHeader) => {
|
|
87
|
+
if (options.allowedOrigins.length === 0) {
|
|
88
|
+
return { "Access-Control-Allow-Origin": "*" };
|
|
89
|
+
}
|
|
90
|
+
if (options.allowedOrigins.length === 1) {
|
|
91
|
+
return {
|
|
92
|
+
"Access-Control-Allow-Origin": options.allowedOrigins[0],
|
|
93
|
+
Vary: "Origin"
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (isAllowedOrigin(originHeader)) {
|
|
97
|
+
return {
|
|
98
|
+
"Access-Control-Allow-Origin": originHeader,
|
|
99
|
+
Vary: "Origin"
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
104
|
+
const allowMethods = (() => {
|
|
105
|
+
if (options.allowedMethods.length > 0) {
|
|
106
|
+
return {
|
|
107
|
+
"Access-Control-Allow-Methods": options.allowedMethods.join(", ")
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
})();
|
|
112
|
+
const allowCredentials = (() => {
|
|
113
|
+
if (options.credentials) {
|
|
114
|
+
return { "Access-Control-Allow-Credentials": "true" };
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
})();
|
|
118
|
+
const allowHeaders = (accessControlRequestHeaders) => {
|
|
119
|
+
if (options.allowedHeaders.length === 0 && accessControlRequestHeaders) {
|
|
120
|
+
return {
|
|
121
|
+
Vary: "Access-Control-Request-Headers",
|
|
122
|
+
"Access-Control-Allow-Headers": accessControlRequestHeaders
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (options.allowedHeaders) {
|
|
126
|
+
return {
|
|
127
|
+
"Access-Control-Allow-Headers": options.allowedHeaders.join(",")
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
};
|
|
132
|
+
const exposeHeaders = (() => {
|
|
133
|
+
if (options.exposedHeaders.length > 0) {
|
|
134
|
+
return {
|
|
135
|
+
"Access-Control-Expose-Headers": options.exposedHeaders.join(",")
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
})();
|
|
140
|
+
const maxAge = (() => {
|
|
141
|
+
if (options.maxAge) {
|
|
142
|
+
return { "Access-Control-Max-Age": options.maxAge.toString() };
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
})();
|
|
146
|
+
return Middleware.make((app) => Effect.gen(function* (_) {
|
|
147
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest);
|
|
148
|
+
const origin = request.headers["origin"];
|
|
149
|
+
const accessControlRequestHeaders = request.headers["access-control-request-headers"];
|
|
150
|
+
let corsHeaders = {
|
|
151
|
+
...allowOrigin(origin ?? ""),
|
|
152
|
+
...allowCredentials,
|
|
153
|
+
...exposeHeaders
|
|
154
|
+
};
|
|
155
|
+
if (request.method === "OPTIONS") {
|
|
156
|
+
corsHeaders = {
|
|
157
|
+
...corsHeaders,
|
|
158
|
+
...allowMethods,
|
|
159
|
+
...allowHeaders(accessControlRequestHeaders),
|
|
160
|
+
...maxAge
|
|
161
|
+
};
|
|
162
|
+
return ServerResponse.empty({ status: 204, headers: HttpHeaders.fromInput(dropUndefined(corsHeaders)) });
|
|
163
|
+
}
|
|
164
|
+
const response = yield* _(app);
|
|
165
|
+
return response.pipe(ServerResponse.setHeaders(dropUndefined(corsHeaders)));
|
|
166
|
+
}));
|
|
167
|
+
};
|
|
168
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL2ludGVybmFsL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQTtBQUVoQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDdEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDM0QsT0FBTyxLQUFLLFVBQVUsTUFBTSxpQ0FBaUMsQ0FBQTtBQUM3RCxPQUFPLEtBQUssaUJBQWlCLE1BQU0sb0NBQW9DLENBQUE7QUFDdkUsT0FBTyxLQUFLLGNBQWMsTUFBTSxxQ0FBcUMsQ0FBQTtBQUNyRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQ25DLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDM0UsT0FBTyxLQUFLLE1BQU0sTUFBTSxlQUFlLENBQUE7QUFDdkMsT0FBTyxLQUFLLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDdEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxnQkFBZ0IsQ0FBQTtBQUN6QyxPQUFPLEtBQUssTUFBTSxNQUFNLGVBQWUsQ0FBQTtBQUd2QyxNQUFNLENBQUMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxRQUFzQyxNQUFNLEVBQUUsRUFBRSxDQUN4RSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FDdEIsSUFBSSxDQUNGLGlCQUFpQixDQUFDLGlCQUFpQixFQUNuQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLEVBQUUsQ0FBQyxD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
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import type * as App from "@effect/platform/HttpApp";
|
|
7
|
+
import type { Effect } from "effect-app";
|
|
8
|
+
import type { NotLoggedInError } from "../errors.js";
|
|
9
|
+
export * from "./internal/events.js";
|
|
10
|
+
/**
|
|
11
|
+
* Add access logs for handled requests. The log runs before each request.
|
|
12
|
+
* Optionally configure log level using the first argument. The default log level
|
|
13
|
+
* is `Debug`.
|
|
14
|
+
*
|
|
15
|
+
* @category logging
|
|
16
|
+
* @since 1.0.0
|
|
17
|
+
*/
|
|
18
|
+
export declare const accessLog: (level?: "Info" | "Warning" | "Debug") => <R, E>(app: App.Default<R, E>) => App.Default<R, E>;
|
|
19
|
+
/**
|
|
20
|
+
* Annotate request logs using generated UUID. The default annotation key is `requestId`.
|
|
21
|
+
* The annotation key is configurable using the first argument.
|
|
22
|
+
*
|
|
23
|
+
* Note that in order to apply the annotation also for access logging, you should
|
|
24
|
+
* make sure the `accessLog` middleware is plugged after the `uuidLogAnnotation`.
|
|
25
|
+
*
|
|
26
|
+
* @category logging
|
|
27
|
+
* @since 1.0.0
|
|
28
|
+
*/
|
|
29
|
+
export declare const uuidLogAnnotation: (logAnnotationKey?: string) => <R, E>(app: App.Default<R, E>) => App.Default<R, E>;
|
|
30
|
+
/**
|
|
31
|
+
* Measure how many times each endpoint was called in a
|
|
32
|
+
* `server.endpoint_calls` counter metrics.
|
|
33
|
+
*
|
|
34
|
+
* @category metrics
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
*/
|
|
37
|
+
export declare const endpointCallsMetric: () => <R, E>(app: App.Default<R, E>) => App.Default<R, E>;
|
|
38
|
+
/**
|
|
39
|
+
* Logs out a handler failure.
|
|
40
|
+
*
|
|
41
|
+
* @category logging
|
|
42
|
+
* @since 1.0.0
|
|
43
|
+
*/
|
|
44
|
+
export declare const errorLog: <R, E>(app: App.Default<R, E>) => App.Default<R, E>;
|
|
45
|
+
/**
|
|
46
|
+
* @category models
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
export interface BasicAuthCredentials {
|
|
50
|
+
user: string;
|
|
51
|
+
password: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Basic auth middleware.
|
|
55
|
+
*
|
|
56
|
+
* @category authorization
|
|
57
|
+
* @since 1.0.0
|
|
58
|
+
*/
|
|
59
|
+
export declare const basicAuth: <R2, _>(checkCredentials: (credentials: BasicAuthCredentials) => Effect<_, NotLoggedInError, R2>, options?: Partial<{
|
|
60
|
+
headerName: string;
|
|
61
|
+
skipPaths: readonly string[];
|
|
62
|
+
}>) => <R1, E>(app: App.Default<E, R1>) => App.Default<E, R1 | R2>;
|
|
63
|
+
/**
|
|
64
|
+
* @category models
|
|
65
|
+
* @since 1.0.0
|
|
66
|
+
*/
|
|
67
|
+
export interface CorsOptions {
|
|
68
|
+
allowedOrigins: readonly string[];
|
|
69
|
+
allowedMethods: readonly string[];
|
|
70
|
+
allowedHeaders: readonly string[];
|
|
71
|
+
exposedHeaders: readonly string[];
|
|
72
|
+
maxAge: number;
|
|
73
|
+
credentials: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Basic auth middleware.
|
|
77
|
+
*
|
|
78
|
+
* @category authorization
|
|
79
|
+
* @since 1.0.0
|
|
80
|
+
*/
|
|
81
|
+
export declare const cors: (options?: Partial<CorsOptions>) => <R, E>(app: App.Default<R, E>) => App.Default<R, E>;
|
|
82
|
+
//# sourceMappingURL=middlewares.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/api/middlewares.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGpD,cAAc,sBAAsB,CAAA;AAEpC;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,CACtB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,KACjC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAsB,CAAA;AAE7E;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,CAC9B,gBAAgB,CAAC,EAAE,MAAM,KACtB,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAA8B,CAAA;AAErF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAC3C,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KACnB,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAgC,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAqB,CAAA;AAE9F;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,EAC5B,gBAAgB,EAAE,CAChB,WAAW,EAAE,oBAAoB,KAC9B,MAAM,CAAC,CAAC,EAAE,gBAAgB,EAAE,EAAE,CAAC,EACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B,CAAC,KACC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAsB,CAAA;AAErF;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,OAAO,CAAA;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,CACjB,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,KAC3B,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAiB,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as internal from "./internal/middlewares.js";
|
|
2
|
+
export * from "./internal/events.js";
|
|
3
|
+
/**
|
|
4
|
+
* Add access logs for handled requests. The log runs before each request.
|
|
5
|
+
* Optionally configure log level using the first argument. The default log level
|
|
6
|
+
* is `Debug`.
|
|
7
|
+
*
|
|
8
|
+
* @category logging
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
export const accessLog = internal.accessLog;
|
|
12
|
+
/**
|
|
13
|
+
* Annotate request logs using generated UUID. The default annotation key is `requestId`.
|
|
14
|
+
* The annotation key is configurable using the first argument.
|
|
15
|
+
*
|
|
16
|
+
* Note that in order to apply the annotation also for access logging, you should
|
|
17
|
+
* make sure the `accessLog` middleware is plugged after the `uuidLogAnnotation`.
|
|
18
|
+
*
|
|
19
|
+
* @category logging
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
*/
|
|
22
|
+
export const uuidLogAnnotation = internal.uuidLogAnnotation;
|
|
23
|
+
/**
|
|
24
|
+
* Measure how many times each endpoint was called in a
|
|
25
|
+
* `server.endpoint_calls` counter metrics.
|
|
26
|
+
*
|
|
27
|
+
* @category metrics
|
|
28
|
+
* @since 1.0.0
|
|
29
|
+
*/
|
|
30
|
+
export const endpointCallsMetric = internal.endpointCallsMetric;
|
|
31
|
+
/**
|
|
32
|
+
* Logs out a handler failure.
|
|
33
|
+
*
|
|
34
|
+
* @category logging
|
|
35
|
+
* @since 1.0.0
|
|
36
|
+
*/
|
|
37
|
+
export const errorLog = internal.errorLog;
|
|
38
|
+
/**
|
|
39
|
+
* Basic auth middleware.
|
|
40
|
+
*
|
|
41
|
+
* @category authorization
|
|
42
|
+
* @since 1.0.0
|
|
43
|
+
*/
|
|
44
|
+
export const basicAuth = internal.basicAuth;
|
|
45
|
+
/**
|
|
46
|
+
* Basic auth middleware.
|
|
47
|
+
*
|
|
48
|
+
* @category authorization
|
|
49
|
+
* @since 1.0.0
|
|
50
|
+
*/
|
|
51
|
+
export const cors = internal.cors;
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sS0FBSyxRQUFRLE1BQU0sMkJBQTJCLENBQUE7QUFFckQsY0FBYyxzQkFBc0IsQ0FBQTtBQUVwQzs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUVxQyxRQUFRLENBQUMsU0FBUyxDQUFBO0FBRTdFOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUU2QixRQUFRLENBQUMsaUJBQWlCLENBQUE7QUFFckY7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBRVAsUUFBUSxDQUFDLG1CQUFtQixDQUFBO0FBRXJEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUF3RCxRQUFRLENBQUMsUUFBUSxDQUFBO0FBVzlGOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQVE2QyxRQUFRLENBQUMsU0FBUyxDQUFBO0FBZXJGOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUUwQyxRQUFRLENBQUMsSUFBSSxDQUFBIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"proper-lockfile": "^4.1.2",
|
|
19
19
|
"pure-rand": "6.1.0",
|
|
20
20
|
"redlock": "^4.2.0",
|
|
21
|
-
"@effect-app/core": "1.10.1",
|
|
22
21
|
"@effect-app/infra-adapters": "1.11.3",
|
|
22
|
+
"@effect-app/schema": "1.12.1",
|
|
23
23
|
"effect-app": "1.17.1",
|
|
24
|
-
"@effect-app/
|
|
24
|
+
"@effect-app/core": "1.10.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@babel/cli": "^7.25.6",
|
|
@@ -95,6 +95,16 @@
|
|
|
95
95
|
"default": "./_cjs/api/codec.cjs"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
|
+
"./api/middlewares": {
|
|
99
|
+
"import": {
|
|
100
|
+
"types": "./dist/api/middlewares.d.ts",
|
|
101
|
+
"default": "./dist/api/middlewares.js"
|
|
102
|
+
},
|
|
103
|
+
"require": {
|
|
104
|
+
"types": "./dist/api/middlewares.d.ts",
|
|
105
|
+
"default": "./_cjs/api/middlewares.cjs"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
98
108
|
"./api/reportError": {
|
|
99
109
|
"import": {
|
|
100
110
|
"types": "./dist/api/reportError.d.ts",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { setupRequestContext } from "@effect-app/infra/api/setupRequest"
|
|
2
|
+
import { reportError } from "@effect-app/infra/errorReporter"
|
|
3
|
+
import { Duration, Effect, pipe, S, Schedule, Stream } from "effect-app"
|
|
4
|
+
import { HttpHeaders, HttpServerResponse } from "effect-app/http"
|
|
5
|
+
|
|
6
|
+
// Tell the client to retry every 10 seconds if connectivity is lost
|
|
7
|
+
const setRetry = Stream.succeed("retry: 10000")
|
|
8
|
+
const keepAlive = Stream.schedule(Effect.succeed(":keep-alive"), Schedule.fixed(Duration.seconds(15)))
|
|
9
|
+
|
|
10
|
+
export const makeSSE = <A extends { id: any }, E,R, SI>(events: Stream.Stream<{ evt: A, namespace: string}, E, R>, schema: S.Schema<A, SI>) => Effect
|
|
11
|
+
.gen(function*() {
|
|
12
|
+
yield* Effect.logInfo("$ start listening to events")
|
|
13
|
+
|
|
14
|
+
const enc = new TextEncoder()
|
|
15
|
+
|
|
16
|
+
const eventStream = Stream.map(
|
|
17
|
+
events,
|
|
18
|
+
(_) => `id: ${_.evt.id}\ndata: ${JSON.stringify(S.encodeSync(schema)(_.evt))}`
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const stream = pipe(
|
|
22
|
+
setRetry,
|
|
23
|
+
Stream.merge(keepAlive),
|
|
24
|
+
Stream.merge(eventStream),
|
|
25
|
+
Stream.map((_) => enc.encode(_ + "\n\n"))
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
const ctx = yield* Effect.context<R>()
|
|
29
|
+
const res = HttpServerResponse.stream(
|
|
30
|
+
stream
|
|
31
|
+
.pipe(
|
|
32
|
+
Stream.tapErrorCause(reportError("Request")),
|
|
33
|
+
Stream.provideContext(ctx)
|
|
34
|
+
),
|
|
35
|
+
{
|
|
36
|
+
contentType: "text/event-stream",
|
|
37
|
+
headers: HttpHeaders.fromInput({
|
|
38
|
+
"content-type": "text/event-stream",
|
|
39
|
+
"cache-control": "no-cache",
|
|
40
|
+
"x-accel-buffering": "no",
|
|
41
|
+
"connection": "keep-alive" // if (req.httpVersion !== "2.0")
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
return res
|
|
46
|
+
})
|
|
47
|
+
.pipe(Effect.tapErrorCause(reportError("Request")), (_) => setupRequestContext(_, "events"))
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from "crypto"
|
|
7
|
+
|
|
8
|
+
import { dropUndefined } from "@effect-app/core/utils"
|
|
9
|
+
import { NotLoggedInError } from "@effect-app/infra/errors"
|
|
10
|
+
import * as Middleware from "@effect/platform/HttpMiddleware"
|
|
11
|
+
import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
|
|
12
|
+
import * as ServerResponse from "@effect/platform/HttpServerResponse"
|
|
13
|
+
import { Effect } from "effect-app"
|
|
14
|
+
import { HttpBody, HttpHeaders, HttpServerResponse } from "effect-app/http"
|
|
15
|
+
import * as Either from "effect/Either"
|
|
16
|
+
import * as FiberRef from "effect/FiberRef"
|
|
17
|
+
import { pipe } from "effect/Function"
|
|
18
|
+
import * as HashMap from "effect/HashMap"
|
|
19
|
+
import * as Metric from "effect/Metric"
|
|
20
|
+
import type * as Middlewares from "../middlewares.js"
|
|
21
|
+
|
|
22
|
+
export const accessLog = (level: "Info" | "Warning" | "Debug" = "Info") =>
|
|
23
|
+
Middleware.make((app) =>
|
|
24
|
+
pipe(
|
|
25
|
+
HttpServerRequest.HttpServerRequest,
|
|
26
|
+
Effect.flatMap((request) => Effect[`log${level}`](`${request.method} ${request.url}`)),
|
|
27
|
+
Effect.flatMap(() => app)
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
export const uuidLogAnnotation = (logAnnotationKey = "requestId") =>
|
|
32
|
+
Middleware.make((app) =>
|
|
33
|
+
pipe(
|
|
34
|
+
Effect.sync(() => crypto.randomUUID()),
|
|
35
|
+
Effect.flatMap((uuid) =>
|
|
36
|
+
FiberRef.update(
|
|
37
|
+
FiberRef.currentLogAnnotations,
|
|
38
|
+
HashMap.set<string, unknown>(logAnnotationKey, uuid)
|
|
39
|
+
)
|
|
40
|
+
),
|
|
41
|
+
Effect.flatMap(() => app)
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
export const endpointCallsMetric = () => {
|
|
46
|
+
const endpointCalledCounter = Metric.counter("server.endpoint_calls")
|
|
47
|
+
|
|
48
|
+
return Middleware.make((app) =>
|
|
49
|
+
Effect.gen(function*(_) {
|
|
50
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest)
|
|
51
|
+
|
|
52
|
+
yield* _(
|
|
53
|
+
Metric.increment(endpointCalledCounter),
|
|
54
|
+
Effect.tagMetrics("path", request.url)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return yield* _(app)
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const errorLog = Middleware.make((app) =>
|
|
63
|
+
Effect.gen(function*(_) {
|
|
64
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest)
|
|
65
|
+
|
|
66
|
+
const response = yield* _(app)
|
|
67
|
+
|
|
68
|
+
if (response.status >= 400 && response.status < 500) {
|
|
69
|
+
yield* _(
|
|
70
|
+
Effect.logWarning(
|
|
71
|
+
`${request.method.toUpperCase()} ${request.url} client error ${response.status}`
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
} else if (response.status >= 500) {
|
|
75
|
+
yield* _(
|
|
76
|
+
Effect.logError(
|
|
77
|
+
`${request.method.toUpperCase()} ${request.url} server error ${response.status}`
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return response
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
export const toServerResponse = (err: NotLoggedInError) =>
|
|
87
|
+
HttpServerResponse.empty().pipe(
|
|
88
|
+
HttpServerResponse.setStatus(401),
|
|
89
|
+
HttpServerResponse.setBody(HttpBody.unsafeJson({ message: err.message }))
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
export const basicAuth = <_, R>(
|
|
93
|
+
checkCredentials: (
|
|
94
|
+
credentials: Middlewares.BasicAuthCredentials
|
|
95
|
+
) => Effect<_, NotLoggedInError, R>,
|
|
96
|
+
options?: Partial<{
|
|
97
|
+
headerName: string
|
|
98
|
+
skipPaths: readonly string[]
|
|
99
|
+
}>
|
|
100
|
+
) =>
|
|
101
|
+
Middleware.make((app) =>
|
|
102
|
+
Effect.gen(function*(_) {
|
|
103
|
+
const headerName = options?.headerName ?? "Authorization"
|
|
104
|
+
const skippedPaths = options?.skipPaths ?? []
|
|
105
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest)
|
|
106
|
+
|
|
107
|
+
if (skippedPaths.includes(request.url)) {
|
|
108
|
+
return yield* _(app)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const authHeader = request.headers[headerName.toLowerCase()]
|
|
112
|
+
|
|
113
|
+
if (authHeader === undefined) {
|
|
114
|
+
return toServerResponse(
|
|
115
|
+
new NotLoggedInError(
|
|
116
|
+
`Expected header ${headerName}`
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const authorizationParts = authHeader.split(" ")
|
|
122
|
+
|
|
123
|
+
if (authorizationParts.length !== 2) {
|
|
124
|
+
return toServerResponse(
|
|
125
|
+
new NotLoggedInError(
|
|
126
|
+
"Incorrect auhorization scheme. Expected \"Basic <credentials>\""
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (authorizationParts[0] !== "Basic") {
|
|
132
|
+
return toServerResponse(
|
|
133
|
+
new NotLoggedInError(
|
|
134
|
+
`Incorrect auhorization type. Expected "Basic", got "${authorizationParts[0]}"`
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const credentialsBuffer = Buffer.from(authorizationParts[1]!, "base64")
|
|
140
|
+
const credentialsText = credentialsBuffer.toString("utf-8")
|
|
141
|
+
const credentialsParts = credentialsText.split(":")
|
|
142
|
+
|
|
143
|
+
if (credentialsParts.length !== 2) {
|
|
144
|
+
return toServerResponse(
|
|
145
|
+
new NotLoggedInError(
|
|
146
|
+
"Incorrect basic auth credentials format. Expected base64 encoded \"<user>:<pass>\"."
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const check = yield* _(
|
|
152
|
+
checkCredentials({
|
|
153
|
+
user: credentialsParts[0],
|
|
154
|
+
password: credentialsParts[1]!
|
|
155
|
+
}),
|
|
156
|
+
Effect.either
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if (Either.isLeft(check)) {
|
|
160
|
+
return toServerResponse(check.left)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return yield* _(app)
|
|
164
|
+
})
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
export const cors = (_options?: Partial<Middlewares.CorsOptions>) => {
|
|
168
|
+
const DEFAULTS = {
|
|
169
|
+
allowedOrigins: ["*"],
|
|
170
|
+
allowedMethods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
|
171
|
+
allowedHeaders: [],
|
|
172
|
+
exposedHeaders: [],
|
|
173
|
+
credentials: false
|
|
174
|
+
} as const
|
|
175
|
+
|
|
176
|
+
const options = { ...DEFAULTS, ..._options }
|
|
177
|
+
|
|
178
|
+
const isAllowedOrigin = (origin: string) => {
|
|
179
|
+
return options.allowedOrigins.includes(origin)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const allowOrigin = (originHeader: string) => {
|
|
183
|
+
if (options.allowedOrigins.length === 0) {
|
|
184
|
+
return { "Access-Control-Allow-Origin": "*" }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (options.allowedOrigins.length === 1) {
|
|
188
|
+
return {
|
|
189
|
+
"Access-Control-Allow-Origin": options.allowedOrigins[0],
|
|
190
|
+
Vary: "Origin"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (isAllowedOrigin(originHeader)) {
|
|
195
|
+
return {
|
|
196
|
+
"Access-Control-Allow-Origin": originHeader,
|
|
197
|
+
Vary: "Origin"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return undefined
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const allowMethods = (() => {
|
|
205
|
+
if (options.allowedMethods.length > 0) {
|
|
206
|
+
return {
|
|
207
|
+
"Access-Control-Allow-Methods": options.allowedMethods.join(", ")
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return undefined
|
|
212
|
+
})()
|
|
213
|
+
|
|
214
|
+
const allowCredentials = (() => {
|
|
215
|
+
if (options.credentials) {
|
|
216
|
+
return { "Access-Control-Allow-Credentials": "true" }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return undefined
|
|
220
|
+
})()
|
|
221
|
+
|
|
222
|
+
const allowHeaders = (accessControlRequestHeaders: string | undefined) => {
|
|
223
|
+
if (options.allowedHeaders.length === 0 && accessControlRequestHeaders) {
|
|
224
|
+
return {
|
|
225
|
+
Vary: "Access-Control-Request-Headers",
|
|
226
|
+
"Access-Control-Allow-Headers": accessControlRequestHeaders
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (options.allowedHeaders) {
|
|
231
|
+
return {
|
|
232
|
+
"Access-Control-Allow-Headers": options.allowedHeaders.join(",")
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return undefined
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const exposeHeaders = (() => {
|
|
240
|
+
if (options.exposedHeaders.length > 0) {
|
|
241
|
+
return {
|
|
242
|
+
"Access-Control-Expose-Headers": options.exposedHeaders.join(",")
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return undefined
|
|
247
|
+
})()
|
|
248
|
+
|
|
249
|
+
const maxAge = (() => {
|
|
250
|
+
if (options.maxAge) {
|
|
251
|
+
return { "Access-Control-Max-Age": options.maxAge.toString() }
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return undefined
|
|
255
|
+
})()
|
|
256
|
+
|
|
257
|
+
return Middleware.make((app) =>
|
|
258
|
+
Effect.gen(function*(_) {
|
|
259
|
+
const request = yield* _(HttpServerRequest.HttpServerRequest)
|
|
260
|
+
|
|
261
|
+
const origin = request.headers["origin"]
|
|
262
|
+
const accessControlRequestHeaders = request.headers["access-control-request-headers"]
|
|
263
|
+
|
|
264
|
+
let corsHeaders = {
|
|
265
|
+
...allowOrigin(origin ?? ""),
|
|
266
|
+
...allowCredentials,
|
|
267
|
+
...exposeHeaders
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (request.method === "OPTIONS") {
|
|
271
|
+
corsHeaders = {
|
|
272
|
+
...corsHeaders,
|
|
273
|
+
...allowMethods,
|
|
274
|
+
...allowHeaders(accessControlRequestHeaders),
|
|
275
|
+
...maxAge
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return ServerResponse.empty({ status: 204, headers: HttpHeaders.fromInput(dropUndefined(corsHeaders)) })
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const response = yield* _(app)
|
|
282
|
+
|
|
283
|
+
return response.pipe(ServerResponse.setHeaders(dropUndefined(corsHeaders)))
|
|
284
|
+
})
|
|
285
|
+
)
|
|
286
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
import type * as App from "@effect/platform/HttpApp"
|
|
7
|
+
import type { Effect } from "effect-app"
|
|
8
|
+
import type { NotLoggedInError } from "../errors.js"
|
|
9
|
+
import * as internal from "./internal/middlewares.js"
|
|
10
|
+
|
|
11
|
+
export * from "./internal/events.js"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Add access logs for handled requests. The log runs before each request.
|
|
15
|
+
* Optionally configure log level using the first argument. The default log level
|
|
16
|
+
* is `Debug`.
|
|
17
|
+
*
|
|
18
|
+
* @category logging
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
export const accessLog: (
|
|
22
|
+
level?: "Info" | "Warning" | "Debug"
|
|
23
|
+
) => <R, E>(app: App.Default<R, E>) => App.Default<R, E> = internal.accessLog
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Annotate request logs using generated UUID. The default annotation key is `requestId`.
|
|
27
|
+
* The annotation key is configurable using the first argument.
|
|
28
|
+
*
|
|
29
|
+
* Note that in order to apply the annotation also for access logging, you should
|
|
30
|
+
* make sure the `accessLog` middleware is plugged after the `uuidLogAnnotation`.
|
|
31
|
+
*
|
|
32
|
+
* @category logging
|
|
33
|
+
* @since 1.0.0
|
|
34
|
+
*/
|
|
35
|
+
export const uuidLogAnnotation: (
|
|
36
|
+
logAnnotationKey?: string
|
|
37
|
+
) => <R, E>(app: App.Default<R, E>) => App.Default<R, E> = internal.uuidLogAnnotation
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Measure how many times each endpoint was called in a
|
|
41
|
+
* `server.endpoint_calls` counter metrics.
|
|
42
|
+
*
|
|
43
|
+
* @category metrics
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
*/
|
|
46
|
+
export const endpointCallsMetric: () => <R, E>(
|
|
47
|
+
app: App.Default<R, E>
|
|
48
|
+
) => App.Default<R, E> = internal.endpointCallsMetric
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Logs out a handler failure.
|
|
52
|
+
*
|
|
53
|
+
* @category logging
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
export const errorLog: <R, E>(app: App.Default<R, E>) => App.Default<R, E> = internal.errorLog
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @category models
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
*/
|
|
62
|
+
export interface BasicAuthCredentials {
|
|
63
|
+
user: string
|
|
64
|
+
password: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Basic auth middleware.
|
|
69
|
+
*
|
|
70
|
+
* @category authorization
|
|
71
|
+
* @since 1.0.0
|
|
72
|
+
*/
|
|
73
|
+
export const basicAuth: <R2, _>(
|
|
74
|
+
checkCredentials: (
|
|
75
|
+
credentials: BasicAuthCredentials
|
|
76
|
+
) => Effect<_, NotLoggedInError, R2>,
|
|
77
|
+
options?: Partial<{
|
|
78
|
+
headerName: string
|
|
79
|
+
skipPaths: readonly string[]
|
|
80
|
+
}>
|
|
81
|
+
) => <R1, E>(app: App.Default<E, R1>) => App.Default<E, R1 | R2> = internal.basicAuth
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @category models
|
|
85
|
+
* @since 1.0.0
|
|
86
|
+
*/
|
|
87
|
+
export interface CorsOptions {
|
|
88
|
+
allowedOrigins: readonly string[]
|
|
89
|
+
allowedMethods: readonly string[]
|
|
90
|
+
allowedHeaders: readonly string[]
|
|
91
|
+
exposedHeaders: readonly string[]
|
|
92
|
+
maxAge: number
|
|
93
|
+
credentials: boolean
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Basic auth middleware.
|
|
98
|
+
*
|
|
99
|
+
* @category authorization
|
|
100
|
+
* @since 1.0.0
|
|
101
|
+
*/
|
|
102
|
+
export const cors: (
|
|
103
|
+
options?: Partial<CorsOptions>
|
|
104
|
+
) => <R, E>(app: App.Default<R, E>) => App.Default<R, E> = internal.cors
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// packages/infra/vitest.config.ts
|
|
2
|
+
import { defineConfig } from "file:///Users/patrickroza/pj/effect-app/libs/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30/node_modules/vite/dist/node/index.js";
|
|
3
|
+
|
|
4
|
+
// vite.config.base.ts
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
var __vite_injected_original_dirname = "/Users/patrickroza/pj/effect-app/libs";
|
|
8
|
+
function makeConfig(dirName) {
|
|
9
|
+
const prefix = path.resolve(__vite_injected_original_dirname, "packages");
|
|
10
|
+
const packages = fs.readdirSync(prefix).map((f) => prefix + "/" + f).filter((f) => fs.lstatSync(f).isDirectory());
|
|
11
|
+
const cfg = {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
13
|
+
//plugins: [autoImport],
|
|
14
|
+
test: {
|
|
15
|
+
include: ["./test/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
16
|
+
reporters: "verbose",
|
|
17
|
+
globals: true
|
|
18
|
+
},
|
|
19
|
+
resolve: {
|
|
20
|
+
alias: packages.reduce((acc, cur) => {
|
|
21
|
+
acc[JSON.parse(fs.readFileSync(cur + "/package.json", "utf-8")).name] = path.resolve(cur, cur.endsWith("core") ? "dist" : "src");
|
|
22
|
+
return acc;
|
|
23
|
+
}, {})
|
|
24
|
+
// "@effect-app/core/Prelude": path.join(__dirname, "packages/core/src/Prelude.code.ts")
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
console.log(cfg);
|
|
28
|
+
return cfg;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// packages/infra/vitest.config.ts
|
|
32
|
+
var __vite_injected_original_dirname2 = "/Users/patrickroza/pj/effect-app/libs/packages/infra";
|
|
33
|
+
var vitest_config_default = defineConfig(makeConfig(__vite_injected_original_dirname2));
|
|
34
|
+
export {
|
|
35
|
+
vitest_config_default as default
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50cyIsICJ2aXRlLmNvbmZpZy5iYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYS92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlXCJcbmltcG9ydCBtYWtlQ29uZmlnIGZyb20gXCIuLi8uLi92aXRlLmNvbmZpZy5iYXNlXCJcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKG1ha2VDb25maWcoX19kaXJuYW1lKSlcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlic1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy92aXRlLmNvbmZpZy5iYXNlLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCBmcyBmcm9tIFwiZnNcIlxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSBcInVucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGVcIlxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVzdC9jb25maWdcIlxuXG4vLyBjb25zdCBhdXRvSW1wb3J0ID0gQXV0b0ltcG9ydCh7XG4vLyAgIGR0czogXCIuL3Rlc3QvYXV0by1pbXBvcnRzLmQudHNcIixcbi8vICAgLy8gaW5jbHVkZTogW1xuLy8gICAvLyAgIC9cXC50ZXN0XFwuW3RqXXN4PyQvIC8vIC50cywgLnRzeCwgLmpzLCAuanN4XG4vLyAgIC8vIF0sXG4vLyAgIGltcG9ydHM6IFtcbi8vICAgICBcInZpdGVzdFwiXG4vLyAgIF1cbi8vIH0pXG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIG1ha2VDb25maWcoZGlyTmFtZT86IHN0cmluZykge1xuICBjb25zdCBwcmVmaXggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcInBhY2thZ2VzXCIpXG4gIGNvbnN0IHBhY2thZ2VzID0gZnMucmVhZGRpclN5bmMocHJlZml4KS5tYXAoZiA9PiBwcmVmaXggKyBcIi9cIiArIGYpLmZpbHRlcihmID0+IGZzLmxzdGF0U3luYyhmKS5pc0RpcmVjdG9yeSgpIClcbiAgY29uc3QgY2ZnID0ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgLy9wbHVnaW5zOiBbYXV0b0ltcG9ydF0sXG4gICAgdGVzdDoge1xuICAgICAgaW5jbHVkZTogIFtcIi4vdGVzdC8qKi8qLnRlc3Que2pzLG1qcyxjanMsdHMsbXRzLGN0cyxqc3gsdHN4fVwiXSxcbiAgICAgIHJlcG9ydGVyczogXCJ2ZXJib3NlXCIsXG4gICAgICBnbG9iYWxzOiB0cnVlXG4gICAgfSxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczogcGFja2FnZXMucmVkdWNlKChhY2MsIGN1cikgPT4geyAvLyB3b3JrYXJvdW5kIGZvciAvUHJlbHVkZSBpc3N1ZVxuICAgICAgYWNjW0pTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGN1ciArIFwiL3BhY2thZ2UuanNvblwiLCBcInV0Zi04XCIpKS5uYW1lXSA9IHBhdGgucmVzb2x2ZShjdXIsIGN1ci5lbmRzV2l0aChcImNvcmVcIikgPyBcImRpc3RcIiA6IFwic3JjXCIpXG4gICAgICByZXR1cm4gYWNjXG4gICAgfSwgeyB9KSAvLyBcIkBlZmZlY3QtYXBwL2NvcmUvUHJlbHVkZVwiOiBwYXRoLmpvaW4oX19kaXJuYW1lLCBcInBhY2thZ2VzL2NvcmUvc3JjL1ByZWx1ZGUuY29kZS50c1wiKVxuICB9XG4gIH1cbiAgY29uc29sZS5sb2coY2ZnKVxuICByZXR1cm4gY2ZnXG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUyxvQkFBb0I7OztBQ0E3QixPQUFPLFVBQVU7QUFDakIsT0FBTyxRQUFRO0FBRmYsSUFBTSxtQ0FBbUM7QUFnQjFCLFNBQVIsV0FBNEIsU0FBa0I7QUFDbkQsUUFBTSxTQUFTLEtBQUssUUFBUSxrQ0FBVyxVQUFVO0FBQ2pELFFBQU0sV0FBVyxHQUFHLFlBQVksTUFBTSxFQUFFLElBQUksT0FBSyxTQUFTLE1BQU0sQ0FBQyxFQUFFLE9BQU8sT0FBSyxHQUFHLFVBQVUsQ0FBQyxFQUFFLFlBQVksQ0FBRTtBQUM3RyxRQUFNLE1BQU07QUFBQTtBQUFBO0FBQUEsSUFHVixNQUFNO0FBQUEsTUFDSixTQUFVLENBQUMsa0RBQWtEO0FBQUEsTUFDN0QsV0FBVztBQUFBLE1BQ1gsU0FBUztBQUFBLElBQ1g7QUFBQSxJQUNBLFNBQVM7QUFBQSxNQUNQLE9BQU8sU0FBUyxPQUFPLENBQUMsS0FBSyxRQUFRO0FBQ3JDLFlBQUksS0FBSyxNQUFNLEdBQUcsYUFBYSxNQUFNLGlCQUFpQixPQUFPLENBQUMsRUFBRSxJQUFJLElBQUksS0FBSyxRQUFRLEtBQUssSUFBSSxTQUFTLE1BQU0sSUFBSSxTQUFTLEtBQUs7QUFDL0gsZUFBTztBQUFBLE1BQ1QsR0FBRyxDQUFFLENBQUM7QUFBQTtBQUFBLElBQ1I7QUFBQSxFQUNBO0FBQ0EsVUFBUSxJQUFJLEdBQUc7QUFDZixTQUFPO0FBQ1Q7OztBRHBDQSxJQUFNQSxvQ0FBbUM7QUFJekMsSUFBTyx3QkFBUSxhQUFhLFdBQVdDLGlDQUFTLENBQUM7IiwKICAibmFtZXMiOiBbIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIiwgIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIl0KfQo=
|