atom.io 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +14 -8
  2. package/dist/index.d.ts +117 -62
  3. package/dist/index.js +577 -287
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +574 -285
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +16 -6
  8. package/react/dist/index.d.ts +12 -17
  9. package/react/dist/index.js +25 -34
  10. package/react/dist/index.js.map +1 -1
  11. package/react/dist/index.mjs +21 -34
  12. package/react/dist/index.mjs.map +1 -1
  13. package/react-devtools/dist/index.css +26 -0
  14. package/react-devtools/dist/index.css.map +1 -0
  15. package/react-devtools/dist/index.d.ts +15 -0
  16. package/react-devtools/dist/index.js +1579 -0
  17. package/react-devtools/dist/index.js.map +1 -0
  18. package/react-devtools/dist/index.mjs +1551 -0
  19. package/react-devtools/dist/index.mjs.map +1 -0
  20. package/react-devtools/package.json +15 -0
  21. package/src/index.ts +14 -8
  22. package/src/internal/atom-internal.ts +10 -5
  23. package/src/internal/families-internal.ts +7 -7
  24. package/src/internal/get.ts +9 -9
  25. package/src/internal/index.ts +2 -1
  26. package/src/internal/meta/attach-meta.ts +17 -0
  27. package/src/internal/meta/index.ts +4 -0
  28. package/src/internal/meta/meta-state.ts +135 -0
  29. package/src/internal/meta/meta-timelines.ts +1 -0
  30. package/src/internal/meta/meta-transactions.ts +1 -0
  31. package/src/internal/operation.ts +14 -3
  32. package/src/internal/selector-internal.ts +37 -15
  33. package/src/internal/store.ts +35 -6
  34. package/src/internal/time-travel-internal.ts +89 -0
  35. package/src/internal/timeline-internal.ts +110 -93
  36. package/src/internal/transaction-internal.ts +14 -5
  37. package/src/{internal/logger.ts → logger.ts} +2 -2
  38. package/src/react/index.ts +28 -46
  39. package/src/react-devtools/AtomIODevtools.tsx +107 -0
  40. package/src/react-devtools/StateEditor.tsx +73 -0
  41. package/src/react-devtools/TokenList.tsx +49 -0
  42. package/src/react-devtools/devtools.scss +130 -0
  43. package/src/react-devtools/index.ts +1 -0
  44. package/src/react-explorer/AtomIOExplorer.tsx +208 -0
  45. package/src/react-explorer/explorer-effects.ts +20 -0
  46. package/src/react-explorer/explorer-states.ts +224 -0
  47. package/src/react-explorer/index.ts +23 -0
  48. package/src/react-explorer/space-states.ts +73 -0
  49. package/src/react-explorer/view-states.ts +43 -0
  50. package/src/selector.ts +11 -11
  51. package/src/subscribe.ts +3 -3
  52. package/src/timeline.ts +3 -12
  53. package/src/transaction.ts +9 -4
  54. package/src/web-effects/index.ts +1 -0
  55. package/src/web-effects/storage.ts +30 -0
package/dist/index.js CHANGED
@@ -22,20 +22,20 @@ var __spreadValues = (a, b) => {
22
22
  };
23
23
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
24
  var __objRest = (source, exclude) => {
25
- var target3 = {};
25
+ var target2 = {};
26
26
  for (var prop in source)
27
27
  if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
28
- target3[prop] = source[prop];
28
+ target2[prop] = source[prop];
29
29
  if (source != null && __getOwnPropSymbols)
30
30
  for (var prop of __getOwnPropSymbols(source)) {
31
31
  if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
32
- target3[prop] = source[prop];
32
+ target2[prop] = source[prop];
33
33
  }
34
- return target3;
34
+ return target2;
35
35
  };
36
- var __export = (target3, all) => {
36
+ var __export = (target2, all) => {
37
37
  for (var name in all)
38
- __defProp(target3, name, { get: all[name], enumerable: true });
38
+ __defProp(target2, name, { get: all[name], enumerable: true });
39
39
  };
40
40
  var __copyProps = (to, from, except, desc) => {
41
41
  if (from && typeof from === "object" || typeof from === "function") {
@@ -45,12 +45,12 @@ var __copyProps = (to, from, except, desc) => {
45
45
  }
46
46
  return to;
47
47
  };
48
- var __toESM = (mod, isNodeMode, target3) => (target3 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
48
+ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
49
49
  // If the importer is in node compatibility mode or this is not an ESM
50
50
  // file that has been converted to a CommonJS file using a Babel-
51
51
  // compatible transform (i.e. "__esModule" has not been set), then set
52
52
  // "default" to the CommonJS "module.exports" for node compatibility.
53
- isNodeMode || !mod || !mod.__esModule ? __defProp(target3, "default", { value: mod, enumerable: true }) : target3,
53
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target2, "default", { value: mod, enumerable: true }) : target2,
54
54
  mod
55
55
  ));
56
56
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
@@ -58,6 +58,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
58
58
  // src/index.ts
59
59
  var src_exports = {};
60
60
  __export(src_exports, {
61
+ LOG_LEVELS: () => LOG_LEVELS,
61
62
  __INTERNAL__: () => internal_exports,
62
63
  atom: () => atom,
63
64
  atomFamily: () => atomFamily,
@@ -82,7 +83,7 @@ module.exports = __toCommonJS(src_exports);
82
83
  var internal_exports = {};
83
84
  __export(internal_exports, {
84
85
  IMPLICIT: () => IMPLICIT,
85
- LOG_LEVELS: () => LOG_LEVELS,
86
+ META: () => meta_exports,
86
87
  TRANSACTION_PHASES: () => TRANSACTION_PHASES,
87
88
  abortTransaction: () => abortTransaction,
88
89
  applyTransaction: () => applyTransaction,
@@ -120,7 +121,6 @@ __export(internal_exports, {
120
121
  selectorFamily__INTERNAL: () => selectorFamily__INTERNAL,
121
122
  selector__INTERNAL: () => selector__INTERNAL,
122
123
  setAtomState: () => setAtomState,
123
- setLogLevel: () => setLogLevel,
124
124
  setSelectorState: () => setSelectorState,
125
125
  setState__INTERNAL: () => setState__INTERNAL,
126
126
  storeAtom: () => storeAtom,
@@ -136,12 +136,12 @@ __export(internal_exports, {
136
136
  undoTransactionUpdate: () => undoTransactionUpdate,
137
137
  undo__INTERNAL: () => undo__INTERNAL,
138
138
  updateSelectorAtoms: () => updateSelectorAtoms,
139
- useLogger: () => useLogger,
140
139
  withdraw: () => withdraw
141
140
  });
142
141
 
143
142
  // src/internal/atom-internal.ts
144
- var Rx2 = __toESM(require("rxjs"));
143
+ var import_hamt_plus5 = __toESM(require("hamt_plus"));
144
+ var Rx3 = __toESM(require("rxjs"));
145
145
 
146
146
  // src/internal/get.ts
147
147
  var import_hamt_plus = __toESM(require("hamt_plus"));
@@ -168,7 +168,7 @@ var getState__INTERNAL = (state, store = IMPLICIT.STORE) => {
168
168
  (_a = store.config.logger) == null ? void 0 : _a.info(`>> read "${state.key}"`);
169
169
  return readCachedValue(state.key, store);
170
170
  }
171
- if (`get` in state) {
171
+ if (state.type !== `atom`) {
172
172
  (_b = store.config.logger) == null ? void 0 : _b.info(`-> calc "${state.key}"`);
173
173
  return computeSelectorState(state);
174
174
  }
@@ -202,6 +202,7 @@ var import_hamt_plus3 = __toESM(require("hamt_plus"));
202
202
 
203
203
  // src/internal/store.ts
204
204
  var import_hamt_plus2 = __toESM(require("hamt_plus"));
205
+ var Rx = __toESM(require("rxjs"));
205
206
 
206
207
  // ../anvl/src/function/index.ts
207
208
  var doNothing = () => void 0;
@@ -293,18 +294,68 @@ var hasExactProperties = (
293
294
  (isValue) => hasProperties(isValue, { allowExtraProperties: false })
294
295
  );
295
296
 
297
+ // ../anvl/src/refinement/index.ts
298
+ var canExist = (_) => true;
299
+ var cannotExist = (_) => false;
300
+ var isLiteral = (value) => (input) => input === value;
301
+ var couldBe = (isTypeA, logging = false, refinements = [isTypeA]) => {
302
+ const name = `(${refinements.map((r) => r.name || `anon`).join(` | `)})`;
303
+ const _ = {
304
+ [name]: (input) => refinements.some(
305
+ (refinement) => {
306
+ var _a;
307
+ return logging && console.log(
308
+ refinements.map((r) => r.name || `anon`).join(` | `),
309
+ `>`,
310
+ (_a = refinement.name) != null ? _a : `anon`,
311
+ `:`,
312
+ refinement(input)
313
+ ), refinement(input);
314
+ }
315
+ )
316
+ };
317
+ const checkTypes = Object.assign(_[name], {
318
+ or: (isTypeB) => couldBe(isTypeB, logging, [...refinements, isTypeB])
319
+ });
320
+ return checkTypes;
321
+ };
322
+ var isUnion = couldBe(cannotExist);
323
+ var mustBe = (isTypeA, logging = false, refinements = [isTypeA]) => {
324
+ const name = `(${refinements.map((r) => r.name || `anon`).join(` & `)})`;
325
+ const _ = {
326
+ [name]: (input) => refinements.every(
327
+ (refinement) => (logging && console.log(
328
+ refinements.map((r) => r.name || `anon`).join(` & `),
329
+ `>`,
330
+ refinement.name || `anon`,
331
+ `:`,
332
+ refinement(input)
333
+ ), refinement(input))
334
+ )
335
+ };
336
+ const checkTypes = Object.assign(_[name], {
337
+ and: (isTypeB) => mustBe(isTypeB, logging, [...refinements, isTypeB])
338
+ });
339
+ return checkTypes;
340
+ };
341
+ var isIntersection = mustBe(canExist);
342
+
296
343
  // ../anvl/src/join/core-relation-data.ts
297
344
  var RELATION_TYPES = [`1:1`, `1:n`, `n:n`];
298
345
  var isRelationType = (x) => RELATION_TYPES.includes(x);
299
346
  var EMPTY_RELATION_DATA = {
300
347
  contents: {},
301
348
  relations: {},
302
- relationType: `n:n`
349
+ relationType: `n:n`,
350
+ a: `from`,
351
+ b: `to`
303
352
  };
304
- var isRelationData = (isContent) => (input) => hasExactProperties({
353
+ var isRelationData = (isContent, a = `from`, b = `to`) => (input) => hasExactProperties({
305
354
  contents: isContent ? isRecord(import_string.isString, isContent) : hasExactProperties({}),
306
355
  relations: isRecord(import_string.isString, isArray(import_string.isString)),
307
- relationType: isRelationType
356
+ relationType: isRelationType,
357
+ a: isLiteral(a),
358
+ b: isLiteral(b)
308
359
  })(input);
309
360
 
310
361
  // ../anvl/src/join/get-related-ids.ts
@@ -393,7 +444,11 @@ var removeAll = (current, idToRemove) => {
393
444
  });
394
445
  return next;
395
446
  };
396
- var removeRelation = (current, idA, idB) => idB ? removeSpecific(current, idA, idB) : removeAll(current, idA);
447
+ var removeRelation = (current, relation) => {
448
+ const idA = relation[current.a];
449
+ const idB = relation[current.b];
450
+ return idB ? removeSpecific(current, idA, idB) : removeAll(current, idA);
451
+ };
397
452
 
398
453
  // ../anvl/src/join/set-relation.ts
399
454
  var setManyToMany = (map2, idA, idB, ...rest) => {
@@ -437,7 +492,8 @@ var set1To1 = (current, wifeId, husbandId, ...rest) => {
437
492
  const content = rest[0];
438
493
  return content ? setContent(next, wifeId, husbandId, content) : next;
439
494
  };
440
- var setRelationWithContent = (current, idA, idB, ...rest) => {
495
+ var setRelationWithContent = (current, relation, ...rest) => {
496
+ const { [current.a]: idA, [current.b]: idB } = relation;
441
497
  switch (current.relationType) {
442
498
  case `1:1`:
443
499
  return set1To1(current, idA, idB, ...rest);
@@ -461,96 +517,69 @@ var getRelations = (relationMap, id) => getRelationEntries(relationMap, id).map(
461
517
  id: id2
462
518
  }, content)
463
519
  );
464
- var setRelations = (current, idA, relations) => (0, import_function6.pipe)(
465
- current,
466
- (relationData) => {
467
- const relatedIds = getRelatedIds(current, idA);
468
- const removedIds = relatedIds.filter(
469
- (id) => !relations.some((r) => r.id === id)
470
- );
471
- let step = relationData;
472
- for (const idB of removedIds)
473
- step = removeRelation(step, idA, idB);
474
- return step;
475
- },
476
- (relationData) => {
477
- let step = relationData;
478
- for (const _a of relations) {
479
- const _b = _a, { id: idB } = _b, rest = __objRest(_b, ["id"]);
480
- const content = isEmptyObject(rest) ? void 0 : rest;
481
- step = setRelationWithContent(step, idA, idB, content);
482
- }
483
- return step;
484
- },
485
- (relationData) => {
486
- const newlyOrderedIds = relations.map((r) => r.id);
487
- return __spreadProps(__spreadValues({}, relationData), {
488
- relations: __spreadProps(__spreadValues({}, relationData.relations), {
489
- [idA]: newlyOrderedIds
490
- })
491
- });
492
- }
493
- );
494
-
495
- // ../anvl/src/refinement/index.ts
496
- var canExist = (_) => true;
497
- var cannotExist = (_) => false;
498
- var couldBe = (isTypeA, logging = false, refinements = [isTypeA]) => {
499
- const name = `(${refinements.map((r) => r.name || `anon`).join(` | `)})`;
500
- const _ = {
501
- [name]: (input) => refinements.some(
502
- (refinement) => {
503
- var _a;
504
- return logging && console.log(
505
- refinements.map((r) => r.name || `anon`).join(` | `),
506
- `>`,
507
- (_a = refinement.name) != null ? _a : `anon`,
508
- `:`,
509
- refinement(input)
510
- ), refinement(input);
520
+ var setRelations = (current, subject, relations) => {
521
+ const idA = subject[current.a];
522
+ const idB = subject[current.b];
523
+ return (0, import_function6.pipe)(
524
+ current,
525
+ (relationData) => {
526
+ const relatedIds = getRelatedIds(current, idA);
527
+ const removedIds = relatedIds.filter(
528
+ (id) => !relations.some((r) => r.id === id)
529
+ );
530
+ let step = relationData;
531
+ for (const id of removedIds) {
532
+ const remove = {
533
+ [current.a]: idA != null ? idA : id,
534
+ [current.b]: idB != null ? idB : id
535
+ };
536
+ step = removeRelation(step, remove);
511
537
  }
512
- )
513
- };
514
- const checkTypes = Object.assign(_[name], {
515
- or: (isTypeB) => couldBe(isTypeB, logging, [...refinements, isTypeB])
516
- });
517
- return checkTypes;
518
- };
519
- var isUnion = couldBe(cannotExist);
520
- var mustBe = (isTypeA, logging = false, refinements = [isTypeA]) => {
521
- const name = `(${refinements.map((r) => r.name || `anon`).join(` & `)})`;
522
- const _ = {
523
- [name]: (input) => refinements.every(
524
- (refinement) => (logging && console.log(
525
- refinements.map((r) => r.name || `anon`).join(` & `),
526
- `>`,
527
- refinement.name || `anon`,
528
- `:`,
529
- refinement(input)
530
- ), refinement(input))
531
- )
532
- };
533
- const checkTypes = Object.assign(_[name], {
534
- and: (isTypeB) => mustBe(isTypeB, logging, [...refinements, isTypeB])
535
- });
536
- return checkTypes;
538
+ return step;
539
+ },
540
+ (relationData) => {
541
+ let step = relationData;
542
+ for (const _a of relations) {
543
+ const _b = _a, { id } = _b, rest = __objRest(_b, ["id"]);
544
+ const content = isEmptyObject(rest) ? void 0 : rest;
545
+ step = setRelationWithContent(
546
+ step,
547
+ { [current.a]: idA != null ? idA : id, [current.b]: idB != null ? idB : id },
548
+ // @ts-expect-error hacky
549
+ content
550
+ );
551
+ }
552
+ return step;
553
+ },
554
+ (relationData) => {
555
+ const newlyOrderedIds = relations.map((r) => r.id);
556
+ return __spreadProps(__spreadValues({}, relationData), {
557
+ relations: __spreadProps(__spreadValues({}, relationData.relations), {
558
+ [idA != null ? idA : idB]: newlyOrderedIds
559
+ })
560
+ });
561
+ }
562
+ );
537
563
  };
538
- var isIntersection = mustBe(canExist);
539
564
 
540
565
  // ../anvl/src/join/index.ts
541
566
  var Join = class {
542
567
  constructor(json) {
568
+ this.a = `from`;
569
+ this.b = `to`;
543
570
  Object.assign(this, __spreadValues(__spreadValues({}, EMPTY_RELATION_DATA), json));
544
571
  }
545
572
  toJSON() {
546
573
  return {
547
574
  relationType: this.relationType,
548
575
  relations: this.relations,
549
- contents: this.contents
576
+ contents: this.contents,
577
+ a: this.a,
578
+ b: this.b
550
579
  };
551
580
  }
552
- static fromJSON(json, isContent = cannotExist) {
553
- const isValid = isRelationData(isContent)(json);
581
+ static fromJSON(json, isContent = cannotExist, a = `from`, b = `to`) {
582
+ const isValid = isRelationData(isContent, a, b)(json);
554
583
  if (isValid) {
555
584
  return new Join(json);
556
585
  }
@@ -558,6 +587,12 @@ var Join = class {
558
587
  `Saved JSON for this Join is invalid: ${JSON.stringify(json)}`
559
588
  );
560
589
  }
590
+ from(newA) {
591
+ return new Join(__spreadProps(__spreadValues({}, this), { a: newA }));
592
+ }
593
+ to(newB) {
594
+ return new Join(__spreadProps(__spreadValues({}, this), { b: newB }));
595
+ }
561
596
  getRelatedId(id) {
562
597
  return getRelatedId(this, id);
563
598
  }
@@ -579,14 +614,16 @@ var Join = class {
579
614
  getRelations(id) {
580
615
  return getRelations(this, id);
581
616
  }
582
- setRelations(id, relations) {
583
- return new Join(setRelations(this, id, relations));
617
+ setRelations(subject, relations) {
618
+ return new Join(setRelations(this, subject, relations));
584
619
  }
585
- set(idA, idB, ...rest) {
586
- return new Join(setRelationWithContent(this, idA, idB, ...rest));
620
+ set(relation, ...rest) {
621
+ return new Join(setRelationWithContent(this, relation, ...rest));
587
622
  }
588
- remove(idA, idB) {
589
- return new Join(removeRelation(this, idA, idB));
623
+ remove(relation) {
624
+ return new Join(
625
+ removeRelation(this, relation)
626
+ );
590
627
  }
591
628
  };
592
629
 
@@ -595,14 +632,20 @@ var createStore = (name) => ({
595
632
  atoms: import_hamt_plus2.default.make(),
596
633
  atomsThatAreDefault: /* @__PURE__ */ new Set(),
597
634
  readonlySelectors: import_hamt_plus2.default.make(),
598
- selectorAtoms: new Join({ relationType: `n:n` }),
635
+ selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
599
636
  selectorGraph: new Join({ relationType: `n:n` }),
600
637
  selectors: import_hamt_plus2.default.make(),
601
638
  timelines: import_hamt_plus2.default.make(),
602
- timelineAtoms: new Join({ relationType: `1:n` }),
639
+ timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
603
640
  timelineStore: import_hamt_plus2.default.make(),
604
641
  transactions: import_hamt_plus2.default.make(),
605
642
  valueMap: import_hamt_plus2.default.make(),
643
+ subject: {
644
+ atomCreation: new Rx.Subject(),
645
+ selectorCreation: new Rx.Subject(),
646
+ transactionCreation: new Rx.Subject(),
647
+ timelineCreation: new Rx.Subject()
648
+ },
606
649
  operation: {
607
650
  open: false
608
651
  },
@@ -631,21 +674,29 @@ var clearStore = (store = IMPLICIT.STORE) => {
631
674
  };
632
675
 
633
676
  // src/internal/operation.ts
634
- var openOperation = (store) => {
635
- var _a;
677
+ var openOperation = (token, store) => {
678
+ var _a, _b;
636
679
  const core = target(store);
680
+ if (core.operation.open) {
681
+ (_a = store.config.logger) == null ? void 0 : _a.error(
682
+ `\u274C failed to setState to "${token.key}" during a setState for "${core.operation.token.key}"`
683
+ );
684
+ throw Symbol(`violation`);
685
+ }
637
686
  core.operation = {
638
687
  open: true,
639
688
  done: /* @__PURE__ */ new Set(),
640
- prev: store.valueMap
689
+ prev: store.valueMap,
690
+ time: Date.now(),
691
+ token
641
692
  };
642
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u2B55`, `operation start`);
693
+ (_b = store.config.logger) == null ? void 0 : _b.info(`\u2B55 operation start from "${token.key}"`);
643
694
  };
644
695
  var closeOperation = (store) => {
645
696
  var _a;
646
697
  const core = target(store);
647
698
  core.operation = { open: false };
648
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F534}`, `operation done`);
699
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F534} operation done`);
649
700
  };
650
701
  var isDone = (key, store = IMPLICIT.STORE) => {
651
702
  var _a;
@@ -713,7 +764,7 @@ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
713
764
 
714
765
  // src/internal/transaction-internal.ts
715
766
  var import_hamt_plus4 = __toESM(require("hamt_plus"));
716
- var Rx = __toESM(require("rxjs"));
767
+ var Rx2 = __toESM(require("rxjs"));
717
768
  var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
718
769
  var buildTransaction = (key, params, store) => {
719
770
  var _a;
@@ -740,7 +791,7 @@ var buildTransaction = (key, params, store) => {
740
791
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
741
792
  };
742
793
  var applyTransaction = (output, store) => {
743
- var _a, _b, _c;
794
+ var _a, _b, _c, _d;
744
795
  if (store.transactionStatus.phase !== `building`) {
745
796
  (_a = store.config.logger) == null ? void 0 : _a.warn(
746
797
  `abortTransaction called outside of a transaction. This is probably a bug.`
@@ -748,13 +799,19 @@ var applyTransaction = (output, store) => {
748
799
  return;
749
800
  }
750
801
  (_b = store.config.logger) == null ? void 0 : _b.info(
751
- ` \u25B6\uFE0F apply transaction "${store.transactionStatus.key}" (init)`
802
+ `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
752
803
  );
753
804
  store.transactionStatus.phase = `applying`;
754
805
  store.transactionStatus.output = output;
755
806
  const { atomUpdates } = store.transactionStatus;
756
- for (const { key, oldValue, newValue } of atomUpdates) {
807
+ for (const { key, newValue } of atomUpdates) {
757
808
  const token = { key, type: `atom` };
809
+ if (!import_hamt_plus4.default.has(token.key, store.valueMap)) {
810
+ const atom2 = import_hamt_plus4.default.get(token.key, store.transactionStatus.core.atoms);
811
+ store.atoms = import_hamt_plus4.default.set(atom2.key, atom2, store.atoms);
812
+ store.valueMap = import_hamt_plus4.default.set(atom2.key, atom2.default, store.valueMap);
813
+ (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${atom2.key}"`);
814
+ }
758
815
  const state = withdraw(token, store);
759
816
  setState(state, newValue, store);
760
817
  }
@@ -769,12 +826,12 @@ var applyTransaction = (output, store) => {
769
826
  params: store.transactionStatus.params
770
827
  });
771
828
  store.transactionStatus = { phase: `idle` };
772
- (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F6EC}`, `transaction done`);
829
+ (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
773
830
  };
774
831
  var undoTransactionUpdate = (update, store) => {
775
832
  var _a;
776
833
  (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
777
- for (const { key, oldValue, newValue } of update.atomUpdates) {
834
+ for (const { key, oldValue } of update.atomUpdates) {
778
835
  const token = { key, type: `atom` };
779
836
  const state = withdraw(token, store);
780
837
  setState(state, oldValue, store);
@@ -783,7 +840,7 @@ var undoTransactionUpdate = (update, store) => {
783
840
  var redoTransactionUpdate = (update, store) => {
784
841
  var _a;
785
842
  (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
786
- for (const { key, oldValue, newValue } of update.atomUpdates) {
843
+ for (const { key, newValue } of update.atomUpdates) {
787
844
  const token = { key, type: `atom` };
788
845
  const state = withdraw(token, store);
789
846
  setState(state, newValue, store);
@@ -823,7 +880,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
823
880
  throw thrown;
824
881
  }
825
882
  },
826
- subject: new Rx.Subject()
883
+ subject: new Rx2.Subject()
827
884
  };
828
885
  const core = target(store);
829
886
  core.transactions = import_hamt_plus4.default.set(
@@ -832,6 +889,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
832
889
  core.transactions
833
890
  );
834
891
  const token = deposit(newTransaction);
892
+ store.subject.transactionCreation.next(token);
835
893
  return token;
836
894
  }
837
895
  var target = (store = IMPLICIT.STORE) => store.transactionStatus.phase === `building` ? store.transactionStatus.core : store;
@@ -847,24 +905,28 @@ function atom__INTERNAL(options, family, store = IMPLICIT.STORE) {
847
905
  );
848
906
  return deposit(core.atoms.get(options.key));
849
907
  }
850
- const subject = new Rx2.Subject();
908
+ const subject = new Rx3.Subject();
851
909
  const newAtom = __spreadValues(__spreadProps(__spreadValues({}, options), {
852
910
  subject,
853
911
  type: `atom`
854
912
  }), family && { family });
855
913
  const initialValue = options.default instanceof Function ? options.default() : options.default;
856
- storeAtom(newAtom, store);
914
+ core.atoms = import_hamt_plus5.default.set(newAtom.key, newAtom, core.atoms);
857
915
  markAtomAsDefault(options.key, store);
858
916
  cacheValue(options.key, initialValue, store);
859
917
  const token = deposit(newAtom);
860
- const setSelf = (next) => setState(token, next, store);
861
- const onSet = (handle) => subscribe(token, handle, store);
862
- (_c = options.effects) == null ? void 0 : _c.forEach((effect) => effect({ setSelf, onSet }));
918
+ (_c = options.effects) == null ? void 0 : _c.forEach(
919
+ (effect) => effect({
920
+ setSelf: (next) => setState(token, next, store),
921
+ onSet: (handle) => subscribe(token, handle, store)
922
+ })
923
+ );
924
+ store.subject.atomCreation.next(token);
863
925
  return token;
864
926
  }
865
927
 
866
928
  // src/internal/families-internal.ts
867
- var Rx3 = __toESM(require("rxjs"));
929
+ var Rx4 = __toESM(require("rxjs"));
868
930
 
869
931
  // ../anvl/src/json/index.ts
870
932
  var import_function8 = require("fp-ts/function");
@@ -872,13 +934,13 @@ var stringifyJson = (json) => JSON.stringify(json);
872
934
 
873
935
  // src/internal/families-internal.ts
874
936
  function atomFamily__INTERNAL(options, store = IMPLICIT.STORE) {
875
- const subject = new Rx3.Subject();
937
+ const subject = new Rx4.Subject();
876
938
  return Object.assign(
877
939
  (key) => {
878
940
  var _a;
879
941
  const subKey = stringifyJson(key);
880
942
  const family = { key: options.key, subKey };
881
- const fullKey = `${options.key}__${subKey}`;
943
+ const fullKey = `${options.key}(${subKey})`;
882
944
  const existing = withdraw({ key: fullKey, type: `atom` }, store);
883
945
  const token = existing ? deposit(existing) : atom__INTERNAL(
884
946
  {
@@ -901,12 +963,12 @@ function atomFamily__INTERNAL(options, store = IMPLICIT.STORE) {
901
963
  }
902
964
  function readonlySelectorFamily__INTERNAL(options, store) {
903
965
  const core = target(store);
904
- const subject = new Rx3.Subject();
966
+ const subject = new Rx4.Subject();
905
967
  return Object.assign(
906
968
  (key) => {
907
969
  const subKey = stringifyJson(key);
908
970
  const family = { key: options.key, subKey };
909
- const fullKey = `${options.key}__${subKey}`;
971
+ const fullKey = `${options.key}(${subKey})`;
910
972
  const existing = core.readonlySelectors.get(fullKey);
911
973
  if (existing) {
912
974
  return deposit(existing);
@@ -933,12 +995,12 @@ function selectorFamily__INTERNAL(options, store = IMPLICIT.STORE) {
933
995
  return readonlySelectorFamily__INTERNAL(options, store);
934
996
  }
935
997
  const core = target(store);
936
- const subject = new Rx3.Subject();
998
+ const subject = new Rx4.Subject();
937
999
  return Object.assign(
938
1000
  (key) => {
939
1001
  const subKey = stringifyJson(key);
940
1002
  const family = { key: options.key, subKey };
941
- const fullKey = `${options.key}__${subKey}`;
1003
+ const fullKey = `${options.key}(${subKey})`;
942
1004
  const existing = core.selectors.get(fullKey);
943
1005
  if (existing) {
944
1006
  return deposit(existing);
@@ -962,42 +1024,123 @@ function selectorFamily__INTERNAL(options, store = IMPLICIT.STORE) {
962
1024
  );
963
1025
  }
964
1026
 
965
- // src/internal/logger.ts
966
- var LOG_LEVELS = [
967
- `info`,
968
- `warn`,
969
- `error`
970
- ];
971
- var setLogLevel = (preferredLevel, store = IMPLICIT.STORE) => {
972
- const { logger__INTERNAL } = store.config;
973
- if (preferredLevel === null) {
974
- store.config.logger = null;
975
- } else {
976
- store.config.logger = __spreadValues({}, console);
977
- LOG_LEVELS.forEach((logLevel) => {
978
- if (LOG_LEVELS.indexOf(logLevel) < LOG_LEVELS.indexOf(preferredLevel)) {
979
- store.config.logger[logLevel] = doNothing;
980
- } else {
981
- store.config.logger[logLevel] = logger__INTERNAL[logLevel];
1027
+ // src/internal/meta/index.ts
1028
+ var meta_exports = {};
1029
+ __export(meta_exports, {
1030
+ attachMetaAtoms: () => attachMetaAtoms,
1031
+ attachMetaSelectors: () => attachMetaSelectors,
1032
+ attachMetaState: () => attachMetaState
1033
+ });
1034
+
1035
+ // src/internal/meta/meta-state.ts
1036
+ var attachMetaAtoms = (store = IMPLICIT.STORE) => {
1037
+ const atomTokenIndexState__INTERNAL = atom({
1038
+ key: `\u{1F441}\u200D\u{1F5E8}_atom_token_index__INTERNAL`,
1039
+ default: () => [...store.atoms].reduce((acc, [key]) => {
1040
+ acc[key] = { key, type: `atom` };
1041
+ return acc;
1042
+ }, {}),
1043
+ effects: [
1044
+ ({ setSelf }) => {
1045
+ store.subject.atomCreation.subscribe((atomToken) => {
1046
+ if (store.operation.open) {
1047
+ return;
1048
+ }
1049
+ setSelf((state) => {
1050
+ const { key, family } = atomToken;
1051
+ if (family) {
1052
+ const { key: familyKey, subKey } = family;
1053
+ const current = state[familyKey];
1054
+ if (current === void 0 || `familyMembers` in current) {
1055
+ const familyKeyState = current || {
1056
+ key: familyKey,
1057
+ familyMembers: {}
1058
+ };
1059
+ return __spreadProps(__spreadValues({}, state), {
1060
+ [familyKey]: __spreadProps(__spreadValues({}, familyKeyState), {
1061
+ familyMembers: __spreadProps(__spreadValues({}, familyKeyState.familyMembers), {
1062
+ [subKey]: atomToken
1063
+ })
1064
+ })
1065
+ });
1066
+ }
1067
+ }
1068
+ return __spreadProps(__spreadValues({}, state), {
1069
+ [key]: atomToken
1070
+ });
1071
+ });
1072
+ });
982
1073
  }
983
- });
984
- }
1074
+ ]
1075
+ });
1076
+ return selector({
1077
+ key: `\u{1F441}\u200D\u{1F5E8}_atom_token_index`,
1078
+ get: ({ get }) => get(atomTokenIndexState__INTERNAL)
1079
+ });
985
1080
  };
986
- var useLogger = (logger, store = IMPLICIT.STORE) => {
987
- var _a;
988
- const currentLogLevel = store.config.logger === null ? null : (_a = LOG_LEVELS.find(
989
- (logLevel) => {
990
- var _a2;
991
- return ((_a2 = store.config.logger) == null ? void 0 : _a2[logLevel]) !== doNothing;
992
- }
993
- )) != null ? _a : null;
994
- store.config.logger__INTERNAL = __spreadValues({}, logger);
995
- setLogLevel(currentLogLevel, store);
1081
+ var attachMetaSelectors = (store = IMPLICIT.STORE) => {
1082
+ const readonlySelectorTokenIndexState__INTERNAL = atom({
1083
+ key: `\u{1F441}\u200D\u{1F5E8}_selector_token_index__INTERNAL`,
1084
+ default: () => Object.assign(
1085
+ [...store.readonlySelectors].reduce((acc, [key]) => {
1086
+ acc[key] = { key, type: `readonly_selector` };
1087
+ return acc;
1088
+ }, {}),
1089
+ [...store.selectors].reduce((acc, [key]) => {
1090
+ acc[key] = { key, type: `selector` };
1091
+ return acc;
1092
+ }, {})
1093
+ ),
1094
+ effects: [
1095
+ ({ setSelf }) => {
1096
+ store.subject.selectorCreation.subscribe((selectorToken) => {
1097
+ if (store.operation.open) {
1098
+ return;
1099
+ }
1100
+ setSelf((state) => {
1101
+ const { key, family } = selectorToken;
1102
+ if (family) {
1103
+ const { key: familyKey, subKey } = family;
1104
+ const current = state[familyKey];
1105
+ if (current === void 0 || `familyMembers` in current) {
1106
+ const familyKeyState = current || {
1107
+ key: familyKey,
1108
+ familyMembers: {}
1109
+ };
1110
+ return __spreadProps(__spreadValues({}, state), {
1111
+ [familyKey]: __spreadProps(__spreadValues({}, familyKeyState), {
1112
+ familyMembers: __spreadProps(__spreadValues({}, familyKeyState.familyMembers), {
1113
+ [subKey]: selectorToken
1114
+ })
1115
+ })
1116
+ });
1117
+ }
1118
+ }
1119
+ return __spreadProps(__spreadValues({}, state), {
1120
+ [key]: selectorToken
1121
+ });
1122
+ });
1123
+ });
1124
+ }
1125
+ ]
1126
+ });
1127
+ return selector({
1128
+ key: `\u{1F441}\u200D\u{1F5E8}_selector_token_index`,
1129
+ get: ({ get }) => get(readonlySelectorTokenIndexState__INTERNAL)
1130
+ });
1131
+ };
1132
+
1133
+ // src/internal/meta/attach-meta.ts
1134
+ var attachMetaState = (store = IMPLICIT.STORE) => {
1135
+ return {
1136
+ atomTokenIndexState: attachMetaAtoms(store),
1137
+ selectorTokenIndexState: attachMetaSelectors(store)
1138
+ };
996
1139
  };
997
1140
 
998
1141
  // src/internal/selector-internal.ts
999
- var import_hamt_plus5 = __toESM(require("hamt_plus"));
1000
- var Rx4 = __toESM(require("rxjs"));
1142
+ var import_hamt_plus6 = __toESM(require("hamt_plus"));
1143
+ var Rx5 = __toESM(require("rxjs"));
1001
1144
  var lookupSelectorSources = (key, store) => target(store).selectorGraph.getRelations(key).filter(({ source }) => source !== key).map(({ source }) => lookup(source, store));
1002
1145
  var traceSelectorAtoms = (selectorKey, dependency, store) => {
1003
1146
  const roots = [];
@@ -1029,7 +1172,10 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1029
1172
  var _a, _b;
1030
1173
  const core = target(store);
1031
1174
  if (dependency.type === `atom`) {
1032
- core.selectorAtoms = core.selectorAtoms.set(selectorKey, dependency.key);
1175
+ core.selectorAtoms = core.selectorAtoms.set({
1176
+ selectorKey,
1177
+ atomKey: dependency.key
1178
+ });
1033
1179
  (_a = store.config.logger) == null ? void 0 : _a.info(
1034
1180
  ` || adding root for "${selectorKey}": ${dependency.key}`
1035
1181
  );
@@ -1041,7 +1187,10 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1041
1187
  roots.map((r) => r.key)
1042
1188
  );
1043
1189
  for (const root of roots) {
1044
- core.selectorAtoms = core.selectorAtoms.set(selectorKey, root.key);
1190
+ core.selectorAtoms = core.selectorAtoms.set({
1191
+ selectorKey,
1192
+ atomKey: root.key
1193
+ });
1045
1194
  }
1046
1195
  };
1047
1196
  var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
@@ -1058,12 +1207,16 @@ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1058
1207
  );
1059
1208
  } else {
1060
1209
  (_b = store.config.logger) == null ? void 0 : _b.info(
1061
- `\u{1F50C} registerSelector "${selectorKey}" <- "${dependency.key}" =`,
1062
- dependencyValue
1210
+ `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1211
+ dependencyValue,
1212
+ `)`
1213
+ );
1214
+ core.selectorGraph = core.selectorGraph.set(
1215
+ { from: dependency.key, to: selectorKey },
1216
+ {
1217
+ source: dependency.key
1218
+ }
1063
1219
  );
1064
- core.selectorGraph = core.selectorGraph.set(selectorKey, dependency.key, {
1065
- source: dependency.key
1066
- });
1067
1220
  }
1068
1221
  updateSelectorAtoms(selectorKey, dependency, store);
1069
1222
  return dependencyValue;
@@ -1076,12 +1229,12 @@ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1076
1229
  function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1077
1230
  var _a, _b, _c;
1078
1231
  const core = target(store);
1079
- if (import_hamt_plus5.default.has(options.key, core.selectors)) {
1232
+ if (import_hamt_plus6.default.has(options.key, core.selectors)) {
1080
1233
  (_a = store.config.logger) == null ? void 0 : _a.error(
1081
1234
  `Key "${options.key}" already exists in the store.`
1082
1235
  );
1083
1236
  }
1084
- const subject = new Rx4.Subject();
1237
+ const subject = new Rx5.Subject();
1085
1238
  const { get, set } = registerSelector(options.key, store);
1086
1239
  const getSelf = () => {
1087
1240
  const value = options.get({ get });
@@ -1094,14 +1247,20 @@ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1094
1247
  get: getSelf,
1095
1248
  type: `readonly_selector`
1096
1249
  }), family && { family });
1097
- core.readonlySelectors = import_hamt_plus5.default.set(
1250
+ core.readonlySelectors = import_hamt_plus6.default.set(
1098
1251
  options.key,
1099
1252
  readonlySelector,
1100
1253
  core.readonlySelectors
1101
1254
  );
1102
1255
  const initialValue2 = getSelf();
1103
1256
  (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
1104
- return __spreadProps(__spreadValues({}, readonlySelector), { type: `readonly_selector` });
1257
+ const token2 = {
1258
+ key: options.key,
1259
+ type: `readonly_selector`,
1260
+ family
1261
+ };
1262
+ store.subject.selectorCreation.next(token2);
1263
+ return token2;
1105
1264
  }
1106
1265
  const setSelf = (next) => {
1107
1266
  var _a2;
@@ -1121,14 +1280,20 @@ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1121
1280
  set: setSelf,
1122
1281
  type: `selector`
1123
1282
  }), family && { family });
1124
- core.selectors = import_hamt_plus5.default.set(options.key, mySelector, core.selectors);
1283
+ core.selectors = import_hamt_plus6.default.set(options.key, mySelector, core.selectors);
1125
1284
  const initialValue = getSelf();
1126
1285
  (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
1127
- return __spreadProps(__spreadValues({}, mySelector), { type: `selector` });
1286
+ const token = {
1287
+ key: options.key,
1288
+ type: `selector`,
1289
+ family
1290
+ };
1291
+ store.subject.selectorCreation.next(token);
1292
+ return token;
1128
1293
  }
1129
1294
 
1130
1295
  // src/internal/set.ts
1131
- var import_hamt_plus6 = __toESM(require("hamt_plus"));
1296
+ var import_hamt_plus7 = __toESM(require("hamt_plus"));
1132
1297
  var evictDownStream = (state, store = IMPLICIT.STORE) => {
1133
1298
  var _a, _b;
1134
1299
  const core = target(store);
@@ -1147,7 +1312,7 @@ var evictDownStream = (state, store = IMPLICIT.STORE) => {
1147
1312
  (_a2 = store.config.logger) == null ? void 0 : _a2.info(` || ${stateKey} already done`);
1148
1313
  return;
1149
1314
  }
1150
- const state2 = (_b2 = import_hamt_plus6.default.get(stateKey, core.selectors)) != null ? _b2 : import_hamt_plus6.default.get(stateKey, core.readonlySelectors);
1315
+ const state2 = (_b2 = import_hamt_plus7.default.get(stateKey, core.selectors)) != null ? _b2 : import_hamt_plus7.default.get(stateKey, core.readonlySelectors);
1151
1316
  if (!state2) {
1152
1317
  (_c = store.config.logger) == null ? void 0 : _c.info(
1153
1318
  ` || ${stateKey} is an atom, and can't be downstream`
@@ -1248,112 +1413,32 @@ var subscribeToRootAtoms = (state, store) => {
1248
1413
  return dependencySubscriptions;
1249
1414
  };
1250
1415
 
1251
- // src/internal/timeline-internal.ts
1252
- var import_hamt_plus7 = __toESM(require("hamt_plus"));
1253
- function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1254
- let incompleteTransactionKey = null;
1255
- const timelineData = {
1256
- at: 0,
1257
- timeTraveling: false,
1258
- history: []
1259
- };
1260
- const subscribeToAtom = (token) => {
1261
- const state = withdraw(token, store);
1262
- state.subject.subscribe((update) => {
1263
- var _a, _b, _c;
1264
- const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1265
- (_a = store.config.logger) == null ? void 0 : _a.info(
1266
- `\u23F3 timeline "${options.key}" saw atom "${token.key}" go (`,
1267
- update.oldValue,
1268
- `->`,
1269
- update.newValue,
1270
- storeCurrentTransactionKey ? `) in "${storeCurrentTransactionKey}"` : `) independently`
1271
- );
1272
- if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1273
- const currentTransaction = withdraw(
1274
- { key: storeCurrentTransactionKey, type: `transaction` },
1275
- store
1276
- );
1277
- if (incompleteTransactionKey !== storeCurrentTransactionKey) {
1278
- if (incompleteTransactionKey) {
1279
- (_b = store.config.logger) == null ? void 0 : _b.error(
1280
- `Timeline "${options.key}" was unable to resolve transaction "${incompleteTransactionKey}. This is probably a bug.`
1281
- );
1282
- }
1283
- incompleteTransactionKey = storeCurrentTransactionKey;
1284
- const subscription = currentTransaction.subject.subscribe((update2) => {
1285
- var _a2;
1286
- if (timelineData.timeTraveling === false) {
1287
- timelineData.history.push(__spreadProps(__spreadValues({
1288
- type: `transaction_update`
1289
- }, update2), {
1290
- atomUpdates: update2.atomUpdates.filter(
1291
- (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1292
- )
1293
- }));
1294
- }
1295
- timelineData.at = timelineData.history.length;
1296
- subscription.unsubscribe();
1297
- incompleteTransactionKey = null;
1298
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1299
- `\u231B timeline "${options.key}" pushed a transaction_update from "${update2.key}"`
1300
- );
1301
- });
1302
- }
1303
- } else {
1304
- if (timelineData.timeTraveling === false) {
1305
- timelineData.history.push({
1306
- type: `state_update`,
1307
- key: token.key,
1308
- oldValue: update.oldValue,
1309
- newValue: update.newValue
1310
- });
1311
- (_c = store.config.logger) == null ? void 0 : _c.info(
1312
- `\u231B timeline "${options.key}" pushed a state_update to "${token.key}"`
1313
- );
1314
- timelineData.at = timelineData.history.length;
1315
- }
1316
- }
1317
- });
1318
- };
1319
- for (const tokenOrFamily of options.atoms) {
1320
- if (tokenOrFamily.type === `atom_family`) {
1321
- const family = tokenOrFamily;
1322
- family.subject.subscribe((token) => subscribeToAtom(token));
1323
- } else {
1324
- const token = tokenOrFamily;
1325
- subscribeToAtom(token);
1326
- }
1327
- }
1328
- store.timelineStore = import_hamt_plus7.default.set(options.key, timelineData, store.timelineStore);
1329
- return {
1330
- key: options.key,
1331
- type: `timeline`
1332
- };
1333
- }
1416
+ // src/internal/time-travel-internal.ts
1334
1417
  var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1335
- var _a, _b;
1418
+ var _a, _b, _c, _d;
1419
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u23E9 redo "${token.key}"`);
1336
1420
  const timelineData = store.timelineStore.get(token.key);
1337
1421
  if (!timelineData) {
1338
- (_a = store.config.logger) == null ? void 0 : _a.error(
1339
- `Tried to redo on timeline "${token.key}" has not been initialized.`
1422
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1423
+ `Failed to redo on timeline "${token.key}". This timeline has not been initialized.`
1340
1424
  );
1341
1425
  return;
1342
1426
  }
1343
1427
  if (timelineData.at === timelineData.history.length) {
1344
- (_b = store.config.logger) == null ? void 0 : _b.warn(
1345
- `Tried to redo on timeline "${token.key}" but there is nothing to redo.`
1428
+ (_c = store.config.logger) == null ? void 0 : _c.warn(
1429
+ `Failed to redo at the end of timeline "${token.key}". There is nothing to redo.`
1346
1430
  );
1347
1431
  return;
1348
1432
  }
1349
1433
  timelineData.timeTraveling = true;
1350
1434
  const update = timelineData.history[timelineData.at];
1351
1435
  switch (update.type) {
1352
- case `state_update`: {
1436
+ case `atom_update`: {
1353
1437
  const { key, newValue } = update;
1354
1438
  setState({ key, type: `atom` }, newValue);
1355
1439
  break;
1356
1440
  }
1441
+ case `selector_update`:
1357
1442
  case `transaction_update`: {
1358
1443
  for (const atomUpdate of update.atomUpdates) {
1359
1444
  const { key, newValue } = atomUpdate;
@@ -1364,19 +1449,23 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1364
1449
  }
1365
1450
  ++timelineData.at;
1366
1451
  timelineData.timeTraveling = false;
1452
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1453
+ `\u23F9\uFE0F "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`
1454
+ );
1367
1455
  };
1368
1456
  var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1369
- var _a, _b;
1457
+ var _a, _b, _c, _d;
1458
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u23EA undo "${token.key}"`);
1370
1459
  const timelineData = store.timelineStore.get(token.key);
1371
1460
  if (!timelineData) {
1372
- (_a = store.config.logger) == null ? void 0 : _a.error(
1373
- `Tried to undo on timeline "${token.key}" has not been initialized.`
1461
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1462
+ `Failed to undo on timeline "${token.key}". This timeline has not been initialized.`
1374
1463
  );
1375
1464
  return;
1376
1465
  }
1377
1466
  if (timelineData.at === 0) {
1378
- (_b = store.config.logger) == null ? void 0 : _b.warn(
1379
- `Tried to undo on timeline "${token.key}" but there is nothing to undo.`
1467
+ (_c = store.config.logger) == null ? void 0 : _c.warn(
1468
+ `Failed to undo at the beginning of timeline "${token.key}". There is nothing to undo.`
1380
1469
  );
1381
1470
  return;
1382
1471
  }
@@ -1384,11 +1473,12 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1384
1473
  --timelineData.at;
1385
1474
  const update = timelineData.history[timelineData.at];
1386
1475
  switch (update.type) {
1387
- case `state_update`: {
1476
+ case `atom_update`: {
1388
1477
  const { key, oldValue } = update;
1389
1478
  setState({ key, type: `atom` }, oldValue);
1390
1479
  break;
1391
1480
  }
1481
+ case `selector_update`:
1392
1482
  case `transaction_update`: {
1393
1483
  for (const atomUpdate of update.atomUpdates) {
1394
1484
  const { key, oldValue } = atomUpdate;
@@ -1398,8 +1488,167 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1398
1488
  }
1399
1489
  }
1400
1490
  timelineData.timeTraveling = false;
1491
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1492
+ `\u23F9\uFE0F "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`
1493
+ );
1401
1494
  };
1402
1495
 
1496
+ // src/internal/timeline-internal.ts
1497
+ var import_hamt_plus8 = __toESM(require("hamt_plus"));
1498
+ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1499
+ var _a, _b;
1500
+ const timelineData = {
1501
+ at: 0,
1502
+ timeTraveling: false,
1503
+ history: [],
1504
+ selectorTime: null,
1505
+ transactionKey: null
1506
+ };
1507
+ const subscribeToAtom = (token2) => {
1508
+ const state = withdraw(token2, store);
1509
+ state.subject.subscribe((update) => {
1510
+ var _a2, _b2, _c, _d, _e;
1511
+ const storeCurrentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1512
+ const storeCurrentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1513
+ const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1514
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1515
+ `\u23F3 timeline "${options.key}" saw atom "${token2.key}" go (`,
1516
+ update.oldValue,
1517
+ `->`,
1518
+ update.newValue,
1519
+ storeCurrentTransactionKey ? `) in transaction "${storeCurrentTransactionKey}"` : storeCurrentSelectorKey ? `) in selector "${storeCurrentSelectorKey}"` : `)`
1520
+ );
1521
+ if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1522
+ const currentTransaction = withdraw(
1523
+ { key: storeCurrentTransactionKey, type: `transaction` },
1524
+ store
1525
+ );
1526
+ if (timelineData.transactionKey !== storeCurrentTransactionKey) {
1527
+ if (timelineData.transactionKey) {
1528
+ (_b2 = store.config.logger) == null ? void 0 : _b2.error(
1529
+ `Timeline "${options.key}" was unable to resolve transaction "${timelineData.transactionKey}. This is probably a bug.`
1530
+ );
1531
+ }
1532
+ timelineData.transactionKey = storeCurrentTransactionKey;
1533
+ const subscription = currentTransaction.subject.subscribe((update2) => {
1534
+ var _a3;
1535
+ if (timelineData.timeTraveling === false) {
1536
+ if (timelineData.at !== timelineData.history.length) {
1537
+ timelineData.history.splice(timelineData.at);
1538
+ }
1539
+ timelineData.history.push(__spreadProps(__spreadValues({
1540
+ type: `transaction_update`
1541
+ }, update2), {
1542
+ atomUpdates: update2.atomUpdates.filter(
1543
+ (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1544
+ )
1545
+ }));
1546
+ }
1547
+ timelineData.at = timelineData.history.length;
1548
+ subscription.unsubscribe();
1549
+ timelineData.transactionKey = null;
1550
+ (_a3 = store.config.logger) == null ? void 0 : _a3.info(
1551
+ `\u231B timeline "${options.key}" got a transaction_update "${update2.key}"`
1552
+ );
1553
+ });
1554
+ }
1555
+ } else if (storeCurrentSelectorKey) {
1556
+ if (timelineData.timeTraveling === false) {
1557
+ if (storeCurrentSelectorTime !== timelineData.selectorTime) {
1558
+ const newSelectorUpdate = {
1559
+ type: `selector_update`,
1560
+ key: storeCurrentSelectorKey,
1561
+ atomUpdates: []
1562
+ };
1563
+ newSelectorUpdate.atomUpdates.push(__spreadValues({
1564
+ key: token2.key,
1565
+ type: `atom_update`
1566
+ }, update));
1567
+ if (timelineData.at !== timelineData.history.length) {
1568
+ timelineData.history.splice(timelineData.at);
1569
+ }
1570
+ timelineData.history.push(newSelectorUpdate);
1571
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1572
+ `\u231B timeline "${options.key}" got a selector_update "${storeCurrentSelectorKey}" with`,
1573
+ newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1574
+ );
1575
+ timelineData.at = timelineData.history.length;
1576
+ timelineData.selectorTime = storeCurrentSelectorTime;
1577
+ } else {
1578
+ const latestUpdate = timelineData.history.at(-1);
1579
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1580
+ latestUpdate.atomUpdates.push(__spreadValues({
1581
+ key: token2.key,
1582
+ type: `atom_update`
1583
+ }, update));
1584
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1585
+ ` \u231B timeline "${options.key}" set selector_update "${storeCurrentSelectorKey}" to`,
1586
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1587
+ );
1588
+ }
1589
+ }
1590
+ }
1591
+ } else {
1592
+ if (timelineData.timeTraveling === false) {
1593
+ timelineData.selectorTime = null;
1594
+ if (timelineData.at !== timelineData.history.length) {
1595
+ timelineData.history.splice(timelineData.at);
1596
+ }
1597
+ timelineData.history.push({
1598
+ type: `atom_update`,
1599
+ key: token2.key,
1600
+ oldValue: update.oldValue,
1601
+ newValue: update.newValue
1602
+ });
1603
+ (_e = store.config.logger) == null ? void 0 : _e.info(
1604
+ `\u231B timeline "${options.key}" got a state_update to "${token2.key}"`
1605
+ );
1606
+ timelineData.at = timelineData.history.length;
1607
+ }
1608
+ }
1609
+ });
1610
+ };
1611
+ const core = target(store);
1612
+ for (const tokenOrFamily of options.atoms) {
1613
+ const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key);
1614
+ if (timelineKey) {
1615
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1616
+ `\u274C Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
1617
+ );
1618
+ continue;
1619
+ }
1620
+ if (tokenOrFamily.type === `atom_family`) {
1621
+ const family = tokenOrFamily;
1622
+ family.subject.subscribe((token2) => subscribeToAtom(token2));
1623
+ } else {
1624
+ const token2 = tokenOrFamily;
1625
+ if (`family` in token2 && token2.family) {
1626
+ const familyTimelineKey = core.timelineAtoms.getRelatedId(
1627
+ token2.family.key
1628
+ );
1629
+ if (familyTimelineKey) {
1630
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1631
+ `\u274C Failed to add atom "${token2.key}" to timeline "${options.key}" because its family "${token2.family.key}" belongs to timeline "${familyTimelineKey}"`
1632
+ );
1633
+ continue;
1634
+ }
1635
+ }
1636
+ subscribeToAtom(token2);
1637
+ }
1638
+ core.timelineAtoms = core.timelineAtoms.set({
1639
+ atomKey: tokenOrFamily.key,
1640
+ timelineKey: options.key
1641
+ });
1642
+ }
1643
+ store.timelineStore = import_hamt_plus8.default.set(options.key, timelineData, store.timelineStore);
1644
+ const token = {
1645
+ key: options.key,
1646
+ type: `timeline`
1647
+ };
1648
+ store.subject.timelineCreation.next(token);
1649
+ return token;
1650
+ }
1651
+
1403
1652
  // src/atom.ts
1404
1653
  function atom(options) {
1405
1654
  return atom__INTERNAL(options);
@@ -1408,6 +1657,39 @@ function atomFamily(options) {
1408
1657
  return atomFamily__INTERNAL(options);
1409
1658
  }
1410
1659
 
1660
+ // src/logger.ts
1661
+ var LOG_LEVELS = [
1662
+ `info`,
1663
+ `warn`,
1664
+ `error`
1665
+ ];
1666
+ var setLogLevel = (preferredLevel, store = IMPLICIT.STORE) => {
1667
+ const { logger__INTERNAL } = store.config;
1668
+ if (preferredLevel === null) {
1669
+ store.config.logger = null;
1670
+ } else {
1671
+ store.config.logger = __spreadValues({}, console);
1672
+ LOG_LEVELS.forEach((logLevel) => {
1673
+ if (LOG_LEVELS.indexOf(logLevel) < LOG_LEVELS.indexOf(preferredLevel)) {
1674
+ store.config.logger[logLevel] = doNothing;
1675
+ } else {
1676
+ store.config.logger[logLevel] = logger__INTERNAL[logLevel];
1677
+ }
1678
+ });
1679
+ }
1680
+ };
1681
+ var useLogger = (logger, store = IMPLICIT.STORE) => {
1682
+ var _a;
1683
+ const currentLogLevel = store.config.logger === null ? null : (_a = LOG_LEVELS.find(
1684
+ (logLevel) => {
1685
+ var _a2;
1686
+ return ((_a2 = store.config.logger) == null ? void 0 : _a2[logLevel]) !== doNothing;
1687
+ }
1688
+ )) != null ? _a : null;
1689
+ store.config.logger__INTERNAL = __spreadValues({}, logger);
1690
+ setLogLevel(currentLogLevel, store);
1691
+ };
1692
+
1411
1693
  // src/selector.ts
1412
1694
  function selector(options) {
1413
1695
  return selector__INTERNAL(options);
@@ -1416,30 +1698,13 @@ function selectorFamily(options) {
1416
1698
  return selectorFamily__INTERNAL(options);
1417
1699
  }
1418
1700
 
1419
- // src/timeline.ts
1420
- var timeline = (options) => {
1421
- return timeline__INTERNAL(options);
1422
- };
1423
- var redo = (token) => {
1424
- return redo__INTERNAL(token, IMPLICIT.STORE);
1425
- };
1426
- var undo = (token) => {
1427
- return undo__INTERNAL(token, IMPLICIT.STORE);
1428
- };
1429
-
1430
- // src/transaction.ts
1431
- function transaction(options) {
1432
- return transaction__INTERNAL(options);
1433
- }
1434
- var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => withdraw(token, store).run(...parameters);
1435
-
1436
1701
  // src/subscribe.ts
1437
1702
  var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1438
1703
  var _a;
1439
1704
  const state = withdraw(token, store);
1440
1705
  const subscription = state.subject.subscribe(handleUpdate);
1441
1706
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to "${state.key}"`);
1442
- const dependencySubscriptions = `get` in state ? subscribeToRootAtoms(state, store) : null;
1707
+ const dependencySubscriptions = state.type !== `atom` ? subscribeToRootAtoms(state, store) : null;
1443
1708
  const unsubscribe = dependencySubscriptions === null ? () => {
1444
1709
  var _a2;
1445
1710
  (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from "${state.key}"`);
@@ -1469,13 +1734,37 @@ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1469
1734
  return unsubscribe;
1470
1735
  };
1471
1736
 
1737
+ // src/timeline.ts
1738
+ var timeline = (options) => {
1739
+ return timeline__INTERNAL(options);
1740
+ };
1741
+ var redo = (token) => {
1742
+ return redo__INTERNAL(token, IMPLICIT.STORE);
1743
+ };
1744
+ var undo = (token) => {
1745
+ return undo__INTERNAL(token, IMPLICIT.STORE);
1746
+ };
1747
+
1748
+ // src/transaction.ts
1749
+ function transaction(options) {
1750
+ return transaction__INTERNAL(options);
1751
+ }
1752
+ var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => withdraw(token, store).run(...parameters);
1753
+
1472
1754
  // src/index.ts
1473
1755
  var getState = (token, store = IMPLICIT.STORE) => {
1474
1756
  const state = withdraw(token, store);
1475
1757
  return getState__INTERNAL(state, store);
1476
1758
  };
1477
1759
  var setState = (token, value, store = IMPLICIT.STORE) => {
1478
- openOperation(store);
1760
+ try {
1761
+ openOperation(token, store);
1762
+ } catch (thrown) {
1763
+ if (!(typeof thrown === `symbol`)) {
1764
+ throw thrown;
1765
+ }
1766
+ return;
1767
+ }
1479
1768
  const state = withdraw(token, store);
1480
1769
  setState__INTERNAL(state, value, store);
1481
1770
  closeOperation(store);
@@ -1483,6 +1772,7 @@ var setState = (token, value, store = IMPLICIT.STORE) => {
1483
1772
  var isDefault = (token, store = IMPLICIT.STORE) => token.type === `atom` ? isAtomDefault(token.key, store) : isSelectorDefault(token.key, store);
1484
1773
  // Annotate the CommonJS export names for ESM import in node:
1485
1774
  0 && (module.exports = {
1775
+ LOG_LEVELS,
1486
1776
  __INTERNAL__,
1487
1777
  atom,
1488
1778
  atomFamily,