atom.io 0.24.4 → 0.24.6

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,582 +725,463 @@ 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;
765
+ return createRegularAtomFamily(options, store);
1047
766
  }
1048
767
 
1049
- // internal/src/get-environment-data.ts
1050
- function getEnvironmentData(store) {
1051
- return {
1052
- store
1053
- };
1054
- }
768
+ // internal/src/keys.ts
769
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
770
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
771
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
772
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1055
773
 
1056
- // internal/src/get-state/get-from-store.ts
1057
- function getFromStore(token, store) {
1058
- if (token.type === `molecule`) {
1059
- try {
1060
- const molecule = withdraw(token, store);
1061
- return molecule.instance;
1062
- } catch (_) {
1063
- return void 0;
1064
- }
1065
- }
1066
- const state = withdraw(token, store);
1067
- return readOrComputeValue(state, store);
1068
- }
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
- }
774
+ // internal/src/selector/get-selector-dependency-keys.ts
775
+ var getSelectorDependencyKeys = (key, store) => {
776
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
777
+ return sources;
1092
778
  };
1093
779
 
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) {
780
+ // internal/src/selector/trace-selector-atoms.ts
781
+ var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
782
+ const rootKeys = [];
783
+ const indirectDependencyKeys = getSelectorDependencyKeys(
784
+ directDependencyKey,
785
+ store
786
+ );
787
+ let depth = 0;
788
+ while (indirectDependencyKeys.length > 0) {
789
+ const indirectDependencyKey = indirectDependencyKeys.shift();
790
+ ++depth;
791
+ if (depth > 99999) {
1110
792
  throw new Error(
1111
- `Molecule ${stringKey} not found in store "${store.config.name}"`
793
+ `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1112
794
  );
1113
795
  }
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);
796
+ if (!isAtomKey(indirectDependencyKey, store)) {
797
+ indirectDependencyKeys.push(
798
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
799
+ );
800
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
801
+ rootKeys.push(indirectDependencyKey);
802
+ }
1121
803
  }
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
- }
804
+ return rootKeys;
805
+ };
806
+ var traceAllSelectorAtoms = (selector, store) => {
807
+ const selectorKey = selector.key;
808
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
809
+ return directDependencyKeys.flatMap(
810
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
811
+ );
812
+ };
813
+
814
+ // internal/src/selector/update-selector-atoms.ts
815
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
816
+ const target = newest(store);
817
+ if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
818
+ target.selectorAtoms.set({
819
+ selectorKey,
820
+ atomKey: dependency.key
821
+ });
822
+ store.logger.info(
823
+ `\u{1F50D}`,
824
+ `selector`,
825
+ selectorKey,
826
+ `discovers root atom "${dependency.key}"`
827
+ );
828
+ } else {
829
+ const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
830
+ store.logger.info(
831
+ `\u{1F50D}`,
832
+ `selector`,
833
+ selectorKey,
834
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
835
+ );
836
+ for (const atomKey of rootKeys) {
837
+ target.selectorAtoms = target.selectorAtoms.set({
838
+ selectorKey,
839
+ atomKey
840
+ });
841
+ }
842
+ }
843
+ };
844
+
845
+ // internal/src/selector/register-selector.ts
846
+ var registerSelector = (selectorKey, store) => ({
847
+ get: (dependency) => {
848
+ const target = newest(store);
849
+ const dependencyState = withdraw(dependency, store);
850
+ const dependencyValue = readOrComputeValue(dependencyState, store);
851
+ store.logger.info(
852
+ `\u{1F50C}`,
853
+ `selector`,
854
+ selectorKey,
855
+ `registers dependency ( "${dependency.key}" =`,
856
+ dependencyValue,
857
+ `)`
858
+ );
859
+ target.selectorGraph.set(
860
+ {
861
+ upstreamSelectorKey: dependency.key,
862
+ downstreamSelectorKey: selectorKey
863
+ },
864
+ {
865
+ source: dependency.key
1155
866
  }
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
- )
867
+ );
868
+ updateSelectorAtoms(selectorKey, dependency, store);
869
+ return dependencyValue;
870
+ },
871
+ set: (WritableToken, newValue) => {
872
+ const target = newest(store);
873
+ const state = withdraw(WritableToken, target);
874
+ setAtomOrSelector(state, newValue, target);
875
+ },
876
+ find: (token, key) => findInStore(token, key, store),
877
+ seek: (token, key) => seekInStore(token, key, store),
878
+ json: (token) => getJsonToken(token, store)
879
+ });
880
+
881
+ // internal/src/selector/create-readonly-selector.ts
882
+ var createReadonlySelector = (options, family, store) => {
883
+ const target = newest(store);
884
+ const subject = new Subject();
885
+ const { get, find, seek, json } = registerSelector(options.key, target);
886
+ const getSelf = () => {
887
+ const value = options.get({ get, find, seek, json });
888
+ cacheValue(options.key, value, subject, newest(store));
889
+ return value;
1170
890
  };
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
891
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
892
+ subject,
893
+ install: (s) => createReadonlySelector(options, family, s),
894
+ get: getSelf,
895
+ type: `readonly_selector`
896
+ }), family && { family });
897
+ target.readonlySelectors.set(options.key, readonlySelector);
898
+ const initialValue = getSelf();
899
+ store.logger.info(
900
+ `\u2728`,
901
+ readonlySelector.type,
902
+ readonlySelector.key,
903
+ `=`,
904
+ initialValue
905
+ );
906
+ const token = {
907
+ key: options.key,
908
+ type: `readonly_selector`
1179
909
  };
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);
910
+ if (family) {
911
+ token.family = family;
1185
912
  }
1186
913
  return token;
1187
- }
914
+ };
1188
915
 
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;
916
+ // internal/src/selector/create-writable-selector.ts
917
+ var createWritableSelector = (options, family, store) => {
918
+ const target = newest(store);
919
+ const subject = new Subject();
920
+ const transactors = registerSelector(options.key, target);
921
+ const { find, get, seek, json } = transactors;
922
+ const readonlyTransactors = { find, get, seek, json };
923
+ const getSelf = (innerTarget = newest(store)) => {
924
+ const value = options.get(readonlyTransactors);
925
+ cacheValue(options.key, value, subject, innerTarget);
926
+ return value;
927
+ };
928
+ const setSelf = (next) => {
929
+ const innerTarget = newest(store);
930
+ const oldValue = getSelf(innerTarget);
931
+ const newValue = become(next)(oldValue);
932
+ store.logger.info(
933
+ `\u{1F4DD}`,
934
+ `selector`,
935
+ options.key,
936
+ `set (`,
937
+ oldValue,
938
+ `->`,
939
+ newValue,
940
+ `)`
941
+ );
942
+ cacheValue(options.key, newValue, subject, innerTarget);
943
+ markDone(options.key, innerTarget);
944
+ if (isRootStore(innerTarget)) {
945
+ subject.next({ newValue, oldValue });
1199
946
  }
947
+ options.set(transactors, newValue);
948
+ };
949
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
950
+ subject,
951
+ install: (s) => createWritableSelector(options, family, s),
952
+ get: getSelf,
953
+ set: setSelf,
954
+ type: `selector`
955
+ }), family && { family });
956
+ target.selectors.set(options.key, mySelector);
957
+ const initialValue = getSelf();
958
+ store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
959
+ const token = {
960
+ key: options.key,
961
+ type: `selector`
962
+ };
963
+ if (family) {
964
+ token.family = family;
1200
965
  }
1201
- }
1202
- function ingestDisposalEvent(update, applying, store) {
1203
- switch (applying) {
1204
- case `newValue`: {
1205
- disposeFromStore(update.token, store);
1206
- break;
1207
- }
1208
- case `oldValue`: {
1209
- createInStore(update.token, store);
1210
- store.valueMap.set(update.token.key, update.value);
1211
- break;
1212
- }
966
+ return token;
967
+ };
968
+
969
+ // internal/src/selector/create-standalone-selector.ts
970
+ function createStandaloneSelector(options, store) {
971
+ const isWritable = `set` in options;
972
+ if (isWritable) {
973
+ const state2 = createWritableSelector(options, void 0, store);
974
+ store.on.selectorCreation.next(state2);
975
+ return state2;
1213
976
  }
977
+ const state = createReadonlySelector(options, void 0, store);
978
+ store.on.selectorCreation.next(state);
979
+ return state;
1214
980
  }
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;
981
+
982
+ // internal/src/selector/dispose-selector.ts
983
+ function disposeSelector(selectorToken, store) {
984
+ var _a;
985
+ const target = newest(store);
986
+ const { key } = selectorToken;
987
+ const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
988
+ if (!selector) {
989
+ store.logger.info(
990
+ `\u274C`,
991
+ `selector`,
992
+ key,
993
+ `Tried to dispose selector, but it does not exist in the store.`
994
+ );
995
+ } else if (!selector.family) {
996
+ store.logger.error(
997
+ `\u274C`,
998
+ `selector`,
999
+ key,
1000
+ `Standalone selectors cannot be disposed.`
1001
+ );
1002
+ } else {
1003
+ const molecule = target.molecules.get(selector.family.subKey);
1004
+ if (molecule) {
1005
+ molecule.tokens.delete(key);
1006
+ }
1007
+ switch (selectorToken.type) {
1008
+ case `selector`:
1009
+ {
1010
+ target.selectors.delete(key);
1011
+ const family = withdraw(
1012
+ { key: selector.family.key, type: `selector_family` },
1013
+ store
1014
+ );
1015
+ family.subject.next({
1016
+ type: `state_disposal`,
1017
+ token: selectorToken
1018
+ });
1019
+ }
1020
+ break;
1021
+ case `readonly_selector`:
1022
+ {
1023
+ target.readonlySelectors.delete(key);
1024
+ const family = withdraw(
1025
+ { key: selector.family.key, type: `readonly_selector_family` },
1026
+ store
1027
+ );
1028
+ family.subject.next({
1029
+ type: `state_disposal`,
1030
+ token: selectorToken
1031
+ });
1032
+ }
1033
+ break;
1034
+ }
1035
+ target.valueMap.delete(key);
1036
+ target.selectorAtoms.delete(key);
1037
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1038
+ ([downstreamSelectorKey]) => {
1039
+ var _a2;
1040
+ return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1223
1041
  }
1224
- if (store.config.lifespan === `immortal`) {
1225
- throw new Error(`No molecule found for key "${token.family.subKey}"`);
1042
+ );
1043
+ for (const downstreamToken of downstreamTokens) {
1044
+ if (downstreamToken) {
1045
+ disposeSelector(downstreamToken, store);
1226
1046
  }
1227
- initFamilyMemberInStore(family, json.parseJson(token.family.subKey), store);
1047
+ }
1048
+ target.selectorGraph.delete(key);
1049
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1050
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1051
+ target.transactionMeta.update.updates.push({
1052
+ type: `state_disposal`,
1053
+ token: selectorToken
1054
+ });
1055
+ } else {
1056
+ store.on.selectorDisposal.next(selectorToken);
1228
1057
  }
1229
1058
  }
1230
1059
  }
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
1060
+
1061
+ // internal/src/families/create-readonly-selector-family.ts
1062
+ function createReadonlySelectorFamily(options, store) {
1063
+ const subject = new Subject();
1064
+ const readonlySelectorFamily = Object.assign(
1065
+ (key) => {
1066
+ const subKey = json.stringifyJson(key);
1067
+ const family = { key: options.key, subKey };
1068
+ const fullKey = `${options.key}(${subKey})`;
1069
+ const target = newest(store);
1070
+ const token = createReadonlySelector(
1071
+ {
1072
+ key: fullKey,
1073
+ get: options.get(key)
1074
+ },
1075
+ family,
1076
+ target
1240
1077
  );
1241
- break;
1242
- case `oldValue`:
1243
- disposeFromStore(update.token, store);
1244
- break;
1245
- }
1078
+ subject.next({ type: `state_creation`, token });
1079
+ return token;
1080
+ },
1081
+ {
1082
+ key: options.key,
1083
+ type: `readonly_selector_family`,
1084
+ subject,
1085
+ install: (s) => createReadonlySelectorFamily(options, s)
1086
+ }
1087
+ );
1088
+ store.families.set(options.key, readonlySelectorFamily);
1089
+ return readonlySelectorFamily;
1246
1090
  }
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
1091
+ function createWritableSelectorFamily(options, store) {
1092
+ const subject = new Subject();
1093
+ const selectorFamily = Object.assign(
1094
+ (key) => {
1095
+ const subKey = json.stringifyJson(key);
1096
+ const family = { key: options.key, subKey };
1097
+ const fullKey = `${options.key}(${subKey})`;
1098
+ const target = newest(store);
1099
+ const token = createWritableSelector(
1100
+ {
1101
+ key: fullKey,
1102
+ get: options.get(key),
1103
+ set: options.set(key)
1104
+ },
1105
+ family,
1106
+ target
1258
1107
  );
1259
- break;
1260
- }
1108
+ subject.next({ type: `state_creation`, token });
1109
+ return token;
1110
+ },
1111
+ {
1112
+ key: options.key,
1113
+ type: `selector_family`,
1114
+ subject,
1115
+ install: (s) => createWritableSelectorFamily(options, s)
1116
+ }
1117
+ );
1118
+ store.families.set(options.key, selectorFamily);
1119
+ return selectorFamily;
1261
1120
  }
1262
1121
 
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);
1122
+ // internal/src/families/create-selector-family.ts
1123
+ function createSelectorFamily(options, store) {
1124
+ const isWritable = `set` in options;
1125
+ if (isWritable) {
1126
+ return createWritableSelectorFamily(options, store);
1268
1127
  }
1128
+ return createReadonlySelectorFamily(options, store);
1269
1129
  }
1270
1130
 
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;
1131
+ // internal/src/molecule/dispose-molecule.ts
1132
+ function disposeMolecule(token, store) {
1133
+ var _a;
1134
+ let molecule;
1135
+ try {
1136
+ molecule = withdraw(token, store);
1137
+ } catch (thrown) {
1138
+ if (thrown instanceof Error) {
1139
+ store.logger.error(
1140
+ `\u{1F41E}`,
1141
+ `molecule`,
1142
+ JSON.stringify(token.key),
1143
+ `Failed to dispose molecule, because it was not found in the store.`,
1144
+ thrown.message
1145
+ );
1295
1146
  }
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
1147
  return;
1310
1148
  }
1311
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1312
- if (continuityKey !== void 0) {
1313
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
1149
+ const { family } = token;
1150
+ const context = [];
1151
+ for (const above of molecule.above.values()) {
1152
+ context.push(deposit(above));
1314
1153
  }
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;
1330
- }
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
- for (const tracker of child.trackers.values()) {
1344
- const mutableKey = tracker.mutableState.key;
1345
- if (!parent.atoms.has(mutableKey)) {
1346
- const atom = child.atoms.get(mutableKey);
1347
- atom == null ? void 0 : atom.install(parent);
1348
- }
1349
- tracker.dispose();
1350
- }
1351
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1352
- if (isRootStore(parent)) {
1353
- setEpochNumberOfAction(
1354
- child.transactionMeta.update.key,
1355
- child.transactionMeta.update.epoch,
1356
- parent
1357
- );
1358
- const myTransaction = withdraw(
1359
- { key: child.transactionMeta.update.key, type: `transaction` },
1360
- store
1361
- );
1362
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
1363
- store.logger.info(
1364
- `\u{1F6EC}`,
1365
- `transaction`,
1366
- child.transactionMeta.update.key,
1367
- `Finished applying transaction.`
1368
- );
1369
- } else if (isChildStore(parent)) {
1370
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1371
- }
1372
- parent.on.transactionApplying.next(null);
1373
- };
1374
-
1375
- // internal/src/transaction/assign-transaction-to-continuity.ts
1376
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1377
- const isRoot = isRootStore(store);
1378
- if (!isRoot) {
1379
- return;
1380
- }
1381
- const { epoch, actionContinuities } = store.transactionMeta;
1382
- actionContinuities.set(continuityKey, transactionKey);
1383
- if (!epoch.has(continuityKey)) {
1384
- epoch.set(continuityKey, -1);
1385
- }
1386
- }
1387
-
1388
- // internal/src/lazy-map.ts
1389
- var LazyMap = class extends Map {
1390
- constructor(source) {
1391
- super();
1392
- this.source = source;
1393
- this.deleted = /* @__PURE__ */ new Set();
1394
- }
1395
- get(key) {
1396
- const has = super.has(key);
1397
- if (has) {
1398
- return super.get(key);
1399
- }
1400
- if (!this.deleted.has(key) && this.source.has(key)) {
1401
- const value = this.source.get(key);
1402
- return value;
1403
- }
1404
- return void 0;
1405
- }
1406
- set(key, value) {
1407
- this.deleted.delete(key);
1408
- return super.set(key, value);
1409
- }
1410
- hasOwn(key) {
1411
- return super.has(key);
1412
- }
1413
- has(key) {
1414
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1415
- }
1416
- delete(key) {
1417
- this.deleted.add(key);
1418
- return super.delete(key);
1419
- }
1420
- };
1421
-
1422
- // internal/src/transaction/build-transaction.ts
1423
- var buildTransaction = (key, params, store, id) => {
1424
- const parent = newest(store);
1425
- const childBase = {
1426
- parent,
1427
- child: null,
1428
- on: parent.on,
1429
- loggers: parent.loggers,
1430
- logger: parent.logger,
1431
- config: parent.config,
1432
- atoms: new LazyMap(parent.atoms),
1433
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1434
- families: new LazyMap(parent.families),
1435
- operation: { open: false },
1436
- readonlySelectors: new LazyMap(parent.readonlySelectors),
1437
- timelines: new LazyMap(parent.timelines),
1438
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
1439
- trackers: /* @__PURE__ */ new Map(),
1440
- transactions: new LazyMap(parent.transactions),
1441
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1442
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1443
- makeContentKey: (...keys) => keys.sort().join(`:`)
1444
- }),
1445
- selectors: new LazyMap(parent.selectors),
1446
- valueMap: new LazyMap(parent.valueMap),
1447
- molecules: new LazyMap(parent.molecules),
1448
- moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1449
- miscResources: new LazyMap(parent.miscResources)
1450
- };
1451
- const epoch = getEpochNumberOfAction(key, store);
1452
- const transactionMeta = {
1453
- phase: `building`,
1454
- update: {
1455
- type: `transaction_update`,
1456
- key,
1457
- id,
1458
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1459
- updates: [],
1460
- params,
1461
- output: void 0
1462
- },
1463
- transactors: {
1464
- get: (token) => getFromStore(token, child),
1465
- set: (token, value) => {
1466
- setIntoStore(token, value, child);
1467
- },
1468
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1469
- find: (token, k) => findInStore(token, k, child),
1470
- seek: (token, k) => seekInStore(token, k, child),
1471
- json: (token) => getJsonToken(token, child),
1472
- make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1473
- dispose: (token) => {
1474
- disposeFromStore(token, child);
1475
- },
1476
- env: () => getEnvironmentData(child)
1477
- }
1478
- };
1479
- const child = Object.assign(childBase, {
1480
- transactionMeta
1481
- });
1482
- parent.child = child;
1483
- store.logger.info(
1484
- `\u{1F6EB}`,
1485
- `transaction`,
1486
- key,
1487
- `Building transaction with params:`,
1488
- params
1489
- );
1490
- return child;
1491
- };
1492
-
1493
- // internal/src/transaction/create-transaction.ts
1494
- function createTransaction(options, store) {
1495
- const newTransaction = {
1496
- key: options.key,
1497
- type: `transaction`,
1498
- run: (params, id) => {
1499
- const childStore = buildTransaction(options.key, params, store, id);
1500
- try {
1501
- const target2 = newest(store);
1502
- const { transactors } = childStore.transactionMeta;
1503
- const output = options.do(transactors, ...params);
1504
- applyTransaction(output, target2);
1505
- return output;
1506
- } catch (thrown) {
1507
- abortTransaction(target);
1508
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1509
- throw thrown;
1510
- }
1511
- },
1512
- install: (s) => createTransaction(options, s),
1513
- subject: new Subject()
1514
- };
1515
- const target = newest(store);
1516
- target.transactions.set(newTransaction.key, newTransaction);
1517
- const token = deposit(newTransaction);
1518
- store.on.transactionCreation.next(token);
1519
- return token;
1520
- }
1521
-
1522
- // internal/src/transaction/get-epoch-number.ts
1523
- function getContinuityKey(transactionKey, store) {
1524
- const isRoot = isRootStore(store);
1525
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1526
- return continuity;
1527
- }
1528
- function getEpochNumberOfContinuity(continuityKey, store) {
1529
- const isRoot = isRootStore(store);
1530
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1531
- return epoch;
1532
- }
1533
- function getEpochNumberOfAction(transactionKey, store) {
1534
- const isRoot = isRootStore(store);
1535
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1536
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1537
- return epoch;
1538
- }
1539
-
1540
- // internal/src/transaction/index.ts
1541
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1542
-
1543
- // internal/src/molecule/dispose-molecule.ts
1544
- function disposeMolecule(token, store) {
1545
- var _a;
1546
- let molecule;
1547
- try {
1548
- molecule = withdraw(token, store);
1549
- } catch (thrown) {
1550
- if (thrown instanceof Error) {
1551
- store.logger.error(
1552
- `\u{1F41E}`,
1553
- `molecule`,
1554
- JSON.stringify(token.key),
1555
- `Failed to dispose molecule, because it was not found in the store.`,
1556
- thrown.message
1557
- );
1558
- }
1559
- return;
1560
- }
1561
- const { family } = token;
1562
- for (const state of molecule.tokens.values()) {
1563
- disposeFromStore(state, store);
1564
- }
1565
- for (const child of molecule.below.values()) {
1566
- if (((_a = child.family) == null ? void 0 : _a.dependsOn) === `all`) {
1567
- disposeMolecule(child, store);
1568
- } else {
1569
- child.above.delete(molecule.stringKey);
1570
- if (child.above.size === 0) {
1571
- disposeMolecule(child, store);
1572
- }
1573
- }
1154
+ const values = [];
1155
+ for (const stateToken of molecule.tokens.values()) {
1156
+ const tokenFamily = stateToken.family;
1157
+ values.push([tokenFamily.key, store.valueMap.get(stateToken.key)]);
1574
1158
  }
1575
- molecule.below.clear();
1576
1159
  if (family) {
1577
1160
  const Formula = withdraw(family, store);
1578
1161
  const disposalEvent = {
1579
1162
  type: `molecule_disposal`,
1580
1163
  token,
1581
1164
  family,
1582
- context: [...molecule.above.values()].map((m) => deposit(m)),
1583
- familyKeys: [...molecule.tokens.values()].map((t) => {
1584
- var _a2;
1585
- return (_a2 = t.family) == null ? void 0 : _a2.key;
1586
- }).filter((k) => typeof k === `string`)
1165
+ context,
1166
+ values
1587
1167
  };
1588
1168
  if (token.family) {
1589
1169
  disposalEvent.family = token.family;
1590
1170
  }
1171
+ for (const state of molecule.tokens.values()) {
1172
+ disposeFromStore(state, store);
1173
+ }
1174
+ for (const child of molecule.below.values()) {
1175
+ if (((_a = child.family) == null ? void 0 : _a.dependsOn) === `all`) {
1176
+ disposeMolecule(child, store);
1177
+ } else {
1178
+ child.above.delete(molecule.stringKey);
1179
+ if (child.above.size === 0) {
1180
+ disposeMolecule(child, store);
1181
+ }
1182
+ }
1183
+ }
1184
+ molecule.below.clear();
1591
1185
  const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1592
1186
  if (isTransaction) {
1593
1187
  store.transactionMeta.update.updates.push(disposalEvent);
@@ -1630,13 +1224,8 @@ function initFamilyMemberInStore(token, key, store) {
1630
1224
  }
1631
1225
  const state = family(key);
1632
1226
  const target = newest(store);
1633
- if (state.family) {
1634
- if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1635
- target.transactionMeta.update.updates.push({
1636
- type: `state_creation`,
1637
- token: state
1638
- });
1639
- } else {
1227
+ if (state.family && target.moleculeInProgress === null) {
1228
+ if (isRootStore(target)) {
1640
1229
  switch (state.type) {
1641
1230
  case `atom`:
1642
1231
  case `mutable_atom`:
@@ -1647,9 +1236,14 @@ function initFamilyMemberInStore(token, key, store) {
1647
1236
  store.on.selectorCreation.next(state);
1648
1237
  break;
1649
1238
  }
1650
- }
1651
- }
1652
- return state;
1239
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1240
+ target.transactionMeta.update.updates.push({
1241
+ type: `state_creation`,
1242
+ token: state
1243
+ });
1244
+ }
1245
+ }
1246
+ return state;
1653
1247
  }
1654
1248
  function seekInStore(token, key, store) {
1655
1249
  const subKey = json.stringifyJson(key);
@@ -1694,291 +1288,715 @@ function findInStore(token, key, store) {
1694
1288
  return state;
1695
1289
  }
1696
1290
 
1697
- // internal/src/keys.ts
1698
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
1699
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1700
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1701
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1291
+ // internal/src/molecule/create-molecule-family.ts
1292
+ function createMoleculeFamily(options, store) {
1293
+ var _a;
1294
+ const subject = new Subject();
1295
+ const token = {
1296
+ type: `molecule_family`,
1297
+ key: options.key,
1298
+ dependsOn: (_a = options.dependsOn) != null ? _a : `all`
1299
+ };
1300
+ const family = __spreadProps(__spreadValues({}, token), {
1301
+ subject,
1302
+ new: options.new
1303
+ });
1304
+ store.moleculeFamilies.set(options.key, family);
1305
+ return token;
1306
+ }
1702
1307
 
1703
- // internal/src/selector/get-selector-dependency-keys.ts
1704
- var getSelectorDependencyKeys = (key, store) => {
1705
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1706
- return sources;
1707
- };
1308
+ // internal/src/molecule/grow-molecule-in-store.ts
1309
+ function growMoleculeInStore(molecule, family, store) {
1310
+ const stateToken = initFamilyMemberInStore(family, molecule.key, store);
1311
+ molecule.tokens.set(stateToken.key, stateToken);
1312
+ const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1313
+ const moleculeInProgress = store.moleculeInProgress === molecule.key;
1314
+ if (!isTransaction && !moleculeInProgress) {
1315
+ molecule.subject.next({ type: `state_creation`, token: stateToken });
1316
+ }
1317
+ return stateToken;
1318
+ }
1708
1319
 
1709
- // internal/src/selector/trace-selector-atoms.ts
1710
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1711
- const rootKeys = [];
1712
- const indirectDependencyKeys = getSelectorDependencyKeys(
1713
- directDependencyKey,
1320
+ // internal/src/get-environment-data.ts
1321
+ function getEnvironmentData(store) {
1322
+ return {
1714
1323
  store
1715
- );
1716
- let depth = 0;
1717
- while (indirectDependencyKeys.length > 0) {
1718
- const indirectDependencyKey = indirectDependencyKeys.shift();
1719
- ++depth;
1720
- if (depth > 99999) {
1721
- throw new Error(
1722
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1723
- );
1324
+ };
1325
+ }
1326
+
1327
+ // internal/src/get-state/get-from-store.ts
1328
+ function getFromStore(token, store) {
1329
+ if (token.type === `molecule`) {
1330
+ try {
1331
+ const molecule = withdraw(token, store);
1332
+ return molecule.instance;
1333
+ } catch (_) {
1334
+ return void 0;
1724
1335
  }
1725
- if (!isAtomKey(indirectDependencyKey, store)) {
1726
- indirectDependencyKeys.push(
1727
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
1728
- );
1729
- } else if (!rootKeys.includes(indirectDependencyKey)) {
1730
- rootKeys.push(indirectDependencyKey);
1336
+ }
1337
+ const state = withdraw(token, store);
1338
+ return readOrComputeValue(state, store);
1339
+ }
1340
+ var Molecule = class {
1341
+ constructor(ctx, key, family) {
1342
+ this.key = key;
1343
+ this.type = `molecule`;
1344
+ this.subject = new Subject();
1345
+ this.tokens = /* @__PURE__ */ new Map();
1346
+ this.above = /* @__PURE__ */ new Map();
1347
+ this.below = /* @__PURE__ */ new Map();
1348
+ this.joins = /* @__PURE__ */ new Map();
1349
+ this.stringKey = json.stringifyJson(key);
1350
+ if (family) {
1351
+ this.family = family;
1352
+ }
1353
+ if (ctx) {
1354
+ if (Array.isArray(ctx)) {
1355
+ for (const molecule of ctx) {
1356
+ this.above.set(molecule.stringKey, molecule);
1357
+ }
1358
+ } else {
1359
+ this.above.set(ctx.stringKey, ctx);
1360
+ }
1731
1361
  }
1732
1362
  }
1733
- return rootKeys;
1734
- };
1735
- var traceAllSelectorAtoms = (selector, store) => {
1736
- const selectorKey = selector.key;
1737
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1738
- return directDependencyKeys.flatMap(
1739
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1740
- );
1741
1363
  };
1742
1364
 
1743
- // internal/src/selector/update-selector-atoms.ts
1744
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
1365
+ // internal/src/molecule/make-molecule-in-store.ts
1366
+ function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1745
1367
  const target = newest(store);
1746
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1747
- target.selectorAtoms.set({
1748
- selectorKey,
1749
- atomKey: dependency.key
1750
- });
1751
- store.logger.info(
1752
- `\u{1F50D}`,
1753
- `selector`,
1754
- selectorKey,
1755
- `discovers root atom "${dependency.key}"`
1756
- );
1757
- } else {
1758
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1759
- store.logger.info(
1760
- `\u{1F50D}`,
1761
- `selector`,
1762
- selectorKey,
1763
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1764
- );
1765
- for (const atomKey of rootKeys) {
1766
- target.selectorAtoms = target.selectorAtoms.set({
1767
- selectorKey,
1768
- atomKey
1769
- });
1368
+ target.moleculeInProgress = key;
1369
+ const contextArray = Array.isArray(context) ? context : [context];
1370
+ const owners = contextArray.map((ctx) => {
1371
+ if (ctx instanceof Molecule) {
1372
+ return ctx;
1373
+ }
1374
+ const stringKey = json.stringifyJson(ctx.key);
1375
+ const molecule2 = store.molecules.get(stringKey);
1376
+ if (!molecule2) {
1377
+ throw new Error(
1378
+ `Molecule ${stringKey} not found in store "${store.config.name}"`
1379
+ );
1770
1380
  }
1381
+ return molecule2;
1382
+ });
1383
+ const molecule = new Molecule(owners, key, familyToken);
1384
+ target.molecules.set(json.stringifyJson(key), molecule);
1385
+ for (const owner of owners) {
1386
+ owner.below.set(molecule.stringKey, molecule);
1771
1387
  }
1772
- };
1773
-
1774
- // internal/src/selector/register-selector.ts
1775
- var registerSelector = (selectorKey, store) => ({
1776
- get: (dependency) => {
1777
- const target = newest(store);
1778
- const dependencyState = withdraw(dependency, store);
1779
- const dependencyValue = readOrComputeValue(dependencyState, store);
1780
- store.logger.info(
1781
- `\u{1F50C}`,
1782
- `selector`,
1783
- selectorKey,
1784
- `registers dependency ( "${dependency.key}" =`,
1785
- dependencyValue,
1786
- `)`
1787
- );
1788
- target.selectorGraph.set(
1789
- {
1790
- upstreamSelectorKey: dependency.key,
1791
- downstreamSelectorKey: selectorKey
1792
- },
1793
- {
1794
- source: dependency.key
1388
+ const transactors = {
1389
+ get: (t) => getFromStore(t, newest(store)),
1390
+ set: (t, newValue) => {
1391
+ setIntoStore(t, newValue, newest(store));
1392
+ },
1393
+ seek: (t, k) => seekInStore(t, k, newest(store)),
1394
+ json: (t) => getJsonToken(t, newest(store)),
1395
+ run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
1396
+ make: (ctx, f, k, ...args) => makeMoleculeInStore(newest(store), ctx, f, k, ...args),
1397
+ dispose: (t) => {
1398
+ disposeFromStore(t, newest(store));
1399
+ },
1400
+ env: () => getEnvironmentData(newest(store)),
1401
+ bond: (f) => growMoleculeInStore(
1402
+ molecule,
1403
+ withdraw(f, store),
1404
+ newest(store)
1405
+ ),
1406
+ claim: (below, options) => {
1407
+ const { exclusive } = options;
1408
+ const belowMolecule = newest(store).molecules.get(json.stringifyJson(below.key));
1409
+ if (belowMolecule) {
1410
+ if (exclusive) {
1411
+ for (const value of belowMolecule.above.values()) {
1412
+ value.below.delete(belowMolecule.stringKey);
1413
+ }
1414
+ belowMolecule.above.clear();
1415
+ belowMolecule.above.set(molecule.stringKey, molecule);
1416
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1417
+ } else {
1418
+ belowMolecule.above.set(molecule.stringKey, molecule);
1419
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1420
+ }
1795
1421
  }
1796
- );
1797
- updateSelectorAtoms(selectorKey, dependency, store);
1798
- return dependencyValue;
1799
- },
1800
- set: (WritableToken, newValue) => {
1801
- const state = withdraw(WritableToken, store);
1802
- setAtomOrSelector(state, newValue, store);
1803
- },
1804
- find: (token, key) => findInStore(token, key, store),
1805
- seek: (token, key) => seekInStore(token, key, store),
1806
- json: (token) => getJsonToken(token, store)
1807
- });
1808
-
1809
- // internal/src/selector/create-readonly-selector.ts
1810
- var createReadonlySelector = (options, family, store) => {
1811
- const target = newest(store);
1812
- const subject = new Subject();
1813
- const { get, find, seek, json } = registerSelector(options.key, target);
1814
- const getSelf = () => {
1815
- const value = options.get({ get, find, seek, json });
1816
- cacheValue(options.key, value, subject, newest(store));
1817
- return value;
1422
+ },
1423
+ join: (joinToken) => {
1424
+ const join = data.getJoin(joinToken, store);
1425
+ join.molecules.set(json.stringifyJson(key), molecule);
1426
+ molecule.joins.set(joinToken.key, join);
1427
+ return joinToken;
1428
+ },
1429
+ spawn: (f, k, ...p) => makeMoleculeInStore(
1430
+ newest(store),
1431
+ [molecule],
1432
+ withdraw(f, store),
1433
+ k,
1434
+ ...p
1435
+ )
1818
1436
  };
1819
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1820
- subject,
1821
- install: (s) => createReadonlySelector(options, family, s),
1822
- get: getSelf,
1823
- type: `readonly_selector`
1824
- }), family && { family });
1825
- target.readonlySelectors.set(options.key, readonlySelector);
1826
- const initialValue = getSelf();
1827
- store.logger.info(
1828
- `\u2728`,
1829
- readonlySelector.type,
1830
- readonlySelector.key,
1831
- `=`,
1832
- initialValue
1833
- );
1437
+ const family = withdraw(familyToken, store);
1438
+ const Constructor = family.new;
1439
+ molecule.instance = new Constructor(transactors, key, ...params);
1834
1440
  const token = {
1835
- key: options.key,
1836
- type: `readonly_selector`
1441
+ type: `molecule`,
1442
+ key,
1443
+ family: familyToken
1837
1444
  };
1838
- if (family) {
1839
- token.family = family;
1445
+ const update = {
1446
+ type: `molecule_creation`,
1447
+ token,
1448
+ family: familyToken,
1449
+ context: contextArray,
1450
+ params
1451
+ };
1452
+ if (isRootStore(target)) {
1453
+ family.subject.next(update);
1454
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1455
+ target.transactionMeta.update.updates.push(update);
1840
1456
  }
1457
+ target.moleculeInProgress = null;
1841
1458
  return token;
1842
- };
1459
+ }
1843
1460
 
1844
- // internal/src/selector/create-writable-selector.ts
1845
- var createWritableSelector = (options, family, store) => {
1846
- const target = newest(store);
1847
- const subject = new Subject();
1848
- const transactors = registerSelector(options.key, target);
1849
- const { find, get, seek, json } = transactors;
1850
- const readonlyTransactors = { find, get, seek, json };
1851
- const getSelf = () => {
1852
- const value = options.get(readonlyTransactors);
1853
- cacheValue(options.key, value, subject, newest(store));
1854
- return value;
1855
- };
1856
- const setSelf = (next) => {
1857
- const oldValue = getSelf();
1858
- const newValue = become(next)(oldValue);
1859
- store.logger.info(
1860
- `\u{1F4DD}`,
1861
- `selector`,
1862
- options.key,
1863
- `set (`,
1864
- oldValue,
1865
- `->`,
1866
- newValue,
1867
- `)`
1868
- );
1869
- cacheValue(options.key, newValue, subject, store);
1870
- markDone(options.key, store);
1871
- if (isRootStore(target)) {
1872
- subject.next({ newValue, oldValue });
1461
+ // internal/src/ingest-updates/ingest-creation-disposal.ts
1462
+ function ingestCreationEvent(update, applying, store) {
1463
+ switch (applying) {
1464
+ case `newValue`: {
1465
+ createInStore(update.token, store);
1466
+ break;
1467
+ }
1468
+ case `oldValue`: {
1469
+ disposeFromStore(update.token, store);
1470
+ break;
1873
1471
  }
1874
- options.set(transactors, newValue);
1875
- };
1876
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1877
- subject,
1878
- install: (s) => createWritableSelector(options, family, s),
1879
- get: getSelf,
1880
- set: setSelf,
1881
- type: `selector`
1882
- }), family && { family });
1883
- target.selectors.set(options.key, mySelector);
1884
- const initialValue = getSelf();
1885
- store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
1886
- const token = {
1887
- key: options.key,
1888
- type: `selector`
1889
- };
1890
- if (family) {
1891
- token.family = family;
1892
1472
  }
1893
- return token;
1894
- };
1473
+ }
1474
+ function ingestDisposalEvent(update, applying, store) {
1475
+ switch (applying) {
1476
+ case `newValue`: {
1477
+ disposeFromStore(update.token, store);
1478
+ break;
1479
+ }
1480
+ case `oldValue`: {
1481
+ createInStore(update.token, store);
1482
+ store.valueMap.set(update.token.key, update.value);
1483
+ break;
1484
+ }
1485
+ }
1486
+ }
1487
+ function createInStore(token, store) {
1488
+ if (token.family) {
1489
+ const family = store.families.get(token.family.key);
1490
+ if (family) {
1491
+ const molecule = store.molecules.get(token.family.subKey);
1492
+ if (molecule) {
1493
+ growMoleculeInStore(molecule, family, store);
1494
+ return;
1495
+ }
1496
+ if (store.config.lifespan === `immortal`) {
1497
+ throw new Error(`No molecule found for key "${token.family.subKey}"`);
1498
+ }
1499
+ initFamilyMemberInStore(family, json.parseJson(token.family.subKey), store);
1500
+ }
1501
+ }
1502
+ }
1503
+ function ingestMoleculeCreationEvent(update, applying, store) {
1504
+ switch (applying) {
1505
+ case `newValue`:
1506
+ makeMoleculeInStore(
1507
+ store,
1508
+ update.context,
1509
+ update.family,
1510
+ update.token.key,
1511
+ ...update.params
1512
+ );
1513
+ break;
1514
+ case `oldValue`:
1515
+ disposeFromStore(update.token, store);
1516
+ break;
1517
+ }
1518
+ }
1519
+ function ingestMoleculeDisposalEvent(update, applying, store) {
1520
+ switch (applying) {
1521
+ case `newValue`:
1522
+ disposeFromStore(update.token, store);
1523
+ break;
1524
+ case `oldValue`:
1525
+ {
1526
+ const moleculeToken = makeMoleculeInStore(
1527
+ store,
1528
+ update.context,
1529
+ update.family,
1530
+ update.token.key
1531
+ );
1532
+ for (const [familyKey, value] of update.values) {
1533
+ const memberKey = `${familyKey}(${json.stringifyJson(moleculeToken.key)})`;
1534
+ const molecule = withdraw(moleculeToken, store);
1535
+ const alreadyCreated = molecule.tokens.has(memberKey);
1536
+ const family = store.families.get(familyKey);
1537
+ if (family && !alreadyCreated) {
1538
+ growMoleculeInStore(molecule, family, store);
1539
+ }
1540
+ store.valueMap.set(memberKey, value);
1541
+ }
1542
+ }
1543
+ break;
1544
+ }
1545
+ }
1895
1546
 
1896
- // internal/src/selector/create-standalone-selector.ts
1897
- function createStandaloneSelector(options, store) {
1898
- const isWritable = `set` in options;
1899
- if (isWritable) {
1900
- const state2 = createWritableSelector(options, void 0, store);
1901
- store.on.selectorCreation.next(state2);
1902
- return state2;
1547
+ // internal/src/ingest-updates/ingest-selector-update.ts
1548
+ function ingestSelectorUpdate(applying, selectorUpdate, store) {
1549
+ const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1550
+ for (const atomUpdate of updates) {
1551
+ ingestAtomUpdate(applying, atomUpdate, store);
1903
1552
  }
1904
- const state = createReadonlySelector(options, void 0, store);
1905
- store.on.selectorCreation.next(state);
1906
- return state;
1907
1553
  }
1908
1554
 
1909
- // internal/src/selector/dispose-selector.ts
1910
- function disposeSelector(selectorToken, store) {
1555
+ // internal/src/ingest-updates/ingest-transaction-update.ts
1556
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1557
+ const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1558
+ for (const updateFromTransaction of updates) {
1559
+ switch (updateFromTransaction.type) {
1560
+ case `atom_update`:
1561
+ case `selector_update`:
1562
+ ingestAtomUpdate(applying, updateFromTransaction, store);
1563
+ break;
1564
+ case `state_creation`:
1565
+ ingestCreationEvent(updateFromTransaction, applying, store);
1566
+ break;
1567
+ case `state_disposal`:
1568
+ ingestDisposalEvent(updateFromTransaction, applying, store);
1569
+ break;
1570
+ case `molecule_creation`:
1571
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1572
+ break;
1573
+ case `molecule_disposal`:
1574
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1575
+ break;
1576
+ case `transaction_update`:
1577
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
1578
+ break;
1579
+ }
1580
+ }
1581
+ }
1582
+
1583
+ // internal/src/transaction/set-epoch-number.ts
1584
+ function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
1585
+ const isRoot = isRootStore(store);
1586
+ if (isRoot && continuityKey) {
1587
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1588
+ }
1589
+ }
1590
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1591
+ const isRoot = isRootStore(store);
1592
+ if (!isRoot) {
1593
+ return;
1594
+ }
1595
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1596
+ if (continuityKey !== void 0) {
1597
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1598
+ }
1599
+ }
1600
+
1601
+ // internal/src/transaction/apply-transaction.ts
1602
+ var applyTransaction = (output, store) => {
1911
1603
  var _a;
1912
- const target = newest(store);
1913
- const { key } = selectorToken;
1914
- const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1915
- if (!selector) {
1916
- store.logger.info(
1917
- `\u274C`,
1918
- `selector`,
1919
- key,
1920
- `Tried to dispose selector, but it does not exist in the store.`
1604
+ const child = newest(store);
1605
+ const { parent } = child;
1606
+ if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
1607
+ store.logger.warn(
1608
+ `\u{1F41E}`,
1609
+ `transaction`,
1610
+ `???`,
1611
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1921
1612
  );
1922
- } else if (!selector.family) {
1923
- store.logger.error(
1924
- `\u274C`,
1925
- `selector`,
1926
- key,
1927
- `Standalone selectors cannot be disposed.`
1613
+ return;
1614
+ }
1615
+ child.transactionMeta.phase = `applying`;
1616
+ child.transactionMeta.update.output = output;
1617
+ parent.child = null;
1618
+ parent.on.transactionApplying.next(child.transactionMeta);
1619
+ const { updates } = child.transactionMeta.update;
1620
+ store.logger.info(
1621
+ `\u{1F6C4}`,
1622
+ `transaction`,
1623
+ child.transactionMeta.update.key,
1624
+ `Applying transaction with ${updates.length} updates:`,
1625
+ updates
1626
+ );
1627
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1628
+ if (isRootStore(parent)) {
1629
+ setEpochNumberOfAction(
1630
+ child.transactionMeta.update.key,
1631
+ child.transactionMeta.update.epoch,
1632
+ parent
1928
1633
  );
1929
- } else {
1930
- switch (selectorToken.type) {
1931
- case `selector`:
1932
- {
1933
- target.selectors.delete(key);
1934
- const family = withdraw(
1935
- { key: selector.family.key, type: `selector_family` },
1936
- store
1937
- );
1938
- family.subject.next({
1939
- type: `state_disposal`,
1940
- token: selectorToken
1941
- });
1634
+ const myTransaction = withdraw(
1635
+ { key: child.transactionMeta.update.key, type: `transaction` },
1636
+ store
1637
+ );
1638
+ myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
1639
+ store.logger.info(
1640
+ `\u{1F6EC}`,
1641
+ `transaction`,
1642
+ child.transactionMeta.update.key,
1643
+ `Finished applying transaction.`
1644
+ );
1645
+ } else if (isChildStore(parent)) {
1646
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1647
+ }
1648
+ parent.on.transactionApplying.next(null);
1649
+ };
1650
+
1651
+ // internal/src/transaction/assign-transaction-to-continuity.ts
1652
+ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1653
+ const isRoot = isRootStore(store);
1654
+ if (!isRoot) {
1655
+ return;
1656
+ }
1657
+ const { epoch, actionContinuities } = store.transactionMeta;
1658
+ actionContinuities.set(continuityKey, transactionKey);
1659
+ if (!epoch.has(continuityKey)) {
1660
+ epoch.set(continuityKey, -1);
1661
+ }
1662
+ }
1663
+
1664
+ // internal/src/lazy-map.ts
1665
+ var LazyMap = class extends Map {
1666
+ constructor(source) {
1667
+ super();
1668
+ this.source = source;
1669
+ this.deleted = /* @__PURE__ */ new Set();
1670
+ }
1671
+ get(key) {
1672
+ const has = super.has(key);
1673
+ if (has) {
1674
+ return super.get(key);
1675
+ }
1676
+ if (!this.deleted.has(key) && this.source.has(key)) {
1677
+ const value = this.source.get(key);
1678
+ return value;
1679
+ }
1680
+ return void 0;
1681
+ }
1682
+ set(key, value) {
1683
+ this.deleted.delete(key);
1684
+ return super.set(key, value);
1685
+ }
1686
+ hasOwn(key) {
1687
+ return super.has(key);
1688
+ }
1689
+ has(key) {
1690
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1691
+ }
1692
+ delete(key) {
1693
+ this.deleted.add(key);
1694
+ return super.delete(key);
1695
+ }
1696
+ };
1697
+
1698
+ // internal/src/transaction/build-transaction.ts
1699
+ var buildTransaction = (key, params, store, id) => {
1700
+ const parent = newest(store);
1701
+ const childBase = {
1702
+ parent,
1703
+ child: null,
1704
+ on: parent.on,
1705
+ loggers: parent.loggers,
1706
+ logger: parent.logger,
1707
+ config: parent.config,
1708
+ atoms: new LazyMap(parent.atoms),
1709
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1710
+ families: new LazyMap(parent.families),
1711
+ operation: { open: false },
1712
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
1713
+ timelines: new LazyMap(parent.timelines),
1714
+ timelineTopics: new Junction(parent.timelineTopics.toJSON()),
1715
+ trackers: /* @__PURE__ */ new Map(),
1716
+ transactions: new LazyMap(parent.transactions),
1717
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1718
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1719
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1720
+ }),
1721
+ selectors: new LazyMap(parent.selectors),
1722
+ valueMap: new LazyMap(parent.valueMap),
1723
+ molecules: new LazyMap(parent.molecules),
1724
+ moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1725
+ moleculeInProgress: parent.moleculeInProgress,
1726
+ miscResources: new LazyMap(parent.miscResources)
1727
+ };
1728
+ const epoch = getEpochNumberOfAction(key, store);
1729
+ const transactionMeta = {
1730
+ phase: `building`,
1731
+ update: {
1732
+ type: `transaction_update`,
1733
+ key,
1734
+ id,
1735
+ epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1736
+ updates: [],
1737
+ params,
1738
+ output: void 0
1739
+ },
1740
+ transactors: {
1741
+ get: (token) => getFromStore(token, child),
1742
+ set: (token, value) => {
1743
+ setIntoStore(token, value, child);
1744
+ },
1745
+ run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1746
+ find: (token, k) => findInStore(token, k, child),
1747
+ seek: (token, k) => seekInStore(token, k, child),
1748
+ json: (token) => getJsonToken(token, child),
1749
+ make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1750
+ dispose: (token) => {
1751
+ disposeFromStore(token, child);
1752
+ },
1753
+ env: () => getEnvironmentData(child)
1754
+ }
1755
+ };
1756
+ const child = Object.assign(childBase, {
1757
+ transactionMeta
1758
+ });
1759
+ parent.child = child;
1760
+ store.logger.info(
1761
+ `\u{1F6EB}`,
1762
+ `transaction`,
1763
+ key,
1764
+ `Building transaction with params:`,
1765
+ params
1766
+ );
1767
+ return child;
1768
+ };
1769
+
1770
+ // internal/src/transaction/create-transaction.ts
1771
+ function createTransaction(options, store) {
1772
+ const newTransaction = {
1773
+ key: options.key,
1774
+ type: `transaction`,
1775
+ run: (params, id) => {
1776
+ const childStore = buildTransaction(options.key, params, store, id);
1777
+ try {
1778
+ const target2 = newest(store);
1779
+ const { transactors } = childStore.transactionMeta;
1780
+ const output = options.do(transactors, ...params);
1781
+ applyTransaction(output, target2);
1782
+ return output;
1783
+ } catch (thrown) {
1784
+ abortTransaction(target);
1785
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1786
+ throw thrown;
1787
+ }
1788
+ },
1789
+ install: (s) => createTransaction(options, s),
1790
+ subject: new Subject()
1791
+ };
1792
+ const target = newest(store);
1793
+ target.transactions.set(newTransaction.key, newTransaction);
1794
+ const token = deposit(newTransaction);
1795
+ store.on.transactionCreation.next(token);
1796
+ return token;
1797
+ }
1798
+
1799
+ // internal/src/transaction/get-epoch-number.ts
1800
+ function getContinuityKey(transactionKey, store) {
1801
+ const isRoot = isRootStore(store);
1802
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1803
+ return continuity;
1804
+ }
1805
+ function getEpochNumberOfContinuity(continuityKey, store) {
1806
+ const isRoot = isRootStore(store);
1807
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1808
+ return epoch;
1809
+ }
1810
+ function getEpochNumberOfAction(transactionKey, store) {
1811
+ const isRoot = isRootStore(store);
1812
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1813
+ const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1814
+ return epoch;
1815
+ }
1816
+
1817
+ // internal/src/transaction/index.ts
1818
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1819
+
1820
+ // internal/src/store/store.ts
1821
+ var Store = class {
1822
+ constructor(config, store = null) {
1823
+ this.parent = null;
1824
+ this.child = null;
1825
+ this.valueMap = /* @__PURE__ */ new Map();
1826
+ this.atoms = /* @__PURE__ */ new Map();
1827
+ this.selectors = /* @__PURE__ */ new Map();
1828
+ this.readonlySelectors = /* @__PURE__ */ new Map();
1829
+ this.atomsThatAreDefault = /* @__PURE__ */ new Set();
1830
+ this.selectorAtoms = new Junction({
1831
+ between: [`selectorKey`, `atomKey`],
1832
+ cardinality: `n:n`
1833
+ });
1834
+ this.selectorGraph = new Junction(
1835
+ {
1836
+ between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
1837
+ cardinality: `n:n`
1838
+ },
1839
+ {
1840
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1841
+ }
1842
+ );
1843
+ this.trackers = /* @__PURE__ */ new Map();
1844
+ this.families = /* @__PURE__ */ new Map();
1845
+ this.transactions = /* @__PURE__ */ new Map();
1846
+ this.transactionMeta = {
1847
+ epoch: /* @__PURE__ */ new Map(),
1848
+ actionContinuities: new Junction({
1849
+ between: [`continuity`, `action`],
1850
+ cardinality: `1:n`
1851
+ })
1852
+ };
1853
+ this.timelines = /* @__PURE__ */ new Map();
1854
+ this.timelineTopics = new Junction({
1855
+ between: [`timelineKey`, `topicKey`],
1856
+ cardinality: `1:n`
1857
+ });
1858
+ this.molecules = /* @__PURE__ */ new Map();
1859
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
1860
+ this.moleculeInProgress = null;
1861
+ this.miscResources = /* @__PURE__ */ new Map();
1862
+ this.on = {
1863
+ atomCreation: new Subject(),
1864
+ atomDisposal: new Subject(),
1865
+ selectorCreation: new Subject(),
1866
+ selectorDisposal: new Subject(),
1867
+ timelineCreation: new Subject(),
1868
+ transactionCreation: new Subject(),
1869
+ transactionApplying: new StatefulSubject(
1870
+ null
1871
+ ),
1872
+ operationClose: new Subject(),
1873
+ moleculeCreationStart: new Subject(),
1874
+ moleculeCreationDone: new Subject(),
1875
+ moleculeDisposal: new Subject()
1876
+ };
1877
+ this.operation = { open: false };
1878
+ this.config = {
1879
+ name: `IMPLICIT_STORE`,
1880
+ lifespan: `ephemeral`
1881
+ };
1882
+ this.loggers = [
1883
+ new atom_io.AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
1884
+ ];
1885
+ this.logger = {
1886
+ error: (...messages) => {
1887
+ for (const logger of this.loggers) logger.error(...messages);
1888
+ },
1889
+ info: (...messages) => {
1890
+ for (const logger of this.loggers) logger.info(...messages);
1891
+ },
1892
+ warn: (...messages) => {
1893
+ for (const logger of this.loggers) logger.warn(...messages);
1894
+ }
1895
+ };
1896
+ if (store !== null) {
1897
+ this.valueMap = new Map(store == null ? void 0 : store.valueMap);
1898
+ this.operation = __spreadValues({}, store == null ? void 0 : store.operation);
1899
+ if (isRootStore(store)) {
1900
+ this.transactionMeta = {
1901
+ epoch: new Map(store == null ? void 0 : store.transactionMeta.epoch),
1902
+ actionContinuities: new Junction(
1903
+ store == null ? void 0 : store.transactionMeta.actionContinuities.toJSON()
1904
+ )
1905
+ };
1906
+ }
1907
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
1908
+ for (const [, family] of store.families) {
1909
+ family.install(this);
1910
+ }
1911
+ const mutableHelpers = /* @__PURE__ */ new Set();
1912
+ for (const [, atom] of store.atoms) {
1913
+ if (mutableHelpers.has(atom.key)) {
1914
+ continue;
1942
1915
  }
1916
+ atom.install(this);
1917
+ if (atom.type === `mutable_atom`) {
1918
+ const originalJsonToken = getJsonToken(atom, store);
1919
+ const originalUpdateToken = getUpdateToken(atom);
1920
+ mutableHelpers.add(originalJsonToken.key);
1921
+ mutableHelpers.add(originalUpdateToken.key);
1922
+ }
1923
+ }
1924
+ for (const [, selector] of store.readonlySelectors) {
1925
+ selector.install(this);
1926
+ }
1927
+ for (const [, selector] of store.selectors) {
1928
+ if (mutableHelpers.has(selector.key)) {
1929
+ continue;
1930
+ }
1931
+ selector.install(this);
1932
+ }
1933
+ for (const [, tx] of store.transactions) {
1934
+ tx.install(this);
1935
+ }
1936
+ for (const [, timeline] of store.timelines) {
1937
+ timeline.install(this);
1938
+ }
1939
+ }
1940
+ }
1941
+ };
1942
+ var IMPLICIT = {
1943
+ STORE_INTERNAL: void 0,
1944
+ get STORE() {
1945
+ var _a;
1946
+ return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
1947
+ name: `IMPLICIT_STORE`,
1948
+ lifespan: `ephemeral`
1949
+ });
1950
+ }
1951
+ };
1952
+ var clearStore = (store) => {
1953
+ const { config } = store;
1954
+ for (const disposable of store.miscResources.values()) {
1955
+ disposable[Symbol.dispose]();
1956
+ }
1957
+ Object.assign(store, new Store(config));
1958
+ store.config = config;
1959
+ };
1960
+ function withdraw(token, store) {
1961
+ let withdrawn;
1962
+ let target = store;
1963
+ while (target !== null) {
1964
+ switch (token.type) {
1965
+ case `atom`:
1966
+ case `mutable_atom`:
1967
+ withdrawn = target.atoms.get(token.key);
1968
+ break;
1969
+ case `selector`:
1970
+ withdrawn = target.selectors.get(token.key);
1971
+ break;
1972
+ case `readonly_selector`:
1973
+ withdrawn = target.readonlySelectors.get(token.key);
1974
+ break;
1975
+ case `atom_family`:
1976
+ case `mutable_atom_family`:
1977
+ case `selector_family`:
1978
+ case `readonly_selector_family`:
1979
+ withdrawn = target.families.get(token.key);
1980
+ break;
1981
+ case `timeline`:
1982
+ withdrawn = target.timelines.get(token.key);
1983
+ break;
1984
+ case `transaction`:
1985
+ withdrawn = target.transactions.get(token.key);
1943
1986
  break;
1944
- case `readonly_selector`:
1945
- {
1946
- target.readonlySelectors.delete(key);
1947
- const family = withdraw(
1948
- { key: selector.family.key, type: `readonly_selector_family` },
1949
- store
1950
- );
1951
- family.subject.next({
1952
- type: `state_disposal`,
1953
- token: selectorToken
1954
- });
1955
- }
1987
+ case `molecule`:
1988
+ withdrawn = target.molecules.get(json.stringifyJson(token.key));
1989
+ break;
1990
+ case `molecule_family`:
1991
+ withdrawn = target.moleculeFamilies.get(token.key);
1956
1992
  break;
1957
1993
  }
1958
- target.valueMap.delete(key);
1959
- target.selectorAtoms.delete(key);
1960
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1961
- ([downstreamSelectorKey]) => {
1962
- var _a2;
1963
- return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1964
- }
1965
- );
1966
- for (const downstreamToken of downstreamTokens) {
1967
- if (downstreamToken) {
1968
- disposeSelector(downstreamToken, store);
1969
- }
1970
- }
1971
- target.selectorGraph.delete(key);
1972
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1973
- if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1974
- target.transactionMeta.update.updates.push({
1975
- type: `state_disposal`,
1976
- token: selectorToken
1977
- });
1978
- } else {
1979
- store.on.selectorDisposal.next(selectorToken);
1994
+ if (withdrawn) {
1995
+ return withdrawn;
1980
1996
  }
1997
+ target = target.child;
1981
1998
  }
1999
+ throw new NotFoundError(token, store);
1982
2000
  }
1983
2001
 
1984
2002
  // internal/src/subscribe/recall-state.ts
@@ -2175,7 +2193,7 @@ var Tracker = class {
2175
2193
  subscribeToState(
2176
2194
  latestUpdateState,
2177
2195
  ({ newValue, oldValue }) => {
2178
- const timelineId = target.timelineAtoms.getRelatedKey(
2196
+ const timelineId = target.timelineTopics.getRelatedKey(
2179
2197
  latestUpdateState.key
2180
2198
  );
2181
2199
  if (timelineId) {
@@ -2626,6 +2644,10 @@ function disposeAtom(atomToken, store) {
2626
2644
  token: atomToken,
2627
2645
  value: lastValue
2628
2646
  });
2647
+ const molecule = target.molecules.get(atom.family.subKey);
2648
+ if (molecule) {
2649
+ molecule.tokens.delete(key);
2650
+ }
2629
2651
  target.atoms.delete(key);
2630
2652
  target.valueMap.delete(key);
2631
2653
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -2639,7 +2661,7 @@ function disposeAtom(atomToken, store) {
2639
2661
  }
2640
2662
  target.selectorAtoms.delete(key);
2641
2663
  target.atomsThatAreDefault.delete(key);
2642
- target.timelineAtoms.delete(key);
2664
+ target.timelineTopics.delete(key);
2643
2665
  if (atomToken.type === `mutable_atom`) {
2644
2666
  const updateToken = getUpdateToken(atomToken);
2645
2667
  disposeAtom(updateToken, store);
@@ -2656,26 +2678,123 @@ function disposeAtom(atomToken, store) {
2656
2678
  }
2657
2679
  }
2658
2680
  }
2659
-
2660
- // internal/src/timeline/add-atom-to-timeline.ts
2661
- var addAtomToTimeline = (atomToken, tl, store) => {
2681
+ function createTimeline(options, store, data) {
2682
+ var _a;
2683
+ const tl = __spreadProps(__spreadValues({
2684
+ type: `timeline`,
2685
+ key: options.key,
2686
+ at: 0,
2687
+ timeTraveling: null,
2688
+ selectorTime: null,
2689
+ transactionKey: null
2690
+ }, data), {
2691
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2692
+ install: (s) => createTimeline(options, s, tl),
2693
+ subject: new Subject(),
2694
+ subscriptions: /* @__PURE__ */ new Map()
2695
+ });
2696
+ if (options.shouldCapture) {
2697
+ tl.shouldCapture = options.shouldCapture;
2698
+ }
2699
+ const timelineKey = options.key;
2700
+ const target = newest(store);
2701
+ for (const initialTopic of options.scope) {
2702
+ switch (initialTopic.type) {
2703
+ case `atom`:
2704
+ case `mutable_atom`:
2705
+ {
2706
+ const atomToken = initialTopic;
2707
+ const atomKey = atomToken.key;
2708
+ let existingTimelineKey = target.timelineTopics.getRelatedKey(atomKey);
2709
+ if (`family` in atomToken) {
2710
+ const familyKey = atomToken.family.key;
2711
+ existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2712
+ if (existingTimelineKey) {
2713
+ store.logger.error(
2714
+ `\u274C`,
2715
+ `timeline`,
2716
+ options.key,
2717
+ `Failed to add atom "${atomKey}" because its family "${familyKey}" already belongs to timeline "${existingTimelineKey}"`
2718
+ );
2719
+ continue;
2720
+ }
2721
+ }
2722
+ if (existingTimelineKey) {
2723
+ store.logger.error(
2724
+ `\u274C`,
2725
+ `timeline`,
2726
+ options.key,
2727
+ `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2728
+ );
2729
+ continue;
2730
+ }
2731
+ addAtomToTimeline(atomToken, tl, store);
2732
+ }
2733
+ break;
2734
+ case `atom_family`:
2735
+ case `mutable_atom_family`:
2736
+ {
2737
+ const familyToken = initialTopic;
2738
+ const familyKey = familyToken.key;
2739
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2740
+ if (existingTimelineKey) {
2741
+ store.logger.error(
2742
+ `\u274C`,
2743
+ `timeline`,
2744
+ options.key,
2745
+ `Failed to add atom family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2746
+ );
2747
+ continue;
2748
+ }
2749
+ addAtomFamilyToTimeline(familyToken, tl, store);
2750
+ }
2751
+ break;
2752
+ case `molecule_family`:
2753
+ {
2754
+ const familyToken = initialTopic;
2755
+ const familyKey = familyToken.key;
2756
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2757
+ if (existingTimelineKey) {
2758
+ store.logger.error(
2759
+ `\u274C`,
2760
+ `timeline`,
2761
+ options.key,
2762
+ `Failed to add molecule family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2763
+ );
2764
+ continue;
2765
+ }
2766
+ addMoleculeFamilyToTimeline(familyToken, tl, store);
2767
+ }
2768
+ break;
2769
+ }
2770
+ }
2771
+ store.timelines.set(options.key, tl);
2772
+ const token = {
2773
+ key: timelineKey,
2774
+ type: `timeline`
2775
+ };
2776
+ store.on.timelineCreation.next(token);
2777
+ return token;
2778
+ }
2779
+ function addAtomToTimeline(atomToken, tl, store) {
2662
2780
  let maybeAtom = withdraw(atomToken, store);
2663
2781
  if (maybeAtom.type === `mutable_atom`) {
2664
2782
  const updateToken = getUpdateToken(maybeAtom);
2665
2783
  maybeAtom = withdraw(updateToken, store);
2666
2784
  }
2667
2785
  const atom = maybeAtom;
2668
- store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
2786
+ store.timelineTopics.set(
2787
+ { topicKey: atom.key, timelineKey: tl.key },
2788
+ { topicType: `atom` }
2789
+ );
2669
2790
  tl.subscriptions.set(
2670
2791
  atom.key,
2671
2792
  atom.subject.subscribe(`timeline`, (update) => {
2672
- var _a, _b, _c, _d, _e, _f;
2793
+ var _a, _b, _c, _d, _e;
2673
2794
  const target = newest(store);
2674
2795
  const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2675
2796
  const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2676
- const { transactionApplying } = target.on;
2677
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
2678
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
2797
+ const txUpdateInProgress = (_a = target.on.transactionApplying.state) == null ? void 0 : _a.update;
2679
2798
  store.logger.info(
2680
2799
  `\u23F3`,
2681
2800
  `timeline`,
@@ -2686,109 +2805,11 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2686
2805
  update.oldValue,
2687
2806
  `->`,
2688
2807
  update.newValue,
2689
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2808
+ txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2690
2809
  );
2691
2810
  if (tl.timeTraveling === null) {
2692
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2693
- const mostRecentUpdate = tl.history.at(-1);
2694
- if (mostRecentUpdate === void 0) {
2695
- throw new Error(
2696
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
2697
- );
2698
- }
2699
- }
2700
- if (currentTransactionKey) {
2701
- const txToken = {
2702
- key: currentTransactionKey,
2703
- type: `transaction`
2704
- };
2705
- const currentTransaction = withdraw(txToken, store);
2706
- if (tl.transactionKey !== currentTransactionKey) {
2707
- if (tl.transactionKey) {
2708
- store.logger.error(
2709
- `\u{1F41E}`,
2710
- `timeline`,
2711
- tl.key,
2712
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2713
- );
2714
- }
2715
- tl.transactionKey = currentTransactionKey;
2716
- const unsubscribe = currentTransaction.subject.subscribe(
2717
- `timeline:${tl.key}`,
2718
- (transactionUpdate) => {
2719
- var _a2, _b2;
2720
- unsubscribe();
2721
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
2722
- if (tl.at !== tl.history.length) {
2723
- tl.history.splice(tl.at);
2724
- }
2725
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2726
- var _a3, _b3;
2727
- const newestStore = newest(store);
2728
- if (`updates` in updateFromTx) {
2729
- return true;
2730
- }
2731
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2732
- if (!atomOrFamilyKeys) {
2733
- return false;
2734
- }
2735
- let key;
2736
- let familyKey;
2737
- switch (updateFromTx.type) {
2738
- case `state_creation`:
2739
- case `state_disposal`:
2740
- key = updateFromTx.token.key;
2741
- familyKey = (_a3 = updateFromTx.token.family) == null ? void 0 : _a3.key;
2742
- break;
2743
- case `molecule_creation`:
2744
- case `molecule_disposal`:
2745
- break;
2746
- default:
2747
- key = updateFromTx.key;
2748
- familyKey = (_b3 = updateFromTx.family) == null ? void 0 : _b3.key;
2749
- break;
2750
- }
2751
- if (key === void 0) {
2752
- return false;
2753
- }
2754
- if (atomOrFamilyKeys.has(key)) {
2755
- return true;
2756
- }
2757
- if (familyKey !== void 0) {
2758
- return atomOrFamilyKeys.has(familyKey);
2759
- }
2760
- return false;
2761
- }).map((updateFromTx) => {
2762
- if (`updates` in updateFromTx) {
2763
- return __spreadProps(__spreadValues({}, updateFromTx), {
2764
- updates: filterUpdates(updateFromTx.updates)
2765
- });
2766
- }
2767
- return updateFromTx;
2768
- });
2769
- const updates = filterUpdates(transactionUpdate.updates);
2770
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
2771
- timestamp: Date.now()
2772
- }, transactionUpdate), {
2773
- updates
2774
- });
2775
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2776
- if (willCapture) {
2777
- tl.history.push(timelineTransactionUpdate);
2778
- tl.at = tl.history.length;
2779
- tl.subject.next(timelineTransactionUpdate);
2780
- }
2781
- }
2782
- tl.transactionKey = null;
2783
- store.logger.info(
2784
- `\u231B`,
2785
- `timeline`,
2786
- tl.key,
2787
- `got a transaction_update "${transactionUpdate.key}"`
2788
- );
2789
- }
2790
- );
2791
- }
2811
+ if (txUpdateInProgress) {
2812
+ joinTransaction(tl, txUpdateInProgress, store);
2792
2813
  } else if (currentSelectorKey && currentSelectorTime) {
2793
2814
  let latestUpdate = tl.history.at(-1);
2794
2815
  if (currentSelectorTime !== tl.selectorTime) {
@@ -2831,7 +2852,7 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2831
2852
  }
2832
2853
  }
2833
2854
  if (latestUpdate) {
2834
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2855
+ const willCaptureSelectorUpdate = (_c = (_b = tl.shouldCapture) == null ? void 0 : _b.call(tl, latestUpdate, tl)) != null ? _c : true;
2835
2856
  if (willCaptureSelectorUpdate) {
2836
2857
  tl.subject.next(latestUpdate);
2837
2858
  } else {
@@ -2855,7 +2876,7 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2855
2876
  if (atom.family) {
2856
2877
  atomUpdate.family = atom.family;
2857
2878
  }
2858
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
2879
+ const willCapture = (_e = (_d = tl.shouldCapture) == null ? void 0 : _d.call(tl, atomUpdate, tl)) != null ? _e : true;
2859
2880
  store.logger.info(
2860
2881
  `\u231B`,
2861
2882
  `timeline`,
@@ -2871,181 +2892,207 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2871
2892
  }
2872
2893
  })
2873
2894
  );
2874
- };
2875
- function createTimeline(options, store, data) {
2876
- var _a, _b;
2877
- const tl = __spreadProps(__spreadValues({
2878
- type: `timeline`,
2879
- key: options.key,
2880
- at: 0,
2881
- timeTraveling: null,
2882
- selectorTime: null,
2883
- transactionKey: null
2884
- }, data), {
2885
- history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2886
- install: (s) => createTimeline(options, s, tl),
2887
- subject: new Subject(),
2888
- subscriptions: /* @__PURE__ */ new Map()
2889
- });
2890
- if (options.shouldCapture) {
2891
- tl.shouldCapture = options.shouldCapture;
2895
+ }
2896
+ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
2897
+ var _a;
2898
+ const family = withdraw(atomFamilyToken, store);
2899
+ store.timelineTopics.set(
2900
+ { topicKey: family.key, timelineKey: tl.key },
2901
+ { topicType: `atom_family` }
2902
+ );
2903
+ tl.subscriptions.set(
2904
+ family.key,
2905
+ family.subject.subscribe(`timeline`, (creationOrDisposal) => {
2906
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
2907
+ })
2908
+ );
2909
+ for (const atom of store.atoms.values()) {
2910
+ if (((_a = atom.family) == null ? void 0 : _a.key) === family.key) {
2911
+ addAtomToTimeline(atom, tl, store);
2912
+ }
2892
2913
  }
2893
- const timelineKey = options.key;
2894
- const target = newest(store);
2895
- for (const tokenOrFamily of options.scope) {
2896
- let atomKey = tokenOrFamily.key;
2897
- switch (tokenOrFamily.type) {
2898
- case `atom_family`:
2899
- case `mutable_atom_family`:
2900
- {
2901
- const familyToken = tokenOrFamily;
2902
- const family = withdraw(familyToken, store);
2903
- const familyKey = family.key;
2904
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2905
- tl.subscriptions.set(
2906
- family.key,
2907
- family.subject.subscribe(
2908
- `timeline:${options.key}`,
2909
- (creationOrDisposal) => {
2910
- handleStateLifecycleEvent(creationOrDisposal, tl, store);
2914
+ }
2915
+ function addMoleculeFamilyToTimeline(familyToken, tl, store) {
2916
+ store.timelineTopics.set(
2917
+ { topicKey: familyToken.key, timelineKey: tl.key },
2918
+ { topicType: `molecule_family` }
2919
+ );
2920
+ const family = store.moleculeFamilies.get(familyToken.key);
2921
+ if (family) {
2922
+ tl.subscriptions.set(
2923
+ familyToken.key,
2924
+ family.subject.subscribe(`timeline:${tl.key}`, (creationOrDisposal) => {
2925
+ var _a, _b, _c, _d;
2926
+ store.logger.info(
2927
+ `\u{1F41E}`,
2928
+ `timeline`,
2929
+ tl.key,
2930
+ `got a molecule creation or disposal`,
2931
+ creationOrDisposal
2932
+ );
2933
+ switch (creationOrDisposal.type) {
2934
+ case `molecule_creation`:
2935
+ {
2936
+ store.timelineTopics.set(
2937
+ {
2938
+ topicKey: creationOrDisposal.token.key,
2939
+ timelineKey: tl.key
2940
+ },
2941
+ { topicType: `molecule` }
2942
+ );
2943
+ const txUpdateInProgress = (_a = newest(store).on.transactionApplying.state) == null ? void 0 : _a.update;
2944
+ if (txUpdateInProgress) {
2945
+ joinTransaction(tl, txUpdateInProgress, store);
2946
+ } else if (tl.timeTraveling === null) {
2947
+ const event = Object.assign(creationOrDisposal, {
2948
+ timestamp: Date.now()
2949
+ });
2950
+ tl.history.push(event);
2951
+ tl.at = tl.history.length;
2952
+ tl.subject.next(event);
2911
2953
  }
2912
- )
2913
- );
2914
- for (const atom of target.atoms.values()) {
2915
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2916
- addAtomToTimeline(atom, tl, store);
2917
- }
2918
- }
2919
- }
2920
- break;
2921
- case `atom`:
2922
- case `mutable_atom`:
2923
- {
2924
- let atom = withdraw(tokenOrFamily, store);
2925
- if (isMutable(atom)) {
2926
- const updateAtom = withdraw(getUpdateToken(atom), store);
2927
- atom = updateAtom;
2928
- atomKey = atom.key;
2929
- }
2930
- if (`family` in atom) {
2931
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2932
- atom.family.key
2933
- );
2934
- if (familyTimelineKey) {
2935
- store.logger.error(
2936
- `\u274C`,
2937
- `timeline`,
2938
- options.key,
2939
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
2954
+ const molecule = withdraw(creationOrDisposal.token, store);
2955
+ for (const token of molecule.tokens.values()) {
2956
+ switch (token.type) {
2957
+ case `atom`:
2958
+ case `mutable_atom`:
2959
+ addAtomToTimeline(token, tl, store);
2960
+ break;
2961
+ }
2962
+ }
2963
+ tl.subscriptions.set(
2964
+ molecule.key,
2965
+ molecule.subject.subscribe(
2966
+ `timeline:${tl.key}`,
2967
+ (stateCreationOrDisposal) => {
2968
+ handleStateLifecycleEvent(stateCreationOrDisposal, tl, store);
2969
+ }
2970
+ )
2940
2971
  );
2941
- continue;
2942
2972
  }
2973
+ break;
2974
+ case `molecule_disposal`:
2975
+ {
2976
+ const txUpdateInProgress = (_b = newest(store).on.transactionApplying.state) == null ? void 0 : _b.update;
2977
+ if (txUpdateInProgress) {
2978
+ joinTransaction(tl, txUpdateInProgress, store);
2979
+ } else if (tl.timeTraveling === null) {
2980
+ const event = Object.assign(creationOrDisposal, {
2981
+ timestamp: Date.now()
2982
+ });
2983
+ tl.history.push(event);
2984
+ tl.at = tl.history.length;
2985
+ tl.subject.next(event);
2986
+ }
2987
+ const moleculeKey = creationOrDisposal.token.key;
2988
+ (_c = tl.subscriptions.get(moleculeKey)) == null ? void 0 : _c();
2989
+ tl.subscriptions.delete(moleculeKey);
2990
+ for (const [familyKey] of creationOrDisposal.values) {
2991
+ const stateKey = `${familyKey}(${json.stringifyJson(moleculeKey)})`;
2992
+ (_d = tl.subscriptions.get(stateKey)) == null ? void 0 : _d();
2993
+ tl.subscriptions.delete(stateKey);
2994
+ store.timelineTopics.delete(stateKey);
2995
+ }
2996
+ }
2997
+ break;
2998
+ }
2999
+ })
3000
+ );
3001
+ }
3002
+ }
3003
+ function joinTransaction(tl, txUpdateInProgress, store) {
3004
+ const currentTxKey = txUpdateInProgress.key;
3005
+ const currentTxInstanceId = txUpdateInProgress.id;
3006
+ const currentTxToken = {
3007
+ key: currentTxKey,
3008
+ type: `transaction`
3009
+ };
3010
+ const currentTransaction = withdraw(currentTxToken, store);
3011
+ if (currentTxKey && tl.transactionKey === null) {
3012
+ tl.transactionKey = currentTxKey;
3013
+ const unsubscribe = currentTransaction.subject.subscribe(
3014
+ `timeline:${tl.key}`,
3015
+ (transactionUpdate) => {
3016
+ var _a, _b;
3017
+ unsubscribe();
3018
+ tl.transactionKey = null;
3019
+ if (tl.timeTraveling === null && currentTxInstanceId) {
3020
+ if (tl.at !== tl.history.length) {
3021
+ tl.history.splice(tl.at);
2943
3022
  }
2944
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2945
- if (existingTimelineKey) {
2946
- store.logger.error(
2947
- `\u274C`,
2948
- `timeline`,
2949
- options.key,
2950
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2951
- );
2952
- continue;
3023
+ const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
3024
+ const updates = filterTransactionUpdates(
3025
+ transactionUpdate.updates,
3026
+ timelineTopics
3027
+ );
3028
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
3029
+ timestamp: Date.now()
3030
+ }, transactionUpdate), {
3031
+ updates
3032
+ });
3033
+ const willCapture = (_b = (_a = tl.shouldCapture) == null ? void 0 : _a.call(tl, timelineTransactionUpdate, tl)) != null ? _b : true;
3034
+ if (willCapture) {
3035
+ tl.history.push(timelineTransactionUpdate);
3036
+ tl.at = tl.history.length;
3037
+ tl.subject.next(timelineTransactionUpdate);
2953
3038
  }
2954
- addAtomToTimeline(atom, tl, store);
2955
3039
  }
3040
+ }
3041
+ );
3042
+ }
3043
+ }
3044
+ function filterTransactionUpdates(updates, timelineTopics) {
3045
+ return updates.filter((updateFromTx) => {
3046
+ if (updateFromTx.type === `transaction_update`) {
3047
+ return true;
3048
+ }
3049
+ let key;
3050
+ switch (updateFromTx.type) {
3051
+ case `state_creation`:
3052
+ case `state_disposal`:
3053
+ case `molecule_creation`:
3054
+ case `molecule_disposal`:
3055
+ key = updateFromTx.token.key;
2956
3056
  break;
2957
- case `molecule_family`:
2958
- {
2959
- const family = store.moleculeFamilies.get(tokenOrFamily.key);
2960
- if (family) {
2961
- tl.subscriptions.set(
2962
- tokenOrFamily.key,
2963
- family.subject.subscribe(
2964
- `timeline:${options.key}`,
2965
- (creationOrDisposal) => {
2966
- var _a2, _b2;
2967
- switch (creationOrDisposal.type) {
2968
- case `molecule_creation`:
2969
- {
2970
- const molecule = store.molecules.get(
2971
- json.stringifyJson(creationOrDisposal.token.key)
2972
- );
2973
- if (molecule) {
2974
- const event = Object.assign(creationOrDisposal, {
2975
- timestamp: Date.now()
2976
- });
2977
- tl.history.push(event);
2978
- tl.at = tl.history.length;
2979
- tl.subject.next(event);
2980
- for (const token2 of molecule.tokens.values()) {
2981
- switch (token2.type) {
2982
- case `atom`:
2983
- case `mutable_atom`:
2984
- addAtomToTimeline(token2, tl, store);
2985
- break;
2986
- }
2987
- }
2988
- tl.subscriptions.set(
2989
- molecule.key,
2990
- molecule.subject.subscribe(
2991
- `timeline:${options.key}`,
2992
- (stateCreationOrDisposal) => {
2993
- handleStateLifecycleEvent(
2994
- stateCreationOrDisposal,
2995
- tl,
2996
- store
2997
- );
2998
- }
2999
- )
3000
- );
3001
- }
3002
- }
3003
- break;
3004
- case `molecule_disposal`:
3005
- (_a2 = tl.subscriptions.get(creationOrDisposal.token.key)) == null ? void 0 : _a2();
3006
- tl.subscriptions.delete(creationOrDisposal.token.key);
3007
- for (const familyKey of creationOrDisposal.familyKeys) {
3008
- const stateKey = `${familyKey}(${json.stringifyJson(
3009
- creationOrDisposal.token.key
3010
- )})`;
3011
- (_b2 = tl.subscriptions.get(stateKey)) == null ? void 0 : _b2();
3012
- tl.subscriptions.delete(stateKey);
3013
- }
3014
- break;
3015
- }
3016
- }
3017
- )
3018
- );
3019
- }
3020
- }
3057
+ default:
3058
+ key = updateFromTx.key;
3021
3059
  break;
3022
3060
  }
3023
- }
3024
- store.timelines.set(options.key, tl);
3025
- const token = {
3026
- key: timelineKey,
3027
- type: `timeline`
3028
- };
3029
- store.on.timelineCreation.next(token);
3030
- return token;
3061
+ return timelineTopics.has(key);
3062
+ }).map((updateFromTx) => {
3063
+ if (`updates` in updateFromTx) {
3064
+ return __spreadProps(__spreadValues({}, updateFromTx), {
3065
+ updates: filterTransactionUpdates(
3066
+ updateFromTx.updates,
3067
+ timelineTopics
3068
+ )
3069
+ });
3070
+ }
3071
+ return updateFromTx;
3072
+ });
3031
3073
  }
3032
3074
  function handleStateLifecycleEvent(event, tl, store) {
3033
- var _a;
3075
+ var _a, _b;
3034
3076
  const timestamp = Date.now();
3035
3077
  const timelineEvent = Object.assign(event, {
3036
3078
  timestamp
3037
3079
  });
3038
3080
  if (!tl.timeTraveling) {
3039
- tl.history.push(timelineEvent);
3040
- tl.at = tl.history.length;
3041
- tl.subject.next(timelineEvent);
3081
+ const txUpdateInProgress = (_a = newest(store).on.transactionApplying.state) == null ? void 0 : _a.update;
3082
+ if (txUpdateInProgress) {
3083
+ joinTransaction(tl, txUpdateInProgress, store);
3084
+ } else {
3085
+ tl.history.push(timelineEvent);
3086
+ tl.at = tl.history.length;
3087
+ tl.subject.next(timelineEvent);
3088
+ }
3042
3089
  }
3043
3090
  switch (event.type) {
3044
3091
  case `state_creation`:
3045
3092
  addAtomToTimeline(event.token, tl, store);
3046
3093
  break;
3047
3094
  case `state_disposal`:
3048
- (_a = tl.subscriptions.get(event.token.key)) == null ? void 0 : _a();
3095
+ (_b = tl.subscriptions.get(event.token.key)) == null ? void 0 : _b();
3049
3096
  tl.subscriptions.delete(event.token.key);
3050
3097
  break;
3051
3098
  }
@@ -3140,7 +3187,6 @@ exports.TRANSACTION_PHASES = TRANSACTION_PHASES;
3140
3187
  exports.Tracker = Tracker;
3141
3188
  exports.abortTransaction = abortTransaction;
3142
3189
  exports.actUponStore = actUponStore;
3143
- exports.addAtomToTimeline = addAtomToTimeline;
3144
3190
  exports.applyTransaction = applyTransaction;
3145
3191
  exports.arbitrary = arbitrary;
3146
3192
  exports.assignTransactionToContinuity = assignTransactionToContinuity;