@mangjuxiong/elpis 1.0.2
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/.babelrc +5 -0
- package/.eslintignore +3 -0
- package/.eslintrc +66 -0
- package/README.md +214 -0
- package/app/controller/base.js +39 -0
- package/app/controller/project.js +75 -0
- package/app/controller/view.js +19 -0
- package/app/extend/database.js +5 -0
- package/app/extend/logger.js +38 -0
- package/app/middleware/api-params-verify.js +74 -0
- package/app/middleware/api-sign-verify.js +36 -0
- package/app/middleware/error-handle.js +32 -0
- package/app/middleware/project-handler.js +26 -0
- package/app/middleware.js +39 -0
- package/app/pages/asserts/custom.css +14 -0
- package/app/pages/boot.js +48 -0
- package/app/pages/common/curl.js +80 -0
- package/app/pages/common/utils.js +34 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +24 -0
- package/app/pages/dashboard/complex-view/header-view/head-view.vue +113 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +118 -0
- package/app/pages/dashboard/complex-view/schema-view/components/components-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +85 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +103 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +112 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +90 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +22 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +113 -0
- package/app/pages/dashboard/dashboard.vue +85 -0
- package/app/pages/dashboard/entry.dashboard.js +46 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +54 -0
- package/app/pages/store/project.js +13 -0
- package/app/pages/widgets/head-container/asserts/logo.png +0 -0
- package/app/pages/widgets/head-container/head-container.vue +77 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +135 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +120 -0
- package/app/pages/widgets/schema-form/form-item-config.js +23 -0
- package/app/pages/widgets/schema-form/schema-form.vue +130 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +51 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +55 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +38 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +40 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +100 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +31 -0
- package/app/pages/widgets/schema-table/schema-table.vue +225 -0
- package/app/pages/widgets/sider-container/sider-container.vue +27 -0
- package/app/public/output/entry.page1.tpl +42 -0
- package/app/public/static/logo.jpg +0 -0
- package/app/public/static/normalize.css +267 -0
- package/app/router/project.js +6 -0
- package/app/router/view.js +7 -0
- package/app/router-schema/project.js +30 -0
- package/app/service/base.js +13 -0
- package/app/service/project.js +42 -0
- package/app/view/entry.tpl +25 -0
- package/app/webpack/config/babel.config.js +4 -0
- package/app/webpack/config/webpack.base.js +229 -0
- package/app/webpack/config/webpack.dev.js +57 -0
- package/app/webpack/config/webpack.prod.js +120 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/libs/dev.js +53 -0
- package/app/webpack/libs/prod.js +22 -0
- package/config/config.default.js +4 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +81 -0
- package/elpis-core/loader/config.js +52 -0
- package/elpis-core/loader/controller.js +59 -0
- package/elpis-core/loader/extend.js +47 -0
- package/elpis-core/loader/middleware.js +57 -0
- package/elpis-core/loader/router-schema.js +41 -0
- package/elpis-core/loader/router.js +42 -0
- package/elpis-core/loader/service.js +59 -0
- package/index.js +39 -0
- package/model/index.js +107 -0
- package/package.json +90 -0
- package/test/controller/project.test.js +194 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const mrege = require('webpack-merge');
|
|
3
|
+
const HappyPackPlugin = require('happypack');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
6
|
+
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
|
7
|
+
const TerserPlugin = require('terser-webpack-plugin');
|
|
8
|
+
const CSSMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
9
|
+
const HtmlWebpackInjectAttributesPlugin = require('html-webpack-inject-attributes-plugin');
|
|
10
|
+
|
|
11
|
+
// 多线程 build 设置
|
|
12
|
+
const happypackCommonConfig = {
|
|
13
|
+
threadPool: HappyPackPlugin.ThreadPool({
|
|
14
|
+
size: os.cpus().length,
|
|
15
|
+
}),
|
|
16
|
+
debug: false,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// 基类配置
|
|
20
|
+
const baseConfig = require('./webpack.base.js');
|
|
21
|
+
|
|
22
|
+
// 生产环境 webpack 配置
|
|
23
|
+
const webpackConfig = mrege(baseConfig, {
|
|
24
|
+
// 指定生产环境
|
|
25
|
+
mode: 'production',
|
|
26
|
+
// 生产环境的 output 配置
|
|
27
|
+
output: {
|
|
28
|
+
filename: 'js/[name]_[chunkhash:8].bundle.js',
|
|
29
|
+
path: path.join(process.cwd(), './app/public/dist/prod/'),
|
|
30
|
+
publicPath: '/dist/prod/',
|
|
31
|
+
crossOriginLoading: 'anonymous',
|
|
32
|
+
},
|
|
33
|
+
module: {
|
|
34
|
+
rules: [
|
|
35
|
+
{
|
|
36
|
+
test: /\.css$/,
|
|
37
|
+
use: [MiniCssExtractPlugin.loader, `${require.resolve('happypack/loader')}?id=css`],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
test: /\.less$/,
|
|
41
|
+
use: [MiniCssExtractPlugin.loader, `${require.resolve('happypack/loader')}?id=css`],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
test: /\.js$/,
|
|
45
|
+
// 只对app/pages目录下的js文件进行babel-loader处理,加快打包速度
|
|
46
|
+
include: [
|
|
47
|
+
// elpis目录
|
|
48
|
+
path.resolve(__dirname, '../../pages'),
|
|
49
|
+
// 业务目录
|
|
50
|
+
path.resolve(process.cwd(), './app/pages'),
|
|
51
|
+
],
|
|
52
|
+
use: [`${require.resolve('happypack/loader')}?id=js`],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
// webpack 不会有大量hits信息,默然为warning
|
|
57
|
+
performance: {
|
|
58
|
+
hints: false,
|
|
59
|
+
},
|
|
60
|
+
plugins: [
|
|
61
|
+
// 每次build前清空 public/dist 目录
|
|
62
|
+
new CleanWebpackPlugin(['public/dist'], {
|
|
63
|
+
root: path.join(process.cwd(), './app/'),
|
|
64
|
+
exclude: [],
|
|
65
|
+
verbose: true,
|
|
66
|
+
dry: false,
|
|
67
|
+
}),
|
|
68
|
+
// 提取css公共部分,有效利用缓存
|
|
69
|
+
new MiniCssExtractPlugin({
|
|
70
|
+
filename: 'css/[name]_[contenthash:8].css',
|
|
71
|
+
chunkFilename: 'css/[name]_[contenthash:8].chunk.css',
|
|
72
|
+
}),
|
|
73
|
+
// 优化并压缩css资源
|
|
74
|
+
new CSSMinimizerPlugin({
|
|
75
|
+
minimizerOptions: {
|
|
76
|
+
preset: ['default', { discardComments: { removeAll: true } }],
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
// 多进程打包js,加快打包速度
|
|
80
|
+
new HappyPackPlugin({
|
|
81
|
+
...happypackCommonConfig,
|
|
82
|
+
id: 'js',
|
|
83
|
+
loaders: [`${require.resolve('babel-loader')}?${JSON.stringify(require('./babel.config.js'))}`],
|
|
84
|
+
}),
|
|
85
|
+
// 多进程打包css,加快打包速度
|
|
86
|
+
new HappyPackPlugin({
|
|
87
|
+
...happypackCommonConfig,
|
|
88
|
+
id: 'css',
|
|
89
|
+
loaders: [
|
|
90
|
+
{
|
|
91
|
+
path: require.resolve('css-loader'),
|
|
92
|
+
options: {
|
|
93
|
+
importLoaders: 1,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
}),
|
|
98
|
+
// 浏览器在请求资源时不发送用户的身份凭证
|
|
99
|
+
new HtmlWebpackInjectAttributesPlugin({
|
|
100
|
+
crossorigin: 'anonymous',
|
|
101
|
+
}),
|
|
102
|
+
],
|
|
103
|
+
optimization: {
|
|
104
|
+
// 使用 TersePlugin 的并发和缓存,提升压缩阶段的性能
|
|
105
|
+
// 清除 console.log
|
|
106
|
+
minimize: true,
|
|
107
|
+
minimizer: [
|
|
108
|
+
new TerserPlugin({
|
|
109
|
+
parallel: true, // 利用多核CPU的优势来加快压缩速度
|
|
110
|
+
terserOptions: {
|
|
111
|
+
compress: {
|
|
112
|
+
drop_console: true, //去掉console.log
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
module.exports = webpackConfig;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// 本地开发启动 devServer 命令
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const devMiddleware = require('webpack-dev-middleware');
|
|
6
|
+
const hotMiddleware = require('webpack-hot-middleware');
|
|
7
|
+
const consoler = require('consoler');
|
|
8
|
+
|
|
9
|
+
module.exports = () => {
|
|
10
|
+
// 从 webpack.dev.config.js 中获取配置信息
|
|
11
|
+
const { webpackConfig, DEV_SERVER_CONFIG } = require('../config/webpack.dev.js');
|
|
12
|
+
|
|
13
|
+
const app = express();
|
|
14
|
+
|
|
15
|
+
const compiler = webpack(webpackConfig);
|
|
16
|
+
|
|
17
|
+
// 指定静态文件目录
|
|
18
|
+
app.use(express.static(path.join(process.cwd(), './app/public/dist')));
|
|
19
|
+
// 引入 webpack-dev-middleware 监控文件改动
|
|
20
|
+
app.use(
|
|
21
|
+
devMiddleware(compiler, {
|
|
22
|
+
// 落地文件
|
|
23
|
+
writeToDisk: (filePath) => filePath.endsWith('.tpl'),
|
|
24
|
+
// 资源路径
|
|
25
|
+
publicPath: webpackConfig.output.publicPath,
|
|
26
|
+
// headers 配置
|
|
27
|
+
headers: {
|
|
28
|
+
'Access-Control-Allow-Origin': '*',
|
|
29
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
|
30
|
+
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
|
|
31
|
+
'Referrer-Policy': 'no-referrer-when-downgrade',
|
|
32
|
+
},
|
|
33
|
+
stats: {
|
|
34
|
+
colors: true,
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
// 引入 webpack-hot-middleware 实现热通信
|
|
39
|
+
app.use(
|
|
40
|
+
hotMiddleware(compiler, {
|
|
41
|
+
path: `/${DEV_SERVER_CONFIG.hmrPath}`,
|
|
42
|
+
log: () => {},
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
consoler.info('请等待webpack初次构建完成提示。。。');
|
|
47
|
+
|
|
48
|
+
// 启动 devServer
|
|
49
|
+
const port = DEV_SERVER_CONFIG.port;
|
|
50
|
+
app.listen(port, () => {
|
|
51
|
+
consoler.success(`webpack-dev-server is running at http://localhost:${port}`);
|
|
52
|
+
});
|
|
53
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
2
|
+
const webpackProdConfig = require('../config/webpack.prod.js');
|
|
3
|
+
|
|
4
|
+
module.exports = () => {
|
|
5
|
+
console.log('\nbuilding... \n');
|
|
6
|
+
|
|
7
|
+
webpack(webpackProdConfig, (err, stats) => {
|
|
8
|
+
if (err) {
|
|
9
|
+
console.log('🚀 ~ webpack ~ err:', err);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
process.stdout.write(
|
|
13
|
+
stats.toString({
|
|
14
|
+
colors: true, // 在控制台输出色彩信息
|
|
15
|
+
modules: false, // 不显示每个模块的打包信息
|
|
16
|
+
children: false, // 不显示子编译任务的信息
|
|
17
|
+
chunks: false, // 不显示每个代码块的信息
|
|
18
|
+
chunkModules: true, // 显示代码块中模块的信息
|
|
19
|
+
}) + '\n\n'
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = () => {
|
|
2
|
+
return {
|
|
3
|
+
//判断是否本地环境
|
|
4
|
+
isLocal() {
|
|
5
|
+
return process.env._ENV.trim() === 'local';
|
|
6
|
+
},
|
|
7
|
+
//判断是否测试环境
|
|
8
|
+
isBeta() {
|
|
9
|
+
return process.env._ENV.trim() === 'beta';
|
|
10
|
+
},
|
|
11
|
+
//判断是否生产环境
|
|
12
|
+
isProduction() {
|
|
13
|
+
return process.env._ENV.trim() === 'production';
|
|
14
|
+
},
|
|
15
|
+
//获取当前环境
|
|
16
|
+
get() {
|
|
17
|
+
return process.env._ENV.trim() ?? 'local';
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const Koa = require('koa');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { sep } = path; //为了兼容不同操作系统的斜杠
|
|
4
|
+
|
|
5
|
+
const env = require('./env');
|
|
6
|
+
|
|
7
|
+
const middlewareLoader = require('./loader/middleware');
|
|
8
|
+
const routerLoader = require('./loader/router');
|
|
9
|
+
const routerSchemaLoader = require('./loader/router-schema');
|
|
10
|
+
const controllerLoader = require('./loader/controller');
|
|
11
|
+
const serviceLoader = require('./loader/service');
|
|
12
|
+
const configLoader = require('./loader/config');
|
|
13
|
+
const extendLoader = require('./loader/extend');
|
|
14
|
+
|
|
15
|
+
module.exports = {
|
|
16
|
+
/**
|
|
17
|
+
* 启动项目
|
|
18
|
+
* @param {} options 项目配置
|
|
19
|
+
* options = {
|
|
20
|
+
* name,
|
|
21
|
+
* homePage
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
start(options = {}) {
|
|
25
|
+
// koa实例
|
|
26
|
+
const app = new Koa();
|
|
27
|
+
// 应用配置
|
|
28
|
+
app.options = options;
|
|
29
|
+
// 基础路径
|
|
30
|
+
app.baseDir = process.cwd();
|
|
31
|
+
// 业务文件路径
|
|
32
|
+
app.businessDir = path.resolve(app.baseDir, `.${sep}app`);
|
|
33
|
+
// 初始化配置环境
|
|
34
|
+
app.env = env();
|
|
35
|
+
// 加载middleware
|
|
36
|
+
middlewareLoader(app);
|
|
37
|
+
console.log('-- {start} load middleware done --');
|
|
38
|
+
// 加载routerSchema
|
|
39
|
+
routerSchemaLoader(app);
|
|
40
|
+
console.log('-- {start} load routerSchemaLoader done --');
|
|
41
|
+
// 加载controller
|
|
42
|
+
controllerLoader(app);
|
|
43
|
+
console.log('-- {start} load controllerLoader done --');
|
|
44
|
+
// 加载service
|
|
45
|
+
serviceLoader(app);
|
|
46
|
+
console.log('-- {start} load serviceLoader done --');
|
|
47
|
+
// 加载config
|
|
48
|
+
configLoader(app);
|
|
49
|
+
console.log('-- {start} load configLoader done --');
|
|
50
|
+
// 加载extend
|
|
51
|
+
extendLoader(app);
|
|
52
|
+
console.log('-- {start} load extendLoader done --');
|
|
53
|
+
// 注册elpis全局中间件
|
|
54
|
+
const elpisMiddlewarePath = path.resolve(__dirname, `..${sep}app${sep}middleware.js`);
|
|
55
|
+
const elpisMiddleware = require(elpisMiddlewarePath);
|
|
56
|
+
elpisMiddleware(app);
|
|
57
|
+
console.log('-- {start} load global elpis middleware done --');
|
|
58
|
+
|
|
59
|
+
// 注册业务全局中间件
|
|
60
|
+
try {
|
|
61
|
+
require(path.resolve(app.businessDir, `.${sep}middleware`))(app);
|
|
62
|
+
console.log('-- {start} load global business middleware done --');
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.log('[exception] there is global business middleware file exception');
|
|
65
|
+
}
|
|
66
|
+
//注册路由,路由分发需要经过所有中间件处理后再执行
|
|
67
|
+
routerLoader(app);
|
|
68
|
+
console.log('-- {start} load routerLoader done --');
|
|
69
|
+
|
|
70
|
+
// 启动服务
|
|
71
|
+
try {
|
|
72
|
+
const port = process.env.PORT || 8080;
|
|
73
|
+
const host = process.env.IP || '0.0.0.0';
|
|
74
|
+
app.listen(port, host);
|
|
75
|
+
console.log(`Server runnin on port:${port}`);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.log(err);
|
|
78
|
+
}
|
|
79
|
+
return app;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { sep } = path;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* config loader
|
|
6
|
+
* @param {object} app Koa 实例
|
|
7
|
+
*
|
|
8
|
+
* 配置区分 本地/测试/生产,通过env环境读取不同文件配置 env.config
|
|
9
|
+
* 通过 env.config 覆盖 default.config 加载到 app.config
|
|
10
|
+
*
|
|
11
|
+
* 目录下对应的config 配置
|
|
12
|
+
* 默认配置 config/config.default.js
|
|
13
|
+
* 本地配置 config/config.local.js
|
|
14
|
+
* 测试配置 config/config.beta.js
|
|
15
|
+
* 生产配置 config/config.prod.js
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
module.exports = (app) => {
|
|
19
|
+
// elpis config 目录及相关文件
|
|
20
|
+
const elpisConfigPath = path.resolve(__dirname, `..${sep}..${sep}config`);
|
|
21
|
+
let defaultConfig = require(path.resolve(elpisConfigPath, `.${sep}config.default.js`));
|
|
22
|
+
|
|
23
|
+
// 业务 config 目录及文件
|
|
24
|
+
const businessConfigPath = path.resolve(app.baseDir, `.${sep}config`);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
defaultConfig = {
|
|
28
|
+
...defaultConfig,
|
|
29
|
+
...require(path.resolve(businessConfigPath, `.${sep}config.default.js`)),
|
|
30
|
+
};
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.log('[exception] there is default config file exception');
|
|
33
|
+
}
|
|
34
|
+
//获取env.config
|
|
35
|
+
let envConfig = {};
|
|
36
|
+
try {
|
|
37
|
+
if (app.env.isLocal()) {
|
|
38
|
+
//本地环境
|
|
39
|
+
envConfig = require(path.resolve(businessConfigPath, `.${sep}config.local.js`));
|
|
40
|
+
} else if (app.env.isBeta()) {
|
|
41
|
+
//测试环境
|
|
42
|
+
envConfig = require(path.resolve(businessConfigPath, `.${sep}config.beta.js`));
|
|
43
|
+
} else if (app.env.isProduction()) {
|
|
44
|
+
//生产环境
|
|
45
|
+
envConfig = require(path.resolve(businessConfigPath, `.${sep}config.prod.js`));
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.log('[exception] there is env config file exception');
|
|
49
|
+
}
|
|
50
|
+
//覆盖并加载config配置
|
|
51
|
+
app.config = Object.assign({}, defaultConfig, envConfig);
|
|
52
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const { sep } = path;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* controller loader
|
|
7
|
+
* @param {object} app Koa 实例
|
|
8
|
+
*
|
|
9
|
+
* 加载所有controller, 可通过'app.controllers.${目录}.${文件}'访问
|
|
10
|
+
*
|
|
11
|
+
例子:
|
|
12
|
+
app/controller
|
|
13
|
+
|
|
|
14
|
+
| -- custom-module
|
|
15
|
+
|
|
|
16
|
+
| -- custom-controller.js
|
|
17
|
+
=> app.controller.customModule.customController
|
|
18
|
+
*/
|
|
19
|
+
module.exports = (app) => {
|
|
20
|
+
//读取 elpis/app/controller/**/**.js 下所有文件
|
|
21
|
+
const elpisControllerPath = path.resolve(__dirname, `..${sep}..${sep}app${sep}controller`);
|
|
22
|
+
const elpisFileList = glob.sync(path.resolve(elpisControllerPath, `.${sep}**${sep}**.js`));
|
|
23
|
+
|
|
24
|
+
// 读取业务的 app/controller/**/**.js 下所有文件
|
|
25
|
+
const businessControllerPath = path.resolve(app.businessDir, `.${sep}controller`);
|
|
26
|
+
const businessFileList = glob.sync(path.resolve(businessControllerPath, `.${sep}**${sep}**.js`));
|
|
27
|
+
|
|
28
|
+
// 合并所有controller文件
|
|
29
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
30
|
+
|
|
31
|
+
// 把内容加载到 app.controller 下
|
|
32
|
+
const controllers = {};
|
|
33
|
+
fileList.forEach((file) => {
|
|
34
|
+
//提取文件名称
|
|
35
|
+
let name = path.resolve(file);
|
|
36
|
+
//截取路径 app/controller/custom-module/custom-controller.js => custom-module/custom-controller
|
|
37
|
+
name = name.substring(name.lastIndexOf(`controller${sep}`) + `controller${sep}`.length, name.lastIndexOf('.'));
|
|
38
|
+
//把'-'统一改为驼峰式,custom-module/custom-controller => cunstomModule.customController
|
|
39
|
+
name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
|
|
40
|
+
//挂载controller到内存app对象中
|
|
41
|
+
let tempController = controllers;
|
|
42
|
+
const names = name.split(sep);
|
|
43
|
+
for (let i = 0, len = names.length; i < names.length; i++) {
|
|
44
|
+
if (i == len - 1) {
|
|
45
|
+
//文件
|
|
46
|
+
const ControllerModule = require(path.resolve(file))(app);
|
|
47
|
+
//因为controller都是些class,所以需要new一下
|
|
48
|
+
tempController[names[i]] = new ControllerModule();
|
|
49
|
+
} else {
|
|
50
|
+
//文件夹
|
|
51
|
+
if (!tempController[names[i]]) {
|
|
52
|
+
tempController[names[i]] = {};
|
|
53
|
+
}
|
|
54
|
+
tempController = tempController[names[i]];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
app.controllers = controllers;
|
|
59
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const { sep } = path;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* extend loader
|
|
7
|
+
* @param {object} app Koa 实例
|
|
8
|
+
*
|
|
9
|
+
* 加载所有extend, 可通过'app.extends.${文件}'访问
|
|
10
|
+
*
|
|
11
|
+
例子:
|
|
12
|
+
app/extend
|
|
13
|
+
|
|
|
14
|
+
| -- custom-extend.js
|
|
15
|
+
=> app.extend.customModule.customExtend
|
|
16
|
+
*/
|
|
17
|
+
module.exports = (app) => {
|
|
18
|
+
//读取 elpis/app/extend/**.js 下所有文件
|
|
19
|
+
const elpisExtendPath = path.resolve(__dirname, `..${sep}..${sep}app${sep}extend`);
|
|
20
|
+
const elpisFileList = glob.sync(path.resolve(elpisExtendPath, `.${sep}**.js`));
|
|
21
|
+
|
|
22
|
+
// 读取业务 app/extend/**.js 下所有文件
|
|
23
|
+
const businessExtendPath = path.resolve(app.businessDir, `.${sep}extend`);
|
|
24
|
+
const businessFileList = glob.sync(path.resolve(businessExtendPath, `.${sep}**.js`));
|
|
25
|
+
|
|
26
|
+
// 合并extend 文件
|
|
27
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
28
|
+
|
|
29
|
+
// 把内容加载到 app 下
|
|
30
|
+
fileList.forEach((file) => {
|
|
31
|
+
//提取文件名称
|
|
32
|
+
let name = path.resolve(file);
|
|
33
|
+
//截取路径 app/extend/custom-extend.js => custom-extend.js
|
|
34
|
+
name = name.substring(name.lastIndexOf(`extend${sep}`) + `extend${sep}`.length, name.lastIndexOf('.'));
|
|
35
|
+
//把'-'统一改为驼峰式,custom-extend.js => customExtend
|
|
36
|
+
name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
|
|
37
|
+
//过滤app已存在的key
|
|
38
|
+
for (const key in app) {
|
|
39
|
+
if (key === name) {
|
|
40
|
+
console.log(`[extend load error] app.${name} is exist, please change file name or rename app.${name}]`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//挂载extend到app对象中
|
|
45
|
+
app[name] = require(path.resolve(file))(app);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const { sep } = path;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* middleware loader
|
|
7
|
+
* @param {object} app Koa 实例
|
|
8
|
+
*
|
|
9
|
+
* 加载所有middleware, 可通过'app.middlewares.${目录}.${文件}'访问
|
|
10
|
+
*
|
|
11
|
+
例子:
|
|
12
|
+
app/middleware
|
|
13
|
+
|
|
|
14
|
+
| -- custom-module
|
|
15
|
+
|
|
|
16
|
+
| -- custom-middleware.js
|
|
17
|
+
=> app.middlewares.customModule.customMiddleware
|
|
18
|
+
*/
|
|
19
|
+
module.exports = (app) => {
|
|
20
|
+
const middlewares = {};
|
|
21
|
+
|
|
22
|
+
// 读取app/middleware/**/**.js 下所有文件
|
|
23
|
+
const elpisMiddlewarePath = path.resolve(__dirname, `..${sep}..${sep}app${sep}middleware`);
|
|
24
|
+
const elpisFileList = glob.sync(path.resolve(elpisMiddlewarePath, `.${sep}**${sep}**.js`));
|
|
25
|
+
|
|
26
|
+
// 读取业务根目录 app/middleware/**/**.js 下所有文件
|
|
27
|
+
const businessMiddlewarePath = path.resolve(app.businessDir, `.${sep}middleware`);
|
|
28
|
+
const businessFileList = glob.sync(path.resolve(businessMiddlewarePath, `.${sep}**${sep}**.js`));
|
|
29
|
+
|
|
30
|
+
// 合并middleware 所有文件
|
|
31
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
32
|
+
|
|
33
|
+
//遍历所有文件目录,把内容加载到 app.middlewares 下
|
|
34
|
+
fileList.forEach((file) => {
|
|
35
|
+
//提取文件名称
|
|
36
|
+
let name = path.resolve(file);
|
|
37
|
+
//截取路径 app/middleware/custom-module/custom-middleware.js => custom-module/custom-middleware
|
|
38
|
+
name = name.substring(name.lastIndexOf(`middleware${sep}`) + `middleware${sep}`.length, name.lastIndexOf('.'));
|
|
39
|
+
//吧'-'统一改为驼峰式,custom-module/custom-middleware => cunstomModule.customMiddleware
|
|
40
|
+
name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
|
|
41
|
+
//挂载middleware到内存app对象中
|
|
42
|
+
let tempMiddleware = middlewares;
|
|
43
|
+
const names = name.split(sep);
|
|
44
|
+
for (let i = 0, len = names.length; i < names.length; i++) {
|
|
45
|
+
if (i == len - 1) {
|
|
46
|
+
tempMiddleware[names[i]] = require(path.resolve(file))(app);
|
|
47
|
+
} else {
|
|
48
|
+
if (!tempMiddleware[names[i]]) {
|
|
49
|
+
tempMiddleware[names[i]] = {};
|
|
50
|
+
}
|
|
51
|
+
tempMiddleware = tempMiddleware[names[i]];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
app.middlewares = middlewares;
|
|
57
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const { sep } = path;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* router-schema loader
|
|
7
|
+
* @param {object} app koa实例
|
|
8
|
+
*
|
|
9
|
+
* 通过'json-schema & ajv' 对api 规则进行约束,配合 api-params-verify 中间件使用
|
|
10
|
+
*
|
|
11
|
+
* app/router-schema/xxx.js
|
|
12
|
+
|
|
13
|
+
输出:
|
|
14
|
+
app.routerSchema = {
|
|
15
|
+
'${api1}': ${jsonSchema},
|
|
16
|
+
'${api2}': ${jsonSchema},
|
|
17
|
+
}
|
|
18
|
+
*/
|
|
19
|
+
module.exports = (app) => {
|
|
20
|
+
// 读取elpis/app/router-schema/**/**.js 下所有文件
|
|
21
|
+
const elpisRouterSchemaPath = path.resolve(__dirname, `..${sep}..${sep}app${sep}router-schema`);
|
|
22
|
+
const elpisFileList = glob.sync(path.resolve(elpisRouterSchemaPath, `.${sep}**${sep}**.js`));
|
|
23
|
+
|
|
24
|
+
// 读取 业务的app/router-schema/**/**.js 下所有文件
|
|
25
|
+
const businessRouterSchemaPath = path.resolve(app.businessDir, `.${sep}router-schema`);
|
|
26
|
+
const businessFileList = glob.sync(path.resolve(businessRouterSchemaPath, `.${sep}**${sep}**.js`));
|
|
27
|
+
|
|
28
|
+
// 合并所有的 router-schema 文件
|
|
29
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
30
|
+
|
|
31
|
+
//注册所有 routerSchema, 使得'app.routerSchema' 访问
|
|
32
|
+
let routerSchema = {};
|
|
33
|
+
fileList.forEach((file) => {
|
|
34
|
+
routerSchema = {
|
|
35
|
+
...routerSchema,
|
|
36
|
+
...require(path.resolve(file)),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
app.routerSchema = routerSchema;
|
|
41
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const KoaRouter = require('koa-router');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const glob = require('glob');
|
|
4
|
+
const { sep } = path;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* router loader
|
|
8
|
+
* @param {object} app koa实例
|
|
9
|
+
*
|
|
10
|
+
* 解析所有 app/router 下所有js文件,加载到KoaRouter下
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
module.exports = (app) => {
|
|
14
|
+
// 实例化 KoaRouter
|
|
15
|
+
const router = new KoaRouter();
|
|
16
|
+
|
|
17
|
+
// 找到elpis路由文件路径
|
|
18
|
+
const elpisRouterPath = path.resolve(__dirname, `..${sep}..${sep}app${sep}router`);
|
|
19
|
+
// 注册所有路由
|
|
20
|
+
const elpisFileList = glob.sync(path.resolve(elpisRouterPath, `.${sep}**${sep}**.js`));
|
|
21
|
+
|
|
22
|
+
// 找到业务路由文件路径
|
|
23
|
+
const businessRouterPath = path.resolve(app.businessDir, `.${sep}router`);
|
|
24
|
+
// 注册所有业务路由
|
|
25
|
+
const businessFileList = glob.sync(path.resolve(businessRouterPath, `.${sep}**${sep}**.js`));
|
|
26
|
+
|
|
27
|
+
// 合并所有路由文件
|
|
28
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
29
|
+
|
|
30
|
+
fileList.forEach((file) => {
|
|
31
|
+
require(path.resolve(file))(app, router);
|
|
32
|
+
});
|
|
33
|
+
//路由兜底
|
|
34
|
+
router.get('*', async (ctx, next) => {
|
|
35
|
+
//临时重定向
|
|
36
|
+
ctx.status = 302;
|
|
37
|
+
ctx.redirect(app?.options?.homePage ?? '/');
|
|
38
|
+
});
|
|
39
|
+
//路由注册到app上
|
|
40
|
+
app.use(router.routes());
|
|
41
|
+
app.use(router.allowedMethods());
|
|
42
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const { sep } = path;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* service loader
|
|
7
|
+
* @param {object} app Koa 实例
|
|
8
|
+
*
|
|
9
|
+
* 加载所有service, 可通过'app.services.${目录}.${文件}'访问
|
|
10
|
+
*
|
|
11
|
+
例子:
|
|
12
|
+
app/service
|
|
13
|
+
|
|
|
14
|
+
| -- custom-module
|
|
15
|
+
|
|
|
16
|
+
| -- custom-service.js
|
|
17
|
+
=> app.service.customModule.customService
|
|
18
|
+
*/
|
|
19
|
+
module.exports = (app) => {
|
|
20
|
+
//读取 elpis/app/service/**/**.js 下所有文件
|
|
21
|
+
const elpisServicePath = path.resolve(__dirname, `..${sep}..${sep}app${sep}service`);
|
|
22
|
+
const elpisFileList = glob.sync(path.resolve(elpisServicePath, `.${sep}**${sep}**.js`));
|
|
23
|
+
|
|
24
|
+
//读取业务的app/service/**/**.js 下所有文件
|
|
25
|
+
const businessServicePath = path.resolve(app.businessDir, `.${sep}service`);
|
|
26
|
+
const businessFileList = glob.sync(path.resolve(businessServicePath, `.${sep}**${sep}**.js`));
|
|
27
|
+
|
|
28
|
+
// 合并所有service 文件
|
|
29
|
+
const fileList = elpisFileList.concat(businessFileList);
|
|
30
|
+
|
|
31
|
+
// 把内容加载到 app.service 下
|
|
32
|
+
const services = {};
|
|
33
|
+
fileList.forEach((file) => {
|
|
34
|
+
//提取文件名称
|
|
35
|
+
let name = path.resolve(file);
|
|
36
|
+
//截取路径 app/service/custom-module/custom-service.js => custom-module/custom-service
|
|
37
|
+
name = name.substring(name.lastIndexOf(`service${sep}`) + `service${sep}`.length, name.lastIndexOf('.'));
|
|
38
|
+
//把'-'统一改为驼峰式,custom-module/custom-service => cunstomModule.customService
|
|
39
|
+
name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
|
|
40
|
+
//挂载service到内存app对象中
|
|
41
|
+
let tempService = services;
|
|
42
|
+
const names = name.split(sep);
|
|
43
|
+
for (let i = 0, len = names.length; i < names.length; i++) {
|
|
44
|
+
if (i == len - 1) {
|
|
45
|
+
//文件
|
|
46
|
+
const ServiceModule = require(path.resolve(file))(app);
|
|
47
|
+
//因为service都是些class,所以需要new一下
|
|
48
|
+
tempService[names[i]] = new ServiceModule();
|
|
49
|
+
} else {
|
|
50
|
+
//文件夹
|
|
51
|
+
if (!tempService[names[i]]) {
|
|
52
|
+
tempService[names[i]] = {};
|
|
53
|
+
}
|
|
54
|
+
tempService = tempService[names[i]];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
app.services = services;
|
|
59
|
+
};
|