@eggjs/static 3.0.0
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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/commonjs/app/middleware/static.d.ts +5 -0
- package/dist/commonjs/app/middleware/static.js +57 -0
- package/dist/commonjs/app.d.ts +6 -0
- package/dist/commonjs/app.js +21 -0
- package/dist/commonjs/config/config.default.d.ts +6 -0
- package/dist/commonjs/config/config.default.js +22 -0
- package/dist/commonjs/config/config.prod.d.ts +5 -0
- package/dist/commonjs/config/config.prod.js +9 -0
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +4 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +60 -0
- package/dist/commonjs/types.js +3 -0
- package/dist/esm/app/middleware/static.d.ts +5 -0
- package/dist/esm/app/middleware/static.js +52 -0
- package/dist/esm/app.d.ts +6 -0
- package/dist/esm/app.js +18 -0
- package/dist/esm/config/config.default.d.ts +6 -0
- package/dist/esm/config/config.default.js +17 -0
- package/dist/esm/config/config.prod.d.ts +5 -0
- package/dist/esm/config/config.prod.js +7 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +60 -0
- package/dist/esm/types.js +2 -0
- package/dist/package.json +4 -0
- package/package.json +93 -0
- package/src/app/middleware/static.ts +66 -0
- package/src/app.ts +18 -0
- package/src/config/config.default.ts +19 -0
- package/src/config/config.prod.ts +8 -0
- package/src/index.ts +1 -0
- package/src/types.ts +64 -0
- package/src/typings/index.d.ts +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017-present Alibaba Group Holding Limited and other contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @eggjs/static
|
|
2
|
+
|
|
3
|
+
[![NPM version][npm-image]][npm-url]
|
|
4
|
+
[](https://github.com/eggjs/static/actions/workflows/nodejs.yml)
|
|
5
|
+
[![Test coverage][codecov-image]][codecov-url]
|
|
6
|
+
[![Known Vulnerabilities][snyk-image]][snyk-url]
|
|
7
|
+
[![npm download][download-image]][download-url]
|
|
8
|
+
[](https://nodejs.org/en/download/)
|
|
9
|
+
[](https://makeapullrequest.com)
|
|
10
|
+
|
|
11
|
+
[npm-image]: https://img.shields.io/npm/v/@eggjs/static.svg?style=flat-square
|
|
12
|
+
[npm-url]: https://npmjs.org/package/@eggjs/static
|
|
13
|
+
[codecov-image]: https://img.shields.io/codecov/c/github/eggjs/static.svg?style=flat-square
|
|
14
|
+
[codecov-url]: https://codecov.io/github/eggjs/static?branch=master
|
|
15
|
+
[snyk-image]: https://snyk.io/test/npm/@eggjs/static/badge.svg?style=flat-square
|
|
16
|
+
[snyk-url]: https://snyk.io/test/npm/@eggjs/static
|
|
17
|
+
[download-image]: https://img.shields.io/npm/dm/@eggjs/static.svg?style=flat-square
|
|
18
|
+
[download-url]: https://npmjs.org/package/@eggjs/static
|
|
19
|
+
|
|
20
|
+
Static server plugin for egg, base on [@eggjs/koa-static-cache](https://github.com/eggjs/koa-static-cache).
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
`@eggjs/static` is a plugin that has been built-in for egg. It is enabled by default.
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
`@eggjs/static` support all configurations in [@eggjs/koa-static-cache](https://github.com/eggjs/koa-static-cache).
|
|
29
|
+
And with default configurations below:
|
|
30
|
+
|
|
31
|
+
- prefix: `'/public/'`
|
|
32
|
+
- dir: `path.join(appInfo.baseDir, 'app/public')`
|
|
33
|
+
- dynamic: `true`
|
|
34
|
+
- preload: `false`
|
|
35
|
+
- maxAge: `31536000` in prod env, `0` in other envs
|
|
36
|
+
- buffer: `true` in prod env, `false` in other envs
|
|
37
|
+
|
|
38
|
+
`@eggjs/static` provides one more option:
|
|
39
|
+
|
|
40
|
+
- maxFiles: the maximum value of cache items, only effective when dynamic is true, default is `1000`.
|
|
41
|
+
|
|
42
|
+
**All static files in `$baseDir/app/public` can be visited with prefix `/public`, and all the files are lazy loaded.**
|
|
43
|
+
|
|
44
|
+
- In non-production environment, assets won't be cached, your modification can take effect immediately.
|
|
45
|
+
- In production environment, `@eggjs/static` will cache the assets after visited, you need to restart the process to update the assets.
|
|
46
|
+
- Dir default is `$baseDir/app/public` but you can also define **multiple directory** by use `dir: [dir1, dir2, ...]` or `dir: [dir1, { prefix: '/static2', dir: dir2 }]`, static server will use all these directories.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// {app_root}/config/config.default.ts
|
|
50
|
+
export default {
|
|
51
|
+
static: {
|
|
52
|
+
// maxAge: 31536000,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Questions & Suggestions
|
|
58
|
+
|
|
59
|
+
Please open an issue [here](https://github.com/eggjs/egg/issues).
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
[MIT](LICENSE)
|
|
64
|
+
|
|
65
|
+
## Contributors
|
|
66
|
+
|
|
67
|
+
[](https://github.com/eggjs/static/graphs/contributors)
|
|
68
|
+
|
|
69
|
+
Made with [contributors-img](https://contrib.rocks).
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import compose from 'koa-compose';
|
|
2
|
+
import type { EggCore, Context } from '@eggjs/core';
|
|
3
|
+
import type { StaticConfig } from '../../types.js';
|
|
4
|
+
declare const _default: (options: StaticConfig, app: EggCore) => compose.ComposedMiddleware<Context>;
|
|
5
|
+
export default _default;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const koa_range_1 = __importDefault(require("koa-range"));
|
|
9
|
+
const koa_compose_1 = __importDefault(require("koa-compose"));
|
|
10
|
+
const koa_static_cache_1 = require("@eggjs/koa-static-cache");
|
|
11
|
+
const ylru_1 = require("ylru");
|
|
12
|
+
const is_type_of_1 = require("is-type-of");
|
|
13
|
+
exports.default = (options, app) => {
|
|
14
|
+
const dirs = (options.dirs ?? []).concat(options.dir);
|
|
15
|
+
const prefixes = [];
|
|
16
|
+
function rangeMiddleware(ctx, next) {
|
|
17
|
+
// if match static file, and use range middleware.
|
|
18
|
+
const isMatch = prefixes.some(p => ctx.path.startsWith(p));
|
|
19
|
+
if (isMatch) {
|
|
20
|
+
return (0, koa_range_1.default)(ctx, next);
|
|
21
|
+
}
|
|
22
|
+
return next();
|
|
23
|
+
}
|
|
24
|
+
const middlewares = [rangeMiddleware];
|
|
25
|
+
for (const dirObj of dirs) {
|
|
26
|
+
(0, node_assert_1.default)((0, is_type_of_1.isObject)(dirObj) || typeof dirObj === 'string', '`config.static.dir` must be `string | Array<string|object>`');
|
|
27
|
+
let newOptions;
|
|
28
|
+
if (typeof dirObj === 'string') {
|
|
29
|
+
// copy origin options to new options ensure the safety of objects
|
|
30
|
+
newOptions = {
|
|
31
|
+
...options,
|
|
32
|
+
dir: dirObj,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
(0, node_assert_1.default)(typeof dirObj.dir === 'string', '`config.static.dirs` should contains `[].dir` property when object style');
|
|
37
|
+
newOptions = {
|
|
38
|
+
...options,
|
|
39
|
+
...dirObj,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (newOptions.dynamic && !newOptions.files) {
|
|
43
|
+
newOptions.files = new ylru_1.LRU(newOptions.maxFiles);
|
|
44
|
+
}
|
|
45
|
+
if (newOptions.prefix) {
|
|
46
|
+
prefixes.push(newOptions.prefix);
|
|
47
|
+
}
|
|
48
|
+
// ensure directory exists
|
|
49
|
+
if (!(0, node_fs_1.existsSync)(newOptions.dir)) {
|
|
50
|
+
(0, node_fs_1.mkdirSync)(newOptions.dir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
middlewares.push((0, koa_static_cache_1.staticCache)(newOptions));
|
|
53
|
+
app.coreLogger.info('[@eggjs/static] starting static serve %s -> %s', newOptions.prefix, newOptions.dir);
|
|
54
|
+
}
|
|
55
|
+
return (0, koa_compose_1.default)(middlewares);
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9taWRkbGV3YXJlL3N0YXRpYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDhEQUFpQztBQUNqQyxxQ0FBZ0Q7QUFDaEQsMERBQThCO0FBQzlCLDhEQUFrQztBQUVsQyw4REFBc0Q7QUFDdEQsK0JBQTJCO0FBQzNCLDJDQUFzQztBQUd0QyxrQkFBZSxDQUFDLE9BQXFCLEVBQUUsR0FBWSxFQUFFLEVBQUU7SUFDckQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFdEQsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO0lBRTlCLFNBQVMsZUFBZSxDQUFDLEdBQVksRUFBRSxJQUFVO1FBQy9DLGtEQUFrRDtRQUNsRCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osT0FBTyxJQUFBLG1CQUFLLEVBQUMsR0FBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxPQUFPLElBQUksRUFBRSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxDQUFFLGVBQWUsQ0FBRSxDQUFDO0lBRXhDLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7UUFDMUIsSUFBQSxxQkFBTSxFQUFDLElBQUEscUJBQVEsRUFBQyxNQUFNLENBQUMsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQ25ELDZEQUE2RCxDQUFDLENBQUM7UUFFakUsSUFBSSxVQUE0QixDQUFDO1FBQ2pDLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDL0Isa0VBQWtFO1lBQ2xFLFVBQVUsR0FBRztnQkFDWCxHQUFHLE9BQU87Z0JBQ1YsR0FBRyxFQUFFLE1BQU07YUFDWixDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTixJQUFBLHFCQUFNLEVBQUMsT0FBTyxNQUFNLENBQUMsR0FBRyxLQUFLLFFBQVEsRUFDbkMsMEVBQTBFLENBQUMsQ0FBQztZQUM5RSxVQUFVLEdBQUc7Z0JBQ1gsR0FBRyxPQUFPO2dCQUNWLEdBQUcsTUFBTTthQUNWLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxVQUFVLENBQUMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzVDLFVBQVUsQ0FBQyxLQUFLLEdBQUcsSUFBSSxVQUFHLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELENBQUM7UUFFRCxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN0QixRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBRUQsMEJBQTBCO1FBQzFCLElBQUksQ0FBQyxJQUFBLG9CQUFVLEVBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDaEMsSUFBQSxtQkFBUyxFQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBQ0QsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFBLDhCQUFXLEVBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUV6QyxHQUFXLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxnREFBZ0QsRUFDM0UsVUFBVSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELE9BQU8sSUFBQSxxQkFBTyxFQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzlCLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class AppBoot {
|
|
4
|
+
app;
|
|
5
|
+
constructor(app) {
|
|
6
|
+
this.app = app;
|
|
7
|
+
}
|
|
8
|
+
async configWillLoad() {
|
|
9
|
+
const app = this.app;
|
|
10
|
+
// make sure static middleware is before bodyParser
|
|
11
|
+
const index = app.config.coreMiddleware.indexOf('bodyParser');
|
|
12
|
+
if (index === -1) {
|
|
13
|
+
app.config.coreMiddleware.push('static');
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
app.config.coreMiddleware.splice(index, 0, 'static');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = AppBoot;
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQXFCLE9BQU87SUFDVCxHQUFHLENBQUM7SUFDckIsWUFBWSxHQUFZO1FBQ3RCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxLQUFLLENBQUMsY0FBYztRQUNsQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3JCLG1EQUFtRDtRQUNuRCxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDOUQsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNqQixHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDM0MsQ0FBQzthQUFNLENBQUM7WUFDTixHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN2RCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBZkQsMEJBZUMifQ==
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
+
exports.default = (appInfo) => {
|
|
8
|
+
return {
|
|
9
|
+
static: {
|
|
10
|
+
prefix: '/public/',
|
|
11
|
+
dir: node_path_1.default.join(appInfo.baseDir, 'app/public'),
|
|
12
|
+
// dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
|
|
13
|
+
dirs: undefined,
|
|
14
|
+
// support lazy load
|
|
15
|
+
dynamic: true,
|
|
16
|
+
preload: false,
|
|
17
|
+
buffer: false,
|
|
18
|
+
maxFiles: 1000,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMERBQTZCO0FBSTdCLGtCQUFlLENBQUMsT0FBbUIsRUFBRSxFQUFFO0lBQ3JDLE9BQU87UUFDTCxNQUFNLEVBQUU7WUFDTixNQUFNLEVBQUUsVUFBVTtZQUNsQixHQUFHLEVBQUUsbUJBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUM7WUFDN0MsdUVBQXVFO1lBQ3ZFLElBQUksRUFBRSxTQUFTO1lBQ2Ysb0JBQW9CO1lBQ3BCLE9BQU8sRUFBRSxJQUFJO1lBQ2IsT0FBTyxFQUFFLEtBQUs7WUFDZCxNQUFNLEVBQUUsS0FBSztZQUNiLFFBQVEsRUFBRSxJQUFJO1NBQ0M7S0FDbEIsQ0FBQztBQUNKLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = {
|
|
4
|
+
static: {
|
|
5
|
+
maxAge: 31536000,
|
|
6
|
+
buffer: true,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLnByb2QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5wcm9kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUEsa0JBQWU7SUFDYixNQUFNLEVBQUU7UUFDTixNQUFNLEVBQUUsUUFBUTtRQUNoQixNQUFNLEVBQUUsSUFBSTtLQUNHO0NBQ2xCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
require("./types.js");
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxzQkFBb0IifQ==
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Options as StaticCacheOptions } from '@eggjs/koa-static-cache';
|
|
2
|
+
export interface StaticDirOptions extends Omit<StaticCacheOptions, 'dir'> {
|
|
3
|
+
/**
|
|
4
|
+
* static files store dir
|
|
5
|
+
*/
|
|
6
|
+
dir: string;
|
|
7
|
+
/**
|
|
8
|
+
* static files prefix
|
|
9
|
+
* Default to `'/public/'`
|
|
10
|
+
*/
|
|
11
|
+
prefix: string;
|
|
12
|
+
/**
|
|
13
|
+
* cache max age in `seconds`
|
|
14
|
+
* Default to `0` on development, `31536000` on production
|
|
15
|
+
*/
|
|
16
|
+
maxAge: number;
|
|
17
|
+
/**
|
|
18
|
+
* dynamic load file which not cached on initialization
|
|
19
|
+
* Default to `true
|
|
20
|
+
*/
|
|
21
|
+
dynamic: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* caches the assets on initialization or not,
|
|
24
|
+
* always work together with `options.dynamic`
|
|
25
|
+
* Default to `false`
|
|
26
|
+
*/
|
|
27
|
+
preload: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* buffer the file content or not
|
|
30
|
+
* Default to `false` on development, `true` on production
|
|
31
|
+
*/
|
|
32
|
+
buffer: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* max files count in store
|
|
35
|
+
* Default to `1000`
|
|
36
|
+
*/
|
|
37
|
+
maxFiles: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Static file serve
|
|
41
|
+
* @member Config#static
|
|
42
|
+
* @see https://github.com/koajs/static-cache
|
|
43
|
+
*/
|
|
44
|
+
export interface StaticConfig extends Omit<StaticDirOptions, 'dir'> {
|
|
45
|
+
/**
|
|
46
|
+
* static files store dir
|
|
47
|
+
* Default to `${baseDir}/app/public`
|
|
48
|
+
*/
|
|
49
|
+
dir: string | Array<string | StaticDirOptions>;
|
|
50
|
+
/**
|
|
51
|
+
* static files store dirs
|
|
52
|
+
* @deprecated use `dir` instead
|
|
53
|
+
*/
|
|
54
|
+
dirs?: Array<string | StaticDirOptions>;
|
|
55
|
+
}
|
|
56
|
+
declare module '@eggjs/core' {
|
|
57
|
+
interface EggAppConfig {
|
|
58
|
+
static: StaticConfig;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import compose from 'koa-compose';
|
|
2
|
+
import type { EggCore, Context } from '@eggjs/core';
|
|
3
|
+
import type { StaticConfig } from '../../types.js';
|
|
4
|
+
declare const _default: (options: StaticConfig, app: EggCore) => compose.ComposedMiddleware<Context>;
|
|
5
|
+
export default _default;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { mkdirSync, existsSync } from 'node:fs';
|
|
3
|
+
import range from 'koa-range';
|
|
4
|
+
import compose from 'koa-compose';
|
|
5
|
+
import { staticCache } from '@eggjs/koa-static-cache';
|
|
6
|
+
import { LRU } from 'ylru';
|
|
7
|
+
import { isObject } from 'is-type-of';
|
|
8
|
+
export default (options, app) => {
|
|
9
|
+
const dirs = (options.dirs ?? []).concat(options.dir);
|
|
10
|
+
const prefixes = [];
|
|
11
|
+
function rangeMiddleware(ctx, next) {
|
|
12
|
+
// if match static file, and use range middleware.
|
|
13
|
+
const isMatch = prefixes.some(p => ctx.path.startsWith(p));
|
|
14
|
+
if (isMatch) {
|
|
15
|
+
return range(ctx, next);
|
|
16
|
+
}
|
|
17
|
+
return next();
|
|
18
|
+
}
|
|
19
|
+
const middlewares = [rangeMiddleware];
|
|
20
|
+
for (const dirObj of dirs) {
|
|
21
|
+
assert(isObject(dirObj) || typeof dirObj === 'string', '`config.static.dir` must be `string | Array<string|object>`');
|
|
22
|
+
let newOptions;
|
|
23
|
+
if (typeof dirObj === 'string') {
|
|
24
|
+
// copy origin options to new options ensure the safety of objects
|
|
25
|
+
newOptions = {
|
|
26
|
+
...options,
|
|
27
|
+
dir: dirObj,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
assert(typeof dirObj.dir === 'string', '`config.static.dirs` should contains `[].dir` property when object style');
|
|
32
|
+
newOptions = {
|
|
33
|
+
...options,
|
|
34
|
+
...dirObj,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (newOptions.dynamic && !newOptions.files) {
|
|
38
|
+
newOptions.files = new LRU(newOptions.maxFiles);
|
|
39
|
+
}
|
|
40
|
+
if (newOptions.prefix) {
|
|
41
|
+
prefixes.push(newOptions.prefix);
|
|
42
|
+
}
|
|
43
|
+
// ensure directory exists
|
|
44
|
+
if (!existsSync(newOptions.dir)) {
|
|
45
|
+
mkdirSync(newOptions.dir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
middlewares.push(staticCache(newOptions));
|
|
48
|
+
app.coreLogger.info('[@eggjs/static] starting static serve %s -> %s', newOptions.prefix, newOptions.dir);
|
|
49
|
+
}
|
|
50
|
+
return compose(middlewares);
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9taWRkbGV3YXJlL3N0YXRpYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDakMsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDaEQsT0FBTyxLQUFLLE1BQU0sV0FBVyxDQUFDO0FBQzlCLE9BQU8sT0FBTyxNQUFNLGFBQWEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdEQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBR3RDLGVBQWUsQ0FBQyxPQUFxQixFQUFFLEdBQVksRUFBRSxFQUFFO0lBQ3JELE1BQU0sSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXRELE1BQU0sUUFBUSxHQUFhLEVBQUUsQ0FBQztJQUU5QixTQUFTLGVBQWUsQ0FBQyxHQUFZLEVBQUUsSUFBVTtRQUMvQyxrREFBa0Q7UUFDbEQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNaLE9BQU8sS0FBSyxDQUFDLEdBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsT0FBTyxJQUFJLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsQ0FBRSxlQUFlLENBQUUsQ0FBQztJQUV4QyxLQUFLLE1BQU0sTUFBTSxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUNuRCw2REFBNkQsQ0FBQyxDQUFDO1FBRWpFLElBQUksVUFBNEIsQ0FBQztRQUNqQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQy9CLGtFQUFrRTtZQUNsRSxVQUFVLEdBQUc7Z0JBQ1gsR0FBRyxPQUFPO2dCQUNWLEdBQUcsRUFBRSxNQUFNO2FBQ1osQ0FBQztRQUNKLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxDQUFDLE9BQU8sTUFBTSxDQUFDLEdBQUcsS0FBSyxRQUFRLEVBQ25DLDBFQUEwRSxDQUFDLENBQUM7WUFDOUUsVUFBVSxHQUFHO2dCQUNYLEdBQUcsT0FBTztnQkFDVixHQUFHLE1BQU07YUFDVixDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksVUFBVSxDQUFDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM1QyxVQUFVLENBQUMsS0FBSyxHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsSUFBSSxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEIsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkMsQ0FBQztRQUVELDBCQUEwQjtRQUMxQixJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2hDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUNELFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFFekMsR0FBVyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsZ0RBQWdELEVBQzNFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUM5QixDQUFDLENBQUMifQ==
|
package/dist/esm/app.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default class AppBoot {
|
|
2
|
+
app;
|
|
3
|
+
constructor(app) {
|
|
4
|
+
this.app = app;
|
|
5
|
+
}
|
|
6
|
+
async configWillLoad() {
|
|
7
|
+
const app = this.app;
|
|
8
|
+
// make sure static middleware is before bodyParser
|
|
9
|
+
const index = app.config.coreMiddleware.indexOf('bodyParser');
|
|
10
|
+
if (index === -1) {
|
|
11
|
+
app.config.coreMiddleware.push('static');
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
app.config.coreMiddleware.splice(index, 0, 'static');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsT0FBTyxPQUFPLE9BQU87SUFDVCxHQUFHLENBQUM7SUFDckIsWUFBWSxHQUFZO1FBQ3RCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxLQUFLLENBQUMsY0FBYztRQUNsQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3JCLG1EQUFtRDtRQUNuRCxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDOUQsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNqQixHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDM0MsQ0FBQzthQUFNLENBQUM7WUFDTixHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN2RCxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export default (appInfo) => {
|
|
3
|
+
return {
|
|
4
|
+
static: {
|
|
5
|
+
prefix: '/public/',
|
|
6
|
+
dir: path.join(appInfo.baseDir, 'app/public'),
|
|
7
|
+
// dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
|
|
8
|
+
dirs: undefined,
|
|
9
|
+
// support lazy load
|
|
10
|
+
dynamic: true,
|
|
11
|
+
preload: false,
|
|
12
|
+
buffer: false,
|
|
13
|
+
maxFiles: 1000,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmRlZmF1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5kZWZhdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUk3QixlQUFlLENBQUMsT0FBbUIsRUFBRSxFQUFFO0lBQ3JDLE9BQU87UUFDTCxNQUFNLEVBQUU7WUFDTixNQUFNLEVBQUUsVUFBVTtZQUNsQixHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQztZQUM3Qyx1RUFBdUU7WUFDdkUsSUFBSSxFQUFFLFNBQVM7WUFDZixvQkFBb0I7WUFDcEIsT0FBTyxFQUFFLElBQUk7WUFDYixPQUFPLEVBQUUsS0FBSztZQUNkLE1BQU0sRUFBRSxLQUFLO1lBQ2IsUUFBUSxFQUFFLElBQUk7U0FDQztLQUNsQixDQUFDO0FBQ0osQ0FBQyxDQUFDIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
static: {
|
|
3
|
+
maxAge: 31536000,
|
|
4
|
+
buffer: true,
|
|
5
|
+
},
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLnByb2QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2NvbmZpZy5wcm9kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLGVBQWU7SUFDYixNQUFNLEVBQUU7UUFDTixNQUFNLEVBQUUsUUFBUTtRQUNoQixNQUFNLEVBQUUsSUFBSTtLQUNHO0NBQ2xCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Options as StaticCacheOptions } from '@eggjs/koa-static-cache';
|
|
2
|
+
export interface StaticDirOptions extends Omit<StaticCacheOptions, 'dir'> {
|
|
3
|
+
/**
|
|
4
|
+
* static files store dir
|
|
5
|
+
*/
|
|
6
|
+
dir: string;
|
|
7
|
+
/**
|
|
8
|
+
* static files prefix
|
|
9
|
+
* Default to `'/public/'`
|
|
10
|
+
*/
|
|
11
|
+
prefix: string;
|
|
12
|
+
/**
|
|
13
|
+
* cache max age in `seconds`
|
|
14
|
+
* Default to `0` on development, `31536000` on production
|
|
15
|
+
*/
|
|
16
|
+
maxAge: number;
|
|
17
|
+
/**
|
|
18
|
+
* dynamic load file which not cached on initialization
|
|
19
|
+
* Default to `true
|
|
20
|
+
*/
|
|
21
|
+
dynamic: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* caches the assets on initialization or not,
|
|
24
|
+
* always work together with `options.dynamic`
|
|
25
|
+
* Default to `false`
|
|
26
|
+
*/
|
|
27
|
+
preload: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* buffer the file content or not
|
|
30
|
+
* Default to `false` on development, `true` on production
|
|
31
|
+
*/
|
|
32
|
+
buffer: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* max files count in store
|
|
35
|
+
* Default to `1000`
|
|
36
|
+
*/
|
|
37
|
+
maxFiles: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Static file serve
|
|
41
|
+
* @member Config#static
|
|
42
|
+
* @see https://github.com/koajs/static-cache
|
|
43
|
+
*/
|
|
44
|
+
export interface StaticConfig extends Omit<StaticDirOptions, 'dir'> {
|
|
45
|
+
/**
|
|
46
|
+
* static files store dir
|
|
47
|
+
* Default to `${baseDir}/app/public`
|
|
48
|
+
*/
|
|
49
|
+
dir: string | Array<string | StaticDirOptions>;
|
|
50
|
+
/**
|
|
51
|
+
* static files store dirs
|
|
52
|
+
* @deprecated use `dir` instead
|
|
53
|
+
*/
|
|
54
|
+
dirs?: Array<string | StaticDirOptions>;
|
|
55
|
+
}
|
|
56
|
+
declare module '@eggjs/core' {
|
|
57
|
+
interface EggAppConfig {
|
|
58
|
+
static: StaticConfig;
|
|
59
|
+
}
|
|
60
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eggjs/static",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "static server plugin for egg",
|
|
8
|
+
"eggPlugin": {
|
|
9
|
+
"name": "static",
|
|
10
|
+
"exports": {
|
|
11
|
+
"import": "./dist/esm",
|
|
12
|
+
"require": "./dist/commonjs",
|
|
13
|
+
"typescript": "./src"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/eggjs/static.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"egg",
|
|
22
|
+
"egg-plugin",
|
|
23
|
+
"eggPlugin",
|
|
24
|
+
"static"
|
|
25
|
+
],
|
|
26
|
+
"author": "dead_horse",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">= 18.19.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@eggjs/core": "^6.2.13",
|
|
33
|
+
"@eggjs/koa-static-cache": "^6.0.0",
|
|
34
|
+
"is-type-of": "^2.2.0",
|
|
35
|
+
"koa-compose": "^4.1.0",
|
|
36
|
+
"koa-range": "^0.3.0",
|
|
37
|
+
"ylru": "^2.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@arethetypeswrong/cli": "^0.17.1",
|
|
41
|
+
"@eggjs/bin": "7",
|
|
42
|
+
"@eggjs/mock": "^6.0.5",
|
|
43
|
+
"@eggjs/tsconfig": "1",
|
|
44
|
+
"@types/koa-compose": "^3.2.8",
|
|
45
|
+
"@types/koa-range": "^0.3.5",
|
|
46
|
+
"@types/mocha": "10",
|
|
47
|
+
"@types/node": "22",
|
|
48
|
+
"egg": "4",
|
|
49
|
+
"eslint": "8",
|
|
50
|
+
"eslint-config-egg": "14",
|
|
51
|
+
"rimraf": "6",
|
|
52
|
+
"tshy": "3",
|
|
53
|
+
"tshy-after": "1",
|
|
54
|
+
"typescript": "5"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"lint": "eslint --cache src test --ext .ts",
|
|
58
|
+
"pretest": "npm run clean && npm run lint -- --fix",
|
|
59
|
+
"test": "egg-bin test",
|
|
60
|
+
"preci": "npm run clean && npm run lint",
|
|
61
|
+
"ci": "egg-bin cov",
|
|
62
|
+
"postci": "npm run prepublishOnly && npm run clean",
|
|
63
|
+
"clean": "rimraf dist",
|
|
64
|
+
"prepublishOnly": "tshy && tshy-after && attw --pack"
|
|
65
|
+
},
|
|
66
|
+
"type": "module",
|
|
67
|
+
"tshy": {
|
|
68
|
+
"exports": {
|
|
69
|
+
".": "./src/index.ts",
|
|
70
|
+
"./package.json": "./package.json"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"exports": {
|
|
74
|
+
".": {
|
|
75
|
+
"import": {
|
|
76
|
+
"types": "./dist/esm/index.d.ts",
|
|
77
|
+
"default": "./dist/esm/index.js"
|
|
78
|
+
},
|
|
79
|
+
"require": {
|
|
80
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
81
|
+
"default": "./dist/commonjs/index.js"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"./package.json": "./package.json"
|
|
85
|
+
},
|
|
86
|
+
"files": [
|
|
87
|
+
"dist",
|
|
88
|
+
"src"
|
|
89
|
+
],
|
|
90
|
+
"types": "./dist/commonjs/index.d.ts",
|
|
91
|
+
"main": "./dist/commonjs/index.js",
|
|
92
|
+
"module": "./dist/esm/index.js"
|
|
93
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { mkdirSync, existsSync } from 'node:fs';
|
|
3
|
+
import range from 'koa-range';
|
|
4
|
+
import compose from 'koa-compose';
|
|
5
|
+
import type { EggCore, Context, Next } from '@eggjs/core';
|
|
6
|
+
import { staticCache } from '@eggjs/koa-static-cache';
|
|
7
|
+
import { LRU } from 'ylru';
|
|
8
|
+
import { isObject } from 'is-type-of';
|
|
9
|
+
import type { StaticConfig, StaticDirOptions } from '../../types.js';
|
|
10
|
+
|
|
11
|
+
export default (options: StaticConfig, app: EggCore) => {
|
|
12
|
+
const dirs = (options.dirs ?? []).concat(options.dir);
|
|
13
|
+
|
|
14
|
+
const prefixes: string[] = [];
|
|
15
|
+
|
|
16
|
+
function rangeMiddleware(ctx: Context, next: Next) {
|
|
17
|
+
// if match static file, and use range middleware.
|
|
18
|
+
const isMatch = prefixes.some(p => ctx.path.startsWith(p));
|
|
19
|
+
if (isMatch) {
|
|
20
|
+
return range(ctx as any, next);
|
|
21
|
+
}
|
|
22
|
+
return next();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const middlewares = [ rangeMiddleware ];
|
|
26
|
+
|
|
27
|
+
for (const dirObj of dirs) {
|
|
28
|
+
assert(isObject(dirObj) || typeof dirObj === 'string',
|
|
29
|
+
'`config.static.dir` must be `string | Array<string|object>`');
|
|
30
|
+
|
|
31
|
+
let newOptions: StaticDirOptions;
|
|
32
|
+
if (typeof dirObj === 'string') {
|
|
33
|
+
// copy origin options to new options ensure the safety of objects
|
|
34
|
+
newOptions = {
|
|
35
|
+
...options,
|
|
36
|
+
dir: dirObj,
|
|
37
|
+
};
|
|
38
|
+
} else {
|
|
39
|
+
assert(typeof dirObj.dir === 'string',
|
|
40
|
+
'`config.static.dirs` should contains `[].dir` property when object style');
|
|
41
|
+
newOptions = {
|
|
42
|
+
...options,
|
|
43
|
+
...dirObj,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (newOptions.dynamic && !newOptions.files) {
|
|
48
|
+
newOptions.files = new LRU(newOptions.maxFiles);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (newOptions.prefix) {
|
|
52
|
+
prefixes.push(newOptions.prefix);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ensure directory exists
|
|
56
|
+
if (!existsSync(newOptions.dir)) {
|
|
57
|
+
mkdirSync(newOptions.dir, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
middlewares.push(staticCache(newOptions));
|
|
60
|
+
|
|
61
|
+
(app as any).coreLogger.info('[@eggjs/static] starting static serve %s -> %s',
|
|
62
|
+
newOptions.prefix, newOptions.dir);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return compose(middlewares);
|
|
66
|
+
};
|
package/src/app.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ILifecycleBoot, EggCore } from '@eggjs/core';
|
|
2
|
+
|
|
3
|
+
export default class AppBoot implements ILifecycleBoot {
|
|
4
|
+
private readonly app;
|
|
5
|
+
constructor(app: EggCore) {
|
|
6
|
+
this.app = app;
|
|
7
|
+
}
|
|
8
|
+
async configWillLoad() {
|
|
9
|
+
const app = this.app;
|
|
10
|
+
// make sure static middleware is before bodyParser
|
|
11
|
+
const index = app.config.coreMiddleware.indexOf('bodyParser');
|
|
12
|
+
if (index === -1) {
|
|
13
|
+
app.config.coreMiddleware.push('static');
|
|
14
|
+
} else {
|
|
15
|
+
app.config.coreMiddleware.splice(index, 0, 'static');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import type { EggAppInfo } from '@eggjs/core';
|
|
3
|
+
import type { StaticConfig } from '../types.js';
|
|
4
|
+
|
|
5
|
+
export default (appInfo: EggAppInfo) => {
|
|
6
|
+
return {
|
|
7
|
+
static: {
|
|
8
|
+
prefix: '/public/',
|
|
9
|
+
dir: path.join(appInfo.baseDir, 'app/public'),
|
|
10
|
+
// dirs: [ dir1, dir2 ] or [ dir1, { prefix: '/static2', dir: dir2 } ],
|
|
11
|
+
dirs: undefined,
|
|
12
|
+
// support lazy load
|
|
13
|
+
dynamic: true,
|
|
14
|
+
preload: false,
|
|
15
|
+
buffer: false,
|
|
16
|
+
maxFiles: 1000,
|
|
17
|
+
} as StaticConfig,
|
|
18
|
+
};
|
|
19
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './types.js';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Options as StaticCacheOptions } from '@eggjs/koa-static-cache';
|
|
2
|
+
|
|
3
|
+
export interface StaticDirOptions extends Omit<StaticCacheOptions, 'dir'> {
|
|
4
|
+
/**
|
|
5
|
+
* static files store dir
|
|
6
|
+
*/
|
|
7
|
+
dir: string;
|
|
8
|
+
/**
|
|
9
|
+
* static files prefix
|
|
10
|
+
* Default to `'/public/'`
|
|
11
|
+
*/
|
|
12
|
+
prefix: string;
|
|
13
|
+
/**
|
|
14
|
+
* cache max age in `seconds`
|
|
15
|
+
* Default to `0` on development, `31536000` on production
|
|
16
|
+
*/
|
|
17
|
+
maxAge: number;
|
|
18
|
+
/**
|
|
19
|
+
* dynamic load file which not cached on initialization
|
|
20
|
+
* Default to `true
|
|
21
|
+
*/
|
|
22
|
+
dynamic: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* caches the assets on initialization or not,
|
|
25
|
+
* always work together with `options.dynamic`
|
|
26
|
+
* Default to `false`
|
|
27
|
+
*/
|
|
28
|
+
preload: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* buffer the file content or not
|
|
31
|
+
* Default to `false` on development, `true` on production
|
|
32
|
+
*/
|
|
33
|
+
buffer: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* max files count in store
|
|
36
|
+
* Default to `1000`
|
|
37
|
+
*/
|
|
38
|
+
maxFiles: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Static file serve
|
|
43
|
+
* @member Config#static
|
|
44
|
+
* @see https://github.com/koajs/static-cache
|
|
45
|
+
*/
|
|
46
|
+
export interface StaticConfig extends Omit<StaticDirOptions, 'dir'> {
|
|
47
|
+
/**
|
|
48
|
+
* static files store dir
|
|
49
|
+
* Default to `${baseDir}/app/public`
|
|
50
|
+
*/
|
|
51
|
+
dir: string | Array<string | StaticDirOptions>;
|
|
52
|
+
/**
|
|
53
|
+
* static files store dirs
|
|
54
|
+
* @deprecated use `dir` instead
|
|
55
|
+
*/
|
|
56
|
+
dirs?: Array<string | StaticDirOptions>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
declare module '@eggjs/core' {
|
|
60
|
+
// add EggAppConfig overrides types
|
|
61
|
+
interface EggAppConfig {
|
|
62
|
+
static: StaticConfig;
|
|
63
|
+
}
|
|
64
|
+
}
|