Skip to content

Commit 3dc5562

Browse files
authored
Update dependencies + Migrate tests and code from callback to async/await style + Support Koa v3 + Support Node.js v18+ (#59)
* Update dependencies + Migrate tests and code from callback to async/await style + Support Node.js v18+ * [x] Update dependencies * [x] Migrate tests and code from callback to async/await style * [x] Support Node.js v18+ * [x] Support Koa v3
1 parent 4b69544 commit 3dc5562

16 files changed

+472
-573
lines changed

.github/workflows/unit-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
runs-on: ubuntu-latest
66
strategy:
77
matrix:
8-
node-version: [14.x, 16.x, 18.x, 20.x]
8+
node-version: [18.x, 20.x, 22.x]
99
steps:
1010
- uses: actions/checkout@v3
1111
- uses: actions/setup-node@v3

package.json

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,30 @@
2828
}
2929
],
3030
"devDependencies": {
31-
"@commitlint/cli": "^17.3.0",
32-
"@commitlint/config-conventional": "^17.3.0",
33-
"@koa/router": "^12",
31+
"@commitlint/cli": "^19.8.1",
32+
"@commitlint/config-conventional": "^19.8.1",
33+
"@koa/router": "^13",
3434
"concat-stream": "^2",
3535
"eslint-config-xo-lass": "^2.0.1",
36+
"fix-esm": "^1.0.1",
3637
"fixpack": "^4.0.0",
3738
"form-data": "^4",
38-
"fs-temp": "^1",
39-
"husky": "^8.0.2",
40-
"koa": "^2",
41-
"lint-staged": "^13.0.3",
42-
"mocha": "3.x",
39+
"fs-temp": "^2",
40+
"husky": "^9.1.7",
41+
"koa": "^3",
42+
"lint-staged": "^16.0.0",
43+
"mocha": "^11.3.0",
4344
"multer": "1",
44-
"nyc": "^15.1.0",
45+
"nyc": "^17.1.0",
4546
"on-finished": "^2",
4647
"remark-cli": "^11.0.0",
4748
"remark-preset-github": "^4.0.4",
48-
"rimraf": "^3",
49+
"rimraf": "^6",
4950
"testdata-w3c-json-form": "^1",
50-
"xo": "^0.54.2"
51+
"xo": "^0.60.0"
5152
},
5253
"engines": {
53-
"node": ">= 14"
54+
"node": ">= 18"
5455
},
5556
"files": [
5657
"LICENSE",
@@ -92,7 +93,8 @@
9293
},
9394
"main": "index.js",
9495
"peerDependencies": {
95-
"multer": "*"
96+
"multer": "*",
97+
"koa": ">=2"
9698
},
9799
"prettier": {
98100
"singleQuote": true,
@@ -113,7 +115,7 @@
113115
},
114116
"scripts": {
115117
"lint": "xo && remark . -qfo",
116-
"test": "npm run lint && mocha",
118+
"test": "npm run lint && mocha --exit",
117119
"test-ci": "nyc npm run test --reporter=lcov"
118120
},
119121
"xo": {

test/_util.js

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const fs = require('node:fs');
22
const path = require('node:path');
33
const stream = require('node:stream');
4+
const { promisify } = require('node:util');
45
const onFinished = require('on-finished');
56

67
exports.file = (name) => {
@@ -11,35 +12,27 @@ exports.fileSize = (path) => {
1112
return fs.statSync(path).size;
1213
};
1314

14-
exports.submitForm = (multer, form, cb) => {
15-
form.getLength((err, length) => {
16-
if (err) return cb(err);
17-
18-
const req = new stream.PassThrough();
19-
20-
req.complete = false;
21-
form.once('end', () => {
22-
req.complete = true;
23-
});
24-
25-
form.pipe(req);
26-
req.headers = {
27-
'content-type': 'multipart/form-data; boundary=' + form.getBoundary(),
28-
'content-length': length
29-
};
30-
31-
const res = null;
32-
const ctx = { req, res };
33-
multer(ctx, () => {})
34-
.then(() => {
35-
onFinished(req, () => {
36-
cb(null, req);
37-
});
38-
})
39-
.catch((err_) => {
40-
onFinished(req, () => {
41-
cb(err_, req);
42-
});
43-
});
15+
exports.submitForm = async (multer, form) => {
16+
const getFormLength = promisify(form.getLength.bind(form));
17+
const length = await getFormLength();
18+
19+
const req = new stream.PassThrough();
20+
21+
req.complete = false;
22+
form.once('end', () => {
23+
req.complete = true;
4424
});
25+
26+
form.pipe(req);
27+
req.headers = {
28+
'content-type': 'multipart/form-data; boundary=' + form.getBoundary(),
29+
'content-length': length
30+
};
31+
32+
const res = null;
33+
const ctx = { req, res };
34+
await multer(ctx, () => {});
35+
onFinished(req, () => {});
36+
37+
return req;
4538
};

test/disk-storage.js

Lines changed: 77 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,46 @@
33
const assert = require('node:assert');
44
const fs = require('node:fs');
55
const path = require('node:path');
6-
const temp = require('fs-temp');
7-
const rimraf = require('rimraf');
6+
const { promisify } = require('node:util');
7+
const temp = require('fix-esm').require('fs-temp').default;
8+
const { rimraf } = require('rimraf');
89
const FormData = require('form-data');
910
const multer = require('..');
1011
const util = require('./_util');
1112

13+
const tempMkdirAsync = promisify(temp.mkdir);
14+
1215
describe('Disk Storage', () => {
1316
let uploadDir;
1417
let upload;
1518

16-
beforeEach((done) => {
17-
temp.mkdir((err, path) => {
18-
if (err) return done(err);
19-
20-
uploadDir = path;
21-
upload = multer({ dest: path });
22-
done();
23-
});
19+
beforeEach(async () => {
20+
uploadDir = await tempMkdirAsync();
21+
upload = multer({ dest: uploadDir });
2422
});
2523

26-
afterEach((done) => {
27-
rimraf(uploadDir, done);
24+
afterEach(async () => {
25+
await rimraf(uploadDir);
2826
});
2927

30-
it('should process parser/form-data POST request', (done) => {
28+
it('should process parser/form-data POST request', async () => {
3129
const form = new FormData();
3230
const parser = upload.single('small0');
3331

3432
form.append('name', 'Multer');
3533
form.append('small0', util.file('small0.dat'));
3634

37-
util.submitForm(parser, form, (err, req) => {
38-
assert.ifError(err);
39-
40-
assert.equal(req.body.name, 'Multer');
35+
const req = await util.submitForm(parser, form);
4136

42-
assert.equal(req.file.fieldname, 'small0');
43-
assert.equal(req.file.originalname, 'small0.dat');
44-
assert.equal(req.file.size, 1778);
45-
assert.equal(util.fileSize(req.file.path), 1778);
37+
assert.equal(req.body.name, 'Multer');
4638

47-
done();
48-
});
39+
assert.equal(req.file.fieldname, 'small0');
40+
assert.equal(req.file.originalname, 'small0.dat');
41+
assert.equal(req.file.size, 1778);
42+
assert.equal(util.fileSize(req.file.path), 1778);
4943
});
5044

51-
it('should process empty fields and an empty file', (done) => {
45+
it('should process empty fields and an empty file', async () => {
5246
const form = new FormData();
5347
const parser = upload.single('empty');
5448

@@ -63,27 +57,23 @@ describe('Disk Storage', () => {
6357
form.append('checkboxempty', '');
6458
form.append('checkboxempty', '');
6559

66-
util.submitForm(parser, form, (err, req) => {
67-
assert.ifError(err);
60+
const req = await util.submitForm(parser, form);
6861

69-
assert.equal(req.body.name, 'Multer');
70-
assert.equal(req.body.version, '');
71-
assert.equal(req.body.year, '');
62+
assert.equal(req.body.name, 'Multer');
63+
assert.equal(req.body.version, '');
64+
assert.equal(req.body.year, '');
7265

73-
assert.deepEqual(req.body.checkboxfull, ['cb1', 'cb2']);
74-
assert.deepEqual(req.body.checkboxhalfempty, ['cb1', '']);
75-
assert.deepEqual(req.body.checkboxempty, ['', '']);
66+
assert.deepEqual(req.body.checkboxfull, ['cb1', 'cb2']);
67+
assert.deepEqual(req.body.checkboxhalfempty, ['cb1', '']);
68+
assert.deepEqual(req.body.checkboxempty, ['', '']);
7669

77-
assert.equal(req.file.fieldname, 'empty');
78-
assert.equal(req.file.originalname, 'empty.dat');
79-
assert.equal(req.file.size, 0);
80-
assert.equal(util.fileSize(req.file.path), 0);
81-
82-
done();
83-
});
70+
assert.equal(req.file.fieldname, 'empty');
71+
assert.equal(req.file.originalname, 'empty.dat');
72+
assert.equal(req.file.size, 0);
73+
assert.equal(util.fileSize(req.file.path), 0);
8474
});
8575

86-
it('should process multiple files', (done) => {
76+
it('should process multiple files', async () => {
8777
const form = new FormData();
8878
const parser = upload.fields([
8979
{ name: 'empty', maxCount: 1 },
@@ -103,70 +93,65 @@ describe('Disk Storage', () => {
10393
form.append('medium', util.file('medium.dat'));
10494
form.append('large', util.file('large.jpg'));
10595

106-
util.submitForm(parser, form, (err, req) => {
107-
assert.ifError(err);
108-
109-
assert.deepEqual(req.body, {});
110-
111-
assert.equal(req.files.empty[0].fieldname, 'empty');
112-
assert.equal(req.files.empty[0].originalname, 'empty.dat');
113-
assert.equal(req.files.empty[0].size, 0);
114-
assert.equal(util.fileSize(req.files.empty[0].path), 0);
115-
116-
assert.equal(req.files.tiny0[0].fieldname, 'tiny0');
117-
assert.equal(req.files.tiny0[0].originalname, 'tiny0.dat');
118-
assert.equal(req.files.tiny0[0].size, 122);
119-
assert.equal(util.fileSize(req.files.tiny0[0].path), 122);
120-
121-
assert.equal(req.files.tiny1[0].fieldname, 'tiny1');
122-
assert.equal(req.files.tiny1[0].originalname, 'tiny1.dat');
123-
assert.equal(req.files.tiny1[0].size, 7);
124-
assert.equal(util.fileSize(req.files.tiny1[0].path), 7);
125-
126-
assert.equal(req.files.small0[0].fieldname, 'small0');
127-
assert.equal(req.files.small0[0].originalname, 'small0.dat');
128-
assert.equal(req.files.small0[0].size, 1778);
129-
assert.equal(util.fileSize(req.files.small0[0].path), 1778);
130-
131-
assert.equal(req.files.small1[0].fieldname, 'small1');
132-
assert.equal(req.files.small1[0].originalname, 'small1.dat');
133-
assert.equal(req.files.small1[0].size, 315);
134-
assert.equal(util.fileSize(req.files.small1[0].path), 315);
135-
136-
assert.equal(req.files.medium[0].fieldname, 'medium');
137-
assert.equal(req.files.medium[0].originalname, 'medium.dat');
138-
assert.equal(req.files.medium[0].size, 13196);
139-
assert.equal(util.fileSize(req.files.medium[0].path), 13196);
140-
141-
assert.equal(req.files.large[0].fieldname, 'large');
142-
assert.equal(req.files.large[0].originalname, 'large.jpg');
143-
assert.equal(req.files.large[0].size, 2413677);
144-
assert.equal(util.fileSize(req.files.large[0].path), 2413677);
145-
146-
done();
147-
});
96+
const req = await util.submitForm(parser, form);
97+
assert.deepEqual(req.body, {});
98+
99+
assert.equal(req.files.empty[0].fieldname, 'empty');
100+
assert.equal(req.files.empty[0].originalname, 'empty.dat');
101+
assert.equal(req.files.empty[0].size, 0);
102+
assert.equal(util.fileSize(req.files.empty[0].path), 0);
103+
104+
assert.equal(req.files.tiny0[0].fieldname, 'tiny0');
105+
assert.equal(req.files.tiny0[0].originalname, 'tiny0.dat');
106+
assert.equal(req.files.tiny0[0].size, 122);
107+
assert.equal(util.fileSize(req.files.tiny0[0].path), 122);
108+
109+
assert.equal(req.files.tiny1[0].fieldname, 'tiny1');
110+
assert.equal(req.files.tiny1[0].originalname, 'tiny1.dat');
111+
assert.equal(req.files.tiny1[0].size, 7);
112+
assert.equal(util.fileSize(req.files.tiny1[0].path), 7);
113+
114+
assert.equal(req.files.small0[0].fieldname, 'small0');
115+
assert.equal(req.files.small0[0].originalname, 'small0.dat');
116+
assert.equal(req.files.small0[0].size, 1778);
117+
assert.equal(util.fileSize(req.files.small0[0].path), 1778);
118+
119+
assert.equal(req.files.small1[0].fieldname, 'small1');
120+
assert.equal(req.files.small1[0].originalname, 'small1.dat');
121+
assert.equal(req.files.small1[0].size, 315);
122+
assert.equal(util.fileSize(req.files.small1[0].path), 315);
123+
124+
assert.equal(req.files.medium[0].fieldname, 'medium');
125+
assert.equal(req.files.medium[0].originalname, 'medium.dat');
126+
assert.equal(req.files.medium[0].size, 13196);
127+
assert.equal(util.fileSize(req.files.medium[0].path), 13196);
128+
129+
assert.equal(req.files.large[0].fieldname, 'large');
130+
assert.equal(req.files.large[0].originalname, 'large.jpg');
131+
assert.equal(req.files.large[0].size, 2413677);
132+
assert.equal(util.fileSize(req.files.large[0].path), 2413677);
148133
});
149134

150-
it('should remove uploaded files on error', (done) => {
135+
it('should remove uploaded files on error', async () => {
151136
const form = new FormData();
152137
const parser = upload.single('tiny0');
153138

154139
form.append('tiny0', util.file('tiny0.dat'));
155140
form.append('small0', util.file('small0.dat'));
156141

157-
util.submitForm(parser, form, (err, req) => {
142+
try {
143+
await util.submitForm(parser, form);
144+
} catch (err) {
158145
assert.equal(err.code, 'LIMIT_UNEXPECTED_FILE');
159146
assert.equal(err.field, 'small0');
160147
assert.deepEqual(err.storageErrors, []);
161148

162149
const files = fs.readdirSync(uploadDir);
163150
assert.deepEqual(files, []);
164-
165-
done();
166-
});
151+
}
167152
});
168153

169-
it("should report error when directory doesn't exist", (done) => {
154+
it("should report error when directory doesn't exist", async () => {
170155
const directory = path.join(temp.mkdirSync(), 'ghost');
171156
function dest($0, $1, cb) {
172157
cb(null, directory);
@@ -179,11 +164,11 @@ describe('Disk Storage', () => {
179164

180165
form.append('tiny0', util.file('tiny0.dat'));
181166

182-
util.submitForm(parser, form, (err, req) => {
167+
try {
168+
await util.submitForm(parser, form);
169+
} catch (err) {
183170
assert.equal(err.code, 'ENOENT');
184171
assert.equal(path.dirname(err.path), directory);
185-
186-
done();
187-
});
172+
}
188173
});
189174
});

0 commit comments

Comments
 (0)