@lixianwei/elpis 1.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/.eslintignore +2 -0
- package/.eslintrc +55 -0
- package/.idea/dictionaries/project.xml +8 -0
- package/.idea/elpis.iml +8 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/inspectionProfiles/Project_Default.xml +329 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +201 -0
- package/app/controller/base.js +77 -0
- package/app/controller/project.js +69 -0
- package/app/controller/view.js +20 -0
- package/app/extend/logger.js +35 -0
- package/app/middleware/api-params-verify.js +74 -0
- package/app/middleware/api-sign-verify.js +33 -0
- package/app/middleware/error-hander.js +32 -0
- package/app/middleware/project-handler.js +25 -0
- package/app/middleware.js +37 -0
- package/app/pages/asserts/custom.css +11 -0
- package/app/pages/boot.js +43 -0
- package/app/pages/common/curl.js +83 -0
- package/app/pages/common/index.js +2 -0
- package/app/pages/common/utils.js +0 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +23 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +117 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +40 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +45 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/tabel-panel/tabel-panel.vue +134 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +20 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +89 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +101 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +128 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +119 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +96 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +117 -0
- package/app/pages/dashboard/dashboard.vue +88 -0
- package/app/pages/dashboard/entry.dashboard.js +41 -0
- package/app/pages/router/index.js +11 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +65 -0
- package/app/pages/store/project.js +16 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +103 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +142 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +143 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +130 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +132 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +48 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +50 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +142 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +24 -0
- package/app/pages/widgets/schema-table/schema-table.vue +238 -0
- package/app/pages/widgets/sider-container/sider-container.vue +31 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +9 -0
- package/app/router/view.js +7 -0
- package/app/router-schema/project.js +32 -0
- package/app/service/base.js +12 -0
- package/app/service/project.js +42 -0
- package/app/view/entry.tpl +26 -0
- package/app/webpack/config/webpack.base.js +219 -0
- package/app/webpack/config/webpack.dev.js +55 -0
- package/app/webpack/config/webpack.prod.js +118 -0
- package/app/webpack/dev.js +52 -0
- package/app/webpack/libs/blank.js +2 -0
- package/app/webpack/prod.js +18 -0
- package/config/config.default.js +3 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +92 -0
- package/elpis-core/loader/config.js +54 -0
- package/elpis-core/loader/controller.js +61 -0
- package/elpis-core/loader/extend.js +55 -0
- package/elpis-core/loader/middleware.js +61 -0
- package/elpis-core/loader/router-schema.js +39 -0
- package/elpis-core/loader/router.js +42 -0
- package/elpis-core/loader/service.js +64 -0
- package/index.js +41 -0
- package/model/index.js +105 -0
- package/package.json +94 -0
- package/test/controller/project.test.js +194 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const merge = require('webpack-merge');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const HappyPack = require('happypack');
|
|
5
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
6
|
+
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
|
7
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
8
|
+
const HtmlWebpackInjectAttributesPlugin = require('html-webpack-inject-attributes-plugin')
|
|
9
|
+
const TerserWebpackPlugin = require('terser-webpack-plugin');
|
|
10
|
+
|
|
11
|
+
// 多线程build的设置
|
|
12
|
+
const happyPackCommonConfig ={
|
|
13
|
+
debug: false,
|
|
14
|
+
threadPool:HappyPack.ThreadPool({size:os.cpus().length}),
|
|
15
|
+
}
|
|
16
|
+
// 基础类
|
|
17
|
+
const baseConfig = require('./webpack.base.js');
|
|
18
|
+
|
|
19
|
+
// 生产环境webpack配置
|
|
20
|
+
const webpackConfig = merge.smart(baseConfig, {
|
|
21
|
+
// 指定生产环境
|
|
22
|
+
mode: 'production',
|
|
23
|
+
cache:{
|
|
24
|
+
type: 'filesystem',
|
|
25
|
+
}, //跳过重复解析/编译
|
|
26
|
+
// 生产环境的output配置
|
|
27
|
+
// 产物输出路径,因为开发和生产环境输出不一致,所以在各自环境中自行配置
|
|
28
|
+
output:{
|
|
29
|
+
filename: 'js/[name]_[chunkhash:8].bundle.js',
|
|
30
|
+
path:path.join(process.cwd(),'./app/public/dist/prod/'),
|
|
31
|
+
publicPath:'/dist/prod/',
|
|
32
|
+
crossOriginLoading: 'anonymous'
|
|
33
|
+
},
|
|
34
|
+
module:{
|
|
35
|
+
rules:[
|
|
36
|
+
{
|
|
37
|
+
test:/\.css$/,
|
|
38
|
+
use:[
|
|
39
|
+
MiniCssExtractPlugin.loader,
|
|
40
|
+
`${require.resolve('happypack/loader')}?id=css`
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
test:/\.js$/,
|
|
45
|
+
include:[
|
|
46
|
+
// 处理elpis 目录
|
|
47
|
+
path.resolve(__dirname, '../../pages'),
|
|
48
|
+
// 处理业务目录
|
|
49
|
+
path.resolve(process.cwd(), './app/pages'),
|
|
50
|
+
],
|
|
51
|
+
use:[`${require.resolve('happypack/loader')}?id=js`]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
// webpack 不会有大量 hints 信息,默认为waring
|
|
56
|
+
performance: {
|
|
57
|
+
hints: false,
|
|
58
|
+
},
|
|
59
|
+
plugins: [
|
|
60
|
+
// 每次build前,都要先清空public/dist 目录
|
|
61
|
+
new CleanWebpackPlugin(['public/dist'],{
|
|
62
|
+
root:path.resolve(process.cwd(),'./app/'),
|
|
63
|
+
exclude:[],
|
|
64
|
+
verbose:true,
|
|
65
|
+
dry:false
|
|
66
|
+
}),
|
|
67
|
+
//提起css公共部分,有效利用缓存
|
|
68
|
+
new MiniCssExtractPlugin({
|
|
69
|
+
chunkFilename: 'css/[name]_[chunkhash:8].bundle.css',
|
|
70
|
+
}),
|
|
71
|
+
// 优化并压缩css资源
|
|
72
|
+
new CssMinimizerPlugin(),
|
|
73
|
+
// 多线程打包js,加快打包速度
|
|
74
|
+
new HappyPack({
|
|
75
|
+
...happyPackCommonConfig,
|
|
76
|
+
id:'js',
|
|
77
|
+
loaders:[`${require.resolve('babel-loader')}?${JSON.stringify({
|
|
78
|
+
presets: [require.resolve('@babel/preset-env')],
|
|
79
|
+
plugins: [
|
|
80
|
+
require.resolve('@babel/plugin-transform-runtime'),
|
|
81
|
+
],
|
|
82
|
+
cacheDirectory: true, //加快第二次编译的速度
|
|
83
|
+
})}`]
|
|
84
|
+
}),
|
|
85
|
+
// 多线程打包css,加快打包速度
|
|
86
|
+
new HappyPack({
|
|
87
|
+
...happyPackCommonConfig,
|
|
88
|
+
id:'css',
|
|
89
|
+
loaders:[{
|
|
90
|
+
path:require.resolve('css-loader'),
|
|
91
|
+
options:{
|
|
92
|
+
importLoaders: 1,
|
|
93
|
+
}
|
|
94
|
+
}]
|
|
95
|
+
}),
|
|
96
|
+
// 浏览器在请求资源时不发送用户的身份凭证
|
|
97
|
+
new HtmlWebpackInjectAttributesPlugin({
|
|
98
|
+
crossorigin: 'anonymous',
|
|
99
|
+
})
|
|
100
|
+
],
|
|
101
|
+
optimization: {
|
|
102
|
+
// 使用TerserPlugin 的并发和缓存,提升压缩阶段的性能
|
|
103
|
+
// 清楚console.log
|
|
104
|
+
minimize:true,
|
|
105
|
+
minimizer: [
|
|
106
|
+
new TerserWebpackPlugin({
|
|
107
|
+
parallel: true, //利用多核cpu 的优势来加快压缩速度
|
|
108
|
+
terserOptions: {
|
|
109
|
+
compress: {
|
|
110
|
+
drop_console: true,//去掉console.log 打印
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
})
|
|
118
|
+
module.exports = webpackConfig;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// 本地开发启动
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const consoler = require('consoler');
|
|
6
|
+
const devMiddleware = require('webpack-dev-middleware');
|
|
7
|
+
const hotMiddleware = require('webpack-hot-middleware');
|
|
8
|
+
|
|
9
|
+
module.exports = () => {
|
|
10
|
+
// 从webpack.dev.js获取webpack配置和devServer配置
|
|
11
|
+
const {webpackConfig,DEV_SERVER_CONFIG} = require('./config/webpack.dev.js');
|
|
12
|
+
|
|
13
|
+
console.log('9999',webpackConfig)
|
|
14
|
+
|
|
15
|
+
const app = express();
|
|
16
|
+
|
|
17
|
+
const compiler = webpack(webpackConfig);
|
|
18
|
+
// 指定静态文件目录
|
|
19
|
+
app.use(express.static(path.join(__dirname, '../public/dist')));
|
|
20
|
+
// 引用devMiddleware 中间件(监控文件改动)
|
|
21
|
+
app.use(devMiddleware(compiler, {
|
|
22
|
+
// 落地文件
|
|
23
|
+
writeToDisk: (filePath)=>filePath.endsWith('.tpl'),
|
|
24
|
+
// 资源路径
|
|
25
|
+
publicPath: webpackConfig.output.publicPath,
|
|
26
|
+
headers: {
|
|
27
|
+
'Access-Control-Allow-Origin': '*',
|
|
28
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS,PATCH',
|
|
29
|
+
'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type, Authorization'
|
|
30
|
+
},
|
|
31
|
+
stats:{
|
|
32
|
+
colors: true
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
// 引用hotMiddleware中间件(实现热更新)
|
|
37
|
+
app.use(hotMiddleware(compiler, {
|
|
38
|
+
path:`/${DEV_SERVER_CONFIG.HMR_PATH}`,
|
|
39
|
+
log:()=>{
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
}))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
consoler.info('请等待webpack初次构建完成提示....')
|
|
46
|
+
|
|
47
|
+
// 启动dev服务
|
|
48
|
+
const port = DEV_SERVER_CONFIG.PORT
|
|
49
|
+
app.listen(port, () => {
|
|
50
|
+
console.log('app listening on port ' + port);
|
|
51
|
+
})
|
|
52
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const webpack = require('webpack')
|
|
2
|
+
const webpackProdConfig = require('./config/webpack.prod.js')
|
|
3
|
+
module.exports = () => {
|
|
4
|
+
console.log('building...')
|
|
5
|
+
webpack(webpackProdConfig,(err, stats) => {
|
|
6
|
+
if (err) {
|
|
7
|
+
console.log(err)
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
process.stdout.write(`${stats.toString({
|
|
11
|
+
colors: true,//在控制台输出色彩信息
|
|
12
|
+
modules: false,//不显示每个模块的打包信息
|
|
13
|
+
children: false,//不显示子编译任务的信息
|
|
14
|
+
chunks: false,//不显示每个代码块的信息
|
|
15
|
+
chunkModules: true,//显示每个代码块中模块信息
|
|
16
|
+
})}\n`);
|
|
17
|
+
})
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = (app) =>{
|
|
2
|
+
return{
|
|
3
|
+
// 判断是否是本地环境
|
|
4
|
+
isLocal() {
|
|
5
|
+
return process.env._ENV === 'local';
|
|
6
|
+
},
|
|
7
|
+
// 判断是否是测试环境
|
|
8
|
+
isBeta() {
|
|
9
|
+
return process.env._ENV === 'beta';
|
|
10
|
+
},
|
|
11
|
+
// 判断是否是生产环境
|
|
12
|
+
isProduction() {
|
|
13
|
+
return process.env._ENV === 'production';
|
|
14
|
+
},
|
|
15
|
+
// 获取当前环境
|
|
16
|
+
get() {
|
|
17
|
+
return process.env._ENV ?? 'local';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const koa = require('koa');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {sep} = path
|
|
4
|
+
const env = require('./env')
|
|
5
|
+
const middlewareLoader = require('./loader/middleware')
|
|
6
|
+
const routerLoader = require('./loader/router')
|
|
7
|
+
const routerSchemaLoader = require('./loader/router-schema')
|
|
8
|
+
const serviceLoader = require('./loader/service')
|
|
9
|
+
const configLoader = require('./loader/config')
|
|
10
|
+
const controllerLoader = require('./loader/controller')
|
|
11
|
+
const extendLoader = require('./loader/extend')
|
|
12
|
+
|
|
13
|
+
module.exports ={
|
|
14
|
+
/**
|
|
15
|
+
* 启动项目
|
|
16
|
+
* @params options 项目配置
|
|
17
|
+
* options ={
|
|
18
|
+
* name //项目名称
|
|
19
|
+
* homePath //项目首页
|
|
20
|
+
* }
|
|
21
|
+
* */
|
|
22
|
+
start(options = {}){
|
|
23
|
+
//koa实例
|
|
24
|
+
const app = new koa();
|
|
25
|
+
|
|
26
|
+
// 应用配置
|
|
27
|
+
app.options= options
|
|
28
|
+
|
|
29
|
+
// 基础路径
|
|
30
|
+
app.baseDir = process.cwd();
|
|
31
|
+
|
|
32
|
+
// 业务文件路径
|
|
33
|
+
app.businessPath = path.resolve(app.baseDir, `.${sep}app`);
|
|
34
|
+
|
|
35
|
+
// 初始化环境配置
|
|
36
|
+
app.env = env();
|
|
37
|
+
console.log(`----${app.env.get()}---`);
|
|
38
|
+
// 加载config
|
|
39
|
+
configLoader(app)
|
|
40
|
+
console.log(`----start config-----`);
|
|
41
|
+
|
|
42
|
+
// 加载extend
|
|
43
|
+
extendLoader(app)
|
|
44
|
+
console.log(`----start extend-----`);
|
|
45
|
+
|
|
46
|
+
// 加载routerSchema
|
|
47
|
+
routerSchemaLoader(app)
|
|
48
|
+
console.log(`----start routerSchema-----`);
|
|
49
|
+
|
|
50
|
+
// 加载 service
|
|
51
|
+
serviceLoader(app)
|
|
52
|
+
console.log(`----start service-----`);
|
|
53
|
+
|
|
54
|
+
// 加载 controller
|
|
55
|
+
controllerLoader(app)
|
|
56
|
+
|
|
57
|
+
console.log(`----start controller-----`);
|
|
58
|
+
|
|
59
|
+
// 加载middleware
|
|
60
|
+
middlewareLoader(app)
|
|
61
|
+
console.log(`----start middleware-----`);
|
|
62
|
+
|
|
63
|
+
// 注册elpis 中间件
|
|
64
|
+
const elpisMiddlewarePath = path.resolve(__dirname,`..${sep}app${sep}/middleware.js`);
|
|
65
|
+
const elpisMiddleware = require(elpisMiddlewarePath);
|
|
66
|
+
elpisMiddleware(app)
|
|
67
|
+
|
|
68
|
+
console.log(`--[start] load global elpis middleware done--`)
|
|
69
|
+
|
|
70
|
+
// 注册业务全局中间件
|
|
71
|
+
try{
|
|
72
|
+
require(`${app.businessPath}${sep}middleware.js`)(app);
|
|
73
|
+
console.log(`----start loader middleware done-----`);
|
|
74
|
+
}catch(e){
|
|
75
|
+
console.log('there is no global business middleware file')
|
|
76
|
+
}
|
|
77
|
+
// 注册路由
|
|
78
|
+
routerLoader(app)
|
|
79
|
+
console.log(`----start router-----`);
|
|
80
|
+
// 启动服务
|
|
81
|
+
try{
|
|
82
|
+
const port = process.env.PORT || 8080;
|
|
83
|
+
const host = process.env.IP || '0.0.0.0';
|
|
84
|
+
app.listen(port, host)
|
|
85
|
+
console.log('Listening on port ' + port);
|
|
86
|
+
} catch(e){
|
|
87
|
+
console.error(e);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return app;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const {sep} = path
|
|
3
|
+
/*
|
|
4
|
+
* config loader
|
|
5
|
+
* @parame {object} app koa 实例
|
|
6
|
+
* 配置区分 本地/测试/生产 , 通过env 环境读取不同文件配置 evn.config
|
|
7
|
+
* 通过env.config 覆盖 default.config 加载到app.config 中
|
|
8
|
+
*
|
|
9
|
+
* 目录下对应的config配置
|
|
10
|
+
* 默认配置 config/config.default.js
|
|
11
|
+
* 本地配置 config/config.local.js
|
|
12
|
+
* 测试配置 config/config.beta.js
|
|
13
|
+
* 生产配置 config/config.prod.js
|
|
14
|
+
* */
|
|
15
|
+
module.exports = (app) => {
|
|
16
|
+
// elpis config 目录及相关文件
|
|
17
|
+
const elpisConfigPath = path.resolve(__dirname,`..${sep}..${sep}config`);
|
|
18
|
+
let defaultConfig = require(path.resolve(elpisConfigPath,`.${sep}config.default.js`));
|
|
19
|
+
|
|
20
|
+
// 业务config目录及相关文件
|
|
21
|
+
const businessConfigPath = path.resolve(process.cwd(),`.${sep}config`);
|
|
22
|
+
console.log(businessConfigPath)
|
|
23
|
+
|
|
24
|
+
// 获取default.config
|
|
25
|
+
try{
|
|
26
|
+
defaultConfig={
|
|
27
|
+
...defaultConfig,
|
|
28
|
+
...require(path.resolve(businessConfigPath,`.${sep}config.default.js`))
|
|
29
|
+
}
|
|
30
|
+
}catch(e){
|
|
31
|
+
console.log('there is no default.config file')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 获取env.config
|
|
35
|
+
let envConfig = {};
|
|
36
|
+
try{
|
|
37
|
+
// 本地环境
|
|
38
|
+
if(app.env.isLocal()){
|
|
39
|
+
envConfig = require(path.resolve(businessConfigPath,`.${sep}config.local.js`));
|
|
40
|
+
// 测试环境
|
|
41
|
+
}else if(app.env.isBeta()){
|
|
42
|
+
envConfig = require(path.resolve(businessConfigPath,`.${sep}config.beta.js`));
|
|
43
|
+
// 生产环境
|
|
44
|
+
}else if(app.env.isProduction()){
|
|
45
|
+
envConfig = require(path.resolve(businessConfigPath,`.${sep}config.prod.js`));
|
|
46
|
+
console.log(envConfig,'_ENV')
|
|
47
|
+
}
|
|
48
|
+
}catch(e){
|
|
49
|
+
console.log('there is no config file')
|
|
50
|
+
}
|
|
51
|
+
// 覆盖并加载config配置
|
|
52
|
+
app.config = Object.assign({},defaultConfig,envConfig);
|
|
53
|
+
console.log('app.config:',app.config);
|
|
54
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {sep} = path
|
|
4
|
+
/*
|
|
5
|
+
* controller loader
|
|
6
|
+
* @param{object} app Koa 实例
|
|
7
|
+
* 加载所有controller,可通过 'app.controller.${目录}.${文件}' 访问
|
|
8
|
+
* 例子
|
|
9
|
+
* app/controller
|
|
10
|
+
* |
|
|
11
|
+
* | --custom-module
|
|
12
|
+
* |
|
|
13
|
+
* | --custom-controller.js
|
|
14
|
+
* => app.controller.customModule.customController
|
|
15
|
+
* */
|
|
16
|
+
|
|
17
|
+
module.exports = (app) => {
|
|
18
|
+
const controller = {}
|
|
19
|
+
// 读取elpis/app/controller/**/**.js 下所有文件
|
|
20
|
+
const elpisControllerPath = path.resolve(__dirname,`..${sep}..${sep}app${sep}controller`);
|
|
21
|
+
const elpisFileList = glob.sync(path.resolve(elpisControllerPath, `.${sep}**${sep}**.js`));
|
|
22
|
+
elpisFileList.forEach(file => {
|
|
23
|
+
handleFile(file)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// 读取业务/app/controller/**/**.js 下所有文件
|
|
27
|
+
const businessControllerPath = path.resolve(app.businessPath,`.${sep}controller`);
|
|
28
|
+
const businessFileList = glob.sync(path.resolve(businessControllerPath, `.${sep}**${sep}**.js`));
|
|
29
|
+
businessFileList.forEach(file => {
|
|
30
|
+
handleFile(file)
|
|
31
|
+
})
|
|
32
|
+
//把内容加载到app.controller 下
|
|
33
|
+
function handleFile(file) {
|
|
34
|
+
//提取文件名称
|
|
35
|
+
let name = path.resolve(file)
|
|
36
|
+
|
|
37
|
+
// 截取路径 app/controller/custom-module/custom-controller.js =>custom-module/custom-controller
|
|
38
|
+
name = name.substring(name.lastIndexOf(`controller${sep}`)+`controller${sep}`.length,name.lastIndexOf('.'));
|
|
39
|
+
|
|
40
|
+
//把'-' 统一改成驼峰命名
|
|
41
|
+
name = name.replace(/[_-][a-z]/ig,(s)=>s.substring(1).toUpperCase());
|
|
42
|
+
|
|
43
|
+
//挂载controller到内存app对象中
|
|
44
|
+
let temController = controller;
|
|
45
|
+
const names = name.split(sep) //[customModule(目录),customController(文件)]
|
|
46
|
+
for(let i =0,len = names.length;i<len; ++i ){
|
|
47
|
+
if(i===len - 1){
|
|
48
|
+
const ControllerMoule = require(path.resolve(file))(app)
|
|
49
|
+
temController[names[i]] = new ControllerMoule();
|
|
50
|
+
}else{
|
|
51
|
+
if(!temController[names[i]]){
|
|
52
|
+
temController[names[i]] = {};
|
|
53
|
+
}
|
|
54
|
+
temController = temController[names[i]];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
app.controller = controller;
|
|
60
|
+
};
|
|
61
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {sep} = path
|
|
4
|
+
/*
|
|
5
|
+
* extend loader
|
|
6
|
+
* @param{object} app Koa 实例
|
|
7
|
+
* 加载所有extend,可通过 'app.extend.${文件}' 访问
|
|
8
|
+
* 例子
|
|
9
|
+
* app/extend
|
|
10
|
+
* |
|
|
11
|
+
* | --custom-extend.js
|
|
12
|
+
* => app.extend.customExtend
|
|
13
|
+
* */
|
|
14
|
+
|
|
15
|
+
module.exports = (app) => {
|
|
16
|
+
|
|
17
|
+
// 读取elpis/app/extend/**.js 下所有文件
|
|
18
|
+
const elpisExtendPath = path.resolve(__dirname,`..${sep}..${sep}app${sep}extend`);
|
|
19
|
+
const elpisFileList = glob.sync(path.resolve(elpisExtendPath, `.${sep}**${sep}**.js`));
|
|
20
|
+
elpisFileList.forEach(file => {
|
|
21
|
+
handelFile(file)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// 读取业务/app/extend/**.js 下所有文件
|
|
25
|
+
const businessExtendPath = path.resolve(app.businessPath,`.${sep}extend`);
|
|
26
|
+
const businessFileList = glob.sync(path.resolve(businessExtendPath, `.${sep}**${sep}**.js`));
|
|
27
|
+
|
|
28
|
+
businessFileList.forEach(file => {
|
|
29
|
+
handelFile(file)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
//把内容加载到app.extend 下
|
|
33
|
+
function handelFile(file){
|
|
34
|
+
//提取文件名称
|
|
35
|
+
let name = path.resolve(file)
|
|
36
|
+
|
|
37
|
+
// 截取路径 app/extend/custom-extend.js =>custom-extend
|
|
38
|
+
name = name.substring(name.lastIndexOf(`extend${sep}`)+`extend${sep}`.length,name.lastIndexOf('.'));
|
|
39
|
+
|
|
40
|
+
//把'-' 统一改成驼峰命名
|
|
41
|
+
name = name.replace(/[_-][a-z]/ig,(s)=>s.substring(1).toUpperCase());
|
|
42
|
+
// 过滤app 已经存在的key
|
|
43
|
+
for(const key in app){
|
|
44
|
+
if(key === name){
|
|
45
|
+
console.log(`${name} is already in app`);
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 挂载extend 到app上
|
|
51
|
+
app[name] = require(path.resolve(file))(app);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
};
|
|
55
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {sep} = path
|
|
4
|
+
/*
|
|
5
|
+
* middleware loader
|
|
6
|
+
* @param{object} app Koa 实例
|
|
7
|
+
* 加载所有minddleware,可通过 'app.minddlewares.${目录}.${文件}' 访问
|
|
8
|
+
* 例子
|
|
9
|
+
* app/middleware
|
|
10
|
+
* |
|
|
11
|
+
* | --custom-module
|
|
12
|
+
* |
|
|
13
|
+
* | --custom-middleware.js
|
|
14
|
+
* => app.middleware.customModule.customMiddleware
|
|
15
|
+
* */
|
|
16
|
+
|
|
17
|
+
module.exports = (app) => {
|
|
18
|
+
const middleware = {}
|
|
19
|
+
// 读取elpis/app/middleware/**/**.js 下所有文件
|
|
20
|
+
const elpisMiddlewarePath = path.resolve(__dirname,`..${sep}..${sep}app${sep}middleware`);
|
|
21
|
+
const elpisFileList = glob.sync(path.resolve(elpisMiddlewarePath, `.${sep}**${sep}**.js`));
|
|
22
|
+
elpisFileList.forEach(file => {
|
|
23
|
+
handleFile(file)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// 读取业务根目录/app/middleware/**/**.js 下所有文件
|
|
27
|
+
const businessMiddlewarePath = path.resolve(app.businessPath,`.${sep}middleware`);
|
|
28
|
+
const businessFileList = glob.sync(path.resolve(businessMiddlewarePath, `.${sep}**${sep}**.js`));
|
|
29
|
+
businessFileList.forEach(file => {
|
|
30
|
+
handleFile(file)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
//,把内容加载到app.middlewares 下
|
|
34
|
+
function handleFile(file){
|
|
35
|
+
//提取文件名称
|
|
36
|
+
let name = path.resolve(file)
|
|
37
|
+
|
|
38
|
+
// 截取路径 app/middleware/custom-module/custom-middleware =>custom-module/custom-middleware
|
|
39
|
+
name = name.substring(name.lastIndexOf(`middleware${sep}`)+`middleware${sep}`.length,name.lastIndexOf('.'));
|
|
40
|
+
|
|
41
|
+
//把'-' 统一改成驼峰命名
|
|
42
|
+
name = name.replace(/[_-][a-z]/ig,(s)=>s.substring(1).toUpperCase());
|
|
43
|
+
|
|
44
|
+
//挂载middleware到内存app对象中
|
|
45
|
+
let tempMiddleware = middleware;
|
|
46
|
+
const names = name.split(sep)
|
|
47
|
+
for(let i =0,len = names.length;i<len; ++i ){
|
|
48
|
+
if(i===len -1){
|
|
49
|
+
tempMiddleware[names[i]] = require(path.resolve(file))(app);
|
|
50
|
+
}else{
|
|
51
|
+
if(!tempMiddleware[names[i]]){
|
|
52
|
+
tempMiddleware[names[i]] = {};
|
|
53
|
+
}
|
|
54
|
+
tempMiddleware = tempMiddleware[names[i]];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
app.middlewares = middleware;
|
|
60
|
+
};
|
|
61
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const {sep} = path
|
|
4
|
+
/*
|
|
5
|
+
* router-schema loader
|
|
6
|
+
* @param {object} app koa 实例
|
|
7
|
+
* 通过 ‘json-schema& ajv ' 对API 规则进行约束,配合api-params-verify 中间件使用
|
|
8
|
+
* app/router-schema/**.js
|
|
9
|
+
* 输出
|
|
10
|
+
app.rouSchema ={
|
|
11
|
+
'${api1}':${jsonSchema},
|
|
12
|
+
'${api2}':${jsonSchema}
|
|
13
|
+
}
|
|
14
|
+
* */
|
|
15
|
+
module.exports = (app) => {
|
|
16
|
+
let routerSchema ={};
|
|
17
|
+
// 读取elpis/app/router-schema/**/**.js 下所有文件
|
|
18
|
+
const elpisRouterSchemaPath = path.resolve(__dirname,`..${sep}..${sep}app${sep}router-schema`);
|
|
19
|
+
const elpisFileList = glob.sync(path.resolve(elpisRouterSchemaPath, `.${sep}**${sep}**.js`));
|
|
20
|
+
elpisFileList.forEach(file => {
|
|
21
|
+
handleFile(file)
|
|
22
|
+
})
|
|
23
|
+
// 读取业务/app/router-schema/**/**.js 下所有文件
|
|
24
|
+
const businessRouterSchemaPath = path.resolve(app.businessPath,`.${sep}router-schema`);
|
|
25
|
+
const businessFileList = glob.sync(path.resolve(businessRouterSchemaPath, `.${sep}**${sep}**.js`));
|
|
26
|
+
businessFileList.forEach(file => {
|
|
27
|
+
handleFile(file)
|
|
28
|
+
})
|
|
29
|
+
// 注册所有的routerSchema,使得可以 app.routerSchema 这样访问
|
|
30
|
+
function handleFile(file){
|
|
31
|
+
routerSchema ={
|
|
32
|
+
...routerSchema,
|
|
33
|
+
...require(path.resolve(file))
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
app.routerSchema = routerSchema;
|
|
39
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const KoaRouter = require('koa-router');
|
|
2
|
+
const glob = require('glob')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const {sep} = path;
|
|
5
|
+
/*
|
|
6
|
+
* router loader
|
|
7
|
+
* @param {object} app koa 实例
|
|
8
|
+
*
|
|
9
|
+
* 解析所有app/router/ 下所有js 文件 加载到KoaRouter 下
|
|
10
|
+
* */
|
|
11
|
+
|
|
12
|
+
module.exports = (app) => {
|
|
13
|
+
// 实例化KoaRouter
|
|
14
|
+
const router = new KoaRouter();
|
|
15
|
+
|
|
16
|
+
// 找到elpis路由文件路径
|
|
17
|
+
const elpisRouterPath = path.resolve(__dirname,`..${sep}..${sep}app${sep}router`);
|
|
18
|
+
// 注册所有路由
|
|
19
|
+
const elpisFileList = glob.sync(path.resolve(elpisRouterPath, `.${sep}**${sep}**.js`));
|
|
20
|
+
elpisFileList.forEach(file => {
|
|
21
|
+
require(path.resolve(file))(app,router);
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
// 找到业务路由文件路径
|
|
26
|
+
const businessRouterPath = path.resolve(app.businessPath,`.${sep}router`);
|
|
27
|
+
// 注册所有路由
|
|
28
|
+
const businessFileList = glob.sync(path.resolve(businessRouterPath, `.${sep}**${sep}**.js`));
|
|
29
|
+
|
|
30
|
+
businessFileList.forEach(file => {
|
|
31
|
+
require(path.resolve(file))(app,router);
|
|
32
|
+
})
|
|
33
|
+
// 路由兜底
|
|
34
|
+
router.get('*',async (ctx, next) => {
|
|
35
|
+
ctx.status = 302;//临时重定向
|
|
36
|
+
ctx.redirect(`${app?.options?.homePath ?? '/'}`)
|
|
37
|
+
})
|
|
38
|
+
// 路由注册到app上
|
|
39
|
+
app.use(router.routes());
|
|
40
|
+
app.use(router.allowedMethods());
|
|
41
|
+
|
|
42
|
+
};
|