mm_config 2.1.5 → 2.1.7

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/index.js CHANGED
@@ -1,351 +1,363 @@
1
1
  require('mm_expand');
2
2
 
3
+ /**
4
+ * 配置字典(私有)
5
+ * @type {object}
6
+ */
7
+ const dict = {};
8
+
3
9
  /**
4
10
  * 配置类
5
11
  * @class
6
12
  */
7
13
  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
- }
14
+ /**
15
+ * 创建配置实例
16
+ * @param {object} config - 配置选项
17
+ * @param {number} config.debounce_time - 防抖时间(ms)
18
+ * @param {boolean} config.pretty - 是否美化输出
19
+ * @param {string} config.format - 格式(json/json5)
20
+ * @param {string} config.file - 配置文件路径
21
+ * @param {object} options - 选项
22
+ */
23
+ constructor(config, options = {}) {
24
+ this.config = {
25
+ debounce_time: 0, // 默认不防抖
26
+ pretty: true,
27
+ format: 'json',
28
+ file: ''
29
+ };
30
+
31
+ this.options = options || {};
32
+ this._conn = null;
33
+ this._timer = null;
34
+ this._promise = Promise.resolve();
35
+ this._logger = $.log || console;
36
+ // 设置配置
37
+ this.setConfig(config);
38
+ }
53
39
  }
54
40
 
41
+ /**
42
+ * 日志输出
43
+ * @param {string} level - 日志级别(debug/info/warn/error)
44
+ * @param {string} message - 日志消息
45
+ * @param {...*} args - 可选参数
46
+ */
47
+ Config.prototype.log = function (level, message, ...args) {
48
+ this._logger[level](`[${this.constructor.name}] ${message}`, ...args);
49
+ };
50
+
55
51
  /**
56
52
  * 设置配置
57
- * @param {Object} config - 配置对象
53
+ * @param {object} config - 配置对象
58
54
  */
59
55
  Config.prototype.setConfig = function (config) {
60
- Object.assign(this.config, config);
61
- }
56
+ $.push(this.config, config);
57
+ };
62
58
 
63
59
  /**
64
60
  * 设置配置
65
- * @param {Object} options - 配置对象
61
+ * @param {object} options - 配置对象
66
62
  */
67
63
  Config.prototype.setOptions = function (options) {
68
- $.push(this.options, options, true);
69
- }
64
+ $.push(this.options, options, true);
65
+ };
70
66
 
71
67
  /**
72
68
  * 初始化配置(连接文件)
73
- * @param {Object} conn - 已连接的文件对象
74
- * @returns {Promise} 连接结果
69
+ * @param {object} conn - 已连接的文件对象
70
+ * @returns {object} 连接的文件对象
75
71
  */
76
- Config.prototype.setup = async function (conn) {
77
- if (conn) this._conn = conn;
78
- return this._conn;
72
+ Config.prototype.setup = function (conn) {
73
+ if (conn) this._conn = conn;
74
+ return this._conn;
79
75
  };
80
76
 
81
77
  /**
82
78
  * 保存配置到文件(同步)
83
- * @returns {Boolean} 保存是否成功
79
+ * @returns {boolean} 保存是否成功
84
80
  */
85
81
  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
- }
82
+ if (!this.config.file) return false;
83
+ try {
84
+ this.config.file.saveJson(this.options);
85
+ return true;
86
+ } catch (err) {
87
+ this.log('error', `Error saving options to ${this.config.file}:`, err.message);
88
+ return false;
89
+ }
94
90
  };
95
91
 
96
92
  /**
97
93
  * 保存配置到文件(异步)
98
- * @returns {Promise<Boolean>}
94
+ * @returns {Promise<boolean>} 保存操作是否成功
99
95
  */
100
96
  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;
97
+ if (!this.config.file) return Promise.resolve(true);
98
+
99
+ // 确保之前的写操作完成
100
+ await this._promise;
101
+
102
+ this._promise = Promise.resolve()
103
+ .then(() => {
104
+ this.config.file.saveJson(this.options);
105
+ return true;
106
+ })
107
+ .catch(err => {
108
+ this.log('error', `Error saving options to ${this.config.file}:`, err.message);
109
+ return false;
110
+ });
111
+
112
+ return this._promise;
117
113
  };
118
114
 
119
115
  /**
120
116
  * 获取代理对象
121
- * @returns {Proxy}
117
+ * @returns {Proxy} 配置对象的代理实例
122
118
  */
123
119
  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
- });
120
+ const self = this;
121
+
122
+ return new Proxy(this.options, {
123
+ set(obj, prop, val) {
124
+ obj[prop] = val;
125
+
126
+ if (self.config.debounce_time > 0) {
127
+ // 防抖处理
128
+ if (self._timer) {
129
+ clearTimeout(self._timer);
130
+ }
131
+ self._timer = setTimeout(() => {
132
+ self.saveSync();
133
+ }, self.config.debounce_time);
134
+ } else {
135
+ // 无防抖,直接保存
136
+ self.saveSync();
137
+ }
138
+
139
+ return true;
140
+ },
141
+
142
+ get(obj, prop) {
143
+ // 提供一些特殊属性访问
144
+ if (prop === '_saveAsync') {
145
+ return () => self.saveAsync();
146
+ }
147
+ if (prop === '_saveSync') {
148
+ return () => self.saveSync();
149
+ }
150
+ if (prop === '_raw') {
151
+ return obj;
152
+ }
153
+
154
+ return obj[prop];
155
+ }
156
+ });
161
157
  };
162
158
 
163
159
  /**
164
160
  * 获取异步代理对象
165
- * @returns {Proxy}
161
+ * @returns {Proxy} 异步配置对象的代理实例
166
162
  */
167
163
  Config.prototype.getAsyncProxy = function () {
168
- var self = this;
169
-
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
- });
164
+ const self = this;
165
+
166
+ return new Proxy(this.options, {
167
+ set(obj, prop, val) {
168
+ obj[prop] = val;
169
+
170
+ if (self.config.debounce_time > 0) {
171
+ if (self._timer) {
172
+ clearTimeout(self._timer);
173
+ }
174
+ self._timer = setTimeout(() => {
175
+ self.saveAsync();
176
+ }, self.config.debounce_time);
177
+ } else {
178
+ self.saveAsync();
179
+ }
180
+
181
+ return true;
182
+ },
183
+
184
+ get(obj, prop) {
185
+ if (prop === '_saveAsync') {
186
+ return () => self.saveAsync();
187
+ }
188
+ if (prop === '_saveSync') {
189
+ return () => self.saveSync();
190
+ }
191
+ if (prop === '_raw') {
192
+ return obj;
193
+ }
194
+
195
+ return obj[prop];
196
+ }
197
+ });
202
198
  };
203
199
 
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();
229
- }
230
-
231
- /**
232
- * 创建配置(异步)
233
- * @param {String} file - 配置文件路径
234
- * @param {Object} options - 配置对象
235
- * @param {Object} config - 配置选项
236
- * @returns {Promise<Proxy>}
237
- */
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
- }
251
-
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
- }
262
- }
263
-
264
- /**
265
- * 清理所有配置缓存
266
- */
267
- function clearAll() {
268
- Object.keys(dict).forEach(key => {
269
- delete dict[key];
270
- });
271
- }
272
-
273
200
  /**
274
201
  * 获取配置值
275
- * @param {String} key - 配置键
276
- * @returns {*}
202
+ * @param {string} key - 配置键
203
+ * @returns {*} 配置值
277
204
  */
278
205
  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;
206
+ let value;
207
+ if (this._conn) {
208
+ value = await this._conn.get(key);
209
+ }
210
+ if (!value) {
211
+ value = this.options[key];
212
+ }
213
+ return value;
287
214
  };
288
215
 
289
216
  /**
290
217
  * 设置配置值
291
- * @param {String} key - 配置键
218
+ * @param {string} key - 配置键
292
219
  * @param {*} value - 配置值
293
220
  */
294
221
  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
- }
222
+ if (this._conn) {
223
+ await this._conn.set(key, value);
224
+ }
225
+ else {
226
+ this.options[key] = value;
227
+ }
301
228
  };
302
229
 
303
230
  /**
304
231
  * 检查配置是否存在
305
- * @param {String} key - 配置键
306
- * @returns {Boolean}
232
+ * @param {string} key - 配置键
233
+ * @returns {boolean} 配置项是否存在
307
234
  */
308
235
  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;
236
+ let bl = false;
237
+ if (this._conn) {
238
+ bl = await this._conn.has(key);
239
+ };
240
+ if (!bl) {
241
+ bl = this.options.hasOwnProperty(key);
242
+ }
243
+ return bl;
317
244
  };
318
245
 
319
246
  /**
320
247
  * 删除配置项
321
- * @param {String} key - 配置键
248
+ * @param {string} key - 配置键
322
249
  */
323
250
  Config.prototype.del = async function (key) {
324
- if (this._conn) {
325
- await this._conn.del(key);
326
- };
327
- delete this.options[key];
251
+ if (this._conn) {
252
+ await this._conn.del(key);
253
+ };
254
+ delete this.options[key];
328
255
  };
329
256
 
330
257
  /**
331
258
  * 获取所有配置键
332
- * @returns {Array<String>}
259
+ * @returns {Array<string>} 配置键列表
333
260
  */
334
261
  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;
262
+ let keys = [];
263
+ if (this._conn) {
264
+ keys = await this._conn.keys();
265
+ }
266
+ const local_keys = Object.keys(this.options);
267
+ keys = keys.concat(local_keys);
268
+ return keys;
342
269
  };
343
270
 
271
+ /**
272
+ * 销毁
273
+ */
274
+ Config.prototype.destroy = function () {
275
+ if (this._conn) {
276
+ this._conn.close();
277
+ }
278
+ delete dict[this.config.file];
279
+ };
280
+
281
+ /**
282
+ * 创建配置(同步)
283
+ * @param {string} file - 配置文件路径
284
+ * @param {object} options - 配置对象
285
+ * @param {object} config - 配置选项
286
+ * @returns {Proxy} 配置代理对象
287
+ */
288
+ function create(file, options = {}, config = {}) {
289
+ const f = file.fullname();
290
+ // 检查是否已存在配置
291
+ if (dict[f]) {
292
+ return dict[f].getProxy();
293
+ }
294
+ const cfg = new Config({ file: f, ...config }, options);
295
+ cfg.saveSync(); // 确保文件存在
296
+ // 注册配置字典
297
+ dict[f] = cfg;
298
+ return dict[f].getProxy();
299
+ }
300
+
301
+ /**
302
+ * 创建配置(异步)
303
+ * @param {string} file - 配置文件路径
304
+ * @param {object} options - 配置对象
305
+ * @param {object} config - 配置选项
306
+ * @returns {Promise<Proxy>} 异步配置代理对象
307
+ */
308
+ async function createAsync(file, options = {}, config = {}) {
309
+ const f = file.fullname();
310
+ // 检查是否已存在配置
311
+ if (dict[f]) {
312
+ this.log('warn', `Config for file ${f} already exists.`);
313
+ return dict[f].getAsyncProxy();
314
+ }
315
+ const cfg = new Config({ file: f, ...config }, options);
316
+ await cfg.saveAsync(); // 确保文件存在
317
+ // 注册配置字典
318
+ dict[f] = cfg;
319
+ return dict[f].getAsyncProxy();
320
+ }
321
+
322
+ /**
323
+ * 清理指定文件配置缓存
324
+ * @param {string} file - 配置文件路径
325
+ * @returns {void}
326
+ */
327
+ function clear(file) {
328
+ if (!file) return clearAll();
329
+ const f = file.fullname();
330
+ if (dict[f]) {
331
+ delete dict[f];
332
+ }
333
+ }
334
+
335
+ /**
336
+ * 清理所有配置缓存
337
+ */
338
+ function clearAll() {
339
+ Object.keys(dict).forEach(key => {
340
+ delete dict[key];
341
+ });
342
+ }
343
+
344
+ /**
345
+ * 获取配置代理对象
346
+ * @param {object} options - 配置对象
347
+ * @param {string} file - 配置文件路径
348
+ * @param {object} config - 配置选项
349
+ * @returns {Proxy} 配置代理对象
350
+ */
351
+ function conf(options, file, config = {}) {
352
+ return createAsync(file, options, config);
353
+ }
354
+
344
355
  // 模块导出
345
356
  module.exports = {
346
- Config,
347
- create,
348
- createAsync,
349
- clear,
350
- clearAll
357
+ Config,
358
+ create,
359
+ createAsync,
360
+ clear,
361
+ clearAll,
362
+ conf
351
363
  };
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "mm_config",
3
- "version": "2.1.5",
4
- "description": "这是超级美眉配置同步器,用于更改配置同步保存为JSON文件",
3
+ "version": "2.1.7",
4
+ "description": "Super Meimei Configuration Synchronizer - Automatically sync configuration changes to JSON files",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "node test.js"
7
+ "test": "node test.js",
8
+ "lint": "eslint index.js",
9
+ "lint:fix": "eslint index.js --fix"
8
10
  },
9
11
  "repository": {
10
12
  "type": "git",
@@ -17,7 +19,10 @@
17
19
  "sync",
18
20
  "async",
19
21
  "debounce",
20
- "json5"
22
+ "json5",
23
+ "configuration",
24
+ "settings",
25
+ "automation"
21
26
  ],
22
27
  "author": "邱文武",
23
28
  "license": "ISC",
@@ -25,7 +30,21 @@
25
30
  "url": "https://gitee.com/qiuwenwu91/mm_config/issues"
26
31
  },
27
32
  "homepage": "https://gitee.com/qiuwenwu91/mm_config#readme",
33
+ "engines": {
34
+ "node": ">=14.0.0"
35
+ },
36
+ "files": [
37
+ "index.js",
38
+ "README.md",
39
+ "README_EN.md",
40
+ "LICENSE"
41
+ ],
28
42
  "dependencies": {
29
- "mm_expand": "^1.9.7"
43
+ "mm_expand": "^2.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "eslint": "^9.39.2",
47
+ "eslint-plugin-jsdoc": "^61.5.0",
48
+ "mm_eslint": "^1.0.6"
30
49
  }
31
- }
50
+ }
package/.gitattributes DELETED
@@ -1,5 +0,0 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto
3
- *.js linguist-language=JavaScript
4
- *.css linguist-language=JavaScript
5
- *.html linguist-language=JavaScript