atom.io 0.6.5 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +32 -78
  2. package/dist/index.d.mts +11 -43
  3. package/dist/index.d.ts +11 -43
  4. package/dist/index.js +111 -291
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +108 -278
  7. package/dist/index.mjs.map +1 -1
  8. package/introspection/dist/index.d.mts +273 -0
  9. package/introspection/dist/index.d.ts +273 -0
  10. package/introspection/dist/index.js +350 -0
  11. package/introspection/dist/index.js.map +1 -0
  12. package/introspection/dist/index.mjs +327 -0
  13. package/introspection/dist/index.mjs.map +1 -0
  14. package/introspection/package.json +15 -0
  15. package/package.json +22 -12
  16. package/react-devtools/dist/index.css +22 -5
  17. package/react-devtools/dist/index.css.map +1 -1
  18. package/react-devtools/dist/index.d.mts +347 -10
  19. package/react-devtools/dist/index.d.ts +347 -10
  20. package/react-devtools/dist/index.js +2743 -696
  21. package/react-devtools/dist/index.js.map +1 -1
  22. package/react-devtools/dist/index.mjs +2739 -701
  23. package/react-devtools/dist/index.mjs.map +1 -1
  24. package/src/internal/atom-internal.ts +5 -6
  25. package/src/internal/get.ts +7 -9
  26. package/src/internal/index.ts +0 -1
  27. package/src/internal/operation.ts +15 -21
  28. package/src/internal/selector/create-read-write-selector.ts +8 -4
  29. package/src/internal/selector/create-readonly-selector.ts +1 -7
  30. package/src/internal/selector-internal.ts +1 -3
  31. package/src/internal/set.ts +1 -4
  32. package/src/internal/store.ts +22 -24
  33. package/src/internal/subscribe-internal.ts +7 -1
  34. package/src/internal/time-travel-internal.ts +2 -0
  35. package/src/internal/timeline/add-atom-to-timeline.ts +11 -12
  36. package/src/internal/timeline-internal.ts +6 -4
  37. package/src/internal/transaction/apply-transaction.ts +9 -6
  38. package/src/internal/transaction/build-transaction.ts +6 -6
  39. package/src/internal/transaction-internal.ts +1 -7
  40. package/src/introspection/attach-atom-index.ts +73 -0
  41. package/src/introspection/attach-introspection-states.ts +42 -0
  42. package/src/introspection/attach-selector-index.ts +77 -0
  43. package/src/introspection/attach-timeline-family.ts +59 -0
  44. package/src/introspection/attach-timeline-index.ts +36 -0
  45. package/src/introspection/attach-transaction-index.ts +38 -0
  46. package/src/introspection/attach-transaction-logs.ts +40 -0
  47. package/src/introspection/index.ts +20 -0
  48. package/src/react-devtools/AtomIODevtools.tsx +97 -97
  49. package/src/react-devtools/Button.tsx +24 -0
  50. package/src/react-devtools/StateEditor.tsx +14 -16
  51. package/src/react-devtools/StateIndex.tsx +153 -0
  52. package/src/react-devtools/TimelineIndex.tsx +92 -0
  53. package/src/react-devtools/TransactionIndex.tsx +70 -0
  54. package/src/react-devtools/Updates.tsx +145 -0
  55. package/src/react-devtools/devtools.scss +196 -15
  56. package/src/react-devtools/index.ts +71 -0
  57. package/src/react-explorer/AtomIOExplorer.tsx +3 -4
  58. package/src/react-explorer/explorer-states.ts +1 -1
  59. package/src/react-explorer/space-states.ts +3 -1
  60. package/src/react-explorer/view-states.ts +0 -2
  61. package/realtime-testing/dist/index.d.mts +0 -49
  62. package/realtime-testing/dist/index.d.ts +0 -49
  63. package/realtime-testing/dist/index.js +0 -165
  64. package/realtime-testing/dist/index.js.map +0 -1
  65. package/realtime-testing/dist/index.mjs +0 -129
  66. package/realtime-testing/dist/index.mjs.map +0 -1
  67. package/src/internal/meta/attach-meta.ts +0 -17
  68. package/src/internal/meta/index.ts +0 -4
  69. package/src/internal/meta/meta-state.ts +0 -135
  70. package/src/internal/meta/meta-timelines.ts +0 -1
  71. package/src/internal/meta/meta-transactions.ts +0 -1
  72. package/src/react-devtools/TokenList.tsx +0 -61
@@ -1,9 +1,7 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import { Subject } from "."
4
2
  import { deposit } from "./get"
5
3
  import { markAtomAsDefault } from "./is-default"
6
- import { cacheValue, hasKeyBeenUsed } from "./operation"
4
+ import { cacheValue } from "./operation"
7
5
  import type { Store } from "./store"
8
6
  import { IMPLICIT } from "./store"
9
7
  import { target } from "./transaction-internal"
@@ -25,11 +23,12 @@ export function atom__INTERNAL<T>(
25
23
  store: Store = IMPLICIT.STORE,
26
24
  ): AtomToken<T> {
27
25
  const core = target(store)
28
- if (hasKeyBeenUsed(options.key, store)) {
26
+ const existing = core.atoms.get(options.key)
27
+ if (existing) {
29
28
  store.config.logger?.error?.(
30
29
  `Key "${options.key}" already exists in the store.`,
31
30
  )
32
- return deposit(core.atoms.get(options.key))
31
+ return deposit(existing)
33
32
  }
34
33
  const subject = new Subject<{ newValue: T; oldValue: T }>()
35
34
  const newAtom = {
@@ -40,7 +39,7 @@ export function atom__INTERNAL<T>(
40
39
  } as const
41
40
  const initialValue =
42
41
  options.default instanceof Function ? options.default() : options.default
43
- core.atoms = HAMT.set(newAtom.key, newAtom, core.atoms)
42
+ core.atoms.set(newAtom.key, newAtom)
44
43
  markAtomAsDefault(options.key, store)
45
44
  cacheValue(options.key, initialValue, store)
46
45
  const token = deposit(newAtom)
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import type { ƒn } from "~/packages/anvl/src/function"
4
2
 
5
3
  import type {
@@ -29,9 +27,9 @@ export function lookup(
29
27
  store: Store,
30
28
  ): AtomToken<unknown> | ReadonlySelectorToken<unknown> | SelectorToken<unknown> {
31
29
  const core = target(store)
32
- const type = HAMT.has(key, core.atoms)
30
+ const type = core.atoms.has(key)
33
31
  ? `atom`
34
- : HAMT.has(key, core.selectors)
32
+ : core.selectors.has(key)
35
33
  ? `selector`
36
34
  : `readonly_selector`
37
35
  return { key, type } as any
@@ -75,11 +73,11 @@ export function withdraw<T>(
75
73
  | null {
76
74
  const core = target(store)
77
75
  return (
78
- HAMT.get(token.key, core.atoms) ??
79
- HAMT.get(token.key, core.selectors) ??
80
- HAMT.get(token.key, core.readonlySelectors) ??
81
- HAMT.get(token.key, core.transactions) ??
82
- HAMT.get(token.key, core.timelines) ??
76
+ core.atoms.get(token.key) ??
77
+ core.selectors.get(token.key) ??
78
+ core.readonlySelectors.get(token.key) ??
79
+ core.transactions.get(token.key) ??
80
+ core.timelines.get(token.key) ??
83
81
  null
84
82
  )
85
83
  }
@@ -2,7 +2,6 @@ export * from "./atom-internal"
2
2
  export * from "./families-internal"
3
3
  export * from "./get"
4
4
  export * from "./is-default"
5
- export * as META from "./meta"
6
5
  export * from "./operation"
7
6
  export * from "./selector-internal"
8
7
  export * from "./selector"
@@ -1,6 +1,3 @@
1
- import type { Hamt } from "hamt_plus"
2
- import HAMT from "hamt_plus"
3
-
4
1
  import type { Atom, ReadonlySelector, Selector } from "."
5
2
  import { target } from "."
6
3
  import type { Store } from "./store"
@@ -14,7 +11,7 @@ export type OperationProgress =
14
11
  | {
15
12
  open: true
16
13
  done: Set<string>
17
- prev: Hamt<any, string>
14
+ prev: Map<string, any>
18
15
  time: number
19
16
  token: StateToken<any>
20
17
  }
@@ -30,7 +27,7 @@ export const openOperation = (token: StateToken<any>, store: Store): void => {
30
27
  core.operation = {
31
28
  open: true,
32
29
  done: new Set(),
33
- prev: store.valueMap,
30
+ prev: new Map(store.valueMap),
34
31
  time: Date.now(),
35
32
  token,
36
33
  }
@@ -42,6 +39,7 @@ export const closeOperation = (store: Store): void => {
42
39
  const core = target(store)
43
40
  core.operation = { open: false }
44
41
  store.config.logger?.info(`🔴 operation done`)
42
+ store.subject.operationStatus.next(core.operation)
45
43
  }
46
44
 
47
45
  export const isDone = (key: string, store: Store = IMPLICIT.STORE): boolean => {
@@ -73,9 +71,9 @@ export const recallState = <T>(
73
71
  store.config.logger?.warn(
74
72
  `recall called outside of an operation. This is probably a bug.`,
75
73
  )
76
- return HAMT.get(state.key, core.valueMap)
74
+ return core.valueMap.get(state.key)
77
75
  }
78
- return HAMT.get(state.key, core.operation.prev)
76
+ return core.operation.prev.get(state.key)
79
77
  }
80
78
 
81
79
  export const cacheValue = (
@@ -84,7 +82,7 @@ export const cacheValue = (
84
82
  store: Store = IMPLICIT.STORE,
85
83
  ): void => {
86
84
  const core = target(store)
87
- core.valueMap = HAMT.set(key, value, core.valueMap)
85
+ core.valueMap.set(key, value)
88
86
  }
89
87
 
90
88
  export const evictCachedValue = (
@@ -92,24 +90,24 @@ export const evictCachedValue = (
92
90
  store: Store = IMPLICIT.STORE,
93
91
  ): void => {
94
92
  const core = target(store)
95
- core.valueMap = HAMT.remove(key, core.valueMap)
93
+ core.valueMap.delete(key)
96
94
  }
97
95
  export const readCachedValue = <T>(
98
96
  key: string,
99
97
  store: Store = IMPLICIT.STORE,
100
- ): T => HAMT.get(key, target(store).valueMap)
98
+ ): T => target(store).valueMap.get(key)
101
99
 
102
100
  export const isValueCached = (
103
101
  key: string,
104
102
  store: Store = IMPLICIT.STORE,
105
- ): boolean => HAMT.has(key, target(store).valueMap)
103
+ ): boolean => target(store).valueMap.has(key)
106
104
 
107
105
  export const storeAtom = (
108
106
  atom: Atom<any>,
109
107
  store: Store = IMPLICIT.STORE,
110
108
  ): void => {
111
109
  const core = target(store)
112
- core.atoms = HAMT.set(atom.key, atom, core.atoms)
110
+ core.atoms.set(atom.key, atom)
113
111
  }
114
112
 
115
113
  export const storeSelector = (
@@ -117,7 +115,7 @@ export const storeSelector = (
117
115
  store: Store = IMPLICIT.STORE,
118
116
  ): void => {
119
117
  const core = target(store)
120
- core.selectors = HAMT.set(selector.key, selector, core.selectors)
118
+ core.selectors.set(selector.key, selector)
121
119
  }
122
120
 
123
121
  export const storeReadonlySelector = (
@@ -125,11 +123,7 @@ export const storeReadonlySelector = (
125
123
  store: Store = IMPLICIT.STORE,
126
124
  ): void => {
127
125
  const core = target(store)
128
- core.readonlySelectors = HAMT.set(
129
- selector.key,
130
- selector,
131
- core.readonlySelectors,
132
- )
126
+ core.readonlySelectors.set(selector.key, selector)
133
127
  }
134
128
 
135
129
  export const hasKeyBeenUsed = (
@@ -138,8 +132,8 @@ export const hasKeyBeenUsed = (
138
132
  ): boolean => {
139
133
  const core = target(store)
140
134
  return (
141
- HAMT.has(key, core.atoms) ||
142
- HAMT.has(key, core.selectors) ||
143
- HAMT.has(key, core.readonlySelectors)
135
+ core.atoms.has(key) ||
136
+ core.selectors.has(key) ||
137
+ core.readonlySelectors.has(key)
144
138
  )
145
139
  }
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import { become } from "~/packages/anvl/src/function"
4
2
 
5
3
  import { Subject } from ".."
@@ -30,8 +28,14 @@ export const createReadWriteSelector = <T>(
30
28
  }
31
29
 
32
30
  const setSelf = (next: T | ((oldValue: T) => T)): void => {
33
- store.config.logger?.info(` <- "${options.key}" became`, next)
34
31
  const oldValue = getSelf()
32
+ store.config.logger?.info(
33
+ ` <- "${options.key}" went (`,
34
+ oldValue,
35
+ `->`,
36
+ next,
37
+ `)`,
38
+ )
35
39
  const newValue = become(next)(oldValue)
36
40
  cacheValue(options.key, newValue, store)
37
41
  markDone(options.key, store)
@@ -49,7 +53,7 @@ export const createReadWriteSelector = <T>(
49
53
  type: `selector`,
50
54
  ...(family && { family }),
51
55
  }
52
- core.selectors = HAMT.set(options.key, mySelector, core.selectors)
56
+ core.selectors.set(options.key, mySelector)
53
57
  const initialValue = getSelf()
54
58
  store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
55
59
  const token: SelectorToken<T> = {
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import { registerSelector } from "./register-selector"
4
2
  import { Subject } from ".."
5
3
  import type {
@@ -35,11 +33,7 @@ export const createReadonlySelector = <T>(
35
33
  type: `readonly_selector`,
36
34
  ...(family && { family }),
37
35
  }
38
- core.readonlySelectors = HAMT.set(
39
- options.key,
40
- readonlySelector,
41
- core.readonlySelectors,
42
- )
36
+ core.readonlySelectors.set(options.key, readonlySelector)
43
37
  const initialValue = getSelf()
44
38
  store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
45
39
  const token: ReadonlySelectorToken<T> = {
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import { target, IMPLICIT } from "."
4
2
  import type { Store, Subject } from "."
5
3
  import { createReadWriteSelector } from "./selector/create-read-write-selector"
@@ -47,7 +45,7 @@ export function selector__INTERNAL<T>(
47
45
  ): ReadonlySelectorToken<T> | SelectorToken<T> {
48
46
  const core = target(store)
49
47
 
50
- if (HAMT.has(options.key, core.selectors)) {
48
+ if (core.selectors.has(options.key)) {
51
49
  store.config.logger?.error(
52
50
  `Key "${options.key}" already exists in the store.`,
53
51
  )
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import { become } from "~/packages/anvl/src/function"
4
2
 
5
3
  import type { Atom, Selector, Store } from "."
@@ -37,8 +35,7 @@ export const evictDownStream = <T>(
37
35
  return
38
36
  }
39
37
  const state =
40
- HAMT.get(stateKey, core.selectors) ??
41
- HAMT.get(stateKey, core.readonlySelectors)
38
+ core.selectors.get(stateKey) ?? core.readonlySelectors.get(stateKey)
42
39
  if (!state) {
43
40
  store.config.logger?.info(
44
41
  ` || ${stateKey} is an atom, and can't be downstream`,
@@ -1,6 +1,3 @@
1
- import type { Hamt } from "hamt_plus"
2
- import HAMT from "hamt_plus"
3
-
4
1
  import type { ƒn } from "~/packages/anvl/src/function"
5
2
  import { doNothing } from "~/packages/anvl/src/function"
6
3
  import { Join } from "~/packages/anvl/src/join"
@@ -40,24 +37,25 @@ export type StoreCore = Pick<
40
37
  >
41
38
 
42
39
  export interface Store {
43
- atoms: Hamt<Atom<any>, string>
40
+ atoms: Map<string, Atom<any>>
44
41
  atomsThatAreDefault: Set<string>
45
- readonlySelectors: Hamt<ReadonlySelector<any>, string>
42
+ readonlySelectors: Map<string, ReadonlySelector<any>>
46
43
  selectorAtoms: Join<null, `selectorKey`, `atomKey`>
47
44
  selectorGraph: Join<{ source: string }>
48
- selectors: Hamt<Selector<any>, string>
45
+ selectors: Map<string, Selector<any>>
49
46
  timelineAtoms: Join<null, `timelineKey`, `atomKey`>
50
- timelines: Hamt<Timeline, string>
51
- transactions: Hamt<Transaction<any>, string>
52
- valueMap: Hamt<any, string>
47
+ timelines: Map<string, Timeline>
48
+ transactions: Map<string, Transaction<any>>
49
+ valueMap: Map<string, any>
53
50
 
54
51
  subject: {
55
52
  atomCreation: Subject<AtomToken<unknown>>
56
53
  selectorCreation: Subject<
57
54
  ReadonlySelectorToken<unknown> | SelectorToken<unknown>
58
55
  >
59
- transactionCreation: Subject<TransactionToken<unknown>>
56
+ transactionCreation: Subject<TransactionToken<ƒn>>
60
57
  timelineCreation: Subject<TimelineToken>
58
+ operationStatus: Subject<OperationProgress>
61
59
  }
62
60
 
63
61
  operation: OperationProgress
@@ -70,7 +68,7 @@ export interface Store {
70
68
  }
71
69
 
72
70
  export const createStore = (name: string, store: Store | null = null): Store => {
73
- const copiedStore = {
71
+ const created = {
74
72
  ...(store ??
75
73
  (() => ({
76
74
  atomsThatAreDefault: new Set(),
@@ -78,14 +76,14 @@ export const createStore = (name: string, store: Store | null = null): Store =>
78
76
  .from(`selectorKey`)
79
77
  .to(`atomKey`),
80
78
  selectorGraph: new Join({ relationType: `n:n` }),
81
- valueMap: HAMT.make<any, string>(),
82
79
  }))()),
83
80
 
84
- atoms: HAMT.make<Atom<any>, string>(),
85
- readonlySelectors: HAMT.make<ReadonlySelector<any>, string>(),
86
- selectors: HAMT.make<Selector<any>, string>(),
87
- transactions: HAMT.make<Transaction<any>, string>(),
88
- timelines: HAMT.make<Timeline, string>(),
81
+ valueMap: new Map(store?.valueMap),
82
+ atoms: new Map(),
83
+ readonlySelectors: new Map(),
84
+ selectors: new Map(),
85
+ transactions: new Map(),
86
+ timelines: new Map(),
89
87
 
90
88
  timelineAtoms: new Join({ relationType: `1:n` })
91
89
  .from(`timelineKey`)
@@ -96,7 +94,7 @@ export const createStore = (name: string, store: Store | null = null): Store =>
96
94
  selectorCreation: new Subject(),
97
95
  transactionCreation: new Subject(),
98
96
  timelineCreation: new Subject(),
99
- ...store?.subject,
97
+ operationStatus: new Subject(),
100
98
  },
101
99
 
102
100
  operation: {
@@ -121,22 +119,22 @@ export const createStore = (name: string, store: Store | null = null): Store =>
121
119
 
122
120
  store?.atoms.forEach((atom) => {
123
121
  const copiedAtom = { ...atom, subject: new Subject() } satisfies Atom<any>
124
- copiedStore.atoms = HAMT.set(atom.key, copiedAtom, copiedStore.atoms)
122
+ created.atoms.set(atom.key, copiedAtom)
125
123
  })
126
124
  store?.readonlySelectors.forEach((selector) => {
127
- selector.install(copiedStore)
125
+ selector.install(created)
128
126
  })
129
127
  store?.selectors.forEach((selector) => {
130
- selector.install(copiedStore)
128
+ selector.install(created)
131
129
  })
132
130
  store?.transactions.forEach((tx) => {
133
- tx.install(copiedStore)
131
+ tx.install(created)
134
132
  })
135
133
  store?.timelines.forEach((timeline) => {
136
- timeline.install(copiedStore)
134
+ timeline.install(created)
137
135
  })
138
136
 
139
- return copiedStore
137
+ return created
140
138
  }
141
139
 
142
140
  export const IMPLICIT = {
@@ -74,7 +74,13 @@ export const subscribeToRootAtoms = <T>(
74
74
  )
75
75
  const oldValue = recallState(state, store)
76
76
  const newValue = getState__INTERNAL(state, store)
77
- store.config.logger?.info(` <- ${state.key} became`, newValue)
77
+ store.config.logger?.info(
78
+ ` <- "${state.key}" went (`,
79
+ oldValue,
80
+ `->`,
81
+ newValue,
82
+ `)`,
83
+ )
78
84
  state.subject.next({ newValue, oldValue })
79
85
  })
80
86
  })
@@ -39,6 +39,7 @@ export const redo__INTERNAL = (
39
39
  }
40
40
  }
41
41
  ++timelineData.at
42
+ timelineData.subject.next(`redo`)
42
43
  timelineData.timeTraveling = false
43
44
  store.config.logger?.info(
44
45
  `⏹️ "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
@@ -82,6 +83,7 @@ export const undo__INTERNAL = (
82
83
  break
83
84
  }
84
85
  }
86
+ timelineData.subject.next(`undo`)
85
87
  timelineData.timeTraveling = false
86
88
  store.config.logger?.info(
87
89
  `⏹️ "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
@@ -1,6 +1,5 @@
1
1
  import { IMPLICIT, withdraw } from ".."
2
2
  import type {
3
- TimelineSelectorUpdate,
4
3
  Timeline,
5
4
  Store,
6
5
  TimelineTransactionUpdate,
@@ -58,9 +57,6 @@ export const addAtomToTimeline = (
58
57
  `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`,
59
58
  )
60
59
  }
61
- if (mostRecentUpdate.type === `selector_update`) {
62
- tl.subject.next(mostRecentUpdate)
63
- }
64
60
  }
65
61
  if (
66
62
  currentTransactionKey &&
@@ -83,6 +79,7 @@ export const addAtomToTimeline = (
83
79
  }
84
80
  tl.transactionKey = currentTransactionKey
85
81
  const subscription = currentTransaction.subject.subscribe((update) => {
82
+ subscription.unsubscribe()
86
83
  if (tl.timeTraveling === false && currentTransactionTime) {
87
84
  if (tl.at !== tl.history.length) {
88
85
  tl.history.splice(tl.at)
@@ -96,10 +93,9 @@ export const addAtomToTimeline = (
96
93
  ),
97
94
  }
98
95
  tl.history.push(timelineTransactionUpdate)
96
+ tl.at = tl.history.length
99
97
  tl.subject.next(timelineTransactionUpdate)
100
98
  }
101
- tl.at = tl.history.length
102
- subscription.unsubscribe()
103
99
  tl.transactionKey = null
104
100
  store.config.logger?.info(
105
101
  `⌛ timeline "${tl.key}" got a transaction_update "${update.key}"`,
@@ -107,14 +103,16 @@ export const addAtomToTimeline = (
107
103
  })
108
104
  }
109
105
  } else if (currentSelectorKey && currentSelectorTime) {
106
+ let latestUpdate: TimelineUpdate | undefined = tl.history.at(-1)
107
+
110
108
  if (currentSelectorTime !== tl.selectorTime) {
111
- const newSelectorUpdate: TimelineSelectorUpdate = {
109
+ latestUpdate = {
112
110
  type: `selector_update`,
113
111
  timestamp: currentSelectorTime,
114
112
  key: currentSelectorKey,
115
113
  atomUpdates: [],
116
114
  }
117
- newSelectorUpdate.atomUpdates.push({
115
+ latestUpdate.atomUpdates.push({
118
116
  key: atom.key,
119
117
  type: `atom_update`,
120
118
  ...update,
@@ -122,16 +120,16 @@ export const addAtomToTimeline = (
122
120
  if (tl.at !== tl.history.length) {
123
121
  tl.history.splice(tl.at)
124
122
  }
125
- tl.history.push(newSelectorUpdate)
123
+ tl.history.push(latestUpdate)
126
124
 
127
125
  store.config.logger?.info(
128
126
  `⌛ timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
129
- newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key),
127
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key),
130
128
  )
129
+
131
130
  tl.at = tl.history.length
132
131
  tl.selectorTime = currentSelectorTime
133
132
  } else {
134
- const latestUpdate = tl.history.at(-1)
135
133
  if (latestUpdate?.type === `selector_update`) {
136
134
  latestUpdate.atomUpdates.push({
137
135
  key: atom.key,
@@ -144,6 +142,7 @@ export const addAtomToTimeline = (
144
142
  )
145
143
  }
146
144
  }
145
+ if (latestUpdate) tl.subject.next(latestUpdate)
147
146
  } else {
148
147
  const timestamp = Date.now()
149
148
  tl.selectorTime = null
@@ -160,7 +159,7 @@ export const addAtomToTimeline = (
160
159
  tl.history.push(atomUpdate)
161
160
  tl.subject.next(atomUpdate)
162
161
  store.config.logger?.info(
163
- `⌛ timeline "${tl.key}" got a state_update to "${atom.key}"`,
162
+ `⌛ timeline "${tl.key}" got an atom_update to "${atom.key}"`,
164
163
  )
165
164
  tl.at = tl.history.length
166
165
  }
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import type { ƒn } from "~/packages/anvl/src/function"
4
2
 
5
3
  import type { Store } from "."
@@ -39,7 +37,11 @@ export type Timeline = {
39
37
  transactionKey: string | null
40
38
  install: (store: Store) => void
41
39
  subject: Subject<
42
- TimelineAtomUpdate | TimelineSelectorUpdate | TimelineTransactionUpdate
40
+ | TimelineAtomUpdate
41
+ | TimelineSelectorUpdate
42
+ | TimelineTransactionUpdate
43
+ | `redo`
44
+ | `undo`
43
45
  >
44
46
  }
45
47
 
@@ -95,7 +97,7 @@ export function timeline__INTERNAL(
95
97
  })
96
98
  }
97
99
 
98
- store.timelines = HAMT.set(options.key, tl, store.timelines)
100
+ store.timelines.set(options.key, tl)
99
101
  const token: TimelineToken = {
100
102
  key: options.key,
101
103
  type: `timeline`,
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import type { ƒn } from "~/packages/anvl/src/function"
4
2
 
5
3
  import type { Store } from ".."
@@ -26,10 +24,15 @@ export const applyTransaction = <ƒ extends ƒn>(
26
24
 
27
25
  for (const { key, newValue } of atomUpdates) {
28
26
  const token: AtomToken<unknown> = { key, type: `atom` }
29
- if (!HAMT.has(token.key, store.valueMap)) {
30
- const newAtom = HAMT.get(token.key, store.transactionStatus.core.atoms)
31
- store.atoms = HAMT.set(newAtom.key, newAtom, store.atoms)
32
- store.valueMap = HAMT.set(newAtom.key, newAtom.default, store.valueMap)
27
+ if (!store.valueMap.has(token.key)) {
28
+ const newAtom = store.transactionStatus.core.atoms.get(token.key)
29
+ if (!newAtom) {
30
+ throw new Error(
31
+ `Absurd Error: Atom "${token.key}" not found while copying updates from transaction "${store.transactionStatus.key}" to store "${store.config.name}"`,
32
+ )
33
+ }
34
+ store.atoms.set(newAtom.key, newAtom)
35
+ store.valueMap.set(newAtom.key, newAtom.default)
33
36
  store.config.logger?.info(`🔧`, `add atom "${newAtom.key}"`)
34
37
  }
35
38
  setState(token, newValue, store)
@@ -10,17 +10,17 @@ export const buildTransaction = (
10
10
  phase: `building`,
11
11
  time: Date.now(),
12
12
  core: {
13
- atoms: store.atoms,
13
+ atoms: new Map(store.atoms),
14
14
  atomsThatAreDefault: store.atomsThatAreDefault,
15
15
  operation: { open: false },
16
- readonlySelectors: store.readonlySelectors,
17
- timelines: store.timelines,
16
+ readonlySelectors: new Map(store.readonlySelectors),
17
+ timelines: new Map(store.timelines),
18
18
  timelineAtoms: store.timelineAtoms,
19
- transactions: store.transactions,
19
+ transactions: new Map(store.transactions),
20
20
  selectorAtoms: store.selectorAtoms,
21
21
  selectorGraph: store.selectorGraph,
22
- selectors: store.selectors,
23
- valueMap: store.valueMap,
22
+ selectors: new Map(store.selectors),
23
+ valueMap: new Map(store.valueMap),
24
24
  },
25
25
  atomUpdates: [],
26
26
  params,
@@ -1,5 +1,3 @@
1
- import HAMT from "hamt_plus"
2
-
3
1
  import type { ƒn } from "~/packages/anvl/src/function"
4
2
 
5
3
  import type { Store, StoreCore } from "."
@@ -51,11 +49,7 @@ export function transaction__INTERNAL<ƒ extends ƒn>(
51
49
  subject: new Subject(),
52
50
  }
53
51
  const core = target(store)
54
- core.transactions = HAMT.set(
55
- newTransaction.key,
56
- newTransaction,
57
- core.transactions,
58
- )
52
+ core.transactions.set(newTransaction.key, newTransaction)
59
53
  const token = deposit(newTransaction)
60
54
  store.subject.transactionCreation.next(token)
61
55
  return token
@@ -0,0 +1,73 @@
1
+ import type { AtomToken, ReadonlySelectorToken } from "atom.io"
2
+ import { __INTERNAL__ } from "atom.io"
3
+
4
+ import type { StateTokenIndex } from "."
5
+
6
+ export type AtomTokenIndex = StateTokenIndex<AtomToken<unknown>>
7
+
8
+ export const attachAtomIndex = (
9
+ store: __INTERNAL__.Store = __INTERNAL__.IMPLICIT.STORE,
10
+ ): ReadonlySelectorToken<AtomTokenIndex> => {
11
+ const atomTokenIndexState__INTERNAL =
12
+ __INTERNAL__.atom__INTERNAL<AtomTokenIndex>(
13
+ {
14
+ key: `👁‍🗨 Atom Token Index (Internal)`,
15
+ default: () =>
16
+ [...store.atoms]
17
+ .filter(([key]) => !key.includes(`👁‍🗨`))
18
+ .reduce<AtomTokenIndex>((acc, [key]) => {
19
+ acc[key] = { key, type: `atom` }
20
+ return acc
21
+ }, {}),
22
+ effects: [
23
+ ({ setSelf }) => {
24
+ store.subject.atomCreation.subscribe((atomToken) => {
25
+ if (store.operation.open) {
26
+ return
27
+ }
28
+ if (atomToken.key.includes(`👁‍🗨`)) {
29
+ return
30
+ }
31
+ setSelf((state) => {
32
+ const { key, family } = atomToken
33
+ if (family) {
34
+ const { key: familyKey, subKey } = family
35
+ const current = state[familyKey]
36
+ if (current === undefined || `familyMembers` in current) {
37
+ const familyKeyState = current || {
38
+ key: familyKey,
39
+ familyMembers: {},
40
+ }
41
+ return {
42
+ ...state,
43
+ [familyKey]: {
44
+ ...familyKeyState,
45
+ familyMembers: {
46
+ ...familyKeyState.familyMembers,
47
+ [subKey]: atomToken,
48
+ },
49
+ },
50
+ }
51
+ }
52
+ }
53
+ return {
54
+ ...state,
55
+ [key]: atomToken,
56
+ }
57
+ })
58
+ })
59
+ },
60
+ ],
61
+ },
62
+ undefined,
63
+ store,
64
+ )
65
+ return __INTERNAL__.selector__INTERNAL(
66
+ {
67
+ key: `👁‍🗨 Atom Token Index`,
68
+ get: ({ get }) => get(atomTokenIndexState__INTERNAL),
69
+ },
70
+ undefined,
71
+ store,
72
+ )
73
+ }