mm_config 2.1.2 → 2.1.4
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 +284 -194
- package/cache_test1.json +3 -0
- package/cache_test2.json +3 -0
- package/cache_test3.json +3 -0
- package/config1.json +6 -0
- package/config2.json +4 -0
- package/config_async.json +5 -0
- package/config_debounce.json +5 -0
- package/config_json5.json +4 -0
- package/index.js +337 -185
- package/package.json +3 -3
- package/test.js +125 -65
- package/base.js +0 -30
- package/config.json +0 -6
package/index.js
CHANGED
|
@@ -1,199 +1,351 @@
|
|
|
1
|
-
require('
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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(`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}
|
|
165
|
-
|
|
166
|
-
|
|
64
|
+
* 设置配置
|
|
65
|
+
* @param {Object} options - 配置对象
|
|
66
|
+
*/
|
|
67
|
+
Config.prototype.setOptions = function (options) {
|
|
68
|
+
Object.assign(this.options, options);
|
|
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
|
|
170
|
-
|
|
171
|
-
if (!_jsonFile && this && this.filename) {
|
|
172
|
-
_jsonFile = this.filename;
|
|
173
|
-
}
|
|
167
|
+
Config.prototype.getAsyncProxy = function () {
|
|
168
|
+
var self = this;
|
|
174
169
|
|
|
175
|
-
|
|
176
|
-
|
|
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 {
|
|
182
|
-
* @param {
|
|
183
|
-
* @param {Object}
|
|
232
|
+
* 创建配置(异步)
|
|
233
|
+
* @param {String} file - 配置文件路径
|
|
234
|
+
* @param {Object} options - 配置对象
|
|
235
|
+
* @param {Object} config - 配置选项
|
|
184
236
|
* @returns {Promise<Proxy>}
|
|
185
237
|
*/
|
|
186
|
-
async function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
193
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
+
"version": "2.1.4",
|
|
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
|
-
"
|
|
29
|
+
"mm_expand": "^1.9.7"
|
|
30
30
|
}
|
|
31
|
-
}
|
|
31
|
+
}
|