@eggjs/multipart 4.0.0 → 5.0.0-beta.17

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
@@ -0,0 +1,28 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+
4
+ //#region src/config/config.default.ts
5
+ var config_default_default = (appInfo) => {
6
+ return { multipart: {
7
+ mode: "stream",
8
+ autoFields: false,
9
+ defaultCharset: "utf8",
10
+ defaultParamCharset: "utf8",
11
+ fieldNameSize: 100,
12
+ fieldSize: "100kb",
13
+ fields: 10,
14
+ fileSize: "10mb",
15
+ files: 10,
16
+ fileExtensions: [],
17
+ whitelist: null,
18
+ allowArrayField: false,
19
+ tmpdir: path.join(os.tmpdir(), "egg-multipart-tmp", appInfo.name),
20
+ cleanSchedule: {
21
+ cron: "0 30 4 * * *",
22
+ disable: false
23
+ }
24
+ } };
25
+ };
26
+
27
+ //#endregion
28
+ export { config_default_default as default };
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import "./app/extend/context.js";
2
+
3
+ export { };
@@ -0,0 +1,8 @@
1
+ //#region src/lib/LimitError.d.ts
2
+ declare class LimitError extends Error {
3
+ code: string;
4
+ status: number;
5
+ constructor(code: string, message: string);
6
+ }
7
+ //#endregion
8
+ export { LimitError };
@@ -0,0 +1,15 @@
1
+ //#region src/lib/LimitError.ts
2
+ var LimitError = class extends Error {
3
+ code;
4
+ status;
5
+ constructor(code, message) {
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
+ };
13
+
14
+ //#endregion
15
+ export { LimitError };
@@ -0,0 +1,9 @@
1
+ //#region src/lib/MultipartFileTooLargeError.d.ts
2
+ declare class MultipartFileTooLargeError extends Error {
3
+ status: number;
4
+ fields: Record<string, any>;
5
+ filename: string;
6
+ constructor(message: string, fields: Record<string, any>, filename: string);
7
+ }
8
+ //#endregion
9
+ export { MultipartFileTooLargeError };
@@ -0,0 +1,17 @@
1
+ //#region src/lib/MultipartFileTooLargeError.ts
2
+ var MultipartFileTooLargeError = class extends Error {
3
+ status;
4
+ fields;
5
+ filename;
6
+ constructor(message, fields, filename) {
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
+ };
15
+
16
+ //#endregion
17
+ export { MultipartFileTooLargeError };
@@ -0,0 +1,8 @@
1
+ import { MultipartConfig } from "../config/config.default.js";
2
+
3
+ //#region src/lib/utils.d.ts
4
+ declare const whitelist: string[];
5
+ declare function humanizeBytes(size: number | string): number;
6
+ declare function normalizeOptions(options: MultipartConfig): MultipartConfig;
7
+ //#endregion
8
+ export { humanizeBytes, normalizeOptions, whitelist };
@@ -0,0 +1,71 @@
1
+ import path from "node:path";
2
+ import assert from "node:assert";
3
+ import bytes from "bytes";
4
+
5
+ //#region src/lib/utils.ts
6
+ const whitelist = [
7
+ ".jpg",
8
+ ".jpeg",
9
+ ".png",
10
+ ".gif",
11
+ ".bmp",
12
+ ".wbmp",
13
+ ".webp",
14
+ ".tif",
15
+ ".psd",
16
+ ".svg",
17
+ ".js",
18
+ ".jsx",
19
+ ".json",
20
+ ".css",
21
+ ".less",
22
+ ".html",
23
+ ".htm",
24
+ ".xml",
25
+ ".zip",
26
+ ".gz",
27
+ ".tgz",
28
+ ".gzip",
29
+ ".mp3",
30
+ ".mp4",
31
+ ".avi"
32
+ ];
33
+ function humanizeBytes(size) {
34
+ if (typeof size === "number") return size;
35
+ return bytes(size);
36
+ }
37
+ function normalizeOptions(options) {
38
+ options.fileSize = humanizeBytes(options.fileSize);
39
+ options.fieldSize = humanizeBytes(options.fieldSize);
40
+ options.fieldNameSize = humanizeBytes(options.fieldNameSize);
41
+ options.mode = options.mode || "stream";
42
+ assert(["stream", "file"].includes(options.mode), `Expect mode to be 'stream' or 'file', but got '${options.mode}'`);
43
+ if (options.mode === "file") assert(!options.fileModeMatch, "`fileModeMatch` options only work on stream mode, please remove it");
44
+ if (Array.isArray(options.whitelist)) options.whitelist = options.whitelist.map((extname) => extname.toLowerCase());
45
+ if (Array.isArray(options.fileExtensions)) options.fileExtensions = options.fileExtensions.map((extname) => {
46
+ return extname.startsWith(".") || extname === "" ? extname.toLowerCase() : `.${extname.toLowerCase()}`;
47
+ });
48
+ function checkExt(fileName) {
49
+ if (typeof options.whitelist === "function") return options.whitelist(fileName);
50
+ const extname = path.extname(fileName).toLowerCase();
51
+ if (Array.isArray(options.whitelist)) return options.whitelist.includes(extname);
52
+ return whitelist.includes(extname) || options.fileExtensions.includes(extname);
53
+ }
54
+ options.checkFile = (_fieldName, fileStream, fileName) => {
55
+ if (!fileStream || !fileName) return;
56
+ try {
57
+ if (!checkExt(fileName)) {
58
+ const err = /* @__PURE__ */ new Error("Invalid filename: " + fileName);
59
+ Reflect.set(err, "status", 400);
60
+ return err;
61
+ }
62
+ } catch (err) {
63
+ err.status = 400;
64
+ return err;
65
+ }
66
+ };
67
+ return options;
68
+ }
69
+
70
+ //#endregion
71
+ export { humanizeBytes, normalizeOptions, whitelist };
@@ -0,0 +1,24 @@
1
+ import { EggFile, MultipartFileStream, MultipartOptions } from "./app/extend/context.js";
2
+ import { MultipartConfig } from "./config/config.default.js";
3
+
4
+ //#region src/types.d.ts
5
+ declare module 'egg' {
6
+ interface EggAppConfig {
7
+ /**
8
+ * multipart parser options
9
+ * @member Config#multipart
10
+ */
11
+ multipart: MultipartConfig;
12
+ }
13
+ interface Request {
14
+ /**
15
+ * Files Object Array
16
+ */
17
+ files?: EggFile[];
18
+ }
19
+ interface Context {
20
+ saveRequestFiles(options?: MultipartOptions): Promise<void>;
21
+ getFileStream(options?: MultipartOptions): Promise<MultipartFileStream>;
22
+ cleanupRequestFiles(files?: EggFile[]): Promise<void>;
23
+ }
24
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export { };
package/package.json CHANGED
@@ -1,24 +1,12 @@
1
1
  {
2
2
  "name": "@eggjs/multipart",
3
- "version": "4.0.0",
4
- "publishConfig": {
5
- "access": "public"
6
- },
3
+ "version": "5.0.0-beta.17",
4
+ "description": "multipart plugin for egg",
7
5
  "eggPlugin": {
8
6
  "name": "multipart",
9
7
  "optionalDependencies": [
10
8
  "schedule"
11
- ],
12
- "exports": {
13
- "import": "./dist/esm",
14
- "require": "./dist/commonjs",
15
- "typescript": "./src"
16
- }
17
- },
18
- "description": "multipart plugin for egg",
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/eggjs/multipart.git"
9
+ ]
22
10
  },
23
11
  "keywords": [
24
12
  "egg",
@@ -26,78 +14,71 @@
26
14
  "eggPlugin",
27
15
  "multipart"
28
16
  ],
29
- "author": "gxcsoccer <gxcsoccer@126.com>",
30
- "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git://github.com/eggjs/egg.git",
20
+ "directory": "plugins/multipart"
21
+ },
31
22
  "bugs": {
32
23
  "url": "https://github.com/eggjs/egg/issues"
33
24
  },
34
- "homepage": "https://github.com/eggjs/multipart#readme",
25
+ "homepage": "https://github.com/eggjs/egg/tree/next/plugins/multipart#readme",
26
+ "author": "gxcsoccer <gxcsoccer@126.com>",
27
+ "license": "MIT",
35
28
  "engines": {
36
- "node": ">= 18.19.0"
29
+ "node": ">= 22.18.0"
30
+ },
31
+ "type": "module",
32
+ "exports": {
33
+ ".": "./dist/index.js",
34
+ "./app": "./dist/app.js",
35
+ "./app/extend/context": "./dist/app/extend/context.js",
36
+ "./app/middleware/multipart": "./dist/app/middleware/multipart.js",
37
+ "./app/schedule/clean_tmpdir": "./dist/app/schedule/clean_tmpdir.js",
38
+ "./config/config.default": "./dist/config/config.default.js",
39
+ "./lib/LimitError": "./dist/lib/LimitError.js",
40
+ "./lib/MultipartFileTooLargeError": "./dist/lib/MultipartFileTooLargeError.js",
41
+ "./lib/utils": "./dist/lib/utils.js",
42
+ "./types": "./dist/types.js",
43
+ "./package.json": "./package.json"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
37
47
  },
38
48
  "dependencies": {
39
- "@eggjs/core": "^6.3.1",
40
49
  "bytes": "^3.1.2",
41
50
  "co-busboy": "^2.0.1",
42
- "dayjs": "^1.11.5",
43
- "egg-path-matching": "^2.1.0"
51
+ "dayjs": "^1.11.13",
52
+ "egg-path-matching": "^2.0.0"
53
+ },
54
+ "peerDependencies": {
55
+ "egg": "4.1.0-beta.17"
44
56
  },
45
57
  "devDependencies": {
46
- "@arethetypeswrong/cli": "^0.17.1",
47
- "@eggjs/bin": "7",
48
- "@eggjs/mock": "^6.0.5",
49
- "@eggjs/tsconfig": "1",
50
58
  "@types/bytes": "^3.1.5",
51
- "@types/mocha": "10",
52
- "@types/node": "22",
53
- "egg": "^4.0.6",
54
- "eslint": "8",
55
- "eslint-config-egg": "14",
59
+ "@types/node": "24.5.2",
56
60
  "formstream": "^1.5.1",
57
- "is-type-of": "2",
58
- "path-to-regexp-v8": "npm:path-to-regexp@8",
59
- "rimraf": "6",
61
+ "is-type-of": "^2.2.0",
60
62
  "stream-wormhole": "^2.0.1",
61
- "tshy": "3",
62
- "tshy-after": "1",
63
- "typescript": "5",
64
- "urllib": "4"
65
- },
66
- "scripts": {
67
- "lint": "eslint --cache src test --ext .ts",
68
- "pretest": "npm run clean && npm run lint -- --fix",
69
- "test": "egg-bin test",
70
- "preci": "npm run clean && npm run lint",
71
- "ci": "egg-bin cov",
72
- "postci": "npm run prepublishOnly && npm run clean",
73
- "clean": "rimraf dist",
74
- "prepublishOnly": "tshy && tshy-after && attw --pack"
75
- },
76
- "type": "module",
77
- "tshy": {
78
- "exports": {
79
- ".": "./src/index.ts",
80
- "./package.json": "./package.json"
81
- }
82
- },
83
- "exports": {
84
- ".": {
85
- "import": {
86
- "types": "./dist/esm/index.d.ts",
87
- "default": "./dist/esm/index.js"
88
- },
89
- "require": {
90
- "types": "./dist/commonjs/index.d.ts",
91
- "default": "./dist/commonjs/index.js"
92
- }
93
- },
94
- "./package.json": "./package.json"
63
+ "tsdown": "^0.15.4",
64
+ "typescript": "5.9.2",
65
+ "urllib": "^4.8.2",
66
+ "vitest": "4.0.0-beta.13",
67
+ "@eggjs/mock": "7.0.0-beta.17",
68
+ "@eggjs/tsconfig": "3.1.0-beta.17",
69
+ "@eggjs/schedule": "6.0.0-beta.17"
95
70
  },
96
71
  "files": [
97
- "dist",
98
- "src"
72
+ "dist"
99
73
  ],
100
- "types": "./dist/commonjs/index.d.ts",
101
- "main": "./dist/commonjs/index.js",
102
- "module": "./dist/esm/index.js"
103
- }
74
+ "main": "./dist/index.js",
75
+ "module": "./dist/index.js",
76
+ "types": "./dist/index.d.ts",
77
+ "scripts": {
78
+ "build": "tsdown",
79
+ "typecheck": "tsc --noEmit",
80
+ "lint": "oxlint --type-aware",
81
+ "lint:fix": "npm run lint -- --fix",
82
+ "test": "npm run lint:fix && vitest"
83
+ }
84
+ }
@@ -1,110 +0,0 @@
1
- import { Readable } from 'node:stream';
2
- import { Context } from '@eggjs/core';
3
- export interface EggFile {
4
- field: string;
5
- filename: string;
6
- encoding: string;
7
- mime: string;
8
- filepath: string;
9
- }
10
- export interface MultipartFileStream extends Readable {
11
- fields: Record<string, any>;
12
- filename: string;
13
- fieldname: string;
14
- mime: string;
15
- mimeType: string;
16
- transferEncoding: string;
17
- encoding: string;
18
- truncated: boolean;
19
- }
20
- export interface MultipartOptions {
21
- autoFields?: boolean;
22
- /**
23
- * required file submit, default is true
24
- */
25
- requireFile?: boolean;
26
- /**
27
- * default charset encoding
28
- */
29
- defaultCharset?: string;
30
- /**
31
- * compatible with defaultCharset
32
- * @deprecated use `defaultCharset` instead
33
- */
34
- defCharset?: string;
35
- defaultParamCharset?: string;
36
- /**
37
- * compatible with defaultParamCharset
38
- * @deprecated use `defaultParamCharset` instead
39
- */
40
- defParamCharset?: string;
41
- limits?: {
42
- fieldNameSize?: number;
43
- fieldSize?: number;
44
- fields?: number;
45
- fileSize?: number;
46
- files?: number;
47
- parts?: number;
48
- headerPairs?: number;
49
- };
50
- checkFile?(fieldname: string, file: any, filename: string, encoding: string, mimetype: string): void | Error;
51
- }
52
- export default class MultipartContext extends Context {
53
- /**
54
- * create multipart.parts instance, to get separated files.
55
- * @function Context#multipart
56
- * @param {Object} [options] - override default multipart configurations
57
- * - {Boolean} options.autoFields
58
- * - {String} options.defaultCharset
59
- * - {String} options.defaultParamCharset
60
- * - {Object} options.limits
61
- * - {Function} options.checkFile
62
- * @return {Yieldable | AsyncIterable<Yieldable>} parts
63
- */
64
- multipart(options?: MultipartOptions): AsyncIterable<MultipartFileStream>;
65
- /**
66
- * save request multipart data and files to `ctx.request`
67
- * @function Context#saveRequestFiles
68
- * @param {Object} options - { limits, checkFile, ... }
69
- */
70
- saveRequestFiles(options?: MultipartOptions): Promise<void>;
71
- /**
72
- * get upload file stream
73
- * @example
74
- * ```js
75
- * const stream = await ctx.getFileStream();
76
- * // get other fields
77
- * console.log(stream.fields);
78
- * ```
79
- * @function Context#getFileStream
80
- * @param {Object} options
81
- * - {Boolean} options.requireFile - required file submit, default is true
82
- * - {String} options.defaultCharset
83
- * - {String} options.defaultParamCharset
84
- * - {Object} options.limits
85
- * - {Function} options.checkFile
86
- * @return {ReadStream} stream
87
- * @since 1.0.0
88
- * @deprecated Not safe enough, use `ctx.multipart()` instead
89
- */
90
- getFileStream(options?: MultipartOptions): Promise<MultipartFileStream>;
91
- /**
92
- * clean up request tmp files helper
93
- * @function Context#cleanupRequestFiles
94
- * @param {Array<String>} [files] - file paths need to cleanup, default is `ctx.request.files`.
95
- */
96
- cleanupRequestFiles(files?: EggFile[]): Promise<void>;
97
- }
98
- declare module '@eggjs/core' {
99
- interface Request {
100
- /**
101
- * Files Object Array
102
- */
103
- files?: EggFile[];
104
- }
105
- interface Context {
106
- saveRequestFiles(options?: MultipartOptions): Promise<void>;
107
- getFileStream(options?: MultipartOptions): Promise<MultipartFileStream>;
108
- cleanupRequestFiles(files?: EggFile[]): Promise<void>;
109
- }
110
- }