@knotx/data 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.cjs ADDED
@@ -0,0 +1,807 @@
1
+ 'use strict';
2
+
3
+ const rxjs = require('rxjs');
4
+ const operators = require('rxjs/operators');
5
+
6
+ var __defProp$1 = Object.defineProperty;
7
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
8
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues$1 = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp$1.call(b, prop))
14
+ __defNormalProp$1(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols$1)
16
+ for (var prop of __getOwnPropSymbols$1(b)) {
17
+ if (__propIsEnum$1.call(b, prop))
18
+ __defNormalProp$1(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
23
+ class DataManager {
24
+ constructor(tag) {
25
+ this.tag = tag;
26
+ __publicField$1(this, "operations$", new rxjs.Subject());
27
+ __publicField$1(this, "operationPipes$", new rxjs.BehaviorSubject({
28
+ transform: [],
29
+ preOperation: [],
30
+ postOperation: []
31
+ }));
32
+ __publicField$1(this, "drafts$", new rxjs.BehaviorSubject(/* @__PURE__ */ new Map()));
33
+ __publicField$1(this, "dataMap$", new rxjs.BehaviorSubject(/* @__PURE__ */ new Map()));
34
+ __publicField$1(this, "currentDraftDataMap$", new rxjs.BehaviorSubject(void 0));
35
+ /**
36
+ * 数据版本号,用于标识数据的变化,数据更新时,patchVersion 会递增
37
+ */
38
+ __publicField$1(this, "patchVersion$", new rxjs.BehaviorSubject(0));
39
+ /**
40
+ * 数据版本号,用于标识数据的变化,数据增删时,mapVersion 会递增
41
+ */
42
+ __publicField$1(this, "mapVersion$", new rxjs.BehaviorSubject(0));
43
+ __publicField$1(this, "_patchVersionUpdating", false);
44
+ __publicField$1(this, "_mapVersionUpdating", false);
45
+ }
46
+ get version() {
47
+ return this.patchVersion$.value + this.mapVersion$.value;
48
+ }
49
+ getDataList$() {
50
+ return this.dataMap$.pipe(
51
+ operators.map((dataMap) => Array.from(dataMap.values()))
52
+ );
53
+ }
54
+ getDataList() {
55
+ return Array.from(this.dataMap$.value.values());
56
+ }
57
+ getData$(id, equal = Object.is) {
58
+ return this.dataMap$.pipe(
59
+ operators.map((dataMap) => dataMap.get(id)),
60
+ operators.distinctUntilChanged(equal)
61
+ );
62
+ }
63
+ getData(id) {
64
+ return this.dataMap$.value.get(id);
65
+ }
66
+ addDataOperationPipe(pipe2) {
67
+ const currentPipes = this.operationPipes$.value;
68
+ if (pipe2.transform) {
69
+ currentPipes.transform.push(pipe2.transform);
70
+ }
71
+ if (pipe2.preOperation) {
72
+ currentPipes.preOperation.push(pipe2.preOperation);
73
+ }
74
+ if (pipe2.postOperation) {
75
+ currentPipes.postOperation.push(pipe2.postOperation);
76
+ }
77
+ this.operationPipes$.next(currentPipes);
78
+ }
79
+ init(initialDataList = []) {
80
+ this.operations$.pipe(
81
+ // 执行预设转换管道
82
+ rxjs.pipe(...this.operationPipes$.value.transform.map((pipe2) => pipe2(this.operations$))),
83
+ // 执行预处理管道
84
+ rxjs.pipe(...this.operationPipes$.value.preOperation.map((pipe2) => pipe2(this.operations$))),
85
+ // 更新版本号
86
+ operators.tap((operation) => this.updateVersion(operation)),
87
+ operators.scan((dataMap, operation) => this.applyOperation(dataMap, operation), this.dataMap$.value),
88
+ operators.map((dataMap) => ({ dataMap, operations: [] })),
89
+ // 执行后处理管道
90
+ rxjs.pipe(...this.operationPipes$.value.postOperation.map((pipe2) => pipe2(this.operations$))),
91
+ // 更新版本号
92
+ operators.tap(({ operations }) => this.updateVersion({ type: "batch", operations })),
93
+ operators.map(({ dataMap, operations }) => this.applyOperation(dataMap, { type: "batch", operations }))
94
+ ).subscribe(this.dataMap$);
95
+ this.operations$.next({ type: "batch", operations: initialDataList.map((data) => ({ type: "add", data })), isInit: true });
96
+ }
97
+ getOperations$() {
98
+ return this.operations$.asObservable();
99
+ }
100
+ dispatch(operation) {
101
+ this.operations$.next(operation);
102
+ }
103
+ getDraftDataList(draftId) {
104
+ const draftDataMap = this.drafts$.value.get(draftId);
105
+ return draftDataMap ? Array.from(draftDataMap.value.values()).filter((data) => data !== false) : void 0;
106
+ }
107
+ getDraftData(draftId, dataId) {
108
+ const draftDataMap = this.drafts$.value.get(draftId);
109
+ const data = draftDataMap == null ? void 0 : draftDataMap.value.get(dataId);
110
+ if (data === false) {
111
+ return void 0;
112
+ }
113
+ return data;
114
+ }
115
+ getCurrentDraftData(dataId) {
116
+ var _a;
117
+ const data = (_a = this.currentDraftDataMap$.value) == null ? void 0 : _a.get(dataId);
118
+ if (data === false) {
119
+ return void 0;
120
+ }
121
+ return data;
122
+ }
123
+ applyOperation(dataMap, operation) {
124
+ switch (operation.type) {
125
+ case "add":
126
+ dataMap.delete(operation.data.id);
127
+ dataMap.set(operation.data.id, operation.data);
128
+ break;
129
+ case "remove":
130
+ dataMap.delete(operation.id);
131
+ break;
132
+ case "update": {
133
+ const current = dataMap.get(operation.id);
134
+ if (current) {
135
+ dataMap.set(operation.id, __spreadValues$1(__spreadValues$1({}, current), operation.data));
136
+ }
137
+ break;
138
+ }
139
+ case "batch":
140
+ operation.operations.reduce(
141
+ (acc, op) => this.applyOperation(acc, op),
142
+ dataMap
143
+ );
144
+ break;
145
+ case "startDraft": {
146
+ const draftDataMap$ = new rxjs.BehaviorSubject(/* @__PURE__ */ new Map());
147
+ this.drafts$.next(this.drafts$.value.set(operation.draftId, draftDataMap$));
148
+ this.currentDraftDataMap$.next(draftDataMap$.value);
149
+ break;
150
+ }
151
+ case "draftOperation": {
152
+ const draftDataMap = this.drafts$.value.get(operation.draftId);
153
+ if (draftDataMap) {
154
+ this.applyOperation(new Proxy(draftDataMap.value, {
155
+ get(target, prop) {
156
+ const draft = target;
157
+ switch (prop) {
158
+ case "get":
159
+ return (id) => {
160
+ if (!draft.has(id)) {
161
+ return dataMap.get(id);
162
+ }
163
+ return draft.get(id) || void 0;
164
+ };
165
+ case "set":
166
+ return (id, value) => draft.set(id, value);
167
+ case "delete":
168
+ return (id) => draft.set(id, false);
169
+ default:
170
+ return Reflect.get(target, prop);
171
+ }
172
+ }
173
+ }), operation.operation);
174
+ this.currentDraftDataMap$.next(draftDataMap.value);
175
+ }
176
+ break;
177
+ }
178
+ case "commitDraft": {
179
+ const draftData = this.drafts$.value.get(operation.draftId);
180
+ if (draftData) {
181
+ const operations = [];
182
+ draftData.value.forEach((data, id) => {
183
+ if (data === false) {
184
+ if (dataMap.has(id)) {
185
+ operations.push({ type: "remove", id });
186
+ }
187
+ return;
188
+ }
189
+ if (!dataMap.has(id)) {
190
+ operations.push({ type: "add", data });
191
+ return;
192
+ }
193
+ const currentData = dataMap.get(id);
194
+ if (!Object.is(currentData, data)) {
195
+ operations.push({ type: "update", id, data });
196
+ }
197
+ });
198
+ if (operations.length > 0) {
199
+ this.dispatch({ type: "batch", operations });
200
+ }
201
+ this.drafts$.value.delete(operation.draftId);
202
+ this.drafts$.next(this.drafts$.value);
203
+ if (this.currentDraftDataMap$.value === draftData.value) {
204
+ this.currentDraftDataMap$.next(void 0);
205
+ }
206
+ }
207
+ break;
208
+ }
209
+ case "discardDraft": {
210
+ this.drafts$.value.delete(operation.draftId);
211
+ this.drafts$.next(this.drafts$.value);
212
+ const draftData = this.drafts$.value.get(operation.draftId);
213
+ if (this.currentDraftDataMap$.value === (draftData == null ? void 0 : draftData.value)) {
214
+ this.currentDraftDataMap$.next(void 0);
215
+ }
216
+ break;
217
+ }
218
+ }
219
+ return dataMap;
220
+ }
221
+ updateVersion(operation, scheduler = queueMicrotask) {
222
+ if (this.isPatchOperation(operation)) {
223
+ if (this._patchVersionUpdating) {
224
+ return;
225
+ }
226
+ this._patchVersionUpdating = true;
227
+ scheduler(() => {
228
+ this.patchVersion$.next(this.patchVersion$.value + 1);
229
+ this._patchVersionUpdating = false;
230
+ });
231
+ }
232
+ if (this.isMapOperation(operation)) {
233
+ if (this._mapVersionUpdating) {
234
+ return;
235
+ }
236
+ this._mapVersionUpdating = true;
237
+ scheduler(() => {
238
+ this.mapVersion$.next(this.mapVersion$.value + 1);
239
+ this._mapVersionUpdating = false;
240
+ });
241
+ }
242
+ }
243
+ isPatchOperation(operation) {
244
+ switch (operation.type) {
245
+ case "update":
246
+ return true;
247
+ case "batch": {
248
+ return operation.isInit ? false : operation.operations.some((op) => this.isPatchOperation(op));
249
+ }
250
+ }
251
+ return false;
252
+ }
253
+ isMapOperation(operation) {
254
+ switch (operation.type) {
255
+ case "add":
256
+ case "remove":
257
+ return true;
258
+ case "batch": {
259
+ return operation.isInit ? false : operation.operations.some((op) => this.isMapOperation(op));
260
+ }
261
+ }
262
+ return false;
263
+ }
264
+ }
265
+
266
+ var __defProp = Object.defineProperty;
267
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
268
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
269
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
270
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
271
+ var __spreadValues = (a, b) => {
272
+ for (var prop in b || (b = {}))
273
+ if (__hasOwnProp.call(b, prop))
274
+ __defNormalProp(a, prop, b[prop]);
275
+ if (__getOwnPropSymbols)
276
+ for (var prop of __getOwnPropSymbols(b)) {
277
+ if (__propIsEnum.call(b, prop))
278
+ __defNormalProp(a, prop, b[prop]);
279
+ }
280
+ return a;
281
+ };
282
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
283
+ var ChangeType = /* @__PURE__ */ ((ChangeType2) => {
284
+ ChangeType2["ADD"] = "add";
285
+ ChangeType2["REMOVE"] = "remove";
286
+ return ChangeType2;
287
+ })(ChangeType || {});
288
+ class DualRelation {
289
+ constructor(options = {}) {
290
+ __publicField(this, "parentToChildren");
291
+ // 父节点到子节点集合的映射
292
+ __publicField(this, "childToParent");
293
+ // 子节点到父节点的映射
294
+ __publicField(this, "_version", 0);
295
+ // 内部版本计数器
296
+ __publicField(this, "_versionSubject");
297
+ // 版本变更的Observable
298
+ __publicField(this, "_batchUpdateMode", false);
299
+ // 是否处于批量更新模式
300
+ __publicField(this, "_hasPendingChanges", false);
301
+ // 是否有待处理的变更
302
+ __publicField(this, "_changeHistory", []);
303
+ // 变更历史记录
304
+ __publicField(this, "_options");
305
+ // 配置选项
306
+ __publicField(this, "_pendingChanges", []);
307
+ // 批量模式下的待处理变更
308
+ __publicField(this, "_nodeLevels", /* @__PURE__ */ new Map());
309
+ // 节点层级映射
310
+ __publicField(this, "_needsLevelRecalculation", false);
311
+ var _a, _b;
312
+ this.parentToChildren = /* @__PURE__ */ new Map();
313
+ this.childToParent = /* @__PURE__ */ new Map();
314
+ this._versionSubject = new rxjs.BehaviorSubject(this._version);
315
+ this._options = {
316
+ allowEmptyParent: (_a = options.allowEmptyParent) != null ? _a : false,
317
+ historyDepth: (_b = options.historyDepth) != null ? _b : 10
318
+ };
319
+ }
320
+ // 是否需要重新计算所有层级
321
+ /**
322
+ * 获取版本变更的Observable
323
+ */
324
+ get version() {
325
+ return this._versionSubject;
326
+ }
327
+ /**
328
+ * 获取变更历史记录
329
+ */
330
+ get changeHistory() {
331
+ return this._changeHistory;
332
+ }
333
+ /**
334
+ * 更新配置选项
335
+ * @param options 新的配置选项
336
+ */
337
+ updateOptions(options) {
338
+ this._options = __spreadValues(__spreadValues({}, this._options), options);
339
+ if (options.historyDepth !== void 0 && this._changeHistory.length > options.historyDepth) {
340
+ this._changeHistory = this._changeHistory.slice(-options.historyDepth);
341
+ }
342
+ }
343
+ /**
344
+ * 获取节点的层级
345
+ * 层级定义:
346
+ * 0: 不在关系中的节点
347
+ * 1: 顶层父节点(没有父节点的节点)
348
+ * n > 1: 子节点的层级是其父节点的层级 + 1
349
+ * @param node 要查询的节点
350
+ * @returns 节点的层级
351
+ */
352
+ getNodeLevel(node) {
353
+ if (this._needsLevelRecalculation) {
354
+ this.recalculateAllLevels();
355
+ }
356
+ return this._nodeLevels.get(node) || 0;
357
+ }
358
+ /**
359
+ * 重新计算所有节点的层级
360
+ * @private
361
+ */
362
+ recalculateAllLevels() {
363
+ this._nodeLevels.clear();
364
+ for (const parent of this.parentToChildren.keys()) {
365
+ if (!this.childToParent.has(parent)) {
366
+ this._nodeLevels.set(parent, 1);
367
+ }
368
+ }
369
+ const processed = /* @__PURE__ */ new Set();
370
+ let currentLevel = 1;
371
+ let currentLevelNodes = Array.from(this._nodeLevels.keys());
372
+ while (currentLevelNodes.length > 0) {
373
+ const nextLevelNodes = [];
374
+ currentLevel++;
375
+ for (const node of currentLevelNodes) {
376
+ processed.add(node);
377
+ const children = this.getChildren(node);
378
+ for (const child of children) {
379
+ if (!processed.has(child)) {
380
+ this._nodeLevels.set(child, currentLevel);
381
+ nextLevelNodes.push(child);
382
+ }
383
+ }
384
+ }
385
+ currentLevelNodes = nextLevelNodes;
386
+ }
387
+ this._needsLevelRecalculation = false;
388
+ }
389
+ /**
390
+ * 更新节点层级
391
+ * @param node 要更新的节点
392
+ * @param parent 节点的父节点
393
+ * @private
394
+ */
395
+ updateNodeLevel(node, parent) {
396
+ if (!parent) {
397
+ this._nodeLevels.delete(node);
398
+ return;
399
+ }
400
+ let parentLevel = this._nodeLevels.get(parent);
401
+ if (parentLevel === void 0) {
402
+ const grandParent = this.getParent(parent);
403
+ if (grandParent) {
404
+ this.updateNodeLevel(parent, grandParent);
405
+ parentLevel = this._nodeLevels.get(parent);
406
+ } else {
407
+ parentLevel = 1;
408
+ this._nodeLevels.set(parent, parentLevel);
409
+ }
410
+ }
411
+ if (parentLevel === void 0) {
412
+ this._needsLevelRecalculation = true;
413
+ parentLevel = 1;
414
+ }
415
+ this._nodeLevels.set(node, parentLevel + 1);
416
+ this.updateChildrenLevels(node, parentLevel + 1);
417
+ }
418
+ /**
419
+ * 递归更新所有子节点的层级
420
+ * @param parent 父节点
421
+ * @param parentLevel 父节点的层级
422
+ * @private
423
+ */
424
+ updateChildrenLevels(parent, parentLevel) {
425
+ const children = this.getChildren(parent);
426
+ for (const child of children) {
427
+ const childLevel = parentLevel + 1;
428
+ this._nodeLevels.set(child, childLevel);
429
+ this.updateChildrenLevels(child, childLevel);
430
+ }
431
+ }
432
+ /**
433
+ * 记录变更
434
+ * @param parent 父节点
435
+ * @param children 子节点数组
436
+ * @param type 变更类型
437
+ * @private
438
+ */
439
+ recordChange(parent, children, type) {
440
+ const change = {
441
+ parent,
442
+ children: [...children],
443
+ type,
444
+ timestamp: Date.now()
445
+ };
446
+ if (this._batchUpdateMode) {
447
+ this._pendingChanges.push(change);
448
+ } else {
449
+ this._changeHistory.push(change);
450
+ if (this._changeHistory.length > this._options.historyDepth) {
451
+ this._changeHistory.shift();
452
+ }
453
+ }
454
+ }
455
+ /**
456
+ * 更新版本号,用于通知外部关系发生了变化
457
+ * @private
458
+ */
459
+ updateVersion() {
460
+ if (this._batchUpdateMode) {
461
+ this._hasPendingChanges = true;
462
+ return;
463
+ }
464
+ this._version++;
465
+ this._versionSubject.next(this._version);
466
+ }
467
+ /**
468
+ * 开始批量更新操作
469
+ * 在此模式下,所有导致版本变更的操作将被延迟,直到调用commitBatch
470
+ */
471
+ beginBatch() {
472
+ this._batchUpdateMode = true;
473
+ this._hasPendingChanges = false;
474
+ this._pendingChanges = [];
475
+ }
476
+ /**
477
+ * 提交批量更新,如果有变更则更新版本
478
+ * @returns 是否有变更被提交
479
+ */
480
+ commitBatch() {
481
+ if (!this._batchUpdateMode) {
482
+ return false;
483
+ }
484
+ this._batchUpdateMode = false;
485
+ if (this._hasPendingChanges) {
486
+ for (const change of this._pendingChanges) {
487
+ this._changeHistory.push(change);
488
+ if (this._changeHistory.length > this._options.historyDepth) {
489
+ this._changeHistory.shift();
490
+ }
491
+ }
492
+ this._pendingChanges = [];
493
+ this._version++;
494
+ this._versionSubject.next(this._version);
495
+ this._hasPendingChanges = false;
496
+ if (this._needsLevelRecalculation) {
497
+ this.recalculateAllLevels();
498
+ }
499
+ return true;
500
+ }
501
+ return false;
502
+ }
503
+ /**
504
+ * 回滚批量更新,取消所有未提交的变更
505
+ * 注意:此方法不会撤销已执行的关系变更,只会阻止版本更新
506
+ */
507
+ rollbackBatch() {
508
+ this._batchUpdateMode = false;
509
+ this._hasPendingChanges = false;
510
+ this._pendingChanges = [];
511
+ }
512
+ /**
513
+ * 在批量模式中执行多个操作并自动提交
514
+ * @param operations 要执行的函数
515
+ * @returns 批量操作是否导致了版本变更
516
+ */
517
+ batch(operations) {
518
+ this.beginBatch();
519
+ try {
520
+ operations();
521
+ return this.commitBatch();
522
+ } catch (error) {
523
+ this.rollbackBatch();
524
+ throw error;
525
+ }
526
+ }
527
+ /**
528
+ * 添加父子关系
529
+ * @param parent 父节点
530
+ * @param child 子节点
531
+ */
532
+ add(parent, child) {
533
+ const hadParent = this.childToParent.has(child);
534
+ const oldParent = hadParent ? this.childToParent.get(child) : null;
535
+ const isNewRelation = !hadParent || oldParent !== parent;
536
+ if (!isNewRelation) {
537
+ return;
538
+ }
539
+ if (this.childToParent.has(child)) {
540
+ const oldParent2 = this.childToParent.get(child);
541
+ const children = this.parentToChildren.get(oldParent2);
542
+ if (children) {
543
+ children.delete(child);
544
+ if (children.size === 0 && !this._options.allowEmptyParent) {
545
+ this.parentToChildren.delete(oldParent2);
546
+ if (!this.childToParent.has(oldParent2)) {
547
+ this._nodeLevels.delete(oldParent2);
548
+ }
549
+ }
550
+ this.recordChange(oldParent2, [child], "remove" /* REMOVE */);
551
+ }
552
+ }
553
+ if (!this.parentToChildren.has(parent)) {
554
+ this.parentToChildren.set(parent, /* @__PURE__ */ new Set());
555
+ if (!this.childToParent.has(parent)) {
556
+ this._nodeLevels.set(parent, 1);
557
+ }
558
+ }
559
+ this.parentToChildren.get(parent).add(child);
560
+ this.childToParent.set(child, parent);
561
+ this.updateNodeLevel(child, parent);
562
+ this.recordChange(parent, [child], "add" /* ADD */);
563
+ this.updateVersion();
564
+ }
565
+ /**
566
+ * 移除子节点及其父关系
567
+ * @param child 子节点
568
+ * @returns 是否成功移除
569
+ */
570
+ removeChild(child) {
571
+ if (!this.childToParent.has(child)) {
572
+ return false;
573
+ }
574
+ const parent = this.childToParent.get(child);
575
+ const children = this.parentToChildren.get(parent);
576
+ if (children) {
577
+ children.delete(child);
578
+ if (children.size === 0 && !this._options.allowEmptyParent) {
579
+ this.parentToChildren.delete(parent);
580
+ }
581
+ }
582
+ this.childToParent.delete(child);
583
+ this._nodeLevels.delete(child);
584
+ if (this.parentToChildren.has(child)) {
585
+ this._needsLevelRecalculation = true;
586
+ }
587
+ this.recordChange(parent, [child], "remove" /* REMOVE */);
588
+ this.updateVersion();
589
+ return true;
590
+ }
591
+ /**
592
+ * 移除父节点及其所有子节点的关系
593
+ * @param parent 父节点
594
+ * @returns 是否成功移除
595
+ */
596
+ removeParent(parent) {
597
+ if (!this.parentToChildren.has(parent)) {
598
+ return false;
599
+ }
600
+ const children = this.parentToChildren.get(parent);
601
+ const childrenArray = Array.from(children);
602
+ for (const child of children) {
603
+ if (this.parentToChildren.has(child)) {
604
+ this._needsLevelRecalculation = true;
605
+ break;
606
+ }
607
+ }
608
+ children.forEach((child) => {
609
+ this.childToParent.delete(child);
610
+ this._nodeLevels.delete(child);
611
+ });
612
+ this.parentToChildren.delete(parent);
613
+ if (!this.childToParent.has(parent)) {
614
+ this._nodeLevels.delete(parent);
615
+ }
616
+ this.recordChange(parent, childrenArray, "remove" /* REMOVE */);
617
+ this.updateVersion();
618
+ return true;
619
+ }
620
+ /**
621
+ * 清空所有关系并清除历史记录
622
+ * @param clearHistory 是否清除历史记录,默认为true
623
+ */
624
+ clear(clearHistory = true) {
625
+ if (this.parentToChildren.size > 0 || this.childToParent.size > 0) {
626
+ if (!clearHistory) {
627
+ for (const [parent, children] of this.parentToChildren.entries()) {
628
+ this.recordChange(parent, Array.from(children), "remove" /* REMOVE */);
629
+ }
630
+ }
631
+ this.parentToChildren.clear();
632
+ this.childToParent.clear();
633
+ this._nodeLevels.clear();
634
+ this._needsLevelRecalculation = false;
635
+ if (clearHistory) {
636
+ this._changeHistory = [];
637
+ }
638
+ this.updateVersion();
639
+ }
640
+ }
641
+ /**
642
+ * 获取所有子节点
643
+ * @param parent 父节点
644
+ * @returns 子节点集合
645
+ */
646
+ getChildren(parent) {
647
+ return this.parentToChildren.get(parent) || /* @__PURE__ */ new Set();
648
+ }
649
+ /**
650
+ * 获取父节点
651
+ * @param child 子节点
652
+ * @returns 父节点,如果不存在则返回undefined
653
+ */
654
+ getParent(child) {
655
+ return this.childToParent.get(child);
656
+ }
657
+ /**
658
+ * 获取根节点
659
+ * @param node 子节点
660
+ * @returns 根节点,如果节点无父节点则返回该节点本身,如果检测到循环引用则返回null
661
+ */
662
+ getRootParent(node) {
663
+ if (!this.childToParent.has(node)) {
664
+ return node;
665
+ }
666
+ const visited = /* @__PURE__ */ new Set();
667
+ let current = node;
668
+ while (true) {
669
+ visited.add(current);
670
+ const parent = this.childToParent.get(current);
671
+ if (!parent) {
672
+ return current;
673
+ }
674
+ if (visited.has(parent)) {
675
+ return null;
676
+ }
677
+ current = parent;
678
+ }
679
+ }
680
+ /**
681
+ * 检查是否存在循环引用
682
+ * @returns 是否存在循环引用
683
+ */
684
+ hasCircularReference() {
685
+ for (const child of this.childToParent.keys()) {
686
+ const visited = /* @__PURE__ */ new Set();
687
+ let current = child;
688
+ while (true) {
689
+ visited.add(current);
690
+ const parent = this.childToParent.get(current);
691
+ if (!parent) {
692
+ break;
693
+ }
694
+ if (visited.has(parent)) {
695
+ return true;
696
+ }
697
+ current = parent;
698
+ }
699
+ }
700
+ return false;
701
+ }
702
+ /**
703
+ * 添加父子关系,但会检查是否会形成循环引用
704
+ * @param parent 父节点
705
+ * @param child 子节点
706
+ * @returns 是否成功添加关系(如果会形成循环引用则返回false)
707
+ */
708
+ addSafe(parent, child) {
709
+ if (parent === child) {
710
+ return false;
711
+ }
712
+ if (this.isAncestorOf(child, parent)) {
713
+ return false;
714
+ }
715
+ this.add(parent, child);
716
+ return true;
717
+ }
718
+ /**
719
+ * 检查节点A是否是节点B的祖先节点
720
+ * @param nodeA 可能的祖先节点
721
+ * @param nodeB 待检查节点
722
+ * @returns 是否是祖先关系
723
+ */
724
+ isAncestorOf(nodeA, nodeB) {
725
+ if (!this.parentToChildren.has(nodeB)) {
726
+ return false;
727
+ }
728
+ const queue = [nodeB];
729
+ const visited = /* @__PURE__ */ new Set();
730
+ while (queue.length > 0) {
731
+ const current = queue.shift();
732
+ visited.add(current);
733
+ const parent = this.getParent(current);
734
+ if (parent === nodeA) {
735
+ return true;
736
+ }
737
+ if (parent && !visited.has(parent)) {
738
+ queue.push(parent);
739
+ }
740
+ }
741
+ return false;
742
+ }
743
+ /**
744
+ * 获取所有父节点
745
+ * @returns 父节点集合
746
+ */
747
+ getAllParents() {
748
+ return new Set(this.parentToChildren.keys());
749
+ }
750
+ /**
751
+ * 获取所有子节点
752
+ * @returns 子节点集合
753
+ */
754
+ getAllChildren() {
755
+ return new Set(this.childToParent.keys());
756
+ }
757
+ /**
758
+ * 检查父子关系是否存在
759
+ * @param parent 父节点
760
+ * @param child 子节点
761
+ * @returns 是否存在关系
762
+ */
763
+ hasRelation(parent, child) {
764
+ const children = this.parentToChildren.get(parent);
765
+ return children ? children.has(child) : false;
766
+ }
767
+ /**
768
+ * 获取关系数量
769
+ * @returns 关系数量
770
+ */
771
+ size() {
772
+ return this.childToParent.size;
773
+ }
774
+ /**
775
+ * 获取指定节点的所有后代节点(包括子节点、孙节点等)
776
+ * @param parent 父节点
777
+ * @param includeSelf 是否包含自身,默认为false
778
+ * @returns 所有后代节点的集合
779
+ */
780
+ getDescendants(parent, includeSelf = false) {
781
+ const result = /* @__PURE__ */ new Set();
782
+ if (!this.parentToChildren.has(parent)) {
783
+ return result;
784
+ }
785
+ const queue = [parent];
786
+ const visitedParents = /* @__PURE__ */ new Set();
787
+ while (queue.length > 0) {
788
+ const current = queue.shift();
789
+ visitedParents.add(current);
790
+ const children = this.getChildren(current);
791
+ for (const child of children) {
792
+ result.add(child);
793
+ if (this.parentToChildren.has(child) && !visitedParents.has(child)) {
794
+ queue.push(child);
795
+ }
796
+ }
797
+ }
798
+ if (includeSelf) {
799
+ result.add(parent);
800
+ }
801
+ return result;
802
+ }
803
+ }
804
+
805
+ exports.ChangeType = ChangeType;
806
+ exports.DataManager = DataManager;
807
+ exports.DualRelation = DualRelation;