chanjs 1.1.4 → 1.1.6

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.
@@ -3,7 +3,7 @@ class BaseService {
3
3
  * @description 构造函数
4
4
  * @param {*} knex - knex实例
5
5
  */
6
- constructor(DB=Chan.knex) {
6
+ constructor(DB = Chan.knex) {
7
7
  this.knex = DB;
8
8
  this.DB = DB;
9
9
  this.model = ''; // 默认为空字符串
@@ -14,187 +14,187 @@ class BaseService {
14
14
  * @param {Object} query - 包含查询参数的对象
15
15
  * @returns {Promise} 返回所有记录
16
16
  */
17
- all(query={}) {
18
- if(Object.keys(query).length === 0) {
17
+ all(query = {}) {
18
+ if (Object.keys(query).length === 0) {
19
19
  return this.DB(this.model).select();
20
20
  }
21
21
  return this.DB(this.model).where(query).select();
22
22
  }
23
23
 
24
- /**
25
- * @description 根据指定条件查询记录
26
- * @param {Object} options - 包含查询参数的对象
27
- * @param {string} options.id - 查询字段名,默认为 'id'
28
- * @param {*} options.value - 查询字段值,默认为 0
29
- * @param {Array} options.field - 需要返回的字段数组,默认为空(即选择所有字段)
30
- * @param {number} options.len - 期望获取的记录数量,默认为 1(如果为 1 则使用 `.first()`,否则使用 `.limit(len)`)
31
- * @returns {Promise} 返回匹配条件的记录或记录列表
32
- */
33
- async findById({ query, field = [], len = 1 }) {
34
- let dataQuery = this.DB(this.model).where(query);
35
-
36
- // 字段筛选
37
- if (field.length > 0) {
38
- dataQuery = dataQuery.select(field);
39
- }
24
+ /**
25
+ * @description 根据指定条件查询记录
26
+ * @param {Object} options - 包含查询参数的对象
27
+ * @param {string} options.id - 查询字段名,默认为 'id'
28
+ * @param {*} options.value - 查询字段值,默认为 0
29
+ * @param {Array} options.field - 需要返回的字段数组,默认为空(即选择所有字段)
30
+ * @param {number} options.len - 期望获取的记录数量,默认为 1(如果为 1 则使用 `.first()`,否则使用 `.limit(len)`)
31
+ * @returns {Promise} 返回匹配条件的记录或记录列表
32
+ */
33
+ async findById({ query, field = [], len = 1 }) {
34
+ let dataQuery = this.DB(this.model).where(query);
35
+
36
+ // 字段筛选
37
+ if (field.length > 0) {
38
+ dataQuery = dataQuery.select(field);
39
+ }
40
40
 
41
- // 根据len决定是获取单条记录还是多条记录
42
- if (len === 1) {
43
- dataQuery = dataQuery.first();
44
- } else if (len > 1) {
45
- dataQuery = dataQuery.limit(len);
41
+ // 根据len决定是获取单条记录还是多条记录
42
+ if (len === 1) {
43
+ dataQuery = dataQuery.first();
44
+ } else if (len > 1) {
45
+ dataQuery = dataQuery.limit(len);
46
+ }
47
+ let res = await dataQuery;
48
+ //返回结果 undefined 则返回空数组或空对象
49
+ return res || (len === 1 ? {} : []);
46
50
  }
47
- let res = await dataQuery;
48
- //返回结果 undefined 则返回空数组或空对象
49
- return res || (len === 1 ? {} : []);
50
- }
51
51
 
52
52
 
53
- /**
54
- * @description 创建新记录
55
- * @param {Object} data - 包含要插入的数据对象
56
- * @returns {Promise<boolean>} 返回操作是否成功
57
- */
58
- async insert(data = {}) {
59
- if (Object.keys(data).length === 0) {
60
- return false;
53
+ /**
54
+ * @description 创建新记录
55
+ * @param {Object} data - 包含要插入的数据对象
56
+ * @returns {Promise<boolean>} 返回操作是否成功
57
+ */
58
+ async insert(data = {}) {
59
+ if (Object.keys(data).length === 0) {
60
+ return false;
61
+ }
62
+ const result = await this.DB(this.model).insert(data);
63
+ return result?.length > 0 || !!result;
61
64
  }
62
- const result = await this.DB(this.model).insert(data);
63
- return result?.length > 0 || !!result;
64
- }
65
65
 
66
66
  /**
67
67
  * @description 插入多条记录
68
68
  * @param {Array} records - 包含要插入的数据对象数组 [{<key>:<value>}, {<key>:<value>}, ...]
69
69
  * @returns {Promise<Array|Number>} 返回插入后的记录或受影响行数,具体取决于数据库驱动
70
70
  */
71
- async insertMany(records=[]) {
71
+ async insertMany(records = []) {
72
72
  // 如果没有提供数据或者数据为空,则直接返回 false 或者抛出异常
73
73
  if (records.length === 0) {
74
74
  console.log('插入数据不能为空')
75
75
  return false;
76
76
  }
77
-
77
+
78
78
  // 执行插入操作并获取结果
79
79
  const result = await this.DB(this.model).insert(records);
80
-
80
+
81
81
  // 返回插入的结果
82
82
  return result;
83
83
  }
84
-
85
- /**
86
- * @description 根据指定条件删除记录
87
- * @param {Object} query - 包含查询条件的对象
88
- * @returns {Promise<boolean>} 返回操作是否成功(即是否有任何记录被删除)
89
- */
90
- async delete(query = {}) {
91
- if (Object.keys(query).length === 0) {
92
- return false;
84
+
85
+ /**
86
+ * @description 根据指定条件删除记录
87
+ * @param {Object} query - 包含查询条件的对象
88
+ * @returns {Promise<boolean>} 返回操作是否成功(即是否有任何记录被删除)
89
+ */
90
+ async delete(query = {}) {
91
+ if (Object.keys(query).length === 0) {
92
+ return false;
93
+ }
94
+ const affectedRows = await this.DB(this.model).where(query).del();
95
+ return affectedRows > 0;
93
96
  }
94
- const affectedRows = await this.DB(this.model).where(query).del();
95
- return affectedRows > 0;
96
- }
97
- /**
98
- * @description 根据指定条件更新记录
99
- * @param {Object} query - 查询条件
100
- * @param {number} params - 保存内容
101
- * @returns {Promise<boolean>} 返回操作是否成功
102
- */
103
- async update({query, params} = {}) {
97
+ /**
98
+ * @description 根据指定条件更新记录
99
+ * @param {Object} query - 查询条件
100
+ * @param {number} params - 保存内容
101
+ * @returns {Promise<boolean>} 返回操作是否成功
102
+ */
103
+ async update({ query, params } = {}) {
104
104
  const result = await this.DB(this.model).where(query).update(params);
105
105
  return { affectedRows: result };
106
- }
106
+ }
107
107
 
108
108
 
109
- /**
110
- * @description 批量更新多条记录(基于事务保证原子性)
111
- * @param {Array<{query: Object, params: Object}>} updates - 更新操作数组,每个元素包含查询条件和更新内容
112
- * @returns {Promise<{ affectedRows: number[] }>} 返回每个操作影响的行数数组
113
- */
114
- async updateMany(updates = []) {
115
- // 参数合法性校验
116
- if (!Array.isArray(updates)) {
109
+ /**
110
+ * @description 批量更新多条记录(基于事务保证原子性)
111
+ * @param {Array<{query: Object, params: Object}>} updates - 更新操作数组,每个元素包含查询条件和更新内容
112
+ * @returns {Promise<{ affectedRows: number[] }>} 返回每个操作影响的行数数组
113
+ */
114
+ async updateMany(updates = []) {
115
+ // 参数合法性校验
116
+ if (!Array.isArray(updates)) {
117
117
  throw new Error('参数必须为数组格式');
118
- }
118
+ }
119
+
120
+ // 获取事务对象
121
+ const trx = await this.DB.transaction();
119
122
 
120
- // 获取事务对象
121
- const trx = await this.DB.transaction();
122
-
123
- try {
123
+ try {
124
124
  const affectedRows = [];
125
125
  // 循环处理每个更新操作
126
126
  for (const { query, params } of updates) {
127
- // 执行单个更新操作,使用事务对象替换原有knex实例
128
- const result = await trx(this.model)
129
- .where(query)
130
- .update(params);
131
- affectedRows.push(result);
127
+ // 执行单个更新操作,使用事务对象替换原有knex实例
128
+ const result = await trx(this.model)
129
+ .where(query)
130
+ .update(params);
131
+ affectedRows.push(result);
132
132
  }
133
133
  // 提交事务
134
134
  await trx.commit();
135
135
  // 返回影响行数数组(与入参顺序一致)
136
136
  return { affectedRows };
137
- } catch (err) {
137
+ } catch (err) {
138
138
  // 回滚事务
139
139
  await trx.rollback();
140
140
  // 错误向上抛出,由调用者处理
141
141
  throw err;
142
+ }
142
143
  }
143
- }
144
144
 
145
145
 
146
146
 
147
147
 
148
- /**
149
- * 查找所有符合条件的记录,并提供分页信息。
150
- * @param {Object} options - 包含查询参数的对象
151
- * @param {number} options.current - 当前页码,默认第一页
152
- * @param {number} options.pageSize - 每页大小,默认10条记录
153
- * @param {Object} options.query - 查询条件
154
- * @param {Array} options.field - 需要返回的字段
155
- * @returns {Promise<Object>} 返回包含数据列表、总记录数、当前页、每页大小的对象
156
- */
157
- async query({current = 1, pageSize = 10, query = {},field = []}) {
158
- const offset = (current - 1) * pageSize;
159
- let countQuery = this.DB(this.model).count("* as total");
160
- let dataQuery = this.DB(this.model);
161
- // 应用查询条件
162
- if(Object.keys(query).length > 0){
163
- Object.entries(query).forEach(([key, value]) => {
164
- dataQuery = dataQuery.where(key, value);
165
- countQuery = countQuery.where(key,value);
166
- })
167
- }
148
+ /**
149
+ * 查找所有符合条件的记录,并提供分页信息。
150
+ * @param {Object} options - 包含查询参数的对象
151
+ * @param {number} options.current - 当前页码,默认第一页
152
+ * @param {number} options.pageSize - 每页大小,默认10条记录
153
+ * @param {Object} options.query - 查询条件
154
+ * @param {Array} options.field - 需要返回的字段
155
+ * @returns {Promise<Object>} 返回包含数据列表、总记录数、当前页、每页大小的对象
156
+ */
157
+ async query({ current = 1, pageSize = 10, query = {}, field = [] }) {
158
+ const offset = (current - 1) * pageSize;
159
+ let countQuery = this.DB(this.model).count("* as total");
160
+ let dataQuery = this.DB(this.model);
161
+ // 应用查询条件
162
+ if (Object.keys(query).length > 0) {
163
+ Object.entries(query).forEach(([key, value]) => {
164
+ dataQuery = dataQuery.where(key, value);
165
+ countQuery = countQuery.where(key, value);
166
+ })
167
+ }
168
168
 
169
- //字段筛选
170
- if(field.length > 0){
171
- dataQuery = dataQuery.select(field);
172
- }
169
+ //字段筛选
170
+ if (field.length > 0) {
171
+ dataQuery = dataQuery.select(field);
172
+ }
173
173
 
174
- //并行执行获取总记录数和分页数据的查询
175
- const [totalResult, list] = await Promise.all([countQuery.first(), dataQuery.offset(offset).limit(pageSize)]);
176
- // 提取总记录数
177
- const total = totalResult?.total || 0;
174
+ //并行执行获取总记录数和分页数据的查询
175
+ const [totalResult, list] = await Promise.all([countQuery.first(), dataQuery.offset(offset).limit(pageSize)]);
176
+ // 提取总记录数
177
+ const total = totalResult?.total || 0;
178
178
 
179
- return { list, total, current, pageSize };
180
- }
179
+ return { list, total, current, pageSize };
180
+ }
181
181
 
182
182
 
183
- /**
184
- * @description 查询指定条件的记录数量
185
- * @param {Array} query - 数组形式的多个条件 [{<key>:<value>}, {<key>:<value>}, ...]
186
- * @returns {Promise<number>} 返回符合条件的记录数量
187
- */
188
- async count(query=[]) {
189
- let dataQuery = this.DB(this.model);
190
- if(query.length >0){
191
- query.forEach((condition) => {
192
- dataQuery = dataQuery.where(condition);
193
- });
194
- }
195
- const result = await dataQuery.count("* as total").first();
196
- return result.total || 0;
183
+ /**
184
+ * @description 查询指定条件的记录数量
185
+ * @param {Array} query - 数组形式的多个条件 [{<key>:<value>}, {<key>:<value>}, ...]
186
+ * @returns {Promise<number>} 返回符合条件的记录数量
187
+ */
188
+ async count(query = []) {
189
+ let dataQuery = this.DB(this.model);
190
+ if (query.length > 0) {
191
+ query.forEach((condition) => {
192
+ dataQuery = dataQuery.where(condition);
193
+ });
194
+ }
195
+ const result = await dataQuery.count("* as total").first();
196
+ return result.total || 0;
197
197
  }
198
-
198
+
199
199
  }
200
200
  export default BaseService;
package/core/lib/view.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
- import dayjs from 'dayjs';
3
- import { createRequire } from 'module';
2
+ import dayjs from "dayjs";
3
+ import { createRequire } from "module";
4
4
  const require = createRequire(import.meta.url);
5
5
 
6
6
  const template = require("art-template");
@@ -24,8 +24,8 @@ template.defaults.imports.dateFormat = function (date, format) {
24
24
 
25
25
  export default (app, config) => {
26
26
  const { APP_PATH, views, env } = config;
27
- //合并插件中的view
28
- const all = [...views, 'app/modules/web/view'];
27
+ //合并插件中的view
28
+ const all = [...views, "app/modules/web/view"];
29
29
 
30
30
  app.set("view options", {
31
31
  debug: env === "dev",
package/index.js CHANGED
@@ -4,14 +4,12 @@ import fs from "fs";
4
4
  import cors from "cors";
5
5
  import { pathToFileURL } from 'url'; // 新增顶部导入
6
6
  import config from "./core/config.js";
7
- import {bindClass,createKnex,loadWebToEnd} from "./core/helper.js";
8
-
9
-
7
+ import { bindClass, createKnex, loadWebToEnd } from "./core/helper.js";
10
8
 
11
9
  import Service from "./core/lib/service.js";
12
10
  import cache from './core/lib/cache.js';
13
11
  import core from "./core/lib/index.js";
14
- import extend from "./core/lib/extend.js";
12
+
15
13
  /**
16
14
  * @description 基于express封装的mvc框架,遵循约定优于配置原则
17
15
  */
@@ -21,27 +19,17 @@ class Chan {
21
19
  static plugins = {};
22
20
  static config = config;
23
21
  static cache = cache;
24
-
25
-
26
22
  constructor() {
27
23
  this.app = express();
28
24
  this.router = express.Router();
29
25
  }
30
-
31
26
  async init() {
32
- extend(this.app);
33
27
  await this.loadConfig();
34
28
  await this.loadExtends();
35
29
  this.loadCore();
36
30
  this.loadDB();
37
31
  this.loadCors();
38
32
  }
39
-
40
- extend(name, fn) {
41
- this.app.plus[name] = ()=>fn;
42
- }
43
-
44
-
45
33
  async loadConfig() {
46
34
  const configPath = path.join(Chan.config.APP_PATH, "config/index.js");
47
35
  if (fs.existsSync(configPath)) {
@@ -73,11 +61,11 @@ class Chan {
73
61
 
74
62
  //数据库操作
75
63
  loadDB() {
76
- if(Chan.config?.db?.length > 0){
77
- Chan.config.db.map((item,index) => {
78
- if(index ==0){
64
+ if (Chan.config?.db?.length > 0) {
65
+ Chan.config.db.map((item, index) => {
66
+ if (index == 0) {
79
67
  Chan.knex = createKnex(item);
80
- }else{
68
+ } else {
81
69
  Chan[`knex${index}`] = createKnex(item);
82
70
  }
83
71
  })
@@ -85,6 +73,11 @@ class Chan {
85
73
  }
86
74
  }
87
75
 
76
+ //解决跨域
77
+ loadCors() {
78
+ Chan.config?.cors?.origin && this.app.use(cors(Chan.config.cors));
79
+ }
80
+
88
81
  //开始启动
89
82
  beforeStart(cb) {
90
83
  cb && cb();
@@ -98,14 +91,9 @@ class Chan {
98
91
  cb && cb();
99
92
  }
100
93
 
101
- //解决跨域
102
- loadCors() {
103
- Chan.config?.cors?.origin && this.app.use(cors(Chan.config.cors));
104
- }
105
-
106
94
  // 加载插件
107
95
  async loadPlugins() {
108
- await this.loadModules("plugins");
96
+ await this.loadModules("plugins");
109
97
  }
110
98
 
111
99
  /**
@@ -116,7 +104,7 @@ class Chan {
116
104
  if (fs.existsSync(configPath)) {
117
105
  const dirs = loadWebToEnd(Chan.config[modules]);
118
106
  Chan[modules] = {};
119
-
107
+
120
108
  // 先加载所有服务
121
109
  for (const item of dirs) {
122
110
  Chan[modules][item] = {
@@ -125,14 +113,13 @@ class Chan {
125
113
  };
126
114
  await this.loadServices(modules, item); // 确保每个模块的服务加载完成
127
115
  }
128
-
116
+
129
117
  // 加载控制器和路由
130
118
  for (const item of dirs) {
131
119
  await this.loadModule(modules, item); // 确保每个模块的加载完成
132
120
  }
133
121
  }
134
122
  }
135
-
136
123
 
137
124
  /**
138
125
  * @description 加载模块,包括 controller service router
@@ -147,13 +134,18 @@ class Chan {
147
134
  const dir = path.join(Chan.config.APP_PATH, modules, moduleName, type);
148
135
  if (fs.existsSync(dir)) {
149
136
  const files = fs.readdirSync(dir).filter(file => file.endsWith(".js"));
150
- for (const file of files) { // 使用 for...of 确保异步操作顺序
151
- const filePath = path.join(dir, file);
152
- const fileUrl = pathToFileURL(filePath).href;
153
- const module = await import(fileUrl);
154
- const name = file.replace(".js", "");
155
- Chan[modules][moduleName][type][name] = { ...bindClass(module.default) };
156
- }
137
+ await Promise.all(files.map(async (file) => {
138
+ try {
139
+ const filePath = path.join(dir, file);
140
+ const fileUrl = pathToFileURL(filePath).href;
141
+ const module = await import(fileUrl);
142
+ const name = file.replace(".js", "");
143
+ Chan[modules][moduleName][type][name] = { ...bindClass(module.default) };
144
+ } catch (e) {
145
+ console.error(`加载${type}模块失败: ${file}`, e);
146
+ throw e;
147
+ }
148
+ }));
157
149
  }
158
150
  }
159
151
 
@@ -163,7 +155,7 @@ class Chan {
163
155
  * @param {*} moduleName 模块名称
164
156
  */
165
157
  async loadServices(modules, moduleName) {
166
- await this.loadFiles(modules, moduleName, "service");
158
+ await this.loadFiles(modules, moduleName, "service");
167
159
  }
168
160
 
169
161
  /**
@@ -206,7 +198,7 @@ class Chan {
206
198
  run(cb) {
207
199
  const port = Chan.config.port || "81";
208
200
  this.app.listen(port, () => {
209
- cb?cb(port):console.log(`Server is running on port ${port}`);
201
+ cb ? cb(port) : console.log(`Server is running on port ${port}`);
210
202
  });
211
203
  }
212
204
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "chanjs",
4
- "version": "1.1.4",
4
+ "version": "1.1.6",
5
5
  "description": "chanjs基于express5 纯js研发的轻量级mvc框架。",
6
6
  "main": "index.js",
7
7
  "module": "index.js",
@@ -1,13 +0,0 @@
1
- import express from "express";
2
- export default (app)=>{
3
- app.plus = {
4
- setStatic:function ({prefix,dir,maxAge}) {
5
- app.use(prefix, express.static(dir, { maxAge: maxAge || 0 }));
6
- }
7
- }
8
-
9
-
10
- }
11
-
12
-
13
-