@trayio/express 5.33.0 → 5.35.0-unstable.fd7158a
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/dist/http/ExpressHttpController.d.ts +3 -3
- package/dist/http/ExpressHttpController.d.ts.map +1 -1
- package/dist/http/ExpressHttpController.js +37 -63
- package/dist/http/ExpressHttpController.unit.test.js +12 -36
- package/dist/http/ExpressHttpServer.d.ts +0 -1
- package/dist/http/ExpressHttpServer.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Option } from 'effect';
|
|
2
2
|
import { Router } from 'express-serve-static-core';
|
|
3
3
|
import { HttpController } from '@trayio/commons/http/HttpController';
|
|
4
4
|
import { Logging } from '@trayio/commons/logging/Logging';
|
|
5
5
|
export declare class ExpressHttpController {
|
|
6
6
|
protected controller: HttpController;
|
|
7
7
|
protected baseTmpPathForUploadedFiles: string;
|
|
8
|
-
protected logger:
|
|
8
|
+
protected logger: Option.Option<Logging>;
|
|
9
9
|
protected maxFiles: number;
|
|
10
|
-
constructor(controller: HttpController, baseTmpPathForUploadedFiles: string, logger:
|
|
10
|
+
constructor(controller: HttpController, baseTmpPathForUploadedFiles: string | undefined, logger: Option.Option<Logging>, maxFiles?: number);
|
|
11
11
|
private addRoute;
|
|
12
12
|
addRoutes: (router: Router) => Router;
|
|
13
13
|
private parseRequestBody;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressHttpController.d.ts","sourceRoot":"","sources":["../../src/http/ExpressHttpController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpressHttpController.d.ts","sourceRoot":"","sources":["../../src/http/ExpressHttpController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AASnD,OAAO,EACN,cAAc,EAEd,MAAM,qCAAqC,CAAC;AAG7C,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAW1D,qBAAa,qBAAqB;IAEhC,SAAS,CAAC,UAAU,EAAE,cAAc;IACpC,SAAS,CAAC,2BAA2B,EAAE,MAAM;IAC7C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;IACxC,SAAS,CAAC,QAAQ,EAAE,MAAM;gBAHhB,UAAU,EAAE,cAAc,EAC1B,2BAA2B,EAAE,MAAM,YAAS,EAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9B,QAAQ,GAAE,MAAU;IAG/B,OAAO,CAAC,QAAQ,CAgGd;IAEF,SAAS,GAAI,QAAQ,MAAM,YAKzB;IAEF,OAAO,CAAC,gBAAgB,CAiBtB;IAGF,OAAO,CAAC,uBAAuB,CAI7B;IAEF,OAAO,CAAC,sBAAsB,CAmC1B;IAEJ,OAAO,CAAC,aAAa,CAenB;IAEF,OAAO,CAAC,YAAY,CAkBlB;IAEF,OAAO,CAAC,+BAA+B,CAWpC;CACH"}
|
|
@@ -1,35 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
28
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
6
|
exports.ExpressHttpController = void 0;
|
|
30
|
-
const
|
|
31
|
-
const E = __importStar(require("fp-ts/Either"));
|
|
32
|
-
const O = __importStar(require("fp-ts/Option"));
|
|
7
|
+
const effect_1 = require("effect");
|
|
33
8
|
const Http_1 = require("@trayio/commons/http/Http");
|
|
34
9
|
const BufferExtensions_1 = require("@trayio/commons/buffer/BufferExtensions");
|
|
35
10
|
const formidable_1 = __importDefault(require("formidable"));
|
|
@@ -60,7 +35,7 @@ class ExpressHttpController {
|
|
|
60
35
|
requestBody = await this.parseRequestBody(req);
|
|
61
36
|
}
|
|
62
37
|
catch (err) {
|
|
63
|
-
if (
|
|
38
|
+
if (effect_1.Option.isSome(this.logger)) {
|
|
64
39
|
this.logger.value.warning(`Issue in the request: ${err.message}`, {
|
|
65
40
|
path: req.path,
|
|
66
41
|
});
|
|
@@ -75,13 +50,13 @@ class ExpressHttpController {
|
|
|
75
50
|
error: `Invalid request: ${err.message}`,
|
|
76
51
|
});
|
|
77
52
|
}
|
|
78
|
-
const httpResponse = await endpoint.execute(this.logger)(Http_1.HttpRequest.create({
|
|
53
|
+
const httpResponse = await effect_1.Effect.runPromise(endpoint.execute(this.logger)(Http_1.HttpRequest.create({
|
|
79
54
|
headers,
|
|
80
55
|
pathParams: req.params,
|
|
81
56
|
queryString: req.query,
|
|
82
57
|
body: requestBody,
|
|
83
|
-
clientIp:
|
|
84
|
-
}))
|
|
58
|
+
clientIp: effect_1.Option.fromNullable(clientIp),
|
|
59
|
+
})));
|
|
85
60
|
const sanitizeHeaderValue = (value) => {
|
|
86
61
|
let processedValue = value;
|
|
87
62
|
if (Array.isArray(value)) {
|
|
@@ -130,11 +105,7 @@ class ExpressHttpController {
|
|
|
130
105
|
parseRequestBody = async (req) => {
|
|
131
106
|
const contentType = req.headers['content-type'];
|
|
132
107
|
if (contentType && contentType.startsWith('multipart/form-data')) {
|
|
133
|
-
|
|
134
|
-
const multiPartBody = E.getOrElse((error) => {
|
|
135
|
-
throw new Error(error.message);
|
|
136
|
-
})(multiPartResponse);
|
|
137
|
-
return multiPartBody;
|
|
108
|
+
return effect_1.Effect.runPromise(effect_1.Effect.mapError(this.parseMultipartFormData(req), (error) => new Error(error.message)));
|
|
138
109
|
}
|
|
139
110
|
return this.parseGeneralRequestBody(req);
|
|
140
111
|
};
|
|
@@ -143,34 +114,37 @@ class ExpressHttpController {
|
|
|
143
114
|
const body = Object.keys(req.body).length === 0 ? new ArrayBuffer(0) : req.body;
|
|
144
115
|
return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(body);
|
|
145
116
|
};
|
|
146
|
-
parseMultipartFormData = (req) =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
117
|
+
parseMultipartFormData = (req) => effect_1.Effect.tryPromise({
|
|
118
|
+
try: () => new Promise((resolve, reject) => {
|
|
119
|
+
/*
|
|
120
|
+
* NOTE: inorder to use any other underlying file storage other than node fs, we would have to use
|
|
121
|
+
* formidable's fileWriteStreamHandler option that enables formidable to write a file to a stream.
|
|
122
|
+
* When used the fileWriteStreamHandler option with passThrough stream, we ran into errors that we didn't have
|
|
123
|
+
* time to solve, but ideally, we would be using the FileStorage interface instead of letting formidable
|
|
124
|
+
* write to the file system directly.
|
|
125
|
+
*/
|
|
126
|
+
const form = (0, formidable_1.default)({
|
|
127
|
+
maxFiles: this.maxFiles,
|
|
128
|
+
maxFileSize: 100 * 1024 * 1024, // 100MB
|
|
129
|
+
minFileSize: 0,
|
|
130
|
+
allowEmptyFiles: true,
|
|
131
|
+
uploadDir: this.baseTmpPathForUploadedFiles,
|
|
132
|
+
});
|
|
133
|
+
form.parse(req, (err, fields, files) => {
|
|
134
|
+
if (err) {
|
|
135
|
+
reject(err);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const body = {
|
|
139
|
+
fields: this.flattenFields(fields),
|
|
140
|
+
files: this.flattenFiles(files),
|
|
141
|
+
};
|
|
142
|
+
resolve(body);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}),
|
|
146
|
+
catch: (error) => new Error(error.message),
|
|
147
|
+
});
|
|
174
148
|
flattenFields = (fields) => {
|
|
175
149
|
const flattenedFields = {};
|
|
176
150
|
Object.entries(fields).forEach(([key, value]) => {
|
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const effect_1 = require("effect");
|
|
26
4
|
const Http_1 = require("@trayio/commons/http/Http");
|
|
27
|
-
const O = __importStar(require("fp-ts/Option"));
|
|
28
|
-
const T = __importStar(require("fp-ts/Task"));
|
|
29
5
|
const stream_1 = require("stream");
|
|
30
6
|
const ExpressHttpController_1 = require("./ExpressHttpController");
|
|
31
7
|
describe('ExpressHttpController', () => {
|
|
@@ -42,7 +18,7 @@ describe('ExpressHttpController', () => {
|
|
|
42
18
|
mockHttpController = {
|
|
43
19
|
getEndpoints: jest.fn().mockReturnValue([mockEndpoint]),
|
|
44
20
|
};
|
|
45
|
-
expressHttpController = new ExpressHttpController_1.ExpressHttpController(mockHttpController, '/tmp',
|
|
21
|
+
expressHttpController = new ExpressHttpController_1.ExpressHttpController(mockHttpController, '/tmp', effect_1.Option.none());
|
|
46
22
|
mockRouter = {
|
|
47
23
|
get: jest.fn(),
|
|
48
24
|
post: jest.fn(),
|
|
@@ -106,7 +82,7 @@ describe('ExpressHttpController', () => {
|
|
|
106
82
|
headers: {},
|
|
107
83
|
body: mockResponse,
|
|
108
84
|
};
|
|
109
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
85
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
110
86
|
expressHttpController.addRoutes(mockRouter);
|
|
111
87
|
// eslint-disable-next-line prefer-destructuring
|
|
112
88
|
routeHandler = mockRouter.get.mock.calls[0][1];
|
|
@@ -123,7 +99,7 @@ describe('ExpressHttpController', () => {
|
|
|
123
99
|
},
|
|
124
100
|
}),
|
|
125
101
|
};
|
|
126
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
102
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
127
103
|
await routeHandler(mockReq, mockRes);
|
|
128
104
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value_with_control_chars');
|
|
129
105
|
});
|
|
@@ -139,7 +115,7 @@ describe('ExpressHttpController', () => {
|
|
|
139
115
|
},
|
|
140
116
|
}),
|
|
141
117
|
};
|
|
142
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
118
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
143
119
|
await routeHandler(mockReq, mockRes);
|
|
144
120
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value_with_line__breaks');
|
|
145
121
|
});
|
|
@@ -155,7 +131,7 @@ describe('ExpressHttpController', () => {
|
|
|
155
131
|
},
|
|
156
132
|
}),
|
|
157
133
|
};
|
|
158
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
134
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
159
135
|
await routeHandler(mockReq, mockRes);
|
|
160
136
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value"with\\quotes');
|
|
161
137
|
});
|
|
@@ -171,7 +147,7 @@ describe('ExpressHttpController', () => {
|
|
|
171
147
|
},
|
|
172
148
|
}),
|
|
173
149
|
};
|
|
174
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
150
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
175
151
|
await routeHandler(mockReq, mockRes);
|
|
176
152
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value with spaces');
|
|
177
153
|
});
|
|
@@ -187,7 +163,7 @@ describe('ExpressHttpController', () => {
|
|
|
187
163
|
},
|
|
188
164
|
}),
|
|
189
165
|
};
|
|
190
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
166
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
191
167
|
await routeHandler(mockReq, mockRes);
|
|
192
168
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value1,value2,value3');
|
|
193
169
|
});
|
|
@@ -203,7 +179,7 @@ describe('ExpressHttpController', () => {
|
|
|
203
179
|
},
|
|
204
180
|
}),
|
|
205
181
|
};
|
|
206
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
182
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
207
183
|
await routeHandler(mockReq, mockRes);
|
|
208
184
|
expect(mockRes.setHeader).toHaveBeenCalledWith('content-length', '123');
|
|
209
185
|
});
|
|
@@ -219,7 +195,7 @@ describe('ExpressHttpController', () => {
|
|
|
219
195
|
},
|
|
220
196
|
}),
|
|
221
197
|
};
|
|
222
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
198
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
223
199
|
await routeHandler(mockReq, mockRes);
|
|
224
200
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value_with__"multiple\\issues"');
|
|
225
201
|
});
|
|
@@ -235,7 +211,7 @@ describe('ExpressHttpController', () => {
|
|
|
235
211
|
},
|
|
236
212
|
}),
|
|
237
213
|
};
|
|
238
|
-
mockEndpoint.execute.mockReturnValue(() =>
|
|
214
|
+
mockEndpoint.execute.mockReturnValue(() => effect_1.Effect.succeed(httpResponse));
|
|
239
215
|
await routeHandler(mockReq, mockRes);
|
|
240
216
|
expect(mockRes.setHeader).toHaveBeenCalledWith('test-header', 'value_with_em_dash');
|
|
241
217
|
});
|
|
@@ -257,7 +233,7 @@ describe('ExpressHttpController', () => {
|
|
|
257
233
|
status: jest.fn().mockReturnThis(),
|
|
258
234
|
json: jest.fn().mockReturnThis(),
|
|
259
235
|
};
|
|
260
|
-
expressHttpController = new ExpressHttpController_1.ExpressHttpController(mockHttpController, '/tmp',
|
|
236
|
+
expressHttpController = new ExpressHttpController_1.ExpressHttpController(mockHttpController, '/tmp', effect_1.Option.some({
|
|
261
237
|
warning: jest.fn(),
|
|
262
238
|
}));
|
|
263
239
|
expressHttpController.addRoutes(mockRouter);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressHttpServer.d.ts","sourceRoot":"","sources":["../../src/http/ExpressHttpServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpressHttpServer.d.ts","sourceRoot":"","sources":["../../src/http/ExpressHttpServer.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,GAAG,QAAQ,MAAM,CAAC,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,UAAU,oBAAoB;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,CACpB,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC,eAAe,EAAE,OAAO,IAAI,CAAC,cAAc,CAAC,KACnE,SAAS,CAAC;CACf;AAED,eAAO,MAAM,WAAW,GACvB,aAAa,qBAAqB,EAAE,EACpC,SAAS,oBAAoB,yEA6D7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/express",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.35.0-unstable.fd7158a",
|
|
4
4
|
"description": "Express extensions and implementations",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": "./dist/*.js"
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@trayio/commons": "5.
|
|
17
|
+
"@trayio/commons": "5.35.0-unstable.fd7158a",
|
|
18
18
|
"@types/express-serve-static-core": "4.17.41",
|
|
19
19
|
"cors": "2.8.5",
|
|
20
|
+
"effect": "3.22.2",
|
|
20
21
|
"express": "4.20.0",
|
|
21
|
-
"formidable": "3.5.1"
|
|
22
|
-
"fp-ts": "2.12.3"
|
|
22
|
+
"formidable": "3.5.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/cors": "2.8.17",
|