mm_expand 1.9.7 → 1.9.8
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/README.md +45 -0
- package/README_EN.md +45 -0
- package/index.js +34 -13
- package/lib/array.js +3 -1
- package/lib/base.js +9 -17
- package/lib/event.js +5 -5
- package/lib/eventer.js +645 -587
- package/lib/file.js +8 -6
- package/lib/global.js +3 -1
- package/lib/lang.js +7 -5
- package/lib/{log.js → logger.js} +8 -8
- package/lib/string.js +1 -1
- package/lib/timer.js +65 -24
- package/lib/validator.js +1739 -0
- package/package.json +1 -1
- package/test/chain_validation_test.js +223 -0
- package/test/validator_test.js +1693 -0
- package/test_checkval.js +168 -0
- package/test_eventer_refactor.js +166 -0
- package/test_json.js +38 -0
- package/test_object_check.js +155 -0
- package//345/274/200/345/217/221/346/217/220/347/244/272/350/257/215.md +838 -0
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ mm_expand 是一个功能丰富的 JavaScript 工具库,为原生类型(Stri
|
|
|
15
15
|
|
|
16
16
|
- **原生类型扩展**:为 String、Array、Number、Date 等原生类型提供丰富的原型方法
|
|
17
17
|
- **对象操作增强**:提供深度拷贝、对象合并、属性遍历等实用功能
|
|
18
|
+
- **对象验证系统**:提供完整的对象属性验证功能,支持类型、必填、格式等验证规则
|
|
18
19
|
- **文件系统简化**:直观的文件读写、复制、删除等操作方法
|
|
19
20
|
- **灵活事件系统**:支持命名空间、优先级、中间件、节流防抖等高级特性
|
|
20
21
|
- **数据转换工具**:JSON、XML、URL 参数等格式转换功能
|
|
@@ -60,6 +61,19 @@ const formattedDate = new Date().toStr('yyyy-MM-dd hh:mm:ss'); // 格式化日
|
|
|
60
61
|
// 对象操作
|
|
61
62
|
const copiedObj = $.copy({ a: 1, b: { c: 2 } }); // 深度拷贝对象
|
|
62
63
|
|
|
64
|
+
// 对象验证
|
|
65
|
+
const user = { name: '张三', age: 25, email: 'zhangsan@example.com' };
|
|
66
|
+
// 批量验证
|
|
67
|
+
user.check({
|
|
68
|
+
name: { required: true, type: 'string', min: 2, max: 20 },
|
|
69
|
+
age: { required: true, type: 'number', min: 18, max: 100 },
|
|
70
|
+
email: { required: true, type: 'email' }
|
|
71
|
+
});
|
|
72
|
+
// 链式验证
|
|
73
|
+
user.checkVal('name', { required: true, type: 'string', min: 2, max: 20 })
|
|
74
|
+
.checkVal('age', { required: true, type: 'number', min: 18, max: 100 })
|
|
75
|
+
.checkVal('email', { required: true, type: 'email' });
|
|
76
|
+
|
|
63
77
|
// 事件系统使用
|
|
64
78
|
// 注册事件
|
|
65
79
|
$.eventer.on('user:login', (userData) => {
|
|
@@ -214,6 +228,37 @@ await $.sleep(2000, obj, 'ok');
|
|
|
214
228
|
- obj: 要查看的对象
|
|
215
229
|
- file: 保存结果的文件路径(可选)
|
|
216
230
|
|
|
231
|
+
### 对象验证
|
|
232
|
+
|
|
233
|
+
#### Object.prototype.check(rules)
|
|
234
|
+
- 描述:检查对象是否符合指定规则
|
|
235
|
+
- 参数:
|
|
236
|
+
- rules: 验证规则对象
|
|
237
|
+
- 返回值:验证通过返回原始对象,失败抛出TypeError
|
|
238
|
+
- 示例:
|
|
239
|
+
```javascript
|
|
240
|
+
const user = { name: '张三', age: 25, email: 'zhangsan@example.com' };
|
|
241
|
+
user.check({
|
|
242
|
+
name: { required: true, type: 'string', min: 2, max: 20 },
|
|
243
|
+
age: { required: true, type: 'number', min: 18, max: 100 },
|
|
244
|
+
email: { required: true, type: 'email' }
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Object.prototype.checkVal(key, rule)
|
|
249
|
+
- 描述:检查对象属性值是否符合指定规则
|
|
250
|
+
- 参数:
|
|
251
|
+
- key: 属性名
|
|
252
|
+
- rule: 验证规则
|
|
253
|
+
- 返回值:验证通过返回原始对象,失败抛出TypeError
|
|
254
|
+
- 示例:
|
|
255
|
+
```javascript
|
|
256
|
+
const user = { name: '张三', age: 25, email: 'zhangsan@example.com' };
|
|
257
|
+
user.checkVal('name', { required: true, type: 'string', min: 2, max: 20 })
|
|
258
|
+
.checkVal('age', { required: true, type: 'number', min: 18, max: 100 })
|
|
259
|
+
.checkVal('email', { required: true, type: 'email' });
|
|
260
|
+
```
|
|
261
|
+
|
|
217
262
|
### 数据转换
|
|
218
263
|
|
|
219
264
|
#### $.toJson(obj, format)
|
package/README_EN.md
CHANGED
|
@@ -15,6 +15,7 @@ This library extends JavaScript native object prototypes with comprehensive data
|
|
|
15
15
|
|
|
16
16
|
- **Native Type Extension**: Rich prototype methods for native types like String, Array, Number, Date, etc.
|
|
17
17
|
- **Enhanced Object Operations**: Deep copy, object merging, property traversal, and other practical functions
|
|
18
|
+
- **Object Validation System**: Complete object property validation with support for type, required, format, and other validation rules
|
|
18
19
|
- **Simplified File System**: Intuitive file read/write, copy, delete, and other operation methods
|
|
19
20
|
- **Flexible Event System**: Supports advanced features like namespaces, priorities, middleware, throttling, and debouncing
|
|
20
21
|
- **Data Conversion Tools**: JSON, XML, URL parameters, and other format conversion functions
|
|
@@ -86,6 +87,19 @@ const formattedDate = new Date().toStr('yyyy-MM-dd hh:mm:ss'); // Format date
|
|
|
86
87
|
// Object operations
|
|
87
88
|
const copiedObj = $.copy({ a: 1, b: { c: 2 } }); // Deep copy object
|
|
88
89
|
|
|
90
|
+
// Object validation
|
|
91
|
+
const user = { name: 'John', age: 25, email: 'john@example.com' };
|
|
92
|
+
// Batch validation
|
|
93
|
+
user.check({
|
|
94
|
+
name: { required: true, type: 'string', min: 2, max: 20 },
|
|
95
|
+
age: { required: true, type: 'number', min: 18, max: 100 },
|
|
96
|
+
email: { required: true, type: 'email' }
|
|
97
|
+
});
|
|
98
|
+
// Chain validation
|
|
99
|
+
user.checkVal('name', { required: true, type: 'string', min: 2, max: 20 })
|
|
100
|
+
.checkVal('age', { required: true, type: 'number', min: 18, max: 100 })
|
|
101
|
+
.checkVal('email', { required: true, type: 'email' });
|
|
102
|
+
|
|
89
103
|
// Event system usage
|
|
90
104
|
// Register event
|
|
91
105
|
$.eventer.on('user:login', (userData) => {
|
|
@@ -240,6 +254,37 @@ await $.sleep(2000, obj, 'ok');
|
|
|
240
254
|
- obj: Object to inspect
|
|
241
255
|
- file: File path to save results (optional)
|
|
242
256
|
|
|
257
|
+
### Object Validation
|
|
258
|
+
|
|
259
|
+
#### Object.prototype.check(rules)
|
|
260
|
+
- Description: Check if object conforms to specified rules
|
|
261
|
+
- Parameters:
|
|
262
|
+
- rules: Validation rules object
|
|
263
|
+
- Returns: Returns original object if validation passes, throws TypeError if fails
|
|
264
|
+
- Example:
|
|
265
|
+
```javascript
|
|
266
|
+
const user = { name: 'John', age: 25, email: 'john@example.com' };
|
|
267
|
+
user.check({
|
|
268
|
+
name: { required: true, type: 'string', min: 2, max: 20 },
|
|
269
|
+
age: { required: true, type: 'number', min: 18, max: 100 },
|
|
270
|
+
email: { required: true, type: 'email' }
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Object.prototype.checkVal(key, rule)
|
|
275
|
+
- Description: Check if object property value conforms to specified rules
|
|
276
|
+
- Parameters:
|
|
277
|
+
- key: Property name
|
|
278
|
+
- rule: Validation rule
|
|
279
|
+
- Returns: Returns original object if validation passes, throws TypeError if fails
|
|
280
|
+
- Example:
|
|
281
|
+
```javascript
|
|
282
|
+
const user = { name: 'John', age: 25, email: 'john@example.com' };
|
|
283
|
+
user.checkVal('name', { required: true, type: 'string', min: 2, max: 20 })
|
|
284
|
+
.checkVal('age', { required: true, type: 'number', min: 18, max: 100 })
|
|
285
|
+
.checkVal('email', { required: true, type: 'email' });
|
|
286
|
+
```
|
|
287
|
+
|
|
243
288
|
### Data Conversion
|
|
244
289
|
|
|
245
290
|
#### $.toJson(obj, format)
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileOverview JavaScript拓展函数
|
|
3
|
-
* @author <a href="http://qww.elins.cn"
|
|
3
|
+
* @author <a href="http://qww.elins.cn">qww</a>
|
|
4
4
|
* @version 1.2
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -16,30 +16,29 @@ require('./lib/array.js');
|
|
|
16
16
|
require('./lib/date.js');
|
|
17
17
|
|
|
18
18
|
var { File, Dir } = require('./lib/file.js');
|
|
19
|
-
var {
|
|
20
|
-
var { Eventer } = require('./lib/eventer.js');
|
|
19
|
+
var { Logger } = require('./lib/logger.js');
|
|
20
|
+
var { Eventer, eventer } = require('./lib/eventer.js');
|
|
21
21
|
var { Lang } = require('./lib/lang.js');
|
|
22
22
|
var { Event } = require('./lib/event.js');
|
|
23
23
|
var { Base } = require('./lib/base.js');
|
|
24
24
|
var { Timer } = require('./lib/timer.js');
|
|
25
|
+
var { Validator, validator } = require('./lib/validator.js');
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
if (global.$ && !$.is_init) {
|
|
28
29
|
Object.assign($, require('./lib/object.js'), {
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
30
|
+
// 验证器类
|
|
31
|
+
validator,
|
|
32
|
+
// 事件驱动类
|
|
33
|
+
eventer,
|
|
34
|
+
// 日志类
|
|
35
|
+
logger: new Logger(),
|
|
33
36
|
// 文件类
|
|
34
37
|
file: new File(),
|
|
35
38
|
// 目录类
|
|
36
39
|
dir: new Dir(),
|
|
37
|
-
// 事件驱动类
|
|
38
|
-
eventer: new Eventer(),
|
|
39
40
|
// 定时器类
|
|
40
41
|
timer: new Timer(),
|
|
41
|
-
// 日志类
|
|
42
|
-
log: new Log(),
|
|
43
42
|
// 语言包类
|
|
44
43
|
lang: new Lang({
|
|
45
44
|
zh_cn: {
|
|
@@ -48,16 +47,38 @@ if (global.$ && !$.is_init) {
|
|
|
48
47
|
en: {
|
|
49
48
|
name: "MM"
|
|
50
49
|
}
|
|
51
|
-
})
|
|
50
|
+
}),
|
|
51
|
+
// 基础类
|
|
52
|
+
Base,
|
|
53
|
+
// 事件类
|
|
54
|
+
Event
|
|
52
55
|
});
|
|
53
56
|
$.is_init = true;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
module.exports = {
|
|
60
|
+
// 全局对象
|
|
61
|
+
$: global.$,
|
|
62
|
+
// 验证器类
|
|
63
|
+
Validator,
|
|
64
|
+
// 事件类
|
|
57
65
|
Event,
|
|
66
|
+
// 事件驱动类
|
|
58
67
|
Eventer,
|
|
68
|
+
// 定时器类
|
|
69
|
+
Timer,
|
|
70
|
+
// 日志类
|
|
71
|
+
Logger,
|
|
72
|
+
// 语言包类
|
|
59
73
|
Lang,
|
|
74
|
+
// 基础类
|
|
60
75
|
Base,
|
|
76
|
+
// 文件类
|
|
61
77
|
File,
|
|
62
|
-
|
|
78
|
+
// 目录类
|
|
79
|
+
Dir,
|
|
80
|
+
// 验证器实例
|
|
81
|
+
validator,
|
|
82
|
+
// 事件驱动实例
|
|
83
|
+
eventer
|
|
63
84
|
}
|
package/lib/array.js
CHANGED
package/lib/base.js
CHANGED
|
@@ -48,16 +48,6 @@ class Base extends Event {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/**
|
|
52
|
-
* 日志输出
|
|
53
|
-
* @param {String} level 日志级别
|
|
54
|
-
* @param {String} message 日志消息
|
|
55
|
-
* @param {...any} args 日志参数
|
|
56
|
-
*/
|
|
57
|
-
Base.prototype.logger = function (level, message, ...args) {
|
|
58
|
-
this._logger[level](`[${this.constructor.name}] ${message}`, ...args);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
51
|
/**
|
|
62
52
|
* 初始化监听
|
|
63
53
|
*/
|
|
@@ -181,7 +171,7 @@ Base.prototype.end = async function () {
|
|
|
181
171
|
*/
|
|
182
172
|
Base.prototype.do = async function (method, ...args) {
|
|
183
173
|
if (!this[method]) {
|
|
184
|
-
throw new Error(
|
|
174
|
+
throw new Error(`方法${method}不存在`);
|
|
185
175
|
}
|
|
186
176
|
|
|
187
177
|
let ctx = {
|
|
@@ -229,7 +219,7 @@ Base.prototype.do = async function (method, ...args) {
|
|
|
229
219
|
// 5. 错误处理(异步执行,不阻塞)
|
|
230
220
|
if (ctx.error) {
|
|
231
221
|
await this.emitAsync(method + ':error', ctx);
|
|
232
|
-
this.
|
|
222
|
+
this.log('error', `执行方法${method}出错:`, ctx.error);
|
|
233
223
|
}
|
|
234
224
|
|
|
235
225
|
// 6. 后置处理(顺序执行)
|
|
@@ -247,7 +237,7 @@ Base.prototype.do = async function (method, ...args) {
|
|
|
247
237
|
Base.prototype.doEasy = async function (method, ...args) {
|
|
248
238
|
// 快速检查方法是否存在
|
|
249
239
|
if (!this[method]) {
|
|
250
|
-
throw new Error(
|
|
240
|
+
throw new Error(`方法${method}不存在`);
|
|
251
241
|
}
|
|
252
242
|
|
|
253
243
|
try {
|
|
@@ -255,7 +245,7 @@ Base.prototype.doEasy = async function (method, ...args) {
|
|
|
255
245
|
return await this[method](...args);
|
|
256
246
|
} catch (error) {
|
|
257
247
|
// 简单错误处理
|
|
258
|
-
this.
|
|
248
|
+
this.log('error', `快速执行方法${method}出错:`, error);
|
|
259
249
|
throw error;
|
|
260
250
|
}
|
|
261
251
|
}
|
|
@@ -335,7 +325,7 @@ Base.prototype.cmd = async function (command, ...args) {
|
|
|
335
325
|
try {
|
|
336
326
|
return await obj(...args);
|
|
337
327
|
} catch (error) {
|
|
338
|
-
this.
|
|
328
|
+
this.log('error', `执行方法${command}出错:`, error);
|
|
339
329
|
return undefined;
|
|
340
330
|
}
|
|
341
331
|
} else if (Array.isArray(obj)) {
|
|
@@ -442,5 +432,7 @@ function createClass(config, cs_old = {}) {
|
|
|
442
432
|
return cs;
|
|
443
433
|
};
|
|
444
434
|
|
|
445
|
-
exports
|
|
446
|
-
|
|
435
|
+
module.exports = {
|
|
436
|
+
Base,
|
|
437
|
+
createClass
|
|
438
|
+
}
|
package/lib/event.js
CHANGED
|
@@ -17,7 +17,7 @@ class Event extends EventEmitter {
|
|
|
17
17
|
* @param {String} message 日志消息
|
|
18
18
|
* @param {...any} args 日志参数
|
|
19
19
|
*/
|
|
20
|
-
Event.prototype.
|
|
20
|
+
Event.prototype.log = function (level, message, ...args) {
|
|
21
21
|
this._logger[level](`[${this.constructor.name}] ${message}`, ...args);
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -36,7 +36,7 @@ Event.prototype.emitWait = async function (event, ...args) {
|
|
|
36
36
|
try {
|
|
37
37
|
await listener(...args);
|
|
38
38
|
} catch (err) {
|
|
39
|
-
this.
|
|
39
|
+
this.log('error', 'Error in async event listener:', err);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -62,12 +62,12 @@ Event.prototype.emitAsync = async function (event, ...args) {
|
|
|
62
62
|
Promise.resolve(listener(...args))
|
|
63
63
|
.catch(error => {
|
|
64
64
|
// 错误处理 - 记录但不抛出
|
|
65
|
-
this.
|
|
65
|
+
this.log('error', `Async listener error for event ${event}:`, error);
|
|
66
66
|
this.emit('async:error', error, event, args);
|
|
67
67
|
});
|
|
68
68
|
} catch (syncError) {
|
|
69
69
|
// 同步错误处理
|
|
70
|
-
this.
|
|
70
|
+
this.log('error', `Sync listener error for event ${event}:`, syncError);
|
|
71
71
|
this.emit('sync:error', syncError, event, args);
|
|
72
72
|
}
|
|
73
73
|
});
|
|
@@ -142,7 +142,7 @@ Event.prototype.emitWaterfall = async function (event, value, ...args) {
|
|
|
142
142
|
try {
|
|
143
143
|
val = await listener(val, ...args);
|
|
144
144
|
} catch (error) {
|
|
145
|
-
this.
|
|
145
|
+
this.log('error', 'Waterfall execution failed:', error);
|
|
146
146
|
throw error;
|
|
147
147
|
}
|
|
148
148
|
}
|