atom.io 0.24.5 → 0.24.7

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.
@@ -387,187 +387,69 @@ function isChildStore(store) {
387
387
  return `phase` in store.transactionMeta;
388
388
  }
389
389
 
390
- // internal/src/store/store.ts
391
- var Store = class {
392
- constructor(config, store = null) {
393
- this.parent = null;
394
- this.child = null;
395
- this.valueMap = /* @__PURE__ */ new Map();
396
- this.atoms = /* @__PURE__ */ new Map();
397
- this.selectors = /* @__PURE__ */ new Map();
398
- this.readonlySelectors = /* @__PURE__ */ new Map();
399
- this.trackers = /* @__PURE__ */ new Map();
400
- this.families = /* @__PURE__ */ new Map();
401
- this.timelines = /* @__PURE__ */ new Map();
402
- this.transactions = /* @__PURE__ */ new Map();
403
- this.atomsThatAreDefault = /* @__PURE__ */ new Set();
404
- this.timelineAtoms = new Junction({
405
- between: [`timelineKey`, `atomKey`],
406
- cardinality: `1:n`
407
- });
408
- this.selectorAtoms = new Junction({
409
- between: [`selectorKey`, `atomKey`],
410
- cardinality: `n:n`
411
- });
412
- this.selectorGraph = new Junction(
413
- {
414
- between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
415
- cardinality: `n:n`
416
- },
417
- {
418
- makeContentKey: (...keys) => keys.sort().join(`:`)
419
- }
390
+ // internal/src/transaction/abort-transaction.ts
391
+ var abortTransaction = (store) => {
392
+ const target = newest(store);
393
+ if (!isChildStore(target)) {
394
+ store.logger.warn(
395
+ `\u{1F41E}`,
396
+ `transaction`,
397
+ `???`,
398
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
420
399
  );
421
- this.molecules = /* @__PURE__ */ new Map();
422
- this.moleculeFamilies = /* @__PURE__ */ new Map();
423
- this.miscResources = /* @__PURE__ */ new Map();
424
- this.on = {
425
- atomCreation: new Subject(),
426
- atomDisposal: new Subject(),
427
- selectorCreation: new Subject(),
428
- selectorDisposal: new Subject(),
429
- timelineCreation: new Subject(),
430
- transactionCreation: new Subject(),
431
- transactionApplying: new StatefulSubject(
432
- null
433
- ),
434
- operationClose: new Subject(),
435
- moleculeCreationStart: new Subject(),
436
- moleculeCreationDone: new Subject(),
437
- moleculeDisposal: new Subject()
438
- };
439
- this.operation = { open: false };
440
- this.transactionMeta = {
441
- epoch: /* @__PURE__ */ new Map(),
442
- actionContinuities: new Junction({
443
- between: [`continuity`, `action`],
444
- cardinality: `1:n`
445
- })
446
- };
447
- this.config = {
448
- name: `IMPLICIT_STORE`,
449
- lifespan: `ephemeral`
450
- };
451
- this.loggers = [
452
- new atom_io.AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
453
- ];
454
- this.logger = {
455
- error: (...messages) => {
456
- for (const logger of this.loggers) logger.error(...messages);
457
- },
458
- info: (...messages) => {
459
- for (const logger of this.loggers) logger.info(...messages);
460
- },
461
- warn: (...messages) => {
462
- for (const logger of this.loggers) logger.warn(...messages);
463
- }
464
- };
465
- if (store !== null) {
466
- this.valueMap = new Map(store == null ? void 0 : store.valueMap);
467
- this.operation = __spreadValues({}, store == null ? void 0 : store.operation);
468
- if (isRootStore(store)) {
469
- this.transactionMeta = {
470
- epoch: new Map(store == null ? void 0 : store.transactionMeta.epoch),
471
- actionContinuities: new Junction(
472
- store == null ? void 0 : store.transactionMeta.actionContinuities.toJSON()
473
- )
474
- };
475
- }
476
- this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
477
- for (const [, family] of store.families) {
478
- family.install(this);
479
- }
480
- const mutableHelpers = /* @__PURE__ */ new Set();
481
- for (const [, atom] of store.atoms) {
482
- if (mutableHelpers.has(atom.key)) {
483
- continue;
484
- }
485
- atom.install(this);
486
- if (atom.type === `mutable_atom`) {
487
- const originalJsonToken = getJsonToken(atom, store);
488
- const originalUpdateToken = getUpdateToken(atom);
489
- mutableHelpers.add(originalJsonToken.key);
490
- mutableHelpers.add(originalUpdateToken.key);
491
- }
492
- }
493
- for (const [, selector] of store.readonlySelectors) {
494
- selector.install(this);
495
- }
496
- for (const [, selector] of store.selectors) {
497
- if (mutableHelpers.has(selector.key)) {
498
- continue;
499
- }
500
- selector.install(this);
501
- }
502
- for (const [, tx] of store.transactions) {
503
- tx.install(this);
504
- }
505
- for (const [, timeline] of store.timelines) {
506
- timeline.install(this);
507
- }
508
- }
400
+ return;
509
401
  }
402
+ store.logger.info(
403
+ `\u{1FA82}`,
404
+ `transaction`,
405
+ target.transactionMeta.update.key,
406
+ `Aborting transaction`
407
+ );
408
+ target.parent.child = null;
510
409
  };
511
- var IMPLICIT = {
512
- STORE_INTERNAL: void 0,
513
- get STORE() {
514
- var _a;
515
- return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
516
- name: `IMPLICIT_STORE`,
517
- lifespan: `ephemeral`
518
- });
410
+
411
+ // internal/src/not-found-error.ts
412
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
413
+ function prettyPrintTokenType(token) {
414
+ switch (token.type) {
415
+ case `atom_family`:
416
+ return `Atom Family`;
417
+ case `molecule_family`:
418
+ return `Molecule Family`;
419
+ case `readonly_selector`:
420
+ return `Readonly Selector`;
421
+ case `readonly_selector_family`:
422
+ return `Readonly Selector Family`;
423
+ case `selector_family`:
424
+ return `Selector Family`;
425
+ default:
426
+ return capitalize(token.type);
519
427
  }
520
- };
521
- var clearStore = (store) => {
522
- const { config } = store;
523
- for (const disposable of store.miscResources.values()) {
524
- disposable[Symbol.dispose]();
428
+ }
429
+ var NotFoundError = class extends Error {
430
+ constructor(token, store) {
431
+ super(
432
+ `${prettyPrintTokenType(token)} "${token.key}" not found in store "${store.config.name}".`
433
+ );
525
434
  }
526
- Object.assign(store, new Store(config));
527
- store.config = config;
528
435
  };
529
- function withdraw(token, store) {
530
- let withdrawn;
531
- let target = store;
532
- while (target !== null) {
533
- switch (token.type) {
534
- case `atom`:
535
- case `mutable_atom`:
536
- withdrawn = target.atoms.get(token.key);
537
- break;
538
- case `selector`:
539
- withdrawn = target.selectors.get(token.key);
540
- break;
541
- case `readonly_selector`:
542
- withdrawn = target.readonlySelectors.get(token.key);
543
- break;
544
- case `atom_family`:
545
- case `mutable_atom_family`:
546
- case `selector_family`:
547
- case `readonly_selector_family`:
548
- withdrawn = target.families.get(token.key);
549
- break;
550
- case `timeline`:
551
- withdrawn = target.timelines.get(token.key);
552
- break;
553
- case `transaction`:
554
- withdrawn = target.transactions.get(token.key);
555
- break;
556
- case `molecule`:
557
- withdrawn = target.molecules.get(json.stringifyJson(token.key));
558
- break;
559
- case `molecule_family`:
560
- withdrawn = target.moleculeFamilies.get(token.key);
561
- break;
562
- }
563
- if (withdrawn) {
564
- return withdrawn;
436
+
437
+ // internal/src/transaction/act-upon-store.ts
438
+ function actUponStore(token, id, store) {
439
+ return (...parameters) => {
440
+ const tx = withdraw(token, store);
441
+ if (tx) {
442
+ return tx.run(parameters, id);
565
443
  }
566
- target = target.child;
567
- }
568
- throw new NotFoundError(token, store);
444
+ throw new NotFoundError(token, store);
445
+ };
569
446
  }
570
447
 
448
+ // internal/src/set-state/become.ts
449
+ var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
450
+ originalThing instanceof Function ? originalThing() : originalThing
451
+ ) : nextVersionOfThing;
452
+
571
453
  // internal/src/get-state/read-or-compute-value.ts
572
454
  var readOrComputeValue = (state, target) => {
573
455
  if (target.valueMap.has(state.key)) {
@@ -588,176 +470,6 @@ var readOrComputeValue = (state, target) => {
588
470
  );
589
471
  return state.default instanceof Function ? state.default() : state.default;
590
472
  };
591
- function createRegularAtomFamily(options, store) {
592
- const subject = new Subject();
593
- const atomFamily = Object.assign(
594
- (key) => {
595
- const subKey = json.stringifyJson(key);
596
- const family = { key: options.key, subKey };
597
- const fullKey = `${options.key}(${subKey})`;
598
- const target = newest(store);
599
- const def = options.default;
600
- const individualOptions = {
601
- key: fullKey,
602
- default: def instanceof Function ? def(key) : def
603
- };
604
- if (options.effects) {
605
- individualOptions.effects = options.effects(key);
606
- }
607
- const token = createRegularAtom(individualOptions, family, target);
608
- subject.next({ type: `state_creation`, token });
609
- return token;
610
- },
611
- {
612
- key: options.key,
613
- type: `atom_family`,
614
- subject,
615
- install: (s) => createRegularAtomFamily(options, s)
616
- }
617
- );
618
- store.families.set(options.key, atomFamily);
619
- return atomFamily;
620
- }
621
-
622
- // internal/src/families/create-atom-family.ts
623
- function createAtomFamily(options, store) {
624
- const isMutable2 = `mutable` in options;
625
- if (isMutable2) {
626
- return createMutableAtomFamily(options, store);
627
- }
628
- return createRegularAtomFamily(options, store);
629
- }
630
- function createReadonlySelectorFamily(options, store) {
631
- const subject = new Subject();
632
- const readonlySelectorFamily = Object.assign(
633
- (key) => {
634
- const subKey = json.stringifyJson(key);
635
- const family = { key: options.key, subKey };
636
- const fullKey = `${options.key}(${subKey})`;
637
- const target = newest(store);
638
- const token = createReadonlySelector(
639
- {
640
- key: fullKey,
641
- get: options.get(key)
642
- },
643
- family,
644
- target
645
- );
646
- subject.next({ type: `state_creation`, token });
647
- return token;
648
- },
649
- {
650
- key: options.key,
651
- type: `readonly_selector_family`,
652
- subject,
653
- install: (s) => createReadonlySelectorFamily(options, s)
654
- }
655
- );
656
- store.families.set(options.key, readonlySelectorFamily);
657
- return readonlySelectorFamily;
658
- }
659
- function createWritableSelectorFamily(options, store) {
660
- const subject = new Subject();
661
- const selectorFamily = Object.assign(
662
- (key) => {
663
- const subKey = json.stringifyJson(key);
664
- const family = { key: options.key, subKey };
665
- const fullKey = `${options.key}(${subKey})`;
666
- const target = newest(store);
667
- const token = createWritableSelector(
668
- {
669
- key: fullKey,
670
- get: options.get(key),
671
- set: options.set(key)
672
- },
673
- family,
674
- target
675
- );
676
- subject.next({ type: `state_creation`, token });
677
- return token;
678
- },
679
- {
680
- key: options.key,
681
- type: `selector_family`,
682
- subject,
683
- install: (s) => createWritableSelectorFamily(options, s)
684
- }
685
- );
686
- store.families.set(options.key, selectorFamily);
687
- return selectorFamily;
688
- }
689
-
690
- // internal/src/families/create-selector-family.ts
691
- function createSelectorFamily(options, store) {
692
- const isWritable = `set` in options;
693
- if (isWritable) {
694
- return createWritableSelectorFamily(options, store);
695
- }
696
- return createReadonlySelectorFamily(options, store);
697
- }
698
-
699
- // internal/src/transaction/abort-transaction.ts
700
- var abortTransaction = (store) => {
701
- const target = newest(store);
702
- if (!isChildStore(target)) {
703
- store.logger.warn(
704
- `\u{1F41E}`,
705
- `transaction`,
706
- `???`,
707
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
708
- );
709
- return;
710
- }
711
- store.logger.info(
712
- `\u{1FA82}`,
713
- `transaction`,
714
- target.transactionMeta.update.key,
715
- `Aborting transaction`
716
- );
717
- target.parent.child = null;
718
- };
719
-
720
- // internal/src/not-found-error.ts
721
- var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
722
- function prettyPrintTokenType(token) {
723
- switch (token.type) {
724
- case `atom_family`:
725
- return `Atom Family`;
726
- case `molecule_family`:
727
- return `Molecule Family`;
728
- case `readonly_selector`:
729
- return `Readonly Selector`;
730
- case `readonly_selector_family`:
731
- return `Readonly Selector Family`;
732
- case `selector_family`:
733
- return `Selector Family`;
734
- default:
735
- return capitalize(token.type);
736
- }
737
- }
738
- var NotFoundError = class extends Error {
739
- constructor(token, store) {
740
- super(
741
- `${prettyPrintTokenType(token)} "${token.key}" not found in store "${store.config.name}".`
742
- );
743
- }
744
- };
745
-
746
- // internal/src/transaction/act-upon-store.ts
747
- function actUponStore(token, id, store) {
748
- return (...parameters) => {
749
- const tx = withdraw(token, store);
750
- if (tx) {
751
- return tx.run(parameters, id);
752
- }
753
- throw new NotFoundError(token, store);
754
- };
755
- }
756
-
757
- // internal/src/set-state/become.ts
758
- var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
759
- originalThing instanceof Function ? originalThing() : originalThing
760
- ) : nextVersionOfThing;
761
473
 
762
474
  // internal/src/operation.ts
763
475
  var openOperation = (token, store) => {
@@ -854,8 +566,9 @@ var emitUpdate = (state, update, store) => {
854
566
 
855
567
  // internal/src/set-state/evict-downstream.ts
856
568
  var evictDownStream = (atom, store) => {
857
- const downstreamKeys = store.selectorAtoms.getRelatedKeys(atom.key);
858
- store.logger.info(
569
+ const target = newest(store);
570
+ const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom.key);
571
+ target.logger.info(
859
572
  `\u{1F9F9}`,
860
573
  atom.type,
861
574
  atom.key,
@@ -863,20 +576,20 @@ var evictDownStream = (atom, store) => {
863
576
  downstreamKeys != null ? downstreamKeys : `to evict`
864
577
  );
865
578
  if (downstreamKeys) {
866
- if (store.operation.open) {
867
- store.logger.info(
579
+ if (target.operation.open) {
580
+ target.logger.info(
868
581
  `\u{1F9F9}`,
869
582
  atom.type,
870
583
  atom.key,
871
- `[ ${[...store.operation.done].join(`, `)} ] already done`
584
+ `[ ${[...target.operation.done].join(`, `)} ] already done`
872
585
  );
873
586
  }
874
587
  for (const key of downstreamKeys) {
875
- if (isDone(key, store)) {
588
+ if (isDone(key, target)) {
876
589
  continue;
877
590
  }
878
- evictCachedValue(key, store);
879
- markDone(key, store);
591
+ evictCachedValue(key, target);
592
+ markDone(key, target);
880
593
  }
881
594
  }
882
595
  };
@@ -1012,45 +725,44 @@ function ingestAtomUpdate(applying, atomUpdate, store) {
1012
725
  }
1013
726
  setIntoStore(token, value, store);
1014
727
  }
1015
-
1016
- // internal/src/molecule/create-molecule-family.ts
1017
- function createMoleculeFamily(options, store) {
1018
- var _a;
728
+ function createRegularAtomFamily(options, store) {
1019
729
  const subject = new Subject();
1020
- const token = {
1021
- type: `molecule_family`,
1022
- key: options.key,
1023
- dependsOn: (_a = options.dependsOn) != null ? _a : `all`
1024
- };
1025
- const family = __spreadProps(__spreadValues({}, token), {
1026
- subject,
1027
- new: options.new
1028
- });
1029
- store.moleculeFamilies.set(options.key, family);
1030
- return token;
730
+ const atomFamily = Object.assign(
731
+ (key) => {
732
+ const subKey = json.stringifyJson(key);
733
+ const family = { key: options.key, subKey };
734
+ const fullKey = `${options.key}(${subKey})`;
735
+ const target = newest(store);
736
+ const def = options.default;
737
+ const individualOptions = {
738
+ key: fullKey,
739
+ default: def instanceof Function ? def(key) : def
740
+ };
741
+ if (options.effects) {
742
+ individualOptions.effects = options.effects(key);
743
+ }
744
+ const token = createRegularAtom(individualOptions, family, target);
745
+ subject.next({ type: `state_creation`, token });
746
+ return token;
747
+ },
748
+ {
749
+ key: options.key,
750
+ type: `atom_family`,
751
+ subject,
752
+ install: (s) => createRegularAtomFamily(options, s)
753
+ }
754
+ );
755
+ store.families.set(options.key, atomFamily);
756
+ return atomFamily;
1031
757
  }
1032
758
 
1033
- // internal/src/molecule/grow-molecule-in-store.ts
1034
- function growMoleculeInStore(molecule, family, store) {
1035
- const stateToken = initFamilyMemberInStore(family, molecule.key, store);
1036
- molecule.tokens.set(stateToken.key, stateToken);
1037
- const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1038
- if (isTransaction) {
1039
- store.transactionMeta.update.updates.push({
1040
- type: `state_creation`,
1041
- token: stateToken
1042
- });
1043
- } else {
1044
- molecule.subject.next({ type: `state_creation`, token: stateToken });
759
+ // internal/src/families/create-atom-family.ts
760
+ function createAtomFamily(options, store) {
761
+ const isMutable2 = `mutable` in options;
762
+ if (isMutable2) {
763
+ return createMutableAtomFamily(options, store);
1045
764
  }
1046
- return stateToken;
1047
- }
1048
-
1049
- // internal/src/get-environment-data.ts
1050
- function getEnvironmentData(store) {
1051
- return {
1052
- store
1053
- };
765
+ return createRegularAtomFamily(options, store);
1054
766
  }
1055
767
 
1056
768
  // internal/src/get-state/get-from-store.ts
@@ -1066,520 +778,427 @@ function getFromStore(token, store) {
1066
778
  const state = withdraw(token, store);
1067
779
  return readOrComputeValue(state, store);
1068
780
  }
1069
- var Molecule = class {
1070
- constructor(ctx, key, family) {
1071
- this.key = key;
1072
- this.type = `molecule`;
1073
- this.subject = new Subject();
1074
- this.tokens = /* @__PURE__ */ new Map();
1075
- this.above = /* @__PURE__ */ new Map();
1076
- this.below = /* @__PURE__ */ new Map();
1077
- this.joins = /* @__PURE__ */ new Map();
1078
- this.stringKey = json.stringifyJson(key);
1079
- if (family) {
1080
- this.family = family;
1081
- }
1082
- if (ctx) {
1083
- if (Array.isArray(ctx)) {
1084
- for (const molecule of ctx) {
1085
- this.above.set(molecule.stringKey, molecule);
1086
- }
1087
- } else {
1088
- this.above.set(ctx.stringKey, ctx);
1089
- }
1090
- }
1091
- }
781
+
782
+ // internal/src/keys.ts
783
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
784
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
785
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
786
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
787
+
788
+ // internal/src/selector/get-selector-dependency-keys.ts
789
+ var getSelectorDependencyKeys = (key, store) => {
790
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
791
+ return sources;
1092
792
  };
1093
793
 
1094
- // internal/src/molecule/make-molecule-in-store.ts
1095
- function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1096
- const target = newest(store);
1097
- const token = {
1098
- type: `molecule`,
1099
- key,
1100
- family: familyToken
1101
- };
1102
- const contextArray = Array.isArray(context) ? context : [context];
1103
- const owners = contextArray.map((ctx) => {
1104
- if (ctx instanceof Molecule) {
1105
- return ctx;
1106
- }
1107
- const stringKey = json.stringifyJson(ctx.key);
1108
- const molecule2 = store.molecules.get(stringKey);
1109
- if (!molecule2) {
794
+ // internal/src/selector/trace-selector-atoms.ts
795
+ var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
796
+ const rootKeys = [];
797
+ const indirectDependencyKeys = getSelectorDependencyKeys(
798
+ directDependencyKey,
799
+ store
800
+ );
801
+ let depth = 0;
802
+ while (indirectDependencyKeys.length > 0) {
803
+ const indirectDependencyKey = indirectDependencyKeys.shift();
804
+ ++depth;
805
+ if (depth > 99999) {
1110
806
  throw new Error(
1111
- `Molecule ${stringKey} not found in store "${store.config.name}"`
807
+ `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1112
808
  );
1113
809
  }
1114
- return molecule2;
1115
- });
1116
- const family = withdraw(familyToken, store);
1117
- const molecule = new Molecule(owners, key, family);
1118
- target.molecules.set(json.stringifyJson(key), molecule);
1119
- for (const owner of owners) {
1120
- owner.below.set(molecule.stringKey, molecule);
810
+ if (!isAtomKey(indirectDependencyKey, store)) {
811
+ indirectDependencyKeys.push(
812
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
813
+ );
814
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
815
+ rootKeys.push(indirectDependencyKey);
816
+ }
1121
817
  }
1122
- const transactors = {
1123
- get: (t) => getFromStore(t, newest(store)),
1124
- set: (t, newValue) => {
1125
- setIntoStore(t, newValue, newest(store));
1126
- },
1127
- seek: (t, k) => seekInStore(t, k, newest(store)),
1128
- json: (t) => getJsonToken(t, newest(store)),
1129
- run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
1130
- make: (ctx, f, k, ...args) => makeMoleculeInStore(newest(store), ctx, f, k, ...args),
1131
- dispose: (t) => {
1132
- disposeFromStore(t, newest(store));
1133
- },
1134
- env: () => getEnvironmentData(newest(store)),
1135
- bond: (f) => growMoleculeInStore(
1136
- molecule,
1137
- withdraw(f, store),
1138
- newest(store)
1139
- ),
1140
- claim: (below, options) => {
1141
- const { exclusive } = options;
1142
- const belowMolecule = newest(store).molecules.get(json.stringifyJson(below.key));
1143
- if (belowMolecule) {
1144
- if (exclusive) {
1145
- for (const value of belowMolecule.above.values()) {
1146
- value.below.delete(belowMolecule.stringKey);
1147
- }
1148
- belowMolecule.above.clear();
1149
- belowMolecule.above.set(molecule.stringKey, molecule);
1150
- molecule.below.set(belowMolecule.stringKey, belowMolecule);
1151
- } else {
1152
- belowMolecule.above.set(molecule.stringKey, molecule);
1153
- molecule.below.set(belowMolecule.stringKey, belowMolecule);
1154
- }
818
+ return rootKeys;
819
+ };
820
+ var traceAllSelectorAtoms = (selector, store) => {
821
+ const selectorKey = selector.key;
822
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
823
+ return directDependencyKeys.flatMap(
824
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
825
+ );
826
+ };
827
+
828
+ // internal/src/selector/update-selector-atoms.ts
829
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
830
+ const target = newest(store);
831
+ if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
832
+ target.selectorAtoms.set({
833
+ selectorKey,
834
+ atomKey: dependency.key
835
+ });
836
+ store.logger.info(
837
+ `\u{1F50D}`,
838
+ `selector`,
839
+ selectorKey,
840
+ `discovers root atom "${dependency.key}"`
841
+ );
842
+ } else {
843
+ const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
844
+ store.logger.info(
845
+ `\u{1F50D}`,
846
+ `selector`,
847
+ selectorKey,
848
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
849
+ );
850
+ for (const atomKey of rootKeys) {
851
+ target.selectorAtoms = target.selectorAtoms.set({
852
+ selectorKey,
853
+ atomKey
854
+ });
855
+ }
856
+ }
857
+ };
858
+
859
+ // internal/src/selector/register-selector.ts
860
+ var registerSelector = (selectorKey, store) => ({
861
+ get: (dependency) => {
862
+ const target = newest(store);
863
+ if (dependency.type === `molecule`) {
864
+ return getFromStore(dependency, store);
865
+ }
866
+ const dependencyState = withdraw(dependency, store);
867
+ const dependencyValue = readOrComputeValue(dependencyState, store);
868
+ store.logger.info(
869
+ `\u{1F50C}`,
870
+ `selector`,
871
+ selectorKey,
872
+ `registers dependency ( "${dependency.key}" =`,
873
+ dependencyValue,
874
+ `)`
875
+ );
876
+ target.selectorGraph.set(
877
+ {
878
+ upstreamSelectorKey: dependency.key,
879
+ downstreamSelectorKey: selectorKey
880
+ },
881
+ {
882
+ source: dependency.key
1155
883
  }
1156
- },
1157
- join: (joinToken) => {
1158
- const join = data.getJoin(joinToken, store);
1159
- join.molecules.set(json.stringifyJson(key), molecule);
1160
- molecule.joins.set(joinToken.key, join);
1161
- return joinToken;
1162
- },
1163
- spawn: (f, k, ...p) => makeMoleculeInStore(
1164
- newest(store),
1165
- [molecule],
1166
- withdraw(f, store),
1167
- k,
1168
- ...p
1169
- )
884
+ );
885
+ updateSelectorAtoms(selectorKey, dependency, store);
886
+ return dependencyValue;
887
+ },
888
+ set: (WritableToken, newValue) => {
889
+ const target = newest(store);
890
+ const state = withdraw(WritableToken, target);
891
+ setAtomOrSelector(state, newValue, target);
892
+ },
893
+ find: (token, key) => findInStore(token, key, store),
894
+ seek: (token, key) => seekInStore(token, key, store),
895
+ json: (token) => getJsonToken(token, store)
896
+ });
897
+
898
+ // internal/src/selector/create-readonly-selector.ts
899
+ var createReadonlySelector = (options, family, store) => {
900
+ const target = newest(store);
901
+ const subject = new Subject();
902
+ const { get, find, seek, json } = registerSelector(options.key, target);
903
+ const getSelf = () => {
904
+ const value = options.get({ get, find, seek, json });
905
+ cacheValue(options.key, value, subject, newest(store));
906
+ return value;
1170
907
  };
1171
- const Constructor = family.new;
1172
- molecule.instance = new Constructor(transactors, token.key, ...params);
1173
- const update = {
1174
- type: `molecule_creation`,
1175
- token,
1176
- family,
1177
- context: contextArray,
1178
- params
908
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
909
+ subject,
910
+ install: (s) => createReadonlySelector(options, family, s),
911
+ get: getSelf,
912
+ type: `readonly_selector`
913
+ }), family && { family });
914
+ target.readonlySelectors.set(options.key, readonlySelector);
915
+ const initialValue = getSelf();
916
+ store.logger.info(
917
+ `\u2728`,
918
+ readonlySelector.type,
919
+ readonlySelector.key,
920
+ `=`,
921
+ initialValue
922
+ );
923
+ const token = {
924
+ key: options.key,
925
+ type: `readonly_selector`
1179
926
  };
1180
- const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
1181
- if (isTransaction) {
1182
- target.transactionMeta.update.updates.push(update);
1183
- } else {
1184
- family.subject.next(update);
927
+ if (family) {
928
+ token.family = family;
1185
929
  }
1186
930
  return token;
1187
- }
931
+ };
1188
932
 
1189
- // internal/src/ingest-updates/ingest-creation-disposal.ts
1190
- function ingestCreationEvent(update, applying, store) {
1191
- switch (applying) {
1192
- case `newValue`: {
1193
- createInStore(update.token, store);
1194
- break;
1195
- }
1196
- case `oldValue`: {
1197
- disposeFromStore(update.token, store);
1198
- break;
933
+ // internal/src/selector/create-writable-selector.ts
934
+ var createWritableSelector = (options, family, store) => {
935
+ const target = newest(store);
936
+ const subject = new Subject();
937
+ const transactors = registerSelector(options.key, target);
938
+ const { find, get, seek, json } = transactors;
939
+ const readonlyTransactors = { find, get, seek, json };
940
+ const getSelf = (innerTarget = newest(store)) => {
941
+ const value = options.get(readonlyTransactors);
942
+ cacheValue(options.key, value, subject, innerTarget);
943
+ return value;
944
+ };
945
+ const setSelf = (next) => {
946
+ const innerTarget = newest(store);
947
+ const oldValue = getSelf(innerTarget);
948
+ const newValue = become(next)(oldValue);
949
+ store.logger.info(
950
+ `\u{1F4DD}`,
951
+ `selector`,
952
+ options.key,
953
+ `set (`,
954
+ oldValue,
955
+ `->`,
956
+ newValue,
957
+ `)`
958
+ );
959
+ cacheValue(options.key, newValue, subject, innerTarget);
960
+ markDone(options.key, innerTarget);
961
+ if (isRootStore(innerTarget)) {
962
+ subject.next({ newValue, oldValue });
1199
963
  }
964
+ options.set(transactors, newValue);
965
+ };
966
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
967
+ subject,
968
+ install: (s) => createWritableSelector(options, family, s),
969
+ get: getSelf,
970
+ set: setSelf,
971
+ type: `selector`
972
+ }), family && { family });
973
+ target.selectors.set(options.key, mySelector);
974
+ const initialValue = getSelf();
975
+ store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
976
+ const token = {
977
+ key: options.key,
978
+ type: `selector`
979
+ };
980
+ if (family) {
981
+ token.family = family;
982
+ }
983
+ return token;
984
+ };
985
+
986
+ // internal/src/selector/create-standalone-selector.ts
987
+ function createStandaloneSelector(options, store) {
988
+ const isWritable = `set` in options;
989
+ if (isWritable) {
990
+ const state2 = createWritableSelector(options, void 0, store);
991
+ store.on.selectorCreation.next(state2);
992
+ return state2;
1200
993
  }
994
+ const state = createReadonlySelector(options, void 0, store);
995
+ store.on.selectorCreation.next(state);
996
+ return state;
1201
997
  }
1202
- function ingestDisposalEvent(update, applying, store) {
1203
- switch (applying) {
1204
- case `newValue`: {
1205
- disposeFromStore(update.token, store);
1206
- break;
998
+
999
+ // internal/src/selector/dispose-selector.ts
1000
+ function disposeSelector(selectorToken, store) {
1001
+ var _a;
1002
+ const target = newest(store);
1003
+ const { key } = selectorToken;
1004
+ const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1005
+ if (!selector) {
1006
+ store.logger.info(
1007
+ `\u274C`,
1008
+ `selector`,
1009
+ key,
1010
+ `Tried to dispose selector, but it does not exist in the store.`
1011
+ );
1012
+ } else if (!selector.family) {
1013
+ store.logger.error(
1014
+ `\u274C`,
1015
+ `selector`,
1016
+ key,
1017
+ `Standalone selectors cannot be disposed.`
1018
+ );
1019
+ } else {
1020
+ const molecule = target.molecules.get(selector.family.subKey);
1021
+ if (molecule) {
1022
+ molecule.tokens.delete(key);
1207
1023
  }
1208
- case `oldValue`: {
1209
- createInStore(update.token, store);
1210
- store.valueMap.set(update.token.key, update.value);
1211
- break;
1024
+ switch (selectorToken.type) {
1025
+ case `selector`:
1026
+ {
1027
+ target.selectors.delete(key);
1028
+ const family = withdraw(
1029
+ { key: selector.family.key, type: `selector_family` },
1030
+ store
1031
+ );
1032
+ family.subject.next({
1033
+ type: `state_disposal`,
1034
+ token: selectorToken
1035
+ });
1036
+ }
1037
+ break;
1038
+ case `readonly_selector`:
1039
+ {
1040
+ target.readonlySelectors.delete(key);
1041
+ const family = withdraw(
1042
+ { key: selector.family.key, type: `readonly_selector_family` },
1043
+ store
1044
+ );
1045
+ family.subject.next({
1046
+ type: `state_disposal`,
1047
+ token: selectorToken
1048
+ });
1049
+ }
1050
+ break;
1212
1051
  }
1213
- }
1214
- }
1215
- function createInStore(token, store) {
1216
- if (token.family) {
1217
- const family = store.families.get(token.family.key);
1218
- if (family) {
1219
- const molecule = store.molecules.get(token.family.subKey);
1220
- if (molecule) {
1221
- growMoleculeInStore(molecule, family, store);
1222
- return;
1052
+ target.valueMap.delete(key);
1053
+ target.selectorAtoms.delete(key);
1054
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1055
+ ([downstreamSelectorKey]) => {
1056
+ var _a2;
1057
+ return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1223
1058
  }
1224
- if (store.config.lifespan === `immortal`) {
1225
- throw new Error(`No molecule found for key "${token.family.subKey}"`);
1059
+ );
1060
+ for (const downstreamToken of downstreamTokens) {
1061
+ if (downstreamToken) {
1062
+ disposeSelector(downstreamToken, store);
1226
1063
  }
1227
- initFamilyMemberInStore(family, json.parseJson(token.family.subKey), store);
1064
+ }
1065
+ target.selectorGraph.delete(key);
1066
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1067
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1068
+ target.transactionMeta.update.updates.push({
1069
+ type: `state_disposal`,
1070
+ token: selectorToken
1071
+ });
1072
+ } else {
1073
+ store.on.selectorDisposal.next(selectorToken);
1228
1074
  }
1229
1075
  }
1230
1076
  }
1231
- function ingestMoleculeCreationEvent(update, applying, store) {
1232
- switch (applying) {
1233
- case `newValue`:
1234
- makeMoleculeInStore(
1235
- store,
1236
- update.context[0],
1237
- update.family,
1238
- update.token.key,
1239
- ...update.params
1077
+
1078
+ // internal/src/families/create-readonly-selector-family.ts
1079
+ function createReadonlySelectorFamily(options, store) {
1080
+ const subject = new Subject();
1081
+ const readonlySelectorFamily = Object.assign(
1082
+ (key) => {
1083
+ const subKey = json.stringifyJson(key);
1084
+ const family = { key: options.key, subKey };
1085
+ const fullKey = `${options.key}(${subKey})`;
1086
+ const target = newest(store);
1087
+ const token = createReadonlySelector(
1088
+ {
1089
+ key: fullKey,
1090
+ get: options.get(key)
1091
+ },
1092
+ family,
1093
+ target
1240
1094
  );
1241
- break;
1242
- case `oldValue`:
1243
- disposeFromStore(update.token, store);
1244
- break;
1245
- }
1095
+ subject.next({ type: `state_creation`, token });
1096
+ return token;
1097
+ },
1098
+ {
1099
+ key: options.key,
1100
+ type: `readonly_selector_family`,
1101
+ subject,
1102
+ install: (s) => createReadonlySelectorFamily(options, s)
1103
+ }
1104
+ );
1105
+ store.families.set(options.key, readonlySelectorFamily);
1106
+ return readonlySelectorFamily;
1246
1107
  }
1247
- function ingestMoleculeDisposalEvent(update, applying, store) {
1248
- switch (applying) {
1249
- case `newValue`:
1250
- disposeFromStore(update.token, store);
1251
- break;
1252
- case `oldValue`:
1253
- makeMoleculeInStore(
1254
- store,
1255
- update.context[0],
1256
- update.family,
1257
- update.token.key
1108
+ function createWritableSelectorFamily(options, store) {
1109
+ const subject = new Subject();
1110
+ const selectorFamily = Object.assign(
1111
+ (key) => {
1112
+ const subKey = json.stringifyJson(key);
1113
+ const family = { key: options.key, subKey };
1114
+ const fullKey = `${options.key}(${subKey})`;
1115
+ const target = newest(store);
1116
+ const token = createWritableSelector(
1117
+ {
1118
+ key: fullKey,
1119
+ get: options.get(key),
1120
+ set: options.set(key)
1121
+ },
1122
+ family,
1123
+ target
1258
1124
  );
1259
- break;
1260
- }
1125
+ subject.next({ type: `state_creation`, token });
1126
+ return token;
1127
+ },
1128
+ {
1129
+ key: options.key,
1130
+ type: `selector_family`,
1131
+ subject,
1132
+ install: (s) => createWritableSelectorFamily(options, s)
1133
+ }
1134
+ );
1135
+ store.families.set(options.key, selectorFamily);
1136
+ return selectorFamily;
1261
1137
  }
1262
1138
 
1263
- // internal/src/ingest-updates/ingest-selector-update.ts
1264
- function ingestSelectorUpdate(applying, selectorUpdate, store) {
1265
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1266
- for (const atomUpdate of updates) {
1267
- ingestAtomUpdate(applying, atomUpdate, store);
1139
+ // internal/src/families/create-selector-family.ts
1140
+ function createSelectorFamily(options, store) {
1141
+ const isWritable = `set` in options;
1142
+ if (isWritable) {
1143
+ return createWritableSelectorFamily(options, store);
1268
1144
  }
1145
+ return createReadonlySelectorFamily(options, store);
1269
1146
  }
1270
1147
 
1271
- // internal/src/ingest-updates/ingest-transaction-update.ts
1272
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1273
- const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1274
- for (const updateFromTransaction of updates) {
1275
- switch (updateFromTransaction.type) {
1276
- case `atom_update`:
1277
- case `selector_update`:
1278
- ingestAtomUpdate(applying, updateFromTransaction, store);
1279
- break;
1280
- case `state_creation`:
1281
- ingestCreationEvent(updateFromTransaction, applying, store);
1282
- break;
1283
- case `state_disposal`:
1284
- ingestDisposalEvent(updateFromTransaction, applying, store);
1285
- break;
1286
- case `molecule_creation`:
1287
- ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1288
- break;
1289
- case `molecule_disposal`:
1290
- ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1291
- break;
1292
- case `transaction_update`:
1293
- ingestTransactionUpdate(applying, updateFromTransaction, store);
1294
- break;
1148
+ // internal/src/molecule/dispose-molecule.ts
1149
+ function disposeMolecule(token, store) {
1150
+ var _a;
1151
+ let molecule;
1152
+ try {
1153
+ molecule = withdraw(token, store);
1154
+ } catch (thrown) {
1155
+ if (thrown instanceof Error) {
1156
+ store.logger.error(
1157
+ `\u{1F41E}`,
1158
+ `molecule`,
1159
+ JSON.stringify(token.key),
1160
+ `Failed to dispose molecule, because it was not found in the store.`,
1161
+ thrown.message
1162
+ );
1295
1163
  }
1296
- }
1297
- }
1298
-
1299
- // internal/src/transaction/set-epoch-number.ts
1300
- function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
1301
- const isRoot = isRootStore(store);
1302
- if (isRoot && continuityKey) {
1303
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
1304
- }
1305
- }
1306
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1307
- const isRoot = isRootStore(store);
1308
- if (!isRoot) {
1309
1164
  return;
1310
1165
  }
1311
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1312
- if (continuityKey !== void 0) {
1313
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
1166
+ const { family } = token;
1167
+ const context = [];
1168
+ for (const above of molecule.above.values()) {
1169
+ context.push(deposit(above));
1314
1170
  }
1315
- }
1316
-
1317
- // internal/src/transaction/apply-transaction.ts
1318
- var applyTransaction = (output, store) => {
1319
- var _a;
1320
- const child = newest(store);
1321
- const { parent } = child;
1322
- if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
1323
- store.logger.warn(
1324
- `\u{1F41E}`,
1325
- `transaction`,
1326
- `???`,
1327
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1328
- );
1329
- return;
1171
+ const values = [];
1172
+ for (const stateToken of molecule.tokens.values()) {
1173
+ const tokenFamily = stateToken.family;
1174
+ values.push([tokenFamily.key, store.valueMap.get(stateToken.key)]);
1330
1175
  }
1331
- child.transactionMeta.phase = `applying`;
1332
- child.transactionMeta.update.output = output;
1333
- parent.child = null;
1334
- parent.on.transactionApplying.next(child.transactionMeta);
1335
- const { updates } = child.transactionMeta.update;
1336
- store.logger.info(
1337
- `\u{1F6C4}`,
1338
- `transaction`,
1339
- child.transactionMeta.update.key,
1340
- `Applying transaction with ${updates.length} updates:`,
1341
- updates
1342
- );
1343
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1344
- if (isRootStore(parent)) {
1345
- setEpochNumberOfAction(
1346
- child.transactionMeta.update.key,
1347
- child.transactionMeta.update.epoch,
1348
- parent
1349
- );
1350
- const myTransaction = withdraw(
1351
- { key: child.transactionMeta.update.key, type: `transaction` },
1352
- store
1353
- );
1354
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
1355
- store.logger.info(
1356
- `\u{1F6EC}`,
1357
- `transaction`,
1358
- child.transactionMeta.update.key,
1359
- `Finished applying transaction.`
1360
- );
1361
- } else if (isChildStore(parent)) {
1362
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1363
- }
1364
- parent.on.transactionApplying.next(null);
1365
- };
1366
-
1367
- // internal/src/transaction/assign-transaction-to-continuity.ts
1368
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1369
- const isRoot = isRootStore(store);
1370
- if (!isRoot) {
1371
- return;
1372
- }
1373
- const { epoch, actionContinuities } = store.transactionMeta;
1374
- actionContinuities.set(continuityKey, transactionKey);
1375
- if (!epoch.has(continuityKey)) {
1376
- epoch.set(continuityKey, -1);
1377
- }
1378
- }
1379
-
1380
- // internal/src/lazy-map.ts
1381
- var LazyMap = class extends Map {
1382
- constructor(source) {
1383
- super();
1384
- this.source = source;
1385
- this.deleted = /* @__PURE__ */ new Set();
1386
- }
1387
- get(key) {
1388
- const has = super.has(key);
1389
- if (has) {
1390
- return super.get(key);
1391
- }
1392
- if (!this.deleted.has(key) && this.source.has(key)) {
1393
- const value = this.source.get(key);
1394
- return value;
1395
- }
1396
- return void 0;
1397
- }
1398
- set(key, value) {
1399
- this.deleted.delete(key);
1400
- return super.set(key, value);
1401
- }
1402
- hasOwn(key) {
1403
- return super.has(key);
1404
- }
1405
- has(key) {
1406
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1407
- }
1408
- delete(key) {
1409
- this.deleted.add(key);
1410
- return super.delete(key);
1411
- }
1412
- };
1413
-
1414
- // internal/src/transaction/build-transaction.ts
1415
- var buildTransaction = (key, params, store, id) => {
1416
- const parent = newest(store);
1417
- const childBase = {
1418
- parent,
1419
- child: null,
1420
- on: parent.on,
1421
- loggers: parent.loggers,
1422
- logger: parent.logger,
1423
- config: parent.config,
1424
- atoms: new LazyMap(parent.atoms),
1425
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1426
- families: new LazyMap(parent.families),
1427
- operation: { open: false },
1428
- readonlySelectors: new LazyMap(parent.readonlySelectors),
1429
- timelines: new LazyMap(parent.timelines),
1430
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
1431
- trackers: /* @__PURE__ */ new Map(),
1432
- transactions: new LazyMap(parent.transactions),
1433
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1434
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1435
- makeContentKey: (...keys) => keys.sort().join(`:`)
1436
- }),
1437
- selectors: new LazyMap(parent.selectors),
1438
- valueMap: new LazyMap(parent.valueMap),
1439
- molecules: new LazyMap(parent.molecules),
1440
- moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1441
- miscResources: new LazyMap(parent.miscResources)
1442
- };
1443
- const epoch = getEpochNumberOfAction(key, store);
1444
- const transactionMeta = {
1445
- phase: `building`,
1446
- update: {
1447
- type: `transaction_update`,
1448
- key,
1449
- id,
1450
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1451
- updates: [],
1452
- params,
1453
- output: void 0
1454
- },
1455
- transactors: {
1456
- get: (token) => getFromStore(token, child),
1457
- set: (token, value) => {
1458
- setIntoStore(token, value, child);
1459
- },
1460
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1461
- find: (token, k) => findInStore(token, k, child),
1462
- seek: (token, k) => seekInStore(token, k, child),
1463
- json: (token) => getJsonToken(token, child),
1464
- make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1465
- dispose: (token) => {
1466
- disposeFromStore(token, child);
1467
- },
1468
- env: () => getEnvironmentData(child)
1469
- }
1470
- };
1471
- const child = Object.assign(childBase, {
1472
- transactionMeta
1473
- });
1474
- parent.child = child;
1475
- store.logger.info(
1476
- `\u{1F6EB}`,
1477
- `transaction`,
1478
- key,
1479
- `Building transaction with params:`,
1480
- params
1481
- );
1482
- return child;
1483
- };
1484
-
1485
- // internal/src/transaction/create-transaction.ts
1486
- function createTransaction(options, store) {
1487
- const newTransaction = {
1488
- key: options.key,
1489
- type: `transaction`,
1490
- run: (params, id) => {
1491
- const childStore = buildTransaction(options.key, params, store, id);
1492
- try {
1493
- const target2 = newest(store);
1494
- const { transactors } = childStore.transactionMeta;
1495
- const output = options.do(transactors, ...params);
1496
- applyTransaction(output, target2);
1497
- return output;
1498
- } catch (thrown) {
1499
- abortTransaction(target);
1500
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1501
- throw thrown;
1502
- }
1503
- },
1504
- install: (s) => createTransaction(options, s),
1505
- subject: new Subject()
1506
- };
1507
- const target = newest(store);
1508
- target.transactions.set(newTransaction.key, newTransaction);
1509
- const token = deposit(newTransaction);
1510
- store.on.transactionCreation.next(token);
1511
- return token;
1512
- }
1513
-
1514
- // internal/src/transaction/get-epoch-number.ts
1515
- function getContinuityKey(transactionKey, store) {
1516
- const isRoot = isRootStore(store);
1517
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1518
- return continuity;
1519
- }
1520
- function getEpochNumberOfContinuity(continuityKey, store) {
1521
- const isRoot = isRootStore(store);
1522
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1523
- return epoch;
1524
- }
1525
- function getEpochNumberOfAction(transactionKey, store) {
1526
- const isRoot = isRootStore(store);
1527
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1528
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1529
- return epoch;
1530
- }
1531
-
1532
- // internal/src/transaction/index.ts
1533
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1534
-
1535
- // internal/src/molecule/dispose-molecule.ts
1536
- function disposeMolecule(token, store) {
1537
- var _a;
1538
- let molecule;
1539
- try {
1540
- molecule = withdraw(token, store);
1541
- } catch (thrown) {
1542
- if (thrown instanceof Error) {
1543
- store.logger.error(
1544
- `\u{1F41E}`,
1545
- `molecule`,
1546
- JSON.stringify(token.key),
1547
- `Failed to dispose molecule, because it was not found in the store.`,
1548
- thrown.message
1549
- );
1550
- }
1551
- return;
1552
- }
1553
- const { family } = token;
1554
- for (const state of molecule.tokens.values()) {
1555
- disposeFromStore(state, store);
1556
- }
1557
- for (const child of molecule.below.values()) {
1558
- if (((_a = child.family) == null ? void 0 : _a.dependsOn) === `all`) {
1559
- disposeMolecule(child, store);
1560
- } else {
1561
- child.above.delete(molecule.stringKey);
1562
- if (child.above.size === 0) {
1563
- disposeMolecule(child, store);
1564
- }
1565
- }
1566
- }
1567
- molecule.below.clear();
1568
1176
  if (family) {
1569
1177
  const Formula = withdraw(family, store);
1570
1178
  const disposalEvent = {
1571
1179
  type: `molecule_disposal`,
1572
1180
  token,
1573
1181
  family,
1574
- context: [...molecule.above.values()].map((m) => deposit(m)),
1575
- familyKeys: [...molecule.tokens.values()].map((t) => {
1576
- var _a2;
1577
- return (_a2 = t.family) == null ? void 0 : _a2.key;
1578
- }).filter((k) => typeof k === `string`)
1182
+ context,
1183
+ values
1579
1184
  };
1580
1185
  if (token.family) {
1581
1186
  disposalEvent.family = token.family;
1582
1187
  }
1188
+ for (const state of molecule.tokens.values()) {
1189
+ disposeFromStore(state, store);
1190
+ }
1191
+ for (const child of molecule.below.values()) {
1192
+ if (((_a = child.family) == null ? void 0 : _a.dependsOn) === `all`) {
1193
+ disposeMolecule(child, store);
1194
+ } else {
1195
+ child.above.delete(molecule.stringKey);
1196
+ if (child.above.size === 0) {
1197
+ disposeMolecule(child, store);
1198
+ }
1199
+ }
1200
+ }
1201
+ molecule.below.clear();
1583
1202
  const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1584
1203
  if (isTransaction) {
1585
1204
  store.transactionMeta.update.updates.push(disposalEvent);
@@ -1622,13 +1241,8 @@ function initFamilyMemberInStore(token, key, store) {
1622
1241
  }
1623
1242
  const state = family(key);
1624
1243
  const target = newest(store);
1625
- if (state.family) {
1626
- if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1627
- target.transactionMeta.update.updates.push({
1628
- type: `state_creation`,
1629
- token: state
1630
- });
1631
- } else {
1244
+ if (state.family && target.moleculeInProgress === null) {
1245
+ if (isRootStore(target)) {
1632
1246
  switch (state.type) {
1633
1247
  case `atom`:
1634
1248
  case `mutable_atom`:
@@ -1639,6 +1253,11 @@ function initFamilyMemberInStore(token, key, store) {
1639
1253
  store.on.selectorCreation.next(state);
1640
1254
  break;
1641
1255
  }
1256
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1257
+ target.transactionMeta.update.updates.push({
1258
+ type: `state_creation`,
1259
+ token: state
1260
+ });
1642
1261
  }
1643
1262
  }
1644
1263
  return state;
@@ -1686,291 +1305,701 @@ function findInStore(token, key, store) {
1686
1305
  return state;
1687
1306
  }
1688
1307
 
1689
- // internal/src/keys.ts
1690
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
1691
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1692
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1693
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1694
-
1695
- // internal/src/selector/get-selector-dependency-keys.ts
1696
- var getSelectorDependencyKeys = (key, store) => {
1697
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1698
- return sources;
1699
- };
1700
-
1701
- // internal/src/selector/trace-selector-atoms.ts
1702
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1703
- const rootKeys = [];
1704
- const indirectDependencyKeys = getSelectorDependencyKeys(
1705
- directDependencyKey,
1308
+ // internal/src/molecule/create-molecule-family.ts
1309
+ function createMoleculeFamily(options, store) {
1310
+ var _a;
1311
+ const subject = new Subject();
1312
+ const token = {
1313
+ type: `molecule_family`,
1314
+ key: options.key,
1315
+ dependsOn: (_a = options.dependsOn) != null ? _a : `all`
1316
+ };
1317
+ const family = __spreadProps(__spreadValues({}, token), {
1318
+ subject,
1319
+ new: options.new
1320
+ });
1321
+ store.moleculeFamilies.set(options.key, family);
1322
+ return token;
1323
+ }
1324
+
1325
+ // internal/src/molecule/grow-molecule-in-store.ts
1326
+ function growMoleculeInStore(molecule, family, store) {
1327
+ const stateToken = initFamilyMemberInStore(family, molecule.key, store);
1328
+ molecule.tokens.set(stateToken.key, stateToken);
1329
+ const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1330
+ const moleculeInProgress = store.moleculeInProgress === molecule.key;
1331
+ if (!isTransaction && !moleculeInProgress) {
1332
+ molecule.subject.next({ type: `state_creation`, token: stateToken });
1333
+ }
1334
+ return stateToken;
1335
+ }
1336
+
1337
+ // internal/src/get-environment-data.ts
1338
+ function getEnvironmentData(store) {
1339
+ return {
1706
1340
  store
1707
- );
1708
- let depth = 0;
1709
- while (indirectDependencyKeys.length > 0) {
1710
- const indirectDependencyKey = indirectDependencyKeys.shift();
1711
- ++depth;
1712
- if (depth > 99999) {
1713
- throw new Error(
1714
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1715
- );
1341
+ };
1342
+ }
1343
+ var Molecule = class {
1344
+ constructor(ctx, key, family) {
1345
+ this.key = key;
1346
+ this.type = `molecule`;
1347
+ this.subject = new Subject();
1348
+ this.tokens = /* @__PURE__ */ new Map();
1349
+ this.above = /* @__PURE__ */ new Map();
1350
+ this.below = /* @__PURE__ */ new Map();
1351
+ this.joins = /* @__PURE__ */ new Map();
1352
+ this.stringKey = json.stringifyJson(key);
1353
+ if (family) {
1354
+ this.family = family;
1716
1355
  }
1717
- if (!isAtomKey(indirectDependencyKey, store)) {
1718
- indirectDependencyKeys.push(
1719
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
1720
- );
1721
- } else if (!rootKeys.includes(indirectDependencyKey)) {
1722
- rootKeys.push(indirectDependencyKey);
1356
+ if (ctx) {
1357
+ if (Array.isArray(ctx)) {
1358
+ for (const molecule of ctx) {
1359
+ this.above.set(molecule.stringKey, molecule);
1360
+ }
1361
+ } else {
1362
+ this.above.set(ctx.stringKey, ctx);
1363
+ }
1723
1364
  }
1724
1365
  }
1725
- return rootKeys;
1726
- };
1727
- var traceAllSelectorAtoms = (selector, store) => {
1728
- const selectorKey = selector.key;
1729
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1730
- return directDependencyKeys.flatMap(
1731
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1732
- );
1733
1366
  };
1734
1367
 
1735
- // internal/src/selector/update-selector-atoms.ts
1736
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
1368
+ // internal/src/molecule/make-molecule-in-store.ts
1369
+ function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1737
1370
  const target = newest(store);
1738
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1739
- target.selectorAtoms.set({
1740
- selectorKey,
1741
- atomKey: dependency.key
1742
- });
1743
- store.logger.info(
1744
- `\u{1F50D}`,
1745
- `selector`,
1746
- selectorKey,
1747
- `discovers root atom "${dependency.key}"`
1748
- );
1749
- } else {
1750
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1751
- store.logger.info(
1752
- `\u{1F50D}`,
1753
- `selector`,
1754
- selectorKey,
1755
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1756
- );
1757
- for (const atomKey of rootKeys) {
1758
- target.selectorAtoms = target.selectorAtoms.set({
1759
- selectorKey,
1760
- atomKey
1761
- });
1371
+ target.moleculeInProgress = key;
1372
+ const contextArray = Array.isArray(context) ? context : [context];
1373
+ const owners = contextArray.map((ctx) => {
1374
+ if (ctx instanceof Molecule) {
1375
+ return ctx;
1762
1376
  }
1377
+ const stringKey = json.stringifyJson(ctx.key);
1378
+ const molecule2 = store.molecules.get(stringKey);
1379
+ if (!molecule2) {
1380
+ throw new Error(
1381
+ `Molecule ${stringKey} not found in store "${store.config.name}"`
1382
+ );
1383
+ }
1384
+ return molecule2;
1385
+ });
1386
+ const molecule = new Molecule(owners, key, familyToken);
1387
+ target.molecules.set(json.stringifyJson(key), molecule);
1388
+ for (const owner of owners) {
1389
+ owner.below.set(molecule.stringKey, molecule);
1763
1390
  }
1764
- };
1765
-
1766
- // internal/src/selector/register-selector.ts
1767
- var registerSelector = (selectorKey, store) => ({
1768
- get: (dependency) => {
1769
- const target = newest(store);
1770
- const dependencyState = withdraw(dependency, store);
1771
- const dependencyValue = readOrComputeValue(dependencyState, store);
1772
- store.logger.info(
1773
- `\u{1F50C}`,
1774
- `selector`,
1775
- selectorKey,
1776
- `registers dependency ( "${dependency.key}" =`,
1777
- dependencyValue,
1778
- `)`
1779
- );
1780
- target.selectorGraph.set(
1781
- {
1782
- upstreamSelectorKey: dependency.key,
1783
- downstreamSelectorKey: selectorKey
1784
- },
1785
- {
1786
- source: dependency.key
1391
+ const transactors = {
1392
+ get: (t) => getFromStore(t, newest(store)),
1393
+ set: (t, newValue) => {
1394
+ setIntoStore(t, newValue, newest(store));
1395
+ },
1396
+ seek: (t, k) => seekInStore(t, k, newest(store)),
1397
+ json: (t) => getJsonToken(t, newest(store)),
1398
+ run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
1399
+ make: (ctx, f, k, ...args) => makeMoleculeInStore(newest(store), ctx, f, k, ...args),
1400
+ dispose: (t) => {
1401
+ disposeFromStore(t, newest(store));
1402
+ },
1403
+ env: () => getEnvironmentData(newest(store)),
1404
+ bond: (f) => growMoleculeInStore(
1405
+ molecule,
1406
+ withdraw(f, store),
1407
+ newest(store)
1408
+ ),
1409
+ claim: (below, options) => {
1410
+ const { exclusive } = options;
1411
+ const belowMolecule = newest(store).molecules.get(json.stringifyJson(below.key));
1412
+ if (belowMolecule) {
1413
+ if (exclusive) {
1414
+ for (const value of belowMolecule.above.values()) {
1415
+ value.below.delete(belowMolecule.stringKey);
1416
+ }
1417
+ belowMolecule.above.clear();
1418
+ belowMolecule.above.set(molecule.stringKey, molecule);
1419
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1420
+ } else {
1421
+ belowMolecule.above.set(molecule.stringKey, molecule);
1422
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1423
+ }
1787
1424
  }
1788
- );
1789
- updateSelectorAtoms(selectorKey, dependency, store);
1790
- return dependencyValue;
1791
- },
1792
- set: (WritableToken, newValue) => {
1793
- const state = withdraw(WritableToken, store);
1794
- setAtomOrSelector(state, newValue, store);
1795
- },
1796
- find: (token, key) => findInStore(token, key, store),
1797
- seek: (token, key) => seekInStore(token, key, store),
1798
- json: (token) => getJsonToken(token, store)
1799
- });
1800
-
1801
- // internal/src/selector/create-readonly-selector.ts
1802
- var createReadonlySelector = (options, family, store) => {
1803
- const target = newest(store);
1804
- const subject = new Subject();
1805
- const { get, find, seek, json } = registerSelector(options.key, target);
1806
- const getSelf = () => {
1807
- const value = options.get({ get, find, seek, json });
1808
- cacheValue(options.key, value, subject, newest(store));
1809
- return value;
1425
+ },
1426
+ join: (joinToken) => {
1427
+ const join = data.getJoin(joinToken, store);
1428
+ join.molecules.set(json.stringifyJson(key), molecule);
1429
+ molecule.joins.set(joinToken.key, join);
1430
+ return joinToken;
1431
+ },
1432
+ spawn: (f, k, ...p) => makeMoleculeInStore(
1433
+ newest(store),
1434
+ [molecule],
1435
+ withdraw(f, store),
1436
+ k,
1437
+ ...p
1438
+ )
1810
1439
  };
1811
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1812
- subject,
1813
- install: (s) => createReadonlySelector(options, family, s),
1814
- get: getSelf,
1815
- type: `readonly_selector`
1816
- }), family && { family });
1817
- target.readonlySelectors.set(options.key, readonlySelector);
1818
- const initialValue = getSelf();
1819
- store.logger.info(
1820
- `\u2728`,
1821
- readonlySelector.type,
1822
- readonlySelector.key,
1823
- `=`,
1824
- initialValue
1825
- );
1440
+ const family = withdraw(familyToken, store);
1441
+ const Constructor = family.new;
1442
+ molecule.instance = new Constructor(transactors, key, ...params);
1826
1443
  const token = {
1827
- key: options.key,
1828
- type: `readonly_selector`
1444
+ type: `molecule`,
1445
+ key,
1446
+ family: familyToken
1829
1447
  };
1830
- if (family) {
1831
- token.family = family;
1448
+ const update = {
1449
+ type: `molecule_creation`,
1450
+ token,
1451
+ family: familyToken,
1452
+ context: contextArray,
1453
+ params
1454
+ };
1455
+ if (isRootStore(target)) {
1456
+ family.subject.next(update);
1457
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1458
+ target.transactionMeta.update.updates.push(update);
1832
1459
  }
1460
+ target.moleculeInProgress = null;
1833
1461
  return token;
1834
- };
1462
+ }
1835
1463
 
1836
- // internal/src/selector/create-writable-selector.ts
1837
- var createWritableSelector = (options, family, store) => {
1838
- const target = newest(store);
1839
- const subject = new Subject();
1840
- const transactors = registerSelector(options.key, target);
1841
- const { find, get, seek, json } = transactors;
1842
- const readonlyTransactors = { find, get, seek, json };
1843
- const getSelf = () => {
1844
- const value = options.get(readonlyTransactors);
1845
- cacheValue(options.key, value, subject, newest(store));
1846
- return value;
1847
- };
1848
- const setSelf = (next) => {
1849
- const oldValue = getSelf();
1850
- const newValue = become(next)(oldValue);
1851
- store.logger.info(
1852
- `\u{1F4DD}`,
1853
- `selector`,
1854
- options.key,
1855
- `set (`,
1856
- oldValue,
1857
- `->`,
1858
- newValue,
1859
- `)`
1860
- );
1861
- cacheValue(options.key, newValue, subject, store);
1862
- markDone(options.key, store);
1863
- if (isRootStore(target)) {
1864
- subject.next({ newValue, oldValue });
1464
+ // internal/src/ingest-updates/ingest-creation-disposal.ts
1465
+ function ingestCreationEvent(update, applying, store) {
1466
+ switch (applying) {
1467
+ case `newValue`: {
1468
+ createInStore(update.token, store);
1469
+ break;
1470
+ }
1471
+ case `oldValue`: {
1472
+ disposeFromStore(update.token, store);
1473
+ break;
1865
1474
  }
1866
- options.set(transactors, newValue);
1867
- };
1868
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1869
- subject,
1870
- install: (s) => createWritableSelector(options, family, s),
1871
- get: getSelf,
1872
- set: setSelf,
1873
- type: `selector`
1874
- }), family && { family });
1875
- target.selectors.set(options.key, mySelector);
1876
- const initialValue = getSelf();
1877
- store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
1878
- const token = {
1879
- key: options.key,
1880
- type: `selector`
1881
- };
1882
- if (family) {
1883
- token.family = family;
1884
1475
  }
1885
- return token;
1886
- };
1476
+ }
1477
+ function ingestDisposalEvent(update, applying, store) {
1478
+ switch (applying) {
1479
+ case `newValue`: {
1480
+ disposeFromStore(update.token, store);
1481
+ break;
1482
+ }
1483
+ case `oldValue`: {
1484
+ createInStore(update.token, store);
1485
+ store.valueMap.set(update.token.key, update.value);
1486
+ break;
1487
+ }
1488
+ }
1489
+ }
1490
+ function createInStore(token, store) {
1491
+ if (token.family) {
1492
+ const family = store.families.get(token.family.key);
1493
+ if (family) {
1494
+ const molecule = store.molecules.get(token.family.subKey);
1495
+ if (molecule) {
1496
+ growMoleculeInStore(molecule, family, store);
1497
+ return;
1498
+ }
1499
+ if (store.config.lifespan === `immortal`) {
1500
+ throw new Error(`No molecule found for key "${token.family.subKey}"`);
1501
+ }
1502
+ initFamilyMemberInStore(family, json.parseJson(token.family.subKey), store);
1503
+ }
1504
+ }
1505
+ }
1506
+ function ingestMoleculeCreationEvent(update, applying, store) {
1507
+ switch (applying) {
1508
+ case `newValue`:
1509
+ makeMoleculeInStore(
1510
+ store,
1511
+ update.context,
1512
+ update.family,
1513
+ update.token.key,
1514
+ ...update.params
1515
+ );
1516
+ break;
1517
+ case `oldValue`:
1518
+ disposeFromStore(update.token, store);
1519
+ break;
1520
+ }
1521
+ }
1522
+ function ingestMoleculeDisposalEvent(update, applying, store) {
1523
+ switch (applying) {
1524
+ case `newValue`:
1525
+ disposeFromStore(update.token, store);
1526
+ break;
1527
+ case `oldValue`:
1528
+ {
1529
+ const moleculeToken = makeMoleculeInStore(
1530
+ store,
1531
+ update.context,
1532
+ update.family,
1533
+ update.token.key
1534
+ );
1535
+ for (const [familyKey, value] of update.values) {
1536
+ const memberKey = `${familyKey}(${json.stringifyJson(moleculeToken.key)})`;
1537
+ const molecule = withdraw(moleculeToken, store);
1538
+ const alreadyCreated = molecule.tokens.has(memberKey);
1539
+ const family = store.families.get(familyKey);
1540
+ if (family && !alreadyCreated) {
1541
+ growMoleculeInStore(molecule, family, store);
1542
+ }
1543
+ store.valueMap.set(memberKey, value);
1544
+ }
1545
+ }
1546
+ break;
1547
+ }
1548
+ }
1887
1549
 
1888
- // internal/src/selector/create-standalone-selector.ts
1889
- function createStandaloneSelector(options, store) {
1890
- const isWritable = `set` in options;
1891
- if (isWritable) {
1892
- const state2 = createWritableSelector(options, void 0, store);
1893
- store.on.selectorCreation.next(state2);
1894
- return state2;
1550
+ // internal/src/ingest-updates/ingest-selector-update.ts
1551
+ function ingestSelectorUpdate(applying, selectorUpdate, store) {
1552
+ const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1553
+ for (const atomUpdate of updates) {
1554
+ ingestAtomUpdate(applying, atomUpdate, store);
1895
1555
  }
1896
- const state = createReadonlySelector(options, void 0, store);
1897
- store.on.selectorCreation.next(state);
1898
- return state;
1899
1556
  }
1900
1557
 
1901
- // internal/src/selector/dispose-selector.ts
1902
- function disposeSelector(selectorToken, store) {
1558
+ // internal/src/ingest-updates/ingest-transaction-update.ts
1559
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1560
+ const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1561
+ for (const updateFromTransaction of updates) {
1562
+ switch (updateFromTransaction.type) {
1563
+ case `atom_update`:
1564
+ case `selector_update`:
1565
+ ingestAtomUpdate(applying, updateFromTransaction, store);
1566
+ break;
1567
+ case `state_creation`:
1568
+ ingestCreationEvent(updateFromTransaction, applying, store);
1569
+ break;
1570
+ case `state_disposal`:
1571
+ ingestDisposalEvent(updateFromTransaction, applying, store);
1572
+ break;
1573
+ case `molecule_creation`:
1574
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1575
+ break;
1576
+ case `molecule_disposal`:
1577
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1578
+ break;
1579
+ case `transaction_update`:
1580
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
1581
+ break;
1582
+ }
1583
+ }
1584
+ }
1585
+
1586
+ // internal/src/transaction/set-epoch-number.ts
1587
+ function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
1588
+ const isRoot = isRootStore(store);
1589
+ if (isRoot && continuityKey) {
1590
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1591
+ }
1592
+ }
1593
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1594
+ const isRoot = isRootStore(store);
1595
+ if (!isRoot) {
1596
+ return;
1597
+ }
1598
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1599
+ if (continuityKey !== void 0) {
1600
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1601
+ }
1602
+ }
1603
+
1604
+ // internal/src/transaction/apply-transaction.ts
1605
+ var applyTransaction = (output, store) => {
1903
1606
  var _a;
1904
- const target = newest(store);
1905
- const { key } = selectorToken;
1906
- const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1907
- if (!selector) {
1908
- store.logger.info(
1909
- `\u274C`,
1910
- `selector`,
1911
- key,
1912
- `Tried to dispose selector, but it does not exist in the store.`
1607
+ const child = newest(store);
1608
+ const { parent } = child;
1609
+ if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
1610
+ store.logger.warn(
1611
+ `\u{1F41E}`,
1612
+ `transaction`,
1613
+ `???`,
1614
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1913
1615
  );
1914
- } else if (!selector.family) {
1915
- store.logger.error(
1916
- `\u274C`,
1917
- `selector`,
1918
- key,
1919
- `Standalone selectors cannot be disposed.`
1616
+ return;
1617
+ }
1618
+ child.transactionMeta.phase = `applying`;
1619
+ child.transactionMeta.update.output = output;
1620
+ parent.child = null;
1621
+ parent.on.transactionApplying.next(child.transactionMeta);
1622
+ const { updates } = child.transactionMeta.update;
1623
+ store.logger.info(
1624
+ `\u{1F6C4}`,
1625
+ `transaction`,
1626
+ child.transactionMeta.update.key,
1627
+ `Applying transaction with ${updates.length} updates:`,
1628
+ updates
1629
+ );
1630
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1631
+ if (isRootStore(parent)) {
1632
+ setEpochNumberOfAction(
1633
+ child.transactionMeta.update.key,
1634
+ child.transactionMeta.update.epoch,
1635
+ parent
1920
1636
  );
1921
- } else {
1922
- switch (selectorToken.type) {
1923
- case `selector`:
1924
- {
1925
- target.selectors.delete(key);
1926
- const family = withdraw(
1927
- { key: selector.family.key, type: `selector_family` },
1928
- store
1929
- );
1930
- family.subject.next({
1931
- type: `state_disposal`,
1932
- token: selectorToken
1933
- });
1934
- }
1637
+ const myTransaction = withdraw(
1638
+ { key: child.transactionMeta.update.key, type: `transaction` },
1639
+ store
1640
+ );
1641
+ myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
1642
+ store.logger.info(
1643
+ `\u{1F6EC}`,
1644
+ `transaction`,
1645
+ child.transactionMeta.update.key,
1646
+ `Finished applying transaction.`
1647
+ );
1648
+ } else if (isChildStore(parent)) {
1649
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1650
+ }
1651
+ parent.on.transactionApplying.next(null);
1652
+ };
1653
+
1654
+ // internal/src/transaction/assign-transaction-to-continuity.ts
1655
+ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1656
+ const isRoot = isRootStore(store);
1657
+ if (!isRoot) {
1658
+ return;
1659
+ }
1660
+ const { epoch, actionContinuities } = store.transactionMeta;
1661
+ actionContinuities.set(continuityKey, transactionKey);
1662
+ if (!epoch.has(continuityKey)) {
1663
+ epoch.set(continuityKey, -1);
1664
+ }
1665
+ }
1666
+
1667
+ // internal/src/lazy-map.ts
1668
+ var LazyMap = class extends Map {
1669
+ constructor(source) {
1670
+ super();
1671
+ this.source = source;
1672
+ this.deleted = /* @__PURE__ */ new Set();
1673
+ }
1674
+ get(key) {
1675
+ const has = super.has(key);
1676
+ if (has) {
1677
+ return super.get(key);
1678
+ }
1679
+ if (!this.deleted.has(key) && this.source.has(key)) {
1680
+ const value = this.source.get(key);
1681
+ return value;
1682
+ }
1683
+ return void 0;
1684
+ }
1685
+ set(key, value) {
1686
+ this.deleted.delete(key);
1687
+ return super.set(key, value);
1688
+ }
1689
+ hasOwn(key) {
1690
+ return super.has(key);
1691
+ }
1692
+ has(key) {
1693
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1694
+ }
1695
+ delete(key) {
1696
+ this.deleted.add(key);
1697
+ return super.delete(key);
1698
+ }
1699
+ };
1700
+
1701
+ // internal/src/transaction/build-transaction.ts
1702
+ var buildTransaction = (key, params, store, id) => {
1703
+ const parent = newest(store);
1704
+ const childBase = {
1705
+ parent,
1706
+ child: null,
1707
+ on: parent.on,
1708
+ loggers: parent.loggers,
1709
+ logger: parent.logger,
1710
+ config: parent.config,
1711
+ atoms: new LazyMap(parent.atoms),
1712
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1713
+ families: new LazyMap(parent.families),
1714
+ operation: { open: false },
1715
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
1716
+ timelines: new LazyMap(parent.timelines),
1717
+ timelineTopics: new Junction(parent.timelineTopics.toJSON()),
1718
+ trackers: /* @__PURE__ */ new Map(),
1719
+ transactions: new LazyMap(parent.transactions),
1720
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1721
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1722
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1723
+ }),
1724
+ selectors: new LazyMap(parent.selectors),
1725
+ valueMap: new LazyMap(parent.valueMap),
1726
+ molecules: new LazyMap(parent.molecules),
1727
+ moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1728
+ moleculeInProgress: parent.moleculeInProgress,
1729
+ miscResources: new LazyMap(parent.miscResources)
1730
+ };
1731
+ const epoch = getEpochNumberOfAction(key, store);
1732
+ const transactionMeta = {
1733
+ phase: `building`,
1734
+ update: {
1735
+ type: `transaction_update`,
1736
+ key,
1737
+ id,
1738
+ epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1739
+ updates: [],
1740
+ params,
1741
+ output: void 0
1742
+ },
1743
+ transactors: {
1744
+ get: (token) => getFromStore(token, child),
1745
+ set: (token, value) => {
1746
+ setIntoStore(token, value, child);
1747
+ },
1748
+ run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1749
+ find: (token, k) => findInStore(token, k, child),
1750
+ seek: (token, k) => seekInStore(token, k, child),
1751
+ json: (token) => getJsonToken(token, child),
1752
+ make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1753
+ dispose: (token) => {
1754
+ disposeFromStore(token, child);
1755
+ },
1756
+ env: () => getEnvironmentData(child)
1757
+ }
1758
+ };
1759
+ const child = Object.assign(childBase, {
1760
+ transactionMeta
1761
+ });
1762
+ parent.child = child;
1763
+ store.logger.info(
1764
+ `\u{1F6EB}`,
1765
+ `transaction`,
1766
+ key,
1767
+ `Building transaction with params:`,
1768
+ params
1769
+ );
1770
+ return child;
1771
+ };
1772
+
1773
+ // internal/src/transaction/create-transaction.ts
1774
+ function createTransaction(options, store) {
1775
+ const newTransaction = {
1776
+ key: options.key,
1777
+ type: `transaction`,
1778
+ run: (params, id) => {
1779
+ const childStore = buildTransaction(options.key, params, store, id);
1780
+ try {
1781
+ const target2 = newest(store);
1782
+ const { transactors } = childStore.transactionMeta;
1783
+ const output = options.do(transactors, ...params);
1784
+ applyTransaction(output, target2);
1785
+ return output;
1786
+ } catch (thrown) {
1787
+ abortTransaction(target);
1788
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1789
+ throw thrown;
1790
+ }
1791
+ },
1792
+ install: (s) => createTransaction(options, s),
1793
+ subject: new Subject()
1794
+ };
1795
+ const target = newest(store);
1796
+ target.transactions.set(newTransaction.key, newTransaction);
1797
+ const token = deposit(newTransaction);
1798
+ store.on.transactionCreation.next(token);
1799
+ return token;
1800
+ }
1801
+
1802
+ // internal/src/transaction/get-epoch-number.ts
1803
+ function getContinuityKey(transactionKey, store) {
1804
+ const isRoot = isRootStore(store);
1805
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1806
+ return continuity;
1807
+ }
1808
+ function getEpochNumberOfContinuity(continuityKey, store) {
1809
+ const isRoot = isRootStore(store);
1810
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1811
+ return epoch;
1812
+ }
1813
+ function getEpochNumberOfAction(transactionKey, store) {
1814
+ const isRoot = isRootStore(store);
1815
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1816
+ const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1817
+ return epoch;
1818
+ }
1819
+
1820
+ // internal/src/transaction/index.ts
1821
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1822
+
1823
+ // internal/src/store/store.ts
1824
+ var Store = class {
1825
+ constructor(config, store = null) {
1826
+ this.parent = null;
1827
+ this.child = null;
1828
+ this.valueMap = /* @__PURE__ */ new Map();
1829
+ this.atoms = /* @__PURE__ */ new Map();
1830
+ this.selectors = /* @__PURE__ */ new Map();
1831
+ this.readonlySelectors = /* @__PURE__ */ new Map();
1832
+ this.atomsThatAreDefault = /* @__PURE__ */ new Set();
1833
+ this.selectorAtoms = new Junction({
1834
+ between: [`selectorKey`, `atomKey`],
1835
+ cardinality: `n:n`
1836
+ });
1837
+ this.selectorGraph = new Junction(
1838
+ {
1839
+ between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
1840
+ cardinality: `n:n`
1841
+ },
1842
+ {
1843
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1844
+ }
1845
+ );
1846
+ this.trackers = /* @__PURE__ */ new Map();
1847
+ this.families = /* @__PURE__ */ new Map();
1848
+ this.transactions = /* @__PURE__ */ new Map();
1849
+ this.transactionMeta = {
1850
+ epoch: /* @__PURE__ */ new Map(),
1851
+ actionContinuities: new Junction({
1852
+ between: [`continuity`, `action`],
1853
+ cardinality: `1:n`
1854
+ })
1855
+ };
1856
+ this.timelines = /* @__PURE__ */ new Map();
1857
+ this.timelineTopics = new Junction({
1858
+ between: [`timelineKey`, `topicKey`],
1859
+ cardinality: `1:n`
1860
+ });
1861
+ this.molecules = /* @__PURE__ */ new Map();
1862
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
1863
+ this.moleculeInProgress = null;
1864
+ this.miscResources = /* @__PURE__ */ new Map();
1865
+ this.on = {
1866
+ atomCreation: new Subject(),
1867
+ atomDisposal: new Subject(),
1868
+ selectorCreation: new Subject(),
1869
+ selectorDisposal: new Subject(),
1870
+ timelineCreation: new Subject(),
1871
+ transactionCreation: new Subject(),
1872
+ transactionApplying: new StatefulSubject(
1873
+ null
1874
+ ),
1875
+ operationClose: new Subject(),
1876
+ moleculeCreationStart: new Subject(),
1877
+ moleculeCreationDone: new Subject(),
1878
+ moleculeDisposal: new Subject()
1879
+ };
1880
+ this.operation = { open: false };
1881
+ this.config = {
1882
+ name: `IMPLICIT_STORE`,
1883
+ lifespan: `ephemeral`
1884
+ };
1885
+ this.loggers = [
1886
+ new atom_io.AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
1887
+ ];
1888
+ this.logger = {
1889
+ error: (...messages) => {
1890
+ for (const logger of this.loggers) logger.error(...messages);
1891
+ },
1892
+ info: (...messages) => {
1893
+ for (const logger of this.loggers) logger.info(...messages);
1894
+ },
1895
+ warn: (...messages) => {
1896
+ for (const logger of this.loggers) logger.warn(...messages);
1897
+ }
1898
+ };
1899
+ if (store !== null) {
1900
+ this.valueMap = new Map(store == null ? void 0 : store.valueMap);
1901
+ this.operation = __spreadValues({}, store == null ? void 0 : store.operation);
1902
+ if (isRootStore(store)) {
1903
+ this.transactionMeta = {
1904
+ epoch: new Map(store == null ? void 0 : store.transactionMeta.epoch),
1905
+ actionContinuities: new Junction(
1906
+ store == null ? void 0 : store.transactionMeta.actionContinuities.toJSON()
1907
+ )
1908
+ };
1909
+ }
1910
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
1911
+ for (const [, family] of store.families) {
1912
+ family.install(this);
1913
+ }
1914
+ const mutableHelpers = /* @__PURE__ */ new Set();
1915
+ for (const [, atom] of store.atoms) {
1916
+ if (mutableHelpers.has(atom.key)) {
1917
+ continue;
1918
+ }
1919
+ atom.install(this);
1920
+ if (atom.type === `mutable_atom`) {
1921
+ const originalJsonToken = getJsonToken(atom, store);
1922
+ const originalUpdateToken = getUpdateToken(atom);
1923
+ mutableHelpers.add(originalJsonToken.key);
1924
+ mutableHelpers.add(originalUpdateToken.key);
1925
+ }
1926
+ }
1927
+ for (const [, selector] of store.readonlySelectors) {
1928
+ selector.install(this);
1929
+ }
1930
+ for (const [, selector] of store.selectors) {
1931
+ if (mutableHelpers.has(selector.key)) {
1932
+ continue;
1933
+ }
1934
+ selector.install(this);
1935
+ }
1936
+ for (const [, tx] of store.transactions) {
1937
+ tx.install(this);
1938
+ }
1939
+ for (const [, timeline] of store.timelines) {
1940
+ timeline.install(this);
1941
+ }
1942
+ }
1943
+ }
1944
+ };
1945
+ var IMPLICIT = {
1946
+ STORE_INTERNAL: void 0,
1947
+ get STORE() {
1948
+ var _a;
1949
+ return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
1950
+ name: `IMPLICIT_STORE`,
1951
+ lifespan: `ephemeral`
1952
+ });
1953
+ }
1954
+ };
1955
+ var clearStore = (store) => {
1956
+ const { config } = store;
1957
+ for (const disposable of store.miscResources.values()) {
1958
+ disposable[Symbol.dispose]();
1959
+ }
1960
+ Object.assign(store, new Store(config));
1961
+ store.config = config;
1962
+ };
1963
+ function withdraw(token, store) {
1964
+ let withdrawn;
1965
+ let target = store;
1966
+ while (target !== null) {
1967
+ switch (token.type) {
1968
+ case `atom`:
1969
+ case `mutable_atom`:
1970
+ withdrawn = target.atoms.get(token.key);
1971
+ break;
1972
+ case `selector`:
1973
+ withdrawn = target.selectors.get(token.key);
1974
+ break;
1975
+ case `readonly_selector`:
1976
+ withdrawn = target.readonlySelectors.get(token.key);
1977
+ break;
1978
+ case `atom_family`:
1979
+ case `mutable_atom_family`:
1980
+ case `selector_family`:
1981
+ case `readonly_selector_family`:
1982
+ withdrawn = target.families.get(token.key);
1983
+ break;
1984
+ case `timeline`:
1985
+ withdrawn = target.timelines.get(token.key);
1986
+ break;
1987
+ case `transaction`:
1988
+ withdrawn = target.transactions.get(token.key);
1935
1989
  break;
1936
- case `readonly_selector`:
1937
- {
1938
- target.readonlySelectors.delete(key);
1939
- const family = withdraw(
1940
- { key: selector.family.key, type: `readonly_selector_family` },
1941
- store
1942
- );
1943
- family.subject.next({
1944
- type: `state_disposal`,
1945
- token: selectorToken
1946
- });
1947
- }
1990
+ case `molecule`:
1991
+ withdrawn = target.molecules.get(json.stringifyJson(token.key));
1992
+ break;
1993
+ case `molecule_family`:
1994
+ withdrawn = target.moleculeFamilies.get(token.key);
1948
1995
  break;
1949
1996
  }
1950
- target.valueMap.delete(key);
1951
- target.selectorAtoms.delete(key);
1952
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1953
- ([downstreamSelectorKey]) => {
1954
- var _a2;
1955
- return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1956
- }
1957
- );
1958
- for (const downstreamToken of downstreamTokens) {
1959
- if (downstreamToken) {
1960
- disposeSelector(downstreamToken, store);
1961
- }
1962
- }
1963
- target.selectorGraph.delete(key);
1964
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1965
- if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1966
- target.transactionMeta.update.updates.push({
1967
- type: `state_disposal`,
1968
- token: selectorToken
1969
- });
1970
- } else {
1971
- store.on.selectorDisposal.next(selectorToken);
1997
+ if (withdrawn) {
1998
+ return withdrawn;
1972
1999
  }
2000
+ target = target.child;
1973
2001
  }
2002
+ throw new NotFoundError(token, store);
1974
2003
  }
1975
2004
 
1976
2005
  // internal/src/subscribe/recall-state.ts
@@ -2167,7 +2196,7 @@ var Tracker = class {
2167
2196
  subscribeToState(
2168
2197
  latestUpdateState,
2169
2198
  ({ newValue, oldValue }) => {
2170
- const timelineId = target.timelineAtoms.getRelatedKey(
2199
+ const timelineId = target.timelineTopics.getRelatedKey(
2171
2200
  latestUpdateState.key
2172
2201
  );
2173
2202
  if (timelineId) {
@@ -2618,6 +2647,10 @@ function disposeAtom(atomToken, store) {
2618
2647
  token: atomToken,
2619
2648
  value: lastValue
2620
2649
  });
2650
+ const molecule = target.molecules.get(atom.family.subKey);
2651
+ if (molecule) {
2652
+ molecule.tokens.delete(key);
2653
+ }
2621
2654
  target.atoms.delete(key);
2622
2655
  target.valueMap.delete(key);
2623
2656
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -2631,7 +2664,7 @@ function disposeAtom(atomToken, store) {
2631
2664
  }
2632
2665
  target.selectorAtoms.delete(key);
2633
2666
  target.atomsThatAreDefault.delete(key);
2634
- target.timelineAtoms.delete(key);
2667
+ target.timelineTopics.delete(key);
2635
2668
  if (atomToken.type === `mutable_atom`) {
2636
2669
  const updateToken = getUpdateToken(atomToken);
2637
2670
  disposeAtom(updateToken, store);
@@ -2648,26 +2681,123 @@ function disposeAtom(atomToken, store) {
2648
2681
  }
2649
2682
  }
2650
2683
  }
2651
-
2652
- // internal/src/timeline/add-atom-to-timeline.ts
2653
- var addAtomToTimeline = (atomToken, tl, store) => {
2684
+ function createTimeline(options, store, data) {
2685
+ var _a;
2686
+ const tl = __spreadProps(__spreadValues({
2687
+ type: `timeline`,
2688
+ key: options.key,
2689
+ at: 0,
2690
+ timeTraveling: null,
2691
+ selectorTime: null,
2692
+ transactionKey: null
2693
+ }, data), {
2694
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2695
+ install: (s) => createTimeline(options, s, tl),
2696
+ subject: new Subject(),
2697
+ subscriptions: /* @__PURE__ */ new Map()
2698
+ });
2699
+ if (options.shouldCapture) {
2700
+ tl.shouldCapture = options.shouldCapture;
2701
+ }
2702
+ const timelineKey = options.key;
2703
+ const target = newest(store);
2704
+ for (const initialTopic of options.scope) {
2705
+ switch (initialTopic.type) {
2706
+ case `atom`:
2707
+ case `mutable_atom`:
2708
+ {
2709
+ const atomToken = initialTopic;
2710
+ const atomKey = atomToken.key;
2711
+ let existingTimelineKey = target.timelineTopics.getRelatedKey(atomKey);
2712
+ if (`family` in atomToken) {
2713
+ const familyKey = atomToken.family.key;
2714
+ existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2715
+ if (existingTimelineKey) {
2716
+ store.logger.error(
2717
+ `\u274C`,
2718
+ `timeline`,
2719
+ options.key,
2720
+ `Failed to add atom "${atomKey}" because its family "${familyKey}" already belongs to timeline "${existingTimelineKey}"`
2721
+ );
2722
+ continue;
2723
+ }
2724
+ }
2725
+ if (existingTimelineKey) {
2726
+ store.logger.error(
2727
+ `\u274C`,
2728
+ `timeline`,
2729
+ options.key,
2730
+ `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2731
+ );
2732
+ continue;
2733
+ }
2734
+ addAtomToTimeline(atomToken, tl, store);
2735
+ }
2736
+ break;
2737
+ case `atom_family`:
2738
+ case `mutable_atom_family`:
2739
+ {
2740
+ const familyToken = initialTopic;
2741
+ const familyKey = familyToken.key;
2742
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2743
+ if (existingTimelineKey) {
2744
+ store.logger.error(
2745
+ `\u274C`,
2746
+ `timeline`,
2747
+ options.key,
2748
+ `Failed to add atom family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2749
+ );
2750
+ continue;
2751
+ }
2752
+ addAtomFamilyToTimeline(familyToken, tl, store);
2753
+ }
2754
+ break;
2755
+ case `molecule_family`:
2756
+ {
2757
+ const familyToken = initialTopic;
2758
+ const familyKey = familyToken.key;
2759
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2760
+ if (existingTimelineKey) {
2761
+ store.logger.error(
2762
+ `\u274C`,
2763
+ `timeline`,
2764
+ options.key,
2765
+ `Failed to add molecule family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2766
+ );
2767
+ continue;
2768
+ }
2769
+ addMoleculeFamilyToTimeline(familyToken, tl, store);
2770
+ }
2771
+ break;
2772
+ }
2773
+ }
2774
+ store.timelines.set(options.key, tl);
2775
+ const token = {
2776
+ key: timelineKey,
2777
+ type: `timeline`
2778
+ };
2779
+ store.on.timelineCreation.next(token);
2780
+ return token;
2781
+ }
2782
+ function addAtomToTimeline(atomToken, tl, store) {
2654
2783
  let maybeAtom = withdraw(atomToken, store);
2655
2784
  if (maybeAtom.type === `mutable_atom`) {
2656
2785
  const updateToken = getUpdateToken(maybeAtom);
2657
2786
  maybeAtom = withdraw(updateToken, store);
2658
2787
  }
2659
2788
  const atom = maybeAtom;
2660
- store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
2789
+ store.timelineTopics.set(
2790
+ { topicKey: atom.key, timelineKey: tl.key },
2791
+ { topicType: `atom` }
2792
+ );
2661
2793
  tl.subscriptions.set(
2662
2794
  atom.key,
2663
2795
  atom.subject.subscribe(`timeline`, (update) => {
2664
- var _a, _b, _c, _d, _e, _f;
2796
+ var _a, _b, _c, _d, _e;
2665
2797
  const target = newest(store);
2666
2798
  const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2667
2799
  const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2668
- const { transactionApplying } = target.on;
2669
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
2670
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
2800
+ const txUpdateInProgress = (_a = target.on.transactionApplying.state) == null ? void 0 : _a.update;
2671
2801
  store.logger.info(
2672
2802
  `\u23F3`,
2673
2803
  `timeline`,
@@ -2678,109 +2808,11 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2678
2808
  update.oldValue,
2679
2809
  `->`,
2680
2810
  update.newValue,
2681
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2811
+ txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2682
2812
  );
2683
2813
  if (tl.timeTraveling === null) {
2684
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2685
- const mostRecentUpdate = tl.history.at(-1);
2686
- if (mostRecentUpdate === void 0) {
2687
- throw new Error(
2688
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
2689
- );
2690
- }
2691
- }
2692
- if (currentTransactionKey) {
2693
- const txToken = {
2694
- key: currentTransactionKey,
2695
- type: `transaction`
2696
- };
2697
- const currentTransaction = withdraw(txToken, store);
2698
- if (tl.transactionKey !== currentTransactionKey) {
2699
- if (tl.transactionKey) {
2700
- store.logger.error(
2701
- `\u{1F41E}`,
2702
- `timeline`,
2703
- tl.key,
2704
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2705
- );
2706
- }
2707
- tl.transactionKey = currentTransactionKey;
2708
- const unsubscribe = currentTransaction.subject.subscribe(
2709
- `timeline:${tl.key}`,
2710
- (transactionUpdate) => {
2711
- var _a2, _b2;
2712
- unsubscribe();
2713
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
2714
- if (tl.at !== tl.history.length) {
2715
- tl.history.splice(tl.at);
2716
- }
2717
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2718
- var _a3, _b3;
2719
- const newestStore = newest(store);
2720
- if (`updates` in updateFromTx) {
2721
- return true;
2722
- }
2723
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2724
- if (!atomOrFamilyKeys) {
2725
- return false;
2726
- }
2727
- let key;
2728
- let familyKey;
2729
- switch (updateFromTx.type) {
2730
- case `state_creation`:
2731
- case `state_disposal`:
2732
- key = updateFromTx.token.key;
2733
- familyKey = (_a3 = updateFromTx.token.family) == null ? void 0 : _a3.key;
2734
- break;
2735
- case `molecule_creation`:
2736
- case `molecule_disposal`:
2737
- break;
2738
- default:
2739
- key = updateFromTx.key;
2740
- familyKey = (_b3 = updateFromTx.family) == null ? void 0 : _b3.key;
2741
- break;
2742
- }
2743
- if (key === void 0) {
2744
- return false;
2745
- }
2746
- if (atomOrFamilyKeys.has(key)) {
2747
- return true;
2748
- }
2749
- if (familyKey !== void 0) {
2750
- return atomOrFamilyKeys.has(familyKey);
2751
- }
2752
- return false;
2753
- }).map((updateFromTx) => {
2754
- if (`updates` in updateFromTx) {
2755
- return __spreadProps(__spreadValues({}, updateFromTx), {
2756
- updates: filterUpdates(updateFromTx.updates)
2757
- });
2758
- }
2759
- return updateFromTx;
2760
- });
2761
- const updates = filterUpdates(transactionUpdate.updates);
2762
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
2763
- timestamp: Date.now()
2764
- }, transactionUpdate), {
2765
- updates
2766
- });
2767
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2768
- if (willCapture) {
2769
- tl.history.push(timelineTransactionUpdate);
2770
- tl.at = tl.history.length;
2771
- tl.subject.next(timelineTransactionUpdate);
2772
- }
2773
- }
2774
- tl.transactionKey = null;
2775
- store.logger.info(
2776
- `\u231B`,
2777
- `timeline`,
2778
- tl.key,
2779
- `got a transaction_update "${transactionUpdate.key}"`
2780
- );
2781
- }
2782
- );
2783
- }
2814
+ if (txUpdateInProgress) {
2815
+ joinTransaction(tl, txUpdateInProgress, store);
2784
2816
  } else if (currentSelectorKey && currentSelectorTime) {
2785
2817
  let latestUpdate = tl.history.at(-1);
2786
2818
  if (currentSelectorTime !== tl.selectorTime) {
@@ -2823,7 +2855,7 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2823
2855
  }
2824
2856
  }
2825
2857
  if (latestUpdate) {
2826
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2858
+ const willCaptureSelectorUpdate = (_c = (_b = tl.shouldCapture) == null ? void 0 : _b.call(tl, latestUpdate, tl)) != null ? _c : true;
2827
2859
  if (willCaptureSelectorUpdate) {
2828
2860
  tl.subject.next(latestUpdate);
2829
2861
  } else {
@@ -2847,7 +2879,7 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2847
2879
  if (atom.family) {
2848
2880
  atomUpdate.family = atom.family;
2849
2881
  }
2850
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
2882
+ const willCapture = (_e = (_d = tl.shouldCapture) == null ? void 0 : _d.call(tl, atomUpdate, tl)) != null ? _e : true;
2851
2883
  store.logger.info(
2852
2884
  `\u231B`,
2853
2885
  `timeline`,
@@ -2863,181 +2895,207 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2863
2895
  }
2864
2896
  })
2865
2897
  );
2866
- };
2867
- function createTimeline(options, store, data) {
2868
- var _a, _b;
2869
- const tl = __spreadProps(__spreadValues({
2870
- type: `timeline`,
2871
- key: options.key,
2872
- at: 0,
2873
- timeTraveling: null,
2874
- selectorTime: null,
2875
- transactionKey: null
2876
- }, data), {
2877
- history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2878
- install: (s) => createTimeline(options, s, tl),
2879
- subject: new Subject(),
2880
- subscriptions: /* @__PURE__ */ new Map()
2881
- });
2882
- if (options.shouldCapture) {
2883
- tl.shouldCapture = options.shouldCapture;
2898
+ }
2899
+ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
2900
+ var _a;
2901
+ const family = withdraw(atomFamilyToken, store);
2902
+ store.timelineTopics.set(
2903
+ { topicKey: family.key, timelineKey: tl.key },
2904
+ { topicType: `atom_family` }
2905
+ );
2906
+ tl.subscriptions.set(
2907
+ family.key,
2908
+ family.subject.subscribe(`timeline`, (creationOrDisposal) => {
2909
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
2910
+ })
2911
+ );
2912
+ for (const atom of store.atoms.values()) {
2913
+ if (((_a = atom.family) == null ? void 0 : _a.key) === family.key) {
2914
+ addAtomToTimeline(atom, tl, store);
2915
+ }
2884
2916
  }
2885
- const timelineKey = options.key;
2886
- const target = newest(store);
2887
- for (const tokenOrFamily of options.scope) {
2888
- let atomKey = tokenOrFamily.key;
2889
- switch (tokenOrFamily.type) {
2890
- case `atom_family`:
2891
- case `mutable_atom_family`:
2892
- {
2893
- const familyToken = tokenOrFamily;
2894
- const family = withdraw(familyToken, store);
2895
- const familyKey = family.key;
2896
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2897
- tl.subscriptions.set(
2898
- family.key,
2899
- family.subject.subscribe(
2900
- `timeline:${options.key}`,
2901
- (creationOrDisposal) => {
2902
- handleStateLifecycleEvent(creationOrDisposal, tl, store);
2917
+ }
2918
+ function addMoleculeFamilyToTimeline(familyToken, tl, store) {
2919
+ store.timelineTopics.set(
2920
+ { topicKey: familyToken.key, timelineKey: tl.key },
2921
+ { topicType: `molecule_family` }
2922
+ );
2923
+ const family = store.moleculeFamilies.get(familyToken.key);
2924
+ if (family) {
2925
+ tl.subscriptions.set(
2926
+ familyToken.key,
2927
+ family.subject.subscribe(`timeline:${tl.key}`, (creationOrDisposal) => {
2928
+ var _a, _b, _c, _d;
2929
+ store.logger.info(
2930
+ `\u{1F41E}`,
2931
+ `timeline`,
2932
+ tl.key,
2933
+ `got a molecule creation or disposal`,
2934
+ creationOrDisposal
2935
+ );
2936
+ switch (creationOrDisposal.type) {
2937
+ case `molecule_creation`:
2938
+ {
2939
+ store.timelineTopics.set(
2940
+ {
2941
+ topicKey: creationOrDisposal.token.key,
2942
+ timelineKey: tl.key
2943
+ },
2944
+ { topicType: `molecule` }
2945
+ );
2946
+ const txUpdateInProgress = (_a = newest(store).on.transactionApplying.state) == null ? void 0 : _a.update;
2947
+ if (txUpdateInProgress) {
2948
+ joinTransaction(tl, txUpdateInProgress, store);
2949
+ } else if (tl.timeTraveling === null) {
2950
+ const event = Object.assign(creationOrDisposal, {
2951
+ timestamp: Date.now()
2952
+ });
2953
+ tl.history.push(event);
2954
+ tl.at = tl.history.length;
2955
+ tl.subject.next(event);
2903
2956
  }
2904
- )
2905
- );
2906
- for (const atom of target.atoms.values()) {
2907
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2908
- addAtomToTimeline(atom, tl, store);
2909
- }
2910
- }
2911
- }
2912
- break;
2913
- case `atom`:
2914
- case `mutable_atom`:
2915
- {
2916
- let atom = withdraw(tokenOrFamily, store);
2917
- if (isMutable(atom)) {
2918
- const updateAtom = withdraw(getUpdateToken(atom), store);
2919
- atom = updateAtom;
2920
- atomKey = atom.key;
2921
- }
2922
- if (`family` in atom) {
2923
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2924
- atom.family.key
2925
- );
2926
- if (familyTimelineKey) {
2927
- store.logger.error(
2928
- `\u274C`,
2929
- `timeline`,
2930
- options.key,
2931
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
2957
+ const molecule = withdraw(creationOrDisposal.token, store);
2958
+ for (const token of molecule.tokens.values()) {
2959
+ switch (token.type) {
2960
+ case `atom`:
2961
+ case `mutable_atom`:
2962
+ addAtomToTimeline(token, tl, store);
2963
+ break;
2964
+ }
2965
+ }
2966
+ tl.subscriptions.set(
2967
+ molecule.key,
2968
+ molecule.subject.subscribe(
2969
+ `timeline:${tl.key}`,
2970
+ (stateCreationOrDisposal) => {
2971
+ handleStateLifecycleEvent(stateCreationOrDisposal, tl, store);
2972
+ }
2973
+ )
2932
2974
  );
2933
- continue;
2934
2975
  }
2976
+ break;
2977
+ case `molecule_disposal`:
2978
+ {
2979
+ const txUpdateInProgress = (_b = newest(store).on.transactionApplying.state) == null ? void 0 : _b.update;
2980
+ if (txUpdateInProgress) {
2981
+ joinTransaction(tl, txUpdateInProgress, store);
2982
+ } else if (tl.timeTraveling === null) {
2983
+ const event = Object.assign(creationOrDisposal, {
2984
+ timestamp: Date.now()
2985
+ });
2986
+ tl.history.push(event);
2987
+ tl.at = tl.history.length;
2988
+ tl.subject.next(event);
2989
+ }
2990
+ const moleculeKey = creationOrDisposal.token.key;
2991
+ (_c = tl.subscriptions.get(moleculeKey)) == null ? void 0 : _c();
2992
+ tl.subscriptions.delete(moleculeKey);
2993
+ for (const [familyKey] of creationOrDisposal.values) {
2994
+ const stateKey = `${familyKey}(${json.stringifyJson(moleculeKey)})`;
2995
+ (_d = tl.subscriptions.get(stateKey)) == null ? void 0 : _d();
2996
+ tl.subscriptions.delete(stateKey);
2997
+ store.timelineTopics.delete(stateKey);
2998
+ }
2999
+ }
3000
+ break;
3001
+ }
3002
+ })
3003
+ );
3004
+ }
3005
+ }
3006
+ function joinTransaction(tl, txUpdateInProgress, store) {
3007
+ const currentTxKey = txUpdateInProgress.key;
3008
+ const currentTxInstanceId = txUpdateInProgress.id;
3009
+ const currentTxToken = {
3010
+ key: currentTxKey,
3011
+ type: `transaction`
3012
+ };
3013
+ const currentTransaction = withdraw(currentTxToken, store);
3014
+ if (currentTxKey && tl.transactionKey === null) {
3015
+ tl.transactionKey = currentTxKey;
3016
+ const unsubscribe = currentTransaction.subject.subscribe(
3017
+ `timeline:${tl.key}`,
3018
+ (transactionUpdate) => {
3019
+ var _a, _b;
3020
+ unsubscribe();
3021
+ tl.transactionKey = null;
3022
+ if (tl.timeTraveling === null && currentTxInstanceId) {
3023
+ if (tl.at !== tl.history.length) {
3024
+ tl.history.splice(tl.at);
2935
3025
  }
2936
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2937
- if (existingTimelineKey) {
2938
- store.logger.error(
2939
- `\u274C`,
2940
- `timeline`,
2941
- options.key,
2942
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2943
- );
2944
- continue;
3026
+ const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
3027
+ const updates = filterTransactionUpdates(
3028
+ transactionUpdate.updates,
3029
+ timelineTopics
3030
+ );
3031
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
3032
+ timestamp: Date.now()
3033
+ }, transactionUpdate), {
3034
+ updates
3035
+ });
3036
+ const willCapture = (_b = (_a = tl.shouldCapture) == null ? void 0 : _a.call(tl, timelineTransactionUpdate, tl)) != null ? _b : true;
3037
+ if (willCapture) {
3038
+ tl.history.push(timelineTransactionUpdate);
3039
+ tl.at = tl.history.length;
3040
+ tl.subject.next(timelineTransactionUpdate);
2945
3041
  }
2946
- addAtomToTimeline(atom, tl, store);
2947
3042
  }
3043
+ }
3044
+ );
3045
+ }
3046
+ }
3047
+ function filterTransactionUpdates(updates, timelineTopics) {
3048
+ return updates.filter((updateFromTx) => {
3049
+ if (updateFromTx.type === `transaction_update`) {
3050
+ return true;
3051
+ }
3052
+ let key;
3053
+ switch (updateFromTx.type) {
3054
+ case `state_creation`:
3055
+ case `state_disposal`:
3056
+ case `molecule_creation`:
3057
+ case `molecule_disposal`:
3058
+ key = updateFromTx.token.key;
2948
3059
  break;
2949
- case `molecule_family`:
2950
- {
2951
- const family = store.moleculeFamilies.get(tokenOrFamily.key);
2952
- if (family) {
2953
- tl.subscriptions.set(
2954
- tokenOrFamily.key,
2955
- family.subject.subscribe(
2956
- `timeline:${options.key}`,
2957
- (creationOrDisposal) => {
2958
- var _a2, _b2;
2959
- switch (creationOrDisposal.type) {
2960
- case `molecule_creation`:
2961
- {
2962
- const molecule = store.molecules.get(
2963
- json.stringifyJson(creationOrDisposal.token.key)
2964
- );
2965
- if (molecule) {
2966
- const event = Object.assign(creationOrDisposal, {
2967
- timestamp: Date.now()
2968
- });
2969
- tl.history.push(event);
2970
- tl.at = tl.history.length;
2971
- tl.subject.next(event);
2972
- for (const token2 of molecule.tokens.values()) {
2973
- switch (token2.type) {
2974
- case `atom`:
2975
- case `mutable_atom`:
2976
- addAtomToTimeline(token2, tl, store);
2977
- break;
2978
- }
2979
- }
2980
- tl.subscriptions.set(
2981
- molecule.key,
2982
- molecule.subject.subscribe(
2983
- `timeline:${options.key}`,
2984
- (stateCreationOrDisposal) => {
2985
- handleStateLifecycleEvent(
2986
- stateCreationOrDisposal,
2987
- tl,
2988
- store
2989
- );
2990
- }
2991
- )
2992
- );
2993
- }
2994
- }
2995
- break;
2996
- case `molecule_disposal`:
2997
- (_a2 = tl.subscriptions.get(creationOrDisposal.token.key)) == null ? void 0 : _a2();
2998
- tl.subscriptions.delete(creationOrDisposal.token.key);
2999
- for (const familyKey of creationOrDisposal.familyKeys) {
3000
- const stateKey = `${familyKey}(${json.stringifyJson(
3001
- creationOrDisposal.token.key
3002
- )})`;
3003
- (_b2 = tl.subscriptions.get(stateKey)) == null ? void 0 : _b2();
3004
- tl.subscriptions.delete(stateKey);
3005
- }
3006
- break;
3007
- }
3008
- }
3009
- )
3010
- );
3011
- }
3012
- }
3060
+ default:
3061
+ key = updateFromTx.key;
3013
3062
  break;
3014
3063
  }
3015
- }
3016
- store.timelines.set(options.key, tl);
3017
- const token = {
3018
- key: timelineKey,
3019
- type: `timeline`
3020
- };
3021
- store.on.timelineCreation.next(token);
3022
- return token;
3064
+ return timelineTopics.has(key);
3065
+ }).map((updateFromTx) => {
3066
+ if (`updates` in updateFromTx) {
3067
+ return __spreadProps(__spreadValues({}, updateFromTx), {
3068
+ updates: filterTransactionUpdates(
3069
+ updateFromTx.updates,
3070
+ timelineTopics
3071
+ )
3072
+ });
3073
+ }
3074
+ return updateFromTx;
3075
+ });
3023
3076
  }
3024
3077
  function handleStateLifecycleEvent(event, tl, store) {
3025
- var _a;
3078
+ var _a, _b;
3026
3079
  const timestamp = Date.now();
3027
3080
  const timelineEvent = Object.assign(event, {
3028
3081
  timestamp
3029
3082
  });
3030
3083
  if (!tl.timeTraveling) {
3031
- tl.history.push(timelineEvent);
3032
- tl.at = tl.history.length;
3033
- tl.subject.next(timelineEvent);
3084
+ const txUpdateInProgress = (_a = newest(store).on.transactionApplying.state) == null ? void 0 : _a.update;
3085
+ if (txUpdateInProgress) {
3086
+ joinTransaction(tl, txUpdateInProgress, store);
3087
+ } else {
3088
+ tl.history.push(timelineEvent);
3089
+ tl.at = tl.history.length;
3090
+ tl.subject.next(timelineEvent);
3091
+ }
3034
3092
  }
3035
3093
  switch (event.type) {
3036
3094
  case `state_creation`:
3037
3095
  addAtomToTimeline(event.token, tl, store);
3038
3096
  break;
3039
3097
  case `state_disposal`:
3040
- (_a = tl.subscriptions.get(event.token.key)) == null ? void 0 : _a();
3098
+ (_b = tl.subscriptions.get(event.token.key)) == null ? void 0 : _b();
3041
3099
  tl.subscriptions.delete(event.token.key);
3042
3100
  break;
3043
3101
  }
@@ -3132,7 +3190,6 @@ exports.TRANSACTION_PHASES = TRANSACTION_PHASES;
3132
3190
  exports.Tracker = Tracker;
3133
3191
  exports.abortTransaction = abortTransaction;
3134
3192
  exports.actUponStore = actUponStore;
3135
- exports.addAtomToTimeline = addAtomToTimeline;
3136
3193
  exports.applyTransaction = applyTransaction;
3137
3194
  exports.arbitrary = arbitrary;
3138
3195
  exports.assignTransactionToContinuity = assignTransactionToContinuity;