@katn30/trakr 3.0.0 → 4.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.
- package/README.md +128 -4
- package/dist/dev/index.cjs +600 -63
- package/dist/dev/index.cjs.map +1 -1
- package/dist/dev/index.d.cts +71 -10
- package/dist/dev/index.d.ts +71 -10
- package/dist/dev/index.js +595 -62
- package/dist/dev/index.js.map +1 -1
- package/dist/prod/index.cjs +600 -63
- package/dist/prod/index.cjs.map +1 -1
- package/dist/prod/index.js +595 -62
- package/dist/prod/index.js.map +1 -1
- package/package.json +1 -1
package/dist/prod/index.js
CHANGED
|
@@ -257,17 +257,73 @@ var OperationProperties = class {
|
|
|
257
257
|
|
|
258
258
|
// src/ExternallyAssigned.ts
|
|
259
259
|
var AUTO_ID = /* @__PURE__ */ Symbol("autoId");
|
|
260
|
+
var ID_PROPS = /* @__PURE__ */ Symbol("idProps");
|
|
260
261
|
function AutoId(_target, context) {
|
|
261
262
|
context.addInitializer(function() {
|
|
262
|
-
Object.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
263
|
+
const proto = Object.getPrototypeOf(this);
|
|
264
|
+
if (!Object.prototype.hasOwnProperty.call(proto, AUTO_ID)) {
|
|
265
|
+
Object.defineProperty(proto, AUTO_ID, {
|
|
266
|
+
value: String(context.name),
|
|
267
|
+
configurable: true
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
addIdentityProp(proto, String(context.name));
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function Id(_target, context) {
|
|
274
|
+
context.addInitializer(function() {
|
|
275
|
+
const proto = Object.getPrototypeOf(this);
|
|
276
|
+
addIdentityProp(proto, String(context.name));
|
|
266
277
|
});
|
|
267
278
|
}
|
|
279
|
+
function addIdentityProp(proto, propertyName) {
|
|
280
|
+
if (!Object.prototype.hasOwnProperty.call(proto, ID_PROPS)) {
|
|
281
|
+
Object.defineProperty(proto, ID_PROPS, {
|
|
282
|
+
value: [],
|
|
283
|
+
configurable: true,
|
|
284
|
+
writable: true
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
const list = proto[ID_PROPS];
|
|
288
|
+
if (!list.includes(propertyName)) list.push(propertyName);
|
|
289
|
+
}
|
|
268
290
|
function getAutoIdProperty(proto) {
|
|
269
291
|
return AUTO_ID in proto ? proto[AUTO_ID] : void 0;
|
|
270
292
|
}
|
|
293
|
+
function getIdentityProperties(proto) {
|
|
294
|
+
const chain = [];
|
|
295
|
+
let current = proto;
|
|
296
|
+
while (current) {
|
|
297
|
+
chain.push(current);
|
|
298
|
+
current = Object.getPrototypeOf(current);
|
|
299
|
+
}
|
|
300
|
+
const merged = [];
|
|
301
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
302
|
+
const proto2 = chain[i];
|
|
303
|
+
if (!Object.prototype.hasOwnProperty.call(proto2, ID_PROPS)) continue;
|
|
304
|
+
const list = proto2[ID_PROPS];
|
|
305
|
+
for (const name of list) {
|
|
306
|
+
if (!merged.includes(name)) merged.push(name);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return merged;
|
|
310
|
+
}
|
|
311
|
+
function getIdentity(obj) {
|
|
312
|
+
const props = getIdentityProperties(Object.getPrototypeOf(obj));
|
|
313
|
+
if (props.length === 0) return void 0;
|
|
314
|
+
if (props.length === 1) {
|
|
315
|
+
return obj[props[0]];
|
|
316
|
+
}
|
|
317
|
+
const result = {};
|
|
318
|
+
for (const p of props) result[p] = obj[p];
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
function getIdentityObject(obj) {
|
|
322
|
+
const props = getIdentityProperties(Object.getPrototypeOf(obj));
|
|
323
|
+
const result = {};
|
|
324
|
+
for (const p of props) result[p] = obj[p];
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
271
327
|
|
|
272
328
|
// src/TrackedObjectStateMachine.ts
|
|
273
329
|
function applyStateTransition(obj, event, direction, context) {
|
|
@@ -741,6 +797,9 @@ var Tracker = class {
|
|
|
741
797
|
this._commitStateOperation = lastOp;
|
|
742
798
|
this.reset();
|
|
743
799
|
}
|
|
800
|
+
getByTrackingId(trackingId) {
|
|
801
|
+
return this.trackedObjects.find((o) => o.trackingId === trackingId);
|
|
802
|
+
}
|
|
744
803
|
/** @internal */
|
|
745
804
|
_isInUndoStack(op) {
|
|
746
805
|
return this._undoOperations.includes(op);
|
|
@@ -1332,15 +1391,18 @@ var TrackedCollectionChanged = class {
|
|
|
1332
1391
|
// src/EventRegistry.ts
|
|
1333
1392
|
var EVENT_METADATA = /* @__PURE__ */ Symbol("eventMetadata");
|
|
1334
1393
|
var instanceState = /* @__PURE__ */ new WeakMap();
|
|
1394
|
+
var instanceHistory = /* @__PURE__ */ new WeakMap();
|
|
1395
|
+
var instanceHistoryTimes = /* @__PURE__ */ new WeakMap();
|
|
1335
1396
|
var subscribedInstances = /* @__PURE__ */ new WeakSet();
|
|
1336
1397
|
var itemOriginCollection = /* @__PURE__ */ new WeakMap();
|
|
1398
|
+
var DEFAULT_GROUP = "";
|
|
1337
1399
|
function hasOwnEventMetadata(proto) {
|
|
1338
1400
|
return Object.prototype.hasOwnProperty.call(proto, EVENT_METADATA);
|
|
1339
1401
|
}
|
|
1340
1402
|
function ownEventMetadata(proto) {
|
|
1341
1403
|
return hasOwnEventMetadata(proto) ? proto[EVENT_METADATA] : void 0;
|
|
1342
1404
|
}
|
|
1343
|
-
function registerEventProperty(proto, property,
|
|
1405
|
+
function registerEventProperty(proto, property, options) {
|
|
1344
1406
|
if (!hasOwnEventMetadata(proto)) {
|
|
1345
1407
|
Object.defineProperty(proto, EVENT_METADATA, {
|
|
1346
1408
|
value: /* @__PURE__ */ new Map(),
|
|
@@ -1349,7 +1411,7 @@ function registerEventProperty(proto, property, eventType) {
|
|
|
1349
1411
|
}
|
|
1350
1412
|
const map = proto[EVENT_METADATA];
|
|
1351
1413
|
if (!map.has(property)) {
|
|
1352
|
-
map.set(property,
|
|
1414
|
+
map.set(property, options);
|
|
1353
1415
|
}
|
|
1354
1416
|
}
|
|
1355
1417
|
function getEventMetadata(proto) {
|
|
@@ -1363,31 +1425,97 @@ function getEventMetadata(proto) {
|
|
|
1363
1425
|
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1364
1426
|
const own = ownEventMetadata(chain[i]);
|
|
1365
1427
|
if (!own) continue;
|
|
1366
|
-
own.forEach((
|
|
1367
|
-
if (!merged.has(property)) merged.set(property,
|
|
1428
|
+
own.forEach((options, property) => {
|
|
1429
|
+
if (!merged.has(property)) merged.set(property, options);
|
|
1368
1430
|
});
|
|
1369
1431
|
}
|
|
1370
1432
|
return merged;
|
|
1371
1433
|
}
|
|
1434
|
+
var contextStacks = /* @__PURE__ */ new WeakMap();
|
|
1435
|
+
function pushContext(tracker, ctx) {
|
|
1436
|
+
let stack = contextStacks.get(tracker);
|
|
1437
|
+
if (!stack) {
|
|
1438
|
+
stack = [];
|
|
1439
|
+
contextStacks.set(tracker, stack);
|
|
1440
|
+
}
|
|
1441
|
+
stack.push(ctx);
|
|
1442
|
+
}
|
|
1443
|
+
function popContext(tracker) {
|
|
1444
|
+
const stack = contextStacks.get(tracker);
|
|
1445
|
+
if (stack && stack.length > 0) stack.pop();
|
|
1446
|
+
}
|
|
1447
|
+
function peekContext(tracker) {
|
|
1448
|
+
const stack = contextStacks.get(tracker);
|
|
1449
|
+
return stack && stack.length > 0 ? stack[stack.length - 1] : void 0;
|
|
1450
|
+
}
|
|
1372
1451
|
function ensureEventStateSubscription(target) {
|
|
1373
1452
|
if (subscribedInstances.has(target)) return;
|
|
1374
1453
|
subscribedInstances.add(target);
|
|
1375
1454
|
target.changed.subscribe((evt) => {
|
|
1376
1455
|
const meta = getEventMetadata(Object.getPrototypeOf(target));
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1456
|
+
const propMeta = meta.get(evt.property);
|
|
1457
|
+
if (!propMeta) return;
|
|
1458
|
+
if (propMeta.history) {
|
|
1459
|
+
appendHistoryEntry(
|
|
1460
|
+
target,
|
|
1461
|
+
evt.property,
|
|
1462
|
+
evt.newValue,
|
|
1463
|
+
evt.oldValue,
|
|
1464
|
+
propMeta.history,
|
|
1465
|
+
propMeta.coalesceWithin
|
|
1466
|
+
);
|
|
1383
1467
|
} else {
|
|
1384
|
-
|
|
1385
|
-
}
|
|
1386
|
-
if (entry.currentValue === entry.originalValue) {
|
|
1387
|
-
state.delete(evt.property);
|
|
1468
|
+
updateFinalValue(target, evt.property, evt.newValue, evt.oldValue);
|
|
1388
1469
|
}
|
|
1389
1470
|
});
|
|
1390
1471
|
}
|
|
1472
|
+
function updateFinalValue(target, property, newValue, oldValue) {
|
|
1473
|
+
const state = getOrCreateEventState(target);
|
|
1474
|
+
let entry = state.get(property);
|
|
1475
|
+
if (!entry) {
|
|
1476
|
+
entry = { originalValue: oldValue, currentValue: newValue };
|
|
1477
|
+
state.set(property, entry);
|
|
1478
|
+
} else {
|
|
1479
|
+
entry.currentValue = newValue;
|
|
1480
|
+
}
|
|
1481
|
+
if (entry.currentValue === entry.originalValue) {
|
|
1482
|
+
state.delete(property);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function appendHistoryEntry(target, property, newValue, oldValue, historyConfig, coalesceWithin) {
|
|
1486
|
+
const chains = getOrCreateHistoryState(target);
|
|
1487
|
+
let chain = chains.get(property);
|
|
1488
|
+
if (!chain) {
|
|
1489
|
+
chain = [];
|
|
1490
|
+
chains.set(property, chain);
|
|
1491
|
+
}
|
|
1492
|
+
const times = getOrCreateHistoryTimes(target);
|
|
1493
|
+
const now = Date.now();
|
|
1494
|
+
const lastTime = times.get(property);
|
|
1495
|
+
const shouldReplace = coalesceWithin !== void 0 && lastTime !== void 0 && now - lastTime < coalesceWithin && chain.length > 0;
|
|
1496
|
+
let entry;
|
|
1497
|
+
if (typeof historyConfig === "object" && historyConfig.entryFactory) {
|
|
1498
|
+
const ctx = peekContext(target.tracker);
|
|
1499
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1500
|
+
entry = historyConfig.entryFactory(target, newValue, oldValue, change, ctx);
|
|
1501
|
+
} else {
|
|
1502
|
+
entry = { property, value: newValue };
|
|
1503
|
+
}
|
|
1504
|
+
if (shouldReplace) {
|
|
1505
|
+
chain[chain.length - 1] = entry;
|
|
1506
|
+
} else {
|
|
1507
|
+
chain.push(entry);
|
|
1508
|
+
}
|
|
1509
|
+
times.set(property, now);
|
|
1510
|
+
}
|
|
1511
|
+
function getOrCreateHistoryTimes(target) {
|
|
1512
|
+
let times = instanceHistoryTimes.get(target);
|
|
1513
|
+
if (!times) {
|
|
1514
|
+
times = /* @__PURE__ */ new Map();
|
|
1515
|
+
instanceHistoryTimes.set(target, times);
|
|
1516
|
+
}
|
|
1517
|
+
return times;
|
|
1518
|
+
}
|
|
1391
1519
|
function getOrCreateEventState(target) {
|
|
1392
1520
|
let state = instanceState.get(target);
|
|
1393
1521
|
if (!state) {
|
|
@@ -1396,11 +1524,24 @@ function getOrCreateEventState(target) {
|
|
|
1396
1524
|
}
|
|
1397
1525
|
return state;
|
|
1398
1526
|
}
|
|
1527
|
+
function getOrCreateHistoryState(target) {
|
|
1528
|
+
let state = instanceHistory.get(target);
|
|
1529
|
+
if (!state) {
|
|
1530
|
+
state = /* @__PURE__ */ new Map();
|
|
1531
|
+
instanceHistory.set(target, state);
|
|
1532
|
+
}
|
|
1533
|
+
return state;
|
|
1534
|
+
}
|
|
1399
1535
|
function getEventState(target) {
|
|
1400
1536
|
return instanceState.get(target) ?? /* @__PURE__ */ new Map();
|
|
1401
1537
|
}
|
|
1538
|
+
function getHistoryState(target) {
|
|
1539
|
+
return instanceHistory.get(target) ?? /* @__PURE__ */ new Map();
|
|
1540
|
+
}
|
|
1402
1541
|
function clearEventState(target) {
|
|
1403
1542
|
instanceState.delete(target);
|
|
1543
|
+
instanceHistory.delete(target);
|
|
1544
|
+
instanceHistoryTimes.delete(target);
|
|
1404
1545
|
}
|
|
1405
1546
|
function recordItemOrigin(item, collection) {
|
|
1406
1547
|
itemOriginCollection.set(item, collection);
|
|
@@ -1409,42 +1550,312 @@ function getItemOrigin(item) {
|
|
|
1409
1550
|
return itemOriginCollection.get(item);
|
|
1410
1551
|
}
|
|
1411
1552
|
|
|
1553
|
+
// src/EventTrackedCollection.ts
|
|
1554
|
+
var EventTrackedCollection = class extends TrackedCollection {
|
|
1555
|
+
constructor(tracker, items, validator, options) {
|
|
1556
|
+
super(tracker, items, validator);
|
|
1557
|
+
this._historyOps = [];
|
|
1558
|
+
this._baselineItems = /* @__PURE__ */ new Set();
|
|
1559
|
+
this._eventOptions = options;
|
|
1560
|
+
for (const item of this.collection) {
|
|
1561
|
+
this._baselineItems.add(item);
|
|
1562
|
+
if (item instanceof TrackedObject) {
|
|
1563
|
+
recordItemOrigin(item, this);
|
|
1564
|
+
this._validateItemHasIdentity(item);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
this.changed.subscribe((evt) => {
|
|
1568
|
+
for (const item of evt.added) {
|
|
1569
|
+
if (item instanceof TrackedObject) {
|
|
1570
|
+
recordItemOrigin(item, this);
|
|
1571
|
+
this._validateItemHasIdentity(item);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (this._isAggregateMode() && !this.tracker._isReplaying) {
|
|
1575
|
+
for (const item of evt.added) {
|
|
1576
|
+
if (item instanceof TrackedObject) {
|
|
1577
|
+
this._recordAddOp(item);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
for (const item of evt.removed) {
|
|
1581
|
+
if (item instanceof TrackedObject) {
|
|
1582
|
+
this._recordRemoveOp(item);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
if (this._isHistoryMode()) {
|
|
1588
|
+
this._attachItemChangeWatchers();
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
/** @internal */
|
|
1592
|
+
get _lifecycleOptions() {
|
|
1593
|
+
if (!this._eventOptions) return void 0;
|
|
1594
|
+
if (this._isAggregateMode()) return void 0;
|
|
1595
|
+
return {
|
|
1596
|
+
itemAdded: this._eventOptions.itemAdded,
|
|
1597
|
+
itemRemoved: this._eventOptions.itemRemoved
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
/** @internal */
|
|
1601
|
+
get _aggregateOptions() {
|
|
1602
|
+
return this._isAggregateMode() ? this._eventOptions : void 0;
|
|
1603
|
+
}
|
|
1604
|
+
/** @internal */
|
|
1605
|
+
get _historyOpsList() {
|
|
1606
|
+
return this._historyOps;
|
|
1607
|
+
}
|
|
1608
|
+
/** @internal */
|
|
1609
|
+
_clearHistoryOps() {
|
|
1610
|
+
this._historyOps.length = 0;
|
|
1611
|
+
this._baselineItems.clear();
|
|
1612
|
+
for (const item of this.collection) this._baselineItems.add(item);
|
|
1613
|
+
}
|
|
1614
|
+
/** @internal */
|
|
1615
|
+
_isInBaseline(item) {
|
|
1616
|
+
return this._baselineItems.has(item);
|
|
1617
|
+
}
|
|
1618
|
+
/** @internal */
|
|
1619
|
+
_baselineListSnapshot() {
|
|
1620
|
+
return [...this._baselineItems];
|
|
1621
|
+
}
|
|
1622
|
+
/** @internal */
|
|
1623
|
+
_rebaseline() {
|
|
1624
|
+
this._baselineItems.clear();
|
|
1625
|
+
for (const item of this.collection) this._baselineItems.add(item);
|
|
1626
|
+
}
|
|
1627
|
+
_isAggregateMode() {
|
|
1628
|
+
if (!this._eventOptions) return false;
|
|
1629
|
+
return this._eventOptions.eventType !== void 0 || this._eventOptions.history !== void 0;
|
|
1630
|
+
}
|
|
1631
|
+
_isHistoryMode() {
|
|
1632
|
+
return !!this._eventOptions?.history;
|
|
1633
|
+
}
|
|
1634
|
+
_validateItemHasIdentity(item) {
|
|
1635
|
+
const props = getIdentityProperties(Object.getPrototypeOf(item));
|
|
1636
|
+
if (props.length === 0) {
|
|
1637
|
+
throw new Error(
|
|
1638
|
+
`EventTrackedCollection item type ${item.constructor.name} must declare at least one @Id or @AutoId property when used with eventType or history mode`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
_attachItemChangeWatchers() {
|
|
1643
|
+
const watchItem = (item) => {
|
|
1644
|
+
item.changed.subscribe((_evt) => {
|
|
1645
|
+
if (this.tracker._isReplaying) return;
|
|
1646
|
+
if (!this.collection.includes(item)) return;
|
|
1647
|
+
this._recordChangeOp(item);
|
|
1648
|
+
});
|
|
1649
|
+
};
|
|
1650
|
+
for (const item of this.collection) {
|
|
1651
|
+
if (item instanceof TrackedObject) watchItem(item);
|
|
1652
|
+
}
|
|
1653
|
+
this.changed.subscribe((evt) => {
|
|
1654
|
+
for (const item of evt.added) {
|
|
1655
|
+
if (item instanceof TrackedObject) watchItem(item);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
_recordAddOp(item) {
|
|
1660
|
+
const opts = this._eventOptions;
|
|
1661
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1662
|
+
const ctx = peekContext(this.tracker);
|
|
1663
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1664
|
+
this._historyOps.push({
|
|
1665
|
+
op: "add",
|
|
1666
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1667
|
+
});
|
|
1668
|
+
} else if (opts?.history === true) {
|
|
1669
|
+
this._historyOps.push({ op: "add", item, snapshot: snapshotItemAtRecordTime(item) });
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
_recordRemoveOp(item) {
|
|
1673
|
+
const opts = this._eventOptions;
|
|
1674
|
+
const identity = getIdentity(item);
|
|
1675
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1676
|
+
const ctx = peekContext(this.tracker);
|
|
1677
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1678
|
+
this._historyOps.push({
|
|
1679
|
+
op: "remove",
|
|
1680
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1681
|
+
});
|
|
1682
|
+
} else if (opts?.history === true) {
|
|
1683
|
+
this._historyOps.push({ op: "remove", identity });
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
_recordChangeOpDiff(item) {
|
|
1687
|
+
const proto = Object.getPrototypeOf(item);
|
|
1688
|
+
const idProps = getIdentityProperties(proto);
|
|
1689
|
+
const meta = getEventMetadata(proto);
|
|
1690
|
+
const rec = item;
|
|
1691
|
+
const diff = {};
|
|
1692
|
+
for (const [propName] of meta) {
|
|
1693
|
+
if (idProps.includes(propName)) continue;
|
|
1694
|
+
const v = rec[propName];
|
|
1695
|
+
diff[propName] = v === void 0 ? null : v;
|
|
1696
|
+
}
|
|
1697
|
+
return diff;
|
|
1698
|
+
}
|
|
1699
|
+
_recordChangeOp(item) {
|
|
1700
|
+
const opts = this._eventOptions;
|
|
1701
|
+
if (typeof opts?.history === "object" && opts.history.entryFactory) {
|
|
1702
|
+
const ctx = peekContext(this.tracker);
|
|
1703
|
+
const change = { time: /* @__PURE__ */ new Date() };
|
|
1704
|
+
this._historyOps.push({
|
|
1705
|
+
op: "change",
|
|
1706
|
+
raw: opts.history.entryFactory(item, change, ctx)
|
|
1707
|
+
});
|
|
1708
|
+
} else if (opts?.history === true) {
|
|
1709
|
+
const identity = getIdentity(item);
|
|
1710
|
+
const diff = this._recordChangeOpDiff(item);
|
|
1711
|
+
this._historyOps.push({ op: "change", identity, item, diff });
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
};
|
|
1715
|
+
function snapshotItemAtRecordTime(item) {
|
|
1716
|
+
const proto = Object.getPrototypeOf(item);
|
|
1717
|
+
const meta = getEventMetadata(proto);
|
|
1718
|
+
const idProps = getIdentityProperties(proto);
|
|
1719
|
+
const autoIdProp = getAutoIdProperty(proto);
|
|
1720
|
+
const rec = item;
|
|
1721
|
+
const snap = {};
|
|
1722
|
+
for (const idProp of idProps) {
|
|
1723
|
+
if (idProp === autoIdProp) snap[idProp] = null;
|
|
1724
|
+
else snap[idProp] = rec[idProp];
|
|
1725
|
+
}
|
|
1726
|
+
for (const [propName] of meta) {
|
|
1727
|
+
if (idProps.includes(propName)) continue;
|
|
1728
|
+
const v = rec[propName];
|
|
1729
|
+
snap[propName] = v === void 0 ? null : v;
|
|
1730
|
+
}
|
|
1731
|
+
return snap;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1412
1734
|
// src/EventTracker.ts
|
|
1413
1735
|
var EventTracker = class extends Tracker {
|
|
1736
|
+
withContext(ctx, action) {
|
|
1737
|
+
pushContext(this, ctx);
|
|
1738
|
+
try {
|
|
1739
|
+
return action();
|
|
1740
|
+
} finally {
|
|
1741
|
+
popContext(this);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1414
1744
|
onCommit(keys) {
|
|
1415
1745
|
super.onCommit(keys);
|
|
1416
1746
|
for (const obj of this.trackedObjects) {
|
|
1417
1747
|
clearEventState(obj);
|
|
1418
1748
|
}
|
|
1749
|
+
for (const col of this.trackedCollections) {
|
|
1750
|
+
if (col instanceof EventTrackedCollection) {
|
|
1751
|
+
col._clearHistoryOps();
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1419
1754
|
}
|
|
1420
1755
|
generateEvents() {
|
|
1421
1756
|
const events = [];
|
|
1422
1757
|
for (const obj of this.trackedObjects) {
|
|
1423
|
-
const meta = getEventMetadata(Object.getPrototypeOf(obj));
|
|
1424
1758
|
const origin = getItemOrigin(obj);
|
|
1425
|
-
|
|
1759
|
+
if (!origin) continue;
|
|
1760
|
+
const legacy = origin._lifecycleOptions;
|
|
1761
|
+
if (!legacy) continue;
|
|
1762
|
+
const meta = getEventMetadata(Object.getPrototypeOf(obj));
|
|
1426
1763
|
switch (obj.state) {
|
|
1427
1764
|
case "Insert" /* Insert */:
|
|
1428
|
-
if (
|
|
1429
|
-
events.push(buildItemAddedEvent(obj, meta,
|
|
1765
|
+
if (legacy.itemAdded) {
|
|
1766
|
+
events.push(buildItemAddedEvent(obj, meta, legacy.itemAdded));
|
|
1430
1767
|
}
|
|
1431
1768
|
break;
|
|
1432
1769
|
case "Deleted" /* Deleted */:
|
|
1433
|
-
if (
|
|
1434
|
-
events.push(buildItemRemovedEvent(obj,
|
|
1770
|
+
if (legacy.itemRemoved) {
|
|
1771
|
+
events.push(buildItemRemovedEvent(obj, legacy.itemRemoved));
|
|
1435
1772
|
}
|
|
1436
1773
|
break;
|
|
1437
1774
|
case "Changed" /* Changed */:
|
|
1438
1775
|
pushFieldClusterEvents(obj, meta, events);
|
|
1439
1776
|
break;
|
|
1440
|
-
case "Unchanged" /* Unchanged */:
|
|
1441
|
-
default:
|
|
1442
|
-
break;
|
|
1443
1777
|
}
|
|
1444
1778
|
}
|
|
1779
|
+
const ownedCollections = /* @__PURE__ */ new Map();
|
|
1780
|
+
for (const col of this.trackedCollections) {
|
|
1781
|
+
if (!(col instanceof EventTrackedCollection)) continue;
|
|
1782
|
+
const agg = col._aggregateOptions;
|
|
1783
|
+
if (!agg?.owner) continue;
|
|
1784
|
+
const owner = agg.owner.object;
|
|
1785
|
+
let list = ownedCollections.get(owner);
|
|
1786
|
+
if (!list) {
|
|
1787
|
+
list = [];
|
|
1788
|
+
ownedCollections.set(owner, list);
|
|
1789
|
+
}
|
|
1790
|
+
list.push(col);
|
|
1791
|
+
}
|
|
1792
|
+
for (const obj of this.trackedObjects) {
|
|
1793
|
+
const origin = getItemOrigin(obj);
|
|
1794
|
+
if (origin) continue;
|
|
1795
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1796
|
+
const meta = getEventMetadata(Object.getPrototypeOf(obj));
|
|
1797
|
+
const stateMap = getEventState(obj);
|
|
1798
|
+
const historyMap = getHistoryState(obj);
|
|
1799
|
+
for (const [propName, propMeta] of meta) {
|
|
1800
|
+
const group = propMeta.eventType ?? DEFAULT_GROUP;
|
|
1801
|
+
if (propMeta.history) {
|
|
1802
|
+
const chain = historyMap.get(propName);
|
|
1803
|
+
if (chain && chain.length > 0) {
|
|
1804
|
+
addToGroup(groups, group, propName, [...chain]);
|
|
1805
|
+
}
|
|
1806
|
+
} else {
|
|
1807
|
+
const entry = stateMap.get(propName);
|
|
1808
|
+
if (entry) {
|
|
1809
|
+
addToGroup(groups, group, propName, normalizeValue(entry.currentValue));
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
const owned = ownedCollections.get(obj) ?? [];
|
|
1814
|
+
for (const col of owned) {
|
|
1815
|
+
const slot = computeCollectionSlot(col, this);
|
|
1816
|
+
if (slot === void 0) continue;
|
|
1817
|
+
const agg = col._aggregateOptions;
|
|
1818
|
+
const group = agg.eventType ?? DEFAULT_GROUP;
|
|
1819
|
+
const propertyName = agg.owner.property;
|
|
1820
|
+
addToGroup(groups, group, propertyName, slot);
|
|
1821
|
+
}
|
|
1822
|
+
if (groups.size === 0) continue;
|
|
1823
|
+
const identity = getIdentity(obj);
|
|
1824
|
+
for (const [group, payload] of groups) {
|
|
1825
|
+
const event = {
|
|
1826
|
+
eventType: group,
|
|
1827
|
+
payload,
|
|
1828
|
+
trackingId: obj.trackingId
|
|
1829
|
+
};
|
|
1830
|
+
if (identity !== void 0) {
|
|
1831
|
+
event.targetId = identity;
|
|
1832
|
+
}
|
|
1833
|
+
events.push(event);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
for (const col of this.trackedCollections) {
|
|
1837
|
+
if (!(col instanceof EventTrackedCollection)) continue;
|
|
1838
|
+
const agg = col._aggregateOptions;
|
|
1839
|
+
if (!agg || agg.owner) continue;
|
|
1840
|
+
const slot = computeCollectionSlot(col, this);
|
|
1841
|
+
if (slot === void 0) continue;
|
|
1842
|
+
const eventType = agg.eventType ?? DEFAULT_GROUP;
|
|
1843
|
+
events.push({
|
|
1844
|
+
eventType,
|
|
1845
|
+
payload: slot
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1445
1848
|
return events;
|
|
1446
1849
|
}
|
|
1447
1850
|
};
|
|
1851
|
+
function addToGroup(groups, group, key, value) {
|
|
1852
|
+
let payload = groups.get(group);
|
|
1853
|
+
if (!payload) {
|
|
1854
|
+
payload = {};
|
|
1855
|
+
groups.set(group, payload);
|
|
1856
|
+
}
|
|
1857
|
+
payload[key] = value;
|
|
1858
|
+
}
|
|
1448
1859
|
function buildItemAddedEvent(obj, meta, eventType) {
|
|
1449
1860
|
const payload = {};
|
|
1450
1861
|
for (const [propertyName] of meta) {
|
|
@@ -1473,12 +1884,13 @@ function pushFieldClusterEvents(obj, meta, events) {
|
|
|
1473
1884
|
const state = getEventState(obj);
|
|
1474
1885
|
if (state.size === 0) return;
|
|
1475
1886
|
const grouped = /* @__PURE__ */ new Map();
|
|
1476
|
-
for (const [propertyName,
|
|
1887
|
+
for (const [propertyName, propMeta] of meta) {
|
|
1477
1888
|
if (!state.has(propertyName)) continue;
|
|
1478
|
-
|
|
1889
|
+
if (!propMeta.eventType) continue;
|
|
1890
|
+
let bucket = grouped.get(propMeta.eventType);
|
|
1479
1891
|
if (!bucket) {
|
|
1480
1892
|
bucket = [];
|
|
1481
|
-
grouped.set(eventType, bucket);
|
|
1893
|
+
grouped.set(propMeta.eventType, bucket);
|
|
1482
1894
|
}
|
|
1483
1895
|
bucket.push(propertyName);
|
|
1484
1896
|
}
|
|
@@ -1500,57 +1912,175 @@ function pushFieldClusterEvents(obj, meta, events) {
|
|
|
1500
1912
|
events.push(event);
|
|
1501
1913
|
}
|
|
1502
1914
|
}
|
|
1915
|
+
function computeCollectionSlot(col, tracker) {
|
|
1916
|
+
const agg = col._aggregateOptions;
|
|
1917
|
+
const isHistory = agg.history !== void 0 && agg.history !== false;
|
|
1918
|
+
if (isHistory) return computeHistoryOps(col, agg);
|
|
1919
|
+
return computeBucketedSlot(col, tracker);
|
|
1920
|
+
}
|
|
1921
|
+
function computeHistoryOps(col, agg) {
|
|
1922
|
+
const opsList = col._historyOpsList;
|
|
1923
|
+
const hasFactory = typeof agg.history === "object" && agg.history.entryFactory;
|
|
1924
|
+
const ops = [];
|
|
1925
|
+
for (const op of opsList) {
|
|
1926
|
+
if (hasFactory) {
|
|
1927
|
+
ops.push(op.raw);
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
if (op.op === "add") {
|
|
1931
|
+
ops.push({ op: "add", item: op.snapshot ?? (op.item ? snapshotItemForAdded(op.item) : {}) });
|
|
1932
|
+
} else if (op.op === "remove") {
|
|
1933
|
+
const idObj = op.identity && typeof op.identity === "object" ? op.identity : identityToSingleKeyObject(op.identity, col);
|
|
1934
|
+
ops.push({ op: "remove", ...idObj });
|
|
1935
|
+
} else if (op.op === "change" && op.item) {
|
|
1936
|
+
const idObj = getIdentityObject(op.item);
|
|
1937
|
+
const diff = op.diff ?? computeItemDiff(op.item);
|
|
1938
|
+
ops.push({ op: "change", ...idObj, ...diff });
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
if (ops.length === 0) return void 0;
|
|
1942
|
+
return { ops };
|
|
1943
|
+
}
|
|
1944
|
+
function identityToSingleKeyObject(identity, col) {
|
|
1945
|
+
const baseline = col._baselineListSnapshot();
|
|
1946
|
+
const sample = baseline.find((i) => i instanceof TrackedObject);
|
|
1947
|
+
const currentSample = col.collection.find(
|
|
1948
|
+
(i) => i instanceof TrackedObject
|
|
1949
|
+
);
|
|
1950
|
+
const proto = sample ? Object.getPrototypeOf(sample) : currentSample ? Object.getPrototypeOf(currentSample) : void 0;
|
|
1951
|
+
if (!proto) return {};
|
|
1952
|
+
const props = getIdentityProperties(proto);
|
|
1953
|
+
if (props.length === 1) return { [props[0]]: identity };
|
|
1954
|
+
return identity && typeof identity === "object" ? identity : {};
|
|
1955
|
+
}
|
|
1956
|
+
function computeBucketedSlot(col, tracker) {
|
|
1957
|
+
const added = [];
|
|
1958
|
+
const changed = [];
|
|
1959
|
+
const removed = [];
|
|
1960
|
+
const isPrimitive = !hasTrackedObjectItems(col);
|
|
1961
|
+
for (const item of col.collection) {
|
|
1962
|
+
if (item instanceof TrackedObject) {
|
|
1963
|
+
if (item.state === "Insert" /* Insert */) {
|
|
1964
|
+
added.push(snapshotItemForAdded(item));
|
|
1965
|
+
} else if (item.state === "Changed" /* Changed */) {
|
|
1966
|
+
const entry = buildChangedEntry(item);
|
|
1967
|
+
if (entry) changed.push(entry);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
if (isPrimitive) {
|
|
1972
|
+
for (const item of col.collection) {
|
|
1973
|
+
if (!col._isInBaseline(item)) added.push(item);
|
|
1974
|
+
}
|
|
1975
|
+
for (const baselineItem of col._baselineListSnapshot()) {
|
|
1976
|
+
if (!col.collection.includes(baselineItem)) removed.push(baselineItem);
|
|
1977
|
+
}
|
|
1978
|
+
} else {
|
|
1979
|
+
for (const obj of tracker.trackedObjects) {
|
|
1980
|
+
if (obj.state !== "Deleted" /* Deleted */) continue;
|
|
1981
|
+
if (getItemOrigin(obj) !== col) continue;
|
|
1982
|
+
const identity = getIdentity(obj);
|
|
1983
|
+
removed.push(identity);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
if (added.length === 0 && changed.length === 0 && removed.length === 0) {
|
|
1987
|
+
return void 0;
|
|
1988
|
+
}
|
|
1989
|
+
const slot = { added, removed };
|
|
1990
|
+
if (!isPrimitive) slot.changed = changed;
|
|
1991
|
+
return slot;
|
|
1992
|
+
}
|
|
1993
|
+
function hasTrackedObjectItems(col) {
|
|
1994
|
+
for (const item of col.collection) {
|
|
1995
|
+
if (item instanceof TrackedObject) return true;
|
|
1996
|
+
}
|
|
1997
|
+
for (const item of col._baselineListSnapshot()) {
|
|
1998
|
+
if (item instanceof TrackedObject) return true;
|
|
1999
|
+
}
|
|
2000
|
+
return false;
|
|
2001
|
+
}
|
|
2002
|
+
function snapshotItemForAdded(item) {
|
|
2003
|
+
const proto = Object.getPrototypeOf(item);
|
|
2004
|
+
const meta = getEventMetadata(proto);
|
|
2005
|
+
const idProps = getIdentityProperties(proto);
|
|
2006
|
+
const autoIdProp = getAutoIdProperty(proto);
|
|
2007
|
+
const snapshot = {};
|
|
2008
|
+
const rec = item;
|
|
2009
|
+
for (const idProp of idProps) {
|
|
2010
|
+
if (idProp === autoIdProp) {
|
|
2011
|
+
snapshot[idProp] = null;
|
|
2012
|
+
} else {
|
|
2013
|
+
snapshot[idProp] = rec[idProp];
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
for (const [propName] of meta) {
|
|
2017
|
+
if (idProps.includes(propName)) continue;
|
|
2018
|
+
snapshot[propName] = normalizeValue(rec[propName]);
|
|
2019
|
+
}
|
|
2020
|
+
return snapshot;
|
|
2021
|
+
}
|
|
2022
|
+
function buildChangedEntry(item) {
|
|
2023
|
+
const state = getEventState(item);
|
|
2024
|
+
const history = getHistoryState(item);
|
|
2025
|
+
if (state.size === 0 && history.size === 0) return void 0;
|
|
2026
|
+
const proto = Object.getPrototypeOf(item);
|
|
2027
|
+
const idProps = getIdentityProperties(proto);
|
|
2028
|
+
const rec = item;
|
|
2029
|
+
const entry = {};
|
|
2030
|
+
for (const idProp of idProps) {
|
|
2031
|
+
entry[idProp] = rec[idProp];
|
|
2032
|
+
}
|
|
2033
|
+
for (const [propName, e] of state) {
|
|
2034
|
+
if (idProps.includes(propName)) continue;
|
|
2035
|
+
entry[propName] = normalizeValue(e.currentValue);
|
|
2036
|
+
}
|
|
2037
|
+
for (const [propName, chain] of history) {
|
|
2038
|
+
if (idProps.includes(propName)) continue;
|
|
2039
|
+
entry[propName] = [...chain];
|
|
2040
|
+
}
|
|
2041
|
+
return entry;
|
|
2042
|
+
}
|
|
2043
|
+
function computeItemDiff(item) {
|
|
2044
|
+
const state = getEventState(item);
|
|
2045
|
+
const proto = Object.getPrototypeOf(item);
|
|
2046
|
+
const idProps = getIdentityProperties(proto);
|
|
2047
|
+
const diff = {};
|
|
2048
|
+
for (const [propName, e] of state) {
|
|
2049
|
+
if (idProps.includes(propName)) continue;
|
|
2050
|
+
diff[propName] = normalizeValue(e.currentValue);
|
|
2051
|
+
}
|
|
2052
|
+
return diff;
|
|
2053
|
+
}
|
|
1503
2054
|
function normalizeValue(value) {
|
|
1504
2055
|
return value === void 0 ? null : value;
|
|
1505
2056
|
}
|
|
1506
2057
|
|
|
1507
2058
|
// src/EventTracked.ts
|
|
1508
|
-
function EventTracked(
|
|
1509
|
-
const trackedDecorator = Tracked(validator, onChange,
|
|
2059
|
+
function EventTracked(validator, onChange, options) {
|
|
2060
|
+
const trackedDecorator = Tracked(validator, onChange, {
|
|
2061
|
+
coalesceWithin: options?.coalesceWithin
|
|
2062
|
+
});
|
|
1510
2063
|
function decorator(target, context) {
|
|
1511
2064
|
const result = trackedDecorator(target, context);
|
|
1512
2065
|
const propertyName = String(context.name);
|
|
1513
2066
|
context.addInitializer(function() {
|
|
1514
|
-
registerEventProperty(
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
);
|
|
2067
|
+
registerEventProperty(Object.getPrototypeOf(this), propertyName, {
|
|
2068
|
+
eventType: options?.eventType,
|
|
2069
|
+
history: options?.history,
|
|
2070
|
+
coalesceWithin: options?.coalesceWithin
|
|
2071
|
+
});
|
|
1519
2072
|
ensureEventStateSubscription(this);
|
|
1520
2073
|
});
|
|
1521
2074
|
return result;
|
|
1522
2075
|
}
|
|
1523
2076
|
return decorator;
|
|
1524
2077
|
}
|
|
1525
|
-
|
|
1526
|
-
// src/EventTrackedCollection.ts
|
|
1527
|
-
var EventTrackedCollection = class extends TrackedCollection {
|
|
1528
|
-
constructor(tracker, items, validator, eventOptions) {
|
|
1529
|
-
super(tracker, items, validator);
|
|
1530
|
-
this._eventOptions = eventOptions;
|
|
1531
|
-
for (const item of this.collection) {
|
|
1532
|
-
if (item instanceof TrackedObject) {
|
|
1533
|
-
recordItemOrigin(item, this);
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
this.changed.subscribe((evt) => {
|
|
1537
|
-
for (const item of evt.added) {
|
|
1538
|
-
if (item instanceof TrackedObject) {
|
|
1539
|
-
recordItemOrigin(item, this);
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1544
|
-
/** @internal */
|
|
1545
|
-
get _lifecycleOptions() {
|
|
1546
|
-
return this._eventOptions;
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
2078
|
export {
|
|
1550
2079
|
AutoId,
|
|
1551
2080
|
EventTracked,
|
|
1552
2081
|
EventTrackedCollection,
|
|
1553
2082
|
EventTracker,
|
|
2083
|
+
Id,
|
|
1554
2084
|
State,
|
|
1555
2085
|
Tracked,
|
|
1556
2086
|
TrackedCollection,
|
|
@@ -1558,6 +2088,9 @@ export {
|
|
|
1558
2088
|
TrackedObject,
|
|
1559
2089
|
Tracker,
|
|
1560
2090
|
TrackerSession,
|
|
1561
|
-
TypedEvent
|
|
2091
|
+
TypedEvent,
|
|
2092
|
+
getIdentity,
|
|
2093
|
+
getIdentityObject,
|
|
2094
|
+
getIdentityProperties
|
|
1562
2095
|
};
|
|
1563
2096
|
//# sourceMappingURL=index.js.map
|