chanjs 1.0.27 → 1.0.28

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/core/chan.js CHANGED
@@ -1,50 +1,37 @@
1
1
  const express = require("express");
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const cors = require("cors");
2
5
  const config = require("./lib/config/config.js");
3
- const bindClass = require("./lib/extend/bindClass.js");
6
+ const {bindClass,createKnex,loadWebToEnd} = require("./lib/extend/helper.js");
4
7
  const Controller = require("./lib/controller/controller.js");
5
8
  const Service = require("./lib/service/service.js");
6
- const path = require("path");
7
- const fs = require("fs");
8
9
  const core = require("./lib/index.js");
9
- const cors = require("cors");
10
-
11
10
  /**
12
11
  * @description 基于express封装的mvc框架,遵循约定优于配置原则
13
12
  */
14
13
  class Chan {
15
- static config = {};
16
- //模块
14
+ static helper = {};
17
15
  static modules = {};
18
- //插件
19
16
  static plugins = {};
20
- //工具
21
- static helper = {};
22
- static Controller = null;
23
- static Service = null;
24
- constructor(options = {}) {
25
- //配置
26
- Chan.config = { ...config, ...options };
27
- //控制器基类
28
- Chan.Controller = Controller;
17
+ static config = config;
18
+ static Controller = Controller;
19
+ static Service = Service;
20
+ constructor() {
29
21
  this.init();
30
22
  }
31
23
 
32
24
  init() {
33
25
  this.app = express();
34
26
  this.router = express.Router();
35
- //加载配置
36
27
  this.loadConfig();
37
- //加载扩展
38
28
  this.loadExtends();
39
29
  //加载核心(日志、favicon 图标、cookie、json、url、模板引擎、静态资源)
40
30
  this.loadCore();
41
- //加载实例化数据库
42
31
  this.loadKnex();
43
- //解决跨域
44
32
  this.loadCors();
45
33
  }
46
34
 
47
- // 加载配置
48
35
  loadConfig() {
49
36
  const configPath = path.join(Chan.config.APP_PATH, "config/index.js");
50
37
  if (fs.existsSync(configPath)) {
@@ -53,7 +40,6 @@ class Chan {
53
40
  }
54
41
  }
55
42
 
56
- // 加载扩展
57
43
  loadExtends() {
58
44
  const extendPath = path.join(Chan.config.APP_PATH, "extend");
59
45
  if (fs.existsSync(extendPath)) {
@@ -69,65 +55,35 @@ class Chan {
69
55
  }
70
56
  }
71
57
 
58
+ /**
59
+ * @description app核心模块:日志、favicon 图标、cookie、json、url、模板引擎、静态资源
60
+ */
61
+ loadCore() {
62
+ core(this.app, Chan.config);
63
+ }
64
+
72
65
  //数据库操作
73
66
  loadKnex() {
74
- // 连接数据库
75
- const {
76
- host = "localhost",
77
- port = "3306",
78
- user,
79
- password,
80
- database,
81
- client = "mysql2",
82
- charset = "utf8mb4",
83
- } = Chan.config.database;
84
-
85
- const knex = require("knex")({
86
- client: client,
87
- connection: {
88
- host,
89
- port,
90
- user,
91
- password,
92
- database,
93
- charset,
94
- },
95
- debug: Chan.config.SqlDebug, //指明是否开启debug模式,默认为true表示开启
96
- pool: {
97
- //指明数据库连接池的大小,默认为{min: 2, max: 10}
98
- min: 0,
99
- max: 2,
100
- },
101
- log: {
102
- warn(message) {
103
- console.error("[knex warn]", message);
104
- },
105
- error(message) {
106
- console.error("[knex error]", message);
107
- },
108
- },
109
- });
110
-
111
- //数据库操作实例
112
- Chan.knex = knex;
113
- //数据库操作基类
114
- Chan.Service = Service(knex);
67
+ if(Chan.config?.db?.length > 0){
68
+ Chan.config.db.map((item,index) => {
69
+ if(index ==0){
70
+ Chan.knex = createKnex(item);
71
+ }else{
72
+ Chan[`knex${index}`] = createKnex(item);
73
+ }
74
+ })
75
+ }
115
76
  }
116
77
 
117
78
  //开始启动
118
79
  beforeStart(cb) {
119
-
120
80
  cb && cb();
121
81
  }
122
82
  //启动
123
83
  start(cb) {
124
- //加载插件
125
84
  this.loadPlugins();
126
- //加载模块
127
85
  this.loadModules();
128
- //加载通用路由
129
86
  this.loadCommonRouter();
130
- // 初始化一些配置
131
87
  cb && cb();
132
88
  }
133
89
 
@@ -141,25 +97,15 @@ class Chan {
141
97
  this.loadModules("plugins");
142
98
  }
143
99
 
144
- /**
145
- * @description app核心模块:日志、favicon 图标、cookie、json、url、模板引擎、静态资源
146
- */
147
- loadCore() {
148
- core(this.app, Chan.config);
149
- }
150
-
151
100
  /**
152
101
  * @description 模块加载入口(路由&控制器& 服务)
153
102
  */
154
103
  loadModules(modules = "modules") {
155
104
  const configPath = path.join(Chan.config.APP_PATH, modules);
156
105
  if (fs.existsSync(configPath)) {
157
- const dirs = fs
158
- .readdirSync(configPath, { withFileTypes: true })
159
- .filter((dirent) => dirent.isDirectory())
160
- .map((dirent) => dirent.name);
106
+ //模块名称
107
+ const dirs = loadWebToEnd(Chan.config[modules]);
161
108
  Chan[modules] = {};
162
-
163
109
  // 先加载所有服务
164
110
  dirs.forEach((item) => {
165
111
  Chan[modules][item] = {
@@ -173,9 +119,6 @@ class Chan {
173
119
  dirs.forEach((item) => {
174
120
  this.loadModule(modules, item);
175
121
  });
176
-
177
- //执行路由
178
- // this.app.use(this.router);
179
122
  }
180
123
  }
181
124
 
@@ -209,8 +152,7 @@ class Chan {
209
152
  const Service = require(path.join(servicesDir, file));
210
153
  const serviceName = file.replace(".js", "");
211
154
  //模块文件夹-模块文件名-服务-方法
212
- Chan[modules][moduleName].service[serviceName] = {};
213
- Chan[modules][moduleName].service[serviceName] = bindClass(Service);
155
+ Chan[modules][moduleName].service[serviceName] = {...bindClass(Service)};
214
156
  }
215
157
  }
216
158
  }
@@ -235,9 +177,7 @@ class Chan {
235
177
  file = controllers[i];
236
178
  const controller = require(path.join(controllersDir, file));
237
179
  const controllerName = file.replace(".js", "");
238
- Chan[modules][moduleName].controller[controllerName] = {};
239
- Chan[modules][moduleName].controller[controllerName] =
240
- bindClass(controller);
180
+ Chan[modules][moduleName].controller[controllerName] = {...bindClass(controller)};
241
181
  }
242
182
  }
243
183
  }
@@ -0,0 +1,78 @@
1
+ const knex = require('knex');
2
+
3
+ /**
4
+ * @description 实例化一个类,并将该类的所有方法绑定到一个新的对象上。
5
+ * @param {Function} className - 需要实例化的类。
6
+ *@returns {Object} 包含绑定方法的对象。
7
+ */
8
+ function bindClass(className) {
9
+ let obj = {};
10
+ const cls = new className();
11
+ Object.getOwnPropertyNames(cls.constructor.prototype).forEach(
12
+ (methodName) => {
13
+ if (
14
+ methodName !== "constructor" &&
15
+ typeof cls[methodName] === "function"
16
+ ) {
17
+ obj[methodName] = cls[methodName].bind(cls);
18
+ }
19
+ }
20
+ );
21
+ return obj;
22
+ }
23
+
24
+
25
+ function createKnex(opt) {
26
+ let config = {
27
+ host:"localhost",
28
+ port:"3306",
29
+ client:"mysql2",
30
+ charset:"utf8mb4",
31
+ debug:false,
32
+ ...opt
33
+ };
34
+ return knex({
35
+ client: config.client,
36
+ connection: {
37
+ host:config.host,
38
+ port:config.port,
39
+ user:config.user,
40
+ password:config.password,
41
+ database:config.database,
42
+ charset:config.charset,
43
+ },
44
+ debug: config.debug,
45
+ //默认为{min: 2, max: 10}
46
+ pool: {
47
+ min: 0,
48
+ max: 2,
49
+ },
50
+ log: {
51
+ warn(message) {
52
+ console.error("[knex warn]", message);
53
+ },
54
+ error(message) {
55
+ console.error("[knex error]", message);
56
+ },
57
+ },
58
+ });
59
+ }
60
+ /**
61
+ *
62
+ * @param {*} module 模块目录
63
+ * @returns Array
64
+ * @description 将web模块放到最后加载
65
+ */
66
+ function loadWebToEnd(module=[]){
67
+ const index = module.indexOf('web');
68
+ if (index !== -1) {
69
+ const web = module.splice(index, 1);
70
+ module.push(web[0]);
71
+ }
72
+ return module;
73
+ }
74
+ module.exports = {
75
+ bindClass,
76
+ createKnex,
77
+ loadWebToEnd
78
+ };
@@ -19,6 +19,7 @@ template.defaults.imports.dateFormat = function (date, format) {
19
19
  }
20
20
  return date.format(format);
21
21
  };
22
+
22
23
  module.exports = (app, config) => {
23
24
  const { APP_PATH, views, env } = config;
24
25
  //默认home view
@@ -187,8 +187,4 @@ class BaseService {
187
187
  }
188
188
  }
189
189
 
190
- const Service = (knex, model = "") => {
191
- return new BaseService(knex, model);
192
- };
193
-
194
- module.exports = Service;
190
+ module.exports = BaseService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chanjs",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "chanjs基于express 纯js研发的轻量级mvc框架。",
5
5
  "main": "core/chan.js",
6
6
  "module": "core/chan.js",
@@ -1,22 +0,0 @@
1
- /**
2
- * @description 实例化一个类,并将该类的所有方法绑定到一个新的对象上。
3
- * @param {Function} className - 需要实例化的类。
4
- *@returns {Object} 包含绑定方法的对象。
5
- */
6
- function bindClass(className) {
7
- let obj = {};
8
- const cls = new className();
9
- Object.getOwnPropertyNames(cls.constructor.prototype).forEach(
10
- (methodName) => {
11
- if (
12
- methodName !== "constructor" &&
13
- typeof cls[methodName] === "function"
14
- ) {
15
- obj[methodName] = cls[methodName].bind(cls);
16
- }
17
- }
18
- );
19
- return obj;
20
- }
21
-
22
- module.exports = bindClass;
@@ -1,16 +0,0 @@
1
- module.exports = {
2
- /**
3
- * @description 给路由加前缀
4
- * @returns viod 0
5
- */
6
- addRoutePrefix: () => {
7
- return function (req, res, next) {
8
- req.baseUrl = `${prefix}${req.baseUrl || ""}`;
9
- // 如果有 query 参数,则保留原有参数
10
- req.url = `${req.baseUrl}${
11
- req.url.includes("?") ? req.url.split("?")[1] : ""
12
- }`;
13
- next();
14
- };
15
- },
16
- };
@@ -1,135 +0,0 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
-
4
- /**
5
- * @description 是否存在
6
- * @param {*} dir 目录
7
- * @returns {Boolean} 返回true false
8
- */
9
- function isExist(dir) {
10
- let formatDir = path.normalize(dir);
11
- try {
12
- fs.accessSync(formatDir, fs.R_OK);
13
- return true;
14
- } catch (e) {
15
- return false;
16
- }
17
- }
18
-
19
- exports.isExist = isExist;
20
-
21
- /**
22
- * @description 是否是文件
23
- * @param {*} filePath
24
- * @returns {Boolean} true 是文件 false 不是文件
25
- */
26
- function isFile(filePath) {
27
- if (!isExist(filePath)) return false;
28
- try {
29
- const stat = fs.statSync(filePath);
30
- return stat.isFile();
31
- } catch (e) {
32
- return false;
33
- }
34
- }
35
- exports.isFile = isFile;
36
-
37
- /**
38
- * @description 是否是目录
39
- * @param {*} filePath
40
- * @returns {Boolean} 返回true false
41
- */
42
- function isDirectory(filePath) {
43
- if (!isExist(filePath)) return false;
44
- try {
45
- const stat = fs.statSync(filePath);
46
- return stat.isDirectory();
47
- } catch (e) {
48
- return false;
49
- }
50
- }
51
- exports.isDirectory = isDirectory;
52
-
53
- /**
54
- * @description 修改指定路径 `p` 的权限模式为给定的 `mode`。这是一个同步版本的文件权限更改方法
55
- * 如果成功修改权限,则返回 `true`,否则在发生错误时捕获异常并返回 `false`。
56
- * @param {String} p - 要更改权限的文件或目录的绝对路径。
57
- * @param {String|Number} mode - 指定的新权限模式,可以是八进制数字表示(如0o755)或字符串形式(如"755")
58
- * @return {Boolean} - 根据操作是否成功,返回 `true` 表示成功,`false` 表示失败。
59
- */
60
- function chmod(p, mode) {
61
- try {
62
- fs.chmodSync(p, mode);
63
- return true;
64
- } catch (e) {
65
- return false;
66
- }
67
- }
68
- exports.chmod = chmod;
69
-
70
- /**
71
- * @function mkdir
72
- * @description 递归创建目录
73
- * @param {string} dir - 要创建的目录路径。
74
- * @param {string|number} - 默认为 0o777。可以是八进制数字表示或字符串形式。
75
- * @returns {boolean} - 返回 `true` 表示成功,`false` 表示失败。
76
- */
77
- function mkdir(dir, mode) {
78
- if (isExist(dir)) {
79
- if (mode) return chmod(dir, mode);
80
- return true;
81
- }
82
- const pp = path.dirname(dir);
83
- if (isExist(pp)) {
84
- try {
85
- fs.mkdirSync(dir, mode);
86
- return true;
87
- } catch (e) {
88
- return false;
89
- }
90
- }
91
- if (mkdir(pp, mode)) return mkdir(dir, mode);
92
- return false;
93
- }
94
- exports.mkdir = mkdir;
95
-
96
- function getdirFiles(dir, prefix = "") {
97
- dir = path.normalize(dir);
98
- if (!fs.existsSync(dir)) return [];
99
- const files = fs.readdirSync(dir);
100
- let result = [];
101
- files.forEach((item) => {
102
- const currentDir = path.join(dir, item);
103
- const stat = fs.statSync(currentDir);
104
- if (stat.isFile()) {
105
- result.push(path.join(prefix, item));
106
- } else if (stat.isDirectory()) {
107
- const cFiles = getdirFiles(currentDir, path.join(prefix, item));
108
- result = result.concat(cFiles);
109
- }
110
- });
111
- return result;
112
- }
113
-
114
- exports.getdirFiles = getdirFiles;
115
-
116
- /**
117
- * remove dir aync
118
- * @param {String} p [path]
119
- * @param {Boolean} reserve []
120
- * @return {Promise} []
121
- */
122
- function rmdir(p, reserve) {
123
- if (!isDirectory(p)) return Promise.resolve();
124
- return fsReaddir(p).then((files) => {
125
- const promises = files.map((item) => {
126
- const filepath = path.join(p, item);
127
- if (isDirectory(filepath)) return rmdir(filepath, false);
128
- return fsUnlink(filepath);
129
- });
130
- return Promise.all(promises).then(() => {
131
- if (!reserve) return fsRmdir(p);
132
- });
133
- });
134
- }
135
- exports.rmdir = rmdir;