@codertqy/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 (83) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +55 -0
  3. package/README.md +218 -0
  4. package/app/controller/base.js +40 -0
  5. package/app/controller/project.js +81 -0
  6. package/app/controller/view.js +22 -0
  7. package/app/extend/logger.js +43 -0
  8. package/app/middleware/api-params-verify.js +73 -0
  9. package/app/middleware/api-sign-verify.js +49 -0
  10. package/app/middleware/error-handler.js +31 -0
  11. package/app/middleware/project-handler.js +26 -0
  12. package/app/middleware.js +44 -0
  13. package/app/pages/assets/custom.css +14 -0
  14. package/app/pages/boot.js +56 -0
  15. package/app/pages/common/curl.js +84 -0
  16. package/app/pages/common/index.css +3 -0
  17. package/app/pages/common/utils.js +1 -0
  18. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +19 -0
  19. package/app/pages/dashboard/complex-view/header-view/header-view.vue +126 -0
  20. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +45 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +120 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +87 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +122 -0
  27. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +161 -0
  28. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +95 -0
  29. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +19 -0
  30. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
  31. package/app/pages/dashboard/dashboard.vue +86 -0
  32. package/app/pages/dashboard/entry.dashboard.js +48 -0
  33. package/app/pages/store/index.js +3 -0
  34. package/app/pages/store/menu.js +68 -0
  35. package/app/pages/store/project.js +12 -0
  36. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  37. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  38. package/app/pages/widgets/header-container/header-container.vue +107 -0
  39. package/app/pages/widgets/schema-form/complex-view/input/input.vue +138 -0
  40. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +140 -0
  41. package/app/pages/widgets/schema-form/complex-view/select/select.vue +122 -0
  42. package/app/pages/widgets/schema-form/form-item-config.js +20 -0
  43. package/app/pages/widgets/schema-form/schema-form.vue +135 -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 +63 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +41 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +49 -0
  48. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +126 -0
  49. package/app/pages/widgets/schema-search-bar/search-item-config.js +22 -0
  50. package/app/pages/widgets/schema-table/schema-table.vue +259 -0
  51. package/app/pages/widgets/sider-container/sider-container.vue +27 -0
  52. package/app/public/output/entry.page1.tpl +40 -0
  53. package/app/public/output/entry.page2.tpl +11 -0
  54. package/app/public/static/logo.png +0 -0
  55. package/app/public/static/normalize.css +239 -0
  56. package/app/router/project.js +22 -0
  57. package/app/router/view.js +17 -0
  58. package/app/router-schema/project.js +34 -0
  59. package/app/service/base.js +15 -0
  60. package/app/service/project.js +59 -0
  61. package/app/view/entry.tpl +25 -0
  62. package/app/webpack/config/webpack.base.js +280 -0
  63. package/app/webpack/config/webpack.dev.js +57 -0
  64. package/app/webpack/config/webpack.prod.js +127 -0
  65. package/app/webpack/dev.js +63 -0
  66. package/app/webpack/libs/blank.js +1 -0
  67. package/app/webpack/prod.js +22 -0
  68. package/config/config.beta.js +1 -0
  69. package/config/config.default.js +3 -0
  70. package/config/config.prod.js +1 -0
  71. package/elpis-core/env.js +27 -0
  72. package/elpis-core/index.js +98 -0
  73. package/elpis-core/loader/config.js +58 -0
  74. package/elpis-core/loader/controller.js +93 -0
  75. package/elpis-core/loader/extend.js +63 -0
  76. package/elpis-core/loader/middleware.js +84 -0
  77. package/elpis-core/loader/router-schema.js +56 -0
  78. package/elpis-core/loader/router.js +50 -0
  79. package/elpis-core/loader/service.js +85 -0
  80. package/index.js +38 -0
  81. package/model/index.js +129 -0
  82. package/package.json +92 -0
  83. package/test/controller/project.test.js +214 -0
@@ -0,0 +1,98 @@
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 routerSchemaLoader = require("./loader/router-schema");
9
+ const routerLoader = require("./loader/router");
10
+ const controllerLoader = require("./loader/controller");
11
+ const configLoader = require("./loader/config");
12
+ const extendLoader = require("./loader/extend");
13
+ const serviceLoader = require("./loader/service");
14
+
15
+ module.exports = {
16
+ /**
17
+ * 启动项目
18
+ * @param {} options 项目配置
19
+ * options = {
20
+ * name // 项目名称
21
+ * homePath // 项目首页
22
+ * }
23
+ */
24
+ start(options = {}) {
25
+ const app = new Koa();
26
+ // 将配置挂载到app实例上
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(`----[start] env: ${app.env.get()} ----`);
38
+
39
+ // 加载middleware中间件
40
+ middlewareLoader(app);
41
+ console.log(`----[start] middleware done ----`);
42
+
43
+ // 加载routerSchema路由配置
44
+ routerSchemaLoader(app);
45
+ console.log(`----[start] router-schema done ----`);
46
+
47
+ // 加载controller控制器
48
+ controllerLoader(app);
49
+ console.log(`----[start] controller done ----`);
50
+
51
+ // 加载service服务
52
+ serviceLoader(app);
53
+ console.log(`----[start] service done ----`);
54
+
55
+ // 加载config配置
56
+ configLoader(app);
57
+ console.log(`----[start] config done ----`);
58
+
59
+ // 加载extend扩展
60
+ extendLoader(app);
61
+ console.log(`----[start] extend done ----`);
62
+
63
+ // 注册 elpis全局中间件
64
+ const elpisMiddlewarePath = path.resolve(
65
+ __dirname,
66
+ `..${sep}app${sep}middleware.js`,
67
+ );
68
+ const elpisMiddleware = require(elpisMiddlewarePath);
69
+ elpisMiddleware(app);
70
+ console.log(`----[start] load gloabl elpis middelware done ----`);
71
+
72
+
73
+ // 注册 业务全局中间件 也就是通过app/middleware.js文件进行注册
74
+ try {
75
+ require(`${app.businessPath}${sep}middleware.js`)(app);
76
+ console.log(`----[start] load gloabl business middelware done ----`);
77
+ } catch (error) {
78
+ console.log("[exception] there is no gloabl business middleware file");
79
+ }
80
+
81
+ // 加载router路由 要经过前面所有的
82
+ routerLoader(app);
83
+ console.log(`----[start] router done ----`);
84
+
85
+ // 启动服务
86
+ try {
87
+ const port = process.env.PORT || 8080;
88
+ const host = process.env.IP || "0.0.0.0";
89
+ app.listen(port, host);
90
+ console.log(`Server runing on port: ${port}`);
91
+ } catch (e) {
92
+ console.log(e);
93
+ }
94
+
95
+ // 暴露出去交给测试使用
96
+ return app;
97
+ },
98
+ };
@@ -0,0 +1,58 @@
1
+ const path = require("path");
2
+ const { sep } = path;
3
+ /**
4
+ * config loader
5
+ * @param {object} app Koa实例
6
+ *
7
+ * 配置加载器 区分 本地/测试/生产 ,通过env环境读取不同文件配置 env.config
8
+ * 通过 env.config 覆盖 default.config 加载到 app.config 中
9
+ *
10
+ * 目录下对应的 config 配置
11
+ * 默认配置 config/config.default.js
12
+ * 本地配置 config/config.local.js
13
+ * 测试配置 config/config.beta.js
14
+ * 生产配置 config/config.prod.js
15
+ *
16
+ *
17
+ */
18
+ module.exports = (app) => {
19
+ // elpis config 目录及相关文件
20
+ const elpisConfigPath = path.resolve(
21
+ __dirname,
22
+ `..${sep}..${sep}config`,
23
+ );
24
+ let defaultConfig = require(
25
+ path.resolve(elpisConfigPath, `.${sep}config.default.js`),
26
+ );
27
+
28
+ // 业务 config 目录及相关文件
29
+ const busnissConfigPath = path.resolve(process.cwd(), `.${sep}config`);
30
+ try {
31
+ defaultConfig = {
32
+ ...defaultConfig,
33
+ ...require(path.resolve(busnissConfigPath, `.${sep}config.default.js`)),
34
+ };
35
+ } catch (e) {
36
+ console.log("[exception] there is not config.default file");
37
+ }
38
+
39
+ // 3. 获取 env.config
40
+ let envConfig = {};
41
+ try {
42
+ if (app.env.isLocal()) {
43
+ //本地环境
44
+ envConfig = require(path.resolve(busnissConfigPath, `.${sep}config.local.js`));
45
+ } else if (app.env.isBeta()) {
46
+ //测试环境
47
+ envConfig = require(path.resolve(busnissConfigPath, `.${sep}config.beta.js`));
48
+ } else if (app.env.isProd()) {
49
+ //生产环境
50
+ envConfig = require(path.resolve(busnissConfigPath, `.${sep}config.prod.js`));
51
+ }
52
+ } catch (e) {
53
+ console.log("[exception] there is not config.env file or logical errors");
54
+ }
55
+
56
+ // 4. 覆盖并加载 config 配置
57
+ app.config = Object.assign({}, defaultConfig, envConfig);
58
+ };
@@ -0,0 +1,93 @@
1
+ const path = require("path");
2
+ const glob = require("glob");
3
+ const { sep } = path;
4
+ /**
5
+ * controller loader
6
+ * @param {object} app Koa实例
7
+ *
8
+ * 加载所有controller , 可通过'app.controller.${目录}.${文件}' 访问
9
+ * 例子
10
+ * app/controller
11
+ * |
12
+ * |-- custom-module
13
+ * |
14
+ * |-- custom-controller.js
15
+ * ====> app.controller.customModule.customController
16
+ *
17
+ */
18
+ module.exports = (app) => {
19
+ const controller = {};
20
+
21
+ // 读取 elpis/app/controller/**/**.js所有文件
22
+ const elpisControllerPath = path.resolve(
23
+ __dirname,
24
+ `..${sep}..${sep}app${sep}controller`,
25
+ );
26
+ // 遍历所有js文件
27
+ const elpisFileList = glob.sync(
28
+ path.resolve(elpisControllerPath, `.${sep}**${sep}**.js`),
29
+ );
30
+ elpisFileList.forEach((file) => {
31
+ handleFile(file);
32
+ });
33
+
34
+ // 读取 业务/app/controller/**/**.js所有文件
35
+ const businessControllerPath = path.resolve(
36
+ app.businessPath,
37
+ `.${sep}controller`,
38
+ );
39
+ // 遍历所有js文件
40
+ const businessFileList = glob.sync(
41
+ path.resolve(businessControllerPath, `.${sep}**${sep}**.js`),
42
+ );
43
+ businessFileList.forEach((file) => {
44
+ handleFile(file);
45
+ });
46
+
47
+ function handleFile(file) {
48
+ // 提取文件名称
49
+ let name = path.resolve(file);
50
+
51
+ // 截取路径 app/controller/custom-module/custom-controller.js =》custom-module/custom-controller
52
+ name = name.substring(
53
+ name.lastIndexOf(`controller${sep}`) + `controller${sep}`.length,
54
+ name.lastIndexOf("."),
55
+ );
56
+
57
+ // 把 - 统一改为驼峰式
58
+ name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
59
+
60
+ // 根据文件夹构建嵌套对象
61
+ let tempController = controller;
62
+
63
+ // 分割/ 过滤空字符串
64
+ const names = name.split(sep).filter(Boolean);
65
+ for (let i = 0, len = names.length; i < len; i++) {
66
+ const key = names[i];
67
+ // 最后一层,挂载中间件函数
68
+ if (i === len - 1) {
69
+ /**
70
+ * 因为在koa里面middleware是一个可执行方法,可以直接执行
71
+ * controller是一个类,需要构造对象执行
72
+ *
73
+ * require(file)表示加载执行指定路径下的文件。app是当做参数传递给该文件函数
74
+ */
75
+ const ControllerModule = require(file)(app);
76
+ tempController[key] = new ControllerModule();
77
+ } else {
78
+ // 不是最后一层,创建嵌套对象 假设 key为user tempController={user:{}} 也就是则tempController=.user
79
+ if (!tempController[key]) {
80
+ tempController[key] = {};
81
+ }
82
+ // tempcontroller就变为tempcontroller.user ={}
83
+ tempController = tempController[key];
84
+ }
85
+ /**
86
+ * 第二层:key为app 则tempController={ user: { app: { } } } 也就是tempController=.user.app
87
+ */
88
+ }
89
+ }
90
+ // 遍历所有文件目录,把内容加载到 app.controller 下
91
+
92
+ app.controller = controller;
93
+ };
@@ -0,0 +1,63 @@
1
+ const path = require("path");
2
+ const glob = require("glob");
3
+ const { sep } = path;
4
+ /**
5
+ * extend loader
6
+ * @param {object} app Koa实例
7
+ *
8
+ * 加载所有extend , 可通过'app.extend.${文件}' 访问 没有多级路径
9
+ * 例子:
10
+ * app/extend
11
+ * |
12
+ * |-- custom-extend.js
13
+ * ====> app.extend.customExtend
14
+ *
15
+ */
16
+ module.exports = (app) => {
17
+ // 1.读取 eplis/app/extend/**.js所有文件
18
+ const elpisExtendPath = path.resolve(
19
+ __dirname,
20
+ `..${sep}..${sep}app${sep}extend`,
21
+ );
22
+ // 2.遍历所有js文件
23
+ const elpisFileList = glob.sync(
24
+ path.resolve(elpisExtendPath, `.${sep}**${sep}**.js`),
25
+ );
26
+
27
+ elpisFileList.forEach((file) => {
28
+ handleFile(file);
29
+ });
30
+
31
+ // 1.读取 业务/app/extend/**.js所有文件
32
+ const businessExtendPath = path.resolve(app.businessPath, `.${sep}extend`);
33
+ // 2.遍历所有js文件
34
+ const businessFileList = glob.sync(
35
+ path.resolve(businessExtendPath, `.${sep}**${sep}**.js`),
36
+ );
37
+ businessFileList.forEach((file) => {
38
+ handleFile(file);
39
+ });
40
+ function handleFile(file) {
41
+ // 3.1提取文件名称
42
+ let name = path.resolve(file);
43
+
44
+ // 3.2截取路径 app/extend/custom-extend.js =》custom-extend
45
+ name = name.substring(
46
+ name.lastIndexOf(`extend${sep}`) + `extend${sep}`.length,
47
+ name.lastIndexOf("."),
48
+ );
49
+
50
+ // 3.3 把 - 统一改为驼峰式
51
+ name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
52
+
53
+ // 3.4 过滤 app 已经存在的key
54
+ for (const key in app) {
55
+ if (key === name) {
56
+ console.log(`[extend load error] name:${name} is already in app`);
57
+ return;
58
+ }
59
+ }
60
+ // 挂载extend 到 app 上
61
+ app[name] = require(file)(app);
62
+ }
63
+ };
@@ -0,0 +1,84 @@
1
+ const path = require("path");
2
+ const glob = require("glob");
3
+ const { sep } = path;
4
+ /**
5
+ * middleware loader
6
+ * @param {object} app Koa实例
7
+ *
8
+ * 加载所有middleware , 可通过'app.middleware.${目录}.${文件}' 访问
9
+ * 例子
10
+ * app/middleware
11
+ * |
12
+ * |-- custom-module
13
+ * |
14
+ * |-- custom-middleware.js
15
+ * ====> app.middleware.customModule.customMiddleware
16
+ */
17
+ module.exports = (app) => {
18
+ const middlewares = {};
19
+ // 1. 读取 elpis/app/middleware/**/**.js所有文件
20
+ const elpisMiddlewarePath = path.resolve(
21
+ __dirname,
22
+ `..${sep}..${sep}app${sep}middleware`,
23
+ );
24
+ // 2. 遍历所有js文件
25
+ const elpisFileList = glob.sync(
26
+ path.resolve(elpisMiddlewarePath, `.${sep}**${sep}**.js`),
27
+ );
28
+ elpisFileList.forEach((file) => {
29
+ handleFile(file);
30
+ });
31
+
32
+ // 读取 业务根目录/app/middleware/**/**.js所有文件
33
+ const businessMiddlewarePath = path.resolve(
34
+ app.businessPath,
35
+ `.${sep}middleware`,
36
+ );
37
+ const businessFileList = glob.sync(
38
+ path.resolve(businessMiddlewarePath, `.${sep}**${sep}**.js`),
39
+ );
40
+ businessFileList.forEach((file) => {
41
+ handleFile(file);
42
+ });
43
+
44
+ // 3. 遍历所有文件目录,把内容加载到 app.middlewares 下
45
+ function handleFile(file) {
46
+ // 3.1提取文件名称
47
+ let name = path.resolve(file);
48
+
49
+ // 3.2截取路径 app/middleware/custom-module/custom-middleware.js =》custom-module/custom-middleware
50
+ name = name.substring(
51
+ name.lastIndexOf(`middleware${sep}`) + `middleware${sep}`.length,
52
+ name.lastIndexOf("."),
53
+ );
54
+
55
+ // 3.3把 - 统一改为驼峰式
56
+ name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
57
+
58
+ // 3.4根据文件夹构建嵌套对象
59
+ let tempMiddleware = middlewares;
60
+
61
+ // 3.5 分割/ 过滤空字符串 [customMoudle, customController]
62
+ const names = name.split(sep).filter(Boolean);
63
+ for (let i = 0, len = names.length; i < len; i++) {
64
+ const key = names[i];
65
+ // 最后一层,挂载中间件函数
66
+ if (i === len - 1) {
67
+ tempMiddleware[key] = require(file)(app);
68
+ } else {
69
+ // 不是最后一层,创建嵌套对象 假设 key为user 则tempMiddleware={user:{}} 也就是则tempMiddleware.user
70
+ if (!tempMiddleware[key]) {
71
+ tempMiddleware[key] = {};
72
+ }
73
+ // tempMiddleware就变为tempMiddleware.user ={}
74
+ tempMiddleware = tempMiddleware[key];
75
+ }
76
+ /**
77
+ * 第二层:key为app 则tempMiddleware={ user: { app: { } } } 也就是tempMiddleware.user.app
78
+ * 依次循环
79
+ */
80
+ }
81
+ }
82
+ // 4. 挂载 不能使用middleware因为koa内置已经有middleware
83
+ app.middlewares = middlewares;
84
+ };
@@ -0,0 +1,56 @@
1
+ const path = require("path");
2
+ const glob = require("glob");
3
+ const { sep } = path;
4
+ /**
5
+ * router-schema loader
6
+ * @param {object} app Koa实例
7
+ *
8
+ *
9
+ * 通过 'json-schema & ajv' 对API规则进行约束,配合api-params-verify中间件使用
10
+ * --- json-schema 是定义接口,接受什么参数、参数哪些是必传的,参数类型是什么,参数范围是什么
11
+ * --- ajv 是校验json-schema
12
+ *
13
+ * app/router-schema/**.js
14
+ *
15
+ * 输出:
16
+ * app.routerScheam = {
17
+ * `${api1}}`: ${jsonSchema},
18
+ * `${api2}}`: ${jsonSchema},
19
+ * `${api3}}`: ${jsonSchema},
20
+ * `${api4}}`: ${jsonSchema}
21
+ * }
22
+ */
23
+ module.exports = (app) => {
24
+ let routerSchema = {};
25
+ // 读取 elpis/app/router-schema/**/**.js所有文件
26
+ const elpisRouterSchemaPath = path.resolve(
27
+ __dirname,
28
+ `..${sep}..${sep}app${sep}router-schema`,
29
+ );
30
+ const elpisFileList = glob.sync(
31
+ path.resolve(elpisRouterSchemaPath, `.${sep}**${sep}**.js`),
32
+ );
33
+ elpisFileList.forEach((file) => {
34
+ handleFile(file);
35
+ });
36
+
37
+ // 读取 业务/app/router-schema/**/**.js所有文件
38
+ const businessRouterSchemaPath = path.resolve(
39
+ app.businessPath,
40
+ `.${sep}router-schema`,
41
+ );
42
+ const businessFileList = glob.sync(
43
+ path.resolve(businessRouterSchemaPath, `.${sep}**${sep}**.js`),
44
+ );
45
+ businessFileList.forEach((file) => {
46
+ handleFile(file);
47
+ });
48
+ // 注册所有 routerSchema,使得可以 'app.routerSchema’ 这样访问
49
+
50
+ function handleFile(file) {
51
+ // 因为每个接口路径不一样,所以通过扩展运算符的形式,将router-schema下的文件中的数据进行合并
52
+ routerSchema = { ...routerSchema, ...require(path.resolve(file)) };
53
+ }
54
+
55
+ app.routerSchema = routerSchema;
56
+ };
@@ -0,0 +1,50 @@
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 {*} app Koa实例
9
+ * 解析所有 app/router/ 下所有 js 文件,加载到 KoaRouter 下
10
+ */
11
+ module.exports = (app) => {
12
+ const router = new KoaRouter();
13
+
14
+ // 找到 elpis 路由文件路径
15
+ const elpisRouterPath = path.resolve(
16
+ __dirname,
17
+ `..${sep}..${sep}app${sep}router`,
18
+ );
19
+ // 注册所有 elpis 路由
20
+ const elpisFileList = glob.sync(
21
+ path.resolve(elpisRouterPath, `.${sep}**${sep}**.js`),
22
+ );
23
+ elpisFileList.forEach((file) => {
24
+ require(path.resolve(file))(app, router);
25
+ });
26
+
27
+ // 找到业务路由文件路径
28
+ const businessRouterPath = path.resolve(app.businessPath, `.${sep}router`);
29
+
30
+ // 注册所有业务路由
31
+ const businessFileList = glob.sync(
32
+ path.resolve(businessRouterPath, `.${sep}**${sep}**.js`),
33
+ );
34
+ businessFileList.forEach((file) => {
35
+ require(path.resolve(file))(app, router);
36
+ });
37
+
38
+
39
+ // 4. 路由兜底
40
+ router.get("*", async (ctx, next) => {
41
+ console.log("默认传递重定向的路由地址", app?.options?.homePage);
42
+
43
+ ctx.status = 302; // 临时重定向
44
+ ctx.redirect(`${app?.options?.homePage ?? "/"}`);
45
+ });
46
+
47
+ // 5. 路由注册到 app 上
48
+ app.use(router.routes());
49
+ app.use(router.allowedMethods());
50
+ };
@@ -0,0 +1,85 @@
1
+ const path = require("path");
2
+ const glob = require("glob");
3
+ const { sep } = path;
4
+ /**
5
+ * service loader
6
+ * @param {object} app Koa实例
7
+ *
8
+ * 加载所有service , 可通过'app.service.${目录}.${文件}' 访问
9
+ * 例子
10
+ * app/service
11
+ * |
12
+ * |-- custom-module
13
+ * |
14
+ * |-- custom-service.js
15
+ * ====> app.service.customModule.customService
16
+ *
17
+ */
18
+ module.exports = (app) => {
19
+ const service = {};
20
+
21
+ // 读取 app/service/**/**.js所有文件
22
+ const elpisServicePath = path.resolve(
23
+ __dirname,
24
+ `..${sep}..${sep}app${sep}service`,
25
+ );
26
+ // 遍历所有js文件
27
+ const elpisFileList = glob.sync(
28
+ path.resolve(elpisServicePath, `.${sep}**${sep}**.js`),
29
+ );
30
+ // 遍历所有文件目录,把内容加载到 app.service 下
31
+ elpisFileList.forEach((file) => {
32
+ handleFile(file);
33
+ });
34
+
35
+ // 读取 app/service/**/**.js所有文件
36
+ const businessServicePath = path.resolve(app.businessPath, `.${sep}service`);
37
+ // 遍历所有js文件
38
+ const businessFileList = glob.sync(
39
+ path.resolve(businessServicePath, `.${sep}**${sep}**.js`),
40
+ );
41
+ // 遍历所有文件目录,把内容加载到 app.service 下
42
+ businessFileList.forEach((file) => {
43
+ handleFile(file);
44
+ });
45
+
46
+ function handleFile(file) {
47
+ // 提取文件名称
48
+ let name = path.resolve(file);
49
+
50
+ // 截取路径 app/service/custom-module/custom-service.js =》custom-module/custom-service
51
+ name = name.substring(
52
+ name.lastIndexOf(`service${sep}`) + `service${sep}`.length,
53
+ name.lastIndexOf("."),
54
+ );
55
+
56
+ // 把 - 统一改为驼峰式
57
+ name = name.replace(/[_-][a-z]/gi, (s) => s.substring(1).toUpperCase());
58
+
59
+ // 根据文件夹构建嵌套对象
60
+ let tempService = service;
61
+
62
+ // 分割/ 过滤空字符串
63
+ const names = name.split(sep).filter(Boolean);
64
+ for (let i = 0, len = names.length; i < len; i++) {
65
+ const key = names[i];
66
+ // 最后一层,挂载中间件函数
67
+ if (i === len - 1) {
68
+ /**
69
+ * service返回的是一个构造对象(), 文件名作为键名,值为构造对象实例
70
+ */
71
+ const ServiceModule = require(file)(app);
72
+ // 存入的类型就是键值对,键为文件名,值为构造对象 例如:project: ProjectService{}
73
+ tempService[key] = new ServiceModule();
74
+ } else {
75
+ // 不是最后一层,创建嵌套对象 假设 key为user tempService={user:{}} 也就是则tempService=.user
76
+ if (!tempService[key]) {
77
+ tempService[key] = {};
78
+ }
79
+ tempService = tempService[key];
80
+ }
81
+ }
82
+ }
83
+
84
+ app.service = service;
85
+ };
package/index.js ADDED
@@ -0,0 +1,38 @@
1
+ // 引入模块
2
+ const ElpisCore = require("./elpis-core");
3
+
4
+ // 引入前端工程化构建方法
5
+ const FEBuildDev = require("./app/webpack/dev.js");
6
+ const FEBuildProd = require("./app/webpack/prod.js");
7
+
8
+ module.exports = {
9
+ /**
10
+ * 服务端基础
11
+ */
12
+ Controller: {
13
+ Base: require("./app/controller/base.js"),
14
+ },
15
+ Service: {
16
+ Base: require("./app/service/base.js"),
17
+ },
18
+ /**
19
+ * 编译构建前端工程
20
+ * @param {} env 环境变量 local/prod
21
+ */
22
+ frontendBuild(env) {
23
+ if (env === "local") {
24
+ FEBuildDev();
25
+ } else if (env === "prod") {
26
+ FEBuildProd();
27
+ }
28
+ },
29
+ /**
30
+ * 启动 elpis
31
+ * @param {Object} options 项目配置,透传到 elpis-core
32
+ * @returns
33
+ */
34
+ serverStart(options = {}) {
35
+ const app = ElpisCore.start(options);
36
+ return app;
37
+ },
38
+ };