atom.io 0.6.2 → 0.6.4
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/dist/index.d.mts +27 -15
- package/dist/index.d.ts +27 -15
- package/dist/index.js +44 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +44 -24
- package/dist/index.mjs.map +1 -1
- package/json/dist/index.d.mts +18 -0
- package/json/dist/index.d.ts +18 -0
- package/json/dist/index.js +51 -0
- package/json/dist/index.js.map +1 -0
- package/json/dist/index.mjs +15 -0
- package/json/dist/index.mjs.map +1 -0
- package/json/package.json +13 -13
- package/package.json +31 -12
- package/react/dist/index.d.mts +24 -0
- package/react/dist/index.d.ts +24 -0
- package/react/dist/index.js +87 -0
- package/react/dist/index.js.map +1 -0
- package/react/dist/index.mjs +45 -0
- package/react/dist/index.mjs.map +1 -0
- package/react/package.json +13 -13
- package/react-devtools/dist/index.css +26 -0
- package/react-devtools/dist/index.css.map +1 -0
- package/react-devtools/dist/index.d.mts +15 -0
- package/react-devtools/dist/index.d.ts +15 -0
- package/react-devtools/dist/index.js +2108 -0
- package/react-devtools/dist/index.js.map +1 -0
- package/react-devtools/dist/index.mjs +2080 -0
- package/react-devtools/dist/index.mjs.map +1 -0
- package/react-devtools/package.json +13 -13
- package/realtime/dist/index.d.mts +27 -0
- package/realtime/dist/index.d.ts +27 -0
- package/realtime/dist/index.js +191 -0
- package/realtime/dist/index.js.map +1 -0
- package/realtime/dist/index.mjs +152 -0
- package/realtime/dist/index.mjs.map +1 -0
- package/realtime/package.json +13 -13
- package/realtime-react/dist/index.d.mts +45 -0
- package/realtime-react/dist/index.d.ts +45 -0
- package/realtime-react/dist/index.js +217 -0
- package/realtime-react/dist/index.js.map +1 -0
- package/realtime-react/dist/index.mjs +172 -0
- package/realtime-react/dist/index.mjs.map +1 -0
- package/realtime-react/package.json +13 -13
- package/realtime-testing/dist/index.d.mts +49 -0
- package/realtime-testing/dist/index.d.ts +49 -0
- package/realtime-testing/dist/index.js +165 -0
- package/realtime-testing/dist/index.js.map +1 -0
- package/realtime-testing/dist/index.mjs +129 -0
- package/realtime-testing/dist/index.mjs.map +1 -0
- package/realtime-testing/package.json +15 -0
- package/src/atom.ts +16 -17
- package/src/index.ts +59 -59
- package/src/internal/atom-internal.ts +37 -37
- package/src/internal/families-internal.ts +115 -116
- package/src/internal/get.ts +83 -83
- package/src/internal/index.ts +1 -0
- package/src/internal/is-default.ts +17 -17
- package/src/internal/meta/attach-meta.ts +7 -7
- package/src/internal/meta/meta-state.ts +115 -115
- package/src/internal/operation.ts +93 -93
- package/src/internal/selector/create-read-write-selector.ts +47 -47
- package/src/internal/selector/create-readonly-selector.ts +38 -38
- package/src/internal/selector/lookup-selector-sources.ts +9 -9
- package/src/internal/selector/register-selector.ts +44 -44
- package/src/internal/selector/trace-selector-atoms.ts +30 -30
- package/src/internal/selector/update-selector-atoms.ts +25 -25
- package/src/internal/selector-internal.ts +38 -39
- package/src/internal/set.ts +78 -78
- package/src/internal/store.ts +119 -119
- package/src/internal/subject.ts +24 -0
- package/src/internal/subscribe-internal.ts +62 -62
- package/src/internal/time-travel-internal.ts +76 -76
- package/src/internal/timeline/add-atom-to-timeline.ts +158 -153
- package/src/internal/timeline-internal.ts +81 -82
- package/src/internal/transaction/abort-transaction.ts +8 -8
- package/src/internal/transaction/apply-transaction.ts +41 -41
- package/src/internal/transaction/build-transaction.ts +28 -28
- package/src/internal/transaction/index.ts +7 -7
- package/src/internal/transaction/redo-transaction.ts +13 -13
- package/src/internal/transaction/undo-transaction.ts +13 -13
- package/src/internal/transaction-internal.ts +49 -49
- package/src/json/select-json.ts +12 -12
- package/src/logger.ts +30 -30
- package/src/react/store-context.tsx +5 -6
- package/src/react/store-hooks.ts +19 -20
- package/src/react-devtools/AtomIODevtools.tsx +85 -85
- package/src/react-devtools/StateEditor.tsx +54 -55
- package/src/react-devtools/TokenList.tsx +49 -45
- package/src/react-explorer/AtomIOExplorer.tsx +198 -187
- package/src/react-explorer/explorer-effects.ts +11 -11
- package/src/react-explorer/explorer-states.ts +186 -193
- package/src/react-explorer/index.ts +11 -11
- package/src/react-explorer/space-states.ts +48 -50
- package/src/react-explorer/view-states.ts +25 -25
- package/src/realtime/hook-composition/expose-family.ts +81 -81
- package/src/realtime/hook-composition/expose-single.ts +26 -26
- package/src/realtime/hook-composition/expose-timeline.ts +60 -0
- package/src/realtime/hook-composition/index.ts +2 -2
- package/src/realtime/hook-composition/receive-state.ts +18 -18
- package/src/realtime/hook-composition/receive-transaction.ts +8 -8
- package/src/realtime-react/realtime-context.tsx +18 -19
- package/src/realtime-react/realtime-hooks.ts +17 -17
- package/src/realtime-react/realtime-state.ts +4 -4
- package/src/realtime-react/use-pull-family-member.ts +16 -17
- package/src/realtime-react/use-pull-family.ts +14 -15
- package/src/realtime-react/use-pull.ts +13 -14
- package/src/realtime-react/use-push.ts +16 -17
- package/src/realtime-react/use-server-action.ts +22 -23
- package/src/realtime-testing/index.ts +1 -0
- package/src/realtime-testing/setup-realtime-test.tsx +159 -0
- package/src/selector.ts +26 -27
- package/src/silo.ts +38 -38
- package/src/subscribe.ts +68 -68
- package/src/timeline.ts +13 -13
- package/src/transaction.ts +28 -28
- package/src/web-effects/storage.ts +17 -17
|
@@ -8,138 +8,138 @@ import { IMPLICIT } from "./store"
|
|
|
8
8
|
import type { StateToken } from ".."
|
|
9
9
|
|
|
10
10
|
export type OperationProgress =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
| {
|
|
12
|
+
open: false
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
open: true
|
|
16
|
+
done: Set<string>
|
|
17
|
+
prev: Hamt<any, string>
|
|
18
|
+
time: number
|
|
19
|
+
token: StateToken<any>
|
|
20
|
+
}
|
|
21
21
|
|
|
22
22
|
export const openOperation = (token: StateToken<any>, store: Store): void => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
const core = target(store)
|
|
24
|
+
if (core.operation.open) {
|
|
25
|
+
store.config.logger?.error(
|
|
26
|
+
`❌ failed to setState to "${token.key}" during a setState for "${core.operation.token.key}"`,
|
|
27
|
+
)
|
|
28
|
+
throw Symbol(`violation`)
|
|
29
|
+
}
|
|
30
|
+
core.operation = {
|
|
31
|
+
open: true,
|
|
32
|
+
done: new Set(),
|
|
33
|
+
prev: store.valueMap,
|
|
34
|
+
time: Date.now(),
|
|
35
|
+
token,
|
|
36
|
+
}
|
|
37
|
+
store.config.logger?.info(
|
|
38
|
+
`⭕ operation start from "${token.key}" in store "${store.config.name}"`,
|
|
39
|
+
)
|
|
40
40
|
}
|
|
41
41
|
export const closeOperation = (store: Store): void => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const core = target(store)
|
|
43
|
+
core.operation = { open: false }
|
|
44
|
+
store.config.logger?.info(`🔴 operation done`)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export const isDone = (key: string, store: Store = IMPLICIT.STORE): boolean => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
const core = target(store)
|
|
49
|
+
if (!core.operation.open) {
|
|
50
|
+
store.config.logger?.warn(
|
|
51
|
+
`isDone called outside of an operation. This is probably a bug.`,
|
|
52
|
+
)
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
return core.operation.done.has(key)
|
|
56
56
|
}
|
|
57
57
|
export const markDone = (key: string, store: Store = IMPLICIT.STORE): void => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
const core = target(store)
|
|
59
|
+
if (!core.operation.open) {
|
|
60
|
+
store.config.logger?.warn(
|
|
61
|
+
`markDone called outside of an operation. This is probably a bug.`,
|
|
62
|
+
)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
core.operation.done.add(key)
|
|
66
66
|
}
|
|
67
67
|
export const recallState = <T>(
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
69
|
+
store: Store = IMPLICIT.STORE,
|
|
70
70
|
): T => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
const core = target(store)
|
|
72
|
+
if (!core.operation.open) {
|
|
73
|
+
store.config.logger?.warn(
|
|
74
|
+
`recall called outside of an operation. This is probably a bug.`,
|
|
75
|
+
)
|
|
76
|
+
return HAMT.get(state.key, core.valueMap)
|
|
77
|
+
}
|
|
78
|
+
return HAMT.get(state.key, core.operation.prev)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
export const cacheValue = (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
key: string,
|
|
83
|
+
value: unknown,
|
|
84
|
+
store: Store = IMPLICIT.STORE,
|
|
85
85
|
): void => {
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const core = target(store)
|
|
87
|
+
core.valueMap = HAMT.set(key, value, core.valueMap)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
export const evictCachedValue = (
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
key: string,
|
|
92
|
+
store: Store = IMPLICIT.STORE,
|
|
93
93
|
): void => {
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
const core = target(store)
|
|
95
|
+
core.valueMap = HAMT.remove(key, core.valueMap)
|
|
96
96
|
}
|
|
97
97
|
export const readCachedValue = <T>(
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
key: string,
|
|
99
|
+
store: Store = IMPLICIT.STORE,
|
|
100
100
|
): T => HAMT.get(key, target(store).valueMap)
|
|
101
101
|
|
|
102
102
|
export const isValueCached = (
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
key: string,
|
|
104
|
+
store: Store = IMPLICIT.STORE,
|
|
105
105
|
): boolean => HAMT.has(key, target(store).valueMap)
|
|
106
106
|
|
|
107
107
|
export const storeAtom = (
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
atom: Atom<any>,
|
|
109
|
+
store: Store = IMPLICIT.STORE,
|
|
110
110
|
): void => {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const core = target(store)
|
|
112
|
+
core.atoms = HAMT.set(atom.key, atom, core.atoms)
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
export const storeSelector = (
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
selector: Selector<any>,
|
|
117
|
+
store: Store = IMPLICIT.STORE,
|
|
118
118
|
): void => {
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
const core = target(store)
|
|
120
|
+
core.selectors = HAMT.set(selector.key, selector, core.selectors)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export const storeReadonlySelector = (
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
selector: ReadonlySelector<any>,
|
|
125
|
+
store: Store = IMPLICIT.STORE,
|
|
126
126
|
): void => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
const core = target(store)
|
|
128
|
+
core.readonlySelectors = HAMT.set(
|
|
129
|
+
selector.key,
|
|
130
|
+
selector,
|
|
131
|
+
core.readonlySelectors,
|
|
132
|
+
)
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
export const hasKeyBeenUsed = (
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
key: string,
|
|
137
|
+
store: Store = IMPLICIT.STORE,
|
|
138
138
|
): boolean => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
const core = target(store)
|
|
140
|
+
return (
|
|
141
|
+
HAMT.has(key, core.atoms) ||
|
|
142
|
+
HAMT.has(key, core.selectors) ||
|
|
143
|
+
HAMT.has(key, core.readonlySelectors)
|
|
144
|
+
)
|
|
145
145
|
}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
1
|
import HAMT from "hamt_plus"
|
|
2
|
-
import * as Rx from "rxjs"
|
|
3
2
|
|
|
4
3
|
import { become } from "~/packages/anvl/src/function"
|
|
5
4
|
|
|
5
|
+
import { Subject } from ".."
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
type Store,
|
|
8
|
+
type Selector,
|
|
9
|
+
type StoreCore,
|
|
10
|
+
registerSelector,
|
|
11
|
+
selector__INTERNAL,
|
|
12
12
|
} from ".."
|
|
13
13
|
import type { FamilyMetadata, SelectorToken } from "../.."
|
|
14
14
|
import type { SelectorOptions } from "../../selector"
|
|
15
15
|
import { cacheValue, markDone } from "../operation"
|
|
16
16
|
|
|
17
17
|
export const createReadWriteSelector = <T>(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
options: SelectorOptions<T>,
|
|
19
|
+
family: FamilyMetadata | undefined,
|
|
20
|
+
store: Store,
|
|
21
|
+
core: StoreCore,
|
|
22
22
|
): SelectorToken<T> => {
|
|
23
|
-
|
|
23
|
+
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const { get, set } = registerSelector(options.key, store)
|
|
26
|
+
const getSelf = () => {
|
|
27
|
+
const value = options.get({ get })
|
|
28
|
+
cacheValue(options.key, value, store)
|
|
29
|
+
return value
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
32
|
+
const setSelf = (next: T | ((oldValue: T) => T)): void => {
|
|
33
|
+
store.config.logger?.info(` <- "${options.key}" became`, next)
|
|
34
|
+
const oldValue = getSelf()
|
|
35
|
+
const newValue = become(next)(oldValue)
|
|
36
|
+
cacheValue(options.key, newValue, store)
|
|
37
|
+
markDone(options.key, store)
|
|
38
|
+
if (store.transactionStatus.phase === `idle`) {
|
|
39
|
+
subject.next({ newValue, oldValue })
|
|
40
|
+
}
|
|
41
|
+
options.set({ get, set }, newValue)
|
|
42
|
+
}
|
|
43
|
+
const mySelector: Selector<T> = {
|
|
44
|
+
...options,
|
|
45
|
+
subject,
|
|
46
|
+
install: (s: Store) => selector__INTERNAL(options, family, s),
|
|
47
|
+
get: getSelf,
|
|
48
|
+
set: setSelf,
|
|
49
|
+
type: `selector`,
|
|
50
|
+
...(family && { family }),
|
|
51
|
+
}
|
|
52
|
+
core.selectors = HAMT.set(options.key, mySelector, core.selectors)
|
|
53
|
+
const initialValue = getSelf()
|
|
54
|
+
store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
|
|
55
|
+
const token: SelectorToken<T> = {
|
|
56
|
+
key: options.key,
|
|
57
|
+
type: `selector`,
|
|
58
|
+
family,
|
|
59
|
+
}
|
|
60
|
+
store.subject.selectorCreation.next(token)
|
|
61
|
+
return token
|
|
62
62
|
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
import HAMT from "hamt_plus"
|
|
2
|
-
import * as Rx from "rxjs"
|
|
3
2
|
|
|
4
3
|
import { registerSelector } from "./register-selector"
|
|
4
|
+
import { Subject } from ".."
|
|
5
5
|
import type {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
FamilyMetadata,
|
|
7
|
+
ReadonlySelectorOptions,
|
|
8
|
+
ReadonlySelectorToken,
|
|
9
|
+
Store,
|
|
10
10
|
} from "../.."
|
|
11
11
|
import { cacheValue } from "../operation"
|
|
12
12
|
import { selector__INTERNAL, type ReadonlySelector } from "../selector-internal"
|
|
13
13
|
import type { StoreCore } from "../store"
|
|
14
14
|
|
|
15
15
|
export const createReadonlySelector = <T>(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
options: ReadonlySelectorOptions<T>,
|
|
17
|
+
family: FamilyMetadata | undefined,
|
|
18
|
+
store: Store,
|
|
19
|
+
core: StoreCore,
|
|
20
20
|
): ReadonlySelectorToken<T> => {
|
|
21
|
-
|
|
21
|
+
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const { get } = registerSelector(options.key, store)
|
|
24
|
+
const getSelf = () => {
|
|
25
|
+
const value = options.get({ get })
|
|
26
|
+
cacheValue(options.key, value, store)
|
|
27
|
+
return value
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
const readonlySelector: ReadonlySelector<T> = {
|
|
31
|
+
...options,
|
|
32
|
+
subject,
|
|
33
|
+
install: (s: Store) => selector__INTERNAL(options, family, s),
|
|
34
|
+
get: getSelf,
|
|
35
|
+
type: `readonly_selector`,
|
|
36
|
+
...(family && { family }),
|
|
37
|
+
}
|
|
38
|
+
core.readonlySelectors = HAMT.set(
|
|
39
|
+
options.key,
|
|
40
|
+
readonlySelector,
|
|
41
|
+
core.readonlySelectors,
|
|
42
|
+
)
|
|
43
|
+
const initialValue = getSelf()
|
|
44
|
+
store.config.logger?.info(` ✨ "${options.key}" =`, initialValue)
|
|
45
|
+
const token: ReadonlySelectorToken<T> = {
|
|
46
|
+
key: options.key,
|
|
47
|
+
type: `readonly_selector`,
|
|
48
|
+
family,
|
|
49
|
+
}
|
|
50
|
+
store.subject.selectorCreation.next(token)
|
|
51
|
+
return token
|
|
52
52
|
}
|
|
@@ -3,14 +3,14 @@ import { target, lookup } from ".."
|
|
|
3
3
|
import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "../.."
|
|
4
4
|
|
|
5
5
|
export const lookupSelectorSources = (
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
key: string,
|
|
7
|
+
store: Store,
|
|
8
8
|
): (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
| AtomToken<unknown>
|
|
10
|
+
| ReadonlySelectorToken<unknown>
|
|
11
|
+
| SelectorToken<unknown>
|
|
12
12
|
)[] =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
target(store)
|
|
14
|
+
.selectorGraph.getRelations(key)
|
|
15
|
+
.filter(({ source }) => source !== key)
|
|
16
|
+
.map(({ source }) => lookup(source, store))
|
|
@@ -7,51 +7,51 @@ import { IMPLICIT } from "../store"
|
|
|
7
7
|
import { target } from "../transaction-internal"
|
|
8
8
|
|
|
9
9
|
export const registerSelector = (
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
selectorKey: string,
|
|
11
|
+
store: Store = IMPLICIT.STORE,
|
|
12
12
|
): Transactors => ({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
get: (dependency) => {
|
|
14
|
+
const core = target(store)
|
|
15
|
+
const alreadyRegistered = core.selectorGraph
|
|
16
|
+
.getRelations(selectorKey)
|
|
17
|
+
.some(({ source }) => source === dependency.key)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const dependencyState = withdraw(dependency, store)
|
|
20
|
+
if (dependencyState === null) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
const dependencyValue = getState__INTERNAL(dependencyState, store)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
if (alreadyRegistered) {
|
|
28
|
+
store.config.logger?.info(
|
|
29
|
+
` || ${selectorKey} <- ${dependency.key} =`,
|
|
30
|
+
dependencyValue,
|
|
31
|
+
)
|
|
32
|
+
} else {
|
|
33
|
+
store.config.logger?.info(
|
|
34
|
+
`🔌 registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
|
|
35
|
+
dependencyValue,
|
|
36
|
+
`)`,
|
|
37
|
+
)
|
|
38
|
+
core.selectorGraph = core.selectorGraph.set(
|
|
39
|
+
{ from: dependency.key, to: selectorKey },
|
|
40
|
+
{
|
|
41
|
+
source: dependency.key,
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
updateSelectorAtoms(selectorKey, dependency, store)
|
|
46
|
+
return dependencyValue
|
|
47
|
+
},
|
|
48
|
+
set: (stateToken, newValue) => {
|
|
49
|
+
const state = withdraw(stateToken, store)
|
|
50
|
+
if (state === null) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
setState__INTERNAL(state, newValue, store)
|
|
56
|
+
},
|
|
57
57
|
})
|
|
@@ -2,42 +2,42 @@ import { lookupSelectorSources } from "./lookup-selector-sources"
|
|
|
2
2
|
import type { Store, AtomToken, ReadonlySelectorToken, StateToken } from "../.."
|
|
3
3
|
|
|
4
4
|
export const traceSelectorAtoms = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
selectorKey: string,
|
|
6
|
+
dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
|
|
7
|
+
store: Store,
|
|
8
8
|
): AtomToken<unknown>[] => {
|
|
9
|
-
|
|
9
|
+
const roots: AtomToken<unknown>[] = []
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
const sources = lookupSelectorSources(dependency.key, store)
|
|
12
|
+
let depth = 0
|
|
13
|
+
while (sources.length > 0) {
|
|
14
|
+
// rome-ignore lint/style/noNonNullAssertion: just checked length ^^^
|
|
15
|
+
const source = sources.shift()!
|
|
16
|
+
++depth
|
|
17
|
+
if (depth > 999) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Maximum selector dependency depth exceeded in selector "${selectorKey}".`,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (source.type !== `atom`) {
|
|
24
|
+
sources.push(...lookupSelectorSources(source.key, store))
|
|
25
|
+
} else {
|
|
26
|
+
roots.push(source)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
return roots
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export const traceAllSelectorAtoms = (
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
selectorKey: string,
|
|
35
|
+
store: Store,
|
|
36
36
|
): AtomToken<unknown>[] => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
const sources = lookupSelectorSources(selectorKey, store)
|
|
38
|
+
return sources.flatMap((source) =>
|
|
39
|
+
source.type === `atom`
|
|
40
|
+
? source
|
|
41
|
+
: traceSelectorAtoms(selectorKey, source, store),
|
|
42
|
+
)
|
|
43
43
|
}
|