@nimbus2d/core 0.0.1
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/dist/index.mjs +18433 -0
- package/package.json +39 -0
- package/src/base/EventEmitter.js +187 -0
- package/src/base/Subsystem.js +183 -0
- package/src/base/index.js +6 -0
- package/src/core/Application/AppState.js +27 -0
- package/src/core/Application/Application.js +480 -0
- package/src/core/Application/DefaultConfig.js +63 -0
- package/src/core/Application/index.js +7 -0
- package/src/core/AssetManager/AssetManager.js +711 -0
- package/src/core/AssetManager/AssetTypes.js +108 -0
- package/src/core/AssetManager/adapters/IResourceAdapter.js +50 -0
- package/src/core/AssetManager/adapters/PixiAdapter.js +90 -0
- package/src/core/AssetManager/core/RefCounter.js +167 -0
- package/src/core/AssetManager/core/ResourceCache.js +281 -0
- package/src/core/AssetManager/core/ResourceEntry.js +191 -0
- package/src/core/AssetManager/core/ResourceEventBus.js +127 -0
- package/src/core/AssetManager/handlers/IResourceHandler.js +45 -0
- package/src/core/AssetManager/index.js +26 -0
- package/src/core/AssetManager/plugins/IResourcePlugin.js +56 -0
- package/src/core/Camera/Camera.js +534 -0
- package/src/core/Camera/CameraTypes.js +59 -0
- package/src/core/Camera/index.js +13 -0
- package/src/core/ConfigSystem/ConfigLayer.js +230 -0
- package/src/core/ConfigSystem/ConfigLayerType.js +31 -0
- package/src/core/ConfigSystem/ConfigMerger.js +50 -0
- package/src/core/ConfigSystem/ConfigPath.js +96 -0
- package/src/core/ConfigSystem/ConfigSystem.js +378 -0
- package/src/core/ConfigSystem/ConfigTypes.js +29 -0
- package/src/core/ConfigSystem/ConfigWatcher.js +84 -0
- package/src/core/ConfigSystem/index.js +19 -0
- package/src/core/EventBus/EventBus.js +797 -0
- package/src/core/EventBus/Interceptor.js +26 -0
- package/src/core/EventBus/PerformanceStats.js +105 -0
- package/src/core/EventBus/index.js +7 -0
- package/src/core/Lifecycle/Lifecycle.js +265 -0
- package/src/core/Lifecycle/LifecycleState.js +31 -0
- package/src/core/Lifecycle/index.js +6 -0
- package/src/core/Logger/ConsoleHandler.js +55 -0
- package/src/core/Logger/LogHandler.js +34 -0
- package/src/core/Logger/LogLevel.js +38 -0
- package/src/core/Logger/Logger.js +234 -0
- package/src/core/Logger/index.js +8 -0
- package/src/core/PluginSystem/Plugin.js +156 -0
- package/src/core/PluginSystem/PluginEntry.js +102 -0
- package/src/core/PluginSystem/PluginState.js +30 -0
- package/src/core/PluginSystem/PluginSystem.js +530 -0
- package/src/core/PluginSystem/index.js +8 -0
- package/src/core/PoolManager/DefaultConfig.js +19 -0
- package/src/core/PoolManager/ObjectPool.js +326 -0
- package/src/core/PoolManager/PoolManager.js +253 -0
- package/src/core/PoolManager/PoolTypes.js +92 -0
- package/src/core/PoolManager/index.js +15 -0
- package/src/core/SceneManager/FadeTransition.js +64 -0
- package/src/core/SceneManager/MaskTransition.js +234 -0
- package/src/core/SceneManager/Scene.js +221 -0
- package/src/core/SceneManager/SceneManager.js +658 -0
- package/src/core/SceneManager/SceneState.js +29 -0
- package/src/core/SceneManager/SlideTransition.js +113 -0
- package/src/core/SceneManager/Transition.js +102 -0
- package/src/core/SceneManager/ZoomTransition.js +119 -0
- package/src/core/SceneManager/index.js +12 -0
- package/src/core/SpriteGPULayer/SpriteGPULayer.js +321 -0
- package/src/core/SpriteGPULayer/SpriteGPULayerTypes.js +49 -0
- package/src/core/SpriteGPULayer/index.js +11 -0
- package/src/core/Timeline/Clip.js +101 -0
- package/src/core/Timeline/DefaultConfig.js +41 -0
- package/src/core/Timeline/Easing.js +176 -0
- package/src/core/Timeline/Timeline.js +458 -0
- package/src/core/Timeline/TimelineTypes.js +89 -0
- package/src/core/Timeline/Track.js +202 -0
- package/src/core/Timeline/index.js +22 -0
- package/src/errors/ConfigError.js +47 -0
- package/src/errors/LifecycleError.js +58 -0
- package/src/errors/NimbusError.js +43 -0
- package/src/errors/PluginError.js +138 -0
- package/src/errors/ResourceError.js +166 -0
- package/src/errors/SceneError.js +124 -0
- package/src/errors/SubsystemError.js +68 -0
- package/src/errors/index.js +53 -0
- package/src/index.js +86 -0
- package/src/types/index.js +141 -0
- package/src/utils/MemoryChecker.js +374 -0
- package/src/utils/Validator.js +60 -0
- package/src/utils/index.js +84 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Nimbus2D - ConfigSystem 配置系统
|
|
3
|
+
// ----------------------------------------------------------------------------
|
|
4
|
+
// 职责:
|
|
5
|
+
// 1. 运行时可变 + 监听 + 分层覆盖
|
|
6
|
+
// 2. 4 层配置:DEFAULT → MODULE → USER → RUNTIME(优先级递增)
|
|
7
|
+
// 3. 完整 API:set/get/has/delete/watch/unwatch/loadJSON/loadModule
|
|
8
|
+
// 4. 类型校验(可选,setTypeValidation 启用)
|
|
9
|
+
// 5. 路径缓存(Map<string, string[]>)
|
|
10
|
+
// 6. 静默模式(options.silent)
|
|
11
|
+
//
|
|
12
|
+
// 继承关系:
|
|
13
|
+
// EventEmitter → ConfigSystem(基础设施,不被 Lifecycle 调度)
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
import { EventEmitter } from '../../base/EventEmitter.js'
|
|
17
|
+
import { ConfigLayer } from './ConfigLayer.js'
|
|
18
|
+
import { ConfigLayerType, LAYER_FREEZABLE_DEFAULTS } from './ConfigLayerType.js'
|
|
19
|
+
import { ConfigPath } from './ConfigPath.js'
|
|
20
|
+
import { ConfigWatcher } from './ConfigWatcher.js'
|
|
21
|
+
import { deepMerge } from './ConfigMerger.js'
|
|
22
|
+
import { getType, SUPPORTED_TYPES } from './ConfigTypes.js'
|
|
23
|
+
import { ConfigError, ConfigPathError } from '../../errors/ConfigError.js'
|
|
24
|
+
|
|
25
|
+
class ConfigSystem extends EventEmitter {
|
|
26
|
+
/**
|
|
27
|
+
* 构造函数
|
|
28
|
+
*/
|
|
29
|
+
constructor() {
|
|
30
|
+
super()
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 配置层映射(按优先级从低到高)
|
|
34
|
+
* @type {Map<string, ConfigLayer>}
|
|
35
|
+
*/
|
|
36
|
+
this._layers = new Map()
|
|
37
|
+
|
|
38
|
+
/** @type {ConfigPath} 路径解析工具 */
|
|
39
|
+
this._pathTool = new ConfigPath()
|
|
40
|
+
|
|
41
|
+
/** @type {ConfigWatcher} 监听器管理 */
|
|
42
|
+
this._watcher = new ConfigWatcher()
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 类型校验 schema
|
|
46
|
+
* @type {Object<string, string>|null}
|
|
47
|
+
*/
|
|
48
|
+
this._schema = null
|
|
49
|
+
|
|
50
|
+
/** @type {boolean} 是否已初始化 */
|
|
51
|
+
this._isInitialized = false
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// --------------------------------------------------------------------------
|
|
55
|
+
// 读写方法
|
|
56
|
+
// --------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 设置运行时配置(写入 RUNTIME 层)
|
|
60
|
+
* @param {string} path - 配置路径(如 'modules.logger.level')
|
|
61
|
+
* @param {any} value - 配置值
|
|
62
|
+
* @param {Object} [options={}] - 选项
|
|
63
|
+
* @param {boolean} [options.silent=false] - 静默模式(路径父级不存在时不抛错,返回 false)
|
|
64
|
+
* @returns {boolean} 是否设置成功
|
|
65
|
+
*/
|
|
66
|
+
set(path, value, options = {}) {
|
|
67
|
+
if (this._destroyed) return false
|
|
68
|
+
|
|
69
|
+
// 类型校验
|
|
70
|
+
if (this._schema && !this._validateType(path, value, options)) {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 获取旧值(用于监听器通知)
|
|
75
|
+
const oldValue = this._getRaw(path)
|
|
76
|
+
|
|
77
|
+
// 设置到 RUNTIME 层
|
|
78
|
+
const runtimeLayer = this._layers.get(ConfigLayerType.RUNTIME)
|
|
79
|
+
if (!runtimeLayer) {
|
|
80
|
+
if (options.silent) return false
|
|
81
|
+
throw new ConfigError('RUNTIME 配置层未初始化', 'CONFIG_LAYER_MISSING')
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = runtimeLayer.set(path, value)
|
|
85
|
+
if (!result && !options.silent) {
|
|
86
|
+
return false
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 通知监听器
|
|
90
|
+
if (result) {
|
|
91
|
+
this._watcher.notify(path, value, oldValue)
|
|
92
|
+
this.emit('change', { path, oldValue, newValue: value })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return result
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 获取配置(按优先级查询:RUNTIME → USER → MODULE → DEFAULT)
|
|
100
|
+
* @param {string} path - 配置路径
|
|
101
|
+
* @param {any} [defaultValue=undefined] - 默认值
|
|
102
|
+
* @param {Object} [options={}] - 选项
|
|
103
|
+
* @param {boolean} [options.silent=false] - 静默模式(路径不存在时不抛错,返回 defaultValue)
|
|
104
|
+
* @returns {any} 配置值
|
|
105
|
+
*/
|
|
106
|
+
get(path, defaultValue = undefined, options = {}) {
|
|
107
|
+
if (this._destroyed) return defaultValue
|
|
108
|
+
|
|
109
|
+
// 按优先级从高到低查询
|
|
110
|
+
const layerOrder = [
|
|
111
|
+
ConfigLayerType.RUNTIME,
|
|
112
|
+
ConfigLayerType.USER,
|
|
113
|
+
ConfigLayerType.MODULE,
|
|
114
|
+
ConfigLayerType.DEFAULT
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
for (const layerType of layerOrder) {
|
|
118
|
+
const layer = this._layers.get(layerType)
|
|
119
|
+
if (!layer) continue
|
|
120
|
+
|
|
121
|
+
const result = layer.get(path)
|
|
122
|
+
if (result.found) {
|
|
123
|
+
return result.value
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 未找到
|
|
128
|
+
if (options.silent) {
|
|
129
|
+
return defaultValue
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 非静默模式不抛错,返回默认值(配置路径可能确实不存在)
|
|
133
|
+
return defaultValue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 检查配置是否存在
|
|
138
|
+
* @param {string} path - 配置路径
|
|
139
|
+
* @returns {boolean}
|
|
140
|
+
*/
|
|
141
|
+
has(path) {
|
|
142
|
+
if (this._destroyed) return false
|
|
143
|
+
|
|
144
|
+
for (const layer of this._layers.values()) {
|
|
145
|
+
if (layer.has(path)) return true
|
|
146
|
+
}
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 删除运行时配置
|
|
152
|
+
* @param {string} path - 配置路径
|
|
153
|
+
* @returns {boolean} 是否删除成功
|
|
154
|
+
*/
|
|
155
|
+
delete(path) {
|
|
156
|
+
if (this._destroyed) return false
|
|
157
|
+
|
|
158
|
+
const runtimeLayer = this._layers.get(ConfigLayerType.RUNTIME)
|
|
159
|
+
if (!runtimeLayer) return false
|
|
160
|
+
|
|
161
|
+
const oldValue = this._getRaw(path)
|
|
162
|
+
const result = runtimeLayer.delete(path)
|
|
163
|
+
|
|
164
|
+
if (result) {
|
|
165
|
+
const newValue = this._getRaw(path)
|
|
166
|
+
this._watcher.notify(path, newValue, oldValue)
|
|
167
|
+
this.emit('change', { path, oldValue, newValue })
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 注册类型校验 schema
|
|
175
|
+
* @param {Object} schema - schema 对象(path => type 字符串)
|
|
176
|
+
* @returns {ConfigSystem} this(链式)
|
|
177
|
+
*/
|
|
178
|
+
setTypeValidation(schema) {
|
|
179
|
+
// 验证 schema 中的类型是否合法
|
|
180
|
+
for (const [path, type] of Object.entries(schema)) {
|
|
181
|
+
if (!SUPPORTED_TYPES.includes(type)) {
|
|
182
|
+
throw new ConfigError(
|
|
183
|
+
`类型校验 schema 中路径 "${path}" 的类型 "${type}" 不合法,支持:${SUPPORTED_TYPES.join(', ')}`,
|
|
184
|
+
'CONFIG_INVALID_TYPE'
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this._schema = schema
|
|
189
|
+
return this
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// --------------------------------------------------------------------------
|
|
193
|
+
// 监听器
|
|
194
|
+
// --------------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 监听配置变化
|
|
198
|
+
* @param {string} pathPattern - 路径模式(支持通配符 'modules.*.level')
|
|
199
|
+
* @param {Function} callback - 回调 (newValue, oldValue, path) => void
|
|
200
|
+
* @returns {Function} 取消监听函数
|
|
201
|
+
*/
|
|
202
|
+
watch(pathPattern, callback) {
|
|
203
|
+
return this._watcher.watch(pathPattern, callback)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 取消监听
|
|
208
|
+
* @param {string} pathPattern - 路径模式
|
|
209
|
+
* @param {Function} callback - 回调
|
|
210
|
+
* @returns {boolean}
|
|
211
|
+
*/
|
|
212
|
+
unwatch(pathPattern, callback) {
|
|
213
|
+
return this._watcher.unwatch(pathPattern, callback)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// --------------------------------------------------------------------------
|
|
217
|
+
// 批量加载
|
|
218
|
+
// --------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 批量加载 JSON 配置
|
|
222
|
+
* @param {Object} json - 配置对象
|
|
223
|
+
* @param {string} [layerType=ConfigLayerType.USER] - 层类型
|
|
224
|
+
*/
|
|
225
|
+
loadJSON(json, layerType = ConfigLayerType.USER) {
|
|
226
|
+
if (this._destroyed) return
|
|
227
|
+
|
|
228
|
+
const layer = this._layers.get(layerType)
|
|
229
|
+
if (!layer) {
|
|
230
|
+
throw new ConfigError(`配置层 "${layerType}" 未初始化`, 'CONFIG_LAYER_MISSING')
|
|
231
|
+
}
|
|
232
|
+
layer.loadJSON(json)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* 加载模块默认配置(写入 MODULE 层)
|
|
237
|
+
* @param {string} moduleName - 模块名称
|
|
238
|
+
* @param {Object} config - 模块默认配置
|
|
239
|
+
*/
|
|
240
|
+
loadModule(moduleName, config) {
|
|
241
|
+
if (this._destroyed) return
|
|
242
|
+
|
|
243
|
+
const moduleLayer = this._layers.get(ConfigLayerType.MODULE)
|
|
244
|
+
if (!moduleLayer) {
|
|
245
|
+
throw new ConfigError('MODULE 配置层未初始化', 'CONFIG_LAYER_MISSING')
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 以模块名为前缀合并到 MODULE 层
|
|
249
|
+
const moduleConfig = { [moduleName]: config }
|
|
250
|
+
moduleLayer.loadJSON(moduleConfig)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// --------------------------------------------------------------------------
|
|
254
|
+
// 层管理
|
|
255
|
+
// --------------------------------------------------------------------------
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* 获取配置层
|
|
259
|
+
* @param {string} layerType - ConfigLayerType 枚举值
|
|
260
|
+
* @returns {ConfigLayer|undefined}
|
|
261
|
+
*/
|
|
262
|
+
getLayer(layerType) {
|
|
263
|
+
return this._layers.get(layerType)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 获取所有层
|
|
268
|
+
* @returns {ConfigLayer[]}
|
|
269
|
+
*/
|
|
270
|
+
getAllLayers() {
|
|
271
|
+
return Array.from(this._layers.values())
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// --------------------------------------------------------------------------
|
|
275
|
+
// 生命周期方法(基础设施,不继承 Subsystem)
|
|
276
|
+
// --------------------------------------------------------------------------
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 初始化 4 层配置
|
|
280
|
+
* @returns {Promise<void>}
|
|
281
|
+
*/
|
|
282
|
+
async initialize() {
|
|
283
|
+
if (this._isInitialized) return
|
|
284
|
+
|
|
285
|
+
// 创建 4 层配置
|
|
286
|
+
for (const [type, freezable] of Object.entries(LAYER_FREEZABLE_DEFAULTS)) {
|
|
287
|
+
this._layers.set(type, new ConfigLayer(type, {}, freezable))
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
this._isInitialized = true
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* 销毁配置系统,清理监听器和配置
|
|
295
|
+
* @returns {Promise<void>}
|
|
296
|
+
*/
|
|
297
|
+
async destroy() {
|
|
298
|
+
if (this._destroyed) return
|
|
299
|
+
|
|
300
|
+
// 清理监听器
|
|
301
|
+
this._watcher.clear()
|
|
302
|
+
|
|
303
|
+
// 清理路径缓存
|
|
304
|
+
this._pathTool.clearCache()
|
|
305
|
+
|
|
306
|
+
// 清理配置层
|
|
307
|
+
for (const layer of this._layers.values()) {
|
|
308
|
+
layer.clear()
|
|
309
|
+
}
|
|
310
|
+
this._layers.clear()
|
|
311
|
+
|
|
312
|
+
// 清理 schema
|
|
313
|
+
this._schema = null
|
|
314
|
+
|
|
315
|
+
this.emit('destroyed')
|
|
316
|
+
super.destroy()
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// --------------------------------------------------------------------------
|
|
320
|
+
// 内部方法
|
|
321
|
+
// --------------------------------------------------------------------------
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 获取原始值(不经过默认值处理)
|
|
325
|
+
* @param {string} path - 配置路径
|
|
326
|
+
* @returns {any} 配置值(未找到返回 undefined)
|
|
327
|
+
* @private
|
|
328
|
+
*/
|
|
329
|
+
_getRaw(path) {
|
|
330
|
+
const layerOrder = [
|
|
331
|
+
ConfigLayerType.RUNTIME,
|
|
332
|
+
ConfigLayerType.USER,
|
|
333
|
+
ConfigLayerType.MODULE,
|
|
334
|
+
ConfigLayerType.DEFAULT
|
|
335
|
+
]
|
|
336
|
+
|
|
337
|
+
for (const layerType of layerOrder) {
|
|
338
|
+
const layer = this._layers.get(layerType)
|
|
339
|
+
if (!layer) continue
|
|
340
|
+
|
|
341
|
+
const result = layer.get(path)
|
|
342
|
+
if (result.found) {
|
|
343
|
+
return result.value
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return undefined
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* 类型校验
|
|
352
|
+
* @param {string} path - 配置路径
|
|
353
|
+
* @param {any} value - 配置值
|
|
354
|
+
* @param {Object} options - 选项
|
|
355
|
+
* @returns {boolean} 是否通过校验
|
|
356
|
+
* @private
|
|
357
|
+
*/
|
|
358
|
+
_validateType(path, value, options = {}) {
|
|
359
|
+
if (!this._schema) return true
|
|
360
|
+
|
|
361
|
+
// 查找匹配的 schema 规则
|
|
362
|
+
const expectedType = this._schema[path]
|
|
363
|
+
if (!expectedType) return true // 没有对应的校验规则,通过
|
|
364
|
+
|
|
365
|
+
const actualType = getType(value)
|
|
366
|
+
if (actualType !== expectedType) {
|
|
367
|
+
const errorMsg = `配置类型不匹配:路径 "${path}" 期望 ${expectedType},实际 ${actualType}`
|
|
368
|
+
if (options.silent) {
|
|
369
|
+
return false
|
|
370
|
+
}
|
|
371
|
+
throw new ConfigError(errorMsg, 'CONFIG_TYPE_MISMATCH')
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return true
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export { ConfigSystem }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Nimbus2D - 配置类型定义
|
|
3
|
+
// ----------------------------------------------------------------------------
|
|
4
|
+
// ConfigSchema 类型校验定义
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 配置类型校验 schema
|
|
9
|
+
* key 为配置路径,value 为类型字符串
|
|
10
|
+
* 支持的类型:'number'、'string'、'boolean'、'object'、'array'、'function'
|
|
11
|
+
* @typedef {Object<string, string>} ConfigSchema
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 支持的类型校验列表
|
|
16
|
+
* @type {string[]}
|
|
17
|
+
*/
|
|
18
|
+
export const SUPPORTED_TYPES = ['number', 'string', 'boolean', 'object', 'array', 'function']
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 获取值的实际类型
|
|
22
|
+
* @param {any} value - 要检查的值
|
|
23
|
+
* @returns {string} 类型字符串
|
|
24
|
+
*/
|
|
25
|
+
export function getType(value) {
|
|
26
|
+
if (value === null) return 'null'
|
|
27
|
+
if (Array.isArray(value)) return 'array'
|
|
28
|
+
return typeof value
|
|
29
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Nimbus2D - 配置监听器管理
|
|
3
|
+
// ----------------------------------------------------------------------------
|
|
4
|
+
// 管理配置变化监听器,支持通配符路径模式
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
import { ConfigPath } from './ConfigPath.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 配置监听器管理类
|
|
11
|
+
* 管理 watch/unwatch 和变化通知
|
|
12
|
+
*/
|
|
13
|
+
class ConfigWatcher {
|
|
14
|
+
/**
|
|
15
|
+
* 构造函数
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
/**
|
|
19
|
+
* 监听器列表
|
|
20
|
+
* @type {Array<{pattern: string, callback: Function, pathTool: ConfigPath}>}
|
|
21
|
+
*/
|
|
22
|
+
this._watchers = []
|
|
23
|
+
|
|
24
|
+
/** @type {ConfigPath} 路径工具 */
|
|
25
|
+
this._pathTool = new ConfigPath()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 注册监听器
|
|
30
|
+
* @param {string} pathPattern - 路径模式(支持通配符 'modules.*.level')
|
|
31
|
+
* @param {Function} callback - 回调 (newValue, oldValue, path) => void
|
|
32
|
+
* @returns {Function} 取消监听函数
|
|
33
|
+
*/
|
|
34
|
+
watch(pathPattern, callback) {
|
|
35
|
+
const entry = { pattern: pathPattern, callback, pathTool: this._pathTool }
|
|
36
|
+
this._watchers.push(entry)
|
|
37
|
+
|
|
38
|
+
return () => this.unwatch(pathPattern, callback)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 取消监听
|
|
43
|
+
* @param {string} pathPattern - 路径模式
|
|
44
|
+
* @param {Function} callback - 回调函数
|
|
45
|
+
* @returns {boolean} 是否取消成功
|
|
46
|
+
*/
|
|
47
|
+
unwatch(pathPattern, callback) {
|
|
48
|
+
const idx = this._watchers.findIndex(
|
|
49
|
+
(w) => w.pattern === pathPattern && w.callback === callback
|
|
50
|
+
)
|
|
51
|
+
if (idx !== -1) {
|
|
52
|
+
this._watchers.splice(idx, 1)
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 通知配置变化
|
|
60
|
+
* @param {string} path - 变化的配置路径
|
|
61
|
+
* @param {any} newValue - 新值
|
|
62
|
+
* @param {any} oldValue - 旧值
|
|
63
|
+
*/
|
|
64
|
+
notify(path, newValue, oldValue) {
|
|
65
|
+
for (const watcher of this._watchers) {
|
|
66
|
+
if (this._pathTool.match(watcher.pattern, path)) {
|
|
67
|
+
try {
|
|
68
|
+
watcher.callback(newValue, oldValue, path)
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error(`[ConfigWatcher] 监听器执行出错 (${watcher.pattern}):`, e)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 清空所有监听器
|
|
78
|
+
*/
|
|
79
|
+
clear() {
|
|
80
|
+
this._watchers = []
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { ConfigWatcher }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Nimbus2D - ConfigSystem 模块统一导出
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export { ConfigSystem } from './ConfigSystem.js'
|
|
6
|
+
export { ConfigLayer } from './ConfigLayer.js'
|
|
7
|
+
export { ConfigLayerType, LAYER_FREEZABLE_DEFAULTS } from './ConfigLayerType.js'
|
|
8
|
+
export { ConfigPath } from './ConfigPath.js'
|
|
9
|
+
export { ConfigWatcher } from './ConfigWatcher.js'
|
|
10
|
+
export { deepMerge, deepFreeze } from './ConfigMerger.js'
|
|
11
|
+
|
|
12
|
+
/** 深度合并与冻结工具(命名导出别名,供主入口 ConfigMerger 使用) */
|
|
13
|
+
export { deepMerge as ConfigMerger } from './ConfigMerger.js'
|
|
14
|
+
|
|
15
|
+
/** 配置类型校验工具 */
|
|
16
|
+
export { SUPPORTED_TYPES, getType } from './ConfigTypes.js'
|
|
17
|
+
|
|
18
|
+
/** 配置类型校验命名空间(供主入口 ConfigTypes 使用) */
|
|
19
|
+
export * as ConfigTypes from './ConfigTypes.js'
|