@trayio/express 3.8.0 → 3.9.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.
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
35
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
27
  };
@@ -43,140 +34,142 @@ const BufferExtensions_1 = require("@trayio/commons/buffer/BufferExtensions");
43
34
  const formidable_1 = __importDefault(require("formidable"));
44
35
  const stream_1 = require("stream");
45
36
  class ExpressHttpController {
37
+ controller;
38
+ baseTmpPathForUploadedFiles;
46
39
  constructor(controller, baseTmpPathForUploadedFiles = '/tmp') {
47
40
  this.controller = controller;
48
41
  this.baseTmpPathForUploadedFiles = baseTmpPathForUploadedFiles;
49
- this.addRoute = (endpoint) => {
50
- const route = (req, res) => __awaiter(this, void 0, void 0, function* () {
51
- const headers = Object.entries(req.headers).reduce((acc, [key, value]) => {
52
- const newValue = typeof value === 'undefined' ? '' : value;
53
- return Object.assign(Object.assign({}, acc), { [key]: newValue });
54
- }, {});
55
- const requestBody = yield this.parseRequestBody(req);
56
- const httpResponse = yield endpoint.execute({
57
- headers,
58
- pathParams: req.params,
59
- queryString: req.query,
60
- body: requestBody,
61
- })();
62
- const response = Object.entries(httpResponse.headers)
63
- .reduce((acc, [key, value]) => acc.setHeader(key, value), res)
64
- .status(httpResponse.statusCode);
65
- httpResponse.body.pipe(response);
66
- });
67
- let method;
68
- switch (endpoint.method) {
69
- case Http_1.HttpMethod.Get:
70
- method = 'get';
71
- break;
72
- case Http_1.HttpMethod.Post:
73
- method = 'post';
74
- break;
75
- case Http_1.HttpMethod.Put:
76
- method = 'put';
77
- break;
78
- case Http_1.HttpMethod.Delete:
79
- method = 'delete';
80
- break;
81
- case Http_1.HttpMethod.Patch:
82
- method = 'patch';
83
- break;
84
- default:
85
- method = 'get';
86
- break;
87
- }
88
- return (router) => router[method](endpoint.path, route);
89
- };
90
- this.addRoutes = (router) => {
91
- this.controller
92
- .getEndpoints()
93
- .forEach((endpoint) => this.addRoute(endpoint)(router));
94
- return router;
42
+ }
43
+ addRoute = (endpoint) => {
44
+ const route = async (req, res) => {
45
+ const headers = Object.entries(req.headers).reduce((acc, [key, value]) => {
46
+ const newValue = typeof value === 'undefined' ? '' : value;
47
+ return {
48
+ ...acc,
49
+ [key]: newValue,
50
+ };
51
+ }, {});
52
+ const requestBody = await this.parseRequestBody(req);
53
+ const httpResponse = await endpoint.execute({
54
+ headers,
55
+ pathParams: req.params,
56
+ queryString: req.query,
57
+ body: requestBody,
58
+ })();
59
+ const response = Object.entries(httpResponse.headers)
60
+ .reduce((acc, [key, value]) => acc.setHeader(key, value), res)
61
+ .status(httpResponse.statusCode);
62
+ httpResponse.body.pipe(response);
95
63
  };
96
- this.parseRequestBody = (req) => __awaiter(this, void 0, void 0, function* () {
97
- const contentType = req.headers['content-type'];
98
- if (contentType && contentType.startsWith('multipart/form-data')) {
99
- const multiPartResponse = yield this.parseMultipartFormData(req)();
100
- const multiPartBody = E.getOrElse((error) => {
101
- throw new Error(error.message);
102
- })(multiPartResponse);
103
- return multiPartBody;
64
+ let method;
65
+ switch (endpoint.method) {
66
+ case Http_1.HttpMethod.Get:
67
+ method = 'get';
68
+ break;
69
+ case Http_1.HttpMethod.Post:
70
+ method = 'post';
71
+ break;
72
+ case Http_1.HttpMethod.Put:
73
+ method = 'put';
74
+ break;
75
+ case Http_1.HttpMethod.Delete:
76
+ method = 'delete';
77
+ break;
78
+ case Http_1.HttpMethod.Patch:
79
+ method = 'patch';
80
+ break;
81
+ default:
82
+ method = 'get';
83
+ break;
84
+ }
85
+ return (router) => router[method](endpoint.path, route);
86
+ };
87
+ addRoutes = (router) => {
88
+ this.controller
89
+ .getEndpoints()
90
+ .forEach((endpoint) => this.addRoute(endpoint)(router));
91
+ return router;
92
+ };
93
+ parseRequestBody = async (req) => {
94
+ const contentType = req.headers['content-type'];
95
+ if (contentType && contentType.startsWith('multipart/form-data')) {
96
+ const multiPartResponse = await this.parseMultipartFormData(req)();
97
+ const multiPartBody = E.getOrElse((error) => {
98
+ throw new Error(error.message);
99
+ })(multiPartResponse);
100
+ return multiPartBody;
101
+ }
102
+ return this.parseGeneralRequestBody(req);
103
+ };
104
+ // express defaults empty request body to an empty object, so we need to transform to an array buffer
105
+ parseGeneralRequestBody = (req) => {
106
+ const body = Object.keys(req.body).length === 0 ? new ArrayBuffer(0) : req.body;
107
+ return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(body);
108
+ };
109
+ parseMultipartFormData = (req) => TE.tryCatch(() => new Promise((resolve, reject) => {
110
+ /*
111
+ * NOTE: inorder to use any other underlying file storage other than node fs, we would have to use
112
+ * formidable's fileWriteStreamHandler option that enables formidable to write a file to a stream.
113
+ * When used the fileWriteStreamHandler option with passThrough stream, we ran into errors that we didn't have
114
+ * time to solve, but ideally, we would be using the FileStorage interface instead of letting formidable
115
+ * write to the file system directly.
116
+ */
117
+ const form = (0, formidable_1.default)({
118
+ maxFiles: 1,
119
+ maxFileSize: 50 * 1024 * 1024,
120
+ uploadDir: this.baseTmpPathForUploadedFiles,
121
+ });
122
+ form.parse(req, (err, fields, files) => {
123
+ if (err) {
124
+ reject(err);
125
+ }
126
+ else {
127
+ const body = {
128
+ fields: this.flattenFields(fields),
129
+ files: this.flattenFiles(files),
130
+ };
131
+ resolve(body);
104
132
  }
105
- return this.parseGeneralRequestBody(req);
106
133
  });
107
- // express defaults empty request body to an empty object, so we need to transform to an array buffer
108
- this.parseGeneralRequestBody = (req) => {
109
- const body = Object.keys(req.body).length === 0 ? new ArrayBuffer(0) : req.body;
110
- return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(body);
111
- };
112
- this.parseMultipartFormData = (req) => TE.tryCatch(() => new Promise((resolve, reject) => {
113
- /*
114
- * NOTE: inorder to use any other underlying file storage other than node fs, we would have to use
115
- * formidable's fileWriteStreamHandler option that enables formidable to write a file to a stream.
116
- * When used the fileWriteStreamHandler option with passThrough stream, we ran into errors that we didn't have
117
- * time to solve, but ideally, we would be using the FileStorage interface instead of letting formidable
118
- * write to the file system directly.
119
- */
120
- const form = (0, formidable_1.default)({
121
- maxFiles: 1,
122
- maxFileSize: 50 * 1024 * 1024,
123
- uploadDir: this.baseTmpPathForUploadedFiles,
124
- });
125
- form.parse(req, (err, fields, files) => {
126
- if (err) {
127
- reject(err);
128
- }
129
- else {
130
- const body = {
131
- fields: this.flattenFields(fields),
132
- files: this.flattenFiles(files),
133
- };
134
- resolve(body);
135
- }
136
- });
137
- }), (error) => new Error(error.message));
138
- this.flattenFields = (fields) => {
139
- const flattenedFields = {};
140
- Object.entries(fields).forEach(([key, value]) => {
141
- if (Array.isArray(value) && value.length > 1) {
142
- throw new Error(`Field ${key} has more than one value and is current not supported`);
143
- }
144
- if (Array.isArray(value)) {
145
- flattenedFields[key] = value.join(',');
146
- }
147
- else {
148
- flattenedFields[key] = value !== null && value !== void 0 ? value : '';
149
- }
150
- });
151
- return flattenedFields;
152
- };
153
- this.flattenFiles = (files) => {
154
- const flattenedFiles = {};
155
- Object.entries(files)
156
- .filter(([key, file]) => file !== null)
157
- .forEach(([key, file]) => {
158
- if (Array.isArray(file) && file.length > 1) {
159
- throw new Error(`Field ${key} has more than one file and is currently not supported`);
160
- }
161
- if (Array.isArray(file)) {
162
- const fileContent = this.convertFormidableFileToTrayFile(file[0]);
163
- flattenedFiles[key] = fileContent;
164
- }
165
- });
166
- return flattenedFiles;
167
- };
168
- this.convertFormidableFileToTrayFile = (file) => {
169
- var _a;
170
- return ({
171
- key: file.newFilename,
172
- metadata: {
173
- name: file.newFilename,
174
- contentType: (_a = file.mimetype) !== null && _a !== void 0 ? _a : undefined,
175
- size: file.size,
176
- },
177
- content: stream_1.Readable.from('0'),
178
- });
179
- };
180
- }
134
+ }), (error) => new Error(error.message));
135
+ flattenFields = (fields) => {
136
+ const flattenedFields = {};
137
+ Object.entries(fields).forEach(([key, value]) => {
138
+ if (Array.isArray(value) && value.length > 1) {
139
+ throw new Error(`Field ${key} has more than one value and is current not supported`);
140
+ }
141
+ if (Array.isArray(value)) {
142
+ flattenedFields[key] = value.join(',');
143
+ }
144
+ else {
145
+ flattenedFields[key] = value ?? '';
146
+ }
147
+ });
148
+ return flattenedFields;
149
+ };
150
+ flattenFiles = (files) => {
151
+ const flattenedFiles = {};
152
+ Object.entries(files)
153
+ .filter(([key, file]) => file !== null)
154
+ .forEach(([key, file]) => {
155
+ if (Array.isArray(file) && file.length > 1) {
156
+ throw new Error(`Field ${key} has more than one file and is currently not supported`);
157
+ }
158
+ if (Array.isArray(file)) {
159
+ const fileContent = this.convertFormidableFileToTrayFile(file[0]);
160
+ flattenedFiles[key] = fileContent;
161
+ }
162
+ });
163
+ return flattenedFiles;
164
+ };
165
+ convertFormidableFileToTrayFile = (file) => ({
166
+ key: file.newFilename,
167
+ metadata: {
168
+ name: file.newFilename,
169
+ contentType: file.mimetype ?? undefined,
170
+ size: file.size,
171
+ },
172
+ content: stream_1.Readable.from('0'),
173
+ });
181
174
  }
182
175
  exports.ExpressHttpController = ExpressHttpController;
@@ -4,8 +4,7 @@ exports.startServer = void 0;
4
4
  const express = require("express");
5
5
  const cors = require("cors");
6
6
  const startServer = (controllers, options) => {
7
- var _a;
8
- const port = (_a = options.port) !== null && _a !== void 0 ? _a : 3000;
7
+ const port = options.port ?? 3000;
9
8
  const app = express();
10
9
  const router = express.Router();
11
10
  app.use(cors());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trayio/express",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "Express extensions and implementations",
5
5
  "exports": {
6
6
  "./*": "./dist/*.js"
@@ -14,7 +14,7 @@
14
14
  "access": "public"
15
15
  },
16
16
  "dependencies": {
17
- "@trayio/commons": "3.8.0",
17
+ "@trayio/commons": "3.9.0",
18
18
  "cors": "2.8.5",
19
19
  "express": "4.18.2",
20
20
  "formidable": "3.5.1"