atom.io 0.34.2 โ 0.36.0
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/eslint-plugin/index.d.ts +2 -18
- package/dist/eslint-plugin/index.d.ts.map +1 -1
- package/dist/eslint-plugin/index.js +4 -141
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/internal/index.d.ts +74 -77
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +197 -202
- package/dist/internal/index.js.map +1 -1
- package/dist/json/index.d.ts +9 -17
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js +3 -33
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts +689 -795
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +55 -23
- package/dist/main/index.js.map +1 -1
- package/dist/react/index.d.ts +4 -4
- 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 +10 -10
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +4 -4
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +5 -11
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +2 -2
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +10 -10
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +2 -2
- 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 +18 -18
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +13 -19
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/transceivers/set-rtx/index.d.ts +1 -1
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/package.json +7 -7
- package/src/eslint-plugin/index.ts +0 -1
- package/src/eslint-plugin/rules/explicit-state-types.ts +8 -1
- package/src/eslint-plugin/rules/index.ts +0 -1
- package/src/internal/atom/create-regular-atom.ts +1 -0
- package/src/internal/atom/dispose-atom.ts +1 -0
- package/src/internal/atom/index.ts +0 -1
- package/src/internal/families/find-in-store.ts +4 -5
- package/src/internal/families/get-family-of-token.ts +4 -5
- package/src/internal/families/index.ts +0 -1
- package/src/internal/families/init-family-member.ts +3 -4
- package/src/internal/families/seek-in-store.ts +4 -5
- package/src/internal/get-state/read-or-compute-value.ts +14 -2
- package/src/internal/index.ts +116 -96
- package/src/internal/ingest-updates/ingest-creation-disposal.ts +18 -15
- package/src/internal/ingest-updates/ingest-selector-update.ts +9 -5
- package/src/internal/join/get-internal-relations-from-store.ts +2 -2
- package/src/internal/join/join-internal.ts +6 -18
- package/src/internal/molecule.ts +1 -0
- package/src/internal/mutable/create-mutable-atom-family.ts +37 -21
- package/src/internal/mutable/create-mutable-atom.ts +17 -13
- package/src/internal/mutable/get-json-family.ts +7 -6
- package/src/internal/mutable/get-json-token.ts +6 -13
- package/src/internal/mutable/get-update-family.ts +7 -8
- package/src/internal/mutable/get-update-token.ts +5 -9
- package/src/internal/mutable/tracker-family.ts +10 -13
- package/src/internal/mutable/tracker.ts +66 -90
- package/src/internal/mutable/transceiver.ts +35 -8
- package/src/internal/selector/dispose-selector.ts +9 -9
- package/src/internal/selector/register-selector.ts +2 -2
- package/src/internal/set-state/copy-mutable-if-needed.ts +8 -6
- package/src/internal/set-state/reset-atom-or-selector.ts +11 -4
- package/src/internal/set-state/set-atom.ts +1 -1
- package/src/internal/store/counterfeit.ts +3 -4
- package/src/internal/store/deposit.ts +7 -9
- package/src/internal/store/store.ts +2 -2
- package/src/internal/store/withdraw.ts +7 -11
- package/src/json/entries.ts +7 -7
- package/src/json/index.ts +0 -2
- package/src/main/atom.ts +68 -127
- package/src/main/dispose-state.ts +4 -6
- package/src/main/find-state.ts +6 -13
- package/src/main/get-state.ts +0 -2
- package/src/main/index.ts +1 -176
- package/src/main/join.ts +2 -9
- package/src/main/logger.ts +7 -7
- package/src/main/reset-state.ts +0 -2
- package/src/main/selector.ts +5 -72
- package/src/main/set-state.ts +1 -4
- package/src/main/silo.ts +14 -5
- package/src/main/subscribe.ts +0 -7
- package/src/main/timeline.ts +1 -18
- package/src/main/tokens.ts +245 -0
- package/src/main/transaction.ts +28 -60
- package/src/main/validators.ts +2 -2
- package/src/react/use-json.ts +15 -25
- package/src/react-devtools/store.ts +61 -45
- package/src/realtime/shared-room-store.ts +12 -25
- package/src/realtime-client/pull-mutable-atom-family-member.ts +5 -9
- package/src/realtime-client/pull-mutable-atom.ts +5 -9
- package/src/realtime-react/use-pull-mutable-atom.ts +3 -5
- package/src/realtime-react/use-pull-mutable-family-member.ts +3 -4
- package/src/realtime-server/realtime-mutable-family-provider.ts +3 -4
- package/src/realtime-server/realtime-mutable-provider.ts +2 -3
- package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +6 -5
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +9 -18
- package/src/transceivers/set-rtx/set-rtx.ts +1 -1
- package/src/eslint-plugin/rules/synchronous-selector-dependencies.ts +0 -140
- package/src/eslint-plugin/walk.ts +0 -81
- package/src/internal/atom/create-standalone-atom.ts +0 -39
- package/src/internal/families/create-atom-family.ts +0 -38
- package/src/json/select-json-family.ts +0 -55
- package/src/json/select-json.ts +0 -19
|
@@ -4,11 +4,9 @@ import type {
|
|
|
4
4
|
MutableAtomToken,
|
|
5
5
|
UpdateHandler,
|
|
6
6
|
} from "atom.io"
|
|
7
|
-
import type { Json } from "atom.io/json"
|
|
8
|
-
import { selectJson } from "atom.io/json"
|
|
9
7
|
|
|
10
8
|
import type { MutableAtom } from ".."
|
|
11
|
-
import { resetInStore, setIntoStore } from ".."
|
|
9
|
+
import { createStandaloneSelector, resetInStore, setIntoStore } from ".."
|
|
12
10
|
import { newest } from "../lineage"
|
|
13
11
|
import { deposit, type Store } from "../store"
|
|
14
12
|
import { Subject } from "../subject"
|
|
@@ -16,14 +14,11 @@ import { subscribeToState } from "../subscribe"
|
|
|
16
14
|
import { Tracker } from "./tracker"
|
|
17
15
|
import type { Transceiver } from "./transceiver"
|
|
18
16
|
|
|
19
|
-
export function createMutableAtom<
|
|
20
|
-
T extends Transceiver<any>,
|
|
21
|
-
J extends Json.Serializable,
|
|
22
|
-
>(
|
|
17
|
+
export function createMutableAtom<T extends Transceiver<any, any>>(
|
|
23
18
|
store: Store,
|
|
24
|
-
options: MutableAtomOptions<T
|
|
19
|
+
options: MutableAtomOptions<T>,
|
|
25
20
|
family: FamilyMetadata | undefined,
|
|
26
|
-
): MutableAtomToken<T
|
|
21
|
+
): MutableAtomToken<T> {
|
|
27
22
|
store.logger.info(
|
|
28
23
|
`๐จ`,
|
|
29
24
|
`atom`,
|
|
@@ -43,8 +38,11 @@ export function createMutableAtom<
|
|
|
43
38
|
)
|
|
44
39
|
return deposit(existing)
|
|
45
40
|
}
|
|
46
|
-
const subject = new Subject<{
|
|
47
|
-
|
|
41
|
+
const subject = new Subject<{
|
|
42
|
+
newValue: T
|
|
43
|
+
oldValue: T
|
|
44
|
+
}>()
|
|
45
|
+
const newAtom: MutableAtom<T> = {
|
|
48
46
|
...options,
|
|
49
47
|
type,
|
|
50
48
|
install: (s: Store) => {
|
|
@@ -86,8 +84,14 @@ export function createMutableAtom<
|
|
|
86
84
|
|
|
87
85
|
new Tracker(token, store)
|
|
88
86
|
if (!family) {
|
|
89
|
-
|
|
87
|
+
createStandaloneSelector(store, {
|
|
88
|
+
key: `${key}:JSON`,
|
|
89
|
+
get: ({ get }) => get(token).toJSON(),
|
|
90
|
+
set: ({ set }, newValue) => {
|
|
91
|
+
set(token, options.class.fromJSON(newValue))
|
|
92
|
+
},
|
|
93
|
+
})
|
|
90
94
|
}
|
|
91
|
-
|
|
95
|
+
store.on.atomCreation.next(token)
|
|
92
96
|
return token
|
|
93
97
|
}
|
|
@@ -7,16 +7,17 @@ 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>,
|
|
11
|
-
SerializableCore extends Json.Serializable,
|
|
10
|
+
Core extends Transceiver<Json.Serializable, Json.Serializable>,
|
|
12
11
|
Key extends Canonical,
|
|
13
12
|
>(
|
|
14
|
-
mutableAtomFamily: MutableAtomFamilyToken<Core,
|
|
13
|
+
mutableAtomFamily: MutableAtomFamilyToken<Core, Key>,
|
|
15
14
|
store: Store,
|
|
16
|
-
): WritablePureSelectorFamily<
|
|
15
|
+
): WritablePureSelectorFamily<ReturnType<Core[`toJSON`]>, Key> => {
|
|
17
16
|
const target = newest(store)
|
|
18
17
|
const key = `${mutableAtomFamily.key}:JSON`
|
|
19
|
-
const jsonFamily
|
|
20
|
-
|
|
18
|
+
const jsonFamily = target.families.get(key) as WritablePureSelectorFamily<
|
|
19
|
+
ReturnType<Core[`toJSON`]>,
|
|
20
|
+
Key
|
|
21
|
+
>
|
|
21
22
|
return jsonFamily
|
|
22
23
|
}
|
|
@@ -3,27 +3,20 @@ import type {
|
|
|
3
3
|
WritablePureSelectorFamilyToken,
|
|
4
4
|
WritablePureSelectorToken,
|
|
5
5
|
} from "atom.io"
|
|
6
|
-
import type { Json } from "atom.io/json"
|
|
7
6
|
|
|
8
7
|
import { findInStore } from "../families"
|
|
9
8
|
import { newest } from "../lineage"
|
|
10
9
|
import { type Store, withdraw } from "../store"
|
|
11
|
-
import type { Transceiver } from "./transceiver"
|
|
10
|
+
import type { AsJSON, Transceiver } from "./transceiver"
|
|
12
11
|
|
|
13
|
-
export const getJsonToken = <
|
|
14
|
-
Core extends Transceiver<any>,
|
|
15
|
-
SerializableCore extends Json.Serializable,
|
|
16
|
-
>(
|
|
12
|
+
export const getJsonToken = <T extends Transceiver<any, any>>(
|
|
17
13
|
store: Store,
|
|
18
|
-
mutableAtomToken: MutableAtomToken<
|
|
19
|
-
): WritablePureSelectorToken<
|
|
14
|
+
mutableAtomToken: MutableAtomToken<T>,
|
|
15
|
+
): WritablePureSelectorToken<AsJSON<T>> => {
|
|
20
16
|
if (mutableAtomToken.family) {
|
|
21
17
|
const target = newest(store)
|
|
22
18
|
const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`
|
|
23
|
-
const jsonFamilyToken: WritablePureSelectorFamilyToken<
|
|
24
|
-
SerializableCore,
|
|
25
|
-
string
|
|
26
|
-
> = {
|
|
19
|
+
const jsonFamilyToken: WritablePureSelectorFamilyToken<AsJSON<T>, string> = {
|
|
27
20
|
key: jsonFamilyKey,
|
|
28
21
|
type: `writable_pure_selector_family`,
|
|
29
22
|
}
|
|
@@ -32,7 +25,7 @@ export const getJsonToken = <
|
|
|
32
25
|
const jsonToken = findInStore(store, family, subKey)
|
|
33
26
|
return jsonToken
|
|
34
27
|
}
|
|
35
|
-
const token: WritablePureSelectorToken<
|
|
28
|
+
const token: WritablePureSelectorToken<AsJSON<T>> = {
|
|
36
29
|
type: `writable_pure_selector`,
|
|
37
30
|
key: `${mutableAtomToken.key}:JSON`,
|
|
38
31
|
}
|
|
@@ -4,20 +4,19 @@ import type { Json } from "atom.io/json"
|
|
|
4
4
|
import type { AtomFamily } from ".."
|
|
5
5
|
import { newest } from "../lineage"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
|
-
import type {
|
|
7
|
+
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
8
8
|
|
|
9
9
|
export const getUpdateFamily = <
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Key extends string,
|
|
10
|
+
T extends Transceiver<Json.Serializable, Json.Serializable>,
|
|
11
|
+
K extends string,
|
|
13
12
|
>(
|
|
14
|
-
mutableAtomFamily: MutableAtomFamilyToken<
|
|
13
|
+
mutableAtomFamily: MutableAtomFamilyToken<T, K>,
|
|
15
14
|
store: Store,
|
|
16
|
-
): AtomFamily<
|
|
15
|
+
): AtomFamily<SignalFrom<T>, K> => {
|
|
17
16
|
const target = newest(store)
|
|
18
17
|
const key = `*${mutableAtomFamily.key}`
|
|
19
|
-
const updateFamily: AtomFamily<
|
|
18
|
+
const updateFamily: AtomFamily<SignalFrom<T>, K> = target.families.get(
|
|
20
19
|
key,
|
|
21
|
-
) as AtomFamily<
|
|
20
|
+
) as AtomFamily<SignalFrom<T>, K>
|
|
22
21
|
return updateFamily
|
|
23
22
|
}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import type { MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
2
|
-
import type { Json } from "atom.io/json"
|
|
3
2
|
|
|
4
|
-
import type {
|
|
3
|
+
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
5
4
|
|
|
6
|
-
export const getUpdateToken = <
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
>(
|
|
10
|
-
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
11
|
-
): RegularAtomToken<Signal<Core>> => {
|
|
5
|
+
export const getUpdateToken = <T extends Transceiver<any, any>>(
|
|
6
|
+
mutableAtomToken: MutableAtomToken<T>,
|
|
7
|
+
): RegularAtomToken<SignalFrom<T>> => {
|
|
12
8
|
const key = `*${mutableAtomToken.key}`
|
|
13
|
-
const updateToken: RegularAtomToken<
|
|
9
|
+
const updateToken: RegularAtomToken<SignalFrom<T>> = { type: `atom`, key }
|
|
14
10
|
if (mutableAtomToken.family) {
|
|
15
11
|
updateToken.family = {
|
|
16
12
|
key: `*${mutableAtomToken.family.key}`,
|
|
@@ -8,24 +8,21 @@ import { Tracker } from "./tracker"
|
|
|
8
8
|
import type { Transceiver } from "./transceiver"
|
|
9
9
|
|
|
10
10
|
export class FamilyTracker<
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
T extends Transceiver<any, any>,
|
|
12
|
+
K extends Canonical,
|
|
13
13
|
> {
|
|
14
|
-
private trackers: Map<
|
|
14
|
+
private trackers: Map<K, Tracker<T>> = new Map()
|
|
15
15
|
|
|
16
16
|
public readonly latestUpdateAtoms: RegularAtomFamily<
|
|
17
|
-
(
|
|
18
|
-
|
|
17
|
+
(T extends Transceiver<infer Signal, any> ? Signal : never) | null,
|
|
18
|
+
K
|
|
19
19
|
>
|
|
20
|
-
public readonly mutableAtoms: MutableAtomFamily<
|
|
20
|
+
public readonly mutableAtoms: MutableAtomFamily<T, K>
|
|
21
21
|
|
|
22
|
-
public constructor(
|
|
23
|
-
mutableAtoms: MutableAtomFamily<Core, any, FamilyMemberKey>,
|
|
24
|
-
store: Store,
|
|
25
|
-
) {
|
|
22
|
+
public constructor(mutableAtoms: MutableAtomFamily<T, K>, store: Store) {
|
|
26
23
|
const updateAtoms = createRegularAtomFamily<
|
|
27
|
-
(
|
|
28
|
-
|
|
24
|
+
(T extends Transceiver<infer Signal, any> ? Signal : never) | null,
|
|
25
|
+
K
|
|
29
26
|
>(
|
|
30
27
|
store,
|
|
31
28
|
{
|
|
@@ -44,7 +41,7 @@ export class FamilyTracker<
|
|
|
44
41
|
const key = parseJson(token.family.subKey)
|
|
45
42
|
switch (type) {
|
|
46
43
|
case `state_creation`:
|
|
47
|
-
this.trackers.set(key, new Tracker<
|
|
44
|
+
this.trackers.set(key, new Tracker<T>(token, store))
|
|
48
45
|
break
|
|
49
46
|
case `state_disposal`:
|
|
50
47
|
{
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { FamilyMetadata, MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
2
|
-
import type { Json } from "atom.io/json"
|
|
3
2
|
|
|
4
3
|
import type { Store } from ".."
|
|
5
4
|
import {
|
|
@@ -11,20 +10,18 @@ import {
|
|
|
11
10
|
} from ".."
|
|
12
11
|
import { createRegularAtom } from "../atom"
|
|
13
12
|
import { isChildStore } from "../transaction/is-root-store"
|
|
14
|
-
import type { Transceiver } from "./transceiver"
|
|
13
|
+
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* @internal Give the tracker a transceiver state and a store, and it will
|
|
18
17
|
* subscribe to the transceiver's inner value. When the inner value changes,
|
|
19
18
|
* the tracker will update its own state to reflect the change.
|
|
20
19
|
*/
|
|
21
|
-
export class Tracker<
|
|
20
|
+
export class Tracker<T extends Transceiver<any, any>> {
|
|
22
21
|
private initializeState(
|
|
23
|
-
mutableState: MutableAtomToken<
|
|
22
|
+
mutableState: MutableAtomToken<T>,
|
|
24
23
|
store: Store,
|
|
25
|
-
): RegularAtomToken<
|
|
26
|
-
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
27
|
-
> {
|
|
24
|
+
): RegularAtomToken<SignalFrom<T> | null> {
|
|
28
25
|
const latestUpdateStateKey = `*${mutableState.key}`
|
|
29
26
|
store.atoms.delete(latestUpdateStateKey)
|
|
30
27
|
store.valueMap.delete(latestUpdateStateKey)
|
|
@@ -34,9 +31,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
34
31
|
subKey: mutableState.family.subKey,
|
|
35
32
|
}
|
|
36
33
|
: undefined
|
|
37
|
-
const latestUpdateState = createRegularAtom<
|
|
38
|
-
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
39
|
-
>(
|
|
34
|
+
const latestUpdateState = createRegularAtom<SignalFrom<T> | null>(
|
|
40
35
|
store,
|
|
41
36
|
{
|
|
42
37
|
key: latestUpdateStateKey,
|
|
@@ -54,46 +49,41 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
54
49
|
|
|
55
50
|
private unsubscribeFromInnerValue!: () => void
|
|
56
51
|
private unsubscribeFromState!: () => void
|
|
57
|
-
private
|
|
58
|
-
mutableState: MutableAtomToken<
|
|
59
|
-
latestUpdateState: RegularAtomToken<
|
|
60
|
-
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
61
|
-
>,
|
|
52
|
+
private captureSignalsFromCore(
|
|
53
|
+
mutableState: MutableAtomToken<T, any>,
|
|
54
|
+
latestUpdateState: RegularAtomToken<SignalFrom<T> | null>,
|
|
62
55
|
target: Store,
|
|
63
56
|
): void {
|
|
64
57
|
const subscriptionKey = `tracker:${target.config.name}:${
|
|
65
58
|
isChildStore(target) ? target.transactionMeta.update.key : `main`
|
|
66
59
|
}:${mutableState.key}`
|
|
60
|
+
const trackerCapturesOutboundSignal = (update: SignalFrom<T>) => {
|
|
61
|
+
setIntoStore(target, latestUpdateState, update)
|
|
62
|
+
}
|
|
67
63
|
const originalInnerValue = getFromStore(target, mutableState)
|
|
68
64
|
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
69
65
|
subscriptionKey,
|
|
70
|
-
|
|
71
|
-
setIntoStore(target, latestUpdateState, update)
|
|
72
|
-
},
|
|
66
|
+
trackerCapturesOutboundSignal,
|
|
73
67
|
)
|
|
74
68
|
this.unsubscribeFromState = subscribeToState(
|
|
75
69
|
target,
|
|
76
70
|
mutableState,
|
|
77
71
|
subscriptionKey,
|
|
78
|
-
(update)
|
|
72
|
+
function trackerLooksForNewReference(update: SignalFrom<T>) {
|
|
79
73
|
if (update.newValue !== update.oldValue) {
|
|
80
74
|
this.unsubscribeFromInnerValue()
|
|
81
75
|
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
82
76
|
subscriptionKey,
|
|
83
|
-
|
|
84
|
-
setIntoStore(target, latestUpdateState, transceiverUpdate)
|
|
85
|
-
},
|
|
77
|
+
trackerCapturesOutboundSignal,
|
|
86
78
|
)
|
|
87
79
|
}
|
|
88
|
-
},
|
|
80
|
+
}.bind(this),
|
|
89
81
|
)
|
|
90
82
|
}
|
|
91
83
|
|
|
92
|
-
private
|
|
93
|
-
mutableState: MutableAtomToken<
|
|
94
|
-
latestUpdateState: RegularAtomToken<
|
|
95
|
-
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
96
|
-
>,
|
|
84
|
+
private supplySignalsToCore(
|
|
85
|
+
mutableState: MutableAtomToken<T>,
|
|
86
|
+
latestUpdateState: RegularAtomToken<SignalFrom<T> | null>,
|
|
97
87
|
target: Store,
|
|
98
88
|
): void {
|
|
99
89
|
const subscriptionKey = `tracker:${target.config.name}:${
|
|
@@ -103,85 +93,71 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
103
93
|
target,
|
|
104
94
|
latestUpdateState,
|
|
105
95
|
subscriptionKey,
|
|
106
|
-
({ newValue, oldValue })
|
|
96
|
+
function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
107
97
|
const timelineId = target.timelineTopics.getRelatedKey(
|
|
108
98
|
latestUpdateState.key,
|
|
109
99
|
)
|
|
110
100
|
|
|
111
|
-
if (timelineId) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
130
|
-
return
|
|
131
|
-
}
|
|
101
|
+
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
102
|
+
const unsubscribe = subscribeToTimeline(
|
|
103
|
+
target,
|
|
104
|
+
{ key: timelineId, type: `timeline` },
|
|
105
|
+
subscriptionKey,
|
|
106
|
+
function trackerWaitsForTimeTravelToFinish(update) {
|
|
107
|
+
unsubscribe()
|
|
108
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
109
|
+
if (update === `redo` && newValue) {
|
|
110
|
+
transceiver.do(newValue)
|
|
111
|
+
} else if (update === `undo` && oldValue) {
|
|
112
|
+
transceiver.undo(oldValue)
|
|
113
|
+
}
|
|
114
|
+
return transceiver
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
)
|
|
118
|
+
return
|
|
132
119
|
}
|
|
133
120
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
`could not be updated. Expected update number ${
|
|
154
|
-
mutable.cacheUpdateNumber + 1
|
|
155
|
-
}, but got ${updateNumber}`,
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
)
|
|
121
|
+
const mutable = getFromStore(target, mutableState)
|
|
122
|
+
const updateNumber = mutable.getUpdateNumber(newValue)
|
|
123
|
+
const eventOffset = updateNumber - mutable.cacheUpdateNumber
|
|
124
|
+
if (newValue && eventOffset === 1) {
|
|
125
|
+
setIntoStore(
|
|
126
|
+
target,
|
|
127
|
+
mutableState,
|
|
128
|
+
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
129
|
+
)
|
|
130
|
+
} else {
|
|
131
|
+
target.logger.info(
|
|
132
|
+
`โ`,
|
|
133
|
+
`mutable_atom`,
|
|
134
|
+
mutableState.key,
|
|
135
|
+
`could not be updated. Expected update number ${
|
|
136
|
+
mutable.cacheUpdateNumber + 1
|
|
137
|
+
}, but got ${updateNumber}`,
|
|
138
|
+
)
|
|
139
|
+
}
|
|
160
140
|
},
|
|
161
141
|
)
|
|
162
142
|
}
|
|
163
143
|
|
|
164
|
-
public
|
|
165
|
-
public
|
|
166
|
-
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
167
|
-
>
|
|
144
|
+
public mutableAtomToken: MutableAtomToken<T>
|
|
145
|
+
public latestSignalToken: RegularAtomToken<SignalFrom<T> | null>
|
|
168
146
|
|
|
169
147
|
public [Symbol.dispose]!: () => void
|
|
170
148
|
|
|
171
|
-
public constructor(
|
|
172
|
-
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
173
|
-
store: Store,
|
|
174
|
-
) {
|
|
175
|
-
this.mutableState = mutableState
|
|
149
|
+
public constructor(mutableAtomToken: MutableAtomToken<T>, store: Store) {
|
|
176
150
|
const target = newest(store)
|
|
177
|
-
|
|
178
|
-
this.
|
|
179
|
-
this.
|
|
180
|
-
|
|
151
|
+
const latestSignalToken = this.initializeState(mutableAtomToken, target)
|
|
152
|
+
this.mutableAtomToken = mutableAtomToken
|
|
153
|
+
this.latestSignalToken = latestSignalToken
|
|
154
|
+
this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target)
|
|
155
|
+
this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target)
|
|
156
|
+
target.trackers.set(mutableAtomToken.key, this)
|
|
181
157
|
this[Symbol.dispose] = () => {
|
|
182
158
|
this.unsubscribeFromInnerValue()
|
|
183
159
|
this.unsubscribeFromState()
|
|
184
|
-
target.trackers.delete(
|
|
160
|
+
target.trackers.delete(mutableAtomToken.key)
|
|
185
161
|
}
|
|
186
162
|
}
|
|
187
163
|
}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
import type { Json } from "atom.io/json"
|
|
2
2
|
|
|
3
|
-
export interface Transceiver<
|
|
3
|
+
export interface Transceiver<
|
|
4
|
+
S extends Json.Serializable,
|
|
5
|
+
J extends Json.Serializable,
|
|
6
|
+
> {
|
|
4
7
|
do: (update: S) => number | `OUT_OF_RANGE` | null
|
|
5
8
|
undo: (update: S) => void
|
|
6
9
|
subscribe: (key: string, fn: (update: S) => void) => () => void
|
|
7
10
|
cacheUpdateNumber: number
|
|
8
11
|
getUpdateNumber: (update: S) => number
|
|
12
|
+
toJSON: () => J
|
|
9
13
|
}
|
|
10
14
|
|
|
15
|
+
// biome-ignore format: intersection
|
|
16
|
+
export type TransceiverConstructor<
|
|
17
|
+
J extends Json.Serializable,
|
|
18
|
+
T extends Transceiver<any, J>
|
|
19
|
+
> =
|
|
20
|
+
& ( new () => T )
|
|
21
|
+
& { fromJSON: (json: J) => T }
|
|
22
|
+
|
|
11
23
|
export function isTransceiver(
|
|
12
24
|
value: unknown,
|
|
13
|
-
): value is Transceiver<Json.Serializable> {
|
|
25
|
+
): value is Transceiver<Json.Serializable, Json.Serializable> {
|
|
14
26
|
return (
|
|
15
27
|
typeof value === `object` &&
|
|
16
28
|
value !== null &&
|
|
@@ -22,17 +34,28 @@ export function isTransceiver(
|
|
|
22
34
|
|
|
23
35
|
export type TransceiverMode = `playback` | `record` | `transaction`
|
|
24
36
|
|
|
25
|
-
export type
|
|
26
|
-
infer S
|
|
37
|
+
export type SignalFrom<T extends Transceiver<any, any>> = T extends Transceiver<
|
|
38
|
+
infer S,
|
|
39
|
+
any
|
|
27
40
|
>
|
|
28
41
|
? S
|
|
29
42
|
: never
|
|
30
43
|
|
|
44
|
+
export type AsJSON<T extends Transceiver<any, any>> = T extends Transceiver<
|
|
45
|
+
any,
|
|
46
|
+
infer J
|
|
47
|
+
>
|
|
48
|
+
? J
|
|
49
|
+
: never
|
|
50
|
+
|
|
51
|
+
export type ConstructorOf<T extends Transceiver<any, any>> =
|
|
52
|
+
TransceiverConstructor<AsJSON<T>, T>
|
|
53
|
+
|
|
31
54
|
/*
|
|
32
55
|
A transceiver may also keep a list of updates that have been applied to it.
|
|
33
56
|
This is useful for undo/redo functionality, especially in the context of
|
|
34
|
-
revising history. It is a good idea to accept a cache limit in your
|
|
35
|
-
constructor, and overwrite old updates. Here's an example of how we
|
|
57
|
+
revising history. It is a good idea to accept a cache limit in your
|
|
58
|
+
constructor, and overwrite old updates. Here's an example of how we
|
|
36
59
|
might set that up:
|
|
37
60
|
|
|
38
61
|
myTransceiver = Transceiver {
|
|
@@ -48,7 +71,7 @@ myTransceiver = Transceiver {
|
|
|
48
71
|
|
|
49
72
|
CONFIRM/NO-OP
|
|
50
73
|
Update `27=del:"x"` is passed to myTransceiver.do:
|
|
51
|
-
- [updateNumber = 27, update = `del:"x"`]
|
|
74
|
+
- [updateNumber = 27, update = `del:"x"`]
|
|
52
75
|
- updateOffset = updateNumber - cacheUpdateNumber // 0
|
|
53
76
|
- eventOffset < 1 // true (we're validating the past)
|
|
54
77
|
- |eventOffset| < cacheLimit // true (we remember this update)
|
|
@@ -75,7 +98,7 @@ Update `29=del:"x"` is passed to myTransceiver.do:
|
|
|
75
98
|
- eventOffset === 1 // false (we're NOT ready to apply this update)
|
|
76
99
|
- updateIdx := cacheIdx + updateOffset // 3
|
|
77
100
|
- updateIdx %= cacheLimit // 0
|
|
78
|
-
- cache[updateIdx] = update // cache = <{ 0 => del:"x" }>
|
|
101
|
+
- cache[updateIdx] = update // cache = <{ 0 => del:"x" }>
|
|
79
102
|
- expectedUpdateNumber = cacheUpdateNumber + 1 // 28
|
|
80
103
|
- return expectedUpdateNumber // ๐คจ๐
|
|
81
104
|
|
|
@@ -110,3 +133,7 @@ Update `24=add:"z"` is passed to myTransceiver.do:
|
|
|
110
133
|
- return `OUT_OF_RANGE` // ๐ตโ๐ซ๐
|
|
111
134
|
|
|
112
135
|
*/
|
|
136
|
+
|
|
137
|
+
// The function wants a constructor C
|
|
138
|
+
// - that has a static fromJSON(json) returning an instance of C
|
|
139
|
+
// - and whose instances have toJSON() whose return type matches fromJSON's param
|
|
@@ -8,9 +8,8 @@ export function disposeSelector(
|
|
|
8
8
|
selectorToken: SelectorToken<unknown>,
|
|
9
9
|
): void {
|
|
10
10
|
const target = newest(store)
|
|
11
|
-
const { key, type } = selectorToken
|
|
12
|
-
|
|
13
|
-
if (!selector.family) {
|
|
11
|
+
const { key, type, family: familyMeta } = selectorToken
|
|
12
|
+
if (!familyMeta) {
|
|
14
13
|
store.logger.error(
|
|
15
14
|
`โ`,
|
|
16
15
|
type,
|
|
@@ -18,9 +17,9 @@ export function disposeSelector(
|
|
|
18
17
|
`Standalone selectors cannot be disposed.`,
|
|
19
18
|
)
|
|
20
19
|
} else {
|
|
21
|
-
const molecule = target.molecules.get(
|
|
20
|
+
const molecule = target.molecules.get(familyMeta.subKey)
|
|
22
21
|
if (molecule) {
|
|
23
|
-
target.moleculeData.delete(
|
|
22
|
+
target.moleculeData.delete(familyMeta.subKey, familyMeta.key)
|
|
24
23
|
}
|
|
25
24
|
let familyToken: SelectorFamilyToken<any, any>
|
|
26
25
|
switch (selectorToken.type) {
|
|
@@ -28,7 +27,7 @@ export function disposeSelector(
|
|
|
28
27
|
{
|
|
29
28
|
target.writableSelectors.delete(key)
|
|
30
29
|
familyToken = {
|
|
31
|
-
key:
|
|
30
|
+
key: familyMeta.key,
|
|
32
31
|
type: `writable_held_selector_family`,
|
|
33
32
|
}
|
|
34
33
|
const family = withdraw(store, familyToken)
|
|
@@ -43,7 +42,7 @@ export function disposeSelector(
|
|
|
43
42
|
{
|
|
44
43
|
target.writableSelectors.delete(key)
|
|
45
44
|
familyToken = {
|
|
46
|
-
key:
|
|
45
|
+
key: familyMeta.key,
|
|
47
46
|
type: `writable_pure_selector_family`,
|
|
48
47
|
}
|
|
49
48
|
const family = withdraw(store, familyToken)
|
|
@@ -58,7 +57,7 @@ export function disposeSelector(
|
|
|
58
57
|
{
|
|
59
58
|
target.readonlySelectors.delete(key)
|
|
60
59
|
familyToken = {
|
|
61
|
-
key:
|
|
60
|
+
key: familyMeta.key,
|
|
62
61
|
type: `readonly_held_selector_family`,
|
|
63
62
|
}
|
|
64
63
|
const family = withdraw(store, familyToken)
|
|
@@ -73,7 +72,7 @@ export function disposeSelector(
|
|
|
73
72
|
{
|
|
74
73
|
target.readonlySelectors.delete(key)
|
|
75
74
|
familyToken = {
|
|
76
|
-
key:
|
|
75
|
+
key: familyMeta.key,
|
|
77
76
|
type: `readonly_pure_selector_family`,
|
|
78
77
|
}
|
|
79
78
|
const family = withdraw(store, familyToken)
|
|
@@ -89,6 +88,7 @@ export function disposeSelector(
|
|
|
89
88
|
target.valueMap.delete(key)
|
|
90
89
|
target.selectorAtoms.delete(key)
|
|
91
90
|
target.selectorGraph.delete(key)
|
|
91
|
+
target.moleculeData.delete(familyMeta.key, familyMeta.subKey)
|
|
92
92
|
store.logger.info(`๐ฅ`, selectorToken.type, key, `deleted`)
|
|
93
93
|
if (isChildStore(target) && target.transactionMeta.phase === `building`) {
|
|
94
94
|
target.transactionMeta.update.updates.push({
|
|
@@ -3,9 +3,9 @@ import type {
|
|
|
3
3
|
ReadableFamilyToken,
|
|
4
4
|
ReadableToken,
|
|
5
5
|
setState,
|
|
6
|
-
SetterToolkit,
|
|
7
6
|
WritableFamilyToken,
|
|
8
7
|
WritableToken,
|
|
8
|
+
WriterToolkit,
|
|
9
9
|
} from "atom.io"
|
|
10
10
|
import type { Json } from "atom.io/json"
|
|
11
11
|
|
|
@@ -27,7 +27,7 @@ export const registerSelector = (
|
|
|
27
27
|
| `writable_pure_selector`,
|
|
28
28
|
selectorKey: string,
|
|
29
29
|
covered: Set<string>,
|
|
30
|
-
):
|
|
30
|
+
): WriterToolkit => ({
|
|
31
31
|
get: (
|
|
32
32
|
...params:
|
|
33
33
|
| [ReadableFamilyToken<any, any>, Json.Serializable]
|
|
@@ -2,12 +2,14 @@ import type { MutableAtom, Transceiver } from ".."
|
|
|
2
2
|
import { Tracker } from "../mutable"
|
|
3
3
|
import type { Store } from "../store"
|
|
4
4
|
|
|
5
|
-
export function copyMutableIfNeeded<T extends Transceiver<any>>(
|
|
5
|
+
export function copyMutableIfNeeded<T extends Transceiver<any, any>>(
|
|
6
6
|
target: Store,
|
|
7
|
-
atom: MutableAtom<T
|
|
7
|
+
atom: MutableAtom<T>,
|
|
8
8
|
origin: Store,
|
|
9
9
|
): T {
|
|
10
|
-
const originValue = origin.valueMap.get(atom.key)
|
|
10
|
+
const originValue = origin.valueMap.get(atom.key) as
|
|
11
|
+
| Transceiver<any, any>
|
|
12
|
+
| undefined
|
|
11
13
|
const targetValue = target.valueMap.get(atom.key)
|
|
12
14
|
|
|
13
15
|
if (originValue !== targetValue) {
|
|
@@ -15,12 +17,12 @@ export function copyMutableIfNeeded<T extends Transceiver<any>>(
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
if (originValue === undefined) {
|
|
18
|
-
return atom.
|
|
20
|
+
return new atom.class()
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
origin.logger.info(`๐`, `atom`, atom.key, `copying`)
|
|
22
|
-
const jsonValue =
|
|
23
|
-
const copiedValue = atom.
|
|
24
|
+
const jsonValue = originValue.toJSON()
|
|
25
|
+
const copiedValue = atom.class.fromJSON(jsonValue)
|
|
24
26
|
target.valueMap.set(atom.key, copiedValue)
|
|
25
27
|
new Tracker(atom, origin)
|
|
26
28
|
return copiedValue
|