chanjs 2.3.1 → 2.5.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.
- package/App.js +41 -42
- package/base/Controller.js +5 -110
- package/base/Database.js +1 -232
- package/base/Service.js +2 -35
- package/global/import.js +1 -5
- package/helper/index.js +0 -2
- package/index.js +0 -1
- package/middleware/index.js +0 -1
- package/middleware/template.js +2 -1
- package/middleware/waf.js +34 -6
- package/package.json +1 -1
- package/utils/index.js +1 -3
- package/utils/keywords.js +8 -2
- package/utils/response.js +87 -10
- package/base/Context.js +0 -78
- package/helper/db.js +0 -79
- package/middleware/preventRetry.js +0 -30
- package/middleware/validator.js +0 -43
- package/utils/error-handler.js +0 -115
- package/utils/error.js +0 -81
package/App.js
CHANGED
|
@@ -2,18 +2,18 @@ import express from "express";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// 引入基础组件
|
|
6
6
|
import Controller from "./base/Controller.js";
|
|
7
|
-
import DatabaseManager from "./base/Database.js";
|
|
8
|
-
|
|
9
7
|
import Service from "./base/Service.js";
|
|
8
|
+
import DatabaseManager from "./base/Database.js";
|
|
10
9
|
|
|
10
|
+
// 引入配置和工具
|
|
11
11
|
import { Paths } from "./config/index.js";
|
|
12
12
|
import { getChildrenId, filterBody, filterImgFromStr, CODE as commonCode, sendMail, genRegEmailHtml, genResetPasswordEmail, pages, getHtmlFilesSync } from "./common/index.js";
|
|
13
|
-
import {
|
|
13
|
+
import { loadConfig, loadController, loaderSort, formatDateFields, request, delImg, getIp, setToken, getToken, verifyToken, generateToken, getFileTree, readFileContent, saveFileContent, isPathSafe, arrToObj, htmlDecode } from "./helper/index.js";
|
|
14
14
|
import { Cors, setBody, setCookie, setFavicon, setHeader, setStatic, setTemplate, waf } from "./middleware/index.js";
|
|
15
|
-
import { errorResponse, notFoundResponse, parseDatabaseError } from "./utils/
|
|
16
|
-
import {
|
|
15
|
+
import { errorResponse, notFoundResponse, parseDatabaseError, error as responseError, fail, success, checkKeywords } from "./utils/index.js";
|
|
16
|
+
import { importFile, importjs } from "./global/import.js";
|
|
17
17
|
|
|
18
18
|
import "./global/index.js";
|
|
19
19
|
|
|
@@ -22,14 +22,14 @@ import "./global/index.js";
|
|
|
22
22
|
* @class Chan
|
|
23
23
|
* @description 管理应用程序的路由、中间件、数据库连接和服务
|
|
24
24
|
* @example
|
|
25
|
-
* const app = new Chan(
|
|
25
|
+
* const app = new Chan();
|
|
26
26
|
* await app.start();
|
|
27
27
|
*/
|
|
28
28
|
class Chan {
|
|
29
|
+
|
|
30
|
+
// 静态属性:提供全局访问的辅助函数和工具
|
|
29
31
|
static helper = {
|
|
30
32
|
loadController,
|
|
31
|
-
db,
|
|
32
|
-
prefixDbConfig,
|
|
33
33
|
loaderSort,
|
|
34
34
|
loadConfig,
|
|
35
35
|
formatDateFields,
|
|
@@ -47,6 +47,8 @@ class Chan {
|
|
|
47
47
|
arrToObj,
|
|
48
48
|
htmlDecode,
|
|
49
49
|
};
|
|
50
|
+
|
|
51
|
+
// 静态属性:提供全局访问的常用业务函数和工具
|
|
50
52
|
static common = {
|
|
51
53
|
success,
|
|
52
54
|
fail,
|
|
@@ -61,31 +63,35 @@ class Chan {
|
|
|
61
63
|
filterBody,
|
|
62
64
|
filterImgFromStr,
|
|
63
65
|
};
|
|
66
|
+
|
|
67
|
+
// 静态属性:提供全局访问的配置
|
|
64
68
|
static config = {};
|
|
69
|
+
// 静态属性:提供全局访问的数据库
|
|
70
|
+
static db = {};
|
|
71
|
+
// 静态属性:提供全局访问的服务类
|
|
65
72
|
static Service = Service;
|
|
73
|
+
// 静态属性:提供全局访问的控制器类
|
|
66
74
|
static Controller = Controller;
|
|
75
|
+
// 静态属性:提供全局访问的路径配置
|
|
67
76
|
static paths = Paths;
|
|
77
|
+
// 静态属性:提供全局访问的导入函数
|
|
78
|
+
static importFile = importFile;
|
|
79
|
+
static importjs = importjs;
|
|
80
|
+
// 静态属性:提供全局访问的工具函数
|
|
81
|
+
static utils = {
|
|
82
|
+
checkKeywords,
|
|
83
|
+
};
|
|
68
84
|
|
|
69
85
|
/**
|
|
70
86
|
* 构造函数
|
|
71
87
|
* @constructor
|
|
72
|
-
* @param {Object} options - 应用配置选项
|
|
73
|
-
* @param {number} [options.port=3000] - 服务器端口
|
|
74
|
-
* @param {string} [options.env] - 运行环境
|
|
75
88
|
* @description 初始化 Express 应用和核心组件
|
|
76
89
|
*/
|
|
77
|
-
constructor(
|
|
90
|
+
constructor() {
|
|
78
91
|
this.app = express();
|
|
79
|
-
|
|
92
|
+
// 数据库连接管理
|
|
80
93
|
this.dbManager = new DatabaseManager();
|
|
81
|
-
|
|
82
|
-
this.options = {
|
|
83
|
-
port: options.port || 3000,
|
|
84
|
-
env: options.env || process.env.NODE_ENV || "development",
|
|
85
|
-
...options,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
// 应用路由
|
|
89
95
|
this.router = express.Router();
|
|
90
96
|
}
|
|
91
97
|
|
|
@@ -97,10 +103,6 @@ class Chan {
|
|
|
97
103
|
* @returns {Promise<void>}
|
|
98
104
|
*/
|
|
99
105
|
async start() {
|
|
100
|
-
|
|
101
|
-
global.appContext = this.context;
|
|
102
|
-
global.Chan = Chan;
|
|
103
|
-
|
|
104
106
|
//加载配置
|
|
105
107
|
await this.config();
|
|
106
108
|
//加载数据库
|
|
@@ -117,19 +119,17 @@ class Chan {
|
|
|
117
119
|
this.useRouter();
|
|
118
120
|
//404 500 处理
|
|
119
121
|
this.setErrorHandler();
|
|
120
|
-
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
/**
|
|
124
125
|
* 加载配置
|
|
125
126
|
* @async
|
|
126
127
|
* @returns {Promise<void>}
|
|
127
|
-
* @description
|
|
128
|
+
* @description 加载应用配置并设置到全局变量
|
|
128
129
|
*/
|
|
129
130
|
async config() {
|
|
130
131
|
let config = await loadConfig();
|
|
131
132
|
Chan.config = config;
|
|
132
|
-
this.context.set("config", config);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/**
|
|
@@ -140,17 +140,15 @@ class Chan {
|
|
|
140
140
|
*/
|
|
141
141
|
async loadDB() {
|
|
142
142
|
const dbList = Chan.config?.db || [];
|
|
143
|
-
const connections = this.dbManager.getConnections();
|
|
144
143
|
|
|
145
144
|
for (const [index, item] of dbList.entries()) {
|
|
146
145
|
const key = item.key || String(index);
|
|
147
146
|
try {
|
|
148
|
-
const dbConfig =
|
|
147
|
+
const dbConfig = item;
|
|
149
148
|
if (!dbConfig) throw new Error("未找到配置");
|
|
150
149
|
|
|
151
150
|
const connection = this.dbManager.add(key, dbConfig, { isDefault: index === 0 });
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
|
|
154
152
|
if (index === 0) {
|
|
155
153
|
Chan.db = connection;
|
|
156
154
|
}
|
|
@@ -160,7 +158,7 @@ class Chan {
|
|
|
160
158
|
}
|
|
161
159
|
|
|
162
160
|
console.log(
|
|
163
|
-
`[DB] 初始化完成,已加载 ${dbList.length}
|
|
161
|
+
`[DB] 初始化完成,已加载 ${dbList.length} 个数据库`,
|
|
164
162
|
);
|
|
165
163
|
}
|
|
166
164
|
|
|
@@ -195,7 +193,7 @@ class Chan {
|
|
|
195
193
|
const files = fs.readdirSync(_path).filter((file) => file.endsWith(".js"));
|
|
196
194
|
for (const file of files) {
|
|
197
195
|
const filePath = path.join(_path, file);
|
|
198
|
-
let helperModule = await importFile(filePath);
|
|
196
|
+
let helperModule = await Chan.importFile(filePath);
|
|
199
197
|
Object.assign(Chan[key], helperModule);
|
|
200
198
|
}
|
|
201
199
|
}
|
|
@@ -221,7 +219,7 @@ class Chan {
|
|
|
221
219
|
PROXY = "false",
|
|
222
220
|
waf: wafConfig = { enabled: false }
|
|
223
221
|
} = config;
|
|
224
|
-
|
|
222
|
+
|
|
225
223
|
await waf(this.app, wafConfig);
|
|
226
224
|
setFavicon(this.app);
|
|
227
225
|
setStatic(this.app, statics);
|
|
@@ -239,7 +237,6 @@ class Chan {
|
|
|
239
237
|
*/
|
|
240
238
|
setApp() {
|
|
241
239
|
this.app.set("trust proxy", Chan.config.PROXY === "true");
|
|
242
|
-
this.app.set("env", this.options.env);
|
|
243
240
|
this.app.disable("x-powered-by");
|
|
244
241
|
}
|
|
245
242
|
|
|
@@ -349,7 +346,7 @@ class Chan {
|
|
|
349
346
|
if (fs.existsSync(configPath)) {
|
|
350
347
|
const dirs = loaderSort(Chan.config.modules);
|
|
351
348
|
for (const item of dirs) {
|
|
352
|
-
let router = await importFile(`app/modules/${item}/router.js`);
|
|
349
|
+
let router = await Chan.importFile(`app/modules/${item}/router.js`);
|
|
353
350
|
router(this.app, this.router, Chan.config);
|
|
354
351
|
}
|
|
355
352
|
}
|
|
@@ -362,7 +359,7 @@ class Chan {
|
|
|
362
359
|
* @description 加载 app/router.js 中的公共路由
|
|
363
360
|
*/
|
|
364
361
|
async loadCommonRouter() {
|
|
365
|
-
let router = await importFile("app/router.js");
|
|
362
|
+
let router = await Chan.importFile("app/router.js");
|
|
366
363
|
if (router) {
|
|
367
364
|
router(this.app, this.router, Chan.config);
|
|
368
365
|
}
|
|
@@ -374,11 +371,13 @@ class Chan {
|
|
|
374
371
|
* @description 在启动前执行回调,传递端口号
|
|
375
372
|
*/
|
|
376
373
|
run(cb) {
|
|
377
|
-
this.app.listen(
|
|
378
|
-
console.log(`Server running on port ${
|
|
379
|
-
cb?.(
|
|
374
|
+
this.app.listen(Chan.config.PORT, () => {
|
|
375
|
+
console.log(`Server running on port ${Chan.config.PORT}`);
|
|
376
|
+
cb?.(Chan.config.PORT);
|
|
380
377
|
});
|
|
381
378
|
}
|
|
382
379
|
}
|
|
383
380
|
|
|
381
|
+
global.Chan = Chan;
|
|
382
|
+
|
|
384
383
|
export default Chan;
|
package/base/Controller.js
CHANGED
|
@@ -1,92 +1,21 @@
|
|
|
1
|
-
import { success, fail
|
|
1
|
+
import { success, fail } from "../utils/response.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 控制器基类
|
|
5
5
|
* 提供统一的响应格式和常用方法
|
|
6
6
|
*/
|
|
7
7
|
export default class Controller {
|
|
8
|
-
|
|
9
|
-
* 构造函数
|
|
10
|
-
* @param {Object} context - 应用上下文实例
|
|
11
|
-
*/
|
|
12
|
-
constructor(context = null) {
|
|
13
|
-
if (context) {
|
|
14
|
-
this.context = context;
|
|
15
|
-
} else if (global.appContext) {
|
|
16
|
-
this.context = global.appContext;
|
|
17
|
-
} else {
|
|
18
|
-
this.context = { get: () => null, set: () => null };
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 标准化返回结果
|
|
24
|
-
* @private
|
|
25
|
-
* @param {*} result - 原始结果
|
|
26
|
-
* @param {string} defaultMsg - 默认消息
|
|
27
|
-
* @returns {Object} 标准化的结果对象
|
|
28
|
-
*/
|
|
29
|
-
_normalizeResult(result, defaultMsg = "操作成功") {
|
|
30
|
-
if (result === null || result === undefined) {
|
|
31
|
-
return { success: false, code: 5001, msg: "Service 返回空值", data: {} };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (typeof result === 'object' && 'success' in result) {
|
|
35
|
-
return result;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (typeof result === 'object' || Array.isArray(result)) {
|
|
39
|
-
return { success: true, code: 200, msg: defaultMsg, data: result };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return { success: true, code: 200, msg: defaultMsg, data: result };
|
|
43
|
-
}
|
|
8
|
+
constructor() {}
|
|
44
9
|
|
|
45
10
|
/**
|
|
46
11
|
* 返回成功响应
|
|
47
|
-
* @param {
|
|
12
|
+
* @param {Object} options - 响应选项
|
|
48
13
|
* @param {*} options.data - 响应数据
|
|
49
14
|
* @param {string} options.msg - 响应消息,默认"操作成功"
|
|
50
15
|
* @returns {Object} 标准成功响应
|
|
51
16
|
*/
|
|
52
|
-
success(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (options === null || options === undefined) {
|
|
56
|
-
data = undefined;
|
|
57
|
-
} else if (typeof options === 'object' && options !== null && !Array.isArray(options)) {
|
|
58
|
-
if ('data' in options) {
|
|
59
|
-
data = options.data;
|
|
60
|
-
message = options.msg || msg;
|
|
61
|
-
extra = { ...options };
|
|
62
|
-
delete extra.data;
|
|
63
|
-
delete extra.msg;
|
|
64
|
-
} else if ('success' in options && 'code' in options) {
|
|
65
|
-
return options;
|
|
66
|
-
} else {
|
|
67
|
-
data = options;
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
data = options;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (data instanceof Error) {
|
|
74
|
-
return this.error({ err: data });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const normalized = this._normalizeResult(data, message);
|
|
78
|
-
|
|
79
|
-
if (!normalized.success) {
|
|
80
|
-
return this.fail({ msg: normalized.msg, data: normalized.data, code: normalized.code });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
success: true,
|
|
85
|
-
code: 200,
|
|
86
|
-
msg: normalized.msg,
|
|
87
|
-
data: normalized.data,
|
|
88
|
-
...extra
|
|
89
|
-
};
|
|
17
|
+
success({ data, msg = "操作成功" } = {}) {
|
|
18
|
+
return success({ data, msg });
|
|
90
19
|
}
|
|
91
20
|
|
|
92
21
|
/**
|
|
@@ -100,38 +29,4 @@ export default class Controller {
|
|
|
100
29
|
fail({ msg = "操作失败", data = {}, code = 201 } = {}) {
|
|
101
30
|
return fail({ msg, data, code });
|
|
102
31
|
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* 返回错误响应
|
|
106
|
-
* @param {Object} options - 响应选项
|
|
107
|
-
* @param {Error} options.err - 错误对象
|
|
108
|
-
* @param {*} options.data - 响应数据
|
|
109
|
-
* @param {number} options.code - 错误码,默认500
|
|
110
|
-
* @returns {Object} 标准错误响应
|
|
111
|
-
*/
|
|
112
|
-
error({ err, data = {}, code = 500 } = {}) {
|
|
113
|
-
return responseError({ err, data, code });
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* 返回分页响应
|
|
118
|
-
* @param {Array} list - 数据列表
|
|
119
|
-
* @param {number} total - 总记录数
|
|
120
|
-
* @param {number} current - 当前页码
|
|
121
|
-
* @param {number} pageSize - 每页大小
|
|
122
|
-
* @returns {Object} 标准分页响应
|
|
123
|
-
*/
|
|
124
|
-
paginate(list, total, current, pageSize) {
|
|
125
|
-
return success({
|
|
126
|
-
data: {
|
|
127
|
-
list,
|
|
128
|
-
pagination: {
|
|
129
|
-
total,
|
|
130
|
-
current,
|
|
131
|
-
pageSize,
|
|
132
|
-
totalPages: Math.ceil(total / pageSize),
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
32
|
}
|
package/base/Database.js
CHANGED
|
@@ -2,7 +2,7 @@ import knex from "knex";
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 数据库管理器类
|
|
5
|
-
*
|
|
5
|
+
* 用于管理多个数据库连接
|
|
6
6
|
*/
|
|
7
7
|
class DatabaseManager {
|
|
8
8
|
/**
|
|
@@ -78,237 +78,6 @@ class DatabaseManager {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/**
|
|
82
|
-
* 关闭所有数据库连接
|
|
83
|
-
* @returns {Promise<void>}
|
|
84
|
-
*/
|
|
85
|
-
async closeAll() {
|
|
86
|
-
const closePromises = [];
|
|
87
|
-
for (const [name, connection] of this._connections) {
|
|
88
|
-
closePromises.push(
|
|
89
|
-
connection.destroy().catch((err) => {
|
|
90
|
-
console.error(`Error closing database "${name}":`, err);
|
|
91
|
-
})
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
await Promise.all(closePromises);
|
|
95
|
-
this._connections.clear();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 获取所有连接名称
|
|
100
|
-
* @returns {Array<string>} 连接名称数组
|
|
101
|
-
*/
|
|
102
|
-
getConnections() {
|
|
103
|
-
return Array.from(this._connections.keys());
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* 创建数据模型
|
|
108
|
-
* @param {string} name - 模型名称
|
|
109
|
-
* @param {string} tableName - 表名
|
|
110
|
-
* @param {string} connectionName - 连接名称
|
|
111
|
-
* @returns {Object} 模型对象
|
|
112
|
-
*/
|
|
113
|
-
createModel(name, tableName, connectionName) {
|
|
114
|
-
const db = this.get(connectionName);
|
|
115
|
-
return {
|
|
116
|
-
db,
|
|
117
|
-
tableName,
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* 查询字段
|
|
121
|
-
* @param {string} fields - 字段列表,默认"*"
|
|
122
|
-
* @returns {Object} Knex查询构建器
|
|
123
|
-
*/
|
|
124
|
-
select(fields = "*") {
|
|
125
|
-
return db(this.tableName).select(fields);
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* 条件查询
|
|
130
|
-
* @param {Object} conditions - 查询条件
|
|
131
|
-
* @returns {Object} Knex查询构建器
|
|
132
|
-
*/
|
|
133
|
-
where(conditions) {
|
|
134
|
-
return db(this.tableName).where(conditions);
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* 查找记录
|
|
139
|
-
* @param {Object} query - 查询参数
|
|
140
|
-
* @param {Object} query.sort - 排序条件
|
|
141
|
-
* @param {Object} query.where - 查询条件
|
|
142
|
-
* @returns {Promise<Array>} 查询结果数组
|
|
143
|
-
*/
|
|
144
|
-
find(query = {}) {
|
|
145
|
-
let q = db(this.tableName);
|
|
146
|
-
const { sort, ...where } = query;
|
|
147
|
-
|
|
148
|
-
if (Object.keys(where).length > 0) {
|
|
149
|
-
q = q.where(where);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (sort && typeof sort === "object") {
|
|
153
|
-
for (const [field, dir] of Object.entries(sort)) {
|
|
154
|
-
q = q.orderBy(field, dir);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return q.select();
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* 查找单条记录
|
|
163
|
-
* @param {Object} query - 查询条件
|
|
164
|
-
* @returns {Promise<Object|null>} 查询结果或null
|
|
165
|
-
*/
|
|
166
|
-
findOne(query = {}) {
|
|
167
|
-
let q = db(this.tableName);
|
|
168
|
-
if (Object.keys(query).length > 0) {
|
|
169
|
-
q = q.where(query);
|
|
170
|
-
}
|
|
171
|
-
return q.first();
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* 根据ID查找记录
|
|
176
|
-
* @param {number|string} id - 记录ID
|
|
177
|
-
* @returns {Promise<Object|null>} 查询结果或null
|
|
178
|
-
*/
|
|
179
|
-
findById(id) {
|
|
180
|
-
return db(this.tableName).where({ id }).first();
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* 创建记录
|
|
185
|
-
* @param {Object} data - 要插入的数据
|
|
186
|
-
* @returns {Promise<Array>} 插入结果
|
|
187
|
-
*/
|
|
188
|
-
create(data) {
|
|
189
|
-
return db(this.tableName).insert(data);
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* 批量创建记录
|
|
194
|
-
* @param {Array} records - 要插入的记录数组
|
|
195
|
-
* @returns {Promise<Array>} 插入结果
|
|
196
|
-
*/
|
|
197
|
-
createMany(records) {
|
|
198
|
-
return db(this.tableName).insert(records);
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* 更新记录
|
|
203
|
-
* @param {Object} conditions - 更新条件
|
|
204
|
-
* @param {Object} data - 更新数据
|
|
205
|
-
* @returns {Promise<number>} 影响的行数
|
|
206
|
-
*/
|
|
207
|
-
update(conditions, data) {
|
|
208
|
-
return db(this.tableName).where(conditions).update(data);
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* 删除记录
|
|
213
|
-
* @param {Object} conditions - 删除条件
|
|
214
|
-
* @returns {Promise<number>} 影响的行数
|
|
215
|
-
*/
|
|
216
|
-
delete(conditions) {
|
|
217
|
-
return db(this.tableName).where(conditions).del();
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* 统计记录数
|
|
222
|
-
* @param {Object} query - 查询条件
|
|
223
|
-
* @returns {Promise<number>} 记录总数
|
|
224
|
-
*/
|
|
225
|
-
count(query = {}) {
|
|
226
|
-
let q = db(this.tableName).count("* as total");
|
|
227
|
-
if (Object.keys(query).length > 0) {
|
|
228
|
-
q = q.where(query);
|
|
229
|
-
}
|
|
230
|
-
return q.first().then((result) => result?.total ?? 0);
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* 分页查询
|
|
235
|
-
* @param {Object} options - 查询选项
|
|
236
|
-
* @param {number} options.current - 当前页码,默认1
|
|
237
|
-
* @param {number} options.pageSize - 每页大小,默认10
|
|
238
|
-
* @param {Object} options.where - 查询条件
|
|
239
|
-
* @param {Array} options.select - 查询字段
|
|
240
|
-
* @returns {Promise<Object>} 分页结果
|
|
241
|
-
*/
|
|
242
|
-
query(options = {}) {
|
|
243
|
-
const { current = 1, pageSize = 10, where = {}, select } = options;
|
|
244
|
-
const offset = (current - 1) * pageSize;
|
|
245
|
-
|
|
246
|
-
const countQuery = db(this.tableName).count("* as total");
|
|
247
|
-
const dataQuery = db(this.tableName);
|
|
248
|
-
|
|
249
|
-
if (Object.keys(where).length > 0) {
|
|
250
|
-
countQuery.where(where);
|
|
251
|
-
dataQuery.where(where);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (select) {
|
|
255
|
-
dataQuery.select(select);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return Promise.all([
|
|
259
|
-
countQuery.first(),
|
|
260
|
-
dataQuery.offset(offset).limit(pageSize),
|
|
261
|
-
]).then(([totalResult, list]) => ({
|
|
262
|
-
list,
|
|
263
|
-
total: totalResult?.total ?? 0,
|
|
264
|
-
current,
|
|
265
|
-
pageSize,
|
|
266
|
-
}));
|
|
267
|
-
},
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* 关联查询
|
|
271
|
-
* @param {Object} options - 查询选项
|
|
272
|
-
* @param {string} options.joinTable - 关联表名
|
|
273
|
-
* @param {string} options.localField - 本地表字段
|
|
274
|
-
* @param {string} options.foreignField - 关联表字段
|
|
275
|
-
* @param {string} options.select - 查询字段,默认"*"
|
|
276
|
-
* @param {Object} options.where - 查询条件
|
|
277
|
-
* @returns {Object} Knex查询构建器
|
|
278
|
-
*/
|
|
279
|
-
join(options) {
|
|
280
|
-
const { joinTable, localField, foreignField, select = "*", where = {} } = options;
|
|
281
|
-
let q = db(this.tableName)
|
|
282
|
-
.join(joinTable, `${this.tableName}.${localField}`, "=", `${joinTable}.${foreignField}`)
|
|
283
|
-
.select(select);
|
|
284
|
-
|
|
285
|
-
if (Object.keys(where).length > 0) {
|
|
286
|
-
q = q.where(where);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return q;
|
|
290
|
-
},
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* 执行事务
|
|
294
|
-
* @param {Function} callback - 事务回调函数
|
|
295
|
-
* @returns {Promise} 事务执行结果
|
|
296
|
-
*/
|
|
297
|
-
transaction(callback) {
|
|
298
|
-
return db.transaction(callback);
|
|
299
|
-
},
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* 执行原生SQL
|
|
303
|
-
* @param {string} sql - SQL语句
|
|
304
|
-
* @param {Array} bindings - 绑定参数
|
|
305
|
-
* @returns {Promise} 查询结果
|
|
306
|
-
*/
|
|
307
|
-
raw(sql, bindings) {
|
|
308
|
-
return db.raw(sql, bindings);
|
|
309
|
-
},
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
81
|
}
|
|
313
82
|
|
|
314
83
|
export default DatabaseManager;
|
package/base/Service.js
CHANGED
|
@@ -14,11 +14,6 @@ class Service {
|
|
|
14
14
|
if (knex && tableName) {
|
|
15
15
|
this.db = knex;
|
|
16
16
|
this.tableName = tableName;
|
|
17
|
-
this._config = Chan.config || {};
|
|
18
|
-
} else if (global.appContext) {
|
|
19
|
-
this.context = global.appContext;
|
|
20
|
-
} else {
|
|
21
|
-
this.context = { get: () => null, set: () => null };
|
|
22
17
|
}
|
|
23
18
|
|
|
24
19
|
this._dateFields = ['created_at', 'updated_at', 'deleted_at', 'publish_time', 'start_time', 'end_time', 'login_time', 'created_date', 'updated_date', 'createdAt', 'updatedAt', 'deletedAt', 'publishTime', 'startTime', 'endTime', 'loginTime', 'createdDate', 'updatedDate'];
|
|
@@ -29,7 +24,7 @@ class Service {
|
|
|
29
24
|
* @returns {number} 每页记录数,默认20
|
|
30
25
|
*/
|
|
31
26
|
get pageSize() {
|
|
32
|
-
return
|
|
27
|
+
return Chan.config.PAGE_SIZE || 20;
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
/**
|
|
@@ -37,35 +32,7 @@ class Service {
|
|
|
37
32
|
* @returns {number} 最大记录数,默认300
|
|
38
33
|
*/
|
|
39
34
|
get limit() {
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 获取模型实例
|
|
45
|
-
* @param {string} name - 模型名称
|
|
46
|
-
* @returns {Object} 模型实例
|
|
47
|
-
*/
|
|
48
|
-
getModel(name) {
|
|
49
|
-
return this.context.getModel(name);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* 获取数据库连接
|
|
54
|
-
* @param {string} name - 数据库名称
|
|
55
|
-
* @returns {Object} 数据库实例
|
|
56
|
-
*/
|
|
57
|
-
getDB(name) {
|
|
58
|
-
return this.context.get(`db:${name}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 执行事务
|
|
63
|
-
* @param {Function} callback - 事务回调函数
|
|
64
|
-
* @returns {Promise} 事务执行结果
|
|
65
|
-
*/
|
|
66
|
-
async withTransaction(callback) {
|
|
67
|
-
const db = this.getDB("default") || Chan.db;
|
|
68
|
-
return db.transaction(callback);
|
|
35
|
+
return Chan.config.LIMIT_MAX || 300;
|
|
69
36
|
}
|
|
70
37
|
|
|
71
38
|
/**
|
package/global/import.js
CHANGED
package/helper/index.js
CHANGED
package/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as Chan } from "./App.js";
|
|
2
2
|
export { default as Controller } from "./base/Controller.js";
|
|
3
3
|
export { default as Service } from "./base/Service.js";
|
|
4
|
-
export { default as AppContext } from "./base/Context.js";
|
|
5
4
|
export { default as DatabaseManager } from "./base/Database.js";
|
|
6
5
|
|
|
7
6
|
export * as helper from "./helper/index.js";
|
package/middleware/index.js
CHANGED
package/middleware/template.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "../extend/index.js";
|
|
2
|
+
import { importjs } from "../global/import.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 模板引擎中间件配置
|
|
@@ -30,5 +31,5 @@ export let setTemplate = (app, config) => {
|
|
|
30
31
|
});
|
|
31
32
|
app.set("view engine", "html");
|
|
32
33
|
app.set("views", all);
|
|
33
|
-
app.engine(".html",
|
|
34
|
+
app.engine(".html", importjs("express-art-template"));
|
|
34
35
|
};
|