atom.io 0.6.6 → 0.6.8

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 (76) hide show
  1. package/dist/index.d.mts +34 -25
  2. package/dist/index.d.ts +34 -25
  3. package/dist/index.js +94 -115
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +94 -105
  6. package/dist/index.mjs.map +1 -1
  7. package/introspection/dist/index.d.mts +272 -0
  8. package/introspection/dist/index.d.ts +272 -0
  9. package/introspection/dist/index.js +41 -3
  10. package/introspection/dist/index.js.map +1 -1
  11. package/introspection/dist/index.mjs +41 -3
  12. package/introspection/dist/index.mjs.map +1 -1
  13. package/json/dist/index.d.mts +5 -7
  14. package/json/dist/index.d.ts +5 -7
  15. package/json/dist/index.js.map +1 -1
  16. package/json/dist/index.mjs.map +1 -1
  17. package/package.json +22 -14
  18. package/react-devtools/dist/index.css +9 -1
  19. package/react-devtools/dist/index.css.map +1 -1
  20. package/react-devtools/dist/index.d.mts +22 -25
  21. package/react-devtools/dist/index.d.ts +22 -25
  22. package/react-devtools/dist/index.js +845 -326
  23. package/react-devtools/dist/index.js.map +1 -1
  24. package/react-devtools/dist/index.mjs +830 -306
  25. package/react-devtools/dist/index.mjs.map +1 -1
  26. package/realtime/dist/index.d.mts +6 -8
  27. package/realtime/dist/index.d.ts +6 -8
  28. package/realtime/dist/index.js +0 -1
  29. package/realtime/dist/index.js.map +1 -1
  30. package/realtime/dist/index.mjs +0 -1
  31. package/realtime/dist/index.mjs.map +1 -1
  32. package/realtime-react/dist/index.d.mts +11 -13
  33. package/realtime-react/dist/index.d.ts +11 -13
  34. package/realtime-react/dist/index.js.map +1 -1
  35. package/realtime-react/dist/index.mjs.map +1 -1
  36. package/src/atom.ts +4 -4
  37. package/src/index.ts +1 -1
  38. package/src/internal/atom-internal.ts +5 -6
  39. package/src/internal/families-internal.ts +23 -20
  40. package/src/internal/get.ts +7 -9
  41. package/src/internal/index.ts +1 -1
  42. package/src/internal/operation.ts +14 -21
  43. package/src/internal/selector/create-read-write-selector.ts +11 -5
  44. package/src/internal/selector/create-readonly-selector.ts +4 -8
  45. package/src/internal/selector-internal.ts +1 -3
  46. package/src/internal/set.ts +1 -4
  47. package/src/internal/store.ts +19 -22
  48. package/src/internal/subscribe-internal.ts +7 -1
  49. package/src/internal/time-travel-internal.ts +4 -4
  50. package/src/internal/timeline/add-atom-to-timeline.ts +2 -2
  51. package/src/internal/timeline-internal.ts +3 -5
  52. package/src/internal/transaction/apply-transaction.ts +9 -6
  53. package/src/internal/transaction/build-transaction.ts +6 -6
  54. package/src/internal/transaction-internal.ts +1 -7
  55. package/src/introspection/attach-timeline-family.ts +14 -4
  56. package/src/introspection/attach-transaction-logs.ts +1 -1
  57. package/src/json/select-json.ts +1 -1
  58. package/src/react-devtools/AtomIODevtools.tsx +1 -2
  59. package/src/react-devtools/StateEditor.tsx +5 -1
  60. package/src/react-devtools/StateIndex.tsx +4 -1
  61. package/src/react-devtools/devtools.scss +0 -1
  62. package/src/react-explorer/AtomIOExplorer.tsx +3 -3
  63. package/src/realtime/hook-composition/expose-family.ts +2 -2
  64. package/src/realtime/hook-composition/expose-single.ts +1 -1
  65. package/src/realtime/hook-composition/receive-state.ts +1 -1
  66. package/src/realtime-react/realtime-hooks.ts +4 -4
  67. package/src/realtime-react/use-pull-family-member.ts +2 -2
  68. package/src/realtime-react/use-pull-family.ts +2 -2
  69. package/src/realtime-react/use-pull.ts +3 -1
  70. package/src/realtime-react/use-push.ts +3 -1
  71. package/src/selector.ts +14 -12
  72. package/src/subscribe.ts +1 -1
  73. package/src/tracker/index.ts +3 -0
  74. package/src/tracker/tracker.ts +61 -0
  75. package/src/web-effects/storage.ts +1 -1
  76. package/src/internal/subject.ts +0 -24
@@ -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
  }
@@ -74,9 +71,9 @@ export const recallState = <T>(
74
71
  store.config.logger?.warn(
75
72
  `recall called outside of an operation. This is probably a bug.`,
76
73
  )
77
- return HAMT.get(state.key, core.valueMap)
74
+ return core.valueMap.get(state.key)
78
75
  }
79
- return HAMT.get(state.key, core.operation.prev)
76
+ return core.operation.prev.get(state.key)
80
77
  }
81
78
 
82
79
  export const cacheValue = (
@@ -85,7 +82,7 @@ export const cacheValue = (
85
82
  store: Store = IMPLICIT.STORE,
86
83
  ): void => {
87
84
  const core = target(store)
88
- core.valueMap = HAMT.set(key, value, core.valueMap)
85
+ core.valueMap.set(key, value)
89
86
  }
90
87
 
91
88
  export const evictCachedValue = (
@@ -93,24 +90,24 @@ export const evictCachedValue = (
93
90
  store: Store = IMPLICIT.STORE,
94
91
  ): void => {
95
92
  const core = target(store)
96
- core.valueMap = HAMT.remove(key, core.valueMap)
93
+ core.valueMap.delete(key)
97
94
  }
98
95
  export const readCachedValue = <T>(
99
96
  key: string,
100
97
  store: Store = IMPLICIT.STORE,
101
- ): T => HAMT.get(key, target(store).valueMap)
98
+ ): T => target(store).valueMap.get(key)
102
99
 
103
100
  export const isValueCached = (
104
101
  key: string,
105
102
  store: Store = IMPLICIT.STORE,
106
- ): boolean => HAMT.has(key, target(store).valueMap)
103
+ ): boolean => target(store).valueMap.has(key)
107
104
 
108
105
  export const storeAtom = (
109
106
  atom: Atom<any>,
110
107
  store: Store = IMPLICIT.STORE,
111
108
  ): void => {
112
109
  const core = target(store)
113
- core.atoms = HAMT.set(atom.key, atom, core.atoms)
110
+ core.atoms.set(atom.key, atom)
114
111
  }
115
112
 
116
113
  export const storeSelector = (
@@ -118,7 +115,7 @@ export const storeSelector = (
118
115
  store: Store = IMPLICIT.STORE,
119
116
  ): void => {
120
117
  const core = target(store)
121
- core.selectors = HAMT.set(selector.key, selector, core.selectors)
118
+ core.selectors.set(selector.key, selector)
122
119
  }
123
120
 
124
121
  export const storeReadonlySelector = (
@@ -126,11 +123,7 @@ export const storeReadonlySelector = (
126
123
  store: Store = IMPLICIT.STORE,
127
124
  ): void => {
128
125
  const core = target(store)
129
- core.readonlySelectors = HAMT.set(
130
- selector.key,
131
- selector,
132
- core.readonlySelectors,
133
- )
126
+ core.readonlySelectors.set(selector.key, selector)
134
127
  }
135
128
 
136
129
  export const hasKeyBeenUsed = (
@@ -139,8 +132,8 @@ export const hasKeyBeenUsed = (
139
132
  ): boolean => {
140
133
  const core = target(store)
141
134
  return (
142
- HAMT.has(key, core.atoms) ||
143
- HAMT.has(key, core.selectors) ||
144
- HAMT.has(key, core.readonlySelectors)
135
+ core.atoms.has(key) ||
136
+ core.selectors.has(key) ||
137
+ core.readonlySelectors.has(key)
145
138
  )
146
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,13 +53,15 @@ 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> = {
56
60
  key: options.key,
57
61
  type: `selector`,
58
- family,
62
+ }
63
+ if (family) {
64
+ token.family = family
59
65
  }
60
66
  store.subject.selectorCreation.next(token)
61
67
  return token
@@ -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,17 +33,15 @@ 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> = {
46
40
  key: options.key,
47
41
  type: `readonly_selector`,
48
- family,
42
+ }
43
+ if (family) {
44
+ token.family = family
49
45
  }
50
46
  store.subject.selectorCreation.next(token)
51
47
  return token
@@ -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,16 +37,16 @@ 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>>
@@ -71,7 +68,7 @@ export interface Store {
71
68
  }
72
69
 
73
70
  export const createStore = (name: string, store: Store | null = null): Store => {
74
- const copiedStore = {
71
+ const created = {
75
72
  ...(store ??
76
73
  (() => ({
77
74
  atomsThatAreDefault: new Set(),
@@ -79,14 +76,14 @@ export const createStore = (name: string, store: Store | null = null): Store =>
79
76
  .from(`selectorKey`)
80
77
  .to(`atomKey`),
81
78
  selectorGraph: new Join({ relationType: `n:n` }),
82
- valueMap: HAMT.make<any, string>(),
83
79
  }))()),
84
80
 
85
- atoms: HAMT.make<Atom<any>, string>(),
86
- readonlySelectors: HAMT.make<ReadonlySelector<any>, string>(),
87
- selectors: HAMT.make<Selector<any>, string>(),
88
- transactions: HAMT.make<Transaction<any>, string>(),
89
- 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(),
90
87
 
91
88
  timelineAtoms: new Join({ relationType: `1:n` })
92
89
  .from(`timelineKey`)
@@ -122,22 +119,22 @@ export const createStore = (name: string, store: Store | null = null): Store =>
122
119
 
123
120
  store?.atoms.forEach((atom) => {
124
121
  const copiedAtom = { ...atom, subject: new Subject() } satisfies Atom<any>
125
- copiedStore.atoms = HAMT.set(atom.key, copiedAtom, copiedStore.atoms)
122
+ created.atoms.set(atom.key, copiedAtom)
126
123
  })
127
124
  store?.readonlySelectors.forEach((selector) => {
128
- selector.install(copiedStore)
125
+ selector.install(created)
129
126
  })
130
127
  store?.selectors.forEach((selector) => {
131
- selector.install(copiedStore)
128
+ selector.install(created)
132
129
  })
133
130
  store?.transactions.forEach((tx) => {
134
- tx.install(copiedStore)
131
+ tx.install(created)
135
132
  })
136
133
  store?.timelines.forEach((timeline) => {
137
- timeline.install(copiedStore)
134
+ timeline.install(created)
138
135
  })
139
136
 
140
- return copiedStore
137
+ return created
141
138
  }
142
139
 
143
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
  })
@@ -21,7 +21,7 @@ export const redo__INTERNAL = (
21
21
  )
22
22
  return
23
23
  }
24
- timelineData.timeTraveling = true
24
+ timelineData.timeTraveling = `into_future`
25
25
  const update = timelineData.history[timelineData.at]
26
26
  switch (update.type) {
27
27
  case `atom_update`: {
@@ -40,7 +40,7 @@ export const redo__INTERNAL = (
40
40
  }
41
41
  ++timelineData.at
42
42
  timelineData.subject.next(`redo`)
43
- timelineData.timeTraveling = false
43
+ timelineData.timeTraveling = null
44
44
  store.config.logger?.info(
45
45
  `⏹️ "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
46
46
  )
@@ -64,7 +64,7 @@ export const undo__INTERNAL = (
64
64
  )
65
65
  return
66
66
  }
67
- timelineData.timeTraveling = true
67
+ timelineData.timeTraveling = `into_past`
68
68
 
69
69
  --timelineData.at
70
70
  const update = timelineData.history[timelineData.at]
@@ -84,7 +84,7 @@ export const undo__INTERNAL = (
84
84
  }
85
85
  }
86
86
  timelineData.subject.next(`undo`)
87
- timelineData.timeTraveling = false
87
+ timelineData.timeTraveling = null
88
88
  store.config.logger?.info(
89
89
  `⏹️ "${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
90
90
  )
@@ -49,7 +49,7 @@ export const addAtomToTimeline = (
49
49
  : `)`,
50
50
  )
51
51
 
52
- if (tl.timeTraveling === false) {
52
+ if (tl.timeTraveling === null) {
53
53
  if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
54
54
  const mostRecentUpdate: TimelineUpdate | undefined = tl.history.at(-1)
55
55
  if (mostRecentUpdate === undefined) {
@@ -80,7 +80,7 @@ export const addAtomToTimeline = (
80
80
  tl.transactionKey = currentTransactionKey
81
81
  const subscription = currentTransaction.subject.subscribe((update) => {
82
82
  subscription.unsubscribe()
83
- if (tl.timeTraveling === false && currentTransactionTime) {
83
+ if (tl.timeTraveling === null && currentTransactionTime) {
84
84
  if (tl.at !== tl.history.length) {
85
85
  tl.history.splice(tl.at)
86
86
  }
@@ -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 "."
@@ -33,7 +31,7 @@ export type TimelineTransactionUpdate = TransactionUpdate<ƒn> & {
33
31
  export type Timeline = {
34
32
  key: string
35
33
  at: number
36
- timeTraveling: boolean
34
+ timeTraveling: `into_future` | `into_past` | null
37
35
  history: TimelineUpdate[]
38
36
  selectorTime: number | null
39
37
  transactionKey: string | null
@@ -55,7 +53,7 @@ export function timeline__INTERNAL(
55
53
  const tl: Timeline = {
56
54
  key: options.key,
57
55
  at: 0,
58
- timeTraveling: false,
56
+ timeTraveling: null,
59
57
  selectorTime: null,
60
58
  transactionKey: null,
61
59
  ...data,
@@ -99,7 +97,7 @@ export function timeline__INTERNAL(
99
97
  })
100
98
  }
101
99
 
102
- store.timelines = HAMT.set(options.key, tl, store.timelines)
100
+ store.timelines.set(options.key, tl)
103
101
  const token: TimelineToken = {
104
102
  key: options.key,
105
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
@@ -1,7 +1,7 @@
1
1
  import type { ReadonlySelectorFamily, Store } from "atom.io"
2
- import { __INTERNAL__ } from "atom.io"
2
+ import { __INTERNAL__, timeline } from "atom.io"
3
3
 
4
- import type { Timeline } from "../internal"
4
+ import { withdraw, type Timeline, Subject } from "../internal"
5
5
 
6
6
  export const attachTimelineFamily = (
7
7
  store: Store = __INTERNAL__.IMPLICIT.STORE,
@@ -12,11 +12,21 @@ export const attachTimelineFamily = (
12
12
  >(
13
13
  {
14
14
  key: `👁‍🗨 Timeline Update Log (Internal)`,
15
- default: (key) => store.timelines.get(key),
15
+ default: (key) =>
16
+ store.timelines.get(key) ?? {
17
+ key: ``,
18
+ at: 0,
19
+ timeTraveling: null,
20
+ history: [],
21
+ selectorTime: null,
22
+ transactionKey: null,
23
+ install: () => {},
24
+ subject: new Subject(),
25
+ },
16
26
  effects: (key) => [
17
27
  ({ setSelf }) => {
18
28
  const tl = store.timelines.get(key)
19
- tl.subject.subscribe((_) => {
29
+ tl?.subject.subscribe((_) => {
20
30
  if (store.operation.open === true) {
21
31
  const subscription = store.subject.operationStatus.subscribe(
22
32
  (operationStatus) => {
@@ -16,7 +16,7 @@ export const attachTransactionLogs = (
16
16
  effects: (key) => [
17
17
  ({ setSelf }) => {
18
18
  const tx = store.transactions.get(key)
19
- tx.subject.subscribe((transactionUpdate) => {
19
+ tx?.subject.subscribe((transactionUpdate) => {
20
20
  if (transactionUpdate.key === key) {
21
21
  setSelf((state) => [...state, transactionUpdate])
22
22
  }
@@ -2,7 +2,7 @@ import * as AtomIO from "atom.io"
2
2
 
3
3
  import type { Json, JsonInterface } from "~/packages/anvl/src/json"
4
4
 
5
- export const selectJson = <T, J extends Json>(
5
+ export const selectJson = <T, J extends Json.Serializable>(
6
6
  atom: AtomIO.AtomToken<T>,
7
7
  transform: JsonInterface<T, J>,
8
8
  store: AtomIO.Store = AtomIO.__INTERNAL__.IMPLICIT.STORE,
@@ -1,7 +1,6 @@
1
1
  import { useO, useIO } from "atom.io/react"
2
2
  import { LayoutGroup, motion, spring } from "framer-motion"
3
3
  import { useRef } from "react"
4
- import type { FC } from "react"
5
4
 
6
5
  import {
7
6
  atomIndex,
@@ -16,7 +15,7 @@ import { TransactionIndex } from "./TransactionIndex"
16
15
 
17
16
  import "./devtools.scss"
18
17
 
19
- export const AtomIODevtools: FC = () => {
18
+ export const AtomIODevtools = (): JSX.Element => {
20
19
  const constraintsRef = useRef(null)
21
20
 
22
21
  const [devtoolsAreOpen, setDevtoolsAreOpen] = useIO(devtoolsAreOpenState)
@@ -3,7 +3,9 @@ import { useO, useIO } from "atom.io/react"
3
3
  import type { FC } from "react"
4
4
 
5
5
  import { fallback } from "~/packages/anvl/src/function"
6
- import { isJson } from "~/packages/anvl/src/json"
6
+ import { Join } from "~/packages/anvl/src/join"
7
+ import { isJson } from "~/packages/anvl/src/refinement/refine-json"
8
+ import { RelationEditor } from "~/packages/hamr/src/react-data-designer"
7
9
  import { ElasticInput } from "~/packages/hamr/src/react-elastic-input"
8
10
  import { JsonEditor } from "~/packages/hamr/src/react-json-editor"
9
11
 
@@ -13,6 +15,8 @@ export const StateEditor: FC<{
13
15
  const [data, set] = useIO(token)
14
16
  return isJson(data) ? (
15
17
  <JsonEditor data={data} set={set} schema={true} />
18
+ ) : data instanceof Join ? (
19
+ <RelationEditor data={data} set={set} />
16
20
  ) : (
17
21
  <div className="json_editor">
18
22
  <ElasticInput
@@ -3,7 +3,10 @@ import { getState, selectorFamily } from "atom.io"
3
3
  import { useO, useIO } from "atom.io/react"
4
4
  import type { FC } from "react"
5
5
 
6
- import { isJson, refineJsonType } from "~/packages/anvl/src/json"
6
+ import {
7
+ isJson,
8
+ refineJsonType,
9
+ } from "~/packages/anvl/src/refinement/refine-json"
7
10
 
8
11
  import { findViewIsOpenState, primitiveRefinery } from "."
9
12
  import { button } from "./Button"
@@ -241,7 +241,6 @@ main.atom_io_devtools {
241
241
 
242
242
  .json_editor {
243
243
  input {
244
- // font-size: 20px;
245
244
  font-family: theia;
246
245
  border: none;
247
246
  border-bottom: 1px solid;
@@ -3,7 +3,7 @@ import type { FC, ReactNode } from "react"
3
3
  import { useEffect } from "react"
4
4
  import { Link, MemoryRouter, useLocation } from "react-router-dom"
5
5
 
6
- import { ErrorBoundary } from "~/packages/hamr/src/react-error-boundary"
6
+ import { RecoverableErrorBoundary } from "~/packages/hamr/src/react-error-boundary"
7
7
  import type { WC } from "~/packages/hamr/src/react-json-editor"
8
8
 
9
9
  import { attachExplorerState } from "./explorer-states"
@@ -132,14 +132,14 @@ export const composeExplorer = ({
132
132
  const view = useO(findViewState(focusedViewId))
133
133
  return (
134
134
  <div className="space">
135
- <ErrorBoundary>
135
+ <RecoverableErrorBoundary>
136
136
  <MemoryRouter
137
137
  initialEntries={view.location ? [view.location.pathname] : []}
138
138
  >
139
139
  <TabBar spaceId={spaceId} viewIds={viewIds} />
140
140
  <View viewId={focusedViewId}>{children}</View>
141
141
  </MemoryRouter>
142
- </ErrorBoundary>
142
+ </RecoverableErrorBoundary>
143
143
  </div>
144
144
  )
145
145
  }
@@ -17,7 +17,7 @@ const subscribeToTokenCreation = <T>(
17
17
 
18
18
  /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
19
19
  export const useExposeFamily = ({ socket, store }: ServerConfig) => {
20
- return function exposeFamily<J extends Json>(
20
+ return function exposeFamily<J extends Json.Serializable>(
21
21
  family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
22
22
  index: AtomIO.StateToken<Set<string>>,
23
23
  ): () => void {
@@ -39,7 +39,7 @@ export const useExposeFamily = ({ socket, store }: ServerConfig) => {
39
39
  }
40
40
  }
41
41
 
42
- const fillSubRequest = (subKey?: AtomIO.Serializable) => {
42
+ const fillSubRequest = (subKey?: AtomIO.Json.Serializable) => {
43
43
  if (subKey === undefined) {
44
44
  const keys = AtomIO.getState(index, store)
45
45
  keys.forEach((key) => {
@@ -5,7 +5,7 @@ import type { ServerConfig } from ".."
5
5
 
6
6
  /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
7
7
  export const useExposeSingle = ({ socket, store }: ServerConfig) => {
8
- return function exposeSingle<J extends Json>(
8
+ return function exposeSingle<J extends Json.Serializable>(
9
9
  token: AtomIO.StateToken<J>,
10
10
  ): () => void {
11
11
  let unsubscribeFromStateUpdates: (() => void) | null = null
@@ -5,7 +5,7 @@ import type { ServerConfig } from ".."
5
5
 
6
6
  /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
7
7
  export const useReceiveState = ({ socket, store }: ServerConfig) => {
8
- return function receiveState<J extends Json>(
8
+ return function receiveState<J extends Json.Serializable>(
9
9
  token: AtomIO.StateToken<J>,
10
10
  ): () => void {
11
11
  const publish = (newValue: J) => AtomIO.setState(token, newValue, store)