@katn30/trakr 2.2.1 → 4.0.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.
- package/README.md +294 -0
- package/dist/dev/index.cjs +764 -6
- package/dist/dev/index.cjs.map +1 -1
- package/dist/dev/index.d.cts +92 -1
- package/dist/dev/index.d.ts +92 -1
- package/dist/dev/index.js +756 -5
- package/dist/dev/index.js.map +1 -1
- package/dist/prod/index.cjs +764 -6
- package/dist/prod/index.cjs.map +1 -1
- package/dist/prod/index.js +756 -5
- package/dist/prod/index.js.map +1 -1
- package/package.json +1 -1
package/dist/dev/index.cjs
CHANGED
|
@@ -21,6 +21,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AutoId: () => AutoId,
|
|
24
|
+
EventTracked: () => EventTracked,
|
|
25
|
+
EventTrackedCollection: () => EventTrackedCollection,
|
|
26
|
+
EventTracker: () => EventTracker,
|
|
27
|
+
Id: () => Id,
|
|
24
28
|
State: () => State,
|
|
25
29
|
Tracked: () => Tracked,
|
|
26
30
|
TrackedCollection: () => TrackedCollection,
|
|
@@ -28,7 +32,10 @@ __export(index_exports, {
|
|
|
28
32
|
TrackedObject: () => TrackedObject,
|
|
29
33
|
Tracker: () => Tracker,
|
|
30
34
|
TrackerSession: () => TrackerSession,
|
|
31
|
-
TypedEvent: () => TypedEvent
|
|
35
|
+
TypedEvent: () => TypedEvent,
|
|
36
|
+
getIdentity: () => getIdentity,
|
|
37
|
+
getIdentityObject: () => getIdentityObject,
|
|
38
|
+
getIdentityProperties: () => getIdentityProperties
|
|
32
39
|
});
|
|
33
40
|
module.exports = __toCommonJS(index_exports);
|
|
34
41
|
|
|
@@ -291,17 +298,73 @@ var OperationProperties = class {
|
|
|
291
298
|
|
|
292
299
|
// src/ExternallyAssigned.ts
|
|
293
300
|
var AUTO_ID = /* @__PURE__ */ Symbol("autoId");
|
|
301
|
+
var ID_PROPS = /* @__PURE__ */ Symbol("idProps");
|
|
294
302
|
function AutoId(_target, context) {
|
|
295
303
|
context.addInitializer(function() {
|
|
296
|
-
Object.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
304
|
+
const proto = Object.getPrototypeOf(this);
|
|
305
|
+
if (!Object.prototype.hasOwnProperty.call(proto, AUTO_ID)) {
|
|
306
|
+
Object.defineProperty(proto, AUTO_ID, {
|
|
307
|
+
value: String(context.name),
|
|
308
|
+
configurable: true
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
addIdentityProp(proto, String(context.name));
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function Id(_target, context) {
|
|
315
|
+
context.addInitializer(function() {
|
|
316
|
+
const proto = Object.getPrototypeOf(this);
|
|
317
|
+
addIdentityProp(proto, String(context.name));
|
|
300
318
|
});
|
|
301
319
|
}
|
|
320
|
+
function addIdentityProp(proto, propertyName) {
|
|
321
|
+
if (!Object.prototype.hasOwnProperty.call(proto, ID_PROPS)) {
|
|
322
|
+
Object.defineProperty(proto, ID_PROPS, {
|
|
323
|
+
value: [],
|
|
324
|
+
configurable: true,
|
|
325
|
+
writable: true
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
const list = proto[ID_PROPS];
|
|
329
|
+
if (!list.includes(propertyName)) list.push(propertyName);
|
|
330
|
+
}
|
|
302
331
|
function getAutoIdProperty(proto) {
|
|
303
332
|
return AUTO_ID in proto ? proto[AUTO_ID] : void 0;
|
|
304
333
|
}
|
|
334
|
+
function getIdentityProperties(proto) {
|
|
335
|
+
const chain = [];
|
|
336
|
+
let current = proto;
|
|
337
|
+
while (current) {
|
|
338
|
+
chain.push(current);
|
|
339
|
+
current = Object.getPrototypeOf(current);
|
|
340
|
+
}
|
|
341
|
+
const merged = [];
|
|
342
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
343
|
+
const proto2 = chain[i];
|
|
344
|
+
if (!Object.prototype.hasOwnProperty.call(proto2, ID_PROPS)) continue;
|
|
345
|
+
const list = proto2[ID_PROPS];
|
|
346
|
+
for (const name of list) {
|
|
347
|
+
if (!merged.includes(name)) merged.push(name);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return merged;
|
|
351
|
+
}
|
|
352
|
+
function getIdentity(obj) {
|
|
353
|
+
const props = getIdentityProperties(Object.getPrototypeOf(obj));
|
|
354
|
+
if (props.length === 0) return void 0;
|
|
355
|
+
if (props.length === 1) {
|
|
356
|
+
return obj[props[0]];
|
|
357
|
+
}
|
|
358
|
+
const result = {};
|
|
359
|
+
for (const p of props) result[p] = obj[p];
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
function getIdentityObject(obj) {
|
|
363
|
+
const props = getIdentityProperties(Object.getPrototypeOf(obj));
|
|
364
|
+
const result = {};
|
|
365
|
+
for (const p of props) result[p] = obj[p];
|
|
366
|
+
return result;
|
|
367
|
+
}
|
|
305
368
|
|
|
306
369
|
// src/TrackedObjectStateMachine.ts
|
|
307
370
|
function applyStateTransition(obj, event, direction, context) {
|
|
@@ -1362,9 +1425,701 @@ var TrackedCollectionChanged = class {
|
|
|
1362
1425
|
this.newCollection = newCollection;
|
|
1363
1426
|
}
|
|
1364
1427
|
};
|
|
1428
|
+
|
|
1429
|
+
// src/EventRegistry.ts
|
|
1430
|
+
var EVENT_METADATA = /* @__PURE__ */ Symbol("eventMetadata");
|
|
1431
|
+
var instanceState = /* @__PURE__ */ new WeakMap();
|
|
1432
|
+
var instanceHistory = /* @__PURE__ */ new WeakMap();
|
|
1433
|
+
var instanceHistoryTimes = /* @__PURE__ */ new WeakMap();
|
|
1434
|
+
var subscribedInstances = /* @__PURE__ */ new WeakSet();
|
|
1435
|
+
var itemOriginCollection = /* @__PURE__ */ new WeakMap();
|
|
1436
|
+
var DEFAULT_GROUP = "";
|
|
1437
|
+
function hasOwnEventMetadata(proto) {
|
|
1438
|
+
return Object.prototype.hasOwnProperty.call(proto, EVENT_METADATA);
|
|
1439
|
+
}
|
|
1440
|
+
function ownEventMetadata(proto) {
|
|
1441
|
+
return hasOwnEventMetadata(proto) ? proto[EVENT_METADATA] : void 0;
|
|
1442
|
+
}
|
|
1443
|
+
function registerEventProperty(proto, property, options) {
|
|
1444
|
+
if (!hasOwnEventMetadata(proto)) {
|
|
1445
|
+
Object.defineProperty(proto, EVENT_METADATA, {
|
|
1446
|
+
value: /* @__PURE__ */ new Map(),
|
|
1447
|
+
configurable: true
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
const map = proto[EVENT_METADATA];
|
|
1451
|
+
if (!map.has(property)) {
|
|
1452
|
+
map.set(property, options);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
function getEventMetadata(proto) {
|
|
1456
|
+
const chain = [];
|
|
1457
|
+
let current = proto;
|
|
1458
|
+
while (current) {
|
|
1459
|
+
chain.push(current);
|
|
1460
|
+
current = Object.getPrototypeOf(current);
|
|
1461
|
+
}
|
|
1462
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1463
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1464
|
+
const own = ownEventMetadata(chain[i]);
|
|
1465
|
+
if (!own) continue;
|
|
1466
|
+
own.forEach((options, property) => {
|
|
1467
|
+
if (!merged.has(property)) merged.set(property, options);
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
return merged;
|
|
1471
|
+
}
|
|
1472
|
+
var contextStacks = /* @__PURE__ */ new WeakMap();
|
|
1473
|
+
function pushContext(tracker, ctx) {
|
|
1474
|
+
let stack = contextStacks.get(tracker);
|
|
1475
|
+
if (!stack) {
|
|
1476
|
+
stack = [];
|
|
1477
|
+
contextStacks.set(tracker, stack);
|
|
1478
|
+
}
|
|
1479
|
+
stack.push(ctx);
|
|
1480
|
+
}
|
|
1481
|
+
function popContext(tracker) {
|
|
1482
|
+
const stack = contextStacks.get(tracker);
|
|
1483
|
+
if (stack && stack.length > 0) stack.pop();
|
|
1484
|
+
}
|
|
1485
|
+
function peekContext(tracker) {
|
|
1486
|
+
const stack = contextStacks.get(tracker);
|
|
1487
|
+
return stack && stack.length > 0 ? stack[stack.length - 1] : void 0;
|
|
1488
|
+
}
|
|
1489
|
+
function ensureEventStateSubscription(target) {
|
|
1490
|
+
if (subscribedInstances.has(target)) return;
|
|
1491
|
+
subscribedInstances.add(target);
|
|
1492
|
+
target.changed.subscribe((evt) => {
|
|
1493
|
+
const meta = getEventMetadata(Object.getPrototypeOf(target));
|
|
1494
|
+
const propMeta = meta.get(evt.property);
|
|
1495
|
+
if (!propMeta) return;
|
|
1496
|
+
if (propMeta.history) {
|
|
1497
|
+
appendHistoryEntry(
|
|
1498
|
+
target,
|
|
1499
|
+
evt.property,
|
|
1500
|
+
evt.newValue,
|
|
1501
|
+
evt.oldValue,
|
|
1502
|
+
propMeta.history,
|
|
1503
|
+
propMeta.coalesceWithin
|
|
1504
|
+
);
|
|
1505
|
+
} else {
|
|
1506
|
+
updateFinalValue(target, evt.property, evt.newValue, evt.oldValue);
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
function updateFinalValue(target, property, newValue, oldValue) {
|
|
1511
|
+
const state = getOrCreateEventState(target);
|
|
1512
|
+
let entry = state.get(property);
|
|
1513
|
+
if (!entry) {
|
|
1514
|
+
entry = { originalValue: oldValue, currentValue: newValue };
|
|
1515
|
+
state.set(property, entry);
|
|
1516
|
+
} else {
|
|
1517
|
+
entry.currentValue = newValue;
|
|
1518
|
+
}
|
|
1519
|
+
if (entry.currentValue === entry.originalValue) {
|
|
1520
|
+
state.delete(property);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
function appendHistoryEntry(target, property, newValue, oldValue, historyConfig, coalesceWithin) {
|
|
1524
|
+
const chains = getOrCreateHistoryState(target);
|
|
1525
|
+
let chain = chains.get(property);
|
|
1526
|
+
if (!chain) {
|
|
1527
|
+
chain = [];
|
|
1528
|
+
chains.set(property, chain);
|
|
1529
|
+
}
|
|
1530
|
+
const times = getOrCreateHistoryTimes(target);
|
|
1531
|
+
const now = Date.now();
|
|
1532
|
+
const lastTime = times.get(property);
|
|
1533
|
+
const shouldReplace = coalesceWithin !== void 0 && lastTime !== void 0 && now - lastTime < coalesceWithin && chain.length > 0;
|
|
1534
|
+
let entry;
|
|
1535
|
+
if (typeof historyConfig === "object" && historyConfig.entryFactory) {
|
|
1536
|
+
const ctx = peekContext(target.tracker);
|
|
1537
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1538
|
+
entry = historyConfig.entryFactory(target, newValue, oldValue, change, ctx);
|
|
1539
|
+
} else {
|
|
1540
|
+
entry = { property, value: newValue };
|
|
1541
|
+
}
|
|
1542
|
+
if (shouldReplace) {
|
|
1543
|
+
chain[chain.length - 1] = entry;
|
|
1544
|
+
} else {
|
|
1545
|
+
chain.push(entry);
|
|
1546
|
+
}
|
|
1547
|
+
times.set(property, now);
|
|
1548
|
+
}
|
|
1549
|
+
function getOrCreateHistoryTimes(target) {
|
|
1550
|
+
let times = instanceHistoryTimes.get(target);
|
|
1551
|
+
if (!times) {
|
|
1552
|
+
times = /* @__PURE__ */ new Map();
|
|
1553
|
+
instanceHistoryTimes.set(target, times);
|
|
1554
|
+
}
|
|
1555
|
+
return times;
|
|
1556
|
+
}
|
|
1557
|
+
function getOrCreateEventState(target) {
|
|
1558
|
+
let state = instanceState.get(target);
|
|
1559
|
+
if (!state) {
|
|
1560
|
+
state = /* @__PURE__ */ new Map();
|
|
1561
|
+
instanceState.set(target, state);
|
|
1562
|
+
}
|
|
1563
|
+
return state;
|
|
1564
|
+
}
|
|
1565
|
+
function getOrCreateHistoryState(target) {
|
|
1566
|
+
let state = instanceHistory.get(target);
|
|
1567
|
+
if (!state) {
|
|
1568
|
+
state = /* @__PURE__ */ new Map();
|
|
1569
|
+
instanceHistory.set(target, state);
|
|
1570
|
+
}
|
|
1571
|
+
return state;
|
|
1572
|
+
}
|
|
1573
|
+
function getEventState(target) {
|
|
1574
|
+
return instanceState.get(target) ?? /* @__PURE__ */ new Map();
|
|
1575
|
+
}
|
|
1576
|
+
function getHistoryState(target) {
|
|
1577
|
+
return instanceHistory.get(target) ?? /* @__PURE__ */ new Map();
|
|
1578
|
+
}
|
|
1579
|
+
function clearEventState(target) {
|
|
1580
|
+
instanceState.delete(target);
|
|
1581
|
+
instanceHistory.delete(target);
|
|
1582
|
+
instanceHistoryTimes.delete(target);
|
|
1583
|
+
}
|
|
1584
|
+
function recordItemOrigin(item, collection) {
|
|
1585
|
+
itemOriginCollection.set(item, collection);
|
|
1586
|
+
}
|
|
1587
|
+
function getItemOrigin(item) {
|
|
1588
|
+
return itemOriginCollection.get(item);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
// src/EventTrackedCollection.ts
|
|
1592
|
+
var EventTrackedCollection = class extends TrackedCollection {
|
|
1593
|
+
constructor(tracker, items, validator, options) {
|
|
1594
|
+
super(tracker, items, validator);
|
|
1595
|
+
this._historyOps = [];
|
|
1596
|
+
this._baselineItems = /* @__PURE__ */ new Set();
|
|
1597
|
+
this._eventOptions = options;
|
|
1598
|
+
for (const item of this.collection) {
|
|
1599
|
+
this._baselineItems.add(item);
|
|
1600
|
+
if (item instanceof TrackedObject) {
|
|
1601
|
+
recordItemOrigin(item, this);
|
|
1602
|
+
this._validateItemHasIdentity(item);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
this.changed.subscribe((evt) => {
|
|
1606
|
+
for (const item of evt.added) {
|
|
1607
|
+
if (item instanceof TrackedObject) {
|
|
1608
|
+
recordItemOrigin(item, this);
|
|
1609
|
+
this._validateItemHasIdentity(item);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
if (this._isAggregateMode() && !this.tracker._isReplaying) {
|
|
1613
|
+
for (const item of evt.added) {
|
|
1614
|
+
if (item instanceof TrackedObject) {
|
|
1615
|
+
this._recordAddOp(item);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
for (const item of evt.removed) {
|
|
1619
|
+
if (item instanceof TrackedObject) {
|
|
1620
|
+
this._recordRemoveOp(item);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
if (this._isHistoryMode()) {
|
|
1626
|
+
this._attachItemChangeWatchers();
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
/** @internal */
|
|
1630
|
+
get _lifecycleOptions() {
|
|
1631
|
+
if (!this._eventOptions) return void 0;
|
|
1632
|
+
if (this._isAggregateMode()) return void 0;
|
|
1633
|
+
return {
|
|
1634
|
+
itemAdded: this._eventOptions.itemAdded,
|
|
1635
|
+
itemRemoved: this._eventOptions.itemRemoved
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
/** @internal */
|
|
1639
|
+
get _aggregateOptions() {
|
|
1640
|
+
return this._isAggregateMode() ? this._eventOptions : void 0;
|
|
1641
|
+
}
|
|
1642
|
+
/** @internal */
|
|
1643
|
+
get _historyOpsList() {
|
|
1644
|
+
return this._historyOps;
|
|
1645
|
+
}
|
|
1646
|
+
/** @internal */
|
|
1647
|
+
_clearHistoryOps() {
|
|
1648
|
+
this._historyOps.length = 0;
|
|
1649
|
+
this._baselineItems.clear();
|
|
1650
|
+
for (const item of this.collection) this._baselineItems.add(item);
|
|
1651
|
+
}
|
|
1652
|
+
/** @internal */
|
|
1653
|
+
_isInBaseline(item) {
|
|
1654
|
+
return this._baselineItems.has(item);
|
|
1655
|
+
}
|
|
1656
|
+
/** @internal */
|
|
1657
|
+
_baselineListSnapshot() {
|
|
1658
|
+
return [...this._baselineItems];
|
|
1659
|
+
}
|
|
1660
|
+
/** @internal */
|
|
1661
|
+
_rebaseline() {
|
|
1662
|
+
this._baselineItems.clear();
|
|
1663
|
+
for (const item of this.collection) this._baselineItems.add(item);
|
|
1664
|
+
}
|
|
1665
|
+
_isAggregateMode() {
|
|
1666
|
+
if (!this._eventOptions) return false;
|
|
1667
|
+
return this._eventOptions.eventType !== void 0 || this._eventOptions.history !== void 0;
|
|
1668
|
+
}
|
|
1669
|
+
_isHistoryMode() {
|
|
1670
|
+
return !!this._eventOptions?.history;
|
|
1671
|
+
}
|
|
1672
|
+
_validateItemHasIdentity(item) {
|
|
1673
|
+
const props = getIdentityProperties(Object.getPrototypeOf(item));
|
|
1674
|
+
if (props.length === 0) {
|
|
1675
|
+
throw new Error(
|
|
1676
|
+
`EventTrackedCollection item type ${item.constructor.name} must declare at least one @Id or @AutoId property when used with eventType or history mode`
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
_attachItemChangeWatchers() {
|
|
1681
|
+
const watchItem = (item) => {
|
|
1682
|
+
item.changed.subscribe((_evt) => {
|
|
1683
|
+
if (this.tracker._isReplaying) return;
|
|
1684
|
+
if (!this.collection.includes(item)) return;
|
|
1685
|
+
this._recordChangeOp(item);
|
|
1686
|
+
});
|
|
1687
|
+
};
|
|
1688
|
+
for (const item of this.collection) {
|
|
1689
|
+
if (item instanceof TrackedObject) watchItem(item);
|
|
1690
|
+
}
|
|
1691
|
+
this.changed.subscribe((evt) => {
|
|
1692
|
+
for (const item of evt.added) {
|
|
1693
|
+
if (item instanceof TrackedObject) watchItem(item);
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
_recordAddOp(item) {
|
|
1698
|
+
const opts = this._eventOptions;
|
|
1699
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1700
|
+
const ctx = peekContext(this.tracker);
|
|
1701
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1702
|
+
this._historyOps.push({
|
|
1703
|
+
op: "add",
|
|
1704
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1705
|
+
});
|
|
1706
|
+
} else if (opts?.history === true) {
|
|
1707
|
+
this._historyOps.push({ op: "add", item, snapshot: snapshotItemAtRecordTime(item) });
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
_recordRemoveOp(item) {
|
|
1711
|
+
const opts = this._eventOptions;
|
|
1712
|
+
const identity = getIdentity(item);
|
|
1713
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1714
|
+
const ctx = peekContext(this.tracker);
|
|
1715
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1716
|
+
this._historyOps.push({
|
|
1717
|
+
op: "remove",
|
|
1718
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1719
|
+
});
|
|
1720
|
+
} else if (opts?.history === true) {
|
|
1721
|
+
this._historyOps.push({ op: "remove", identity });
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
_recordChangeOpDiff(item) {
|
|
1725
|
+
const proto = Object.getPrototypeOf(item);
|
|
1726
|
+
const idProps = getIdentityProperties(proto);
|
|
1727
|
+
const meta = getEventMetadata(proto);
|
|
1728
|
+
const rec = item;
|
|
1729
|
+
const diff = {};
|
|
1730
|
+
for (const [propName] of meta) {
|
|
1731
|
+
if (idProps.includes(propName)) continue;
|
|
1732
|
+
const v = rec[propName];
|
|
1733
|
+
diff[propName] = v === void 0 ? null : v;
|
|
1734
|
+
}
|
|
1735
|
+
return diff;
|
|
1736
|
+
}
|
|
1737
|
+
_recordChangeOp(item) {
|
|
1738
|
+
const opts = this._eventOptions;
|
|
1739
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1740
|
+
const ctx = peekContext(this.tracker);
|
|
1741
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1742
|
+
this._historyOps.push({
|
|
1743
|
+
op: "change",
|
|
1744
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1745
|
+
});
|
|
1746
|
+
} else if (opts?.history === true) {
|
|
1747
|
+
const identity = getIdentity(item);
|
|
1748
|
+
const diff = this._recordChangeOpDiff(item);
|
|
1749
|
+
this._historyOps.push({ op: "change", identity, item, diff });
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
};
|
|
1753
|
+
function snapshotItemAtRecordTime(item) {
|
|
1754
|
+
const proto = Object.getPrototypeOf(item);
|
|
1755
|
+
const meta = getEventMetadata(proto);
|
|
1756
|
+
const idProps = getIdentityProperties(proto);
|
|
1757
|
+
const autoIdProp = getAutoIdProperty(proto);
|
|
1758
|
+
const rec = item;
|
|
1759
|
+
const snap = {};
|
|
1760
|
+
for (const idProp of idProps) {
|
|
1761
|
+
if (idProp === autoIdProp) snap[idProp] = null;
|
|
1762
|
+
else snap[idProp] = rec[idProp];
|
|
1763
|
+
}
|
|
1764
|
+
for (const [propName] of meta) {
|
|
1765
|
+
if (idProps.includes(propName)) continue;
|
|
1766
|
+
const v = rec[propName];
|
|
1767
|
+
snap[propName] = v === void 0 ? null : v;
|
|
1768
|
+
}
|
|
1769
|
+
return snap;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
// src/EventTracker.ts
|
|
1773
|
+
var EventTracker = class extends Tracker {
|
|
1774
|
+
withContext(ctx, action) {
|
|
1775
|
+
pushContext(this, ctx);
|
|
1776
|
+
try {
|
|
1777
|
+
return action();
|
|
1778
|
+
} finally {
|
|
1779
|
+
popContext(this);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
onCommit(keys) {
|
|
1783
|
+
super.onCommit(keys);
|
|
1784
|
+
for (const obj of this.trackedObjects) {
|
|
1785
|
+
clearEventState(obj);
|
|
1786
|
+
}
|
|
1787
|
+
for (const col of this.trackedCollections) {
|
|
1788
|
+
if (col instanceof EventTrackedCollection) {
|
|
1789
|
+
col._clearHistoryOps();
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
generateEvents() {
|
|
1794
|
+
const events = [];
|
|
1795
|
+
for (const obj of this.trackedObjects) {
|
|
1796
|
+
const origin = getItemOrigin(obj);
|
|
1797
|
+
if (!origin) continue;
|
|
1798
|
+
const legacy = origin._lifecycleOptions;
|
|
1799
|
+
if (!legacy) continue;
|
|
1800
|
+
const meta = getEventMetadata(Object.getPrototypeOf(obj));
|
|
1801
|
+
switch (obj.state) {
|
|
1802
|
+
case "Insert" /* Insert */:
|
|
1803
|
+
if (legacy.itemAdded) {
|
|
1804
|
+
events.push(buildItemAddedEvent(obj, meta, legacy.itemAdded));
|
|
1805
|
+
}
|
|
1806
|
+
break;
|
|
1807
|
+
case "Deleted" /* Deleted */:
|
|
1808
|
+
if (legacy.itemRemoved) {
|
|
1809
|
+
events.push(buildItemRemovedEvent(obj, legacy.itemRemoved));
|
|
1810
|
+
}
|
|
1811
|
+
break;
|
|
1812
|
+
case "Changed" /* Changed */:
|
|
1813
|
+
pushFieldClusterEvents(obj, meta, events);
|
|
1814
|
+
break;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
const ownedCollections = /* @__PURE__ */ new Map();
|
|
1818
|
+
for (const col of this.trackedCollections) {
|
|
1819
|
+
if (!(col instanceof EventTrackedCollection)) continue;
|
|
1820
|
+
const agg = col._aggregateOptions;
|
|
1821
|
+
if (!agg?.owner) continue;
|
|
1822
|
+
const owner = agg.owner.object;
|
|
1823
|
+
let list = ownedCollections.get(owner);
|
|
1824
|
+
if (!list) {
|
|
1825
|
+
list = [];
|
|
1826
|
+
ownedCollections.set(owner, list);
|
|
1827
|
+
}
|
|
1828
|
+
list.push(col);
|
|
1829
|
+
}
|
|
1830
|
+
for (const obj of this.trackedObjects) {
|
|
1831
|
+
const origin = getItemOrigin(obj);
|
|
1832
|
+
if (origin) continue;
|
|
1833
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1834
|
+
const meta = getEventMetadata(Object.getPrototypeOf(obj));
|
|
1835
|
+
const stateMap = getEventState(obj);
|
|
1836
|
+
const historyMap = getHistoryState(obj);
|
|
1837
|
+
for (const [propName, propMeta] of meta) {
|
|
1838
|
+
const group = propMeta.eventType ?? DEFAULT_GROUP;
|
|
1839
|
+
if (propMeta.history) {
|
|
1840
|
+
const chain = historyMap.get(propName);
|
|
1841
|
+
if (chain && chain.length > 0) {
|
|
1842
|
+
addToGroup(groups, group, propName, [...chain]);
|
|
1843
|
+
}
|
|
1844
|
+
} else {
|
|
1845
|
+
const entry = stateMap.get(propName);
|
|
1846
|
+
if (entry) {
|
|
1847
|
+
addToGroup(groups, group, propName, normalizeValue(entry.currentValue));
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
const owned = ownedCollections.get(obj) ?? [];
|
|
1852
|
+
for (const col of owned) {
|
|
1853
|
+
const slot = computeCollectionSlot(col, this);
|
|
1854
|
+
if (slot === void 0) continue;
|
|
1855
|
+
const agg = col._aggregateOptions;
|
|
1856
|
+
const group = agg.eventType ?? DEFAULT_GROUP;
|
|
1857
|
+
const propertyName = agg.owner.property;
|
|
1858
|
+
addToGroup(groups, group, propertyName, slot);
|
|
1859
|
+
}
|
|
1860
|
+
if (groups.size === 0) continue;
|
|
1861
|
+
const identity = getIdentity(obj);
|
|
1862
|
+
for (const [group, payload] of groups) {
|
|
1863
|
+
const event = {
|
|
1864
|
+
eventType: group,
|
|
1865
|
+
payload,
|
|
1866
|
+
trackingId: obj.trackingId
|
|
1867
|
+
};
|
|
1868
|
+
if (identity !== void 0) {
|
|
1869
|
+
event.targetId = identity;
|
|
1870
|
+
}
|
|
1871
|
+
events.push(event);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
for (const col of this.trackedCollections) {
|
|
1875
|
+
if (!(col instanceof EventTrackedCollection)) continue;
|
|
1876
|
+
const agg = col._aggregateOptions;
|
|
1877
|
+
if (!agg || agg.owner) continue;
|
|
1878
|
+
const slot = computeCollectionSlot(col, this);
|
|
1879
|
+
if (slot === void 0) continue;
|
|
1880
|
+
const eventType = agg.eventType ?? DEFAULT_GROUP;
|
|
1881
|
+
events.push({
|
|
1882
|
+
eventType,
|
|
1883
|
+
payload: slot
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
return events;
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
function addToGroup(groups, group, key, value) {
|
|
1890
|
+
let payload = groups.get(group);
|
|
1891
|
+
if (!payload) {
|
|
1892
|
+
payload = {};
|
|
1893
|
+
groups.set(group, payload);
|
|
1894
|
+
}
|
|
1895
|
+
payload[key] = value;
|
|
1896
|
+
}
|
|
1897
|
+
function buildItemAddedEvent(obj, meta, eventType) {
|
|
1898
|
+
const payload = {};
|
|
1899
|
+
for (const [propertyName] of meta) {
|
|
1900
|
+
const value = obj[propertyName];
|
|
1901
|
+
payload[propertyName] = normalizeValue(value);
|
|
1902
|
+
}
|
|
1903
|
+
return {
|
|
1904
|
+
eventType,
|
|
1905
|
+
payload,
|
|
1906
|
+
trackingId: obj.trackingId
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
function buildItemRemovedEvent(obj, eventType) {
|
|
1910
|
+
const autoIdProp = getAutoIdProperty(Object.getPrototypeOf(obj));
|
|
1911
|
+
const targetId = autoIdProp ? obj[autoIdProp] : void 0;
|
|
1912
|
+
const event = {
|
|
1913
|
+
eventType,
|
|
1914
|
+
payload: {}
|
|
1915
|
+
};
|
|
1916
|
+
if (typeof targetId === "number") {
|
|
1917
|
+
event.targetId = targetId;
|
|
1918
|
+
}
|
|
1919
|
+
return event;
|
|
1920
|
+
}
|
|
1921
|
+
function pushFieldClusterEvents(obj, meta, events) {
|
|
1922
|
+
const state = getEventState(obj);
|
|
1923
|
+
if (state.size === 0) return;
|
|
1924
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
1925
|
+
for (const [propertyName, propMeta] of meta) {
|
|
1926
|
+
if (!state.has(propertyName)) continue;
|
|
1927
|
+
if (!propMeta.eventType) continue;
|
|
1928
|
+
let bucket = grouped.get(propMeta.eventType);
|
|
1929
|
+
if (!bucket) {
|
|
1930
|
+
bucket = [];
|
|
1931
|
+
grouped.set(propMeta.eventType, bucket);
|
|
1932
|
+
}
|
|
1933
|
+
bucket.push(propertyName);
|
|
1934
|
+
}
|
|
1935
|
+
const autoIdProp = getAutoIdProperty(Object.getPrototypeOf(obj));
|
|
1936
|
+
const targetIdRaw = autoIdProp ? obj[autoIdProp] : void 0;
|
|
1937
|
+
for (const [eventType, propertyNames] of grouped) {
|
|
1938
|
+
const payload = {};
|
|
1939
|
+
for (const propertyName of propertyNames) {
|
|
1940
|
+
payload[propertyName] = normalizeValue(state.get(propertyName).currentValue);
|
|
1941
|
+
}
|
|
1942
|
+
const event = {
|
|
1943
|
+
eventType,
|
|
1944
|
+
payload,
|
|
1945
|
+
trackingId: obj.trackingId
|
|
1946
|
+
};
|
|
1947
|
+
if (typeof targetIdRaw === "number") {
|
|
1948
|
+
event.targetId = targetIdRaw;
|
|
1949
|
+
}
|
|
1950
|
+
events.push(event);
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
function computeCollectionSlot(col, tracker) {
|
|
1954
|
+
const agg = col._aggregateOptions;
|
|
1955
|
+
const isHistory = agg.history !== void 0 && agg.history !== false;
|
|
1956
|
+
if (isHistory) return computeHistoryOps(col, agg);
|
|
1957
|
+
return computeBucketedSlot(col, tracker);
|
|
1958
|
+
}
|
|
1959
|
+
function computeHistoryOps(col, agg) {
|
|
1960
|
+
const opsList = col._historyOpsList;
|
|
1961
|
+
const hasFactory = typeof agg.history === "object" && agg.history.entryFactory;
|
|
1962
|
+
const ops = [];
|
|
1963
|
+
for (const op of opsList) {
|
|
1964
|
+
if (hasFactory) {
|
|
1965
|
+
ops.push(op.raw);
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1968
|
+
if (op.op === "add") {
|
|
1969
|
+
ops.push({ op: "add", item: op.snapshot ?? (op.item ? snapshotItemForAdded(op.item) : {}) });
|
|
1970
|
+
} else if (op.op === "remove") {
|
|
1971
|
+
const idObj = op.identity && typeof op.identity === "object" ? op.identity : identityToSingleKeyObject(op.identity, col);
|
|
1972
|
+
ops.push({ op: "remove", ...idObj });
|
|
1973
|
+
} else if (op.op === "change" && op.item) {
|
|
1974
|
+
const idObj = getIdentityObject(op.item);
|
|
1975
|
+
const diff = op.diff ?? computeItemDiff(op.item);
|
|
1976
|
+
ops.push({ op: "change", ...idObj, ...diff });
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
if (ops.length === 0) return void 0;
|
|
1980
|
+
return { ops };
|
|
1981
|
+
}
|
|
1982
|
+
function identityToSingleKeyObject(identity, col) {
|
|
1983
|
+
const baseline = col._baselineListSnapshot();
|
|
1984
|
+
const sample = baseline.find((i) => i instanceof TrackedObject);
|
|
1985
|
+
const currentSample = col.collection.find(
|
|
1986
|
+
(i) => i instanceof TrackedObject
|
|
1987
|
+
);
|
|
1988
|
+
const proto = sample ? Object.getPrototypeOf(sample) : currentSample ? Object.getPrototypeOf(currentSample) : void 0;
|
|
1989
|
+
if (!proto) return {};
|
|
1990
|
+
const props = getIdentityProperties(proto);
|
|
1991
|
+
if (props.length === 1) return { [props[0]]: identity };
|
|
1992
|
+
return identity && typeof identity === "object" ? identity : {};
|
|
1993
|
+
}
|
|
1994
|
+
function computeBucketedSlot(col, tracker) {
|
|
1995
|
+
const added = [];
|
|
1996
|
+
const changed = [];
|
|
1997
|
+
const removed = [];
|
|
1998
|
+
const isPrimitive = !hasTrackedObjectItems(col);
|
|
1999
|
+
for (const item of col.collection) {
|
|
2000
|
+
if (item instanceof TrackedObject) {
|
|
2001
|
+
if (item.state === "Insert" /* Insert */) {
|
|
2002
|
+
added.push(snapshotItemForAdded(item));
|
|
2003
|
+
} else if (item.state === "Changed" /* Changed */) {
|
|
2004
|
+
const entry = buildChangedEntry(item);
|
|
2005
|
+
if (entry) changed.push(entry);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
if (isPrimitive) {
|
|
2010
|
+
for (const item of col.collection) {
|
|
2011
|
+
if (!col._isInBaseline(item)) added.push(item);
|
|
2012
|
+
}
|
|
2013
|
+
for (const baselineItem of col._baselineListSnapshot()) {
|
|
2014
|
+
if (!col.collection.includes(baselineItem)) removed.push(baselineItem);
|
|
2015
|
+
}
|
|
2016
|
+
} else {
|
|
2017
|
+
for (const obj of tracker.trackedObjects) {
|
|
2018
|
+
if (obj.state !== "Deleted" /* Deleted */) continue;
|
|
2019
|
+
if (getItemOrigin(obj) !== col) continue;
|
|
2020
|
+
const identity = getIdentity(obj);
|
|
2021
|
+
removed.push(identity);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
if (added.length === 0 && changed.length === 0 && removed.length === 0) {
|
|
2025
|
+
return void 0;
|
|
2026
|
+
}
|
|
2027
|
+
const slot = { added, removed };
|
|
2028
|
+
if (!isPrimitive) slot.changed = changed;
|
|
2029
|
+
return slot;
|
|
2030
|
+
}
|
|
2031
|
+
function hasTrackedObjectItems(col) {
|
|
2032
|
+
for (const item of col.collection) {
|
|
2033
|
+
if (item instanceof TrackedObject) return true;
|
|
2034
|
+
}
|
|
2035
|
+
for (const item of col._baselineListSnapshot()) {
|
|
2036
|
+
if (item instanceof TrackedObject) return true;
|
|
2037
|
+
}
|
|
2038
|
+
return false;
|
|
2039
|
+
}
|
|
2040
|
+
function snapshotItemForAdded(item) {
|
|
2041
|
+
const proto = Object.getPrototypeOf(item);
|
|
2042
|
+
const meta = getEventMetadata(proto);
|
|
2043
|
+
const idProps = getIdentityProperties(proto);
|
|
2044
|
+
const autoIdProp = getAutoIdProperty(proto);
|
|
2045
|
+
const snapshot = {};
|
|
2046
|
+
const rec = item;
|
|
2047
|
+
for (const idProp of idProps) {
|
|
2048
|
+
if (idProp === autoIdProp) {
|
|
2049
|
+
snapshot[idProp] = null;
|
|
2050
|
+
} else {
|
|
2051
|
+
snapshot[idProp] = rec[idProp];
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
for (const [propName] of meta) {
|
|
2055
|
+
if (idProps.includes(propName)) continue;
|
|
2056
|
+
snapshot[propName] = normalizeValue(rec[propName]);
|
|
2057
|
+
}
|
|
2058
|
+
return snapshot;
|
|
2059
|
+
}
|
|
2060
|
+
function buildChangedEntry(item) {
|
|
2061
|
+
const state = getEventState(item);
|
|
2062
|
+
const history = getHistoryState(item);
|
|
2063
|
+
if (state.size === 0 && history.size === 0) return void 0;
|
|
2064
|
+
const proto = Object.getPrototypeOf(item);
|
|
2065
|
+
const idProps = getIdentityProperties(proto);
|
|
2066
|
+
const rec = item;
|
|
2067
|
+
const entry = {};
|
|
2068
|
+
for (const idProp of idProps) {
|
|
2069
|
+
entry[idProp] = rec[idProp];
|
|
2070
|
+
}
|
|
2071
|
+
for (const [propName, e] of state) {
|
|
2072
|
+
if (idProps.includes(propName)) continue;
|
|
2073
|
+
entry[propName] = normalizeValue(e.currentValue);
|
|
2074
|
+
}
|
|
2075
|
+
for (const [propName, chain] of history) {
|
|
2076
|
+
if (idProps.includes(propName)) continue;
|
|
2077
|
+
entry[propName] = [...chain];
|
|
2078
|
+
}
|
|
2079
|
+
return entry;
|
|
2080
|
+
}
|
|
2081
|
+
function computeItemDiff(item) {
|
|
2082
|
+
const state = getEventState(item);
|
|
2083
|
+
const proto = Object.getPrototypeOf(item);
|
|
2084
|
+
const idProps = getIdentityProperties(proto);
|
|
2085
|
+
const diff = {};
|
|
2086
|
+
for (const [propName, e] of state) {
|
|
2087
|
+
if (idProps.includes(propName)) continue;
|
|
2088
|
+
diff[propName] = normalizeValue(e.currentValue);
|
|
2089
|
+
}
|
|
2090
|
+
return diff;
|
|
2091
|
+
}
|
|
2092
|
+
function normalizeValue(value) {
|
|
2093
|
+
return value === void 0 ? null : value;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
// src/EventTracked.ts
|
|
2097
|
+
function EventTracked(validator, onChange, options) {
|
|
2098
|
+
const trackedDecorator = Tracked(validator, onChange, {
|
|
2099
|
+
coalesceWithin: options?.coalesceWithin
|
|
2100
|
+
});
|
|
2101
|
+
function decorator(target, context) {
|
|
2102
|
+
const result = trackedDecorator(target, context);
|
|
2103
|
+
const propertyName = String(context.name);
|
|
2104
|
+
context.addInitializer(function() {
|
|
2105
|
+
registerEventProperty(Object.getPrototypeOf(this), propertyName, {
|
|
2106
|
+
eventType: options?.eventType,
|
|
2107
|
+
history: options?.history,
|
|
2108
|
+
coalesceWithin: options?.coalesceWithin
|
|
2109
|
+
});
|
|
2110
|
+
ensureEventStateSubscription(this);
|
|
2111
|
+
});
|
|
2112
|
+
return result;
|
|
2113
|
+
}
|
|
2114
|
+
return decorator;
|
|
2115
|
+
}
|
|
1365
2116
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1366
2117
|
0 && (module.exports = {
|
|
1367
2118
|
AutoId,
|
|
2119
|
+
EventTracked,
|
|
2120
|
+
EventTrackedCollection,
|
|
2121
|
+
EventTracker,
|
|
2122
|
+
Id,
|
|
1368
2123
|
State,
|
|
1369
2124
|
Tracked,
|
|
1370
2125
|
TrackedCollection,
|
|
@@ -1372,6 +2127,9 @@ var TrackedCollectionChanged = class {
|
|
|
1372
2127
|
TrackedObject,
|
|
1373
2128
|
Tracker,
|
|
1374
2129
|
TrackerSession,
|
|
1375
|
-
TypedEvent
|
|
2130
|
+
TypedEvent,
|
|
2131
|
+
getIdentity,
|
|
2132
|
+
getIdentityObject,
|
|
2133
|
+
getIdentityProperties
|
|
1376
2134
|
});
|
|
1377
2135
|
//# sourceMappingURL=index.cjs.map
|