@nbreak/core 0.1.0

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.
@@ -0,0 +1,831 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _nbreak_shared = require("@nbreak/shared");
3
+ //#region src/pluginSystem.js
4
+ /**
5
+ * @nbreak/core - 插件系统
6
+ *
7
+ * 升级自现有 src/core/pluginSystem.js,保留 hooks 机制并扩展:
8
+ * - 增加中间件支持(hook 前后置拦截)
9
+ * - 增加钩子结果聚合策略
10
+ * - 与 ExtensionRegistry 协同
11
+ */
12
+ /**
13
+ * 钩子聚合策略
14
+ */
15
+ var HOOK_AGGREGATE_STRATEGIES = {
16
+ /** 后者覆盖前者(默认,pipe 风格) */
17
+ PIPE: "pipe",
18
+ /** 收集所有结果为数组 */
19
+ COLLECT: "collect",
20
+ /** 取第一个非空结果 */
21
+ FIRST: "first",
22
+ /** 取最后一个非空结果 */
23
+ LAST: "last",
24
+ /** 并行执行,结果为数组(无序) */
25
+ PARALLEL: "parallel"
26
+ };
27
+ var PluginSystem = class {
28
+ constructor() {
29
+ this.plugins = /* @__PURE__ */ new Map();
30
+ this.hooks = /* @__PURE__ */ new Map();
31
+ this.middlewares = [];
32
+ }
33
+ /**
34
+ * 注册插件
35
+ * @param {Object} plugin - 插件定义
36
+ * @param {string} plugin.name - 插件名称(唯一)
37
+ * @param {Function} plugin.install - 安装函数 (api) => {}
38
+ * @param {Function} [plugin.uninstall] - 卸载函数
39
+ */
40
+ register(plugin) {
41
+ if (!plugin || !plugin.name) {
42
+ console.warn("[DataScreen] 插件注册失败:缺少 name 字段");
43
+ return this;
44
+ }
45
+ if (this.plugins.has(plugin.name)) {
46
+ console.warn(`[DataScreen] 插件 "${plugin.name}" 已注册,跳过`);
47
+ return this;
48
+ }
49
+ const api = this._createPluginApi(plugin.name);
50
+ if (typeof plugin.install === "function") try {
51
+ plugin.install(api);
52
+ } catch (e) {
53
+ console.error(`[DataScreen] 插件 "${plugin.name}" 安装失败:`, e);
54
+ }
55
+ this.plugins.set(plugin.name, {
56
+ ...plugin,
57
+ api
58
+ });
59
+ return this;
60
+ }
61
+ /**
62
+ * 注入钩子(按优先级顺序执行)
63
+ * @param {string} hookName - 钩子名称
64
+ * @param {Object} [context={}] - 上下文数据
65
+ * @param {Object} [options] - 执行选项
66
+ * @param {string} [options.strategy] - 聚合策略
67
+ * @returns {*} 钩子执行结果
68
+ */
69
+ async callHook(hookName, context = {}, options = {}) {
70
+ const sorted = [...this.hooks.get(hookName) || []].sort((a, b) => a.priority - b.priority);
71
+ const strategy = options.strategy || HOOK_AGGREGATE_STRATEGIES.PIPE;
72
+ let processedContext = context;
73
+ for (const mw of this.middlewares) if (mw.before) try {
74
+ processedContext = await mw.before(hookName, processedContext);
75
+ } catch (e) {
76
+ console.error(`[DataScreen] 中间件 before 错误 (${hookName}):`, e);
77
+ }
78
+ if (strategy === HOOK_AGGREGATE_STRATEGIES.COLLECT || strategy === HOOK_AGGREGATE_STRATEGIES.PARALLEL) {
79
+ if (strategy === HOOK_AGGREGATE_STRATEGIES.PARALLEL) return (await Promise.allSettled(sorted.map((h) => Promise.resolve(h.handler((0, _nbreak_shared.deepClone)(processedContext)))))).map((r) => r.status === "fulfilled" ? r.value : null);
80
+ const collected = [];
81
+ for (const handler of sorted) try {
82
+ const result = await handler.handler((0, _nbreak_shared.deepClone)(processedContext));
83
+ collected.push(result);
84
+ } catch (e) {
85
+ console.error(`[DataScreen] Hook "${hookName}" 错误 (${handler.pluginName}):`, e);
86
+ }
87
+ return collected;
88
+ }
89
+ if (strategy === HOOK_AGGREGATE_STRATEGIES.FIRST) {
90
+ for (const handler of sorted) try {
91
+ const result = await handler.handler((0, _nbreak_shared.deepClone)(processedContext));
92
+ if (result !== void 0 && result !== null) return result;
93
+ } catch (e) {
94
+ console.error(`[DataScreen] Hook "${hookName}" 错误 (${handler.pluginName}):`, e);
95
+ }
96
+ return;
97
+ }
98
+ if (strategy === HOOK_AGGREGATE_STRATEGIES.LAST) {
99
+ let lastResult;
100
+ for (const handler of sorted) try {
101
+ const result = await handler.handler((0, _nbreak_shared.deepClone)(processedContext));
102
+ if (result !== void 0 && result !== null) lastResult = result;
103
+ } catch (e) {
104
+ console.error(`[DataScreen] Hook "${hookName}" 错误 (${handler.pluginName}):`, e);
105
+ }
106
+ return lastResult;
107
+ }
108
+ let result = processedContext;
109
+ for (const handler of sorted) try {
110
+ result = await handler.handler(result);
111
+ } catch (e) {
112
+ console.error(`[DataScreen] Hook "${hookName}" 错误 (${handler.pluginName}):`, e);
113
+ }
114
+ for (const mw of this.middlewares) if (mw.after) try {
115
+ result = await mw.after(hookName, result);
116
+ } catch (e) {
117
+ console.error(`[DataScreen] 中间件 after 错误 (${hookName}):`, e);
118
+ }
119
+ return result;
120
+ }
121
+ /**
122
+ * 同步注入钩子(不等待 Promise)
123
+ * @param {string} hookName
124
+ * @param {Object} [context={}]
125
+ * @returns {Object}
126
+ */
127
+ callHookSync(hookName, context = {}) {
128
+ const sorted = [...this.hooks.get(hookName) || []].sort((a, b) => a.priority - b.priority);
129
+ let result = context;
130
+ for (const handler of sorted) try {
131
+ const ret = handler.handler(result);
132
+ if (ret !== void 0) result = ret;
133
+ } catch (e) {
134
+ console.error(`[DataScreen] Hook sync "${hookName}" 错误 (${handler.pluginName}):`, e);
135
+ }
136
+ return result;
137
+ }
138
+ /**
139
+ * 添加全局中间件
140
+ * @param {Object} middleware
141
+ * @param {Function} [middleware.before]
142
+ * @param {Function} [middleware.after]
143
+ */
144
+ use(middleware) {
145
+ if (middleware && (middleware.before || middleware.after)) this.middlewares.push(middleware);
146
+ return this;
147
+ }
148
+ /**
149
+ * 获取所有已注册插件
150
+ */
151
+ getPlugins() {
152
+ return Array.from(this.plugins.values());
153
+ }
154
+ /**
155
+ * 获取插件
156
+ */
157
+ getPlugin(name) {
158
+ return this.plugins.get(name);
159
+ }
160
+ /**
161
+ * 检查插件是否已注册
162
+ */
163
+ hasPlugin(name) {
164
+ return this.plugins.has(name);
165
+ }
166
+ /**
167
+ * 获取所有钩子名
168
+ */
169
+ getHookNames() {
170
+ return Array.from(this.hooks.keys());
171
+ }
172
+ /**
173
+ * 获取某个钩子的处理器数量
174
+ */
175
+ getHookHandlerCount(hookName) {
176
+ return (this.hooks.get(hookName) || []).length;
177
+ }
178
+ /**
179
+ * 卸载插件
180
+ */
181
+ unregister(name) {
182
+ const plugin = this.plugins.get(name);
183
+ if (plugin && typeof plugin.uninstall === "function") try {
184
+ plugin.uninstall();
185
+ } catch (e) {
186
+ console.error(`[DataScreen] 插件 "${name}" 卸载失败:`, e);
187
+ }
188
+ this.plugins.delete(name);
189
+ this.hooks.forEach((handlers, hookName) => {
190
+ this.hooks.set(hookName, handlers.filter((h) => h.pluginName !== name));
191
+ });
192
+ return this;
193
+ }
194
+ /**
195
+ * 清空所有插件与钩子
196
+ */
197
+ clear() {
198
+ this.plugins.clear();
199
+ this.hooks.clear();
200
+ this.middlewares = [];
201
+ return this;
202
+ }
203
+ /**
204
+ * 为插件创建 API 对象
205
+ */
206
+ _createPluginApi(pluginName) {
207
+ return {
208
+ pluginName,
209
+ /**
210
+ * 注册钩子处理器
211
+ * @param {string} hookName
212
+ * @param {Function} handler
213
+ * @param {number} [priority=100] - 优先级(越小越先执行)
214
+ */
215
+ hook: (hookName, handler, priority = 100) => {
216
+ if (typeof handler !== "function") {
217
+ console.warn(`[DataScreen] 插件 "${pluginName}" 注册钩子 "${hookName}" 失败:handler 不是函数`);
218
+ return;
219
+ }
220
+ if (!this.hooks.has(hookName)) this.hooks.set(hookName, []);
221
+ this.hooks.get(hookName).push({
222
+ pluginName,
223
+ handler,
224
+ priority
225
+ });
226
+ },
227
+ /**
228
+ * 注册多个钩子
229
+ * @param {Object} hooks - { hookName: handler }
230
+ */
231
+ hooks: (hooks = {}) => {
232
+ Object.entries(hooks).forEach(([hookName, handler]) => {
233
+ if (typeof handler === "function") this._createPluginApi(pluginName).hook(hookName, handler);
234
+ });
235
+ },
236
+ /**
237
+ * 获取已注册插件
238
+ */
239
+ getPlugin: (name) => this.plugins.get(name),
240
+ /**
241
+ * 获取所有插件
242
+ */
243
+ getPlugins: () => Array.from(this.plugins.values())
244
+ };
245
+ }
246
+ };
247
+ var pluginSystem = new PluginSystem();
248
+ //#endregion
249
+ //#region src/eventBus.js
250
+ /**
251
+ * @nbreak/core - 事件总线(统一版)
252
+ *
253
+ * 合并原 core 与 app(interactions/EventBus) 两套实现,作为唯一事件总线:
254
+ * - 标准 on/off/once/emit(同步触发,双参 handler(data, meta))
255
+ * - emitSync 别名 / emitAsync 异步触发(await handler 返回的 Promise)
256
+ * - 通配符订阅(component:*)+ 命名空间级通配(user:*)
257
+ * - 优先级排序、命名空间隔离、createNamespace 子总线
258
+ * - waitFor(Promise 风格等待事件)
259
+ * - clearEvent / clearNamespace / offNamespace / clear
260
+ * - listenerCount / eventNames / getEvents / getNamespaces
261
+ */
262
+ /**
263
+ * 事件总线类
264
+ */
265
+ var EventBus = class {
266
+ constructor() {
267
+ this.events = /* @__PURE__ */ new Map();
268
+ this.namespaces = /* @__PURE__ */ new Map();
269
+ this.wildcardListeners = [];
270
+ }
271
+ /**
272
+ * 解析事件名称,提取命名空间
273
+ * @param {string} event - 事件名称 (如: 'user:login', 'data:update')
274
+ * @returns {{ event: string, namespace: string|null, action: string }}
275
+ */
276
+ parseEventName(event) {
277
+ const parts = event.split(":");
278
+ return {
279
+ event,
280
+ namespace: parts.length > 1 ? parts[0] : null,
281
+ action: parts.length > 1 ? parts.slice(1).join(":") : event
282
+ };
283
+ }
284
+ /**
285
+ * 订阅事件
286
+ * @param {string} event - 事件名称,支持通配符(如 'component:*')与命名空间
287
+ * @param {Function} callback - 回调函数 (data, meta) => void
288
+ * @param {Object} [options]
289
+ * @param {string} [options.namespace] - 命名空间
290
+ * @param {number} [options.priority] - 优先级(数字越大越先执行)
291
+ * @returns {Function} 取消订阅函数
292
+ */
293
+ on(event, callback, options = {}) {
294
+ if (typeof callback !== "function") {
295
+ console.warn("[EventBus] callback 必须是函数");
296
+ return () => {};
297
+ }
298
+ const { namespace, priority = 0 } = options;
299
+ const eventKey = namespace ? `${namespace}:${event}` : event;
300
+ if (event.includes("*")) {
301
+ this.wildcardListeners.push({
302
+ pattern: event,
303
+ regex: new RegExp("^" + event.replace(/\*/g, ".*") + "$"),
304
+ callback,
305
+ priority
306
+ });
307
+ return () => this.offWildcard(callback);
308
+ }
309
+ if (!this.events.has(eventKey)) this.events.set(eventKey, []);
310
+ const listeners = this.events.get(eventKey);
311
+ const listener = {
312
+ callback,
313
+ priority,
314
+ namespace
315
+ };
316
+ const insertIndex = listeners.findIndex((l) => l.priority < priority);
317
+ if (insertIndex === -1) listeners.push(listener);
318
+ else listeners.splice(insertIndex, 0, listener);
319
+ if (namespace) {
320
+ if (!this.namespaces.has(namespace)) this.namespaces.set(namespace, /* @__PURE__ */ new Set());
321
+ this.namespaces.get(namespace).add(eventKey);
322
+ }
323
+ return () => this.off(eventKey, callback);
324
+ }
325
+ /**
326
+ * 订阅事件(只触发一次)
327
+ */
328
+ once(event, callback, options = {}) {
329
+ const { namespace } = options;
330
+ const eventKey = namespace ? `${namespace}:${event}` : event;
331
+ const wrapper = (data, meta) => {
332
+ callback(data, meta);
333
+ this.off(eventKey, wrapper);
334
+ };
335
+ return this.on(event, wrapper, options);
336
+ }
337
+ /**
338
+ * 取消订阅
339
+ * @param {string} event - 事件名称(或 eventKey)
340
+ * @param {Function} callback - 回调函数;省略则清空该事件所有订阅
341
+ */
342
+ off(event, callback) {
343
+ const listeners = this.events.get(event);
344
+ if (listeners) if (callback) {
345
+ const index = listeners.findIndex((l) => l.callback === callback);
346
+ if (index > -1) listeners.splice(index, 1);
347
+ if (listeners.length === 0) this.events.delete(event);
348
+ } else this.events.delete(event);
349
+ return this;
350
+ }
351
+ /**
352
+ * 取消通配符订阅
353
+ */
354
+ offWildcard(callback) {
355
+ const index = this.wildcardListeners.findIndex((l) => l.callback === callback);
356
+ if (index > -1) this.wildcardListeners.splice(index, 1);
357
+ return this;
358
+ }
359
+ /**
360
+ * 同步触发事件(默认行为)
361
+ *
362
+ * handler 接收双参:(data, meta)
363
+ * meta 包含 { timestamp, event, namespace }
364
+ *
365
+ * @param {string} event - 事件名称
366
+ * @param {*} [data] - 事件数据
367
+ * @param {Object} [meta] - 额外元数据
368
+ */
369
+ emit(event, data, meta = {}) {
370
+ const timestamp = Date.now();
371
+ const eventInfo = this.parseEventName(event);
372
+ const fullMeta = {
373
+ ...meta,
374
+ timestamp,
375
+ event,
376
+ namespace: eventInfo.namespace
377
+ };
378
+ const listeners = this.events.get(event);
379
+ if (listeners) [...listeners].forEach(({ callback }) => {
380
+ try {
381
+ callback(data, fullMeta);
382
+ } catch (e) {
383
+ console.error(`[EventBus] 事件 "${event}" 处理错误:`, e);
384
+ }
385
+ });
386
+ this.wildcardListeners.forEach(({ regex, callback }) => {
387
+ if (regex.test(event)) try {
388
+ callback(data, fullMeta);
389
+ } catch (e) {
390
+ console.error(`[EventBus] 通配事件 "${event}" 处理错误:`, e);
391
+ }
392
+ });
393
+ if (eventInfo.namespace) {
394
+ const nsListeners = this.events.get(`${eventInfo.namespace}:*`);
395
+ if (nsListeners) [...nsListeners].forEach(({ callback }) => {
396
+ try {
397
+ callback(data, fullMeta);
398
+ } catch (e) {
399
+ console.error(`[EventBus] 命名空间事件 "${event}" 处理错误:`, e);
400
+ }
401
+ });
402
+ }
403
+ }
404
+ /**
405
+ * 同步触发(emit 的别名,保持向后兼容)
406
+ */
407
+ emitSync(event, data, meta = {}) {
408
+ return this.emit(event, data, meta);
409
+ }
410
+ /**
411
+ * 异步触发事件(等待 handler 返回的 Promise)
412
+ * @param {string} event
413
+ * @param {*} [data]
414
+ * @param {Object} [meta]
415
+ * @returns {Promise<void>}
416
+ */
417
+ async emitAsync(event, data, meta = {}) {
418
+ const timestamp = Date.now();
419
+ const eventInfo = this.parseEventName(event);
420
+ const fullMeta = {
421
+ ...meta,
422
+ timestamp,
423
+ event,
424
+ namespace: eventInfo.namespace
425
+ };
426
+ const runHandler = async (callback) => {
427
+ try {
428
+ const result = callback(data, fullMeta);
429
+ if (result && typeof result.then === "function") await result;
430
+ } catch (e) {
431
+ console.error(`[EventBus] async 事件 "${event}" 处理错误:`, e);
432
+ }
433
+ };
434
+ const listeners = this.events.get(event);
435
+ if (listeners) for (const { callback } of listeners) await runHandler(callback);
436
+ for (const { regex, callback } of this.wildcardListeners) if (regex.test(event)) await runHandler(callback);
437
+ if (eventInfo.namespace) {
438
+ const nsListeners = this.events.get(`${eventInfo.namespace}:*`);
439
+ if (nsListeners) for (const { callback } of nsListeners) await runHandler(callback);
440
+ }
441
+ }
442
+ /**
443
+ * 清除指定事件的所有订阅
444
+ */
445
+ clearEvent(event) {
446
+ this.events.delete(event);
447
+ return this;
448
+ }
449
+ /**
450
+ * 清除指定命名空间的所有订阅
451
+ */
452
+ clearNamespace(namespace) {
453
+ const events = this.namespaces.get(namespace);
454
+ if (events) {
455
+ events.forEach((event) => this.events.delete(event));
456
+ this.namespaces.delete(namespace);
457
+ }
458
+ return this;
459
+ }
460
+ /**
461
+ * 取消某命名空间下的所有订阅(clearNamespace 别名,向后兼容)
462
+ */
463
+ offNamespace(namespace) {
464
+ return this.clearNamespace(namespace);
465
+ }
466
+ /**
467
+ * 清空所有订阅
468
+ */
469
+ clear() {
470
+ this.events.clear();
471
+ this.namespaces.clear();
472
+ this.wildcardListeners = [];
473
+ return this;
474
+ }
475
+ /**
476
+ * 获取事件的监听器数量
477
+ */
478
+ listenerCount(event) {
479
+ const listeners = this.events.get(event);
480
+ return listeners ? listeners.length : 0;
481
+ }
482
+ /**
483
+ * 获取所有注册的事件名(eventNames 别名)
484
+ */
485
+ getEvents() {
486
+ return Array.from(this.events.keys());
487
+ }
488
+ eventNames() {
489
+ return this.getEvents();
490
+ }
491
+ /**
492
+ * 获取所有命名空间
493
+ */
494
+ getNamespaces() {
495
+ return Array.from(this.namespaces.keys());
496
+ }
497
+ /**
498
+ * 等待某个事件触发(Promise 风格)
499
+ * @param {string} event
500
+ * @param {number} [timeout=5000] - 超时毫秒
501
+ * @returns {Promise} 事件数据
502
+ */
503
+ waitFor(event, timeout = 5e3) {
504
+ return new Promise((resolve, reject) => {
505
+ const timer = setTimeout(() => {
506
+ this.off(event, handler);
507
+ reject(/* @__PURE__ */ new Error(`Timeout waiting for event: ${event}`));
508
+ }, timeout);
509
+ const handler = (data) => {
510
+ clearTimeout(timer);
511
+ this.off(event, handler);
512
+ resolve(data);
513
+ };
514
+ this.on(event, handler);
515
+ });
516
+ }
517
+ /**
518
+ * 创建命名空间子总线
519
+ * @param {string} namespace
520
+ * @returns {{ on, once, emit, clear }}
521
+ */
522
+ createNamespace(namespace) {
523
+ return {
524
+ on: (event, callback, options = {}) => this.on(event, callback, {
525
+ ...options,
526
+ namespace
527
+ }),
528
+ once: (event, callback, options = {}) => this.once(event, callback, {
529
+ ...options,
530
+ namespace
531
+ }),
532
+ emit: (event, data, meta = {}) => this.emit(`${namespace}:${event}`, data, meta),
533
+ clear: () => this.clearNamespace(namespace)
534
+ };
535
+ }
536
+ /**
537
+ * 通配符匹配(内部使用,保留以兼容直接调用)
538
+ */
539
+ _matchPattern(pattern, event) {
540
+ if (!pattern.includes("*")) return false;
541
+ return new RegExp("^" + pattern.replace(/\*/g, ".*") + "$").test(event);
542
+ }
543
+ };
544
+ var eventBus = new EventBus();
545
+ //#endregion
546
+ //#region src/extensionRegistry.js
547
+ /**
548
+ * @nbreak/core - 扩展注册表
549
+ *
550
+ * 核心扩展注册表,按 type 分桶管理所有扩展物
551
+ * 静态加载与动态加载的扩展最终都通过 register() 装载到此
552
+ *
553
+ * 对标:
554
+ * - Superset: PluginContext.registerPlugin()
555
+ * - DataV: 组件市场注册中心
556
+ * - Tableau: Extensions Service
557
+ */
558
+ var { HOOK_NAMES: HOOK_NAMES$1 } = { HOOK_NAMES: {
559
+ BEFORE_EXTENSION_REGISTER: "beforeExtensionRegister",
560
+ AFTER_EXTENSION_REGISTER: "afterExtensionRegister",
561
+ BEFORE_EXTENSION_UNREGISTER: "beforeExtensionUnregister"
562
+ } };
563
+ var ExtensionRegistry = class {
564
+ constructor() {
565
+ this.buckets = /* @__PURE__ */ new Map();
566
+ for (const type of _nbreak_shared.ALL_EXTENSION_TYPES) this.buckets.set(type, /* @__PURE__ */ new Map());
567
+ this.nameIndex = /* @__PURE__ */ new Map();
568
+ this._disposers = [];
569
+ }
570
+ /**
571
+ * 注册扩展
572
+ * @param {Object} extension - 扩展定义对象
573
+ * @returns {boolean} 是否注册成功
574
+ */
575
+ async register(extension) {
576
+ if (!extension || !extension.type || !extension.name) {
577
+ console.warn("[DataScreen Registry] 扩展注册失败:缺少 type 或 name", extension);
578
+ return false;
579
+ }
580
+ if (!_nbreak_shared.ALL_EXTENSION_TYPES.includes(extension.type)) {
581
+ console.warn(`[DataScreen Registry] 无效的扩展类型: "${extension.type}"`);
582
+ return false;
583
+ }
584
+ if (this.nameIndex.has(extension.name)) {
585
+ console.warn(`[DataScreen Registry] 扩展 "${extension.name}" 已注册,跳过`);
586
+ return false;
587
+ }
588
+ if (extension.manifest) {
589
+ const { valid, errors } = (0, _nbreak_shared.validateManifest)(extension.manifest);
590
+ if (!valid) {
591
+ console.warn(`[DataScreen Registry] 扩展 "${extension.name}" manifest 校验失败:`, errors);
592
+ return false;
593
+ }
594
+ }
595
+ try {
596
+ await pluginSystem.callHook(HOOK_NAMES$1.BEFORE_EXTENSION_REGISTER, { extension });
597
+ } catch (e) {
598
+ console.error(`[DataScreen Registry] 扩展 "${extension.name}" 前置钩子异常:`, e);
599
+ }
600
+ const bucket = this.buckets.get(extension.type);
601
+ const ext = {
602
+ ...extension,
603
+ status: _nbreak_shared.EXTENSION_STATUS.REGISTERED,
604
+ registeredAt: Date.now()
605
+ };
606
+ bucket.set(extension.name, ext);
607
+ this.nameIndex.set(extension.name, extension.type);
608
+ eventBus.emit("extension:registered", {
609
+ type: extension.type,
610
+ name: extension.name,
611
+ extension: ext
612
+ });
613
+ try {
614
+ await pluginSystem.callHook(HOOK_NAMES$1.AFTER_EXTENSION_REGISTER, { extension: ext });
615
+ } catch (e) {
616
+ console.error(`[DataScreen Registry] 扩展 "${extension.name}" 后置钩子异常:`, e);
617
+ }
618
+ return true;
619
+ }
620
+ /**
621
+ * 批量注册扩展
622
+ */
623
+ async registerAll(extensions) {
624
+ if (!Array.isArray(extensions)) return [];
625
+ const results = [];
626
+ for (const ext of extensions) results.push(await this.register(ext));
627
+ return results;
628
+ }
629
+ /**
630
+ * 注销扩展
631
+ */
632
+ async unregister(name) {
633
+ const type = this.nameIndex.get(name);
634
+ if (!type) return false;
635
+ try {
636
+ await pluginSystem.callHook(HOOK_NAMES$1.BEFORE_EXTENSION_UNREGISTER, {
637
+ name,
638
+ type
639
+ });
640
+ } catch (e) {
641
+ console.error(`[DataScreen Registry] 扩展 "${name}" 注销前置钩子异常:`, e);
642
+ }
643
+ const bucket = this.buckets.get(type);
644
+ const ext = bucket.get(name);
645
+ bucket.delete(name);
646
+ this.nameIndex.delete(name);
647
+ eventBus.emit("extension:unregistered", {
648
+ name,
649
+ type,
650
+ extension: ext
651
+ });
652
+ return true;
653
+ }
654
+ /**
655
+ * 获取扩展(按 type + name)
656
+ */
657
+ get(type, name) {
658
+ const bucket = this.buckets.get(type);
659
+ if (!bucket) return null;
660
+ return bucket.get(name) || null;
661
+ }
662
+ /**
663
+ * 按 name 跨类型查找
664
+ */
665
+ getByName(name) {
666
+ const type = this.nameIndex.get(name);
667
+ if (!type) return null;
668
+ return this.get(type, name);
669
+ }
670
+ /**
671
+ * 获取某类型的所有扩展
672
+ */
673
+ getByType(type) {
674
+ const bucket = this.buckets.get(type);
675
+ if (!bucket) return [];
676
+ return Array.from(bucket.values());
677
+ }
678
+ /**
679
+ * 获取所有扩展
680
+ */
681
+ getAll() {
682
+ const all = [];
683
+ for (const bucket of this.buckets.values()) for (const ext of bucket.values()) all.push(ext);
684
+ return all;
685
+ }
686
+ /**
687
+ * 检查扩展是否存在
688
+ */
689
+ has(name) {
690
+ return this.nameIndex.has(name);
691
+ }
692
+ /**
693
+ * 按类型检查扩展是否存在
694
+ */
695
+ hasOfType(type, name) {
696
+ const bucket = this.buckets.get(type);
697
+ return bucket ? bucket.has(name) : false;
698
+ }
699
+ /**
700
+ * 获取扩展数量
701
+ */
702
+ size(type) {
703
+ if (type) {
704
+ const bucket = this.buckets.get(type);
705
+ return bucket ? bucket.size : 0;
706
+ }
707
+ return this.nameIndex.size;
708
+ }
709
+ /**
710
+ * 启用扩展
711
+ */
712
+ enable(name) {
713
+ const ext = this.getByName(name);
714
+ if (ext) {
715
+ ext.status = _nbreak_shared.EXTENSION_STATUS.ENABLED;
716
+ eventBus.emit("extension:enabled", {
717
+ name,
718
+ type: ext.type
719
+ });
720
+ }
721
+ return this;
722
+ }
723
+ /**
724
+ * 禁用扩展
725
+ */
726
+ disable(name) {
727
+ const ext = this.getByName(name);
728
+ if (ext) {
729
+ ext.status = _nbreak_shared.EXTENSION_STATUS.DISABLED;
730
+ eventBus.emit("extension:disabled", {
731
+ name,
732
+ type: ext.type
733
+ });
734
+ }
735
+ return this;
736
+ }
737
+ /**
738
+ * 是否启用
739
+ */
740
+ isEnabled(name) {
741
+ const ext = this.getByName(name);
742
+ return ext ? ext.status === _nbreak_shared.EXTENSION_STATUS.ENABLED : false;
743
+ }
744
+ /**
745
+ * 按分类筛选组件扩展
746
+ */
747
+ getComponentsByCategory(category) {
748
+ return this.getByType(_nbreak_shared.EXTENSION_TYPES.COMPONENT).filter((ext) => ext.definition && ext.definition.category === category);
749
+ }
750
+ /**
751
+ * 搜索组件扩展
752
+ */
753
+ searchComponents(keyword) {
754
+ const components = this.getByType(_nbreak_shared.EXTENSION_TYPES.COMPONENT);
755
+ if (!keyword) return components;
756
+ const lower = keyword.toLowerCase();
757
+ return components.filter((ext) => {
758
+ const def = ext.definition || {};
759
+ return (ext.name || "").toLowerCase().includes(lower) || (def.name || "").toLowerCase().includes(lower) || (ext.displayName || "").toLowerCase().includes(lower) || (def.description || "").toLowerCase().includes(lower) || (def.tags || []).some((t) => t.toLowerCase().includes(lower));
760
+ });
761
+ }
762
+ /**
763
+ * 清空所有扩展
764
+ */
765
+ clear() {
766
+ for (const bucket of this.buckets.values()) bucket.clear();
767
+ this.nameIndex.clear();
768
+ return this;
769
+ }
770
+ /**
771
+ * 获取注册表快照(用于调试/序列化)
772
+ */
773
+ snapshot() {
774
+ const snap = {};
775
+ for (const [type, bucket] of this.buckets) snap[type] = Array.from(bucket.keys());
776
+ return snap;
777
+ }
778
+ };
779
+ var extensionRegistry = new ExtensionRegistry();
780
+ //#endregion
781
+ //#region src/index.js
782
+ var VERSION = "0.1.0";
783
+ var PACKAGE_NAME = "@nbreak/core";
784
+ //#endregion
785
+ Object.defineProperty(exports, "ALL_EXTENSION_TYPES", {
786
+ enumerable: true,
787
+ get: function() {
788
+ return _nbreak_shared.ALL_EXTENSION_TYPES;
789
+ }
790
+ });
791
+ Object.defineProperty(exports, "COMPONENT_CATEGORIES", {
792
+ enumerable: true,
793
+ get: function() {
794
+ return _nbreak_shared.COMPONENT_CATEGORIES;
795
+ }
796
+ });
797
+ Object.defineProperty(exports, "EXTENSION_STATUS", {
798
+ enumerable: true,
799
+ get: function() {
800
+ return _nbreak_shared.EXTENSION_STATUS;
801
+ }
802
+ });
803
+ Object.defineProperty(exports, "EXTENSION_TYPES", {
804
+ enumerable: true,
805
+ get: function() {
806
+ return _nbreak_shared.EXTENSION_TYPES;
807
+ }
808
+ });
809
+ exports.EventBus = EventBus;
810
+ exports.ExtensionRegistry = ExtensionRegistry;
811
+ exports.HOOK_AGGREGATE_STRATEGIES = HOOK_AGGREGATE_STRATEGIES;
812
+ Object.defineProperty(exports, "HOOK_NAMES", {
813
+ enumerable: true,
814
+ get: function() {
815
+ return _nbreak_shared.HOOK_NAMES;
816
+ }
817
+ });
818
+ exports.PACKAGE_NAME = PACKAGE_NAME;
819
+ Object.defineProperty(exports, "PROPERTY_FIELD_TYPES", {
820
+ enumerable: true,
821
+ get: function() {
822
+ return _nbreak_shared.PROPERTY_FIELD_TYPES;
823
+ }
824
+ });
825
+ exports.PluginSystem = PluginSystem;
826
+ exports.VERSION = VERSION;
827
+ exports.eventBus = eventBus;
828
+ exports.extensionRegistry = extensionRegistry;
829
+ exports.pluginSystem = pluginSystem;
830
+
831
+ //# sourceMappingURL=index.cjs.map