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.
- package/README.md +32 -78
- package/dist/index.d.mts +11 -43
- package/dist/index.d.ts +11 -43
- package/dist/index.js +111 -291
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +108 -278
- package/dist/index.mjs.map +1 -1
- package/introspection/dist/index.d.mts +273 -0
- package/introspection/dist/index.d.ts +273 -0
- package/introspection/dist/index.js +350 -0
- package/introspection/dist/index.js.map +1 -0
- package/introspection/dist/index.mjs +327 -0
- package/introspection/dist/index.mjs.map +1 -0
- package/introspection/package.json +15 -0
- package/package.json +22 -12
- package/react-devtools/dist/index.css +22 -5
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +347 -10
- package/react-devtools/dist/index.d.ts +347 -10
- package/react-devtools/dist/index.js +2743 -696
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +2739 -701
- package/react-devtools/dist/index.mjs.map +1 -1
- package/src/internal/atom-internal.ts +5 -6
- package/src/internal/get.ts +7 -9
- package/src/internal/index.ts +0 -1
- package/src/internal/operation.ts +15 -21
- package/src/internal/selector/create-read-write-selector.ts +8 -4
- package/src/internal/selector/create-readonly-selector.ts +1 -7
- package/src/internal/selector-internal.ts +1 -3
- package/src/internal/set.ts +1 -4
- package/src/internal/store.ts +22 -24
- package/src/internal/subscribe-internal.ts +7 -1
- package/src/internal/time-travel-internal.ts +2 -0
- package/src/internal/timeline/add-atom-to-timeline.ts +11 -12
- package/src/internal/timeline-internal.ts +6 -4
- package/src/internal/transaction/apply-transaction.ts +9 -6
- package/src/internal/transaction/build-transaction.ts +6 -6
- package/src/internal/transaction-internal.ts +1 -7
- package/src/introspection/attach-atom-index.ts +73 -0
- package/src/introspection/attach-introspection-states.ts +42 -0
- package/src/introspection/attach-selector-index.ts +77 -0
- package/src/introspection/attach-timeline-family.ts +59 -0
- package/src/introspection/attach-timeline-index.ts +36 -0
- package/src/introspection/attach-transaction-index.ts +38 -0
- package/src/introspection/attach-transaction-logs.ts +40 -0
- package/src/introspection/index.ts +20 -0
- package/src/react-devtools/AtomIODevtools.tsx +97 -97
- package/src/react-devtools/Button.tsx +24 -0
- package/src/react-devtools/StateEditor.tsx +14 -16
- package/src/react-devtools/StateIndex.tsx +153 -0
- package/src/react-devtools/TimelineIndex.tsx +92 -0
- package/src/react-devtools/TransactionIndex.tsx +70 -0
- package/src/react-devtools/Updates.tsx +145 -0
- package/src/react-devtools/devtools.scss +196 -15
- package/src/react-devtools/index.ts +71 -0
- package/src/react-explorer/AtomIOExplorer.tsx +3 -4
- package/src/react-explorer/explorer-states.ts +1 -1
- package/src/react-explorer/space-states.ts +3 -1
- package/src/react-explorer/view-states.ts +0 -2
- package/realtime-testing/dist/index.d.mts +0 -49
- package/realtime-testing/dist/index.d.ts +0 -49
- package/realtime-testing/dist/index.js +0 -165
- package/realtime-testing/dist/index.js.map +0 -1
- package/realtime-testing/dist/index.mjs +0 -129
- package/realtime-testing/dist/index.mjs.map +0 -1
- package/src/internal/meta/attach-meta.ts +0 -17
- package/src/internal/meta/index.ts +0 -4
- package/src/internal/meta/meta-state.ts +0 -135
- package/src/internal/meta/meta-timelines.ts +0 -1
- package/src/internal/meta/meta-transactions.ts +0 -1
- 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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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)
|
package/src/internal/get.ts
CHANGED
|
@@ -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 =
|
|
30
|
+
const type = core.atoms.has(key)
|
|
33
31
|
? `atom`
|
|
34
|
-
:
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
}
|
package/src/internal/index.ts
CHANGED
|
@@ -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:
|
|
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
|
|
74
|
+
return core.valueMap.get(state.key)
|
|
77
75
|
}
|
|
78
|
-
return
|
|
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
|
|
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
|
|
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 =>
|
|
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 =>
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
|
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
|
|
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 (
|
|
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
|
)
|
package/src/internal/set.ts
CHANGED
|
@@ -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
|
-
|
|
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`,
|
package/src/internal/store.ts
CHANGED
|
@@ -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:
|
|
40
|
+
atoms: Map<string, Atom<any>>
|
|
44
41
|
atomsThatAreDefault: Set<string>
|
|
45
|
-
readonlySelectors:
|
|
42
|
+
readonlySelectors: Map<string, ReadonlySelector<any>>
|
|
46
43
|
selectorAtoms: Join<null, `selectorKey`, `atomKey`>
|
|
47
44
|
selectorGraph: Join<{ source: string }>
|
|
48
|
-
selectors:
|
|
45
|
+
selectors: Map<string, Selector<any>>
|
|
49
46
|
timelineAtoms: Join<null, `timelineKey`, `atomKey`>
|
|
50
|
-
timelines:
|
|
51
|
-
transactions:
|
|
52
|
-
valueMap:
|
|
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
|
|
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
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
122
|
+
created.atoms.set(atom.key, copiedAtom)
|
|
125
123
|
})
|
|
126
124
|
store?.readonlySelectors.forEach((selector) => {
|
|
127
|
-
selector.install(
|
|
125
|
+
selector.install(created)
|
|
128
126
|
})
|
|
129
127
|
store?.selectors.forEach((selector) => {
|
|
130
|
-
selector.install(
|
|
128
|
+
selector.install(created)
|
|
131
129
|
})
|
|
132
130
|
store?.transactions.forEach((tx) => {
|
|
133
|
-
tx.install(
|
|
131
|
+
tx.install(created)
|
|
134
132
|
})
|
|
135
133
|
store?.timelines.forEach((timeline) => {
|
|
136
|
-
timeline.install(
|
|
134
|
+
timeline.install(created)
|
|
137
135
|
})
|
|
138
136
|
|
|
139
|
-
return
|
|
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(
|
|
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
|
-
|
|
109
|
+
latestUpdate = {
|
|
112
110
|
type: `selector_update`,
|
|
113
111
|
timestamp: currentSelectorTime,
|
|
114
112
|
key: currentSelectorKey,
|
|
115
113
|
atomUpdates: [],
|
|
116
114
|
}
|
|
117
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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 (!
|
|
30
|
-
const newAtom =
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
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
|
+
}
|