koa-files 2.3.7 → 2.3.8

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/esm/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package koa-files
3
3
  * @license MIT
4
- * @version 2.3.7
4
+ * @version 2.3.8
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A static files serving middleware for koa.
7
7
  * @see https://github.com/nuintun/koa-files#readme
@@ -18,122 +18,117 @@ import { relative, isAbsolute } from 'path';
18
18
  const CHARS = Array.from('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
19
19
  /**
20
20
  * @function isOutRoot
21
- * @description Test path is out of bound of root
22
- * @param {string} path
23
- * @param {string} root
24
- * @returns {boolean}
21
+ * @description Check if path is out of root
22
+ * @param path The path to check
23
+ * @param root The root path
25
24
  */
26
25
  function isOutRoot(path, root) {
27
- path = relative(root, path);
28
- return /\.\.(?:[\\/]|$)/.test(path) || isAbsolute(path);
26
+ path = relative(root, path);
27
+ return /\.\.(?:[\\/]|$)/.test(path) || isAbsolute(path);
29
28
  }
30
29
  /**
31
30
  * @function unixify
32
- * @description Convert path separators to posix/unix-style forward slashes
33
- * @param {string} path
34
- * @returns {string}
31
+ * @description Convert path to unix style
32
+ * @param path The path to convert
35
33
  */
36
34
  function unixify(path) {
37
- return path.replace(/\\/g, '/');
35
+ return path.replace(/\\/g, '/');
38
36
  }
39
37
  /**
40
38
  * @function decodeURI
41
- * @description Decode URI component.
42
- * @param {string} URI
43
- * @returns {string|-1}
39
+ * @description Decode URI component
40
+ * @param URI The URI to decode
44
41
  */
45
42
  function decodeURI(URI) {
46
- try {
47
- return decodeURIComponent(URI);
48
- }
49
- catch (error) {
50
- return -1;
51
- }
43
+ try {
44
+ return decodeURIComponent(URI);
45
+ } catch (error) {
46
+ return -1;
47
+ }
52
48
  }
53
49
  /**
54
50
  * @function boundaryGenerator
55
- * @description Create boundary
56
- * @returns {string}
51
+ * @description Generate a boundary
57
52
  */
58
53
  function boundaryGenerator() {
59
- let boundary = '';
60
- // Create boundary
61
- for (let i = 0; i < 38; i++) {
62
- boundary += CHARS[Math.floor(Math.random() * 62)];
63
- }
64
- // Return boundary
65
- return boundary;
54
+ let boundary = '';
55
+ // Create boundary
56
+ for (let i = 0; i < 38; i++) {
57
+ boundary += CHARS[Math.floor(Math.random() * 62)];
58
+ }
59
+ // Return boundary
60
+ return boundary;
66
61
  }
67
62
  /**
68
63
  * @function fstat
69
- * @param {string} path
70
- * @returns {Promise<Stats>}
64
+ * @description Get file stats
65
+ * @param path The file path
71
66
  */
72
67
  function fstat(path) {
73
- return new Promise((resolve, reject) => {
74
- fs.stat(path, (error, stats) => {
75
- error ? reject(error) : resolve(stats);
76
- });
68
+ return new Promise((resolve, reject) => {
69
+ fs.stat(path, (error, stats) => {
70
+ error ? reject(error) : resolve(stats);
77
71
  });
72
+ });
78
73
  }
79
74
  /**
80
75
  * @function hasTrailingSlash
81
- * @param {string} path
82
- * @returns {boolean}
76
+ * @description Check if path has trailing slash
77
+ * @param path The path to check
83
78
  */
84
79
  function hasTrailingSlash(path) {
85
- return /\/$/.test(path);
80
+ return /\/$/.test(path);
86
81
  }
87
82
  /**
88
83
  * @function parseTokens
89
- * @description Parse a HTTP tokens.
90
- * @param {string[]} value
84
+ * @description Parse HTTP tokens
85
+ * @param value The tokens value string
91
86
  */
92
87
  function parseTokens(value) {
93
- let end = 0;
94
- let start = 0;
95
- let tokens = [];
96
- // gather tokens
97
- for (let i = 0, length = value.length; i < length; i++) {
98
- switch (value.charCodeAt(i)) {
99
- case 0x20:
100
- // ' '
101
- if (start === end) {
102
- start = end = i + 1;
103
- }
104
- break;
105
- case 0x2c:
106
- // ','
107
- tokens.push(value.substring(start, end));
108
- start = end = i + 1;
109
- break;
110
- default:
111
- end = i + 1;
112
- break;
88
+ let end = 0;
89
+ let start = 0;
90
+ let tokens = [];
91
+ // gather tokens
92
+ for (let i = 0, length = value.length; i < length; i++) {
93
+ switch (value.charCodeAt(i)) {
94
+ case 0x20:
95
+ // ' '
96
+ if (start === end) {
97
+ start = end = i + 1;
113
98
  }
99
+ break;
100
+ case 0x2c:
101
+ // ','
102
+ tokens.push(value.substring(start, end));
103
+ start = end = i + 1;
104
+ break;
105
+ default:
106
+ end = i + 1;
107
+ break;
114
108
  }
115
- // final token
116
- tokens.push(value.substring(start, end));
117
- return tokens;
109
+ }
110
+ // final token
111
+ tokens.push(value.substring(start, end));
112
+ return tokens;
118
113
  }
119
114
  /**
120
- * @function isETagFresh
121
- * @param {string} match
122
- * @param {string} etag
123
- * @returns {boolean}
115
+ * @function isETag
116
+ * @description Check if etag is valid
117
+ * @param value The value to check
124
118
  */
125
- function isETagFresh(match, etag) {
126
- return parseTokens(match).some(match => {
127
- return match === etag || match === 'W/' + etag || 'W/' + match === etag;
128
- });
119
+ function isETag(value) {
120
+ return /^(?:W\/)?"[\s\S]+"$/.test(value);
129
121
  }
130
122
  /**
131
- * @function isETag
132
- * @param {string} etag
133
- * @returns {boolean}
123
+ * @function isETagFresh
124
+ * @description Check if etag is fresh
125
+ * @param match The match value
126
+ * @param etag The etag value
134
127
  */
135
- function isETag(etag) {
136
- return /(?:W\/)?"(?:[ !#-\x7E\x80-\xFF]*|\r\n[\t ]|\\.)*"/.test(etag);
128
+ function isETagFresh(match, etag) {
129
+ return parseTokens(match).some(match => {
130
+ return match === etag || match === 'W/' + etag || 'W/' + match === etag;
131
+ });
137
132
  }
138
133
 
139
134
  export { boundaryGenerator, decodeURI, fstat, hasTrailingSlash, isETag, isETagFresh, isOutRoot, parseTokens, unixify };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koa-files",
3
- "version": "2.3.7",
3
+ "version": "2.3.8",
4
4
  "description": "A static files serving middleware for koa.",
5
5
  "type": "module",
6
6
  "main": "cjs/index.cjs",
@@ -45,10 +45,10 @@
45
45
  "test": "node tests",
46
46
  "lint": "tsc --noEmit",
47
47
  "clean": "node tools/clean.js",
48
- "format": "prettier --write .",
49
48
  "prepublishOnly": "npm run build",
50
49
  "build:cjs": "rollup -c tools/rollup.cjs.js",
51
50
  "build:esm": "rollup -c tools/rollup.esm.js",
51
+ "format": "prettier --write . --ignore-path .prettierignore",
52
52
  "build": "npm run clean && npm run build:main && npm run format",
53
53
  "build:main": "npm run build:cjs && npm run build:esm && npm run build:types",
54
54
  "build:types": "tsc --declaration --emitDeclarationOnly --declarationDir types"
@@ -65,12 +65,12 @@
65
65
  "@types/etag": "^1.8.3",
66
66
  "@types/koa": "^2.15.0",
67
67
  "@types/range-parser": "^1.2.7",
68
- "koa": "^2.15.0",
68
+ "koa": "^2.15.1",
69
69
  "magic-string": "^0.30.8",
70
70
  "prettier": "^3.2.5",
71
71
  "rimraf": "^5.0.5",
72
- "rollup": "^4.12.0",
73
- "typescript": "^5.3.3"
72
+ "rollup": "^4.13.0",
73
+ "typescript": "^5.4.2"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "koa": "^2.0.0"
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @module Files
3
+ * @license MIT
4
+ * @author nuintun
5
+ */
6
+ import { Context } from 'koa';
7
+ export interface Options {
8
+ etag?: boolean;
9
+ cacheControl?: string;
10
+ acceptRanges?: boolean;
11
+ lastModified?: boolean;
12
+ ignore?: (path: string) => boolean;
13
+ }
14
+ /**
15
+ * @class Files
16
+ */
17
+ export default class Files {
18
+ private root;
19
+ private options;
20
+ /**
21
+ * @constructor
22
+ * @description Create files service
23
+ * @param root Files service root
24
+ * @param options Files service options
25
+ */
26
+ constructor(root: string, options?: Options);
27
+ /**
28
+ * @private
29
+ * @method isConditionalGET
30
+ * @description Check if request is conditional GET
31
+ * @param context Koa context
32
+ */
33
+ private isConditionalGET;
34
+ /**
35
+ * @private
36
+ * @method isPreconditionFailure
37
+ * @description Check if request precondition failure
38
+ * @param context Koa context
39
+ */
40
+ private isPreconditionFailure;
41
+ /**
42
+ * @private
43
+ * @method isRangeFresh
44
+ * @description Check if request range fresh
45
+ * @param context Koa context
46
+ */
47
+ private isRangeFresh;
48
+ /**
49
+ * @private
50
+ * @method isIgnore
51
+ * @description Check if path is ignore
52
+ * @param path File path
53
+ */
54
+ private isIgnore;
55
+ /**
56
+ * @private
57
+ * @method parseRange
58
+ * @description Parse range
59
+ * @param context Koa context
60
+ * @param stats File stats
61
+ */
62
+ private parseRange;
63
+ /**
64
+ * @private
65
+ * @method setupHeaders
66
+ * @description Setup headers
67
+ * @param context Koa context
68
+ * @param path File path
69
+ * @param stats File stats
70
+ */
71
+ private setupHeaders;
72
+ /**
73
+ * @private
74
+ * @method read
75
+ * @description Read file
76
+ * @param path File path
77
+ * @param range Read range
78
+ * @param buffer Destination stream
79
+ * @param end Is destory destination stream after read
80
+ */
81
+ private read;
82
+ /**
83
+ * @private
84
+ * @method send
85
+ * @description Send file
86
+ * @param context Koa context
87
+ * @param path File path
88
+ * @param ranges Read ranges
89
+ */
90
+ private send;
91
+ /**
92
+ * @public
93
+ * @method response
94
+ * @description Response to koa context
95
+ * @param context Koa context
96
+ */
97
+ response(context: Context): Promise<boolean>;
98
+ }
package/types/index.d.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  * @author nuintun
5
5
  */
6
6
  import { Middleware } from 'koa';
7
- import { Options as SendOptions } from './Send';
8
- export interface Options extends SendOptions {
9
- defer?: boolean;
7
+ import { Options as FilesOptions } from './Files';
8
+ export interface Options extends FilesOptions {
9
+ defer?: boolean;
10
10
  }
11
11
  /**
12
12
  * @function server
package/types/utils.d.ts CHANGED
@@ -7,60 +7,56 @@
7
7
  import { Stats } from 'fs';
8
8
  /**
9
9
  * @function isOutRoot
10
- * @description Test path is out of bound of root
11
- * @param {string} path
12
- * @param {string} root
13
- * @returns {boolean}
10
+ * @description Check if path is out of root
11
+ * @param path The path to check
12
+ * @param root The root path
14
13
  */
15
14
  export declare function isOutRoot(path: string, root: string): boolean;
16
15
  /**
17
16
  * @function unixify
18
- * @description Convert path separators to posix/unix-style forward slashes
19
- * @param {string} path
20
- * @returns {string}
17
+ * @description Convert path to unix style
18
+ * @param path The path to convert
21
19
  */
22
20
  export declare function unixify(path: string): string;
23
21
  /**
24
22
  * @function decodeURI
25
- * @description Decode URI component.
26
- * @param {string} URI
27
- * @returns {string|-1}
23
+ * @description Decode URI component
24
+ * @param URI The URI to decode
28
25
  */
29
26
  export declare function decodeURI(URI: string): string | -1;
30
27
  /**
31
28
  * @function boundaryGenerator
32
- * @description Create boundary
33
- * @returns {string}
29
+ * @description Generate a boundary
34
30
  */
35
31
  export declare function boundaryGenerator(): string;
36
32
  /**
37
33
  * @function fstat
38
- * @param {string} path
39
- * @returns {Promise<Stats>}
34
+ * @description Get file stats
35
+ * @param path The file path
40
36
  */
41
37
  export declare function fstat(path: string): Promise<Stats>;
42
38
  /**
43
39
  * @function hasTrailingSlash
44
- * @param {string} path
45
- * @returns {boolean}
40
+ * @description Check if path has trailing slash
41
+ * @param path The path to check
46
42
  */
47
43
  export declare function hasTrailingSlash(path: string): boolean;
48
44
  /**
49
45
  * @function parseTokens
50
- * @description Parse a HTTP tokens.
51
- * @param {string[]} value
46
+ * @description Parse HTTP tokens
47
+ * @param value The tokens value string
52
48
  */
53
49
  export declare function parseTokens(value: string): string[];
54
50
  /**
55
- * @function isETagFresh
56
- * @param {string} match
57
- * @param {string} etag
58
- * @returns {boolean}
51
+ * @function isETag
52
+ * @description Check if etag is valid
53
+ * @param value The value to check
59
54
  */
60
- export declare function isETagFresh(match: string, etag: string): boolean;
55
+ export declare function isETag(value: string): boolean;
61
56
  /**
62
- * @function isETag
63
- * @param {string} etag
64
- * @returns {boolean}
57
+ * @function isETagFresh
58
+ * @description Check if etag is fresh
59
+ * @param match The match value
60
+ * @param etag The etag value
65
61
  */
66
- export declare function isETag(etag: string): boolean;
62
+ export declare function isETagFresh(match: string, etag: string): boolean;