atom.io 0.36.0 → 0.36.2
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/internal/index.d.ts +93 -73
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +233 -248
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +5 -6
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +2 -3
- package/dist/introspection/index.js.map +1 -1
- package/dist/main/index.d.ts +29 -37
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +8 -9
- package/dist/main/index.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.d.ts.map +1 -1
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +7 -8
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +3 -4
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +4 -4
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +2 -2
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/transceivers/set-rtx/index.d.ts +9 -2
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +3 -0
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/package.json +3 -3
- package/src/internal/atom/create-regular-atom.ts +5 -5
- package/src/internal/atom/has-role.ts +12 -0
- package/src/internal/atom/index.ts +1 -0
- package/src/internal/caching.ts +60 -41
- package/src/internal/families/find-in-store.ts +1 -1
- package/src/internal/families/get-family-of-token.ts +1 -1
- package/src/internal/families/init-family-member.ts +1 -1
- package/src/internal/families/seek-in-store.ts +1 -1
- package/src/internal/get-state/read-or-compute-value.ts +26 -21
- package/src/internal/index.ts +8 -8
- package/src/internal/join/create-join.ts +3 -2
- package/src/internal/join/join-internal.ts +7 -4
- package/src/internal/mutable/create-mutable-atom-family.ts +6 -5
- package/src/internal/mutable/create-mutable-atom.ts +1 -1
- package/src/internal/mutable/get-json-family.ts +1 -1
- package/src/internal/mutable/get-json-token.ts +1 -1
- package/src/internal/mutable/get-update-family.ts +1 -1
- package/src/internal/mutable/get-update-token.ts +1 -1
- package/src/internal/mutable/tracker-family.ts +27 -31
- package/src/internal/mutable/tracker.ts +29 -23
- package/src/internal/mutable/transceiver.ts +11 -10
- package/src/internal/selector/create-readonly-held-selector.ts +2 -2
- package/src/internal/selector/create-readonly-pure-selector.ts +2 -2
- package/src/internal/selector/create-writable-held-selector.ts +3 -4
- package/src/internal/selector/create-writable-pure-selector.ts +3 -3
- package/src/internal/set-state/evict-downstream.ts +17 -15
- package/src/internal/set-state/index.ts +1 -0
- package/src/internal/set-state/reset-in-store.ts +6 -50
- package/src/internal/set-state/set-atom.ts +17 -24
- package/src/internal/set-state/set-into-store.ts +29 -13
- package/src/internal/store/counterfeit.ts +1 -1
- package/src/internal/store/deposit.ts +7 -8
- package/src/internal/store/store.ts +6 -6
- package/src/internal/store/withdraw.ts +8 -8
- package/src/internal/subscribe/subscribe-in-store.ts +8 -8
- package/src/internal/subscribe/subscribe-to-timeline.ts +2 -2
- package/src/internal/subscribe/subscribe-to-transaction.ts +2 -2
- package/src/internal/timeline/create-timeline.ts +3 -3
- package/src/internal/transaction/act-upon-store.ts +2 -2
- package/src/internal/transaction/apply-transaction.ts +2 -2
- package/src/internal/transaction/build-transaction.ts +2 -2
- package/src/internal/transaction/create-transaction.ts +3 -3
- package/src/internal/transaction/index.ts +2 -2
- package/src/internal/transaction/is-root-store.ts +4 -2
- package/src/internal/utility-types.ts +1 -1
- package/src/introspection/attach-introspection-states.ts +3 -3
- package/src/introspection/attach-transaction-index.ts +4 -4
- package/src/introspection/attach-transaction-logs.ts +4 -4
- package/src/introspection/auditor.ts +3 -3
- package/src/main/atom.ts +4 -4
- package/src/main/dispose-state.ts +4 -3
- package/src/main/find-state.ts +1 -1
- package/src/main/get-state.ts +6 -5
- package/src/main/reset-state.ts +3 -3
- package/src/main/set-state.ts +3 -3
- package/src/main/subscribe.ts +3 -3
- package/src/main/tokens.ts +9 -18
- package/src/main/transaction.ts +13 -15
- package/src/react/use-json.ts +5 -5
- package/src/react-devtools/TransactionIndex.tsx +3 -3
- package/src/react-devtools/Updates.tsx +2 -2
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +2 -2
- package/src/realtime-client/pull-mutable-atom-family-member.ts +8 -13
- package/src/realtime-client/pull-mutable-atom.ts +5 -8
- package/src/realtime-client/push-state.ts +6 -5
- package/src/realtime-client/server-action.ts +5 -4
- package/src/realtime-react/use-pull-mutable-atom.ts +1 -1
- package/src/realtime-react/use-pull-mutable-family-member.ts +1 -1
- package/src/realtime-react/use-server-action.ts +2 -2
- package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-provider.ts +1 -1
- package/src/transceivers/set-rtx/set-rtx.ts +14 -1
- package/src/internal/set-state/copy-mutable-if-needed.ts +0 -29
package/src/internal/caching.ts
CHANGED
|
@@ -1,34 +1,31 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
import type { ReadableState } from "."
|
|
4
|
-
import { closeOperation, isChildStore, openOperation } from "."
|
|
1
|
+
import type { ReadableState, Transceiver } from "."
|
|
2
|
+
import { closeOperation, isChildStore, openOperation, Tracker } from "."
|
|
5
3
|
import { Future } from "./future"
|
|
6
|
-
import { copyMutableIfNeeded } from "./set-state/copy-mutable-if-needed"
|
|
7
4
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
evictDownstreamFromAtom,
|
|
6
|
+
evictDownstreamFromSelector,
|
|
10
7
|
} from "./set-state/evict-downstream"
|
|
11
8
|
import type { Store } from "./store"
|
|
12
|
-
import type { Subject } from "./subject"
|
|
13
9
|
|
|
14
|
-
export function
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
export function writeToCache<T>(
|
|
11
|
+
target: Store,
|
|
12
|
+
state: ReadableState<T>,
|
|
17
13
|
value: T,
|
|
18
|
-
subject: Subject<StateUpdate<unknown>>,
|
|
14
|
+
// subject: Subject<StateUpdate<unknown>>,
|
|
19
15
|
): T
|
|
20
|
-
export function
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
export function writeToCache<T extends Promise<any>>(
|
|
17
|
+
target: Store,
|
|
18
|
+
state: ReadableState<T>,
|
|
23
19
|
value: T,
|
|
24
|
-
subject: Subject<StateUpdate<unknown>>,
|
|
25
|
-
): Future<T
|
|
26
|
-
export function
|
|
20
|
+
// subject: Subject<StateUpdate<unknown>>,
|
|
21
|
+
): Future<Awaited<T>>
|
|
22
|
+
export function writeToCache<T>(
|
|
27
23
|
target: Store,
|
|
28
|
-
|
|
24
|
+
state: ReadableState<T>,
|
|
29
25
|
value: T,
|
|
30
|
-
subject: Subject<StateUpdate<unknown>>,
|
|
26
|
+
// subject: Subject<StateUpdate<unknown>>,
|
|
31
27
|
): Future<T> | T {
|
|
28
|
+
const { key, subject, type } = state
|
|
32
29
|
const currentValue = target.valueMap.get(key)
|
|
33
30
|
if (currentValue instanceof Future && !currentValue.done) {
|
|
34
31
|
const future = currentValue
|
|
@@ -46,22 +43,21 @@ export function cacheValue<T>(
|
|
|
46
43
|
.then(function handleResolvedFuture(resolved) {
|
|
47
44
|
const current = target.valueMap.get(key)
|
|
48
45
|
if (current === future) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
closeOperation(target)
|
|
63
|
-
}
|
|
46
|
+
openOperation(target, state)
|
|
47
|
+
writeToCache(target, state, resolved)
|
|
48
|
+
switch (type) {
|
|
49
|
+
case `atom`:
|
|
50
|
+
case `mutable_atom`:
|
|
51
|
+
evictDownstreamFromAtom(target, state)
|
|
52
|
+
break
|
|
53
|
+
case `readonly_held_selector`:
|
|
54
|
+
case `readonly_pure_selector`:
|
|
55
|
+
case `writable_held_selector`:
|
|
56
|
+
case `writable_pure_selector`:
|
|
57
|
+
evictDownstreamFromSelector(target, key)
|
|
58
|
+
break
|
|
64
59
|
}
|
|
60
|
+
closeOperation(target)
|
|
65
61
|
subject.next({ newValue: resolved, oldValue: future })
|
|
66
62
|
}
|
|
67
63
|
})
|
|
@@ -74,21 +70,44 @@ export function cacheValue<T>(
|
|
|
74
70
|
return value
|
|
75
71
|
}
|
|
76
72
|
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
/**
|
|
74
|
+
* @param target - the newest layer of the store
|
|
75
|
+
* @param state - the state to read from cache
|
|
76
|
+
* @param mut - whether the value is intended to be mutable
|
|
77
|
+
* @returns the state's current value
|
|
78
|
+
*/
|
|
79
|
+
export function readFromCache<T>(
|
|
79
80
|
target: Store,
|
|
80
|
-
|
|
81
|
+
state: ReadableState<T>,
|
|
82
|
+
mut: `mut` | undefined,
|
|
83
|
+
): T {
|
|
81
84
|
target.logger.info(`📖`, state.type, state.key, `reading cached value`)
|
|
82
85
|
let value = target.valueMap.get(state.key) as T
|
|
83
|
-
|
|
86
|
+
|
|
87
|
+
const mayNeedToBeCopied =
|
|
88
|
+
mut === `mut` && state.type === `mutable_atom` && isChildStore(target)
|
|
89
|
+
if (mayNeedToBeCopied) {
|
|
90
|
+
const mutableAtom = state
|
|
84
91
|
const { parent } = target
|
|
85
|
-
|
|
92
|
+
|
|
93
|
+
if (target.valueMap.hasOwn(mutableAtom.key)) {
|
|
94
|
+
return value
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const parentValue = parent.valueMap.get(mutableAtom.key) as T &
|
|
98
|
+
Transceiver<any, any, any>
|
|
99
|
+
|
|
100
|
+
target.logger.info(`📃`, `atom`, mutableAtom.key, `copying`)
|
|
101
|
+
const jsonValue = parentValue.toJSON()
|
|
102
|
+
const copiedValue = mutableAtom.class.fromJSON(jsonValue)
|
|
103
|
+
target.valueMap.set(mutableAtom.key, copiedValue)
|
|
104
|
+
new Tracker(mutableAtom, parent)
|
|
86
105
|
value = copiedValue
|
|
87
106
|
}
|
|
88
107
|
return value
|
|
89
108
|
}
|
|
90
109
|
|
|
91
|
-
export
|
|
110
|
+
export function evictCachedValue(target: Store, key: string): void {
|
|
92
111
|
const currentValue = target.valueMap.get(key)
|
|
93
112
|
if (currentValue instanceof Future) {
|
|
94
113
|
const selector =
|
|
@@ -25,7 +25,7 @@ import { initFamilyMemberInStore } from "./init-family-member"
|
|
|
25
25
|
import { seekInStore } from "./seek-in-store"
|
|
26
26
|
|
|
27
27
|
export function findInStore<
|
|
28
|
-
T extends Transceiver<any, any>,
|
|
28
|
+
T extends Transceiver<any, any, any>,
|
|
29
29
|
K extends Canonical,
|
|
30
30
|
Key extends K,
|
|
31
31
|
>(
|
|
@@ -25,7 +25,7 @@ import type { Store } from "../store"
|
|
|
25
25
|
import { isChildStore, isRootStore } from "../transaction"
|
|
26
26
|
|
|
27
27
|
export function initFamilyMemberInStore<
|
|
28
|
-
T extends Transceiver<any, any>,
|
|
28
|
+
T extends Transceiver<any, any, any>,
|
|
29
29
|
K extends Canonical,
|
|
30
30
|
Key extends K,
|
|
31
31
|
>(
|
|
@@ -1,48 +1,53 @@
|
|
|
1
|
-
import type { ReadableState } from ".."
|
|
2
|
-
import {
|
|
1
|
+
import type { ReadableState, ViewOf } from ".."
|
|
2
|
+
import { readFromCache, writeToCache } from "../caching"
|
|
3
3
|
import type { Store } from "../store"
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export function readOrComputeValue<T>(
|
|
6
6
|
target: Store,
|
|
7
7
|
state: ReadableState<T>,
|
|
8
|
-
|
|
8
|
+
mut?: undefined,
|
|
9
|
+
): ViewOf<T>
|
|
10
|
+
export function readOrComputeValue<T>(
|
|
11
|
+
target: Store,
|
|
12
|
+
state: ReadableState<T>,
|
|
13
|
+
mut: `mut`,
|
|
14
|
+
): T
|
|
15
|
+
export function readOrComputeValue<T>(
|
|
16
|
+
target: Store,
|
|
17
|
+
state: ReadableState<T>,
|
|
18
|
+
mut: `mut` | undefined,
|
|
19
|
+
): T {
|
|
9
20
|
if (target.valueMap.has(state.key)) {
|
|
10
|
-
return
|
|
21
|
+
return readFromCache(target, state, mut)
|
|
11
22
|
}
|
|
23
|
+
const { key } = state
|
|
12
24
|
switch (state.type) {
|
|
13
25
|
case `readonly_held_selector`:
|
|
14
26
|
case `readonly_pure_selector`:
|
|
15
27
|
case `writable_held_selector`:
|
|
16
28
|
case `writable_pure_selector`:
|
|
17
|
-
target.logger.info(`🧮`, state.type,
|
|
29
|
+
target.logger.info(`🧮`, state.type, key, `computing value`)
|
|
18
30
|
return state.get()
|
|
19
31
|
case `atom`: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
defaultValue = def()
|
|
32
|
+
let def: T
|
|
33
|
+
if (state.default instanceof Function) {
|
|
34
|
+
def = state.default()
|
|
24
35
|
} else {
|
|
25
|
-
|
|
36
|
+
def = state.default
|
|
26
37
|
}
|
|
27
|
-
const cachedValue =
|
|
28
|
-
target,
|
|
29
|
-
state.key,
|
|
30
|
-
defaultValue,
|
|
31
|
-
state.subject,
|
|
32
|
-
)
|
|
38
|
+
const cachedValue = writeToCache(target, state, def)
|
|
33
39
|
target.logger.info(
|
|
34
40
|
`💁`,
|
|
35
41
|
`atom`,
|
|
36
42
|
state.key,
|
|
37
43
|
`could not find cached value; using default`,
|
|
38
|
-
|
|
44
|
+
def,
|
|
39
45
|
)
|
|
40
46
|
return cachedValue
|
|
41
47
|
}
|
|
42
48
|
case `mutable_atom`: {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const cachedValue = cacheValue(target, state.key, instance, state.subject)
|
|
49
|
+
const instance = new state.class()
|
|
50
|
+
const cachedValue = writeToCache(target, state, instance)
|
|
46
51
|
target.logger.info(
|
|
47
52
|
`💁`,
|
|
48
53
|
`mutable_atom`,
|
package/src/internal/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
RegularAtomToken,
|
|
12
12
|
StateCreation,
|
|
13
13
|
StateDisposal,
|
|
14
|
+
StateLifecycleEvent,
|
|
14
15
|
WritableHeldSelectorFamilyToken,
|
|
15
16
|
WritableHeldSelectorToken,
|
|
16
17
|
WritablePureSelectorFamilyToken,
|
|
@@ -18,6 +19,7 @@ import type {
|
|
|
18
19
|
} from "atom.io"
|
|
19
20
|
import type { Canonical } from "atom.io/json"
|
|
20
21
|
|
|
22
|
+
import type { internalRole } from "./atom/has-role"
|
|
21
23
|
import type { ConstructorOf, Transceiver } from "./mutable"
|
|
22
24
|
import type { Store } from "./store"
|
|
23
25
|
import type { Subject } from "./subject"
|
|
@@ -67,9 +69,10 @@ export type RegularAtom<T> = Flat<
|
|
|
67
69
|
type: `atom`
|
|
68
70
|
default: T | (() => T)
|
|
69
71
|
cleanup?: () => void
|
|
72
|
+
internalRoles?: internalRole[]
|
|
70
73
|
}
|
|
71
74
|
>
|
|
72
|
-
export type MutableAtom<T extends Transceiver<any, any>> = Flat<
|
|
75
|
+
export type MutableAtom<T extends Transceiver<any, any, any>> = Flat<
|
|
73
76
|
AtomIOState & {
|
|
74
77
|
type: `mutable_atom`
|
|
75
78
|
class: ConstructorOf<T>
|
|
@@ -78,7 +81,7 @@ export type MutableAtom<T extends Transceiver<any, any>> = Flat<
|
|
|
78
81
|
>
|
|
79
82
|
export type Atom<T> =
|
|
80
83
|
| RegularAtom<T>
|
|
81
|
-
| (T extends Transceiver<any, any> ? MutableAtom<T> : never)
|
|
84
|
+
| (T extends Transceiver<any, any, any> ? MutableAtom<T> : never)
|
|
82
85
|
|
|
83
86
|
export type WritableHeldSelector<T> = Flat<
|
|
84
87
|
AtomIOState & {
|
|
@@ -138,7 +141,7 @@ export type RegularAtomFamily<T, K extends Canonical> =
|
|
|
138
141
|
// biome-ignore format: intersection
|
|
139
142
|
export type MutableAtomFamily<
|
|
140
143
|
// C extends TransceiverConstructor<any,any>,
|
|
141
|
-
T extends Transceiver<any,any>,
|
|
144
|
+
T extends Transceiver<any, any, any>,
|
|
142
145
|
K extends Canonical,
|
|
143
146
|
> =
|
|
144
147
|
& Flat<
|
|
@@ -146,16 +149,13 @@ export type MutableAtomFamily<
|
|
|
146
149
|
& {
|
|
147
150
|
install: (store: Store) => void
|
|
148
151
|
internalRoles: string[] | undefined
|
|
149
|
-
subject: Subject<
|
|
150
|
-
| StateCreation<MutableAtomToken<T>>
|
|
151
|
-
| StateDisposal<MutableAtomToken<T>>
|
|
152
|
-
>
|
|
152
|
+
subject: Subject<StateLifecycleEvent<MutableAtomToken<T>>>
|
|
153
153
|
}
|
|
154
154
|
>
|
|
155
155
|
& ((key: K) => MutableAtomToken<T>)
|
|
156
156
|
|
|
157
157
|
export type AtomFamily<T, K extends Canonical = Canonical> =
|
|
158
|
-
| MutableAtomFamily<T extends Transceiver<any, any> ? T : never, K>
|
|
158
|
+
| MutableAtomFamily<T extends Transceiver<any, any, any> ? T : never, K>
|
|
159
159
|
| RegularAtomFamily<T, K>
|
|
160
160
|
|
|
161
161
|
// biome-ignore format: intersection
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { JoinOptions, JoinToken } from "atom.io"
|
|
2
|
-
import type { Store } from "atom.io/internal"
|
|
3
|
-
import { Join } from "atom.io/internal"
|
|
4
2
|
import type { Json } from "atom.io/json"
|
|
5
3
|
|
|
4
|
+
import type { Store } from "../store"
|
|
5
|
+
import { Join } from "./join-internal"
|
|
6
|
+
|
|
6
7
|
export function createJoin<
|
|
7
8
|
ASide extends string,
|
|
8
9
|
AType extends string,
|
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
} from "../junction"
|
|
30
30
|
import { Junction } from "../junction"
|
|
31
31
|
import type { Molecule } from "../molecule"
|
|
32
|
+
import type { ViewOf } from "../mutable"
|
|
32
33
|
import { createMutableAtomFamily, getJsonFamily, getJsonToken } from "../mutable"
|
|
33
34
|
import { setIntoStore } from "../set-state"
|
|
34
35
|
import type { Store } from "../store"
|
|
@@ -343,8 +344,10 @@ export class Join<
|
|
|
343
344
|
[`join`, `content`],
|
|
344
345
|
)
|
|
345
346
|
|
|
346
|
-
const getContent: Read<(key: string) => Content | null> = (
|
|
347
|
-
get
|
|
347
|
+
const getContent: Read<(key: string) => ViewOf<Content> | null> = (
|
|
348
|
+
{ get },
|
|
349
|
+
key,
|
|
350
|
+
) => get(contentAtoms, key)
|
|
348
351
|
const setContent: Write<(key: string, content: Content) => void> = (
|
|
349
352
|
{ set },
|
|
350
353
|
key,
|
|
@@ -433,7 +436,7 @@ export class Join<
|
|
|
433
436
|
)
|
|
434
437
|
}
|
|
435
438
|
const createSingleEntrySelectorFamily = () =>
|
|
436
|
-
createReadonlyPureSelectorFamily<[string, Content] | null, string>(
|
|
439
|
+
createReadonlyPureSelectorFamily<[string, ViewOf<Content>] | null, string>(
|
|
437
440
|
store,
|
|
438
441
|
{
|
|
439
442
|
key: `${options.key}/singleRelatedEntry`,
|
|
@@ -456,7 +459,7 @@ export class Join<
|
|
|
456
459
|
[`join`, `entries`],
|
|
457
460
|
)
|
|
458
461
|
const getMultipleEntrySelectorFamily = () =>
|
|
459
|
-
createReadonlyPureSelectorFamily<[string, Content][], string>(
|
|
462
|
+
createReadonlyPureSelectorFamily<[string, ViewOf<Content>][], string>(
|
|
460
463
|
store,
|
|
461
464
|
{
|
|
462
465
|
key: `${options.key}/multipleRelatedEntries`,
|
|
@@ -23,17 +23,18 @@ import { FamilyTracker } from "./tracker-family"
|
|
|
23
23
|
import type { AsJSON, Transceiver } from "./transceiver"
|
|
24
24
|
|
|
25
25
|
export function createMutableAtomFamily<
|
|
26
|
-
T extends Transceiver<any, any>,
|
|
26
|
+
T extends Transceiver<any, any, any>,
|
|
27
27
|
K extends Canonical,
|
|
28
28
|
>(
|
|
29
29
|
store: Store,
|
|
30
30
|
options: MutableAtomFamilyOptions<T, K>,
|
|
31
31
|
internalRoles?: string[],
|
|
32
32
|
): MutableAtomFamilyToken<T, K> {
|
|
33
|
-
const familyToken: MutableAtomFamilyToken<T & Transceiver<any, any>, K> =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const familyToken: MutableAtomFamilyToken<T & Transceiver<any, any, any>, K> =
|
|
34
|
+
{
|
|
35
|
+
key: options.key,
|
|
36
|
+
type: `mutable_atom_family`,
|
|
37
|
+
}
|
|
37
38
|
|
|
38
39
|
const existing = store.families.get(options.key)
|
|
39
40
|
if (existing) {
|
|
@@ -14,7 +14,7 @@ import { subscribeToState } from "../subscribe"
|
|
|
14
14
|
import { Tracker } from "./tracker"
|
|
15
15
|
import type { Transceiver } from "./transceiver"
|
|
16
16
|
|
|
17
|
-
export function createMutableAtom<T extends Transceiver<any, any>>(
|
|
17
|
+
export function createMutableAtom<T extends Transceiver<any, any, any>>(
|
|
18
18
|
store: Store,
|
|
19
19
|
options: MutableAtomOptions<T>,
|
|
20
20
|
family: FamilyMetadata | undefined,
|
|
@@ -7,7 +7,7 @@ import type { Store } from "../store"
|
|
|
7
7
|
import type { Transceiver } from "./transceiver"
|
|
8
8
|
|
|
9
9
|
export const getJsonFamily = <
|
|
10
|
-
Core extends Transceiver<Json.Serializable, Json.Serializable>,
|
|
10
|
+
Core extends Transceiver<any, Json.Serializable, Json.Serializable>,
|
|
11
11
|
Key extends Canonical,
|
|
12
12
|
>(
|
|
13
13
|
mutableAtomFamily: MutableAtomFamilyToken<Core, Key>,
|
|
@@ -9,7 +9,7 @@ import { newest } from "../lineage"
|
|
|
9
9
|
import { type Store, withdraw } from "../store"
|
|
10
10
|
import type { AsJSON, Transceiver } from "./transceiver"
|
|
11
11
|
|
|
12
|
-
export const getJsonToken = <T extends Transceiver<any, any>>(
|
|
12
|
+
export const getJsonToken = <T extends Transceiver<any, any, any>>(
|
|
13
13
|
store: Store,
|
|
14
14
|
mutableAtomToken: MutableAtomToken<T>,
|
|
15
15
|
): WritablePureSelectorToken<AsJSON<T>> => {
|
|
@@ -7,7 +7,7 @@ import type { Store } from "../store"
|
|
|
7
7
|
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
8
8
|
|
|
9
9
|
export const getUpdateFamily = <
|
|
10
|
-
T extends Transceiver<Json.Serializable, Json.Serializable>,
|
|
10
|
+
T extends Transceiver<any, Json.Serializable, Json.Serializable>,
|
|
11
11
|
K extends string,
|
|
12
12
|
>(
|
|
13
13
|
mutableAtomFamily: MutableAtomFamilyToken<T, K>,
|
|
@@ -2,7 +2,7 @@ import type { MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
|
2
2
|
|
|
3
3
|
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
4
4
|
|
|
5
|
-
export const getUpdateToken = <T extends Transceiver<any, any>>(
|
|
5
|
+
export const getUpdateToken = <T extends Transceiver<any, any, any>>(
|
|
6
6
|
mutableAtomToken: MutableAtomToken<T>,
|
|
7
7
|
): RegularAtomToken<SignalFrom<T>> => {
|
|
8
8
|
const key = `*${mutableAtomToken.key}`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MutableAtomToken, StateLifecycleEvent } from "atom.io"
|
|
1
2
|
import type { Canonical } from "atom.io/json"
|
|
2
3
|
import { parseJson } from "atom.io/json"
|
|
3
4
|
|
|
@@ -5,25 +6,19 @@ import type { MutableAtomFamily, RegularAtomFamily } from ".."
|
|
|
5
6
|
import { createRegularAtomFamily } from "../families"
|
|
6
7
|
import { type Store, withdraw } from "../store"
|
|
7
8
|
import { Tracker } from "./tracker"
|
|
8
|
-
import type { Transceiver } from "./transceiver"
|
|
9
|
+
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
9
10
|
|
|
10
11
|
export class FamilyTracker<
|
|
11
|
-
T extends Transceiver<any, any>,
|
|
12
|
+
T extends Transceiver<any, any, any>,
|
|
12
13
|
K extends Canonical,
|
|
13
14
|
> {
|
|
14
15
|
private trackers: Map<K, Tracker<T>> = new Map()
|
|
15
16
|
|
|
16
|
-
public readonly
|
|
17
|
-
(T extends Transceiver<infer Signal, any> ? Signal : never) | null,
|
|
18
|
-
K
|
|
19
|
-
>
|
|
17
|
+
public readonly latestSignalAtoms: RegularAtomFamily<SignalFrom<T> | null, K>
|
|
20
18
|
public readonly mutableAtoms: MutableAtomFamily<T, K>
|
|
21
19
|
|
|
22
20
|
public constructor(mutableAtoms: MutableAtomFamily<T, K>, store: Store) {
|
|
23
|
-
const
|
|
24
|
-
(T extends Transceiver<infer Signal, any> ? Signal : never) | null,
|
|
25
|
-
K
|
|
26
|
-
>(
|
|
21
|
+
const latestSignalAtoms = createRegularAtomFamily<SignalFrom<T> | null, K>(
|
|
27
22
|
store,
|
|
28
23
|
{
|
|
29
24
|
key: `*${mutableAtoms.key}`,
|
|
@@ -31,30 +26,31 @@ export class FamilyTracker<
|
|
|
31
26
|
},
|
|
32
27
|
[`mutable`, `updates`],
|
|
33
28
|
)
|
|
34
|
-
this.
|
|
29
|
+
this.latestSignalAtoms = withdraw(store, latestSignalAtoms)
|
|
35
30
|
this.mutableAtoms = mutableAtoms
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
break
|
|
31
|
+
const trackerFamilyWatchesForCreationAndDisposalEvents = (
|
|
32
|
+
event: StateLifecycleEvent<MutableAtomToken<T>>,
|
|
33
|
+
) => {
|
|
34
|
+
const { type, token } = event
|
|
35
|
+
if (token.family) {
|
|
36
|
+
const key = parseJson(token.family.subKey)
|
|
37
|
+
switch (type) {
|
|
38
|
+
case `state_creation`:
|
|
39
|
+
this.trackers.set(key, new Tracker<T>(token, store))
|
|
40
|
+
break
|
|
41
|
+
case `state_disposal`: {
|
|
42
|
+
const tracker = this.trackers.get(key)
|
|
43
|
+
if (tracker) {
|
|
44
|
+
tracker[Symbol.dispose]()
|
|
45
|
+
this.trackers.delete(key)
|
|
46
|
+
}
|
|
55
47
|
}
|
|
56
48
|
}
|
|
57
|
-
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.mutableAtoms.subject.subscribe(
|
|
52
|
+
`store=${store.config.name}::tracker-atom-family`,
|
|
53
|
+
trackerFamilyWatchesForCreationAndDisposalEvents,
|
|
58
54
|
)
|
|
59
55
|
}
|
|
60
56
|
}
|
|
@@ -17,48 +17,52 @@ import type { SignalFrom, Transceiver } from "./transceiver"
|
|
|
17
17
|
* subscribe to the transceiver's inner value. When the inner value changes,
|
|
18
18
|
* the tracker will update its own state to reflect the change.
|
|
19
19
|
*/
|
|
20
|
-
export class Tracker<T extends Transceiver<any, any>> {
|
|
21
|
-
private
|
|
20
|
+
export class Tracker<T extends Transceiver<any, any, any>> {
|
|
21
|
+
private initializeSignalAtom(
|
|
22
22
|
mutableState: MutableAtomToken<T>,
|
|
23
23
|
store: Store,
|
|
24
24
|
): RegularAtomToken<SignalFrom<T> | null> {
|
|
25
|
-
const
|
|
26
|
-
store.atoms.delete(
|
|
27
|
-
store.valueMap.delete(
|
|
25
|
+
const latestSignalStateKey = `*${mutableState.key}`
|
|
26
|
+
store.atoms.delete(latestSignalStateKey)
|
|
27
|
+
store.valueMap.delete(latestSignalStateKey)
|
|
28
28
|
const familyMetaData: FamilyMetadata | undefined = mutableState.family
|
|
29
29
|
? {
|
|
30
30
|
key: `*${mutableState.family.key}`,
|
|
31
31
|
subKey: mutableState.family.subKey,
|
|
32
32
|
}
|
|
33
33
|
: undefined
|
|
34
|
-
const
|
|
34
|
+
const latestSignalState = createRegularAtom<SignalFrom<T> | null>(
|
|
35
35
|
store,
|
|
36
36
|
{
|
|
37
|
-
key:
|
|
37
|
+
key: latestSignalStateKey,
|
|
38
38
|
default: null,
|
|
39
39
|
},
|
|
40
40
|
familyMetaData,
|
|
41
|
+
[`tracker:signal`],
|
|
41
42
|
)
|
|
42
|
-
if (store.parent?.valueMap.has(
|
|
43
|
-
const parentValue = store.parent.valueMap.get(
|
|
44
|
-
store.valueMap.set(
|
|
43
|
+
if (store.parent?.valueMap.has(latestSignalStateKey)) {
|
|
44
|
+
const parentValue = store.parent.valueMap.get(latestSignalStateKey)
|
|
45
|
+
store.valueMap.set(latestSignalStateKey, parentValue)
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
return
|
|
48
|
+
return latestSignalState
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
private unsubscribeFromInnerValue!: () => void
|
|
51
52
|
private unsubscribeFromState!: () => void
|
|
52
53
|
private captureSignalsFromCore(
|
|
53
54
|
mutableState: MutableAtomToken<T, any>,
|
|
54
|
-
|
|
55
|
+
latestSignalState: RegularAtomToken<SignalFrom<T> | null>,
|
|
55
56
|
target: Store,
|
|
56
57
|
): void {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
const stateKey = mutableState.key
|
|
59
|
+
const storeName = target.config.name
|
|
60
|
+
const storeStatus = isChildStore(target)
|
|
61
|
+
? target.transactionMeta.update.key
|
|
62
|
+
: `main`
|
|
63
|
+
const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`
|
|
60
64
|
const trackerCapturesOutboundSignal = (update: SignalFrom<T>) => {
|
|
61
|
-
setIntoStore(target,
|
|
65
|
+
setIntoStore(target, latestSignalState, update)
|
|
62
66
|
}
|
|
63
67
|
const originalInnerValue = getFromStore(target, mutableState)
|
|
64
68
|
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
@@ -83,7 +87,7 @@ export class Tracker<T extends Transceiver<any, any>> {
|
|
|
83
87
|
|
|
84
88
|
private supplySignalsToCore(
|
|
85
89
|
mutableState: MutableAtomToken<T>,
|
|
86
|
-
|
|
90
|
+
latestSignalState: RegularAtomToken<SignalFrom<T> | null>,
|
|
87
91
|
target: Store,
|
|
88
92
|
): void {
|
|
89
93
|
const subscriptionKey = `tracker:${target.config.name}:${
|
|
@@ -91,11 +95,11 @@ export class Tracker<T extends Transceiver<any, any>> {
|
|
|
91
95
|
}:${mutableState.key}`
|
|
92
96
|
subscribeToState(
|
|
93
97
|
target,
|
|
94
|
-
|
|
98
|
+
latestSignalState,
|
|
95
99
|
subscriptionKey,
|
|
96
100
|
function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
97
101
|
const timelineId = target.timelineTopics.getRelatedKey(
|
|
98
|
-
|
|
102
|
+
latestSignalState.key,
|
|
99
103
|
)
|
|
100
104
|
|
|
101
105
|
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
@@ -128,13 +132,15 @@ export class Tracker<T extends Transceiver<any, any>> {
|
|
|
128
132
|
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
129
133
|
)
|
|
130
134
|
} else {
|
|
135
|
+
const expected = mutable.cacheUpdateNumber + 1
|
|
131
136
|
target.logger.info(
|
|
132
137
|
`❌`,
|
|
133
138
|
`mutable_atom`,
|
|
134
139
|
mutableState.key,
|
|
135
|
-
`could not be updated. Expected update number
|
|
136
|
-
|
|
137
|
-
|
|
140
|
+
`could not be updated. Expected update number`,
|
|
141
|
+
expected,
|
|
142
|
+
`but got`,
|
|
143
|
+
updateNumber,
|
|
138
144
|
)
|
|
139
145
|
}
|
|
140
146
|
},
|
|
@@ -148,7 +154,7 @@ export class Tracker<T extends Transceiver<any, any>> {
|
|
|
148
154
|
|
|
149
155
|
public constructor(mutableAtomToken: MutableAtomToken<T>, store: Store) {
|
|
150
156
|
const target = newest(store)
|
|
151
|
-
const latestSignalToken = this.
|
|
157
|
+
const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target)
|
|
152
158
|
this.mutableAtomToken = mutableAtomToken
|
|
153
159
|
this.latestSignalToken = latestSignalToken
|
|
154
160
|
this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target)
|