node-server-engine 1.2.5 → 1.2.7
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/README.md +43 -18
- package/dist/middleware/fileUploader/fileUploader.d.ts +4 -5
- package/dist/middleware/fileUploader/fileUploader.js +68 -255
- package/dist/middleware/fileUploader/fileUploader.js.map +1 -1
- package/dist/middleware/fileUploader/fileUploader.types.d.ts +13 -32
- package/dist/middleware/fileUploader/fileUploader.types.js.map +1 -1
- package/package.json +2 -2
- package/src/middleware/fileUploader/fileUploader.ts +70 -270
- package/src/middleware/fileUploader/fileUploader.types.ts +16 -33
- package/test/env.ts +1 -0
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.d.ts +0 -6
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.js +0 -28
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.js.map +0 -1
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.types.d.ts +0 -12
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.types.js +0 -2
- package/dist/middleware/fileUploader/compressAvatar/compressAvatar.types.js.map +0 -1
- package/dist/middleware/fileUploader/compressAvatar/index.d.ts +0 -2
- package/dist/middleware/fileUploader/compressAvatar/index.js +0 -28
- package/dist/middleware/fileUploader/compressAvatar/index.js.map +0 -1
- package/src/middleware/fileUploader/compressAvatar/compressAvatar.ts +0 -25
- package/src/middleware/fileUploader/compressAvatar/compressAvatar.types.ts +0 -12
- package/src/middleware/fileUploader/compressAvatar/index.ts +0 -2
- package/src/middleware/fileUploader/fileUploader.test.ts +0 -310
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'crypto';
|
|
2
|
-
import { Readable } from 'stream';
|
|
3
|
-
import { setTimeout as setTimeoutAsync } from 'timers/promises';
|
|
4
|
-
import axios from 'axios';
|
|
5
|
-
import { expect } from 'chai';
|
|
6
|
-
import { faker } from '@faker-js/faker';
|
|
7
|
-
import FormData from 'form-data';
|
|
8
|
-
import { Sequelize } from 'sequelize';
|
|
9
|
-
import { stub, SinonStub } from 'sinon';
|
|
10
|
-
import request from 'supertest';
|
|
11
|
-
import { EndpointAuthType, EndpointMethod, Endpoint } from 'entities/Endpoint';
|
|
12
|
-
import { Server } from 'entities/Server';
|
|
13
|
-
import { stubPubSub, stubStorage, createTestApp } from 'test';
|
|
14
|
-
|
|
15
|
-
const PATH = '/test';
|
|
16
|
-
const buffer = Buffer.from(faker.lorem.paragraphs());
|
|
17
|
-
let uploadStub: SinonStub;
|
|
18
|
-
let deleteStub: SinonStub;
|
|
19
|
-
let bucket: string;
|
|
20
|
-
|
|
21
|
-
describe('Middleware - File Uploader', () => {
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
const { upload, remove } = stubStorage();
|
|
24
|
-
uploadStub = upload;
|
|
25
|
-
deleteStub = remove;
|
|
26
|
-
stub(Sequelize.prototype, 'close');
|
|
27
|
-
stubPubSub();
|
|
28
|
-
bucket = faker.lorem.slug();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('should throw an error for multipart requests', async () => {
|
|
32
|
-
const key = faker.lorem.word();
|
|
33
|
-
const app = createTestApp({ path: PATH, file: { bucket, key } });
|
|
34
|
-
await request(app)
|
|
35
|
-
.post(PATH)
|
|
36
|
-
.set('Content-Type', 'application/json')
|
|
37
|
-
.expect(415, { errorCode: 'invalid-content-type' });
|
|
38
|
-
expect(uploadStub).to.not.have.been.called;
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// it('should throw an error for unknown file fields', async () => {
|
|
42
|
-
// const key = faker.lorem.words();
|
|
43
|
-
// const app = createTestApp({
|
|
44
|
-
// path: PATH,
|
|
45
|
-
// file: { bucket, key: faker.lorem.word() }
|
|
46
|
-
// });
|
|
47
|
-
// await request(app)
|
|
48
|
-
// .post(PATH)
|
|
49
|
-
// .attach(key, buffer, faker.system.fileName())
|
|
50
|
-
// .expect(400, { errorCode: 'invalid-file-field', hint: { field: key } });
|
|
51
|
-
// expect(uploadStub).to.not.have.been.called;
|
|
52
|
-
// });
|
|
53
|
-
|
|
54
|
-
// it('should throw an error for a file with an unexpected mime type', async () => {
|
|
55
|
-
// const key = faker.lorem.word();
|
|
56
|
-
// const app = createTestApp({
|
|
57
|
-
// path: PATH,
|
|
58
|
-
// file: { bucket, key, mimeTypes: [faker.lorem.word()] }
|
|
59
|
-
// });
|
|
60
|
-
// await request(app)
|
|
61
|
-
// .post(PATH)
|
|
62
|
-
// .attach(key, buffer, faker.system.fileName())
|
|
63
|
-
// .expect(415, { errorCode: 'invalid-mime-type', hint: { field: key } });
|
|
64
|
-
// expect(uploadStub).to.not.have.been.called;
|
|
65
|
-
// });
|
|
66
|
-
|
|
67
|
-
// it('should upload a single file', async () => {
|
|
68
|
-
// const key = faker.lorem.word();
|
|
69
|
-
// const app = createTestApp({ path: PATH, file: { bucket, key } });
|
|
70
|
-
// await request(app)
|
|
71
|
-
// .post(PATH)
|
|
72
|
-
// .attach(key, buffer, faker.system.fileName())
|
|
73
|
-
// .expect(200);
|
|
74
|
-
// expect(uploadStub).to.have.been.calledOnce;
|
|
75
|
-
// });
|
|
76
|
-
|
|
77
|
-
// it('should upload multiple files', async () => {
|
|
78
|
-
// const key1 = faker.lorem.word();
|
|
79
|
-
// const key2 = faker.lorem.word();
|
|
80
|
-
// const app = createTestApp({
|
|
81
|
-
// path: PATH,
|
|
82
|
-
// files: [
|
|
83
|
-
// { bucket, key: key1 },
|
|
84
|
-
// { bucket, key: key2 }
|
|
85
|
-
// ]
|
|
86
|
-
// });
|
|
87
|
-
// await request(app)
|
|
88
|
-
// .post(PATH)
|
|
89
|
-
// .attach(key1, buffer, faker.system.fileName())
|
|
90
|
-
// .attach(key2, buffer, faker.system.fileName())
|
|
91
|
-
// .expect(200);
|
|
92
|
-
// expect(uploadStub).to.have.been.calledTwice;
|
|
93
|
-
// });
|
|
94
|
-
|
|
95
|
-
// it('should handle file error after one has already been uploaded', async () => {
|
|
96
|
-
// uploadStub.onSecondCall().rejects(new Error('Fake error'));
|
|
97
|
-
// const key1 = faker.lorem.word();
|
|
98
|
-
// const key2 = faker.lorem.word();
|
|
99
|
-
// const app = createTestApp({
|
|
100
|
-
// path: PATH,
|
|
101
|
-
// files: [
|
|
102
|
-
// { bucket, key: key1, path: '/test' },
|
|
103
|
-
// { bucket, key: key2 }
|
|
104
|
-
// ]
|
|
105
|
-
// });
|
|
106
|
-
// await request(app)
|
|
107
|
-
// .post(PATH)
|
|
108
|
-
// .attach(key1, buffer, faker.system.fileName())
|
|
109
|
-
// .attach(key2, buffer, faker.system.fileName())
|
|
110
|
-
// .expect(500, { errorCode: 'server-error' });
|
|
111
|
-
// expect(uploadStub).to.have.been.calledTwice;
|
|
112
|
-
// expect(deleteStub).to.have.been.calledOnce;
|
|
113
|
-
// });
|
|
114
|
-
|
|
115
|
-
// it('should throw an error if some files are missing', async () => {
|
|
116
|
-
// uploadStub.onSecondCall().rejects(new Error('Fake error'));
|
|
117
|
-
// const key1 = faker.lorem.word();
|
|
118
|
-
// const key2 = faker.lorem.word();
|
|
119
|
-
// const app = createTestApp({
|
|
120
|
-
// path: PATH,
|
|
121
|
-
// files: [
|
|
122
|
-
// { bucket, key: key1, path: '/test' },
|
|
123
|
-
// { bucket, key: key2, required: true }
|
|
124
|
-
// ]
|
|
125
|
-
// });
|
|
126
|
-
// await request(app)
|
|
127
|
-
// .post(PATH)
|
|
128
|
-
// .attach(key1, buffer, faker.system.fileName())
|
|
129
|
-
// .expect(400, { errorCode: 'missing-field' });
|
|
130
|
-
// expect(uploadStub).to.have.been.calledOnce;
|
|
131
|
-
// expect(deleteStub).to.have.been.calledOnce;
|
|
132
|
-
// });
|
|
133
|
-
|
|
134
|
-
// it('should not throw an error when there is no files and all are optional', async () => {
|
|
135
|
-
// const key = faker.lorem.word();
|
|
136
|
-
// const app = createTestApp({ path: PATH, file: { bucket, key } });
|
|
137
|
-
// await request(app).post(PATH).field('id', randomUUID()).expect(200);
|
|
138
|
-
// });
|
|
139
|
-
|
|
140
|
-
// it('should handle additional fields', async () => {
|
|
141
|
-
// uploadStub.onSecondCall().rejects(new Error('Fake error'));
|
|
142
|
-
// const key1 = randomUUID();
|
|
143
|
-
// const key2 = randomUUID();
|
|
144
|
-
// const value2 = randomUUID();
|
|
145
|
-
// const key3 = randomUUID();
|
|
146
|
-
// const value3 = false;
|
|
147
|
-
// const key4 = randomUUID();
|
|
148
|
-
// const value4 = [randomUUID(), randomUUID()];
|
|
149
|
-
// const app = createTestApp({
|
|
150
|
-
// path: PATH,
|
|
151
|
-
// files: [{ bucket, key: key1, path: '/test' }],
|
|
152
|
-
// handler: (req, res) => {
|
|
153
|
-
// res.json(req.body);
|
|
154
|
-
// },
|
|
155
|
-
// validator: {
|
|
156
|
-
// [key2]: {
|
|
157
|
-
// in: ['body'],
|
|
158
|
-
// isArray: { options: { min: 1, max: 1 } },
|
|
159
|
-
// customSanitizer: { options: (value: Array<unknown>) => value[0] }
|
|
160
|
-
// },
|
|
161
|
-
// [`${key2}.*`]: {
|
|
162
|
-
// isUUID: { options: 4 }
|
|
163
|
-
// },
|
|
164
|
-
// [key3]: {
|
|
165
|
-
// in: ['body'],
|
|
166
|
-
// isArray: { options: { min: 1, max: 1 } },
|
|
167
|
-
// customSanitizer: {
|
|
168
|
-
// options: (value: Array<unknown>) => value[0] === 'true'
|
|
169
|
-
// }
|
|
170
|
-
// },
|
|
171
|
-
// [`${key3}.*`]: {
|
|
172
|
-
// isBoolean: true
|
|
173
|
-
// },
|
|
174
|
-
// [key4]: {
|
|
175
|
-
// in: ['body'],
|
|
176
|
-
// isArray: { options: { min: 2, max: 2 } }
|
|
177
|
-
// },
|
|
178
|
-
// [`${key4}.*`]: {
|
|
179
|
-
// isUUID: { options: 4 }
|
|
180
|
-
// }
|
|
181
|
-
// }
|
|
182
|
-
// });
|
|
183
|
-
// const { body } = <
|
|
184
|
-
// {
|
|
185
|
-
// /** */
|
|
186
|
-
// body: { [name: string]: string };
|
|
187
|
-
// }
|
|
188
|
-
// >await request(app).post(PATH).attach(key1, buffer, faker.system.fileName()).field(key2, value2).field(key3, value3).field(key4, value4).expect(200);
|
|
189
|
-
// expect(uploadStub).to.have.been.calledOnce;
|
|
190
|
-
// expect(deleteStub).to.not.have.been.calledOnce;
|
|
191
|
-
// expect(body[key2]).to.equal(value2);
|
|
192
|
-
// expect(body[key3]).to.equal(value3);
|
|
193
|
-
// expect(body[key4]).to.deep.equal(value4);
|
|
194
|
-
// });
|
|
195
|
-
|
|
196
|
-
// it('should handle field validation error', async () => {
|
|
197
|
-
// uploadStub.onSecondCall().rejects(new Error('Fake error'));
|
|
198
|
-
// const key1 = faker.lorem.word();
|
|
199
|
-
// const key2 = faker.lorem.word();
|
|
200
|
-
// const value2 = randomUUID();
|
|
201
|
-
// const key3 = faker.lorem.word();
|
|
202
|
-
// const value3 = [randomUUID(), randomUUID()];
|
|
203
|
-
// const app = createTestApp({
|
|
204
|
-
// path: PATH,
|
|
205
|
-
// files: [{ bucket, key: key1, path: '/test' }],
|
|
206
|
-
// handler: (req, res) => {
|
|
207
|
-
// res.json(req.body);
|
|
208
|
-
// },
|
|
209
|
-
// validator: {
|
|
210
|
-
// [`${key2}.*`]: {
|
|
211
|
-
// isLength: { options: { max: 1 } }
|
|
212
|
-
// },
|
|
213
|
-
// [key2]: {
|
|
214
|
-
// in: ['body'],
|
|
215
|
-
// isArray: { options: { min: 1, max: 1 } },
|
|
216
|
-
// customSanitizer: { options: (value: Array<unknown>) => value[0] }
|
|
217
|
-
// },
|
|
218
|
-
// [key3]: {
|
|
219
|
-
// in: ['body'],
|
|
220
|
-
// isArray: { options: { min: 1, max: 1 } }
|
|
221
|
-
// }
|
|
222
|
-
// }
|
|
223
|
-
// });
|
|
224
|
-
// await request(app)
|
|
225
|
-
// .post(PATH)
|
|
226
|
-
// .attach(key1, buffer, faker.system.fileName())
|
|
227
|
-
// .field(key2, value2)
|
|
228
|
-
// .field(key3, value3)
|
|
229
|
-
// .expect(400, {
|
|
230
|
-
// errorCode: 'invalid-request',
|
|
231
|
-
// hint: { [`${key2}[0]`]: 'Invalid value', [key3]: 'Invalid value' }
|
|
232
|
-
// });
|
|
233
|
-
// });
|
|
234
|
-
|
|
235
|
-
// it('should delete already uploaded files on cancel request', async () => {
|
|
236
|
-
// const key1 = faker.lorem.word();
|
|
237
|
-
// const key2 = faker.lorem.word();
|
|
238
|
-
// const key3 = faker.lorem.word();
|
|
239
|
-
// process.env.PORT = '3000';
|
|
240
|
-
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
241
|
-
|
|
242
|
-
// const server = new Server({
|
|
243
|
-
// endpoints: [
|
|
244
|
-
// new Endpoint({
|
|
245
|
-
// method: EndpointMethod.POST,
|
|
246
|
-
// authType: EndpointAuthType.NONE,
|
|
247
|
-
// handler: (req, res): void => {
|
|
248
|
-
// res.json({ message: 'success' });
|
|
249
|
-
// },
|
|
250
|
-
// files: [
|
|
251
|
-
// { bucket, key: key1 },
|
|
252
|
-
// { bucket, key: key2 },
|
|
253
|
-
// { bucket, key: key3 }
|
|
254
|
-
// ],
|
|
255
|
-
// path: PATH,
|
|
256
|
-
// validator: {}
|
|
257
|
-
// })
|
|
258
|
-
// ]
|
|
259
|
-
// });
|
|
260
|
-
|
|
261
|
-
// await server.init();
|
|
262
|
-
|
|
263
|
-
// const form = new FormData();
|
|
264
|
-
// form.append(key1, buffer);
|
|
265
|
-
// form.append(key2, buffer);
|
|
266
|
-
// form.append(key3, buffer);
|
|
267
|
-
|
|
268
|
-
// const requestConfig = {
|
|
269
|
-
// headers: {
|
|
270
|
-
// ...form.getHeaders()
|
|
271
|
-
// }
|
|
272
|
-
// };
|
|
273
|
-
|
|
274
|
-
// // eslint-disable-next-line import/no-named-as-default-member
|
|
275
|
-
// const abort = axios.CancelToken.source();
|
|
276
|
-
|
|
277
|
-
// setTimeout(() => {
|
|
278
|
-
// abort.cancel(`Request Cancelled`);
|
|
279
|
-
// }, 50);
|
|
280
|
-
|
|
281
|
-
// uploadStub.callsFake(async (file: Readable, bucket: string) => {
|
|
282
|
-
// file.resume();
|
|
283
|
-
// await setTimeoutAsync(1);
|
|
284
|
-
// return { bucket };
|
|
285
|
-
// });
|
|
286
|
-
|
|
287
|
-
// await axios
|
|
288
|
-
// .post(`https://localhost:3000` + PATH, form, {
|
|
289
|
-
// ...requestConfig,
|
|
290
|
-
// cancelToken: abort.token
|
|
291
|
-
// })
|
|
292
|
-
// .catch((err: Error) => {
|
|
293
|
-
// expect(err.message).to.equal('Request Cancelled');
|
|
294
|
-
// });
|
|
295
|
-
|
|
296
|
-
// expect(uploadStub).to.have.been.calledThrice;
|
|
297
|
-
// await server.shutdown();
|
|
298
|
-
// process.env.PORT = '8080';
|
|
299
|
-
// });
|
|
300
|
-
|
|
301
|
-
// it('should compress avatar before uploading', async () => {
|
|
302
|
-
// const key = 'avatar';
|
|
303
|
-
// const app = createTestApp({ path: PATH, file: { bucket, key } });
|
|
304
|
-
// await request(app)
|
|
305
|
-
// .post(PATH)
|
|
306
|
-
// .attach(key, buffer, faker.system.fileName())
|
|
307
|
-
// .expect(200);
|
|
308
|
-
// expect(uploadStub).to.have.been.calledOnce;
|
|
309
|
-
// });
|
|
310
|
-
});
|