flightdeck 0.2.15 → 0.2.16

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.
@@ -306,225 +306,48 @@ function deposit(state) {
306
306
  return token;
307
307
  }
308
308
 
309
- // ../atom.io/src/molecule.ts
310
- function makeRootMoleculeInStore(key, store = IMPLICIT.STORE) {
311
- const molecule = {
312
- key,
313
- stringKey: stringifyJson(key),
314
- dependsOn: `any`
315
- };
316
- store.molecules.set(stringifyJson(key), molecule);
317
- return key;
309
+ // ../atom.io/src/atom.ts
310
+ function atom(options) {
311
+ return createStandaloneAtom(IMPLICIT.STORE, options);
318
312
  }
319
- function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
320
- const origin = provenance;
321
- const stringKey = stringifyJson(key);
322
- const invalidKeys = [];
323
- const target = newest(store);
324
- if (Array.isArray(origin)) {
325
- for (const formerClaim of origin) {
326
- const claimString = stringifyJson(formerClaim);
327
- const claim = target.molecules.get(claimString);
328
- if (claim) {
329
- store.moleculeGraph.set(claimString, stringKey, { source: claimString });
330
- } else {
331
- invalidKeys.push(claimString);
332
- }
333
- }
334
- } else {
335
- const claimString = stringifyJson(origin);
336
- const claim = target.molecules.get(claimString);
337
- if (claim) {
338
- store.moleculeGraph.set(claimString, stringKey, { source: claimString });
339
- } else {
340
- invalidKeys.push(claimString);
341
- }
342
- }
343
- if (invalidKeys.length === 0) {
344
- target.molecules.set(stringKey, { key, stringKey, dependsOn });
345
- }
346
- const creationEvent = {
347
- type: `molecule_creation`,
348
- key,
349
- provenance: origin
350
- };
351
- const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
352
- if (isTransaction) {
353
- target.transactionMeta.update.updates.push(creationEvent);
354
- } else {
355
- target.on.moleculeCreation.next(creationEvent);
356
- }
357
- for (const claim of invalidKeys) {
358
- const disposal = store.disposalTraces.buffer.find(
359
- (item) => item?.key === claim
360
- );
361
- store.logger.error(
362
- `\u274C`,
363
- `molecule`,
364
- key,
365
- `allocation failed:`,
366
- `Could not allocate to ${claim} in store "${store.config.name}".`,
367
- disposal ? `
368
- ${claim} was most recently disposed
369
- ${disposal.trace}` : `No previous disposal trace for ${claim} was found.`
370
- );
371
- }
372
- return key;
313
+ function atomFamily(options) {
314
+ return createAtomFamily(IMPLICIT.STORE, options);
373
315
  }
374
- function fuseWithinStore(store, type, sideA, sideB) {
375
- const compoundKey = `T$--${type}==${sideA}++${sideB}`;
376
- const above = [sideA, sideB];
377
- allocateIntoStore(
378
- store,
379
- above,
380
- compoundKey,
381
- `all`
316
+
317
+ // ../atom.io/src/logger.ts
318
+ var simpleLog = (logLevel) => (icon, denomination, tokenKey, message, ...rest) => {
319
+ console[logLevel](
320
+ `${icon} ${denomination} "${tokenKey}" ${message}`,
321
+ ...rest
382
322
  );
383
- return compoundKey;
384
- }
385
- function deallocateFromStore(store, claim) {
386
- const stringKey = stringifyJson(claim);
387
- const molecule = store.molecules.get(stringKey);
388
- if (!molecule) {
389
- const disposal = store.disposalTraces.buffer.find(
390
- (item) => item?.key === stringKey
391
- );
392
- store.logger.error(
393
- `\u274C`,
394
- `molecule`,
395
- claim,
396
- `deallocation failed:`,
397
- `Could not find allocation for ${stringKey} in store "${store.config.name}".`,
398
- disposal ? `
399
- This state was most recently deallocated
400
- ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
401
- );
402
- return;
323
+ };
324
+ var simpleLogger = {
325
+ error: simpleLog(`error`),
326
+ info: simpleLog(`info`),
327
+ warn: simpleLog(`warn`)
328
+ };
329
+ var AtomIOLogger = class {
330
+ constructor(logLevel, filter, logger = simpleLogger) {
331
+ this.logLevel = logLevel;
332
+ this.filter = filter;
333
+ this.logger = logger;
403
334
  }
404
- const joinKeys = store.moleculeJoins.getRelatedKeys(
405
- molecule.key
406
- );
407
- if (joinKeys) {
408
- for (const joinKey of joinKeys) {
409
- const join2 = store.joins.get(joinKey);
410
- if (join2) {
411
- join2.relations.delete(molecule.key);
412
- join2.molecules.delete(molecule.stringKey);
413
- }
335
+ error = (...args) => {
336
+ if ((this.filter?.(...args) ?? true) && this.logLevel !== null) {
337
+ this.logger.error(...args);
414
338
  }
415
- }
416
- store.moleculeJoins.delete(molecule.stringKey);
417
- const provenance = [];
418
- const values = [];
419
- const disposalEvent = {
420
- type: `molecule_disposal`,
421
- key: molecule.key,
422
- values,
423
- provenance
424
339
  };
425
- const target = newest(store);
426
- target.molecules.delete(stringKey);
427
- const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
428
- if (isTransaction) {
429
- target.transactionMeta.update.updates.push(disposalEvent);
430
- }
431
- const relatedMolecules = store.moleculeGraph.getRelationEntries({
432
- downstreamMoleculeKey: molecule.stringKey
433
- });
434
- if (relatedMolecules) {
435
- for (const [relatedStringKey, { source }] of relatedMolecules) {
436
- if (source === molecule.stringKey) {
437
- const relatedKey = parseJson(relatedStringKey);
438
- deallocateFromStore(store, relatedKey);
439
- } else {
440
- provenance.push(source);
441
- }
442
- }
443
- }
444
- const familyKeys = target.moleculeData.getRelatedKeys(molecule.stringKey);
445
- if (familyKeys) {
446
- for (const familyKey of familyKeys) {
447
- const family = target.families.get(familyKey);
448
- const token = findInStore(store, family, molecule.key);
449
- values.push([family.key, token]);
450
- disposeFromStore(store, token);
340
+ info = (...args) => {
341
+ if ((this.filter?.(...args) ?? true) && this.logLevel === `info`) {
342
+ this.logger.info(...args);
451
343
  }
452
- }
453
- target.moleculeGraph.delete(molecule.stringKey);
454
- target.moleculeJoins.delete(molecule.stringKey);
455
- target.moleculeData.delete(molecule.stringKey);
456
- if (!isTransaction) {
457
- target.on.moleculeDisposal.next(disposalEvent);
458
- }
459
- target.molecules.delete(molecule.stringKey);
460
- const trace = getTrace(new Error());
461
- store.disposalTraces.add({ key: stringKey, trace });
462
- }
463
- function claimWithinStore(store, newProvenance, claim, exclusive) {
464
- const stringKey = stringifyJson(claim);
465
- const target = newest(store);
466
- const molecule = target.molecules.get(stringKey);
467
- if (!molecule) {
468
- const disposal = store.disposalTraces.buffer.find(
469
- (item) => item?.key === stringKey
470
- );
471
- store.logger.error(
472
- `\u274C`,
473
- `molecule`,
474
- claim,
475
- `claim failed:`,
476
- `Could not allocate to ${stringKey} in store "${store.config.name}".`,
477
- disposal ? `
478
- ${stringKey} was most recently disposed
479
- ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
480
- );
481
- return claim;
482
- }
483
- const newProvenanceKey = stringifyJson(newProvenance);
484
- const newProvenanceMolecule = target.molecules.get(newProvenanceKey);
485
- if (!newProvenanceMolecule) {
486
- const disposal = store.disposalTraces.buffer.find(
487
- (item) => item?.key === newProvenanceKey
488
- );
489
- store.logger.error(
490
- `\u274C`,
491
- `molecule`,
492
- claim,
493
- `claim failed:`,
494
- `Could not allocate to ${newProvenanceKey} in store "${store.config.name}".`,
495
- disposal ? `
496
- ${newProvenanceKey} was most recently disposed
497
- ${disposal.trace}` : `No previous disposal trace for ${newProvenanceKey} was found.`
498
- );
499
- return claim;
500
- }
501
- const priorProvenance = store.moleculeGraph.getRelationEntries({
502
- downstreamMoleculeKey: molecule.stringKey
503
- }).filter(([, { source }]) => source !== stringKey).map(([key]) => parseJson(key));
504
- if (exclusive) {
505
- target.moleculeGraph.delete(stringKey);
506
- }
507
- target.moleculeGraph.set(
508
- {
509
- upstreamMoleculeKey: newProvenanceMolecule.stringKey,
510
- downstreamMoleculeKey: molecule.stringKey
511
- },
512
- {
513
- source: newProvenanceMolecule.stringKey
344
+ };
345
+ warn = (...args) => {
346
+ if ((this.filter?.(...args) ?? true) && this.logLevel !== `error` && this.logLevel !== null) {
347
+ this.logger.warn(...args);
514
348
  }
515
- );
516
- const transferEvent = {
517
- type: `molecule_transfer`,
518
- key: molecule.key,
519
- from: priorProvenance,
520
- to: [newProvenanceMolecule.key]
521
349
  };
522
- const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
523
- if (isTransaction) {
524
- target.transactionMeta.update.updates.push(transferEvent);
525
- }
526
- return claim;
527
- }
350
+ };
528
351
  var Realm = class {
529
352
  store;
530
353
  constructor(store = IMPLICIT.STORE) {
@@ -572,994 +395,1169 @@ var Anarchy = class {
572
395
  }
573
396
  };
574
397
 
575
- // ../atom.io/src/atom.ts
576
- function atom(options) {
577
- return createStandaloneAtom(IMPLICIT.STORE, options);
578
- }
579
- function atomFamily(options) {
580
- return createAtomFamily(IMPLICIT.STORE, options);
398
+ // ../atom.io/src/selector.ts
399
+ function selectorFamily(options) {
400
+ return createSelectorFamily(IMPLICIT.STORE, options);
581
401
  }
582
402
 
583
- // ../atom.io/src/logger.ts
584
- var simpleLog = (logLevel) => (icon, denomination, tokenKey, message, ...rest) => {
585
- console[logLevel](
586
- `${icon} ${denomination} "${tokenKey}" ${message}`,
587
- ...rest
403
+ // ../atom.io/internal/src/transaction/is-root-store.ts
404
+ function isRootStore(store) {
405
+ return `epoch` in store.transactionMeta;
406
+ }
407
+ function isChildStore(store) {
408
+ return `phase` in store.transactionMeta;
409
+ }
410
+
411
+ // ../atom.io/internal/src/transaction/abort-transaction.ts
412
+ var abortTransaction = (store) => {
413
+ const target = newest(store);
414
+ if (!isChildStore(target)) {
415
+ store.logger.warn(
416
+ `\u{1F41E}`,
417
+ `transaction`,
418
+ `???`,
419
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
420
+ );
421
+ return;
422
+ }
423
+ store.logger.info(
424
+ `\u{1FA82}`,
425
+ `transaction`,
426
+ target.transactionMeta.update.key,
427
+ `Aborting transaction`
588
428
  );
429
+ target.parent.child = null;
589
430
  };
590
- var simpleLogger = {
591
- error: simpleLog(`error`),
592
- info: simpleLog(`info`),
593
- warn: simpleLog(`warn`)
594
- };
595
- var AtomIOLogger = class {
596
- constructor(logLevel, filter, logger = simpleLogger) {
597
- this.logLevel = logLevel;
598
- this.filter = filter;
599
- this.logger = logger;
431
+
432
+ // ../atom.io/internal/src/pretty-print.ts
433
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
434
+ function prettyPrintTokenType(token) {
435
+ return token.type.split(`_`).map(capitalize).join(` `);
436
+ }
437
+
438
+ // ../atom.io/internal/src/not-found-error.ts
439
+ var NotFoundError = class extends Error {
440
+ constructor(token, store) {
441
+ super(
442
+ `${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
443
+ );
600
444
  }
601
- error = (...args) => {
602
- if ((this.filter?.(...args) ?? true) && this.logLevel !== null) {
603
- this.logger.error(...args);
604
- }
605
- };
606
- info = (...args) => {
607
- if ((this.filter?.(...args) ?? true) && this.logLevel === `info`) {
608
- this.logger.info(...args);
609
- }
610
- };
611
- warn = (...args) => {
612
- if ((this.filter?.(...args) ?? true) && this.logLevel !== `error` && this.logLevel !== null) {
613
- this.logger.warn(...args);
614
- }
615
- };
616
445
  };
617
446
 
618
- // ../atom.io/src/selector.ts
619
- function selectorFamily(options) {
620
- return createSelectorFamily(IMPLICIT.STORE, options);
447
+ // ../atom.io/internal/src/transaction/act-upon-store.ts
448
+ function actUponStore(token, id, store) {
449
+ return (...parameters) => {
450
+ const tx = withdraw(token, store);
451
+ if (tx) {
452
+ return tx.run(parameters, id);
453
+ }
454
+ throw new NotFoundError(token, store);
455
+ };
621
456
  }
622
457
 
623
- // ../atom.io/src/transaction.ts
624
- function transaction(options) {
625
- return createTransaction(options, IMPLICIT.STORE);
626
- }
458
+ // ../atom.io/internal/src/set-state/become.ts
459
+ var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(originalThing) : nextVersionOfThing;
627
460
 
628
- // ../atom.io/internal/src/junction.ts
629
- var Junction = class {
630
- a;
631
- b;
632
- cardinality;
633
- relations = /* @__PURE__ */ new Map();
634
- contents = /* @__PURE__ */ new Map();
635
- isAType;
636
- isBType;
637
- isContent;
638
- makeContentKey = (a, b) => `${a}:${b}`;
639
- warn;
640
- getRelatedKeys(key) {
641
- return this.relations.get(key);
642
- }
643
- addRelation(a, b) {
644
- let aRelations = this.relations.get(a);
645
- let bRelations = this.relations.get(b);
646
- if (aRelations) {
647
- aRelations.add(b);
648
- } else {
649
- aRelations = /* @__PURE__ */ new Set([b]);
650
- this.relations.set(a, aRelations);
651
- }
652
- if (bRelations) {
653
- bRelations.add(a);
654
- } else {
655
- bRelations = /* @__PURE__ */ new Set([a]);
656
- this.relations.set(b, bRelations);
657
- }
658
- }
659
- deleteRelation(a, b) {
660
- const aRelations = this.relations.get(a);
661
- if (aRelations) {
662
- aRelations.delete(b);
663
- if (aRelations.size === 0) {
664
- this.relations.delete(a);
665
- }
666
- const bRelations = this.relations.get(b);
667
- if (bRelations) {
668
- bRelations.delete(a);
669
- if (bRelations.size === 0) {
670
- this.relations.delete(b);
671
- }
672
- }
673
- }
461
+ // ../atom.io/internal/src/get-state/read-or-compute-value.ts
462
+ var readOrComputeValue = (state, target) => {
463
+ if (target.valueMap.has(state.key)) {
464
+ target.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
465
+ return readCachedValue(state, target);
674
466
  }
675
- replaceRelationsUnsafely(x, ys) {
676
- this.relations.set(x, new Set(ys));
677
- for (const y of ys) {
678
- const yRelations = (/* @__PURE__ */ new Set()).add(x);
679
- this.relations.set(y, yRelations);
680
- }
467
+ if (state.type === `selector` || state.type === `readonly_selector`) {
468
+ target.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
469
+ return state.get();
681
470
  }
682
- replaceRelationsSafely(x, ys) {
683
- const xRelationsPrev = this.relations.get(x);
684
- let a = this.isAType?.(x) ? x : undefined;
685
- let b = a === undefined ? x : undefined;
686
- if (xRelationsPrev) {
687
- for (const y of xRelationsPrev) {
688
- a ??= y;
689
- b ??= y;
690
- const yRelations = this.relations.get(y);
691
- if (yRelations) {
692
- if (yRelations.size === 1) {
693
- this.relations.delete(y);
694
- } else {
695
- yRelations.delete(x);
696
- }
697
- this.contents.delete(this.makeContentKey(a, b));
698
- }
699
- }
700
- }
701
- this.relations.set(x, new Set(ys));
702
- for (const y of ys) {
703
- let yRelations = this.relations.get(y);
704
- if (yRelations) {
705
- yRelations.add(x);
706
- } else {
707
- yRelations = (/* @__PURE__ */ new Set()).add(x);
708
- this.relations.set(y, yRelations);
709
- }
710
- }
471
+ const fallback = state.default instanceof Function ? state.default() : state.default;
472
+ target.logger.info(
473
+ `\u{1F481}`,
474
+ `atom`,
475
+ state.key,
476
+ `could not find cached value; using default`,
477
+ fallback
478
+ );
479
+ return state.default instanceof Function ? state.default() : state.default;
480
+ };
481
+
482
+ // ../atom.io/internal/src/operation.ts
483
+ var openOperation = (store, token) => {
484
+ if (store.operation.open) {
485
+ const rejectionTime = performance.now();
486
+ store.logger.info(
487
+ `\u2757`,
488
+ token.type,
489
+ token.key,
490
+ `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`
491
+ );
492
+ return rejectionTime;
711
493
  }
712
- getContentInternal(contentKey) {
713
- return this.contents.get(contentKey);
494
+ store.operation = {
495
+ open: true,
496
+ done: /* @__PURE__ */ new Set(),
497
+ prev: /* @__PURE__ */ new Map(),
498
+ time: Date.now(),
499
+ token
500
+ };
501
+ store.logger.info(
502
+ `\u2B55`,
503
+ token.type,
504
+ token.key,
505
+ `operation start in store "${store.config.name}"${!isChildStore(store) ? `` : ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`}`
506
+ );
507
+ };
508
+ var closeOperation = (store) => {
509
+ if (store.operation.open) {
510
+ store.logger.info(
511
+ `\u{1F534}`,
512
+ store.operation.token.type,
513
+ store.operation.token.key,
514
+ `operation done in store "${store.config.name}"`
515
+ );
714
516
  }
715
- setContent(contentKey, content) {
716
- this.contents.set(contentKey, content);
517
+ store.operation = { open: false };
518
+ store.on.operationClose.next(store.operation);
519
+ };
520
+ var isDone = (store, key) => {
521
+ if (!store.operation.open) {
522
+ store.logger.error(
523
+ `\u{1F41E}`,
524
+ `unknown`,
525
+ key,
526
+ `isDone called outside of an operation. This is probably a bug in AtomIO.`
527
+ );
528
+ return true;
717
529
  }
718
- deleteContent(contentKey) {
719
- this.contents.delete(contentKey);
530
+ return store.operation.done.has(key);
531
+ };
532
+ var markDone = (store, key) => {
533
+ if (!store.operation.open) {
534
+ store.logger.error(
535
+ `\u{1F41E}`,
536
+ `unknown`,
537
+ key,
538
+ `markDone called outside of an operation. This is probably a bug in AtomIO.`
539
+ );
540
+ return;
720
541
  }
721
- constructor(data, config) {
722
- this.a = data.between[0];
723
- this.b = data.between[1];
724
- this.cardinality = data.cardinality;
725
- if (!config?.externalStore) {
726
- this.relations = new Map(
727
- data.relations?.map(([x, ys]) => [x, new Set(ys)])
728
- );
729
- this.contents = new Map(data.contents);
730
- }
731
- this.isAType = config?.isAType ?? null;
732
- this.isBType = config?.isBType ?? null;
733
- this.isContent = config?.isContent ?? null;
734
- if (config?.makeContentKey) {
735
- this.makeContentKey = config.makeContentKey;
736
- }
737
- if (config?.externalStore) {
738
- const externalStore = config.externalStore;
739
- this.has = (a, b) => externalStore.has(a, b);
740
- this.addRelation = (a, b) => {
741
- externalStore.addRelation(a, b);
742
- };
743
- this.deleteRelation = (a, b) => {
744
- externalStore.deleteRelation(a, b);
745
- };
746
- this.replaceRelationsSafely = (a, bs) => {
747
- externalStore.replaceRelationsSafely(a, bs);
748
- };
749
- this.replaceRelationsUnsafely = (a, bs) => {
750
- externalStore.replaceRelationsUnsafely(a, bs);
751
- };
752
- this.getRelatedKeys = (key) => externalStore.getRelatedKeys(
753
- key
542
+ store.operation.done.add(key);
543
+ };
544
+
545
+ // ../atom.io/internal/src/set-state/emit-update.ts
546
+ var emitUpdate = (state, update, store) => {
547
+ switch (state.type) {
548
+ case `mutable_atom`:
549
+ store.logger.info(
550
+ `\u{1F4E2}`,
551
+ state.type,
552
+ state.key,
553
+ `is now (`,
554
+ update.newValue,
555
+ `) subscribers:`,
556
+ state.subject.subscribers
557
+ );
558
+ break;
559
+ default:
560
+ store.logger.info(
561
+ `\u{1F4E2}`,
562
+ state.type,
563
+ state.key,
564
+ `went (`,
565
+ update.oldValue,
566
+ `->`,
567
+ update.newValue,
568
+ `) subscribers:`,
569
+ state.subject.subscribers
754
570
  );
755
- if (externalStore.getContent) {
756
- this.getContentInternal = (contentKey) => {
757
- return externalStore.getContent(contentKey);
758
- };
759
- this.setContent = (contentKey, content) => {
760
- externalStore.setContent(contentKey, content);
761
- };
762
- this.deleteContent = (contentKey) => {
763
- externalStore.deleteContent(contentKey);
764
- };
765
- }
766
- for (const [x, ys] of data.relations ?? []) {
767
- let a = this.isAType?.(x) ? x : undefined;
768
- let b = a === undefined ? x : undefined;
769
- for (const y of ys) {
770
- a ??= y;
771
- b ??= y;
772
- this.addRelation(a, b);
773
- }
774
- }
775
- for (const [contentKey, content] of data.contents ?? []) {
776
- this.setContent(contentKey, content);
777
- }
778
- }
779
- if (config?.warn) {
780
- this.warn = config.warn;
781
- }
782
- }
783
- toJSON() {
784
- return {
785
- between: [this.a, this.b],
786
- cardinality: this.cardinality,
787
- relations: [...this.relations.entries()].map(
788
- ([a, b]) => [a, [...b]]
789
- ),
790
- contents: [...this.contents.entries()]
791
- };
792
571
  }
793
- set(...params) {
794
- let a;
795
- let b;
796
- let content;
797
- switch (params.length) {
798
- case 1: {
799
- const relation = params[0];
800
- a = relation[this.a];
801
- b = relation[this.b];
802
- content = undefined;
803
- break;
804
- }
805
- case 2: {
806
- const zeroth = params[0];
807
- if (typeof zeroth === `string`) {
808
- [a, b] = params;
809
- } else {
810
- a = zeroth[this.a];
811
- b = zeroth[this.b];
812
- content = params[1];
813
- }
814
- break;
815
- }
816
- default: {
817
- a = params[0];
818
- b = params[1];
819
- content = params[2];
820
- break;
821
- }
572
+ state.subject.next(update);
573
+ };
574
+
575
+ // ../atom.io/internal/src/set-state/evict-downstream.ts
576
+ var evictDownStream = (atom2, store) => {
577
+ const target = newest(store);
578
+ const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom2.key);
579
+ target.logger.info(
580
+ `\u{1F9F9}`,
581
+ atom2.type,
582
+ atom2.key,
583
+ downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
584
+ downstreamKeys ?? `to evict`
585
+ );
586
+ if (downstreamKeys) {
587
+ if (target.operation.open) {
588
+ target.logger.info(
589
+ `\u{1F9F9}`,
590
+ atom2.type,
591
+ atom2.key,
592
+ `[ ${[...target.operation.done].join(`, `)} ] already done`
593
+ );
822
594
  }
823
- switch (this.cardinality) {
824
- // biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
825
- case `1:1`: {
826
- const bPrev = this.getRelatedKey(a);
827
- if (bPrev && bPrev !== b) this.delete(a, bPrev);
828
- }
829
- case `1:n`: {
830
- const aPrev = this.getRelatedKey(b);
831
- if (aPrev && aPrev !== a) this.delete(aPrev, b);
595
+ for (const key of downstreamKeys) {
596
+ if (isDone(target, key)) {
597
+ continue;
832
598
  }
599
+ evictCachedValue(key, target);
600
+ markDone(target, key);
833
601
  }
834
- if (content) {
835
- const contentKey = this.makeContentKey(a, b);
836
- this.setContent(contentKey, content);
837
- }
838
- this.addRelation(a, b);
839
- return this;
840
602
  }
841
- delete(x, b) {
842
- b = typeof b === `string` ? b : x[this.b];
843
- const a = (
844
- // @ts-expect-error we deduce that this.a may index x
845
- typeof x === `string` ? x : x[this.a]
603
+ };
604
+
605
+ // ../atom.io/internal/src/set-state/stow-update.ts
606
+ function shouldUpdateBeStowed(key, update) {
607
+ if (isTransceiver(update.newValue)) {
608
+ return false;
609
+ }
610
+ if (key.includes(`\u{1F50D}`)) {
611
+ return false;
612
+ }
613
+ return true;
614
+ }
615
+ var stowUpdate = (state, update, store) => {
616
+ const { key } = state;
617
+ const target = newest(store);
618
+ if (!isChildStore(target) || target.transactionMeta.phase !== `building`) {
619
+ store.logger.error(
620
+ `\u{1F41E}`,
621
+ `atom`,
622
+ key,
623
+ `stowUpdate called outside of a transaction. This is probably a bug.`
846
624
  );
847
- if (a === undefined && typeof b === `string`) {
848
- const bRelations = this.getRelatedKeys(b);
849
- if (bRelations) {
850
- for (const bRelation of bRelations) {
851
- this.delete(bRelation, b);
852
- }
625
+ return;
626
+ }
627
+ const shouldStow = shouldUpdateBeStowed(key, update);
628
+ if (!shouldStow) {
629
+ return;
630
+ }
631
+ const atomUpdate = {
632
+ type: `atom_update`,
633
+ key,
634
+ ...update
635
+ };
636
+ if (state.family) {
637
+ atomUpdate.family = state.family;
638
+ }
639
+ target.transactionMeta.update.updates.push(atomUpdate);
640
+ store.logger.info(
641
+ `\u{1F4C1}`,
642
+ `atom`,
643
+ key,
644
+ `stowed (`,
645
+ update.oldValue,
646
+ `->`,
647
+ update.newValue,
648
+ `)`
649
+ );
650
+ };
651
+
652
+ // ../atom.io/internal/src/set-state/set-atom.ts
653
+ var setAtom = (atom2, next, target) => {
654
+ const oldValue = readOrComputeValue(atom2, target);
655
+ let newValue = oldValue;
656
+ if (atom2.type === `mutable_atom` && isChildStore(target)) {
657
+ const { parent } = target;
658
+ const copiedValue = copyMutableIfNeeded(atom2, parent, target);
659
+ newValue = copiedValue;
660
+ }
661
+ newValue = become(next)(newValue);
662
+ target.logger.info(`\u{1F4DD}`, `atom`, atom2.key, `set to`, newValue);
663
+ newValue = cacheValue(atom2.key, newValue, atom2.subject, target);
664
+ if (isAtomDefault(atom2.key, target)) {
665
+ markAtomAsNotDefault(atom2.key, target);
666
+ }
667
+ markDone(target, atom2.key);
668
+ evictDownStream(atom2, target);
669
+ const update = { oldValue, newValue };
670
+ if (isRootStore(target)) {
671
+ emitUpdate(atom2, update, target);
672
+ } else if (target.parent) {
673
+ if (target.on.transactionApplying.state === null) {
674
+ stowUpdate(atom2, update, target);
675
+ } else if (atom2.key.startsWith(`*`)) {
676
+ const mutableKey = atom2.key.slice(1);
677
+ const mutableAtom = target.atoms.get(mutableKey);
678
+ let transceiver = target.valueMap.get(mutableKey);
679
+ if (mutableAtom.type === `mutable_atom` && isChildStore(target)) {
680
+ const { parent } = target;
681
+ const copiedValue = copyMutableIfNeeded(mutableAtom, parent, target);
682
+ transceiver = copiedValue;
853
683
  }
684
+ const accepted = transceiver.do(update.newValue) === null;
685
+ if (accepted) evictDownStream(mutableAtom, target);
854
686
  }
855
- if (typeof a === `string` && b === undefined) {
856
- const aRelations = this.getRelatedKeys(a);
857
- if (aRelations) {
858
- for (const aRelation of aRelations) {
859
- this.delete(a, aRelation);
860
- }
861
- }
687
+ }
688
+ };
689
+
690
+ // ../atom.io/internal/src/set-state/set-atom-or-selector.ts
691
+ var setAtomOrSelector = (state, value, store) => {
692
+ switch (state.type) {
693
+ case `atom`:
694
+ case `mutable_atom`:
695
+ setAtom(state, value, store);
696
+ break;
697
+ case `selector`:
698
+ state.set(value);
699
+ break;
700
+ }
701
+ };
702
+
703
+ // ../atom.io/internal/src/families/get-family-of-token.ts
704
+ function getFamilyOfToken(store, token) {
705
+ if (token.family) {
706
+ const family = store.families.get(token.family.key);
707
+ if (family) {
708
+ return family;
862
709
  }
863
- if (typeof a === `string` && typeof b === `string`) {
864
- this.deleteRelation(a, b);
865
- const contentKey = this.makeContentKey(a, b);
866
- this.deleteContent(contentKey);
710
+ }
711
+ }
712
+
713
+ // ../atom.io/internal/src/set-state/set-into-store.ts
714
+ function setIntoStore(store, ...params) {
715
+ let token;
716
+ let family;
717
+ let key;
718
+ let value;
719
+ if (params.length === 2) {
720
+ token = params[0];
721
+ value = params[1];
722
+ family = getFamilyOfToken(store, token) ?? null;
723
+ if (family) {
724
+ key = token.family ? parseJson(token.family.subKey) : null;
725
+ token = findInStore(store, family, key);
867
726
  }
868
- return this;
727
+ } else {
728
+ family = params[0];
729
+ key = params[1];
730
+ value = params[2];
731
+ token = findInStore(store, family, key);
869
732
  }
870
- getRelatedKey(key) {
871
- const relations = this.getRelatedKeys(key);
872
- if (relations) {
873
- if (relations.size > 1) {
874
- this.warn?.(
875
- `${relations.size} related keys were found for key "${key}": (${[
876
- ...relations
877
- ].map((k) => `"${k}"`).join(`, `)}). Only one related key was expected.`
733
+ if (`counterfeit` in token && `family` in token) {
734
+ const subKey = token.family.subKey;
735
+ const disposal = store.disposalTraces.buffer.find(
736
+ (item) => item?.key === subKey
737
+ );
738
+ store.logger.error(
739
+ `\u274C`,
740
+ token.type,
741
+ token.key,
742
+ `could not be set because it was not found in the store "${store.config.name}".`,
743
+ disposal ? `This state was previously disposed:
744
+ ${disposal.trace}` : `No previous disposal trace was found.`
745
+ );
746
+ return;
747
+ }
748
+ const rejectionTime = openOperation(store, token);
749
+ if (rejectionTime) {
750
+ const unsubscribe = store.on.operationClose.subscribe(
751
+ `waiting to set "${token.key}" at T-${rejectionTime}`,
752
+ () => {
753
+ unsubscribe();
754
+ store.logger.info(
755
+ `\u{1F7E2}`,
756
+ token.type,
757
+ token.key,
758
+ `resuming deferred setState from T-${rejectionTime}`
878
759
  );
760
+ setIntoStore(store, token, value);
879
761
  }
880
- let singleRelation;
881
- for (const relation of relations) {
882
- singleRelation = relation;
883
- break;
762
+ );
763
+ return;
764
+ }
765
+ const state = withdraw(token, store);
766
+ setAtomOrSelector(state, value, store);
767
+ closeOperation(store);
768
+ }
769
+
770
+ // ../atom.io/internal/src/ingest-updates/ingest-atom-update.ts
771
+ function ingestAtomUpdate(applying, atomUpdate, store) {
772
+ const { key, newValue, oldValue } = atomUpdate;
773
+ const value = newValue ;
774
+ const token = { key, type: `atom` };
775
+ if (atomUpdate.family) {
776
+ Object.assign(token, { family: atomUpdate.family });
777
+ }
778
+ setIntoStore(store, token, value);
779
+ }
780
+
781
+ // ../atom.io/internal/src/get-trace.ts
782
+ function getTrace(error) {
783
+ const { stack } = error;
784
+ if (stack) {
785
+ return `
786
+ ` + stack.split(`
787
+ `)?.slice(1)?.join(`
788
+ `);
789
+ }
790
+ return ``;
791
+ }
792
+
793
+ // ../atom.io/internal/src/molecule.ts
794
+ function makeRootMoleculeInStore(key, store = IMPLICIT.STORE) {
795
+ const molecule = {
796
+ key,
797
+ stringKey: stringifyJson(key),
798
+ dependsOn: `any`
799
+ };
800
+ store.molecules.set(stringifyJson(key), molecule);
801
+ return key;
802
+ }
803
+ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
804
+ const origin = provenance;
805
+ const stringKey = stringifyJson(key);
806
+ const invalidKeys = [];
807
+ const target = newest(store);
808
+ if (Array.isArray(origin)) {
809
+ for (const formerClaim of origin) {
810
+ const claimString = stringifyJson(formerClaim);
811
+ const claim = target.molecules.get(claimString);
812
+ if (claim) {
813
+ store.moleculeGraph.set(claimString, stringKey, { source: claimString });
814
+ } else {
815
+ invalidKeys.push(claimString);
884
816
  }
885
- return singleRelation;
886
817
  }
887
- }
888
- replaceRelations(x, relations, config) {
889
- const hasContent = !Array.isArray(relations);
890
- const ys = hasContent ? Object.keys(relations) : relations;
891
- if (config?.reckless) {
892
- this.replaceRelationsUnsafely(x, ys);
818
+ } else {
819
+ const claimString = stringifyJson(origin);
820
+ const claim = target.molecules.get(claimString);
821
+ if (claim) {
822
+ store.moleculeGraph.set(claimString, stringKey, { source: claimString });
893
823
  } else {
894
- this.replaceRelationsSafely(x, ys);
895
- }
896
- if (hasContent) {
897
- for (const y of ys) {
898
- const contentKey = this.makeContentKey(x, y);
899
- const content = relations[y];
900
- this.setContent(contentKey, content);
901
- }
824
+ invalidKeys.push(claimString);
902
825
  }
903
- return this;
904
826
  }
905
- getContent(a, b) {
906
- const contentKey = this.makeContentKey(a, b);
907
- return this.getContentInternal(contentKey);
827
+ if (invalidKeys.length === 0) {
828
+ target.molecules.set(stringKey, { key, stringKey, dependsOn });
908
829
  }
909
- getRelationEntries(input) {
910
- const a = input[this.a];
911
- const b = input[this.b];
912
- if (a !== undefined && b === undefined) {
913
- const aRelations = this.getRelatedKeys(a);
914
- if (aRelations) {
915
- return [...aRelations].map((aRelation) => {
916
- return [aRelation, this.getContent(a, aRelation)];
917
- });
918
- }
919
- }
920
- if (a === undefined && b !== undefined) {
921
- const bRelations = this.getRelatedKeys(b);
922
- if (bRelations) {
923
- return [...bRelations].map((bRelation) => {
924
- return [bRelation, this.getContent(bRelation, b)];
925
- });
926
- }
927
- }
928
- return [];
830
+ const creationEvent = {
831
+ type: `molecule_creation`,
832
+ key,
833
+ provenance: origin
834
+ };
835
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
836
+ if (isTransaction) {
837
+ target.transactionMeta.update.updates.push(creationEvent);
838
+ } else {
839
+ target.on.moleculeCreation.next(creationEvent);
929
840
  }
930
- has(a, b) {
931
- if (b) {
932
- const setA = this.getRelatedKeys(a);
933
- return setA?.has(b) ?? false;
934
- }
935
- return this.relations.has(a);
841
+ for (const claim of invalidKeys) {
842
+ const disposal = store.disposalTraces.buffer.find(
843
+ (item) => item?.key === claim
844
+ );
845
+ store.logger.error(
846
+ `\u274C`,
847
+ `molecule`,
848
+ key,
849
+ `allocation failed:`,
850
+ `Could not allocate to ${claim} in store "${store.config.name}".`,
851
+ disposal ? `
852
+ ${claim} was most recently disposed
853
+ ${disposal.trace}` : `No previous disposal trace for ${claim} was found.`
854
+ );
936
855
  }
937
- };
938
-
939
- // ../atom.io/internal/src/transaction/is-root-store.ts
940
- function isRootStore(store) {
941
- return `epoch` in store.transactionMeta;
856
+ return key;
942
857
  }
943
- function isChildStore(store) {
944
- return `phase` in store.transactionMeta;
858
+ function fuseWithinStore(store, type, sideA, sideB) {
859
+ const compoundKey = `T$--${type}==${sideA}++${sideB}`;
860
+ const above = [sideA, sideB];
861
+ allocateIntoStore(
862
+ store,
863
+ above,
864
+ compoundKey,
865
+ `all`
866
+ );
867
+ return compoundKey;
945
868
  }
946
-
947
- // ../atom.io/internal/src/transaction/abort-transaction.ts
948
- var abortTransaction = (store) => {
949
- const target = newest(store);
950
- if (!isChildStore(target)) {
951
- store.logger.warn(
952
- `\u{1F41E}`,
953
- `transaction`,
954
- `???`,
955
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
869
+ function deallocateFromStore(store, claim) {
870
+ const stringKey = stringifyJson(claim);
871
+ const molecule = store.molecules.get(stringKey);
872
+ if (!molecule) {
873
+ const disposal = store.disposalTraces.buffer.find(
874
+ (item) => item?.key === stringKey
875
+ );
876
+ store.logger.error(
877
+ `\u274C`,
878
+ `molecule`,
879
+ claim,
880
+ `deallocation failed:`,
881
+ `Could not find allocation for ${stringKey} in store "${store.config.name}".`,
882
+ disposal ? `
883
+ This state was most recently deallocated
884
+ ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
956
885
  );
957
886
  return;
958
887
  }
959
- store.logger.info(
960
- `\u{1FA82}`,
961
- `transaction`,
962
- target.transactionMeta.update.key,
963
- `Aborting transaction`
888
+ const joinKeys = store.moleculeJoins.getRelatedKeys(
889
+ molecule.key
964
890
  );
965
- target.parent.child = null;
966
- };
967
-
968
- // ../atom.io/internal/src/pretty-print.ts
969
- var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
970
- function prettyPrintTokenType(token) {
971
- return token.type.split(`_`).map(capitalize).join(` `);
972
- }
973
-
974
- // ../atom.io/internal/src/not-found-error.ts
975
- var NotFoundError = class extends Error {
976
- constructor(...params) {
977
- const token = params[0];
978
- const store = params.length === 2 ? params[1] : params[2];
979
- if (params.length === 2) {
980
- super(
981
- `${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
982
- );
983
- } else {
984
- const key = params[1];
985
- super(
986
- `${prettyPrintTokenType(token)} "${token.key}" member ${stringifyJson(key)} not found in store "${store.config.name}".`
987
- );
891
+ if (joinKeys) {
892
+ for (const joinKey of joinKeys) {
893
+ const join2 = store.joins.get(joinKey);
894
+ if (join2) {
895
+ join2.relations.delete(molecule.key);
896
+ join2.molecules.delete(molecule.stringKey);
897
+ }
988
898
  }
989
899
  }
990
- };
991
-
992
- // ../atom.io/internal/src/transaction/act-upon-store.ts
993
- function actUponStore(token, id, store) {
994
- return (...parameters) => {
995
- const tx = withdraw(token, store);
996
- if (tx) {
997
- return tx.run(parameters, id);
998
- }
999
- throw new NotFoundError(token, store);
900
+ store.moleculeJoins.delete(molecule.stringKey);
901
+ const provenance = [];
902
+ const values = [];
903
+ const disposalEvent = {
904
+ type: `molecule_disposal`,
905
+ key: molecule.key,
906
+ values,
907
+ provenance
1000
908
  };
1001
- }
1002
-
1003
- // ../atom.io/internal/src/set-state/become.ts
1004
- var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(originalThing) : nextVersionOfThing;
1005
-
1006
- // ../atom.io/internal/src/get-state/read-or-compute-value.ts
1007
- var readOrComputeValue = (state, target) => {
1008
- if (target.valueMap.has(state.key)) {
1009
- target.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
1010
- return readCachedValue(state, target);
909
+ const target = newest(store);
910
+ target.molecules.delete(stringKey);
911
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
912
+ if (isTransaction) {
913
+ target.transactionMeta.update.updates.push(disposalEvent);
1011
914
  }
1012
- if (state.type === `selector` || state.type === `readonly_selector`) {
1013
- target.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
1014
- return state.get();
915
+ const relatedMolecules = store.moleculeGraph.getRelationEntries({
916
+ downstreamMoleculeKey: molecule.stringKey
917
+ });
918
+ if (relatedMolecules) {
919
+ for (const [relatedStringKey, { source }] of relatedMolecules) {
920
+ if (source === molecule.stringKey) {
921
+ const relatedKey = parseJson(relatedStringKey);
922
+ deallocateFromStore(store, relatedKey);
923
+ } else {
924
+ provenance.push(source);
925
+ }
926
+ }
1015
927
  }
1016
- const fallback = state.default instanceof Function ? state.default() : state.default;
1017
- target.logger.info(
1018
- `\u{1F481}`,
1019
- `atom`,
1020
- state.key,
1021
- `could not find cached value; using default`,
1022
- fallback
1023
- );
1024
- return state.default instanceof Function ? state.default() : state.default;
1025
- };
1026
-
1027
- // ../atom.io/internal/src/operation.ts
1028
- var openOperation = (store, token) => {
1029
- if (store.operation.open) {
1030
- const rejectionTime = performance.now();
1031
- store.logger.info(
1032
- `\u2757`,
1033
- token.type,
1034
- token.key,
1035
- `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`
1036
- );
1037
- return rejectionTime;
928
+ const familyKeys = target.moleculeData.getRelatedKeys(molecule.stringKey);
929
+ if (familyKeys) {
930
+ for (const familyKey of familyKeys) {
931
+ const family = target.families.get(familyKey);
932
+ const token = findInStore(store, family, molecule.key);
933
+ values.push([family.key, token]);
934
+ disposeFromStore(store, token);
935
+ }
1038
936
  }
1039
- store.operation = {
1040
- open: true,
1041
- done: /* @__PURE__ */ new Set(),
1042
- prev: /* @__PURE__ */ new Map(),
1043
- time: Date.now(),
1044
- token
1045
- };
1046
- store.logger.info(
1047
- `\u2B55`,
1048
- token.type,
1049
- token.key,
1050
- `operation start in store "${store.config.name}"${!isChildStore(store) ? `` : ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`}`
1051
- );
1052
- };
1053
- var closeOperation = (store) => {
1054
- if (store.operation.open) {
1055
- store.logger.info(
1056
- `\u{1F534}`,
1057
- store.operation.token.type,
1058
- store.operation.token.key,
1059
- `operation done in store "${store.config.name}"`
1060
- );
937
+ target.moleculeGraph.delete(molecule.stringKey);
938
+ target.moleculeJoins.delete(molecule.stringKey);
939
+ target.moleculeData.delete(molecule.stringKey);
940
+ if (!isTransaction) {
941
+ target.on.moleculeDisposal.next(disposalEvent);
1061
942
  }
1062
- store.operation = { open: false };
1063
- store.on.operationClose.next(store.operation);
1064
- };
1065
- var isDone = (store, key) => {
1066
- if (!store.operation.open) {
943
+ target.molecules.delete(molecule.stringKey);
944
+ const trace = getTrace(new Error());
945
+ store.disposalTraces.add({ key: stringKey, trace });
946
+ }
947
+ function claimWithinStore(store, newProvenance, claim, exclusive) {
948
+ const stringKey = stringifyJson(claim);
949
+ const target = newest(store);
950
+ const molecule = target.molecules.get(stringKey);
951
+ if (!molecule) {
952
+ const disposal = store.disposalTraces.buffer.find(
953
+ (item) => item?.key === stringKey
954
+ );
1067
955
  store.logger.error(
1068
- `\u{1F41E}`,
1069
- `unknown`,
1070
- key,
1071
- `isDone called outside of an operation. This is probably a bug in AtomIO.`
956
+ `\u274C`,
957
+ `molecule`,
958
+ claim,
959
+ `claim failed:`,
960
+ `Could not allocate to ${stringKey} in store "${store.config.name}".`,
961
+ disposal ? `
962
+ ${stringKey} was most recently disposed
963
+ ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
1072
964
  );
1073
- return true;
965
+ return claim;
1074
966
  }
1075
- return store.operation.done.has(key);
1076
- };
1077
- var markDone = (store, key) => {
1078
- if (!store.operation.open) {
967
+ const newProvenanceKey = stringifyJson(newProvenance);
968
+ const newProvenanceMolecule = target.molecules.get(newProvenanceKey);
969
+ if (!newProvenanceMolecule) {
970
+ const disposal = store.disposalTraces.buffer.find(
971
+ (item) => item?.key === newProvenanceKey
972
+ );
1079
973
  store.logger.error(
1080
- `\u{1F41E}`,
1081
- `unknown`,
1082
- key,
1083
- `markDone called outside of an operation. This is probably a bug in AtomIO.`
974
+ `\u274C`,
975
+ `molecule`,
976
+ claim,
977
+ `claim failed:`,
978
+ `Could not allocate to ${newProvenanceKey} in store "${store.config.name}".`,
979
+ disposal ? `
980
+ ${newProvenanceKey} was most recently disposed
981
+ ${disposal.trace}` : `No previous disposal trace for ${newProvenanceKey} was found.`
1084
982
  );
1085
- return;
983
+ return claim;
1086
984
  }
1087
- store.operation.done.add(key);
1088
- };
985
+ const priorProvenance = store.moleculeGraph.getRelationEntries({
986
+ downstreamMoleculeKey: molecule.stringKey
987
+ }).filter(([, { source }]) => source !== stringKey).map(([key]) => parseJson(key));
988
+ if (exclusive) {
989
+ target.moleculeGraph.delete(stringKey);
990
+ }
991
+ target.moleculeGraph.set(
992
+ {
993
+ upstreamMoleculeKey: newProvenanceMolecule.stringKey,
994
+ downstreamMoleculeKey: molecule.stringKey
995
+ },
996
+ {
997
+ source: newProvenanceMolecule.stringKey
998
+ }
999
+ );
1000
+ const transferEvent = {
1001
+ type: `molecule_transfer`,
1002
+ key: molecule.key,
1003
+ from: priorProvenance,
1004
+ to: [newProvenanceMolecule.key]
1005
+ };
1006
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
1007
+ if (isTransaction) {
1008
+ target.transactionMeta.update.updates.push(transferEvent);
1009
+ }
1010
+ return claim;
1011
+ }
1089
1012
 
1090
- // ../atom.io/internal/src/set-state/emit-update.ts
1091
- var emitUpdate = (state, update, store) => {
1092
- switch (state.type) {
1093
- case `mutable_atom`:
1094
- store.logger.info(
1095
- `\u{1F4E2}`,
1096
- state.type,
1097
- state.key,
1098
- `is now (`,
1099
- update.newValue,
1100
- `) subscribers:`,
1101
- state.subject.subscribers
1102
- );
1013
+ // ../atom.io/internal/src/ingest-updates/ingest-creation-disposal.ts
1014
+ function ingestCreationEvent(update, applying, store) {
1015
+ switch (applying) {
1016
+ case `newValue`: {
1017
+ createInStore(update, store);
1103
1018
  break;
1104
- default:
1105
- store.logger.info(
1106
- `\u{1F4E2}`,
1107
- state.type,
1108
- state.key,
1109
- `went (`,
1110
- update.oldValue,
1111
- `->`,
1112
- update.newValue,
1113
- `) subscribers:`,
1114
- state.subject.subscribers
1115
- );
1019
+ }
1020
+ case `oldValue`: {
1021
+ disposeFromStore(store, update.token);
1022
+ break;
1023
+ }
1116
1024
  }
1117
- state.subject.next(update);
1118
- };
1119
-
1120
- // ../atom.io/internal/src/set-state/evict-downstream.ts
1121
- var evictDownStream = (atom2, store) => {
1122
- const target = newest(store);
1123
- const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom2.key);
1124
- target.logger.info(
1125
- `\u{1F9F9}`,
1126
- atom2.type,
1127
- atom2.key,
1128
- downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
1129
- downstreamKeys ?? `to evict`
1130
- );
1131
- if (downstreamKeys) {
1132
- if (target.operation.open) {
1133
- target.logger.info(
1134
- `\u{1F9F9}`,
1135
- atom2.type,
1136
- atom2.key,
1137
- `[ ${[...target.operation.done].join(`, `)} ] already done`
1138
- );
1025
+ }
1026
+ function ingestDisposalEvent(update, applying, store) {
1027
+ switch (applying) {
1028
+ case `newValue`: {
1029
+ disposeFromStore(store, update.token);
1030
+ break;
1139
1031
  }
1140
- for (const key of downstreamKeys) {
1141
- if (isDone(target, key)) {
1142
- continue;
1032
+ case `oldValue`: {
1033
+ createInStore(update, store);
1034
+ if (update.subType === `atom`) {
1035
+ store.valueMap.set(update.token.key, update.value);
1143
1036
  }
1144
- evictCachedValue(key, target);
1145
- markDone(target, key);
1037
+ break;
1038
+ }
1039
+ }
1040
+ }
1041
+ function createInStore(update, store) {
1042
+ const { family: familyMeta } = update.token;
1043
+ if (familyMeta) {
1044
+ const family = store.families.get(familyMeta.key);
1045
+ if (family) {
1046
+ findInStore(store, family, parseJson(familyMeta.subKey));
1047
+ }
1048
+ }
1049
+ }
1050
+ function ingestMoleculeCreationEvent(update, applying, store) {
1051
+ switch (applying) {
1052
+ case `newValue`:
1053
+ allocateIntoStore(store, update.provenance, update.key);
1054
+ break;
1055
+ case `oldValue`:
1056
+ deallocateFromStore(store, update.key);
1057
+ break;
1058
+ }
1059
+ }
1060
+ function ingestMoleculeDisposalEvent(update, applying, store) {
1061
+ switch (applying) {
1062
+ case `newValue`:
1063
+ deallocateFromStore(store, update.key);
1064
+ break;
1065
+ case `oldValue`:
1066
+ {
1067
+ const provenanceJson = update.provenance.map(parseJson);
1068
+ allocateIntoStore(store, provenanceJson, update.key);
1069
+ for (const [familyKey, value] of update.values) {
1070
+ const family = store.families.get(familyKey);
1071
+ if (family) {
1072
+ findInStore(store, family, update.key);
1073
+ const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
1074
+ store.valueMap.set(memberKey, value);
1075
+ }
1076
+ }
1077
+ }
1078
+ break;
1079
+ }
1080
+ }
1081
+ function ingestMoleculeTransferEvent(update, applying, store) {
1082
+ switch (applying) {
1083
+ case `newValue`:
1084
+ {
1085
+ const provenance = update.to.length === 1 ? update.to[0] : update.to;
1086
+ claimWithinStore(
1087
+ store,
1088
+ provenance,
1089
+ update.key,
1090
+ `exclusive`
1091
+ );
1092
+ }
1093
+ break;
1094
+ case `oldValue`:
1095
+ {
1096
+ const provenance = update.from.length === 1 ? update.from[0] : update.from;
1097
+ claimWithinStore(
1098
+ store,
1099
+ provenance,
1100
+ update.key,
1101
+ `exclusive`
1102
+ );
1103
+ }
1104
+ break;
1105
+ }
1106
+ }
1107
+
1108
+ // ../atom.io/internal/src/ingest-updates/ingest-transaction-update.ts
1109
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1110
+ const updates = transactionUpdate.updates ;
1111
+ for (const updateFromTransaction of updates) {
1112
+ switch (updateFromTransaction.type) {
1113
+ case `atom_update`:
1114
+ case `selector_update`:
1115
+ ingestAtomUpdate(applying, updateFromTransaction, store);
1116
+ break;
1117
+ case `state_creation`:
1118
+ ingestCreationEvent(updateFromTransaction, applying, store);
1119
+ break;
1120
+ case `state_disposal`:
1121
+ ingestDisposalEvent(updateFromTransaction, applying, store);
1122
+ break;
1123
+ case `molecule_creation`:
1124
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1125
+ break;
1126
+ case `molecule_disposal`:
1127
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1128
+ break;
1129
+ case `molecule_transfer`:
1130
+ ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
1131
+ break;
1132
+ case `transaction_update`:
1133
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
1134
+ break;
1146
1135
  }
1147
1136
  }
1148
- };
1137
+ }
1149
1138
 
1150
- // ../atom.io/internal/src/set-state/stow-update.ts
1151
- function shouldUpdateBeStowed(key, update) {
1152
- if (isTransceiver(update.newValue)) {
1153
- return false;
1139
+ // ../atom.io/internal/src/transaction/set-epoch-number.ts
1140
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1141
+ const isRoot = isRootStore(store);
1142
+ if (!isRoot) {
1143
+ return;
1154
1144
  }
1155
- if (key.includes(`\u{1F50D}`)) {
1156
- return false;
1145
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1146
+ if (continuityKey !== undefined) {
1147
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1157
1148
  }
1158
- return true;
1159
1149
  }
1160
- var stowUpdate = (state, update, store) => {
1161
- const { key } = state;
1162
- const target = newest(store);
1163
- if (!isChildStore(target) || target.transactionMeta.phase !== `building`) {
1164
- store.logger.error(
1150
+
1151
+ // ../atom.io/internal/src/transaction/apply-transaction.ts
1152
+ var applyTransaction = (output, store) => {
1153
+ const child = newest(store);
1154
+ const { parent } = child;
1155
+ if (parent === null || !isChildStore(child) || child.transactionMeta?.phase !== `building`) {
1156
+ store.logger.warn(
1165
1157
  `\u{1F41E}`,
1166
- `atom`,
1167
- key,
1168
- `stowUpdate called outside of a transaction. This is probably a bug.`
1158
+ `transaction`,
1159
+ `???`,
1160
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1169
1161
  );
1170
1162
  return;
1171
1163
  }
1172
- const shouldStow = shouldUpdateBeStowed(key, update);
1173
- if (!shouldStow) {
1174
- return;
1175
- }
1176
- const atomUpdate = {
1177
- type: `atom_update`,
1178
- key,
1179
- ...update
1180
- };
1181
- if (state.family) {
1182
- atomUpdate.family = state.family;
1183
- }
1184
- target.transactionMeta.update.updates.push(atomUpdate);
1164
+ child.transactionMeta.phase = `applying`;
1165
+ child.transactionMeta.update.output = output;
1166
+ parent.child = null;
1167
+ parent.on.transactionApplying.next(child.transactionMeta);
1168
+ const { updates } = child.transactionMeta.update;
1185
1169
  store.logger.info(
1186
- `\u{1F4C1}`,
1187
- `atom`,
1188
- key,
1189
- `stowed (`,
1190
- update.oldValue,
1191
- `->`,
1192
- update.newValue,
1193
- `)`
1170
+ `\u{1F6C4}`,
1171
+ `transaction`,
1172
+ child.transactionMeta.update.key,
1173
+ `Applying transaction with ${updates.length} updates:`,
1174
+ updates
1194
1175
  );
1176
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1177
+ if (isRootStore(parent)) {
1178
+ setEpochNumberOfAction(
1179
+ child.transactionMeta.update.key,
1180
+ child.transactionMeta.update.epoch,
1181
+ parent
1182
+ );
1183
+ const myTransaction = withdraw(
1184
+ { key: child.transactionMeta.update.key, type: `transaction` },
1185
+ store
1186
+ );
1187
+ myTransaction?.subject.next(child.transactionMeta.update);
1188
+ store.logger.info(
1189
+ `\u{1F6EC}`,
1190
+ `transaction`,
1191
+ child.transactionMeta.update.key,
1192
+ `Finished applying transaction.`
1193
+ );
1194
+ } else if (isChildStore(parent)) {
1195
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1196
+ }
1197
+ parent.on.transactionApplying.next(null);
1195
1198
  };
1196
1199
 
1197
- // ../atom.io/internal/src/set-state/set-atom.ts
1198
- var setAtom = (atom2, next, target) => {
1199
- const oldValue = readOrComputeValue(atom2, target);
1200
- let newValue = oldValue;
1201
- if (atom2.type === `mutable_atom` && isChildStore(target)) {
1202
- const { parent } = target;
1203
- const copiedValue = copyMutableIfNeeded(atom2, parent, target);
1204
- newValue = copiedValue;
1205
- }
1206
- newValue = become(next)(newValue);
1207
- target.logger.info(`\u{1F4DD}`, `atom`, atom2.key, `set to`, newValue);
1208
- newValue = cacheValue(atom2.key, newValue, atom2.subject, target);
1209
- if (isAtomDefault(atom2.key, target)) {
1210
- markAtomAsNotDefault(atom2.key, target);
1200
+ // ../atom.io/internal/src/get-environment-data.ts
1201
+ function getEnvironmentData(store) {
1202
+ return {
1203
+ store
1204
+ };
1205
+ }
1206
+
1207
+ // ../atom.io/internal/src/get-state/get-from-store.ts
1208
+ function getFromStore(store, ...params) {
1209
+ let token;
1210
+ let family;
1211
+ let key;
1212
+ if (params.length === 1) {
1213
+ token = params[0];
1214
+ } else {
1215
+ family = params[0];
1216
+ key = params[1];
1217
+ token = findInStore(store, family, key);
1211
1218
  }
1212
- markDone(target, atom2.key);
1213
- evictDownStream(atom2, target);
1214
- const update = { oldValue, newValue };
1215
- if (isRootStore(target)) {
1216
- emitUpdate(atom2, update, target);
1217
- } else if (target.parent) {
1218
- if (target.on.transactionApplying.state === null) {
1219
- stowUpdate(atom2, update, target);
1220
- } else if (atom2.key.startsWith(`*`)) {
1221
- const mutableKey = atom2.key.slice(1);
1222
- const mutableAtom = target.atoms.get(mutableKey);
1223
- let transceiver = target.valueMap.get(mutableKey);
1224
- if (mutableAtom.type === `mutable_atom` && isChildStore(target)) {
1225
- const { parent } = target;
1226
- const copiedValue = copyMutableIfNeeded(mutableAtom, parent, target);
1227
- transceiver = copiedValue;
1219
+ if (`counterfeit` in token && `family` in token) {
1220
+ family = store.families.get(token.family.key);
1221
+ const subKey = token.family.subKey;
1222
+ const disposal = store.disposalTraces.buffer.find(
1223
+ (item) => item?.key === subKey
1224
+ );
1225
+ store.logger.error(
1226
+ `\u274C`,
1227
+ token.type,
1228
+ token.key,
1229
+ `could not be retrieved because it was not found in the store "${store.config.name}".`,
1230
+ disposal ? `This state was previously disposed:
1231
+ ${disposal.trace}` : `No previous disposal trace was found.`
1232
+ );
1233
+ switch (family.type) {
1234
+ case `atom_family`:
1235
+ case `mutable_atom_family`:
1236
+ return store.defaults.get(family.key);
1237
+ case `selector_family`:
1238
+ case `readonly_selector_family`: {
1239
+ if (store.defaults.has(family.key)) {
1240
+ return store.defaults.get(token.family.key);
1241
+ }
1242
+ const defaultValue = withdraw(family, store).default(subKey);
1243
+ store.defaults.set(family.key, defaultValue);
1244
+ return defaultValue;
1228
1245
  }
1229
- const accepted = transceiver.do(update.newValue) === null;
1230
- if (accepted) evictDownStream(mutableAtom, target);
1231
1246
  }
1232
1247
  }
1233
- };
1248
+ return readOrComputeValue(withdraw(token, store), store);
1249
+ }
1234
1250
 
1235
- // ../atom.io/internal/src/set-state/set-atom-or-selector.ts
1236
- var setAtomOrSelector = (state, value, store) => {
1237
- switch (state.type) {
1238
- case `atom`:
1239
- case `mutable_atom`:
1240
- setAtom(state, value, store);
1241
- break;
1242
- case `selector`:
1243
- state.set(value);
1244
- break;
1251
+ // ../atom.io/internal/src/junction.ts
1252
+ var Junction = class {
1253
+ a;
1254
+ b;
1255
+ cardinality;
1256
+ relations = /* @__PURE__ */ new Map();
1257
+ contents = /* @__PURE__ */ new Map();
1258
+ isAType;
1259
+ isBType;
1260
+ isContent;
1261
+ makeContentKey = (a, b) => `${a}:${b}`;
1262
+ warn;
1263
+ getRelatedKeys(key) {
1264
+ return this.relations.get(key);
1245
1265
  }
1246
- };
1247
-
1248
- // ../atom.io/internal/src/families/get-family-of-token.ts
1249
- function getFamilyOfToken(store, token) {
1250
- if (token.family) {
1251
- const family = store.families.get(token.family.key);
1252
- if (family) {
1253
- return family;
1266
+ addRelation(a, b) {
1267
+ let aRelations = this.relations.get(a);
1268
+ let bRelations = this.relations.get(b);
1269
+ if (aRelations) {
1270
+ aRelations.add(b);
1271
+ } else {
1272
+ aRelations = /* @__PURE__ */ new Set([b]);
1273
+ this.relations.set(a, aRelations);
1274
+ }
1275
+ if (bRelations) {
1276
+ bRelations.add(a);
1277
+ } else {
1278
+ bRelations = /* @__PURE__ */ new Set([a]);
1279
+ this.relations.set(b, bRelations);
1254
1280
  }
1255
1281
  }
1256
- }
1257
-
1258
- // ../atom.io/internal/src/set-state/set-into-store.ts
1259
- function setIntoStore(store, ...params) {
1260
- let token;
1261
- let family;
1262
- let key;
1263
- let value;
1264
- if (params.length === 2) {
1265
- token = params[0];
1266
- value = params[1];
1267
- family = getFamilyOfToken(store, token) ?? null;
1268
- if (family) {
1269
- key = token.family ? parseJson(token.family.subKey) : null;
1270
- token = findInStore(store, family, key);
1282
+ deleteRelation(a, b) {
1283
+ const aRelations = this.relations.get(a);
1284
+ if (aRelations) {
1285
+ aRelations.delete(b);
1286
+ if (aRelations.size === 0) {
1287
+ this.relations.delete(a);
1288
+ }
1289
+ const bRelations = this.relations.get(b);
1290
+ if (bRelations) {
1291
+ bRelations.delete(a);
1292
+ if (bRelations.size === 0) {
1293
+ this.relations.delete(b);
1294
+ }
1295
+ }
1296
+ }
1297
+ }
1298
+ replaceRelationsUnsafely(x, ys) {
1299
+ this.relations.set(x, new Set(ys));
1300
+ for (const y of ys) {
1301
+ const yRelations = (/* @__PURE__ */ new Set()).add(x);
1302
+ this.relations.set(y, yRelations);
1303
+ }
1304
+ }
1305
+ replaceRelationsSafely(x, ys) {
1306
+ const xRelationsPrev = this.relations.get(x);
1307
+ let a = this.isAType?.(x) ? x : undefined;
1308
+ let b = a === undefined ? x : undefined;
1309
+ if (xRelationsPrev) {
1310
+ for (const y of xRelationsPrev) {
1311
+ a ??= y;
1312
+ b ??= y;
1313
+ const yRelations = this.relations.get(y);
1314
+ if (yRelations) {
1315
+ if (yRelations.size === 1) {
1316
+ this.relations.delete(y);
1317
+ } else {
1318
+ yRelations.delete(x);
1319
+ }
1320
+ this.contents.delete(this.makeContentKey(a, b));
1321
+ }
1322
+ }
1323
+ }
1324
+ this.relations.set(x, new Set(ys));
1325
+ for (const y of ys) {
1326
+ let yRelations = this.relations.get(y);
1327
+ if (yRelations) {
1328
+ yRelations.add(x);
1329
+ } else {
1330
+ yRelations = (/* @__PURE__ */ new Set()).add(x);
1331
+ this.relations.set(y, yRelations);
1332
+ }
1271
1333
  }
1272
- } else {
1273
- family = params[0];
1274
- key = params[1];
1275
- value = params[2];
1276
- token = findInStore(store, family, key);
1277
1334
  }
1278
- if (`counterfeit` in token && `family` in token) {
1279
- const subKey = token.family.subKey;
1280
- const disposal = store.disposalTraces.buffer.find(
1281
- (item) => item?.key === subKey
1282
- );
1283
- store.logger.error(
1284
- `\u274C`,
1285
- token.type,
1286
- token.key,
1287
- `could not be set because it was not found in the store "${store.config.name}".`,
1288
- disposal ? `This state was previously disposed:
1289
- ${disposal.trace}` : `No previous disposal trace was found.`
1290
- );
1291
- return;
1335
+ getContentInternal(contentKey) {
1336
+ return this.contents.get(contentKey);
1292
1337
  }
1293
- const rejectionTime = openOperation(store, token);
1294
- if (rejectionTime) {
1295
- const unsubscribe = store.on.operationClose.subscribe(
1296
- `waiting to set "${token.key}" at T-${rejectionTime}`,
1297
- () => {
1298
- unsubscribe();
1299
- store.logger.info(
1300
- `\u{1F7E2}`,
1301
- token.type,
1302
- token.key,
1303
- `resuming deferred setState from T-${rejectionTime}`
1304
- );
1305
- setIntoStore(store, token, value);
1306
- }
1307
- );
1308
- return;
1338
+ setContent(contentKey, content) {
1339
+ this.contents.set(contentKey, content);
1309
1340
  }
1310
- const state = withdraw(token, store);
1311
- setAtomOrSelector(state, value, store);
1312
- closeOperation(store);
1313
- }
1314
-
1315
- // ../atom.io/internal/src/ingest-updates/ingest-atom-update.ts
1316
- function ingestAtomUpdate(applying, atomUpdate, store) {
1317
- const { key, newValue, oldValue } = atomUpdate;
1318
- const value = newValue ;
1319
- const token = { key, type: `atom` };
1320
- if (atomUpdate.family) {
1321
- Object.assign(token, { family: atomUpdate.family });
1341
+ deleteContent(contentKey) {
1342
+ this.contents.delete(contentKey);
1322
1343
  }
1323
- setIntoStore(store, token, value);
1324
- }
1325
-
1326
- // ../atom.io/internal/src/ingest-updates/ingest-creation-disposal.ts
1327
- function ingestCreationEvent(update, applying, store) {
1328
- switch (applying) {
1329
- case `newValue`: {
1330
- createInStore(update, store);
1331
- break;
1344
+ constructor(data, config) {
1345
+ this.a = data.between[0];
1346
+ this.b = data.between[1];
1347
+ this.cardinality = data.cardinality;
1348
+ if (!config?.externalStore) {
1349
+ this.relations = new Map(
1350
+ data.relations?.map(([x, ys]) => [x, new Set(ys)])
1351
+ );
1352
+ this.contents = new Map(data.contents);
1332
1353
  }
1333
- case `oldValue`: {
1334
- disposeFromStore(store, update.token);
1335
- break;
1354
+ this.isAType = config?.isAType ?? null;
1355
+ this.isBType = config?.isBType ?? null;
1356
+ this.isContent = config?.isContent ?? null;
1357
+ if (config?.makeContentKey) {
1358
+ this.makeContentKey = config.makeContentKey;
1359
+ }
1360
+ if (config?.externalStore) {
1361
+ const externalStore = config.externalStore;
1362
+ this.has = (a, b) => externalStore.has(a, b);
1363
+ this.addRelation = (a, b) => {
1364
+ externalStore.addRelation(a, b);
1365
+ };
1366
+ this.deleteRelation = (a, b) => {
1367
+ externalStore.deleteRelation(a, b);
1368
+ };
1369
+ this.replaceRelationsSafely = (a, bs) => {
1370
+ externalStore.replaceRelationsSafely(a, bs);
1371
+ };
1372
+ this.replaceRelationsUnsafely = (a, bs) => {
1373
+ externalStore.replaceRelationsUnsafely(a, bs);
1374
+ };
1375
+ this.getRelatedKeys = (key) => externalStore.getRelatedKeys(
1376
+ key
1377
+ );
1378
+ if (externalStore.getContent) {
1379
+ this.getContentInternal = (contentKey) => {
1380
+ return externalStore.getContent(contentKey);
1381
+ };
1382
+ this.setContent = (contentKey, content) => {
1383
+ externalStore.setContent(contentKey, content);
1384
+ };
1385
+ this.deleteContent = (contentKey) => {
1386
+ externalStore.deleteContent(contentKey);
1387
+ };
1388
+ }
1389
+ for (const [x, ys] of data.relations ?? []) {
1390
+ let a = this.isAType?.(x) ? x : undefined;
1391
+ let b = a === undefined ? x : undefined;
1392
+ for (const y of ys) {
1393
+ a ??= y;
1394
+ b ??= y;
1395
+ this.addRelation(a, b);
1396
+ }
1397
+ }
1398
+ for (const [contentKey, content] of data.contents ?? []) {
1399
+ this.setContent(contentKey, content);
1400
+ }
1401
+ }
1402
+ if (config?.warn) {
1403
+ this.warn = config.warn;
1336
1404
  }
1337
1405
  }
1338
- }
1339
- function ingestDisposalEvent(update, applying, store) {
1340
- switch (applying) {
1341
- case `newValue`: {
1342
- disposeFromStore(store, update.token);
1343
- break;
1406
+ toJSON() {
1407
+ return {
1408
+ between: [this.a, this.b],
1409
+ cardinality: this.cardinality,
1410
+ relations: [...this.relations.entries()].map(
1411
+ ([a, b]) => [a, [...b]]
1412
+ ),
1413
+ contents: [...this.contents.entries()]
1414
+ };
1415
+ }
1416
+ set(...params) {
1417
+ let a;
1418
+ let b;
1419
+ let content;
1420
+ switch (params.length) {
1421
+ case 1: {
1422
+ const relation = params[0];
1423
+ a = relation[this.a];
1424
+ b = relation[this.b];
1425
+ content = undefined;
1426
+ break;
1427
+ }
1428
+ case 2: {
1429
+ const zeroth = params[0];
1430
+ if (typeof zeroth === `string`) {
1431
+ [a, b] = params;
1432
+ } else {
1433
+ a = zeroth[this.a];
1434
+ b = zeroth[this.b];
1435
+ content = params[1];
1436
+ }
1437
+ break;
1438
+ }
1439
+ default: {
1440
+ a = params[0];
1441
+ b = params[1];
1442
+ content = params[2];
1443
+ break;
1444
+ }
1344
1445
  }
1345
- case `oldValue`: {
1346
- createInStore(update, store);
1347
- if (update.subType === `atom`) {
1348
- store.valueMap.set(update.token.key, update.value);
1446
+ switch (this.cardinality) {
1447
+ // biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
1448
+ case `1:1`: {
1449
+ const bPrev = this.getRelatedKey(a);
1450
+ if (bPrev && bPrev !== b) this.delete(a, bPrev);
1451
+ }
1452
+ case `1:n`: {
1453
+ const aPrev = this.getRelatedKey(b);
1454
+ if (aPrev && aPrev !== a) this.delete(aPrev, b);
1349
1455
  }
1350
- break;
1351
1456
  }
1352
- }
1353
- }
1354
- function createInStore(update, store) {
1355
- const { family: familyMeta } = update.token;
1356
- if (familyMeta) {
1357
- const family = store.families.get(familyMeta.key);
1358
- if (family) {
1359
- findInStore(store, family, parseJson(familyMeta.subKey));
1457
+ if (content) {
1458
+ const contentKey = this.makeContentKey(a, b);
1459
+ this.setContent(contentKey, content);
1360
1460
  }
1461
+ this.addRelation(a, b);
1462
+ return this;
1361
1463
  }
1362
- }
1363
- function ingestMoleculeCreationEvent(update, applying, store) {
1364
- switch (applying) {
1365
- case `newValue`:
1366
- allocateIntoStore(store, update.provenance, update.key);
1367
- break;
1368
- case `oldValue`:
1369
- deallocateFromStore(store, update.key);
1370
- break;
1371
- }
1372
- }
1373
- function ingestMoleculeDisposalEvent(update, applying, store) {
1374
- switch (applying) {
1375
- case `newValue`:
1376
- deallocateFromStore(store, update.key);
1377
- break;
1378
- case `oldValue`:
1379
- {
1380
- const provenanceJson = update.provenance.map(parseJson);
1381
- allocateIntoStore(store, provenanceJson, update.key);
1382
- for (const [familyKey, value] of update.values) {
1383
- const family = store.families.get(familyKey);
1384
- if (family) {
1385
- findInStore(store, family, update.key);
1386
- const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
1387
- store.valueMap.set(memberKey, value);
1388
- }
1464
+ delete(x, b) {
1465
+ b = typeof b === `string` ? b : x[this.b];
1466
+ const a = (
1467
+ // @ts-expect-error we deduce that this.a may index x
1468
+ typeof x === `string` ? x : x[this.a]
1469
+ );
1470
+ if (a === undefined && typeof b === `string`) {
1471
+ const bRelations = this.getRelatedKeys(b);
1472
+ if (bRelations) {
1473
+ for (const bRelation of bRelations) {
1474
+ this.delete(bRelation, b);
1389
1475
  }
1390
1476
  }
1391
- break;
1392
- }
1393
- }
1394
- function ingestMoleculeTransferEvent(update, applying, store) {
1395
- switch (applying) {
1396
- case `newValue`:
1397
- {
1398
- const provenance = update.to.length === 1 ? update.to[0] : update.to;
1399
- claimWithinStore(
1400
- store,
1401
- provenance,
1402
- update.key,
1403
- `exclusive`
1404
- );
1477
+ }
1478
+ if (typeof a === `string` && b === undefined) {
1479
+ const aRelations = this.getRelatedKeys(a);
1480
+ if (aRelations) {
1481
+ for (const aRelation of aRelations) {
1482
+ this.delete(a, aRelation);
1483
+ }
1405
1484
  }
1406
- break;
1407
- case `oldValue`:
1408
- {
1409
- const provenance = update.from.length === 1 ? update.from[0] : update.from;
1410
- claimWithinStore(
1411
- store,
1412
- provenance,
1413
- update.key,
1414
- `exclusive`
1485
+ }
1486
+ if (typeof a === `string` && typeof b === `string`) {
1487
+ this.deleteRelation(a, b);
1488
+ const contentKey = this.makeContentKey(a, b);
1489
+ this.deleteContent(contentKey);
1490
+ }
1491
+ return this;
1492
+ }
1493
+ getRelatedKey(key) {
1494
+ const relations = this.getRelatedKeys(key);
1495
+ if (relations) {
1496
+ if (relations.size > 1) {
1497
+ this.warn?.(
1498
+ `${relations.size} related keys were found for key "${key}": (${[
1499
+ ...relations
1500
+ ].map((k) => `"${k}"`).join(`, `)}). Only one related key was expected.`
1415
1501
  );
1416
1502
  }
1417
- break;
1418
- }
1419
- }
1420
-
1421
- // ../atom.io/internal/src/ingest-updates/ingest-transaction-update.ts
1422
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1423
- const updates = transactionUpdate.updates ;
1424
- for (const updateFromTransaction of updates) {
1425
- switch (updateFromTransaction.type) {
1426
- case `atom_update`:
1427
- case `selector_update`:
1428
- ingestAtomUpdate(applying, updateFromTransaction, store);
1429
- break;
1430
- case `state_creation`:
1431
- ingestCreationEvent(updateFromTransaction, applying, store);
1432
- break;
1433
- case `state_disposal`:
1434
- ingestDisposalEvent(updateFromTransaction, applying, store);
1435
- break;
1436
- case `molecule_creation`:
1437
- ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1438
- break;
1439
- case `molecule_disposal`:
1440
- ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1441
- break;
1442
- case `molecule_transfer`:
1443
- ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
1444
- break;
1445
- case `transaction_update`:
1446
- ingestTransactionUpdate(applying, updateFromTransaction, store);
1503
+ let singleRelation;
1504
+ for (const relation of relations) {
1505
+ singleRelation = relation;
1447
1506
  break;
1507
+ }
1508
+ return singleRelation;
1448
1509
  }
1449
1510
  }
1450
- }
1451
-
1452
- // ../atom.io/internal/src/transaction/set-epoch-number.ts
1453
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1454
- const isRoot = isRootStore(store);
1455
- if (!isRoot) {
1456
- return;
1457
- }
1458
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1459
- if (continuityKey !== undefined) {
1460
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
1461
- }
1462
- }
1463
-
1464
- // ../atom.io/internal/src/transaction/apply-transaction.ts
1465
- var applyTransaction = (output, store) => {
1466
- const child = newest(store);
1467
- const { parent } = child;
1468
- if (parent === null || !isChildStore(child) || child.transactionMeta?.phase !== `building`) {
1469
- store.logger.warn(
1470
- `\u{1F41E}`,
1471
- `transaction`,
1472
- `???`,
1473
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1474
- );
1475
- return;
1476
- }
1477
- child.transactionMeta.phase = `applying`;
1478
- child.transactionMeta.update.output = output;
1479
- parent.child = null;
1480
- parent.on.transactionApplying.next(child.transactionMeta);
1481
- const { updates } = child.transactionMeta.update;
1482
- store.logger.info(
1483
- `\u{1F6C4}`,
1484
- `transaction`,
1485
- child.transactionMeta.update.key,
1486
- `Applying transaction with ${updates.length} updates:`,
1487
- updates
1488
- );
1489
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1490
- if (isRootStore(parent)) {
1491
- setEpochNumberOfAction(
1492
- child.transactionMeta.update.key,
1493
- child.transactionMeta.update.epoch,
1494
- parent
1495
- );
1496
- const myTransaction = withdraw(
1497
- { key: child.transactionMeta.update.key, type: `transaction` },
1498
- store
1499
- );
1500
- myTransaction?.subject.next(child.transactionMeta.update);
1501
- store.logger.info(
1502
- `\u{1F6EC}`,
1503
- `transaction`,
1504
- child.transactionMeta.update.key,
1505
- `Finished applying transaction.`
1506
- );
1507
- } else if (isChildStore(parent)) {
1508
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1511
+ replaceRelations(x, relations, config) {
1512
+ const hasContent = !Array.isArray(relations);
1513
+ const ys = hasContent ? Object.keys(relations) : relations;
1514
+ if (config?.reckless) {
1515
+ this.replaceRelationsUnsafely(x, ys);
1516
+ } else {
1517
+ this.replaceRelationsSafely(x, ys);
1518
+ }
1519
+ if (hasContent) {
1520
+ for (const y of ys) {
1521
+ const contentKey = this.makeContentKey(x, y);
1522
+ const content = relations[y];
1523
+ this.setContent(contentKey, content);
1524
+ }
1525
+ }
1526
+ return this;
1509
1527
  }
1510
- parent.on.transactionApplying.next(null);
1511
- };
1512
-
1513
- // ../atom.io/internal/src/get-environment-data.ts
1514
- function getEnvironmentData(store) {
1515
- return {
1516
- store
1517
- };
1518
- }
1519
-
1520
- // ../atom.io/internal/src/get-state/get-from-store.ts
1521
- function getFromStore(store, ...params) {
1522
- let token;
1523
- let family;
1524
- let key;
1525
- if (params.length === 1) {
1526
- token = params[0];
1527
- } else {
1528
- family = params[0];
1529
- key = params[1];
1530
- token = findInStore(store, family, key);
1528
+ getContent(a, b) {
1529
+ const contentKey = this.makeContentKey(a, b);
1530
+ return this.getContentInternal(contentKey);
1531
1531
  }
1532
- if (`counterfeit` in token && `family` in token) {
1533
- family = store.families.get(token.family.key);
1534
- const subKey = token.family.subKey;
1535
- const disposal = store.disposalTraces.buffer.find(
1536
- (item) => item?.key === subKey
1537
- );
1538
- store.logger.error(
1539
- `\u274C`,
1540
- token.type,
1541
- token.key,
1542
- `could not be retrieved because it was not found in the store "${store.config.name}".`,
1543
- disposal ? `This state was previously disposed:
1544
- ${disposal.trace}` : `No previous disposal trace was found.`
1545
- );
1546
- switch (family.type) {
1547
- case `atom_family`:
1548
- case `mutable_atom_family`:
1549
- return store.defaults.get(family.key);
1550
- case `selector_family`:
1551
- case `readonly_selector_family`: {
1552
- if (store.defaults.has(family.key)) {
1553
- return store.defaults.get(token.family.key);
1554
- }
1555
- const defaultValue = withdraw(family, store).default(subKey);
1556
- store.defaults.set(family.key, defaultValue);
1557
- return defaultValue;
1532
+ getRelationEntries(input) {
1533
+ const a = input[this.a];
1534
+ const b = input[this.b];
1535
+ if (a !== undefined && b === undefined) {
1536
+ const aRelations = this.getRelatedKeys(a);
1537
+ if (aRelations) {
1538
+ return [...aRelations].map((aRelation) => {
1539
+ return [aRelation, this.getContent(a, aRelation)];
1540
+ });
1541
+ }
1542
+ }
1543
+ if (a === undefined && b !== undefined) {
1544
+ const bRelations = this.getRelatedKeys(b);
1545
+ if (bRelations) {
1546
+ return [...bRelations].map((bRelation) => {
1547
+ return [bRelation, this.getContent(bRelation, b)];
1548
+ });
1558
1549
  }
1559
1550
  }
1551
+ return [];
1560
1552
  }
1561
- return readOrComputeValue(withdraw(token, store), store);
1562
- }
1553
+ has(a, b) {
1554
+ if (b) {
1555
+ const setA = this.getRelatedKeys(a);
1556
+ return setA?.has(b) ?? false;
1557
+ }
1558
+ return this.relations.has(a);
1559
+ }
1560
+ };
1563
1561
 
1564
1562
  // ../atom.io/internal/src/lazy-map.ts
1565
1563
  var LazyMap = class extends Map {
@@ -1713,6 +1711,11 @@ function getEpochNumberOfAction(transactionKey, store) {
1713
1711
  return epoch;
1714
1712
  }
1715
1713
 
1714
+ // ../atom.io/src/transaction.ts
1715
+ function transaction(options) {
1716
+ return createTransaction(options, IMPLICIT.STORE);
1717
+ }
1718
+
1716
1719
  // ../atom.io/internal/src/store/store.ts
1717
1720
  var Store = class {
1718
1721
  parent = null;
@@ -2153,11 +2156,7 @@ var registerSelector = (selectorKey, covered, store) => ({
2153
2156
  const family = params[0];
2154
2157
  const key = params[1];
2155
2158
  value = params[2];
2156
- const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(store, family, key) : seekInStore(store, family, key);
2157
- if (!maybeToken) {
2158
- throw new NotFoundError(family, key, store);
2159
- }
2160
- token = maybeToken;
2159
+ token = findInStore(store, family, key);
2161
2160
  }
2162
2161
  const target = newest(store);
2163
2162
  const state = withdraw(token, target);
@@ -3083,18 +3082,6 @@ function disposeAtom(atomToken, store) {
3083
3082
  }
3084
3083
  }
3085
3084
 
3086
- // ../atom.io/internal/src/get-trace.ts
3087
- function getTrace(error) {
3088
- const { stack } = error;
3089
- if (stack) {
3090
- return `
3091
- ` + stack.split(`
3092
- `)?.slice(1)?.join(`
3093
- `);
3094
- }
3095
- return ``;
3096
- }
3097
-
3098
3085
  // ../atom.io/introspection/src/refinery.ts
3099
3086
  var Refinery = class {
3100
3087
  supported;
@@ -3384,7 +3371,10 @@ var SetRTX = class _SetRTX extends Set {
3384
3371
  this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
3385
3372
  }
3386
3373
  } catch (thrown) {
3387
- console.error(`Failed to apply transaction to SetRTX:`, thrown);
3374
+ console.warn(
3375
+ `Did not apply transaction to SetRTX; this error was thrown:`,
3376
+ thrown
3377
+ );
3388
3378
  throw thrown;
3389
3379
  } finally {
3390
3380
  unsubscribe();
@@ -4774,5 +4764,5 @@ var FlightDeckLogger = class {
4774
4764
  };
4775
4765
 
4776
4766
  export { FLIGHTDECK_ERROR, FLIGHTDECK_INFO, FLIGHTDECK_LNAV_FORMAT, FLIGHTDECK_SETUP_PHASES, FLIGHTDECK_UPDATE_PHASES, FLIGHTDECK_WARN, FlightDeck, FlightDeckLogger, flightDeckLogSchema, isVersionNumber };
4777
- //# sourceMappingURL=chunk-XIZZKICH.js.map
4778
- //# sourceMappingURL=chunk-XIZZKICH.js.map
4767
+ //# sourceMappingURL=chunk-AP2UJF2F.js.map
4768
+ //# sourceMappingURL=chunk-AP2UJF2F.js.map