@flowgram.ai/history 0.1.0-alpha.10

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.js ADDED
@@ -0,0 +1,932 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __decorateClass = (decorators, target, key, kind) => {
20
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
21
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
22
+ if (decorator = decorators[i])
23
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24
+ if (kind && result) __defProp(target, key, result);
25
+ return result;
26
+ };
27
+
28
+ // src/index.ts
29
+ var src_exports = {};
30
+ __export(src_exports, {
31
+ HistoryConfig: () => HistoryConfig,
32
+ HistoryContainerModule: () => HistoryContainerModule,
33
+ HistoryContext: () => HistoryContext,
34
+ HistoryManager: () => HistoryManager,
35
+ HistoryMergeEventType: () => HistoryMergeEventType,
36
+ HistoryService: () => HistoryService,
37
+ HistoryStack: () => HistoryStack,
38
+ HistoryStackChangeType: () => HistoryStackChangeType,
39
+ OperationContribution: () => OperationContribution,
40
+ OperationRegistry: () => OperationRegistry,
41
+ OperationService: () => OperationService,
42
+ StackOperation: () => StackOperation,
43
+ UndoRedoChangeType: () => UndoRedoChangeType,
44
+ UndoRedoService: () => UndoRedoService,
45
+ createHistoryPlugin: () => createHistoryPlugin
46
+ });
47
+ module.exports = __toCommonJS(src_exports);
48
+
49
+ // src/operation/operation-contribution.ts
50
+ var OperationContribution = Symbol("OperationContribution");
51
+
52
+ // src/operation/operation-registry.ts
53
+ var import_inversify = require("inversify");
54
+ var import_utils = require("@flowgram.ai/utils");
55
+ var OperationRegistry = class {
56
+ constructor() {
57
+ this._operationMetas = /* @__PURE__ */ new Map();
58
+ this.contributions = [];
59
+ }
60
+ init() {
61
+ for (const contrib of this.contributions) {
62
+ contrib.registerOperationMeta?.(this);
63
+ }
64
+ }
65
+ /**
66
+ * 注册操作的元数据
67
+ * @param operationMeta 操作的元数据
68
+ * @returns 销毁函数
69
+ */
70
+ registerOperationMeta(operationMeta) {
71
+ if (this._operationMetas.has(operationMeta.type)) {
72
+ console.warn(`A operation meta ${operationMeta.type} is already registered.`);
73
+ return import_utils.Disposable.NULL;
74
+ }
75
+ const toDispose = new import_utils.DisposableCollection(this._doRegisterOperationMetaMeta(operationMeta));
76
+ return toDispose;
77
+ }
78
+ /**
79
+ * 获取操作的元数据
80
+ * @param type 操作类型
81
+ * @returns 操作的元数据
82
+ */
83
+ getOperationMeta(type) {
84
+ return this._operationMetas.get(type);
85
+ }
86
+ _doRegisterOperationMetaMeta(operationMeta) {
87
+ this._operationMetas.set(operationMeta.type, operationMeta);
88
+ return {
89
+ dispose: () => {
90
+ this._operationMetas.delete(operationMeta.type);
91
+ }
92
+ };
93
+ }
94
+ };
95
+ __decorateClass([
96
+ (0, import_inversify.multiInject)(OperationContribution),
97
+ (0, import_inversify.optional)()
98
+ ], OperationRegistry.prototype, "contributions", 2);
99
+ __decorateClass([
100
+ (0, import_inversify.postConstruct)()
101
+ ], OperationRegistry.prototype, "init", 1);
102
+ OperationRegistry = __decorateClass([
103
+ (0, import_inversify.injectable)()
104
+ ], OperationRegistry);
105
+
106
+ // src/operation/operation-service.ts
107
+ var import_inversify4 = require("inversify");
108
+ var import_utils2 = require("@flowgram.ai/utils");
109
+
110
+ // src/history-context.ts
111
+ var import_inversify2 = require("inversify");
112
+ var HistoryContext = class {
113
+ };
114
+ HistoryContext = __decorateClass([
115
+ (0, import_inversify2.injectable)()
116
+ ], HistoryContext);
117
+
118
+ // src/history-config.ts
119
+ var import_nanoid = require("nanoid");
120
+ var import_inversify3 = require("inversify");
121
+ var HistoryConfig = class {
122
+ constructor() {
123
+ this.generateId = () => (0, import_nanoid.nanoid)();
124
+ this.getSnapshot = () => "";
125
+ }
126
+ };
127
+ HistoryConfig = __decorateClass([
128
+ (0, import_inversify3.injectable)()
129
+ ], HistoryConfig);
130
+
131
+ // src/operation/operation-service.ts
132
+ var OperationService = class {
133
+ constructor() {
134
+ this.applyEmitter = new import_utils2.Emitter();
135
+ this.onApply = this.applyEmitter.event;
136
+ this._toDispose = new import_utils2.DisposableCollection();
137
+ }
138
+ init() {
139
+ this._toDispose.push(this.applyEmitter);
140
+ }
141
+ /**
142
+ * 执行操作
143
+ * @param op
144
+ * @returns
145
+ */
146
+ applyOperation(op, options) {
147
+ const meta = this.operationRegistry.getOperationMeta(op.type);
148
+ if (!meta) {
149
+ throw new Error(`Operation meta ${op.type} has not registered.`);
150
+ }
151
+ let res;
152
+ if (!options?.noApply) {
153
+ res = meta.apply(op, this.context.source);
154
+ }
155
+ this.applyEmitter.fire(op);
156
+ return res;
157
+ }
158
+ /**
159
+ * 根据操作类型获取操作的label
160
+ * @param operation 操作
161
+ * @returns
162
+ */
163
+ getOperationLabel(operation) {
164
+ const operationMeta = this.operationRegistry.getOperationMeta(operation.type);
165
+ if (operationMeta && operationMeta.getLabel) {
166
+ return operationMeta.getLabel(operation, this.context.source);
167
+ }
168
+ }
169
+ /**
170
+ * 根据操作类型获取操作的description
171
+ * @param operation 操作
172
+ * @returns
173
+ */
174
+ getOperationDescription(operation) {
175
+ const operationMeta = this.operationRegistry.getOperationMeta(operation.type);
176
+ if (operationMeta && operationMeta.getDescription) {
177
+ return operationMeta.getDescription(operation, this.context.source);
178
+ }
179
+ }
180
+ /**
181
+ * 操作取反
182
+ * @param operations
183
+ * @returns
184
+ */
185
+ inverseOperations(operations) {
186
+ return operations.map((op) => this.inverseOperation(op)).reverse();
187
+ }
188
+ inverseOperation(op) {
189
+ const meta = this.operationRegistry.getOperationMeta(op.type);
190
+ if (!meta) {
191
+ throw new Error(`Operation meta ${op.type} has not registered.`);
192
+ }
193
+ return meta.inverse(op);
194
+ }
195
+ dispose() {
196
+ this._toDispose.dispose();
197
+ }
198
+ };
199
+ __decorateClass([
200
+ (0, import_inversify4.inject)(OperationRegistry)
201
+ ], OperationService.prototype, "operationRegistry", 2);
202
+ __decorateClass([
203
+ (0, import_inversify4.inject)(HistoryContext)
204
+ ], OperationService.prototype, "context", 2);
205
+ __decorateClass([
206
+ (0, import_inversify4.inject)(HistoryConfig)
207
+ ], OperationService.prototype, "config", 2);
208
+ __decorateClass([
209
+ (0, import_inversify4.postConstruct)()
210
+ ], OperationService.prototype, "init", 1);
211
+ OperationService = __decorateClass([
212
+ (0, import_inversify4.injectable)()
213
+ ], OperationService);
214
+
215
+ // src/history/undo-redo-service.ts
216
+ var import_inversify5 = require("inversify");
217
+ var import_utils3 = require("@flowgram.ai/utils");
218
+
219
+ // src/history/types.ts
220
+ var UndoRedoChangeType = /* @__PURE__ */ ((UndoRedoChangeType2) => {
221
+ UndoRedoChangeType2["UNDO"] = "undo";
222
+ UndoRedoChangeType2["REDO"] = "redo";
223
+ UndoRedoChangeType2["PUSH"] = "push";
224
+ UndoRedoChangeType2["CLEAR"] = "clear";
225
+ return UndoRedoChangeType2;
226
+ })(UndoRedoChangeType || {});
227
+ var HistoryStackChangeType = /* @__PURE__ */ ((HistoryStackChangeType2) => {
228
+ HistoryStackChangeType2["ADD"] = "add";
229
+ HistoryStackChangeType2["UPDATE"] = "update";
230
+ HistoryStackChangeType2["CLEAR"] = "clear";
231
+ HistoryStackChangeType2["ADD_OPERATION"] = "add_operation";
232
+ HistoryStackChangeType2["UPDATE_OPERATION"] = "update_operation";
233
+ return HistoryStackChangeType2;
234
+ })(HistoryStackChangeType || {});
235
+ var HistoryMergeEventType = /* @__PURE__ */ ((HistoryMergeEventType2) => {
236
+ HistoryMergeEventType2["ADD"] = "ADD";
237
+ HistoryMergeEventType2["UPDATE"] = "UPDATE";
238
+ return HistoryMergeEventType2;
239
+ })(HistoryMergeEventType || {});
240
+
241
+ // src/history/undo-redo-service.ts
242
+ var UndoRedoService = class {
243
+ constructor() {
244
+ this._undoing = false;
245
+ this._redoing = false;
246
+ this._limit = 100;
247
+ this.onChangeEmitter = new import_utils3.Emitter();
248
+ this.onChange = this.onChangeEmitter.event;
249
+ this._toDispose = new import_utils3.DisposableCollection();
250
+ this._undoStack = [];
251
+ this._redoStack = [];
252
+ this._toDispose.push(this.onChangeEmitter);
253
+ }
254
+ setLimit(limit) {
255
+ this._limit = limit;
256
+ }
257
+ pushElement(element) {
258
+ this._redoStack = [];
259
+ this._stackPush(this._undoStack, element);
260
+ this._toDispose.push(element);
261
+ this._emitChange("push" /* PUSH */, element);
262
+ }
263
+ getUndoStack() {
264
+ return this._undoStack;
265
+ }
266
+ getRedoStack() {
267
+ return this._redoStack;
268
+ }
269
+ getLastElement() {
270
+ return this._undoStack[this._undoStack.length - 1];
271
+ }
272
+ /**
273
+ * 执行undo
274
+ * @returns void
275
+ */
276
+ async undo() {
277
+ if (!this.canUndo()) {
278
+ return;
279
+ }
280
+ if (this._undoing) {
281
+ return;
282
+ }
283
+ this._undoing = true;
284
+ const item = this._undoStack.pop();
285
+ try {
286
+ await item.undo();
287
+ } finally {
288
+ this._stackPush(this._redoStack, item);
289
+ this._emitChange("undo" /* UNDO */, item);
290
+ this._undoing = false;
291
+ }
292
+ }
293
+ /**
294
+ * 执行redo
295
+ * @returns void
296
+ */
297
+ async redo() {
298
+ if (!this.canRedo()) {
299
+ return;
300
+ }
301
+ if (this._redoing) {
302
+ return;
303
+ }
304
+ this._redoing = true;
305
+ const item = this._redoStack.pop();
306
+ try {
307
+ await item.redo();
308
+ } finally {
309
+ this._stackPush(this._undoStack, item);
310
+ this._emitChange("redo" /* REDO */, item);
311
+ this._redoing = false;
312
+ }
313
+ }
314
+ /**
315
+ * 是否可undo
316
+ * @returns true代表可以,false代表不可以
317
+ */
318
+ canUndo() {
319
+ return this._undoStack.length > 0;
320
+ }
321
+ /**
322
+ * 是否可redo
323
+ * @returns true代表可以,false代表不可以
324
+ */
325
+ canRedo() {
326
+ return this._redoStack.length > 0;
327
+ }
328
+ /**
329
+ * 是否可以push
330
+ * @returns true代表可以,false代表不可以
331
+ */
332
+ canPush() {
333
+ return !this._redoing && !this._undoing;
334
+ }
335
+ /**
336
+ * 清空
337
+ */
338
+ clear() {
339
+ this.clearRedoStack();
340
+ this.clearUndoStack();
341
+ this._emitChange("clear" /* CLEAR */);
342
+ }
343
+ /**
344
+ * 清空redo栈
345
+ */
346
+ clearRedoStack() {
347
+ this._redoStack.forEach((element) => {
348
+ element.dispose();
349
+ });
350
+ this._redoStack = [];
351
+ }
352
+ /**
353
+ * 清空undo栈
354
+ */
355
+ clearUndoStack() {
356
+ this._undoStack.forEach((element) => {
357
+ element.dispose();
358
+ });
359
+ this._undoStack = [];
360
+ }
361
+ /**
362
+ * 销毁
363
+ */
364
+ dispose() {
365
+ this.clear();
366
+ this._toDispose.dispose();
367
+ }
368
+ _stackPush(stack, element) {
369
+ stack.push(element);
370
+ if (stack.length > this._limit) {
371
+ stack.shift();
372
+ }
373
+ }
374
+ _emitChange(type, element) {
375
+ if (element) {
376
+ this.onChangeEmitter.fire({ type, element });
377
+ } else {
378
+ this.onChangeEmitter.fire({ type });
379
+ }
380
+ }
381
+ };
382
+ UndoRedoService = __decorateClass([
383
+ (0, import_inversify5.injectable)()
384
+ ], UndoRedoService);
385
+
386
+ // src/history/history-service.ts
387
+ var import_lodash3 = require("lodash");
388
+ var import_inversify8 = require("inversify");
389
+ var import_utils7 = require("@flowgram.ai/utils");
390
+
391
+ // src/history/stack-operation.ts
392
+ var import_lodash = require("lodash");
393
+ var import_utils4 = require("@flowgram.ai/utils");
394
+ var StackOperation = class {
395
+ constructor(operationService, operations = []) {
396
+ this._toDispose = new import_utils4.DisposableCollection();
397
+ this._timestamp = Date.now();
398
+ this._operationService = operationService;
399
+ this._operations = operations.map((op) => this._operation(op));
400
+ this._id = operationService.config.generateId();
401
+ }
402
+ get id() {
403
+ return this._id;
404
+ }
405
+ getTimestamp() {
406
+ return this._timestamp;
407
+ }
408
+ pushOperation(operation) {
409
+ const op = this._operation(operation);
410
+ this._operations.push(op);
411
+ return op;
412
+ }
413
+ getOperations() {
414
+ return this._operations;
415
+ }
416
+ getChangeOperations(type) {
417
+ if (type === "undo" /* UNDO */) {
418
+ return this._operationService.inverseOperations(this._operations);
419
+ }
420
+ return this._operations;
421
+ }
422
+ getFirstOperation() {
423
+ return this._operations[0];
424
+ }
425
+ getLastOperation() {
426
+ return this._operations[this._operations.length - 1];
427
+ }
428
+ async undo() {
429
+ const inverseOps = this._operationService.inverseOperations(this._operations);
430
+ for (const op of inverseOps) {
431
+ await this._apply(op);
432
+ }
433
+ }
434
+ async redo() {
435
+ for (const op of this._operations) {
436
+ await this._apply(op);
437
+ }
438
+ }
439
+ revert(type) {
440
+ let operations = this._operations;
441
+ if (type !== "undo" /* UNDO */) {
442
+ operations = this._operations.map((op) => this._inverse(op)).reverse();
443
+ }
444
+ for (const op of operations) {
445
+ this._apply(op);
446
+ }
447
+ }
448
+ _inverse(op) {
449
+ return this._operationService.inverseOperation(op);
450
+ }
451
+ async _apply(op) {
452
+ await this._operationService.applyOperation(op);
453
+ }
454
+ _operation(op) {
455
+ return {
456
+ ...op,
457
+ value: (0, import_lodash.cloneDeep)(op.value),
458
+ id: this._operationService.config.generateId()
459
+ };
460
+ }
461
+ dispose() {
462
+ this._toDispose.dispose();
463
+ }
464
+ };
465
+
466
+ // src/history/history-manager.ts
467
+ var import_inversify7 = require("inversify");
468
+ var import_utils6 = require("@flowgram.ai/utils");
469
+
470
+ // src/history/history-stack.ts
471
+ var import_lodash2 = require("lodash");
472
+ var import_inversify6 = require("inversify");
473
+ var import_utils5 = require("@flowgram.ai/utils");
474
+ var HistoryStack = class {
475
+ constructor() {
476
+ this._items = [];
477
+ this.onChangeEmitter = new import_utils5.Emitter();
478
+ this.onChange = this.onChangeEmitter.event;
479
+ this._toDispose = new import_utils5.DisposableCollection();
480
+ this.limit = 100;
481
+ this._toDispose.push(this.onChangeEmitter);
482
+ }
483
+ get items() {
484
+ return this._items;
485
+ }
486
+ add(service, item) {
487
+ const historyItem = this._getHistoryItem(service, item);
488
+ this._items.unshift(historyItem);
489
+ if (this._items.length > this.limit) {
490
+ this._items.pop();
491
+ }
492
+ this.onChangeEmitter.fire({
493
+ type: "add" /* ADD */,
494
+ value: historyItem,
495
+ service
496
+ });
497
+ return historyItem;
498
+ }
499
+ findById(id) {
500
+ return this._items.find((item) => item.id === id);
501
+ }
502
+ changeByIndex(index, service, item) {
503
+ const historyItem = this._getHistoryItem(service, item);
504
+ this._items[index] = historyItem;
505
+ this.onChangeEmitter.fire({
506
+ type: "update" /* UPDATE */,
507
+ value: historyItem,
508
+ service
509
+ });
510
+ }
511
+ addOperation(service, id, op) {
512
+ const historyItem = this._items.find((item) => item.id === id);
513
+ if (!historyItem) {
514
+ console.warn("no history item found");
515
+ return;
516
+ }
517
+ const newOperatopn = this._getHistoryOperation(service, op);
518
+ historyItem.operations.push(newOperatopn);
519
+ this.onChangeEmitter.fire({
520
+ type: "add_operation" /* ADD_OPERATION */,
521
+ value: {
522
+ historyItem,
523
+ operation: newOperatopn
524
+ },
525
+ service
526
+ });
527
+ }
528
+ updateOperation(service, id, op) {
529
+ const historyItem = this._items.find((item) => item.id === id);
530
+ if (!historyItem) {
531
+ console.warn("no history item found");
532
+ return;
533
+ }
534
+ const index = historyItem.operations.findIndex((op2) => op2.id === op2.id);
535
+ if (index < 0) {
536
+ console.warn("no operation found");
537
+ return;
538
+ }
539
+ const newOperatopn = this._getHistoryOperation(service, op);
540
+ historyItem.operations.splice(index, 1, newOperatopn);
541
+ this.onChangeEmitter.fire({
542
+ type: "update_operation" /* UPDATE_OPERATION */,
543
+ value: {
544
+ historyItem,
545
+ operation: newOperatopn
546
+ },
547
+ service
548
+ });
549
+ }
550
+ clear() {
551
+ this._items = [];
552
+ }
553
+ dispose() {
554
+ this._items = [];
555
+ this._toDispose.dispose();
556
+ }
557
+ _getHistoryItem(service, item) {
558
+ return {
559
+ ...item,
560
+ uri: service.context.uri,
561
+ time: HistoryStack.dateFormat(item.timestamp),
562
+ operations: item.operations.map(
563
+ (op) => this._getHistoryOperation(service, op, item.type !== "push" /* PUSH */)
564
+ )
565
+ };
566
+ }
567
+ _getHistoryOperation(service, op, generateId = false) {
568
+ let id;
569
+ if (generateId) {
570
+ id = this.historyConfig.generateId();
571
+ } else {
572
+ const oldId = op.id;
573
+ if (!oldId) {
574
+ throw new Error("no operation id found");
575
+ }
576
+ id = oldId;
577
+ }
578
+ return {
579
+ ...(0, import_lodash2.cloneDeep)(op),
580
+ id,
581
+ label: service.operationService.getOperationLabel(op),
582
+ description: service.operationService.getOperationDescription(op),
583
+ timestamp: Date.now()
584
+ };
585
+ }
586
+ static dateFormat(timestamp) {
587
+ return new Date(timestamp).toLocaleString();
588
+ }
589
+ };
590
+ __decorateClass([
591
+ (0, import_inversify6.inject)(HistoryConfig)
592
+ ], HistoryStack.prototype, "historyConfig", 2);
593
+ HistoryStack = __decorateClass([
594
+ (0, import_inversify6.injectable)()
595
+ ], HistoryStack);
596
+
597
+ // src/history/history-manager.ts
598
+ var HistoryManager = class {
599
+ constructor() {
600
+ this._historyServices = /* @__PURE__ */ new Map();
601
+ this._toDispose = new import_utils6.DisposableCollection();
602
+ }
603
+ registerHistoryService(service) {
604
+ const toDispose = new import_utils6.DisposableCollection();
605
+ toDispose.pushAll([
606
+ service.undoRedoService.onChange((event) => {
607
+ if (event.type === "clear" /* CLEAR */) {
608
+ return;
609
+ }
610
+ const { type, element } = event;
611
+ const operations = element.getChangeOperations(type);
612
+ const historyStackItem = {
613
+ id: type === "push" /* PUSH */ ? element.id : this.historyConfig.generateId(),
614
+ type,
615
+ uri: service.context.uri,
616
+ operations,
617
+ timestamp: Date.now()
618
+ };
619
+ this.historyStack.add(service, historyStackItem);
620
+ }),
621
+ service.onMerge((event) => {
622
+ this._handleMerge(service, event);
623
+ })
624
+ ]);
625
+ this._historyServices.set(service, toDispose);
626
+ this._toDispose.push(
627
+ service.onWillDispose(() => {
628
+ this.unregisterHistoryService(service);
629
+ })
630
+ );
631
+ }
632
+ unregisterHistoryService(service) {
633
+ const disposable = this._historyServices.get(service);
634
+ if (!disposable) {
635
+ return;
636
+ }
637
+ disposable.dispose();
638
+ this._historyServices.delete(service);
639
+ }
640
+ getHistoryServiceByURI(uri) {
641
+ for (const service of this._historyServices.keys()) {
642
+ if (service.context.uri === uri) {
643
+ return service;
644
+ }
645
+ }
646
+ }
647
+ getFirstHistoryService() {
648
+ for (const service of this._historyServices.keys()) {
649
+ return service;
650
+ }
651
+ }
652
+ dispose() {
653
+ this._toDispose.dispose();
654
+ this.historyStack.dispose();
655
+ this._historyServices.forEach((service) => service.dispose());
656
+ this._historyServices.clear();
657
+ }
658
+ _handleMerge(service, event) {
659
+ const { element, operation } = event.value;
660
+ const find = this.historyStack.findById(element.id);
661
+ if (!find) {
662
+ return;
663
+ }
664
+ if (!operation.id) {
665
+ console.warn("no operation id found");
666
+ return;
667
+ }
668
+ if (event.type === "UPDATE" /* UPDATE */) {
669
+ this.historyStack.updateOperation(
670
+ service,
671
+ element.id,
672
+ operation
673
+ );
674
+ }
675
+ if (event.type === "ADD" /* ADD */) {
676
+ this.historyStack.addOperation(
677
+ service,
678
+ element.id,
679
+ operation
680
+ );
681
+ }
682
+ }
683
+ };
684
+ __decorateClass([
685
+ (0, import_inversify7.inject)(HistoryStack)
686
+ ], HistoryManager.prototype, "historyStack", 2);
687
+ __decorateClass([
688
+ (0, import_inversify7.inject)(HistoryConfig)
689
+ ], HistoryManager.prototype, "historyConfig", 2);
690
+ HistoryManager = __decorateClass([
691
+ (0, import_inversify7.injectable)()
692
+ ], HistoryManager);
693
+
694
+ // src/history/history-service.ts
695
+ var HistoryService = class {
696
+ constructor() {
697
+ this._toDispose = new import_utils7.DisposableCollection();
698
+ this._transacting = false;
699
+ this._transactOperation = null;
700
+ this._locked = false;
701
+ this._willDisposeEmitter = new import_utils7.Emitter();
702
+ this._mergeEmitter = new import_utils7.Emitter();
703
+ this.onWillDispose = this._willDisposeEmitter.event;
704
+ this.onMerge = this._mergeEmitter.event;
705
+ }
706
+ get onApply() {
707
+ return this.operationService.onApply;
708
+ }
709
+ init() {
710
+ this._toDispose.push(this._willDisposeEmitter);
711
+ this._toDispose.push(this._mergeEmitter);
712
+ }
713
+ start() {
714
+ this._locked = false;
715
+ }
716
+ stop() {
717
+ this._locked = true;
718
+ }
719
+ limit(num) {
720
+ this.undoRedoService.setLimit(num);
721
+ }
722
+ startTransaction() {
723
+ if (this._transacting) {
724
+ return;
725
+ }
726
+ this._transacting = true;
727
+ const stackOperation = new StackOperation(this.operationService, []);
728
+ this._transactOperation = stackOperation;
729
+ }
730
+ endTransaction() {
731
+ const stackOperation = this._transactOperation;
732
+ if (!stackOperation) {
733
+ return;
734
+ }
735
+ if (stackOperation.getOperations().length !== 0) {
736
+ this._pushStackOperation(stackOperation);
737
+ }
738
+ this._transactOperation = null;
739
+ this._transacting = false;
740
+ }
741
+ transact(transaction) {
742
+ if (this._transacting) {
743
+ return;
744
+ }
745
+ this.startTransaction();
746
+ transaction();
747
+ this.endTransaction();
748
+ }
749
+ pushOperation(operation, options) {
750
+ if (!this._canPush()) {
751
+ return;
752
+ }
753
+ const prev = this._transactOperation || this.undoRedoService.getLastElement();
754
+ const operationMeta = this.operationRegistry.getOperationMeta(operation.type);
755
+ if (!operationMeta) {
756
+ throw new Error(`Operation meta ${operation.type} has not registered.`);
757
+ }
758
+ if (operationMeta.shouldSave && !operationMeta.shouldSave(operation)) {
759
+ return operationMeta.apply(operation, this.context.source);
760
+ }
761
+ const res = this.operationService.applyOperation(operation, { noApply: options?.noApply });
762
+ if (operationMeta.getURI && !operation.uri) {
763
+ operation.uri = operationMeta.getURI(operation, this.context.source);
764
+ }
765
+ const shouldMerge = this._shouldMerge(operation, prev, operationMeta);
766
+ if (shouldMerge) {
767
+ if (typeof shouldMerge === "object") {
768
+ const operation2 = prev.getLastOperation();
769
+ operation2.value = shouldMerge.value;
770
+ this._mergeEmitter.fire({
771
+ type: "UPDATE" /* UPDATE */,
772
+ value: {
773
+ element: prev,
774
+ operation: operation2,
775
+ value: shouldMerge.value
776
+ }
777
+ });
778
+ } else {
779
+ const op = prev.pushOperation(operation);
780
+ this._mergeEmitter.fire({
781
+ type: "ADD" /* ADD */,
782
+ value: {
783
+ element: prev,
784
+ operation: op
785
+ }
786
+ });
787
+ }
788
+ } else {
789
+ const stackOperation = new StackOperation(this.operationService, [operation]);
790
+ this._pushStackOperation(stackOperation);
791
+ }
792
+ return res;
793
+ }
794
+ getHistoryOperations() {
795
+ return this.historyManager.historyStack.items.reverse().map(
796
+ (item) => item.operations.map((o) => ({
797
+ ...(0, import_lodash3.pick)(o, ["type", "value"]),
798
+ label: o.label || o.type
799
+ }))
800
+ ).flat();
801
+ }
802
+ async undo() {
803
+ await this.undoRedoService.undo();
804
+ }
805
+ async redo() {
806
+ await this.undoRedoService.redo();
807
+ }
808
+ canUndo() {
809
+ return this.undoRedoService.canUndo();
810
+ }
811
+ canRedo() {
812
+ return this.undoRedoService.canRedo();
813
+ }
814
+ getSnapshot() {
815
+ return this.config.getSnapshot();
816
+ }
817
+ getRecords() {
818
+ throw new Error("Method not implemented.");
819
+ }
820
+ restore(historyRecord) {
821
+ throw new Error("Method not implemented.");
822
+ }
823
+ clear() {
824
+ this.undoRedoService.clear();
825
+ }
826
+ dispose() {
827
+ this._willDisposeEmitter.fire(this);
828
+ this._toDispose.dispose();
829
+ }
830
+ _canPush() {
831
+ if (this._locked) {
832
+ return false;
833
+ }
834
+ return this.undoRedoService.canPush();
835
+ }
836
+ _pushStackOperation(stackOperation) {
837
+ this.undoRedoService.pushElement(stackOperation);
838
+ this.undoRedoService.clearRedoStack();
839
+ }
840
+ _shouldMerge(operation, prev, operationMeta) {
841
+ if (!prev) {
842
+ return false;
843
+ }
844
+ if (this._transacting) {
845
+ return true;
846
+ }
847
+ return operationMeta.shouldMerge && operationMeta.shouldMerge(operation, prev.getLastOperation(), prev);
848
+ }
849
+ };
850
+ __decorateClass([
851
+ (0, import_inversify8.inject)(UndoRedoService)
852
+ ], HistoryService.prototype, "undoRedoService", 2);
853
+ __decorateClass([
854
+ (0, import_inversify8.inject)(OperationRegistry)
855
+ ], HistoryService.prototype, "operationRegistry", 2);
856
+ __decorateClass([
857
+ (0, import_inversify8.inject)(OperationService)
858
+ ], HistoryService.prototype, "operationService", 2);
859
+ __decorateClass([
860
+ (0, import_inversify8.inject)(HistoryContext)
861
+ ], HistoryService.prototype, "context", 2);
862
+ __decorateClass([
863
+ (0, import_inversify8.inject)(HistoryConfig)
864
+ ], HistoryService.prototype, "config", 2);
865
+ __decorateClass([
866
+ (0, import_inversify8.inject)(HistoryManager)
867
+ ], HistoryService.prototype, "historyManager", 2);
868
+ __decorateClass([
869
+ (0, import_inversify8.postConstruct)()
870
+ ], HistoryService.prototype, "init", 1);
871
+ HistoryService = __decorateClass([
872
+ (0, import_inversify8.injectable)()
873
+ ], HistoryService);
874
+
875
+ // src/history-container-module.ts
876
+ var import_inversify9 = require("inversify");
877
+ var HistoryContainerModule = new import_inversify9.ContainerModule(
878
+ (bind, _unbind, _isBound, _rebind, _unbindAsync, onActivation, _onDeactivation) => {
879
+ bind(OperationRegistry).toSelf().inSingletonScope();
880
+ bind(OperationService).toSelf().inSingletonScope();
881
+ bind(UndoRedoService).toSelf().inSingletonScope();
882
+ bind(HistoryService).toSelf().inSingletonScope();
883
+ bind(HistoryContext).toSelf().inSingletonScope();
884
+ bind(HistoryManager).toSelf().inSingletonScope();
885
+ bind(HistoryStack).toSelf().inSingletonScope();
886
+ bind(HistoryConfig).toSelf().inSingletonScope();
887
+ onActivation(HistoryService, (ctx, historyService) => {
888
+ let historyManager;
889
+ if (ctx.container?.parent?.isBound(HistoryManager)) {
890
+ historyManager = ctx.container?.parent?.get(HistoryManager);
891
+ } else {
892
+ historyManager = ctx.container.get(HistoryManager);
893
+ }
894
+ if (!historyManager) {
895
+ return historyService;
896
+ }
897
+ historyService.historyManager = historyManager;
898
+ historyManager.registerHistoryService(historyService);
899
+ return historyService;
900
+ });
901
+ }
902
+ );
903
+
904
+ // src/create-history-plugin.ts
905
+ var import_core = require("@flowgram.ai/core");
906
+ var createHistoryPlugin = (0, import_core.definePluginCreator)({
907
+ onInit: (ctx, opts) => {
908
+ if (opts.onApply) {
909
+ ctx.get(OperationService).onApply(opts.onApply.bind(null, ctx));
910
+ }
911
+ },
912
+ containerModules: [HistoryContainerModule]
913
+ });
914
+ // Annotate the CommonJS export names for ESM import in node:
915
+ 0 && (module.exports = {
916
+ HistoryConfig,
917
+ HistoryContainerModule,
918
+ HistoryContext,
919
+ HistoryManager,
920
+ HistoryMergeEventType,
921
+ HistoryService,
922
+ HistoryStack,
923
+ HistoryStackChangeType,
924
+ OperationContribution,
925
+ OperationRegistry,
926
+ OperationService,
927
+ StackOperation,
928
+ UndoRedoChangeType,
929
+ UndoRedoService,
930
+ createHistoryPlugin
931
+ });
932
+ //# sourceMappingURL=index.js.map