chanjs 2.0.18 → 2.0.20
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/controller.js +5 -1
- package/core/service.js +140 -76
- package/global/global.js +12 -1
- package/helper/index.js +2 -1
- package/helper/loader.js +24 -6
- package/helper/time.js +47 -1
- package/index.js +4 -3
- package/package.json +1 -1
package/core/controller.js
CHANGED
package/core/service.js
CHANGED
|
@@ -8,18 +8,21 @@ class Service {
|
|
|
8
8
|
/**
|
|
9
9
|
* 构造函数
|
|
10
10
|
* @param {Object} knex - Knex实例
|
|
11
|
-
* @param {string}
|
|
11
|
+
* @param {string} tableName - 表名
|
|
12
12
|
*/
|
|
13
|
-
constructor(knex,
|
|
14
|
-
if (!knex || !
|
|
15
|
-
throw new Error("Service: knex instance and
|
|
13
|
+
constructor(knex, tableName) {
|
|
14
|
+
if (!knex || !tableName) {
|
|
15
|
+
throw new Error("Service: knex instance and tableName are required");
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
20
|
-
this.pageSize =
|
|
18
|
+
this.db = knex;
|
|
19
|
+
this.tableName = tableName;
|
|
20
|
+
this.pageSize = Chan.config?.PAGE_SIZE || 20;
|
|
21
|
+
this.limit = Chan.config?.LIMIT_MAX || 300;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
|
|
25
|
+
|
|
23
26
|
/**
|
|
24
27
|
* 查询表所有记录(慎用)
|
|
25
28
|
* @param {Object} query - 查询条件
|
|
@@ -27,28 +30,58 @@ class Service {
|
|
|
27
30
|
*/
|
|
28
31
|
async all(query = {}) {
|
|
29
32
|
try {
|
|
30
|
-
let
|
|
31
|
-
if (Object.keys(query).length
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
const res = await dbQuery.select();
|
|
33
|
+
let _query = this.db(this.tableName);
|
|
34
|
+
if (Object.keys(query).length) _query = _query.where(query);
|
|
35
|
+
const res = await _query.select();
|
|
35
36
|
return success(res);
|
|
36
37
|
} catch (err) {
|
|
37
38
|
return error(err);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 查询所有文档(仅支持对象模式排序)
|
|
44
|
+
* @param {Object} query - 查询条件,可包含 sort: { field: 'asc|desc' }
|
|
45
|
+
* @returns {Promise} 查询结果
|
|
46
|
+
*/
|
|
47
|
+
async find(query = {}) {
|
|
48
|
+
try {
|
|
49
|
+
let _query = this.db(this.tableName);
|
|
50
|
+
|
|
51
|
+
// 解构出排序参数,剩余作为 where 条件
|
|
52
|
+
const { sort, ...whereConditions } = query;
|
|
53
|
+
|
|
54
|
+
// 应用 where 条件
|
|
55
|
+
if (Object.keys(whereConditions).length > 0) {
|
|
56
|
+
_query = _query.where(whereConditions);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 应用排序(仅支持对象模式)
|
|
60
|
+
if (sort && typeof sort === 'object') {
|
|
61
|
+
for (const [field, dir] of Object.entries(sort)) {
|
|
62
|
+
const direction = ['asc', 'desc'].includes(dir.toLowerCase())
|
|
63
|
+
? dir.toLowerCase()
|
|
64
|
+
: 'asc'; // 默认升序
|
|
65
|
+
_query = _query.orderBy(field, direction);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const res = await _query.select();
|
|
70
|
+
return success(res);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return error(err);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
41
76
|
/**
|
|
42
77
|
* 获取单个记录
|
|
43
78
|
* @param {Object} query - 查询条件
|
|
44
79
|
* @returns {Promise} 查询结果
|
|
45
80
|
*/
|
|
46
|
-
async
|
|
81
|
+
async findOne(query = {}) {
|
|
47
82
|
try {
|
|
48
|
-
let dbQuery = this.
|
|
49
|
-
if (Object.keys(query).length
|
|
50
|
-
dbQuery = dbQuery.where(query);
|
|
51
|
-
}
|
|
83
|
+
let dbQuery = this.db(this.tableName);
|
|
84
|
+
if (Object.keys(query).length) dbQuery = dbQuery.where(query);
|
|
52
85
|
const res = await dbQuery.first();
|
|
53
86
|
return success(res);
|
|
54
87
|
} catch (err) {
|
|
@@ -60,35 +93,30 @@ class Service {
|
|
|
60
93
|
* 根据ID查询记录
|
|
61
94
|
* @param {Object} options - 查询选项
|
|
62
95
|
* @param {Object} options.query - 查询条件
|
|
63
|
-
* @param {Array}
|
|
64
|
-
* @param {number} options.len - 返回数量
|
|
96
|
+
* @param {Array} options.field - 返回字段
|
|
65
97
|
*/
|
|
66
|
-
async findById({ query, field = []
|
|
98
|
+
async findById({ query, field = [] }) {
|
|
67
99
|
try {
|
|
68
|
-
let
|
|
69
|
-
if (field.length
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const res = await dataQuery;
|
|
74
|
-
return success(res || (len === 1 ? {} : []));
|
|
100
|
+
let _query = this.db(this.tableName).where(query);
|
|
101
|
+
if (field.length) _query = _query.select(field);
|
|
102
|
+
const res = await _query.first();
|
|
103
|
+
return success(res);
|
|
75
104
|
} catch (err) {
|
|
76
105
|
return error(err);
|
|
77
106
|
}
|
|
78
107
|
}
|
|
79
108
|
|
|
109
|
+
|
|
80
110
|
/**
|
|
81
111
|
* 创建新记录
|
|
82
|
-
* @param {Object} data -
|
|
112
|
+
* @param {Object} data - 要插入的数据
|
|
83
113
|
* @returns {Promise} 操作结果
|
|
84
114
|
*/
|
|
85
115
|
async insert(data = {}) {
|
|
86
116
|
try {
|
|
87
|
-
if (Object.keys(data).length
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const result = await this.knex(this.model).insert(data);
|
|
91
|
-
return success(result?.length > 0 || !!result);
|
|
117
|
+
if (!Object.keys(data).length) return fail(CODE[2002], { code: 2002 });
|
|
118
|
+
const result = await this.db(this.tableName).insert(data);
|
|
119
|
+
return success(result);
|
|
92
120
|
} catch (err) {
|
|
93
121
|
return error(err);
|
|
94
122
|
}
|
|
@@ -96,15 +124,13 @@ class Service {
|
|
|
96
124
|
|
|
97
125
|
/**
|
|
98
126
|
* 插入多条记录
|
|
99
|
-
* @param {Array} records -
|
|
127
|
+
* @param {Array} records - 数据数组
|
|
100
128
|
* @returns {Promise} 操作结果
|
|
101
129
|
*/
|
|
102
130
|
async insertMany(records = []) {
|
|
103
131
|
try {
|
|
104
|
-
if (records.length
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
const result = await this.knex(this.model).insert(records);
|
|
132
|
+
if (!records.length) return fail(CODE[2002], { code: 2002 });
|
|
133
|
+
const result = await this.db(this.tableName).insert(records);
|
|
108
134
|
return success(result);
|
|
109
135
|
} catch (err) {
|
|
110
136
|
return error(err);
|
|
@@ -112,16 +138,14 @@ class Service {
|
|
|
112
138
|
}
|
|
113
139
|
|
|
114
140
|
/**
|
|
115
|
-
*
|
|
116
|
-
* @param {Object} query -
|
|
141
|
+
* 根据条件删除记录
|
|
142
|
+
* @param {Object} query - 查询条件
|
|
117
143
|
* @returns {Promise} 操作结果
|
|
118
144
|
*/
|
|
119
145
|
async delete(query = {}) {
|
|
120
146
|
try {
|
|
121
|
-
if (Object.keys(query).length
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
const affectedRows = await this.knex(this.model).where(query).del();
|
|
147
|
+
if (!Object.keys(query).length) return fail(CODE[2002], { code: 2002 });
|
|
148
|
+
const affectedRows = await this.db(this.tableName).where(query).del();
|
|
125
149
|
return success(affectedRows > 0);
|
|
126
150
|
} catch (err) {
|
|
127
151
|
return error(err);
|
|
@@ -129,7 +153,7 @@ class Service {
|
|
|
129
153
|
}
|
|
130
154
|
|
|
131
155
|
/**
|
|
132
|
-
*
|
|
156
|
+
* 根据条件更新记录
|
|
133
157
|
* @param {Object} options - 更新选项
|
|
134
158
|
* @param {Object} options.query - 查询条件
|
|
135
159
|
* @param {Object} options.params - 更新数据
|
|
@@ -137,10 +161,10 @@ class Service {
|
|
|
137
161
|
*/
|
|
138
162
|
async update({ query, params } = {}) {
|
|
139
163
|
try {
|
|
140
|
-
if (!query || !params || Object.keys(query).length
|
|
164
|
+
if (!query || !params || !Object.keys(query).length) {
|
|
141
165
|
return fail(CODE[2001], { code: 2001 });
|
|
142
166
|
}
|
|
143
|
-
const result = await this.
|
|
167
|
+
const result = await this.db(this.tableName).where(query).update(params);
|
|
144
168
|
return success(!!result);
|
|
145
169
|
} catch (err) {
|
|
146
170
|
return error(err);
|
|
@@ -148,21 +172,27 @@ class Service {
|
|
|
148
172
|
}
|
|
149
173
|
|
|
150
174
|
/**
|
|
151
|
-
*
|
|
152
|
-
* @param {Array} updates -
|
|
175
|
+
* 批量更新多条记录(事务)
|
|
176
|
+
* @param {Array} updates - [{ query, params }, ...]
|
|
153
177
|
* @returns {Promise} 操作结果
|
|
154
178
|
*/
|
|
155
179
|
async updateMany(updates = []) {
|
|
156
|
-
if (!Array.isArray(updates) || updates.length
|
|
180
|
+
if (!Array.isArray(updates) || !updates.length) {
|
|
157
181
|
return fail(CODE[2002], { code: 2002 });
|
|
158
182
|
}
|
|
159
183
|
|
|
160
|
-
const trx = await this.
|
|
184
|
+
const trx = await this.db.transaction();
|
|
161
185
|
try {
|
|
162
186
|
for (const { query, params } of updates) {
|
|
163
|
-
|
|
187
|
+
// FIX-4 防止空条件全表更新
|
|
188
|
+
if (!query || !Object.keys(query).length) {
|
|
189
|
+
await trx.rollback();
|
|
190
|
+
return fail('批量更新不允许空条件');
|
|
191
|
+
}
|
|
192
|
+
const result = await trx(this.tableName).where(query).update(params);
|
|
164
193
|
if (result === 0) {
|
|
165
194
|
await trx.rollback();
|
|
195
|
+
console.warn('[updateMany] 未匹配到行, query=%j', query); // FIX-3 日志
|
|
166
196
|
return fail(`更新失败: ${JSON.stringify(query)}`);
|
|
167
197
|
}
|
|
168
198
|
}
|
|
@@ -174,37 +204,41 @@ class Service {
|
|
|
174
204
|
}
|
|
175
205
|
}
|
|
176
206
|
|
|
207
|
+
|
|
177
208
|
/**
|
|
178
209
|
* 分页查询
|
|
179
210
|
* @param {Object} options - 查询选项
|
|
180
|
-
* @param {number} options.current
|
|
181
|
-
* @param {number} options.pageSize -
|
|
182
|
-
* @param {Object} options.query
|
|
183
|
-
* @param {Array}
|
|
211
|
+
* @param {number} options.current - 当前页
|
|
212
|
+
* @param {number} options.pageSize - 每页条数
|
|
213
|
+
* @param {Object} options.query - 查询条件
|
|
214
|
+
* @param {Array} options.field - 返回字段
|
|
184
215
|
* @returns {Promise} 查询结果
|
|
185
216
|
*/
|
|
186
217
|
async query({ current = 1, pageSize = 10, query = {}, field = [] }) {
|
|
187
218
|
try {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
219
|
+
const size = pageSize; // 如需要可再做非空校验
|
|
220
|
+
const offset = (current - 1) * size;
|
|
221
|
+
|
|
222
|
+
let countQuery = this.db(this.tableName).count("* as total");
|
|
223
|
+
let dataQuery = this.db(this.tableName);
|
|
224
|
+
|
|
225
|
+
if (Object.keys(query).length) {
|
|
226
|
+
Object.entries(query).forEach(([k, v]) => {
|
|
227
|
+
countQuery = countQuery.where(k, v);
|
|
228
|
+
dataQuery = dataQuery.where(k, v);
|
|
196
229
|
});
|
|
197
230
|
}
|
|
198
231
|
|
|
199
|
-
if (field.length
|
|
232
|
+
if (field && field.length) dataQuery = dataQuery.select(field);
|
|
200
233
|
|
|
201
234
|
const [totalResult, list] = await Promise.all([
|
|
202
235
|
countQuery.first(),
|
|
203
|
-
dataQuery.offset(offset).limit(
|
|
236
|
+
dataQuery.offset(offset).limit(size),
|
|
204
237
|
]);
|
|
205
238
|
|
|
206
|
-
|
|
207
|
-
|
|
239
|
+
// FIX-1 显式转数字,防止字符串 "0"
|
|
240
|
+
const total = Number(totalResult?.total ?? 0);
|
|
241
|
+
return success({ list, total, current, pageSize: size });
|
|
208
242
|
} catch (err) {
|
|
209
243
|
return error(err);
|
|
210
244
|
}
|
|
@@ -212,21 +246,51 @@ class Service {
|
|
|
212
246
|
|
|
213
247
|
/**
|
|
214
248
|
* 计数查询
|
|
215
|
-
* @param {
|
|
249
|
+
* @param {Object} query - 查询条件
|
|
216
250
|
* @returns {Promise} 查询结果
|
|
217
251
|
*/
|
|
218
|
-
async count(query =
|
|
252
|
+
async count(query = {}) {
|
|
219
253
|
try {
|
|
220
|
-
let dataQuery = this.
|
|
221
|
-
if (query.length
|
|
222
|
-
query.forEach((condition) => (dataQuery = dataQuery.where(condition)));
|
|
223
|
-
}
|
|
254
|
+
let dataQuery = this.db(this.tableName);
|
|
255
|
+
if (Object.keys(query).length) dataQuery = dataQuery.where(query);
|
|
224
256
|
const result = await dataQuery.count("* as total").first();
|
|
225
|
-
return success(Number(result?.total
|
|
257
|
+
return success(Number(result?.total ?? 0));
|
|
258
|
+
} catch (err) {
|
|
259
|
+
return error(err);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 多表关联查询
|
|
265
|
+
* @param {Object} query - 关联配置
|
|
266
|
+
* @returns {Promise} 查询结果
|
|
267
|
+
*/
|
|
268
|
+
async join(query) {
|
|
269
|
+
try {
|
|
270
|
+
const {
|
|
271
|
+
joinTable,
|
|
272
|
+
localField,
|
|
273
|
+
foreignField,
|
|
274
|
+
select = "*",
|
|
275
|
+
where = {},
|
|
276
|
+
} = query;
|
|
277
|
+
|
|
278
|
+
let _query = this.db(this.tableName)
|
|
279
|
+
.join(
|
|
280
|
+
joinTable,
|
|
281
|
+
`${this.tableName}.${localField}`,
|
|
282
|
+
"=",
|
|
283
|
+
`${joinTable}.${foreignField}`
|
|
284
|
+
)
|
|
285
|
+
.select(select);
|
|
286
|
+
|
|
287
|
+
if (Object.keys(where).length) _query = _query.where(where);
|
|
288
|
+
const res = await _query;
|
|
289
|
+
return success(res);
|
|
226
290
|
} catch (err) {
|
|
227
291
|
return error(err);
|
|
228
292
|
}
|
|
229
293
|
}
|
|
230
294
|
}
|
|
231
295
|
|
|
232
|
-
export default Service;
|
|
296
|
+
export default Service;
|
package/global/global.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
import { pathToFileURL, fileURLToPath } from "url";
|
|
2
1
|
import path from "path";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from "url";
|
|
4
|
+
|
|
3
5
|
const ROOT_PATH = process.cwd();
|
|
4
6
|
const APP_PATH = path.join(ROOT_PATH, "app");
|
|
5
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
8
|
const __dirname = path.dirname(__filename);
|
|
7
9
|
|
|
10
|
+
const getVersion = () => {
|
|
11
|
+
const packageJsonPath = path.join(ROOT_PATH, "package.json");
|
|
12
|
+
const packageJson = JSON.parse(
|
|
13
|
+
readFileSync(packageJsonPath, "utf8")
|
|
14
|
+
);
|
|
15
|
+
return packageJson?.version || "1.0.0";
|
|
16
|
+
};
|
|
17
|
+
|
|
8
18
|
const globals = {
|
|
9
19
|
__dirname,
|
|
10
20
|
__filename,
|
|
11
21
|
ROOT_PATH,
|
|
12
22
|
APP_PATH,
|
|
23
|
+
APP_VERSION: getVersion(),
|
|
13
24
|
CONFIG_PATH: path.join(ROOT_PATH, "config"),
|
|
14
25
|
EXTEND_PATH: path.join(APP_PATH, "extend"),
|
|
15
26
|
PUBLIC_PATH: path.join(ROOT_PATH, "public"),
|
package/helper/index.js
CHANGED
package/helper/loader.js
CHANGED
|
@@ -48,6 +48,26 @@ export const loadConfig = async function () {
|
|
|
48
48
|
return config;
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* 绑定已实例化对象的方法
|
|
53
|
+
* @param {Object} instance - 已实例化的对象
|
|
54
|
+
* @returns {Object} 绑定方法后的对象
|
|
55
|
+
*/
|
|
56
|
+
export const bindInstance = function (instance) {
|
|
57
|
+
Object.getOwnPropertyNames(Object.getPrototypeOf(instance)).forEach(
|
|
58
|
+
(methodName) => {
|
|
59
|
+
if (
|
|
60
|
+
methodName !== "constructor" &&
|
|
61
|
+
typeof instance[methodName] === "function"
|
|
62
|
+
) {
|
|
63
|
+
instance[methodName] = instance[methodName].bind(instance);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
return instance;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
|
|
51
71
|
/**
|
|
52
72
|
* 加载指定模块名下的所有控制器文件
|
|
53
73
|
* @param {string} moduleName - 模块名称
|
|
@@ -67,17 +87,15 @@ export const loadController = async function (moduleName) {
|
|
|
67
87
|
|
|
68
88
|
for (const file of files) {
|
|
69
89
|
const filePath = path.join(dir, file);
|
|
70
|
-
const name = file.replace(/\.js$/i, "");
|
|
90
|
+
const name = file.replace(/\.js$/i, "");
|
|
71
91
|
|
|
72
92
|
try {
|
|
73
93
|
const module = await importFile(filePath);
|
|
74
|
-
let obj = module
|
|
75
|
-
|
|
76
|
-
controller[name] = obj;
|
|
94
|
+
let obj = module?.default || module;
|
|
95
|
+
// 使用 bindClass 确保方法绑定了正确的 this
|
|
96
|
+
controller[name] = bindInstance(obj);
|
|
77
97
|
} catch (e) {
|
|
78
98
|
console.error(`加载控制器失败: ${filePath}`, e);
|
|
79
|
-
// 可选:抛出错误或继续加载其他文件
|
|
80
|
-
// throw e;
|
|
81
99
|
}
|
|
82
100
|
}
|
|
83
101
|
|
package/helper/time.js
CHANGED
|
@@ -24,5 +24,51 @@ export const formatDay = (data, time = true, format = "YYYY-MM-DD") => {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const formatTime = (data, format = "YYYY-MM-DD HH:mm:ss") => {
|
|
27
|
-
return dayjs(data).format(
|
|
27
|
+
return dayjs(data).format(format);
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 格式化对象或数组中的日期字段
|
|
32
|
+
* @param {Object|Array} data - 要格式化的数据
|
|
33
|
+
* @param {Object} options - 配置选项
|
|
34
|
+
* @param {Array} options.fields - 要格式化的字段名,默认 ['createdAt', 'updatedAt']
|
|
35
|
+
* @param {String} options.format - 日期格式,默认 'YYYY-MM-DD HH:mm:ss'
|
|
36
|
+
* @returns {Object|Array} - 格式化后的数据
|
|
37
|
+
*/
|
|
38
|
+
export const formatDateFields = (data, options = {}) => {
|
|
39
|
+
const {
|
|
40
|
+
fields = ['createdAt', 'updatedAt'],
|
|
41
|
+
format = 'YYYY-MM-DD HH:mm:ss',
|
|
42
|
+
} = options;
|
|
43
|
+
|
|
44
|
+
const isPlainObject = (val) =>
|
|
45
|
+
Object.prototype.toString.call(val) === '[object Object]';
|
|
46
|
+
|
|
47
|
+
if (isPlainObject(data)) {
|
|
48
|
+
const result = { ...data };
|
|
49
|
+
fields.forEach(field => {
|
|
50
|
+
const value = result[field];
|
|
51
|
+
if (value != null) {
|
|
52
|
+
const type = typeof value;
|
|
53
|
+
if (type === 'string' || type === 'number' || value instanceof Date) {
|
|
54
|
+
try {
|
|
55
|
+
result[field] = formatTime(value, format);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.warn(`格式化字段 ${field} 失败:`, e.message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (Array.isArray(data)) {
|
|
66
|
+
return data.map(item =>
|
|
67
|
+
typeof item === 'object' && item !== null
|
|
68
|
+
? formatDateFields(item, options)
|
|
69
|
+
: item
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return data;
|
|
74
|
+
};;
|
package/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { dirname } from "./helper/file.js";
|
|
|
21
21
|
|
|
22
22
|
class Chan {
|
|
23
23
|
//版本号
|
|
24
|
-
#version = "
|
|
24
|
+
#version = "1.0.0";
|
|
25
25
|
static helper = {};
|
|
26
26
|
static common = {}; //公共方法
|
|
27
27
|
static config = {}; //配置
|
|
@@ -29,7 +29,7 @@ class Chan {
|
|
|
29
29
|
static Controller = Controller; //控制器
|
|
30
30
|
static extend = {}; //组件扩展
|
|
31
31
|
static middleware = {}; //中间件
|
|
32
|
-
|
|
32
|
+
static modules = {}; //模块
|
|
33
33
|
|
|
34
34
|
constructor() {
|
|
35
35
|
this.app = express();
|
|
@@ -50,6 +50,8 @@ class Chan {
|
|
|
50
50
|
//加载配置文件
|
|
51
51
|
async config() {
|
|
52
52
|
let config = await loadConfig();
|
|
53
|
+
//版本号,先从package.json中获取,如果没有,则使用默认版本号
|
|
54
|
+
config.APP_VERSION = APP_VERSION || config.APP_VERSION;
|
|
53
55
|
Chan.config = config;
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -165,7 +167,6 @@ class Chan {
|
|
|
165
167
|
methods: Object.keys(r.route.methods),
|
|
166
168
|
}));
|
|
167
169
|
|
|
168
|
-
console.log(routes);
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
run(cb) {
|