mm_config 2.1.3 → 2.1.5

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.
Files changed (6) hide show
  1. package/README.md +284 -194
  2. package/index.js +337 -185
  3. package/package.json +3 -3
  4. package/test.js +132 -65
  5. package/base.js +0 -30
  6. package/config.json +0 -6
package/README.md CHANGED
@@ -1,194 +1,284 @@
1
- # mm_config
2
-
3
- 超级美眉配置帮助类,动态同步文件修改配置。
4
-
5
- ## 功能特点
6
-
7
- - 支持配置文件的动态读取和修改
8
- - 修改配置后自动同步保存到JSON文件
9
- - 使用Proxy实现属性监听,操作方便
10
- - 支持同步和异步API操作
11
- - 支持配置修改防抖功能,减少频繁保存
12
- - 内置错误处理机制,提高稳定性
13
- - 支持JSON5格式配置文件
14
- - 向后兼容原有API
15
-
16
- ## 安装
17
-
18
- ```bash
19
- npm install mm_config
20
- ```
21
-
22
- ## API说明
23
-
24
- ### 导入模块
25
-
26
- ```javascript
27
- // 导入同步配置创建函数(默认)
28
- const conf = require('mm_config');
29
-
30
- // 导入异步配置创建函数
31
- const createConfigAsync = conf.createConfigAsync;
32
-
33
- // 导入配置管理器类
34
- const { ConfigManager } = require('mm_config');
35
- ```
36
-
37
- ### 配置初始化
38
-
39
- #### 同步API
40
-
41
- ```javascript
42
- /**
43
- * 创建同步配置管理器
44
- * @param {Object} _config 配置对象,可选,不传则从文件读取
45
- * @param {String} _jsonFile 配置文件路径,可选,不传则使用this.filename
46
- * @param {Object} options 配置选项,可选
47
- * @param {Number} options.debounceTime 防抖时间(ms),默认0
48
- * @param {Boolean} options.pretty 是否美化输出,默认true
49
- * @param {String} options.format 格式(json/json5),默认json
50
- * @returns {Proxy} 返回配置代理对象
51
- */
52
- const config = conf(_config, _jsonFile, options);
53
- ```
54
-
55
- #### 异步API
56
-
57
- ```javascript
58
- /**
59
- * 创建异步配置管理器
60
- * @param {Object} _config 配置对象,可选,不传则从文件读取
61
- * @param {String} _jsonFile 配置文件路径,可选,不传则使用this.filename
62
- * @param {Object} options 配置选项,可选
63
- * @returns {Promise<Proxy>} 返回配置代理对象的Promise
64
- */
65
- const config = await createConfigAsync(_config, _jsonFile, options);
66
- ```
67
-
68
- #### 代理对象特殊方法
69
-
70
- 通过代理对象可以访问以下特殊方法:
71
-
72
- - `_saveSync()`: 同步保存配置到文件
73
- - `_saveAsync()`: 异步保存配置到文件
74
- - `_raw`: 获取原始配置对象
75
-
76
- ## 使用示例
77
-
78
- ### 1. 基本同步配置(兼容原API)
79
-
80
- ```javascript
81
- // 创建配置并指定保存路径
82
- const config = conf({
83
- name: "demo",
84
- state: 1
85
- }, "./config.json");
86
-
87
- // 修改配置会自动保存到文件
88
- config.name = "test";
89
- config.sort = 2;
90
-
91
- // 显式调用保存
92
- config._saveSync();
93
-
94
- // 读取现有配置
95
- const existingConfig = conf(null, "./config.json");
96
- ```
97
-
98
- ### 2. 使用异步API
99
-
100
- ```javascript
101
- async function setupConfig() {
102
- // 创建异步配置
103
- const config = await createConfigAsync({
104
- name: "asyncDemo",
105
- version: "1.0.0"
106
- }, "./async_config.json");
107
-
108
- // 修改配置会异步自动保存
109
- config.timestamp = new Date().toISOString();
110
-
111
- // 显式调用异步保存
112
- await config._saveAsync();
113
-
114
- return config;
115
- }
116
- ```
117
-
118
- ### 3. 使用防抖功能
119
-
120
- ```javascript
121
- // 创建带防抖的配置(500ms延迟保存)
122
- const debouncedConfig = conf({
123
- name: "debounceDemo"
124
- }, "./debounce_config.json", {
125
- debounceTime: 500 // 500ms防抖时间
126
- });
127
-
128
- // 快速多次修改,只会在最后一次修改后500ms保存一次
129
- for (let i = 0; i < 10; i++) {
130
- debouncedConfig.counter = i;
131
- debouncedConfig.timestamp = new Date().toISOString();
132
- }
133
- ```
134
-
135
- ### 4. 使用JSON5格式
136
-
137
- ```javascript
138
- // 创建支持JSON5格式的配置
139
- const json5Config = conf(null, "./config.json5", {
140
- format: 'json5'
141
- });
142
-
143
- // JSON5格式支持注释、尾随逗号等特性
144
- json5Config.description = "This supports JSON5 format";
145
- ```
146
-
147
- ### 5. 直接使用ConfigManager类
148
-
149
- ```javascript
150
- const { ConfigManager } = require('mm_config');
151
-
152
- // 创建配置管理器实例
153
- const manager = new ConfigManager({
154
- name: "directDemo"
155
- }, "./direct_config.json");
156
-
157
- // 获取代理对象
158
- const config = manager.getProxy();
159
-
160
- // 使用配置
161
- config.version = "1.0.0";
162
-
163
- // 手动调用保存方法
164
- manager.saveSync();
165
- await manager.saveAsync();
166
- ```
167
-
168
- ## 配置选项
169
-
170
- 创建配置时可提供以下选项:
171
-
172
- | 选项 | 类型 | 默认值 | 描述 |
173
- |------|------|--------|------|
174
- | debounceTime | Number | 0 | 防抖时间(毫秒),设置后多次修改会延迟保存 |
175
- | pretty | Boolean | true | 是否美化JSON输出,设为false可生成压缩的JSON |
176
- | format | String | 'json' | 配置文件格式,可选'json'或'json5' |
177
-
178
- ## 注意事项
179
-
180
- 1. 配置文件会自动创建和同步
181
- 2. 修改配置对象的属性会自动保存到文件
182
- 3. 确保有文件的写入权限
183
- 4. 使用防抖功能可以减少频繁的文件IO操作
184
- 5. 异步API适合在非阻塞环境中使用
185
- 6. 当使用JSON5格式时,保存仍使用标准JSON格式,但可读取JSON5格式的文件
186
-
187
- ## 依赖
188
-
189
- - json5: 用于解析JSON5格式
190
- - mm_expand: 提供文件操作扩展
191
-
192
- ## 许可证
193
-
194
- ISC License
1
+ # mm_config
2
+
3
+ 超级美眉配置帮助类,动态同步文件修改配置。
4
+
5
+ ## 功能特点
6
+
7
+ - 支持配置文件的动态读取和修改
8
+ - 修改配置后自动同步保存到JSON文件
9
+ - 使用Proxy实现属性监听,操作方便
10
+ - 支持同步和异步API操作
11
+ - 支持配置修改防抖功能,减少频繁保存
12
+ - 内置错误处理机制,提高稳定性
13
+ - 支持JSON5格式配置文件
14
+ - 简洁命名,遵循单字优先原则
15
+ - 内置缓存管理,避免重复创建配置实例
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ npm install mm_config
21
+ ```
22
+
23
+ ## API说明
24
+
25
+ ### 导入模块
26
+
27
+ ```javascript
28
+ // 导入配置类
29
+ const { Config, create, createAsync, clear, clearAll } = require('mm_config');
30
+ ```
31
+
32
+ ### 配置初始化
33
+
34
+ #### 同步API
35
+
36
+ ```javascript
37
+ /**
38
+ * 创建同步配置
39
+ * @param {String} file - 配置文件路径
40
+ * @param {Object} config - 配置对象,可选
41
+ * @param {Object} options - 配置选项,可选
42
+ * @param {Number} options.debounce_time - 防抖时间(ms),默认0
43
+ * @param {Boolean} options.pretty - 是否美化输出,默认true
44
+ * @param {String} options.format - 格式(json/json5),默认json
45
+ * @returns {Proxy} 返回配置代理对象
46
+ */
47
+ const config = create(file, config, options);
48
+ ```
49
+
50
+ #### 异步API
51
+
52
+ ```javascript
53
+ /**
54
+ * 创建异步配置
55
+ * @param {String} file - 配置文件路径
56
+ * @param {Object} config - 配置对象,可选
57
+ * @param {Object} options - 配置选项,可选
58
+ * @returns {Promise<Proxy>} 返回配置代理对象的Promise
59
+ */
60
+ const config = await createAsync(file, config, options);
61
+ ```
62
+
63
+ #### 缓存管理API
64
+
65
+ ```javascript
66
+ /**
67
+ * 清理指定文件配置缓存
68
+ * @param {String} file - 配置文件路径
69
+ */
70
+ clear(file);
71
+
72
+ /**
73
+ * 清理所有配置缓存
74
+ */
75
+ clearAll();
76
+ ```
77
+
78
+ #### 代理对象特殊方法
79
+
80
+ 通过代理对象可以访问以下特殊方法:
81
+
82
+ - `_saveSync()`: 同步保存配置到文件
83
+ - `_saveAsync()`: 异步保存配置到文件
84
+ - `_raw`: 获取原始配置对象
85
+
86
+ ## 使用示例
87
+
88
+ ### 1. 基本同步配置
89
+
90
+ ```javascript
91
+ const { create } = require('mm_config');
92
+
93
+ // 创建配置并指定保存路径
94
+ const config = create("./config.json", {
95
+ name: "demo",
96
+ state: 1
97
+ });
98
+
99
+ // 修改配置会自动保存到文件
100
+ config.name = "test";
101
+ config.sort = 2;
102
+
103
+ // 显式调用保存
104
+ config._saveSync();
105
+
106
+ // 读取现有配置
107
+ const existingConfig = create("./config.json");
108
+ ```
109
+
110
+ ### 2. 使用异步API
111
+
112
+ ```javascript
113
+ const { createAsync } = require('mm_config');
114
+
115
+ async function setupConfig() {
116
+ // 创建异步配置
117
+ const config = await createAsync("./async_config.json", {
118
+ name: "asyncDemo",
119
+ version: "1.0.0"
120
+ });
121
+
122
+ // 修改配置会异步自动保存
123
+ config.timestamp = new Date().toISOString();
124
+
125
+ // 显式调用异步保存
126
+ await config._saveAsync();
127
+
128
+ return config;
129
+ }
130
+ ```
131
+
132
+ ### 3. 使用防抖功能
133
+
134
+ ```javascript
135
+ const { create } = require('mm_config');
136
+
137
+ // 创建带防抖的配置(500ms延迟保存)
138
+ const config = create("./debounce_config.json", {
139
+ name: "debounceDemo"
140
+ }, {
141
+ debounce_time: 500 // 500ms防抖时间
142
+ });
143
+
144
+ // 快速多次修改,只会在最后一次修改后500ms保存一次
145
+ for (let i = 0; i < 10; i++) {
146
+ config.counter = i;
147
+ config.timestamp = new Date().toISOString();
148
+ }
149
+ ```
150
+
151
+ ### 4. 使用JSON5格式
152
+
153
+ ```javascript
154
+ const { create } = require('mm_config');
155
+
156
+ // 创建支持JSON5格式的配置
157
+ const config = create("./config.json5", null, {
158
+ format: 'json5'
159
+ });
160
+
161
+ // JSON5格式支持注释、尾随逗号等特性
162
+ config.description = "This supports JSON5 format";
163
+ ```
164
+
165
+ ### 5. 直接使用Config类
166
+
167
+ ```javascript
168
+ const { Config } = require('mm_config');
169
+
170
+ // 创建配置实例
171
+ const cfg = new Config({
172
+ name: "directDemo"
173
+ }, "./direct_config.json");
174
+
175
+ // 获取代理对象
176
+ const config = cfg.getProxy();
177
+
178
+ // 使用配置
179
+ config.version = "1.0.0";
180
+
181
+ // 手动调用保存方法
182
+ cfg.saveSync();
183
+ await cfg.saveAsync();
184
+ ```
185
+
186
+ ### 6. 使用配置操作方法
187
+
188
+ ```javascript
189
+ const { Config } = require('mm_config');
190
+
191
+ const cfg = new Config({}, "./methods_config.json");
192
+
193
+ // 设置配置值
194
+ await cfg.set("name", "test");
195
+
196
+ // 获取配置值
197
+ const name = await cfg.get("name");
198
+
199
+ // 检查配置是否存在
200
+ const hasName = await cfg.has("name");
201
+
202
+ // 删除配置项
203
+ await cfg.del("name");
204
+
205
+ // 获取所有键
206
+ const keys = await cfg.keys();
207
+ ```
208
+
209
+ ### 7. 缓存管理功能
210
+
211
+ ```javascript
212
+ const { create, clear, clearAll } = require('mm_config');
213
+
214
+ // 创建配置实例
215
+ const config1 = create("./cache1.json", { test: "cache1" });
216
+ const config2 = create("./cache2.json", { test: "cache2" });
217
+
218
+ // 清理指定文件缓存
219
+ clear("./cache1.json");
220
+
221
+ // 重新创建会生成新实例
222
+ const config1New = create("./cache1.json", { test: "cache1_new" });
223
+
224
+ // 清理所有缓存
225
+ clearAll();
226
+
227
+ // 所有配置都会重新创建
228
+ const config2New = create("./cache2.json", { test: "cache2_new" });
229
+ ```
230
+
231
+ ## 配置选项
232
+
233
+ 创建配置时可提供以下选项:
234
+
235
+ | 选项 | 类型 | 默认值 | 描述 |
236
+ |------|------|--------|------|
237
+ | debounce_time | Number | 0 | 防抖时间(毫秒),设置后多次修改会延迟保存 |
238
+ | pretty | Boolean | true | 是否美化JSON输出,设为false可生成压缩的JSON |
239
+ | format | String | 'json' | 配置文件格式,可选'json'或'json5' |
240
+
241
+ ## 注意事项
242
+
243
+ 1. 配置文件会自动创建和同步
244
+ 2. 修改配置对象的属性会自动保存到文件
245
+ 3. 确保有文件的写入权限
246
+ 4. 使用防抖功能可以减少频繁的文件IO操作
247
+ 5. 异步API适合在非阻塞环境中使用
248
+ 6. 当使用JSON5格式时,保存仍使用标准JSON格式,但可读取JSON5格式的文件
249
+ 7. 配置实例会被缓存,相同文件路径会返回同一实例,使用clear/clearAll可清理缓存
250
+
251
+ ## 依赖
252
+
253
+ - json5: 用于解析JSON5格式
254
+ - mm_expand: 提供文件操作扩展
255
+
256
+ ## 命名规范
257
+
258
+ 本模块遵循简洁命名原则:
259
+ - 类名:`Config`(单字优先)
260
+ - 方法名:`get()`、`set()`、`has()`、`del()`(动词开头)
261
+ - 变量名:`val`、`key`、`bl`(简洁无废话)
262
+
263
+ ## 测试
264
+
265
+ ```bash
266
+ # 运行测试
267
+ npm test
268
+ ```
269
+
270
+ ## 许可证
271
+
272
+ ISC License
273
+
274
+ ## 版本历史
275
+
276
+ - v2.1.4: 添加缓存管理功能,修复内存泄漏问题
277
+ - v2.1.3: 重构API,遵循简洁命名规范
278
+ - v2.1.2: 添加JSON5格式支持
279
+ - v2.1.1: 优化防抖功能
280
+ - v2.1.0: 初始版本发布
281
+
282
+ ## 贡献
283
+
284
+ 欢迎提交Issue和Pull Request来改进这个项目。
package/index.js CHANGED
@@ -1,199 +1,351 @@
1
- require('mm_logs');
2
-
3
- /**
4
- * 配置管理器类,提供同步和异步API
5
- */
6
- class ConfigManager {
7
- /**
8
- * 构造函数
9
- * @param {Object} _config 配置对象
10
- * @param {String} _jsonFile 配置文件路径
11
- * @param {Object} options 配置选项
12
- * @param {Number} options.debounceTime 防抖时间(ms)
13
- * @param {Boolean} options.pretty 是否美化输出
14
- * @param {String} options.format 格式(json/json5)
15
- */
16
- constructor(_config, _jsonFile, options = {}) {
17
- this.config = _config || {};
18
- this.filePath = _jsonFile;
19
- this.options = {
20
- debounceTime: 0, // 默认不防抖
21
- pretty: true,
22
- format: 'json',
23
- ...options
24
- };
25
- this.writeTimer = null;
26
- this.writePromise = Promise.resolve();
27
-
28
- // 如果没有提供配置且有文件路径,则从文件加载
29
- if (!_config && _jsonFile) {
30
- try {
31
- this.config = _jsonFile.loadJson();
32
- } catch(error) {
33
- $.log.error(`[Config] Error loading config from ${_jsonFile}:`, error.message);
34
- this.config = {};
35
- }
36
- }
37
- }
38
-
39
- /**
40
- * 保存配置到文件(同步)
41
- */
42
- saveSync() {
43
- if (!this.filePath) return false;
44
- try {
45
- this.filePath.saveJson(this.config);
46
- return true;
47
- } catch(error) {
48
- $.log.error(`[Config] Error saving config to ${this.filePath}:`, error.message);
49
- return false;
50
- }
51
- }
52
-
53
- /**
54
- * 保存配置到文件(异步)
55
- * @returns {Promise<Boolean>}
56
- */
57
- async saveAsync() {
58
- if (!this.filePath) return Promise.resolve(true);
59
-
60
- // 确保之前的写操作完成
61
- await this.writePromise;
62
-
63
- this.writePromise = Promise.resolve()
64
- .then(() => {
65
- this.filePath.saveJson(this.config);
66
- return true;
67
- })
68
- .catch(error => {
69
- $.log.error(`[Config] Error saving config to ${this.filePath}:`, error.message);
70
- return false;
71
- });
72
-
73
- return this.writePromise;
74
- }
75
-
76
- /**
77
- * 获取代理对象
78
- * @returns {Proxy}
79
- */
80
- getProxy() {
81
- const self = this;
82
-
83
- return new Proxy(this.config, {
84
- set(obj, prop, value) {
85
- obj[prop] = value;
86
-
87
- if (self.options.debounceTime > 0) {
88
- // 防抖处理
89
- if (self.writeTimer) {
90
- clearTimeout(self.writeTimer);
91
- }
92
- self.writeTimer = setTimeout(() => {
93
- self.saveSync();
94
- }, self.options.debounceTime);
95
- } else {
96
- // 无防抖,直接保存
97
- self.saveSync();
98
- }
99
-
100
- return true;
101
- },
102
-
103
- get(obj, prop) {
104
- // 提供一些特殊属性访问
105
- if (prop === '_saveAsync') {
106
- return () => self.saveAsync();
107
- }
108
- if (prop === '_saveSync') {
109
- return () => self.saveSync();
110
- }
111
- if (prop === '_raw') {
112
- return obj;
113
- }
114
-
115
- return obj[prop];
116
- }
117
- });
118
- }
119
-
120
- /**
121
- * 获取异步代理对象
122
- * @returns {Proxy}
123
- */
124
- getAsyncProxy() {
125
- const self = this;
126
-
127
- return new Proxy(this.config, {
128
- set(obj, prop, value) {
129
- obj[prop] = value;
130
-
131
- if (self.options.debounceTime > 0) {
132
- if (self.writeTimer) {
133
- clearTimeout(self.writeTimer);
134
- }
135
- self.writeTimer = setTimeout(() => {
136
- self.saveAsync();
137
- }, self.options.debounceTime);
138
- } else {
139
- self.saveAsync();
140
- }
141
-
142
- return true;
143
- },
144
-
145
- get(obj, prop) {
146
- if (prop === '_saveAsync') {
147
- return () => self.saveAsync();
148
- }
149
- if (prop === '_saveSync') {
150
- return () => self.saveSync();
151
- }
152
- if (prop === '_raw') {
153
- return obj;
154
- }
155
-
156
- return obj[prop];
157
- }
158
- });
159
- }
1
+ require('mm_expand');
2
+
3
+ /**
4
+ * 配置类
5
+ * @class
6
+ */
7
+ class Config {
8
+ /**
9
+ * 创建配置实例
10
+ * @param {Object} options - 配置对象
11
+ * @param {String} file - 配置文件路径
12
+ * @param {Object} config - 配置选项
13
+ * @param {Number} config.debounce_time - 防抖时间(ms)
14
+ * @param {Boolean} config.pretty - 是否美化输出
15
+ * @param {String} config.format - 格式(json/json5)
16
+ * @throws {TypeError} 当options非对象时
17
+ * @throws {TypeError} 当file非字符串时
18
+ */
19
+ constructor(options, file, config) {
20
+ // 参数校验
21
+ if (options && typeof options !== 'object') {
22
+ throw new TypeError('options must be an object');
23
+ }
24
+ if (file && typeof file !== 'string') {
25
+ throw new TypeError('file must be a string');
26
+ }
27
+
28
+ this.config = {
29
+ debounce_time: 0, // 默认不防抖
30
+ pretty: true,
31
+ format: 'json'
32
+ };
33
+ this.options = {};
34
+ this._file = file;
35
+ this._conn = null;
36
+ this._timer = null;
37
+ this._promise = Promise.resolve();
38
+
39
+ // 如果没有提供配置且有文件路径,则从文件加载
40
+ if (!options && file) {
41
+ try {
42
+ this.options = file.loadJson();
43
+ } catch (err) {
44
+ $.log.error(`[options] Error loading options from ${file}:`, err.message);
45
+ this.options = {};
46
+ }
47
+ }
48
+ // 设置配置
49
+ this.setOptions(options);
50
+ // 设置配置
51
+ this.setConfig(config);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * 设置配置
57
+ * @param {Object} config - 配置对象
58
+ */
59
+ Config.prototype.setConfig = function (config) {
60
+ Object.assign(this.config, config);
160
61
  }
161
62
 
162
63
  /**
163
- * 创建配置管理器的工厂函数
164
- * @param {Object} _config 配置对象
165
- * @param {String} _jsonFile 配置文件路径
166
- * @param {Object} options 配置选项
64
+ * 设置配置
65
+ * @param {Object} options - 配置对象
66
+ */
67
+ Config.prototype.setOptions = function (options) {
68
+ $.push(this.options, options, true);
69
+ }
70
+
71
+ /**
72
+ * 初始化配置(连接文件)
73
+ * @param {Object} conn - 已连接的文件对象
74
+ * @returns {Promise} 连接结果
75
+ */
76
+ Config.prototype.setup = async function (conn) {
77
+ if (conn) this._conn = conn;
78
+ return this._conn;
79
+ };
80
+
81
+ /**
82
+ * 保存配置到文件(同步)
83
+ * @returns {Boolean} 保存是否成功
84
+ */
85
+ Config.prototype.saveSync = function () {
86
+ if (!this._file) return false;
87
+ try {
88
+ this._file.saveJson(this.options);
89
+ return true;
90
+ } catch (err) {
91
+ $.log.error(`[options] Error saving options to ${this._file}:`, err.message);
92
+ return false;
93
+ }
94
+ };
95
+
96
+ /**
97
+ * 保存配置到文件(异步)
98
+ * @returns {Promise<Boolean>}
99
+ */
100
+ Config.prototype.saveAsync = async function () {
101
+ if (!this._file) return Promise.resolve(true);
102
+
103
+ // 确保之前的写操作完成
104
+ await this._promise;
105
+
106
+ this._promise = Promise.resolve()
107
+ .then(() => {
108
+ this._file.saveJson(this.options);
109
+ return true;
110
+ })
111
+ .catch(err => {
112
+ $.log.error(`[options] Error saving options to ${this._file}:`, err.message);
113
+ return false;
114
+ });
115
+
116
+ return this._promise;
117
+ };
118
+
119
+ /**
120
+ * 获取代理对象
121
+ * @returns {Proxy}
122
+ */
123
+ Config.prototype.getProxy = function () {
124
+ var self = this;
125
+
126
+ return new Proxy(this.options, {
127
+ set(obj, prop, val) {
128
+ obj[prop] = val;
129
+
130
+ if (self.config.debounce_time > 0) {
131
+ // 防抖处理
132
+ if (self._timer) {
133
+ clearTimeout(self._timer);
134
+ }
135
+ self._timer = setTimeout(() => {
136
+ self.saveSync();
137
+ }, self.config.debounce_time);
138
+ } else {
139
+ // 无防抖,直接保存
140
+ self.saveSync();
141
+ }
142
+
143
+ return true;
144
+ },
145
+
146
+ get(obj, prop) {
147
+ // 提供一些特殊属性访问
148
+ if (prop === '_saveAsync') {
149
+ return () => self.saveAsync();
150
+ }
151
+ if (prop === '_saveSync') {
152
+ return () => self.saveSync();
153
+ }
154
+ if (prop === '_raw') {
155
+ return obj;
156
+ }
157
+
158
+ return obj[prop];
159
+ }
160
+ });
161
+ };
162
+
163
+ /**
164
+ * 获取异步代理对象
167
165
  * @returns {Proxy}
168
166
  */
169
- function createConfig(_config, _jsonFile, options = {}) {
170
- // 兼容旧的调用方式(this.filename)
171
- if (!_jsonFile && this && this.filename) {
172
- _jsonFile = this.filename;
173
- }
167
+ Config.prototype.getAsyncProxy = function () {
168
+ var self = this;
174
169
 
175
- const manager = new ConfigManager(_config, _jsonFile, options);
176
- return manager.getProxy(); // 默认返回同步代理
170
+ return new Proxy(this.options, {
171
+ set(obj, prop, val) {
172
+ obj[prop] = val;
173
+
174
+ if (self.config.debounce_time > 0) {
175
+ if (self._timer) {
176
+ clearTimeout(self._timer);
177
+ }
178
+ self._timer = setTimeout(() => {
179
+ self.saveAsync();
180
+ }, self.config.debounce_time);
181
+ } else {
182
+ self.saveAsync();
183
+ }
184
+
185
+ return true;
186
+ },
187
+
188
+ get(obj, prop) {
189
+ if (prop === '_saveAsync') {
190
+ return () => self.saveAsync();
191
+ }
192
+ if (prop === '_saveSync') {
193
+ return () => self.saveSync();
194
+ }
195
+ if (prop === '_raw') {
196
+ return obj;
197
+ }
198
+
199
+ return obj[prop];
200
+ }
201
+ });
202
+ };
203
+
204
+ /**
205
+ * 配置字典(私有)
206
+ * @type {Object}
207
+ */
208
+ const dict = {};
209
+
210
+ /**
211
+ * 创建配置(同步)
212
+ * @param {String} file - 配置文件路径
213
+ * @param {Object} options - 配置对象
214
+ * @param {Object} config - 配置选项
215
+ * @returns {Proxy}
216
+ */
217
+ function create(file, options = {}, config = {}) {
218
+ let f = file.fullname();
219
+ // 检查是否已存在配置
220
+ if (dict[f]) {
221
+ // $.log.warn(`[options] Config for file ${f} already exists.`);
222
+ return dict[f].getProxy();
223
+ }
224
+ var cfg = new Config(options, f, config);
225
+ cfg.saveSync(); // 确保文件存在
226
+ // 注册配置字典
227
+ dict[f] = cfg;
228
+ return dict[f].getProxy();
177
229
  }
178
230
 
179
231
  /**
180
- * 创建异步配置管理器的工厂函数
181
- * @param {Object} _config 配置对象
182
- * @param {String} _jsonFile 配置文件路径
183
- * @param {Object} options 配置选项
232
+ * 创建配置(异步)
233
+ * @param {String} file - 配置文件路径
234
+ * @param {Object} options - 配置对象
235
+ * @param {Object} config - 配置选项
184
236
  * @returns {Promise<Proxy>}
185
237
  */
186
- async function createConfigAsync(_config, _jsonFile, options = {}) {
187
- // 兼容旧的调用方式(this.filename)
188
- if (!_jsonFile && this && this.filename) {
189
- _jsonFile = this.filename;
190
- }
238
+ async function createAsync(file, options = {}, config = {}) {
239
+ let f = file.fullname();
240
+ // 检查是否已存在配置
241
+ if (dict[f]) {
242
+ $.log.warn(`[options] Config for file ${f} already exists.`);
243
+ return dict[f].getAsyncProxy();
244
+ }
245
+ var cfg = new Config(options, f, config);
246
+ await cfg.saveAsync(); // 确保文件存在
247
+ // 注册配置字典
248
+ dict[f] = cfg;
249
+ return dict[f].getAsyncProxy();
250
+ }
191
251
 
192
- const manager = new ConfigManager(_config, _jsonFile, options);
193
- return manager.getAsyncProxy();
252
+ /**
253
+ * 清理指定文件配置缓存
254
+ * @param {String} file - 配置文件路径
255
+ */
256
+ function clear(file) {
257
+ if (!file) return clearAll();
258
+ let f = file.fullname();
259
+ if (dict[f]) {
260
+ delete dict[f];
261
+ }
194
262
  }
195
263
 
196
- // 导出工厂函数和类
197
- module.exports = createConfig;
198
- module.exports.createConfigAsync = createConfigAsync;
199
- module.exports.ConfigManager = ConfigManager;
264
+ /**
265
+ * 清理所有配置缓存
266
+ */
267
+ function clearAll() {
268
+ Object.keys(dict).forEach(key => {
269
+ delete dict[key];
270
+ });
271
+ }
272
+
273
+ /**
274
+ * 获取配置值
275
+ * @param {String} key - 配置键
276
+ * @returns {*}
277
+ */
278
+ Config.prototype.get = async function (key) {
279
+ var value;
280
+ if (this._conn) {
281
+ value = await this._conn.get(key);
282
+ }
283
+ if (!value) {
284
+ value = this.options[key];
285
+ }
286
+ return value;
287
+ };
288
+
289
+ /**
290
+ * 设置配置值
291
+ * @param {String} key - 配置键
292
+ * @param {*} value - 配置值
293
+ */
294
+ Config.prototype.set = async function (key, value) {
295
+ if (this._conn) {
296
+ await this._conn.set(key, value);
297
+ }
298
+ else {
299
+ this.options[key] = value;
300
+ }
301
+ };
302
+
303
+ /**
304
+ * 检查配置是否存在
305
+ * @param {String} key - 配置键
306
+ * @returns {Boolean}
307
+ */
308
+ Config.prototype.has = async function (key) {
309
+ var bl = false;
310
+ if (this._conn) {
311
+ bl = await this._conn.has(key);
312
+ };
313
+ if (!bl) {
314
+ bl = this.options.hasOwnProperty(key);
315
+ }
316
+ return bl;
317
+ };
318
+
319
+ /**
320
+ * 删除配置项
321
+ * @param {String} key - 配置键
322
+ */
323
+ Config.prototype.del = async function (key) {
324
+ if (this._conn) {
325
+ await this._conn.del(key);
326
+ };
327
+ delete this.options[key];
328
+ };
329
+
330
+ /**
331
+ * 获取所有配置键
332
+ * @returns {Array<String>}
333
+ */
334
+ Config.prototype.keys = async function () {
335
+ let keys = [];
336
+ if (this._conn) {
337
+ keys = await this._conn.keys();
338
+ }
339
+ let local_keys = Object.keys(this.options);
340
+ keys = keys.concat(local_keys);
341
+ return keys;
342
+ };
343
+
344
+ // 模块导出
345
+ module.exports = {
346
+ Config,
347
+ create,
348
+ createAsync,
349
+ clear,
350
+ clearAll
351
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_config",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "description": "这是超级美眉配置同步器,用于更改配置同步保存为JSON文件",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -26,6 +26,6 @@
26
26
  },
27
27
  "homepage": "https://gitee.com/qiuwenwu91/mm_config#readme",
28
28
  "dependencies": {
29
- "mm_logs": "^1.5.1"
29
+ "mm_expand": "^1.9.7"
30
30
  }
31
- }
31
+ }
package/test.js CHANGED
@@ -1,132 +1,199 @@
1
- const conf = require('./index.js');
2
- const createConfigAsync = conf.createConfigAsync;
1
+ const { create, createAsync, Config, clear, clearAll } = require('./index.js');
3
2
 
4
- // 测试同步API(向后兼容)
3
+ // 测试同步API
5
4
  function testSyncConfig() {
6
- console.log('=== 测试同步配置 API(向后兼容)===');
7
-
5
+ $.log.debug('=== 测试同步配置 API ===');
6
+
8
7
  // 方式1:提供配置对象和文件路径
9
- const config1 = conf({
8
+ const config1 = create("./config1.json", {
10
9
  name: "demo",
11
10
  state: 1
12
- }, "./config1.json");
13
-
11
+ });
12
+
14
13
  // 修改配置,会自动保存
15
14
  config1.name = "test1";
16
15
  config1.sort = 1;
17
- console.log('配置1:', config1);
18
-
19
- // 方式2:使用this.filename(兼容旧用法)
20
- const context = {
21
- filename: "./config2.json"
22
- };
23
-
24
- const config2 = conf.call(context, {
25
- name: "demo",
26
- state: 2
27
- });
28
-
16
+ $.log.debug('配置1:', config1);
17
+
18
+ // 方式2:创建空配置
19
+ const config2 = create("./config2.json");
20
+
29
21
  config2.name = "test2";
30
22
  config2.sort = 2;
31
- console.log('配置2:', config2);
32
-
23
+ $.log.debug('配置2:', config2);
24
+
33
25
  // 从文件加载配置
34
- const config3 = conf(null, "./config1.json");
35
- console.log('从文件加载的配置:', config3);
36
-
26
+ const config3 = create("./config1.json");
27
+ $.log.debug('从文件加载的配置:', config3);
28
+
37
29
  // 手动保存
38
30
  config3.age = 26;
39
31
  config3._saveSync(); // 显式调用保存
40
- console.log('更新后的配置3:', config3);
32
+ $.log.debug('更新后的配置3:', config3);
41
33
  }
42
34
 
43
35
  // 测试异步API
44
36
  async function testAsyncConfig() {
45
- console.log('\n=== 测试异步配置 API ===');
46
-
37
+ $.log.debug('\n=== 测试异步配置 API ===');
38
+
47
39
  try {
48
40
  // 创建异步配置
49
- const configAsync = await createConfigAsync({
41
+ const configAsync = await createAsync("./config_async.json", {
50
42
  name: "asyncDemo",
51
43
  state: 3
52
- }, "./config_async.json");
53
-
44
+ });
45
+
54
46
  // 修改配置,会异步自动保存
55
47
  configAsync.name = "asyncTest2";
56
48
  configAsync.timestamp = new Date().toISOString();
57
- console.log('异步配置:', configAsync);
58
-
49
+ $.log.debug('异步配置:', configAsync);
50
+
59
51
  // 显式调用异步保存
60
52
  // await configAsync._saveAsync();
61
- console.log('异步保存完成');
62
-
63
- } catch (error) {
64
- console.error('异步配置测试出错:', error);
53
+ $.log.debug('异步保存完成');
54
+
55
+ } catch (err) {
56
+ $.log.error('异步配置测试出错:', err);
65
57
  }
66
58
  }
67
59
 
68
60
  // 测试高级功能:防抖
69
61
  function testDebounce() {
70
- console.log('\n=== 测试防抖功能 ===');
71
-
62
+ $.log.debug('\n=== 测试防抖功能 ===');
63
+
72
64
  // 创建带防抖的配置(500ms延迟保存)
73
- const configDebounce = conf({
65
+ const configDebounce = create("./config_debounce.json", {
74
66
  name: "debounceDemo"
75
- }, "./config_debounce.json", {
76
- debounceTime: 500, // 500ms防抖时间
67
+ }, {
68
+ debounce_time: 500, // 500ms防抖时间
77
69
  pretty: true // 美化JSON输出
78
70
  });
79
-
71
+
80
72
  // 快速多次修改,应该只保存最后一次
81
- console.log('开始多次快速修改...');
73
+ $.log.debug('开始多次快速修改...');
82
74
  for (let i = 0; i < 5; i++) {
83
75
  configDebounce.value = i;
84
76
  configDebounce.timestamp = new Date().toISOString();
85
77
  }
86
-
87
- console.log('修改完成,等待防抖触发保存...');
88
- console.log('最终配置:', configDebounce);
78
+
79
+ $.log.debug('修改完成,等待防抖触发保存...');
80
+ $.log.debug('最终配置:', configDebounce);
89
81
  }
90
82
 
91
83
  // 测试JSON5格式
92
84
  function testJson5() {
93
- console.log('\n=== 测试JSON5格式支持 ===');
94
-
85
+ $.log.debug('\n=== 测试JSON5格式支持 ===');
86
+
95
87
  // 创建配置时指定JSON5格式
96
- const configJson5 = conf({
97
- name: "json5Demo",
98
- // JSON5支持的一些特性,如注释、尾随逗号等
99
- // 虽然保存时会转为标准JSON,但读取时可以处理JSON5格式
100
- }, "./config_json5.json", {
88
+ const configJson5 = create("./config_json5.json", {
89
+ name: "json5Demo"
90
+ }, {
101
91
  format: 'json5',
102
92
  pretty: true
103
93
  });
104
-
94
+
105
95
  configJson5.description = "This uses JSON5 format";
106
- console.log('JSON5配置:', configJson5);
96
+ $.log.debug('JSON5配置:', configJson5);
97
+ }
98
+
99
+ /**
100
+ * 测试配置方法
101
+ */
102
+ async function testMethods() {
103
+ $.log.debug('\n=== 测试配置方法 ===');
104
+
105
+ // 创建测试配置
106
+ const cg = new Config({
107
+ name: "methodsDemo",
108
+ sort: 100,
109
+ state: 1
110
+ });
111
+
112
+ // 测试设置和获取
113
+ await cg.set('name', 'testMethods');
114
+ const name = await cg.get('name');
115
+ $.log.debug('获取到的名称:', name);
116
+
117
+ // 测试检查存在
118
+ const hasName = await cg.has('name');
119
+ $.log.debug('是否存在名称:', hasName);
120
+
121
+ // 测试删除
122
+ await cg.del('name');
123
+ const hasNameAfterDelete = await cg.has('name');
124
+ $.log.debug('删除后是否存在名称:', hasNameAfterDelete);
125
+
126
+ // 测试获取所有键
127
+ const keys = await cg.keys();
128
+ $.log.debug('所有键:', keys);
129
+
130
+ const state = await cg.get('state');
131
+ $.log.debug('获取到的状态:', state);
132
+
133
+ // 测试设置选项
134
+ await cg.setOptions({
135
+ sort: 200,
136
+ state: "2"
137
+ });
138
+ $.log.debug('设置后的选项:', await cg.options);
139
+ }
140
+
141
+ // 测试缓存清理功能
142
+ async function testCacheClear() {
143
+ $.log.debug('\n=== 测试缓存清理功能 ===');
144
+
145
+ // 创建几个配置实例
146
+ const config1 = create("./cache_test1.json", { test: "cache1" });
147
+ const config2 = create("./cache_test2.json", { test: "cache2" });
148
+ const config3 = await createAsync("./cache_test3.json", { test: "cache3" });
149
+
150
+ $.log.debug('创建了3个配置实例');
151
+
152
+ // 测试清理单个缓存
153
+ clear("./cache_test1.json");
154
+ $.log.debug('已清理cache_test1.json的缓存');
155
+
156
+ // 重新创建应该会创建新实例
157
+ const config1New = create("./cache_test1.json", { test: "cache1_new" });
158
+ $.log.debug('重新创建cache_test1.json');
159
+
160
+ // 测试清理所有缓存
161
+ clearAll();
162
+ $.log.debug('已清理所有缓存');
163
+
164
+ // 再次创建应该都是新实例
165
+ const config2New = create("./cache_test2.json", { test: "cache2_new" });
166
+ const config3New = await createAsync("./cache_test3.json", { test: "cache3_new" });
167
+ $.log.debug('重新创建所有配置实例');
107
168
  }
108
169
 
109
170
  // 运行所有测试
110
171
  async function runAllTests() {
111
- console.log('开始运行配置管理器测试...');
112
-
172
+ $.log.debug('开始运行配置管理器测试...');
173
+
113
174
  // 运行同步测试
114
175
  testSyncConfig();
115
-
176
+
116
177
  // 运行异步测试
117
178
  await testAsyncConfig();
118
-
179
+
119
180
  // 运行防抖测试
120
181
  testDebounce();
121
-
182
+
122
183
  // 运行JSON5测试
123
184
  testJson5();
124
-
125
- console.log('\n所有测试完成!');
126
- console.log('请查看生成的配置文件以验证保存结果。');
185
+
186
+ // 运行缓存清理测试
187
+ await testCacheClear();
188
+
189
+ $.log.debug('\n所有测试完成!');
190
+ $.log.debug('请查看生成的配置文件以验证保存结果。');
191
+
192
+ // 运行方法测试
193
+ await testMethods();
127
194
  }
128
195
 
129
196
  // 执行测试
130
197
  runAllTests().catch(err => {
131
- console.error('测试过程中出现错误:', err);
198
+ $.log.error('测试过程中出现错误:', err);
132
199
  });
package/base.js DELETED
@@ -1,30 +0,0 @@
1
- /**
2
- * 重够配置,同步保存
3
- * @param {Object} _config 配置对象
4
- * @param {String} _jsonFile 配置文件
5
- */
6
- module.exports = function(_config, _jsonFile) {
7
- if (!_jsonFile) {
8
- _jsonFile = this.filename;
9
- }
10
- if (!_config) {
11
- try {
12
- _config = _jsonFile.loadJson();
13
- } catch (error) {
14
- _config = {};
15
- }
16
- }
17
- return new Proxy(_config, {
18
- set: function(obj, prop, value) {
19
- obj[prop] = value;
20
- if (_jsonFile) {
21
- try {
22
- _jsonFile.saveJson(obj); // 使用saveJson原型函数,参数为对象和缩进空格数
23
- } catch (error) {
24
- console.error('[Config] 保存配置失败:', error);
25
- }
26
- }
27
- return true
28
- }
29
- });
30
- }
package/config.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "name": "test",
3
- "state": 2,
4
- "sort": 2,
5
- "age": 26
6
- }