@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.
Files changed (86) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +55 -0
  3. package/.idea/dictionaries/project.xml +8 -0
  4. package/.idea/elpis.iml +8 -0
  5. package/.idea/git_toolbox_prj.xml +15 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +329 -0
  7. package/.idea/modules.xml +8 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/README.md +201 -0
  10. package/app/controller/base.js +77 -0
  11. package/app/controller/project.js +69 -0
  12. package/app/controller/view.js +20 -0
  13. package/app/extend/logger.js +35 -0
  14. package/app/middleware/api-params-verify.js +74 -0
  15. package/app/middleware/api-sign-verify.js +33 -0
  16. package/app/middleware/error-hander.js +32 -0
  17. package/app/middleware/project-handler.js +25 -0
  18. package/app/middleware.js +37 -0
  19. package/app/pages/asserts/custom.css +11 -0
  20. package/app/pages/boot.js +43 -0
  21. package/app/pages/common/curl.js +83 -0
  22. package/app/pages/common/index.js +2 -0
  23. package/app/pages/common/utils.js +0 -0
  24. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +23 -0
  25. package/app/pages/dashboard/complex-view/header-view/header-view.vue +117 -0
  26. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +40 -0
  27. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +45 -0
  28. package/app/pages/dashboard/complex-view/schema-view/complex-view/tabel-panel/tabel-panel.vue +134 -0
  29. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +20 -0
  30. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +89 -0
  31. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +101 -0
  32. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +128 -0
  33. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +119 -0
  34. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +96 -0
  35. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
  36. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +117 -0
  37. package/app/pages/dashboard/dashboard.vue +88 -0
  38. package/app/pages/dashboard/entry.dashboard.js +41 -0
  39. package/app/pages/router/index.js +11 -0
  40. package/app/pages/store/index.js +4 -0
  41. package/app/pages/store/menu.js +65 -0
  42. package/app/pages/store/project.js +16 -0
  43. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  44. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  45. package/app/pages/widgets/header-container/header-container.vue +103 -0
  46. package/app/pages/widgets/schema-form/complex-view/input/input.vue +142 -0
  47. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +143 -0
  48. package/app/pages/widgets/schema-form/complex-view/select/select.vue +130 -0
  49. package/app/pages/widgets/schema-form/form-item-config.js +20 -0
  50. package/app/pages/widgets/schema-form/schema-form.vue +132 -0
  51. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +48 -0
  52. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
  53. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
  54. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +50 -0
  55. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +142 -0
  56. package/app/pages/widgets/schema-search-bar/search-item-config.js +24 -0
  57. package/app/pages/widgets/schema-table/schema-table.vue +238 -0
  58. package/app/pages/widgets/sider-container/sider-container.vue +31 -0
  59. package/app/public/static/logo.png +0 -0
  60. package/app/public/static/normalize.css +239 -0
  61. package/app/router/project.js +9 -0
  62. package/app/router/view.js +7 -0
  63. package/app/router-schema/project.js +32 -0
  64. package/app/service/base.js +12 -0
  65. package/app/service/project.js +42 -0
  66. package/app/view/entry.tpl +26 -0
  67. package/app/webpack/config/webpack.base.js +219 -0
  68. package/app/webpack/config/webpack.dev.js +55 -0
  69. package/app/webpack/config/webpack.prod.js +118 -0
  70. package/app/webpack/dev.js +52 -0
  71. package/app/webpack/libs/blank.js +2 -0
  72. package/app/webpack/prod.js +18 -0
  73. package/config/config.default.js +3 -0
  74. package/elpis-core/env.js +20 -0
  75. package/elpis-core/index.js +92 -0
  76. package/elpis-core/loader/config.js +54 -0
  77. package/elpis-core/loader/controller.js +61 -0
  78. package/elpis-core/loader/extend.js +55 -0
  79. package/elpis-core/loader/middleware.js +61 -0
  80. package/elpis-core/loader/router-schema.js +39 -0
  81. package/elpis-core/loader/router.js +42 -0
  82. package/elpis-core/loader/service.js +64 -0
  83. package/index.js +41 -0
  84. package/model/index.js +105 -0
  85. package/package.json +94 -0
  86. 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,2 @@
1
+ module.exports={
2
+ }
@@ -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,3 @@
1
+ module.exports = {
2
+ name:'elpis'
3
+ }
@@ -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
+ };