chanjs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.MD ADDED
@@ -0,0 +1,52 @@
1
+ # <center>Chan.js mvc框架</center>
2
+
3
+ Chan.js 基于express 纯js研发的轻量级mvc框架。基于函数式编程思想,性能优越,代码清晰,流程易读,可持续维护高。
4
+
5
+ ## 特性
6
+
7
+ - 基于express
8
+ - 支持es6语法
9
+ - 模块化
10
+ - 支持多模块路由
11
+ - 支持多模块视图
12
+ - 支持多模块控制器
13
+ - 支持多模块服务
14
+ - 插件化
15
+ - 轻量级(核心代码300行内)
16
+ - 长期维护
17
+
18
+ ## 规范 遵循约定优于配置
19
+
20
+ ```code
21
+ |- app
22
+ |- config 配置
23
+ |- module 模块1
24
+ |- module1 模块1
25
+ |- controller 控制器
26
+ |- service 服务模型
27
+ |- view 视图模板
28
+ |- router.js 路由
29
+ |- module2 模块2
30
+ |- controller 控制器
31
+ |- service 服务模型
32
+ |- view 视图模板
33
+ |- router.js路由
34
+ |- extend 扩展
35
+ |- middleware 中间件
36
+ |- plugin 插件
37
+ |- public 静态文件
38
+ |- index.js
39
+ ```
40
+
41
+ ### 初始化流程
42
+
43
+ - 初始化
44
+ - 加载配置
45
+ - 加载模块
46
+ - 加载service
47
+ - 加载controller
48
+ - 加载router
49
+ - 加载extend
50
+ - 加载plugin
51
+ - beforeStart() 挂在从数据库获取的配置合并到配置文件中
52
+ - run() 启动服务
package/chan.js ADDED
@@ -0,0 +1,162 @@
1
+ const express = require("express");
2
+ const config = require("./lib/config/config.js");
3
+ const path = require("path");
4
+ const fs = require("fs");
5
+
6
+ /**
7
+ * @description chanjs
8
+ */
9
+ class Chan {
10
+ constructor(options={}) {
11
+
12
+ //加载全局对象
13
+ this.config = Object.assign(config, options);
14
+ //配置
15
+ Chan.config = this.config;
16
+ //模块
17
+ Chan.modules = this.modules = {};
18
+ //帮助文档
19
+ Chan.helper = this.helper = {};
20
+
21
+ this.app = express();
22
+ this.router = express.Router();
23
+
24
+ this.loadConfig();
25
+ this.beforeStart();
26
+ this.init();
27
+ }
28
+
29
+ // 加载配置
30
+ loadConfig() {
31
+ const configPath = path.join(config.APP_PATH, "config/index.js");
32
+ if (fs.existsSync(configPath)) {
33
+ const config = require(configPath);
34
+ Object.assign(this.config, config);
35
+ }
36
+
37
+ console.log("config——>配置文件加载完成");
38
+ }
39
+
40
+ //启动加载
41
+ beforeStart(cb) {
42
+ // 初始化一些配置
43
+ console.log("beforeStart--->初始化一些配置");
44
+ cb && cb();
45
+ }
46
+
47
+ init() {
48
+ this.loadModules();
49
+ this.loadExtends();
50
+ this.loadPlusins();
51
+
52
+ }
53
+
54
+ loadModules() {
55
+ const configPath = path.join(config.APP_PATH, "module");
56
+ if (fs.existsSync(configPath)) {
57
+ const dirs = fs
58
+ .readdirSync(configPath, { withFileTypes: true })
59
+ .filter((dirent) => dirent.isDirectory())
60
+ .map((dirent) => dirent.name)
61
+ .forEach((item, index) => {
62
+ this.modules[item] = {
63
+ controller: {},
64
+ service: {},
65
+ };
66
+ this.loadModule(item);
67
+ });
68
+ //执行路由
69
+ this.app.use(this.router);
70
+ }
71
+ }
72
+
73
+ // 加载插件
74
+ loadPlugins() {
75
+ const configPath = path.join(config.APP_PATH, "plugin");
76
+ if (fs.existsSync(configPath)) {
77
+ const dirs = fs
78
+ .readdirSync(configPath, { withFileTypes: true })
79
+ .filter((dirent) => dirent.isDirectory())
80
+ .map((dirent) => dirent.name);
81
+ this.plugins = dirs;
82
+ } else {
83
+ this.plugins = [];
84
+ }
85
+ }
86
+
87
+ loadModule(moduleName) {
88
+ const moduleDir = path.join(config.APP_PATH, "module", moduleName);
89
+ this.loadServices(moduleDir,moduleName);
90
+ this.loadControllers(moduleDir,moduleName);
91
+ this.loadRoutes(moduleDir,moduleName);
92
+ }
93
+
94
+ // 加载服务
95
+ loadServices(moduleDir,moduleName) {
96
+ const servicesDir = path.join(moduleDir, "service");
97
+ if (fs.existsSync(servicesDir)) {
98
+ let services = fs
99
+ .readdirSync(servicesDir)
100
+ .filter((file) => file.endsWith(".js"));
101
+ for (let i = 0, file = services[i]; i < services.length; i++) {
102
+ const Service = require(path.join(servicesDir, file));
103
+ const serviceName = file.replace(".js", "");
104
+ this.modules[moduleName].service[serviceName] = {};
105
+ this.modules[moduleName].service[serviceName] = Service;
106
+ }
107
+ }
108
+ }
109
+
110
+ // 加载控制器
111
+ loadControllers(moduleDir,moduleName) {
112
+ const controllersDir = path.join(moduleDir, "controller");
113
+ if (fs.existsSync(controllersDir)) {
114
+ let controllers = fs
115
+ .readdirSync(controllersDir)
116
+ .filter((file) => file.endsWith(".js"));
117
+ for (let i = 0, file = controllers[i]; i < controllers.length; i++) {
118
+ const controller = require(path.join(controllersDir, file));
119
+ const controllerName = file.replace(".js", "");
120
+ this.modules[moduleName].controller[controllerName] = {};
121
+ this.modules[moduleName].controller[controllerName] = controller;
122
+ }
123
+ }
124
+ }
125
+
126
+ // 加载路由
127
+ loadRoutes(moduleDir,moduleName) {
128
+ const routersDir = path.join(moduleDir, "router.js");
129
+ if (fs.existsSync(routersDir)) {
130
+ const routes = require(routersDir);
131
+ routes({router:this.router,controller:this.modules[moduleName].controller});
132
+ }
133
+ }
134
+
135
+ // 加载扩展
136
+ loadExtends() {
137
+ const extendPath = path.join(config.APP_PATH, "extend");
138
+ if (fs.existsSync(extendPath)) {
139
+ let controllers = fs
140
+ .readdirSync(extendPath)
141
+ .filter((file) => file.endsWith(".js"));
142
+ for (let i = 0, file = controllers[i]; i < controllers.length; i++) {
143
+ const helper = require(path.join(extendPath, file));
144
+ const fileName = file.replace(".js", "");
145
+ this.helper[fileName] = helper;
146
+ }
147
+ }
148
+ }
149
+
150
+ loadPlusins() {
151
+ // 加载插件
152
+ }
153
+
154
+ run(port) {
155
+ this.app.listen(port, () => {
156
+ console.log(`Server is running on port ${port}`);
157
+ });
158
+ }
159
+ }
160
+
161
+
162
+ module.exports = Chan;
package/lib/base.js ADDED
@@ -0,0 +1,8 @@
1
+ class Base{
2
+ constructor(config){
3
+ this.config = config;
4
+ }
5
+ log(...args){
6
+ console.log(...args);
7
+ }
8
+ }
@@ -0,0 +1,18 @@
1
+ const path = require('path');
2
+
3
+ /**
4
+ * @description 根目录
5
+ */
6
+ const ROOT_PATH = process.cwd();
7
+
8
+ /**
9
+ * @description 程序目录
10
+ */
11
+ const APP_PATH = path.join(ROOT_PATH, 'app');
12
+
13
+ module.exports = {
14
+ ROOT_PATH,
15
+ APP_PATH,
16
+ }
17
+
18
+
@@ -0,0 +1,9 @@
1
+ class Base{
2
+ constructor(config){
3
+ this.config = config;
4
+ }
5
+
6
+ log(...args){
7
+ console.log(...args);
8
+ }
9
+ }
@@ -0,0 +1,217 @@
1
+
2
+ /**
3
+ * extend controller
4
+ */
5
+ module.exports = {
6
+ /**
7
+ * body getter
8
+ */
9
+ get body() {
10
+
11
+ },
12
+ /**
13
+ * body setter
14
+ */
15
+ set body(value) {
16
+
17
+ },
18
+ /**
19
+ * get client ip
20
+ */
21
+ get ip() {
22
+
23
+ },
24
+ /**
25
+ * get client ips
26
+ */
27
+ get ips() {
28
+
29
+ },
30
+ /**
31
+ * get status code
32
+ */
33
+ get status() {
34
+
35
+ },
36
+ /**
37
+ * set status code
38
+ */
39
+ set status(status) {
40
+
41
+ },
42
+ /**
43
+ * get content type
44
+ */
45
+ get type() {
46
+
47
+ },
48
+ /**
49
+ * set content type
50
+ */
51
+ set type(contentType) {
52
+
53
+ },
54
+ /**
55
+ * get userAgent header
56
+ */
57
+ get userAgent() {
58
+
59
+ },
60
+ /**
61
+ * get request method
62
+ */
63
+ get method() {
64
+
65
+ },
66
+ /**
67
+ * is get method
68
+ */
69
+ get isGet() {
70
+
71
+ },
72
+ /**
73
+ * is post method
74
+ */
75
+ get isPost() {
76
+
77
+ },
78
+ /**
79
+ * is command line invoke
80
+ */
81
+ get isCli() {
82
+
83
+ },
84
+ /**
85
+ * get or set config
86
+ * @param {String} name
87
+ * @param {Mix} value
88
+ * @param {String} m
89
+ */
90
+ config(name, value, m ) {
91
+
92
+ },
93
+ /**
94
+ * is method
95
+ * @param {String} method
96
+ */
97
+ isMethod(method) {
98
+
99
+ },
100
+ /**
101
+ * check if is ajax request
102
+ * @param {String} method
103
+ */
104
+ isAjax(method) {
105
+
106
+ },
107
+ /**
108
+ * is jsonp request
109
+ * @param {String} callback
110
+ */
111
+ isJsonp(callbackField) {
112
+
113
+ },
114
+ /**
115
+ * send jsonp data
116
+ */
117
+ jsonp(data, callbackField) {
118
+
119
+ },
120
+ /**
121
+ * send json data
122
+ */
123
+ json(data) {
124
+
125
+ },
126
+ /**
127
+ * send success data
128
+ */
129
+ success(data, message) {
130
+
131
+ },
132
+ /**
133
+ * send fail data
134
+ */
135
+ fail(errno, errmsg, data) {
136
+
137
+ },
138
+ /**
139
+ * set expires header
140
+ * @param {Number} time
141
+ */
142
+ expires(time) {
143
+
144
+ },
145
+ /**
146
+ * get query data
147
+ * @param {String} name
148
+ * @param {Mixed} value
149
+ */
150
+ get(name, value) {
151
+
152
+ },
153
+ /**
154
+ * get query data
155
+ * @param {String} name
156
+ * @param {Mixed} value
157
+ */
158
+ query(name, value) {
159
+
160
+ },
161
+ /**
162
+ * get or set post data
163
+ * @param {String} name
164
+ * @param {Mixed} value
165
+ */
166
+ post(name, value) {
167
+
168
+ },
169
+ /**
170
+ * get or set file data
171
+ * @param {String} name
172
+ * @param {Mixed} value
173
+ */
174
+ file(name, value) {
175
+
176
+ },
177
+ /**
178
+ * get or set cookies
179
+ * @param {String} name
180
+ * @param {String} value
181
+ * @param {Object} options
182
+ */
183
+ cookie(name, value, options) {
184
+
185
+ },
186
+
187
+ /**
188
+ * get referer header
189
+ */
190
+ referrer(onlyHost) {
191
+
192
+ },
193
+ /**
194
+ * get referer header
195
+ */
196
+ referer(onlyHost) {
197
+
198
+ },
199
+ /**
200
+ * Perform a 302 redirect to `url`.
201
+ * @param {String} url
202
+ * @param {String} alt
203
+ */
204
+ redirect(url, alt) {
205
+
206
+ },
207
+
208
+
209
+ /**
210
+ * download
211
+ * @param {String} filepath
212
+ * @param {String} filename
213
+ */
214
+ download(filepath, filename) {
215
+
216
+ }
217
+ };
@@ -0,0 +1,135 @@
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;
@@ -0,0 +1,17 @@
1
+
2
+
3
+ module.exports = {
4
+ /**
5
+ * @description 给路由加前缀
6
+ * @returns viod 0
7
+ */
8
+ addRoutePrefix:()=>{
9
+ return function (req, res, next) {
10
+ req.baseUrl = `${prefix}${req.baseUrl || ''}`;
11
+ // 如果有 query 参数,则保留原有参数
12
+ req.url = `${req.baseUrl}${req.url.includes('?') ? req.url.split('?')[1] : ''}`;
13
+ next();
14
+ };
15
+ }
16
+ }
17
+
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "chanjs",
3
+ "version": "0.0.1",
4
+ "description": "Chan.js 基于express 纯js研发的轻量级mvc框架。基于函数式编程思想,性能优越,代码清晰,流程易读,可持续维护高。",
5
+ "main": "chan.js",
6
+ "directories": {
7
+ "lib": "lib"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "author": "明空",
13
+ "license": "ISC"
14
+ }