@eggjs/multipart 4.0.0 → 5.0.0-beta.18

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.
Files changed (70) hide show
  1. package/README.md +21 -32
  2. package/dist/app/extend/context.d.ts +101 -0
  3. package/dist/app/extend/context.js +199 -0
  4. package/dist/app/middleware/multipart.d.ts +7 -0
  5. package/dist/app/middleware/multipart.js +15 -0
  6. package/dist/app/schedule/clean_tmpdir.d.ts +29 -0
  7. package/dist/app/schedule/clean_tmpdir.js +57 -0
  8. package/dist/app.d.ts +10 -0
  9. package/dist/app.js +21 -0
  10. package/{src/config/config.default.ts → dist/config/config.default.d.ts} +11 -49
  11. package/dist/config/config.default.js +28 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +3 -0
  14. package/dist/lib/LimitError.d.ts +8 -0
  15. package/dist/lib/LimitError.js +15 -0
  16. package/dist/lib/MultipartFileTooLargeError.d.ts +9 -0
  17. package/dist/lib/MultipartFileTooLargeError.js +17 -0
  18. package/dist/lib/utils.d.ts +8 -0
  19. package/dist/lib/utils.js +71 -0
  20. package/dist/types.d.ts +24 -0
  21. package/dist/types.js +1 -0
  22. package/package.json +55 -74
  23. package/dist/commonjs/app/extend/context.d.ts +0 -110
  24. package/dist/commonjs/app/extend/context.js +0 -279
  25. package/dist/commonjs/app/middleware/multipart.d.ts +0 -4
  26. package/dist/commonjs/app/middleware/multipart.js +0 -20
  27. package/dist/commonjs/app/schedule/clean_tmpdir.d.ts +0 -3
  28. package/dist/commonjs/app/schedule/clean_tmpdir.js +0 -58
  29. package/dist/commonjs/app.d.ts +0 -6
  30. package/dist/commonjs/app.js +0 -21
  31. package/dist/commonjs/config/config.default.d.ts +0 -98
  32. package/dist/commonjs/config/config.default.js +0 -31
  33. package/dist/commonjs/index.d.ts +0 -2
  34. package/dist/commonjs/index.js +0 -5
  35. package/dist/commonjs/lib/LimitError.d.ts +0 -5
  36. package/dist/commonjs/lib/LimitError.js +0 -16
  37. package/dist/commonjs/lib/MultipartFileTooLargeError.d.ts +0 -6
  38. package/dist/commonjs/lib/MultipartFileTooLargeError.js +0 -18
  39. package/dist/commonjs/lib/utils.d.ts +0 -4
  40. package/dist/commonjs/lib/utils.js +0 -93
  41. package/dist/commonjs/package.json +0 -3
  42. package/dist/esm/app/extend/context.d.ts +0 -110
  43. package/dist/esm/app/extend/context.js +0 -273
  44. package/dist/esm/app/middleware/multipart.d.ts +0 -4
  45. package/dist/esm/app/middleware/multipart.js +0 -18
  46. package/dist/esm/app/schedule/clean_tmpdir.d.ts +0 -3
  47. package/dist/esm/app/schedule/clean_tmpdir.js +0 -53
  48. package/dist/esm/app.d.ts +0 -6
  49. package/dist/esm/app.js +0 -18
  50. package/dist/esm/config/config.default.d.ts +0 -98
  51. package/dist/esm/config/config.default.js +0 -26
  52. package/dist/esm/index.d.ts +0 -2
  53. package/dist/esm/index.js +0 -3
  54. package/dist/esm/lib/LimitError.d.ts +0 -5
  55. package/dist/esm/lib/LimitError.js +0 -12
  56. package/dist/esm/lib/MultipartFileTooLargeError.d.ts +0 -6
  57. package/dist/esm/lib/MultipartFileTooLargeError.js +0 -14
  58. package/dist/esm/lib/utils.d.ts +0 -4
  59. package/dist/esm/lib/utils.js +0 -85
  60. package/dist/esm/package.json +0 -3
  61. package/dist/package.json +0 -4
  62. package/src/app/extend/context.ts +0 -368
  63. package/src/app/middleware/multipart.ts +0 -20
  64. package/src/app/schedule/clean_tmpdir.ts +0 -55
  65. package/src/app.ts +0 -20
  66. package/src/index.ts +0 -2
  67. package/src/lib/LimitError.ts +0 -12
  68. package/src/lib/MultipartFileTooLargeError.ts +0 -14
  69. package/src/lib/utils.ts +0 -92
  70. package/src/typings/index.d.ts +0 -4
@@ -1,55 +0,0 @@
1
- import path from 'node:path';
2
- import fs from 'node:fs/promises';
3
- import dayjs from 'dayjs';
4
- import { EggCore } from '@eggjs/core';
5
-
6
- export default (app: EggCore): any => {
7
- return class CleanTmpdir extends app.Subscription {
8
- static get schedule() {
9
- return {
10
- type: 'worker',
11
- cron: app.config.multipart.cleanSchedule.cron,
12
- disable: app.config.multipart.cleanSchedule.disable,
13
- immediate: false,
14
- };
15
- }
16
-
17
- async _remove(dir: string) {
18
- const { ctx } = this;
19
- if (await fs.access(dir).then(() => true, () => false)) {
20
- ctx.coreLogger.info('[@eggjs/multipart:CleanTmpdir] removing tmpdir: %j', dir);
21
- try {
22
- await fs.rm(dir, { force: true, recursive: true });
23
- ctx.coreLogger.info('[@eggjs/multipart:CleanTmpdir:success] tmpdir: %j has been removed', dir);
24
- } catch (err) {
25
- /* c8 ignore next 3 */
26
- ctx.coreLogger.error('[@eggjs/multipart:CleanTmpdir:error] remove tmpdir: %j error: %s', dir, err);
27
- ctx.coreLogger.error(err);
28
- }
29
- }
30
- }
31
-
32
- async subscribe() {
33
- const { ctx } = this;
34
- const config = ctx.app.config;
35
- ctx.coreLogger.info('[@eggjs/multipart:CleanTmpdir] start clean tmpdir: %j', config.multipart.tmpdir);
36
- // last year
37
- const lastYear = dayjs().subtract(1, 'years');
38
- const lastYearDir = path.join(config.multipart.tmpdir, lastYear.format('YYYY'));
39
- await this._remove(lastYearDir);
40
- // 3 months
41
- for (let i = 1; i <= 3; i++) {
42
- const date = dayjs().subtract(i, 'months');
43
- const dir = path.join(config.multipart.tmpdir, date.format('YYYY/MM'));
44
- await this._remove(dir);
45
- }
46
- // 7 days
47
- for (let i = 1; i <= 7; i++) {
48
- const date = dayjs().subtract(i, 'days');
49
- const dir = path.join(config.multipart.tmpdir, date.format('YYYY/MM/DD'));
50
- await this._remove(dir);
51
- }
52
- ctx.coreLogger.info('[@eggjs/multipart:CleanTmpdir] end');
53
- }
54
- };
55
- };
package/src/app.ts DELETED
@@ -1,20 +0,0 @@
1
- import type { EggCore, ILifecycleBoot } from '@eggjs/core';
2
- import { normalizeOptions } from './lib/utils.js';
3
-
4
- export default class AppBootHook implements ILifecycleBoot {
5
- constructor(private app: EggCore) {}
6
-
7
- configWillLoad() {
8
- this.app.config.multipart = normalizeOptions(this.app.config.multipart);
9
- const options = this.app.config.multipart;
10
-
11
- this.app.coreLogger.info('[@eggjs/multipart] %s mode enable', options.mode);
12
- if (options.mode === 'file' || options.fileModeMatch) {
13
- this.app.coreLogger.info('[@eggjs/multipart] will save temporary files to %j, cleanup job cron: %j',
14
- options.tmpdir, options.cleanSchedule.cron);
15
- // enable multipart middleware
16
- this.app.config.coreMiddleware.push('multipart');
17
- }
18
- }
19
- }
20
-
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- import './config/config.default.js';
2
- import './app/extend/context.js';
@@ -1,12 +0,0 @@
1
- export class LimitError extends Error {
2
- code: string;
3
- status: number;
4
-
5
- constructor(code: string, message: string) {
6
- super(message);
7
- this.code = code;
8
- this.status = 413;
9
- this.name = this.constructor.name;
10
- Error.captureStackTrace(this, this.constructor);
11
- }
12
- }
@@ -1,14 +0,0 @@
1
- export class MultipartFileTooLargeError extends Error {
2
- status: number;
3
- fields: Record<string, any>;
4
- filename: string;
5
-
6
- constructor(message: string, fields: Record<string, any>, filename: string) {
7
- super(message);
8
- this.name = this.constructor.name;
9
- this.status = 413;
10
- this.fields = fields;
11
- this.filename = filename;
12
- Error.captureStackTrace(this, this.constructor);
13
- }
14
- }
package/src/lib/utils.ts DELETED
@@ -1,92 +0,0 @@
1
- import path from 'node:path';
2
- import assert from 'node:assert';
3
- import bytes from 'bytes';
4
- import { MultipartConfig } from '../config/config.default.js';
5
-
6
- export const whitelist = [
7
- // images
8
- '.jpg', '.jpeg', // image/jpeg
9
- '.png', // image/png, image/x-png
10
- '.gif', // image/gif
11
- '.bmp', // image/bmp
12
- '.wbmp', // image/vnd.wap.wbmp
13
- '.webp',
14
- '.tif',
15
- '.psd',
16
- // text
17
- '.svg',
18
- '.js', '.jsx',
19
- '.json',
20
- '.css', '.less',
21
- '.html', '.htm',
22
- '.xml',
23
- // tar
24
- '.zip',
25
- '.gz', '.tgz', '.gzip',
26
- // video
27
- '.mp3',
28
- '.mp4',
29
- '.avi',
30
- ];
31
-
32
- export function humanizeBytes(size: number | string) {
33
- if (typeof size === 'number') {
34
- return size;
35
- }
36
- return bytes(size) as number;
37
- }
38
-
39
- export function normalizeOptions(options: MultipartConfig) {
40
- // make sure to cast the value of config **Size to number
41
- options.fileSize = humanizeBytes(options.fileSize);
42
- options.fieldSize = humanizeBytes(options.fieldSize);
43
- options.fieldNameSize = humanizeBytes(options.fieldNameSize);
44
-
45
- // validate mode
46
- options.mode = options.mode || 'stream';
47
- assert([ 'stream', 'file' ].includes(options.mode), `Expect mode to be 'stream' or 'file', but got '${options.mode}'`);
48
- if (options.mode === 'file') {
49
- assert(!options.fileModeMatch, '`fileModeMatch` options only work on stream mode, please remove it');
50
- }
51
-
52
- // normalize whitelist
53
- if (Array.isArray(options.whitelist)) {
54
- options.whitelist = options.whitelist.map(extname => extname.toLowerCase());
55
- }
56
-
57
- // normalize fileExtensions
58
- if (Array.isArray(options.fileExtensions)) {
59
- options.fileExtensions = options.fileExtensions.map(extname => {
60
- return (extname.startsWith('.') || extname === '') ? extname.toLowerCase() : `.${extname.toLowerCase()}`;
61
- });
62
- }
63
-
64
- function checkExt(fileName: string) {
65
- if (typeof options.whitelist === 'function') {
66
- return options.whitelist(fileName);
67
- }
68
- const extname = path.extname(fileName).toLowerCase();
69
- if (Array.isArray(options.whitelist)) {
70
- return options.whitelist.includes(extname);
71
- }
72
- // only if user don't provide whitelist, we will use default whitelist + fileExtensions
73
- return whitelist.includes(extname) || options.fileExtensions.includes(extname);
74
- }
75
-
76
- options.checkFile = (_fieldName: string, fileStream: any, fileName: string): void | Error => {
77
- // just ignore, if no file
78
- if (!fileStream || !fileName) return;
79
- try {
80
- if (!checkExt(fileName)) {
81
- const err = new Error('Invalid filename: ' + fileName);
82
- Reflect.set(err, 'status', 400);
83
- return err;
84
- }
85
- } catch (err: any) {
86
- err.status = 400;
87
- return err;
88
- }
89
- };
90
-
91
- return options;
92
- }
@@ -1,4 +0,0 @@
1
- // make sure to import egg typings and let typescript know about it
2
- // @see https://github.com/whxaxes/blog/issues/11
3
- // and https://www.typescriptlang.org/docs/handbook/declaration-merging.html
4
- import 'egg';