@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.
Files changed (81) hide show
  1. package/.babelrc +5 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc +66 -0
  4. package/README.md +214 -0
  5. package/app/controller/base.js +39 -0
  6. package/app/controller/project.js +75 -0
  7. package/app/controller/view.js +19 -0
  8. package/app/extend/database.js +5 -0
  9. package/app/extend/logger.js +38 -0
  10. package/app/middleware/api-params-verify.js +74 -0
  11. package/app/middleware/api-sign-verify.js +36 -0
  12. package/app/middleware/error-handle.js +32 -0
  13. package/app/middleware/project-handler.js +26 -0
  14. package/app/middleware.js +39 -0
  15. package/app/pages/asserts/custom.css +14 -0
  16. package/app/pages/boot.js +48 -0
  17. package/app/pages/common/curl.js +80 -0
  18. package/app/pages/common/utils.js +34 -0
  19. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +24 -0
  20. package/app/pages/dashboard/complex-view/header-view/head-view.vue +113 -0
  21. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
  23. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +118 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/components-config.js +23 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +85 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +103 -0
  27. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +112 -0
  28. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
  29. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +90 -0
  30. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +22 -0
  31. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +113 -0
  32. package/app/pages/dashboard/dashboard.vue +85 -0
  33. package/app/pages/dashboard/entry.dashboard.js +46 -0
  34. package/app/pages/store/index.js +4 -0
  35. package/app/pages/store/menu.js +54 -0
  36. package/app/pages/store/project.js +13 -0
  37. package/app/pages/widgets/head-container/asserts/logo.png +0 -0
  38. package/app/pages/widgets/head-container/head-container.vue +77 -0
  39. package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
  40. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +135 -0
  41. package/app/pages/widgets/schema-form/complex-view/select/select.vue +120 -0
  42. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  43. package/app/pages/widgets/schema-form/schema-form.vue +130 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +51 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +55 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +38 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +40 -0
  48. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +100 -0
  49. package/app/pages/widgets/schema-search-bar/search-item-config.js +31 -0
  50. package/app/pages/widgets/schema-table/schema-table.vue +225 -0
  51. package/app/pages/widgets/sider-container/sider-container.vue +27 -0
  52. package/app/public/output/entry.page1.tpl +42 -0
  53. package/app/public/static/logo.jpg +0 -0
  54. package/app/public/static/normalize.css +267 -0
  55. package/app/router/project.js +6 -0
  56. package/app/router/view.js +7 -0
  57. package/app/router-schema/project.js +30 -0
  58. package/app/service/base.js +13 -0
  59. package/app/service/project.js +42 -0
  60. package/app/view/entry.tpl +25 -0
  61. package/app/webpack/config/babel.config.js +4 -0
  62. package/app/webpack/config/webpack.base.js +229 -0
  63. package/app/webpack/config/webpack.dev.js +57 -0
  64. package/app/webpack/config/webpack.prod.js +120 -0
  65. package/app/webpack/libs/blank.js +1 -0
  66. package/app/webpack/libs/dev.js +53 -0
  67. package/app/webpack/libs/prod.js +22 -0
  68. package/config/config.default.js +4 -0
  69. package/elpis-core/env.js +20 -0
  70. package/elpis-core/index.js +81 -0
  71. package/elpis-core/loader/config.js +52 -0
  72. package/elpis-core/loader/controller.js +59 -0
  73. package/elpis-core/loader/extend.js +47 -0
  74. package/elpis-core/loader/middleware.js +57 -0
  75. package/elpis-core/loader/router-schema.js +41 -0
  76. package/elpis-core/loader/router.js +42 -0
  77. package/elpis-core/loader/service.js +59 -0
  78. package/index.js +39 -0
  79. package/model/index.js +107 -0
  80. package/package.json +90 -0
  81. 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,4 @@
1
+ module.exports = {
2
+ name: 'elpis',
3
+ version: '1.0.0',
4
+ };
@@ -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
+ };