atom.io 0.15.5 → 0.16.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/data/dist/index.cjs +20 -22
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +6 -6
- package/data/dist/index.js +21 -23
- package/data/dist/index.js.map +1 -1
- package/data/src/dict.ts +6 -7
- package/data/src/join.ts +23 -23
- package/data/src/struct-family.ts +2 -2
- package/data/src/struct.ts +4 -5
- package/dist/index.cjs +12 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +67 -60
- package/dist/index.js +13 -6
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +912 -886
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +157 -162
- package/internal/dist/index.js +487 -460
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-regular-atom.ts +9 -12
- package/internal/src/atom/create-standalone-atom.ts +33 -0
- package/internal/src/atom/delete-atom.ts +5 -2
- package/internal/src/atom/index.ts +1 -16
- package/internal/src/atom/is-default.ts +0 -1
- package/internal/src/caching.ts +6 -3
- package/internal/src/families/create-atom-family.ts +11 -7
- package/internal/src/families/create-readonly-selector-family.ts +4 -3
- package/internal/src/families/create-regular-atom-family.ts +12 -27
- package/internal/src/families/create-selector-family.ts +13 -49
- package/internal/src/families/create-writable-selector-family.ts +51 -0
- package/internal/src/index.ts +44 -3
- package/internal/src/lineage.ts +0 -7
- package/internal/src/mutable/create-mutable-atom-family.ts +61 -15
- package/internal/src/mutable/create-mutable-atom.ts +70 -25
- package/internal/src/mutable/get-json-family.ts +4 -5
- package/internal/src/mutable/get-json-token.ts +6 -3
- package/internal/src/mutable/get-update-token.ts +3 -3
- package/internal/src/mutable/index.ts +1 -7
- package/internal/src/mutable/is-mutable.ts +6 -7
- package/internal/src/mutable/tracker-family.ts +4 -4
- package/internal/src/mutable/tracker.ts +6 -6
- package/internal/src/read-or-compute-value.ts +6 -3
- package/internal/src/selector/create-readonly-selector.ts +2 -3
- package/internal/src/selector/create-standalone-selector.ts +32 -0
- package/internal/src/selector/{create-read-write-selector.ts → create-writable-selector.ts} +12 -9
- package/internal/src/selector/delete-selector.ts +2 -2
- package/internal/src/selector/index.ts +3 -1
- package/internal/src/selector/trace-selector-atoms.ts +3 -2
- package/internal/src/selector/update-selector-atoms.ts +1 -1
- package/internal/src/set-state/copy-mutable-if-needed.ts +5 -6
- package/internal/src/set-state/copy-mutable-in-transaction.ts +4 -36
- package/internal/src/set-state/emit-update.ts +2 -3
- package/internal/src/set-state/evict-downstream.ts +1 -1
- package/internal/src/set-state/set-atom-or-selector.ts +3 -3
- package/internal/src/set-state/set-atom.ts +8 -4
- package/internal/src/set-state/stow-update.ts +1 -1
- package/internal/src/store/deposit.ts +25 -13
- package/internal/src/store/store.ts +21 -21
- package/internal/src/store/withdraw-new-family-member.ts +16 -9
- package/internal/src/store/withdraw.ts +43 -19
- package/internal/src/subscribe/recall-state.ts +2 -6
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +39 -41
- package/internal/src/subscribe/subscribe-to-state.ts +3 -1
- package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
- package/internal/src/timeline/create-timeline.ts +19 -22
- package/introspection/dist/index.cjs +4 -8
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +5 -5
- package/introspection/dist/index.js +5 -9
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +4 -5
- package/introspection/src/attach-selector-index.ts +4 -5
- package/introspection/src/attach-timeline-index.ts +6 -3
- package/introspection/src/attach-transaction-index.ts +6 -3
- package/introspection/src/index.ts +9 -5
- package/json/dist/index.cjs +3 -4
- package/json/dist/index.cjs.map +1 -1
- package/json/dist/index.d.ts +4 -3
- package/json/dist/index.js +4 -5
- package/json/dist/index.js.map +1 -1
- package/json/src/select-json-family.ts +24 -4
- package/json/src/select-json.ts +3 -4
- package/package.json +2 -2
- package/react-devtools/dist/index.cjs.map +1 -1
- package/react-devtools/dist/index.d.ts +9 -9
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/src/StateIndex.tsx +18 -10
- package/react-devtools/src/TimelineIndex.tsx +6 -2
- package/react-devtools/src/TransactionIndex.tsx +2 -2
- package/realtime-client/dist/index.cjs +27 -13
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +6 -4
- package/realtime-client/dist/index.js +20 -7
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/index.ts +4 -3
- package/realtime-client/src/server-action.ts +2 -55
- package/realtime-client/src/sync-server-action.ts +75 -0
- package/realtime-react/dist/index.cjs +22 -13
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +3 -1
- package/realtime-react/dist/index.js +20 -12
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/index.ts +1 -0
- package/realtime-react/src/use-server-action.ts +2 -4
- package/realtime-react/src/use-sync-server-action.ts +19 -0
- package/realtime-server/dist/index.cjs +83 -81
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.ts +8 -8
- package/realtime-server/dist/index.js +58 -56
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/src/index.ts +15 -1
- package/realtime-server/src/{hook-composition/receive-transaction.ts → realtime-action-receiver.ts} +6 -2
- package/realtime-server/src/{hook-composition/sync-transaction.ts → realtime-action-synchronizer.ts} +10 -43
- package/realtime-server/src/{hook-composition/expose-family.ts → realtime-family-provider.ts} +9 -23
- package/realtime-server/src/{hook-composition/expose-mutable-family.ts → realtime-mutable-family-provider.ts} +4 -4
- package/realtime-server/src/{hook-composition/expose-mutable.ts → realtime-mutable-provider.ts} +4 -5
- package/realtime-server/src/realtime-server-store.ts +39 -0
- package/realtime-server/src/{hook-composition/expose-single.ts → realtime-state-provider.ts} +7 -8
- package/realtime-server/src/{hook-composition/receive-state.ts → realtime-state-receiver.ts} +7 -4
- package/src/atom.ts +39 -24
- package/src/find-state.ts +20 -19
- package/src/index.ts +41 -28
- package/src/logger.ts +1 -0
- package/src/selector.ts +31 -16
- package/src/silo.ts +45 -6
- package/src/subscribe.ts +1 -0
- package/src/validators.ts +35 -25
- package/internal/src/atom/create-atom.ts +0 -21
- package/internal/src/mutable/get-update-family.ts +0 -23
- package/internal/src/selector/create-selector.ts +0 -65
- package/realtime-server/src/hook-composition/index.ts +0 -15
- /package/realtime-client/src/{pull.ts → pull-state.ts} +0 -0
- /package/realtime-client/src/{push.ts → push-state.ts} +0 -0
- /package/realtime-client/src/{realtime-state.ts → realtime-client-store.ts} +0 -0
|
@@ -1,50 +1,95 @@
|
|
|
1
|
+
import type { UpdateHandler } from "atom.io"
|
|
1
2
|
import type {
|
|
2
3
|
FamilyMetadata,
|
|
3
4
|
MutableAtomOptions,
|
|
4
5
|
MutableAtomToken,
|
|
5
6
|
} from "atom.io"
|
|
7
|
+
import { setState } from "atom.io"
|
|
6
8
|
import type { Json } from "atom.io/json"
|
|
7
9
|
import { selectJson } from "atom.io/json"
|
|
8
10
|
|
|
9
|
-
import {
|
|
11
|
+
import { type MutableAtom, cacheValue } from ".."
|
|
12
|
+
import { createRegularAtom, markAtomAsDefault } from "../atom"
|
|
10
13
|
import { newest } from "../lineage"
|
|
11
|
-
import type
|
|
14
|
+
import { type Store, deposit } from "../store"
|
|
15
|
+
import { Subject } from "../subject"
|
|
12
16
|
import { subscribeToState } from "../subscribe"
|
|
13
17
|
import { Tracker } from "./tracker"
|
|
14
18
|
import type { Transceiver } from "./transceiver"
|
|
15
19
|
|
|
16
20
|
export function createMutableAtom<
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
T extends Transceiver<any>,
|
|
22
|
+
J extends Json.Serializable,
|
|
19
23
|
>(
|
|
20
|
-
options: MutableAtomOptions<
|
|
24
|
+
options: MutableAtomOptions<T, J>,
|
|
21
25
|
family: FamilyMetadata | undefined,
|
|
22
26
|
store: Store,
|
|
23
|
-
): MutableAtomToken<
|
|
27
|
+
): MutableAtomToken<T, J> {
|
|
24
28
|
store.logger.info(
|
|
25
|
-
|
|
29
|
+
`🔨`,
|
|
26
30
|
`atom`,
|
|
27
31
|
options.key,
|
|
28
32
|
`creating in store "${store.config.name}"`,
|
|
29
33
|
)
|
|
30
|
-
const coreState = createRegularAtom<Core>(options, family, store)
|
|
31
|
-
new Tracker(coreState, store)
|
|
32
|
-
const jsonState = selectJson(coreState, options, store)
|
|
33
34
|
const target = newest(store)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const existing = target.atoms.get(options.key)
|
|
36
|
+
if (existing && existing.type === `mutable_atom`) {
|
|
37
|
+
store.logger.error(
|
|
38
|
+
`❌`,
|
|
39
|
+
`atom`,
|
|
40
|
+
options.key,
|
|
41
|
+
`Tried to create atom, but it already exists in the store.`,
|
|
42
|
+
)
|
|
43
|
+
return deposit(existing)
|
|
44
|
+
}
|
|
45
|
+
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
46
|
+
const newAtom: MutableAtom<T, J> = {
|
|
47
|
+
...options,
|
|
48
|
+
type: `mutable_atom`,
|
|
49
|
+
install: (store: Store) => {
|
|
50
|
+
store.logger.info(
|
|
51
|
+
`🛠️`,
|
|
52
|
+
`atom`,
|
|
53
|
+
options.key,
|
|
54
|
+
`installing in store "${store.config.name}"`,
|
|
55
|
+
)
|
|
56
|
+
return createMutableAtom(options, family, store)
|
|
41
57
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
)
|
|
49
|
-
|
|
58
|
+
subject,
|
|
59
|
+
} as const
|
|
60
|
+
if (family) {
|
|
61
|
+
newAtom.family = family
|
|
62
|
+
}
|
|
63
|
+
const initialValue = options.default()
|
|
64
|
+
target.atoms.set(newAtom.key, newAtom)
|
|
65
|
+
markAtomAsDefault(options.key, store)
|
|
66
|
+
cacheValue(options.key, initialValue, subject, target)
|
|
67
|
+
const token = deposit(newAtom)
|
|
68
|
+
if (options.effects) {
|
|
69
|
+
let effectIndex = 0
|
|
70
|
+
const cleanupFunctions: (() => void)[] = []
|
|
71
|
+
for (const effect of options.effects) {
|
|
72
|
+
const cleanup = effect({
|
|
73
|
+
setSelf: (next) => setState(token, next, store),
|
|
74
|
+
onSet: (handle: UpdateHandler<T>) =>
|
|
75
|
+
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
76
|
+
})
|
|
77
|
+
if (cleanup) {
|
|
78
|
+
cleanupFunctions.push(cleanup)
|
|
79
|
+
}
|
|
80
|
+
++effectIndex
|
|
81
|
+
}
|
|
82
|
+
newAtom.cleanup = () => {
|
|
83
|
+
for (const cleanup of cleanupFunctions) {
|
|
84
|
+
cleanup()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
new Tracker(token, store)
|
|
90
|
+
selectJson(token, options, store)
|
|
91
|
+
|
|
92
|
+
store.on.atomCreation.next(token)
|
|
93
|
+
|
|
94
|
+
return token
|
|
50
95
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MutableAtomFamily,
|
|
1
|
+
import type { MutableAtomFamily, WritableSelectorFamily } from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
|
|
4
4
|
import { newest } from "../lineage"
|
|
@@ -12,11 +12,10 @@ export const getJsonFamily = <
|
|
|
12
12
|
>(
|
|
13
13
|
mutableAtomFamily: MutableAtomFamily<Core, SerializableCore, Key>,
|
|
14
14
|
store: Store,
|
|
15
|
-
):
|
|
15
|
+
): WritableSelectorFamily<SerializableCore, Key> => {
|
|
16
16
|
const target = newest(store)
|
|
17
17
|
const key = `${mutableAtomFamily.key}:JSON`
|
|
18
|
-
const jsonFamily:
|
|
19
|
-
key,
|
|
20
|
-
) as SelectorFamily<SerializableCore, Key>
|
|
18
|
+
const jsonFamily: WritableSelectorFamily<SerializableCore, Key> =
|
|
19
|
+
target.families.get(key) as WritableSelectorFamily<SerializableCore, Key>
|
|
21
20
|
return jsonFamily
|
|
22
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MutableAtomToken,
|
|
1
|
+
import type { MutableAtomToken, WritableSelectorToken } from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
|
|
4
4
|
import type { Transceiver } from "./transceiver"
|
|
@@ -8,11 +8,14 @@ export const getJsonToken = <
|
|
|
8
8
|
SerializableCore extends Json.Serializable,
|
|
9
9
|
>(
|
|
10
10
|
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
11
|
-
):
|
|
11
|
+
): WritableSelectorToken<SerializableCore> => {
|
|
12
12
|
const key = mutableAtomToken.family
|
|
13
13
|
? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})`
|
|
14
14
|
: `${mutableAtomToken.key}:JSON`
|
|
15
|
-
const jsonToken:
|
|
15
|
+
const jsonToken: WritableSelectorToken<SerializableCore> = {
|
|
16
|
+
type: `selector`,
|
|
17
|
+
key,
|
|
18
|
+
}
|
|
16
19
|
if (mutableAtomToken.family) {
|
|
17
20
|
jsonToken.family = {
|
|
18
21
|
key: `${mutableAtomToken.family.key}:JSON`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
import type { Signal, Transceiver } from "./transceiver"
|
|
4
4
|
|
|
@@ -7,9 +7,9 @@ export const getUpdateToken = <
|
|
|
7
7
|
SerializableCore extends Json.Serializable,
|
|
8
8
|
>(
|
|
9
9
|
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
10
|
-
):
|
|
10
|
+
): RegularAtomToken<Signal<Core>> => {
|
|
11
11
|
const key = `*${mutableAtomToken.key}`
|
|
12
|
-
const updateToken:
|
|
12
|
+
const updateToken: RegularAtomToken<Signal<Core>> = { type: `atom`, key }
|
|
13
13
|
if (mutableAtomToken.family) {
|
|
14
14
|
updateToken.family = {
|
|
15
15
|
key: `*${mutableAtomToken.family.key}`,
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import type { Atom } from "../atom"
|
|
2
|
-
|
|
3
1
|
export * from "./create-mutable-atom"
|
|
4
2
|
export * from "./create-mutable-atom-family"
|
|
5
3
|
export * from "./get-json-family"
|
|
6
4
|
export * from "./get-json-token"
|
|
7
5
|
export * from "./get-update-token"
|
|
8
|
-
export * from "./
|
|
6
|
+
export * from "./is-mutable"
|
|
9
7
|
export * from "./tracker"
|
|
10
8
|
export * from "./tracker-family"
|
|
11
9
|
export * from "./transceiver"
|
|
12
|
-
|
|
13
|
-
export interface MutableAtom<T> extends Atom<T> {
|
|
14
|
-
mutable: true
|
|
15
|
-
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import type { AtomFamily, MutableAtomFamily } from "atom.io"
|
|
2
2
|
|
|
3
|
-
import type { MutableAtom } from "
|
|
4
|
-
import type { Atom } from "../atom"
|
|
3
|
+
import type { Atom, MutableAtom } from ".."
|
|
5
4
|
|
|
6
|
-
export function isMutable(atom: Atom<any>): atom is MutableAtom<any>
|
|
5
|
+
export function isMutable(atom: Atom<any>): atom is MutableAtom<any, any>
|
|
7
6
|
export function isMutable(
|
|
8
7
|
family: AtomFamily<any, any>,
|
|
9
8
|
): family is MutableAtomFamily<any, any, any>
|
|
10
9
|
export function isMutable(
|
|
11
10
|
atomOrTokenOrFamily: Atom<any> | AtomFamily<any, any>,
|
|
12
11
|
): boolean {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
return (
|
|
13
|
+
atomOrTokenOrFamily.type === `mutable_atom` ||
|
|
14
|
+
atomOrTokenOrFamily.type === `mutable_atom_family`
|
|
15
|
+
)
|
|
17
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MutableAtomFamily, RegularAtomFamily } from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
import { parseJson } from "atom.io/json"
|
|
4
4
|
|
|
@@ -15,14 +15,14 @@ export class FamilyTracker<
|
|
|
15
15
|
? Signal
|
|
16
16
|
: never
|
|
17
17
|
|
|
18
|
-
public readonly findLatestUpdateState:
|
|
18
|
+
public readonly findLatestUpdateState: RegularAtomFamily<
|
|
19
19
|
typeof this.Update | null,
|
|
20
20
|
FamilyMemberKey
|
|
21
21
|
>
|
|
22
|
-
public readonly findMutableState:
|
|
22
|
+
public readonly findMutableState: MutableAtomFamily<Core, any, FamilyMemberKey>
|
|
23
23
|
|
|
24
24
|
public constructor(
|
|
25
|
-
findMutableState:
|
|
25
|
+
findMutableState: MutableAtomFamily<Core, any, FamilyMemberKey>,
|
|
26
26
|
store: Store,
|
|
27
27
|
) {
|
|
28
28
|
this.findLatestUpdateState = createRegularAtomFamily<
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FamilyMetadata, MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
2
2
|
import { getState, setState } from "atom.io"
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
18
18
|
private initializeState(
|
|
19
19
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
20
20
|
store: Store,
|
|
21
|
-
):
|
|
21
|
+
): RegularAtomToken<typeof this.Update | null> {
|
|
22
22
|
const latestUpdateStateKey = `*${mutableState.key}`
|
|
23
23
|
store.atoms.delete(latestUpdateStateKey)
|
|
24
24
|
store.valueMap.delete(latestUpdateStateKey)
|
|
@@ -49,8 +49,8 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
49
49
|
private unsubscribeFromInnerValue: () => void
|
|
50
50
|
private unsubscribeFromState: () => void
|
|
51
51
|
private observeCore(
|
|
52
|
-
mutableState: MutableAtomToken<Mutable,
|
|
53
|
-
latestUpdateState:
|
|
52
|
+
mutableState: MutableAtomToken<Mutable, any>,
|
|
53
|
+
latestUpdateState: RegularAtomToken<typeof this.Update | null>,
|
|
54
54
|
store: Store,
|
|
55
55
|
): void {
|
|
56
56
|
const originalInnerValue = getState(mutableState, store)
|
|
@@ -112,7 +112,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
112
112
|
|
|
113
113
|
private updateCore<Core extends Transceiver<any>>(
|
|
114
114
|
mutableState: MutableAtomToken<Core, Json.Serializable>,
|
|
115
|
-
latestUpdateState:
|
|
115
|
+
latestUpdateState: RegularAtomToken<typeof this.Update | null>,
|
|
116
116
|
store: Store,
|
|
117
117
|
): void {
|
|
118
118
|
subscribeToState(
|
|
@@ -174,7 +174,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
public mutableState: MutableAtomToken<Mutable, Json.Serializable>
|
|
177
|
-
public latestUpdateState:
|
|
177
|
+
public latestUpdateState: RegularAtomToken<typeof this.Update | null>
|
|
178
178
|
|
|
179
179
|
public dispose: () => void
|
|
180
180
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReadableState } from "."
|
|
2
2
|
import { readCachedValue } from "./caching"
|
|
3
3
|
import type { Store } from "./store"
|
|
4
4
|
|
|
5
|
-
export const readOrComputeValue = <T>(
|
|
5
|
+
export const readOrComputeValue = <T>(
|
|
6
|
+
state: ReadableState<T>,
|
|
7
|
+
target: Store,
|
|
8
|
+
): T => {
|
|
6
9
|
if (target.valueMap.has(state.key)) {
|
|
7
10
|
target.logger.info(`📖`, state.type, state.key, `reading cached value`)
|
|
8
11
|
return readCachedValue(state, target)
|
|
9
12
|
}
|
|
10
|
-
if (state.type !== `atom`) {
|
|
13
|
+
if (state.type !== `atom` && state.type !== `mutable_atom`) {
|
|
11
14
|
target.logger.info(`🧮`, state.type, state.key, `computing value`)
|
|
12
15
|
return state.get()
|
|
13
16
|
}
|
|
@@ -4,12 +4,11 @@ import type {
|
|
|
4
4
|
ReadonlySelectorToken,
|
|
5
5
|
} from "atom.io"
|
|
6
6
|
|
|
7
|
+
import type { ReadonlySelector } from ".."
|
|
7
8
|
import { cacheValue } from "../caching"
|
|
8
9
|
import { newest } from "../lineage"
|
|
9
10
|
import type { Store } from "../store"
|
|
10
11
|
import { Subject } from "../subject"
|
|
11
|
-
import type { ReadonlySelector } from "./create-selector"
|
|
12
|
-
import { createSelector } from "./create-selector"
|
|
13
12
|
import { registerSelector } from "./register-selector"
|
|
14
13
|
|
|
15
14
|
export const createReadonlySelector = <T>(
|
|
@@ -30,7 +29,7 @@ export const createReadonlySelector = <T>(
|
|
|
30
29
|
const readonlySelector: ReadonlySelector<T> = {
|
|
31
30
|
...options,
|
|
32
31
|
subject,
|
|
33
|
-
install: (s: Store) =>
|
|
32
|
+
install: (s: Store) => createReadonlySelector(options, family, s),
|
|
34
33
|
get: getSelf,
|
|
35
34
|
type: `readonly_selector`,
|
|
36
35
|
...(family && { family }),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FamilyMetadata,
|
|
3
|
+
ReadonlySelectorOptions,
|
|
4
|
+
ReadonlySelectorToken,
|
|
5
|
+
WritableSelectorOptions,
|
|
6
|
+
WritableSelectorToken,
|
|
7
|
+
} from "atom.io"
|
|
8
|
+
|
|
9
|
+
import type { Store } from "../store"
|
|
10
|
+
import type { Subject } from "../subject"
|
|
11
|
+
import { createReadonlySelector } from "./create-readonly-selector"
|
|
12
|
+
import { createWritableSelector } from "./create-writable-selector"
|
|
13
|
+
|
|
14
|
+
export function createStandaloneSelector<T>(
|
|
15
|
+
options: WritableSelectorOptions<T>,
|
|
16
|
+
store: Store,
|
|
17
|
+
): WritableSelectorToken<T>
|
|
18
|
+
export function createStandaloneSelector<T>(
|
|
19
|
+
options: ReadonlySelectorOptions<T>,
|
|
20
|
+
store: Store,
|
|
21
|
+
): ReadonlySelectorToken<T>
|
|
22
|
+
export function createStandaloneSelector<T>(
|
|
23
|
+
options: ReadonlySelectorOptions<T> | WritableSelectorOptions<T>,
|
|
24
|
+
store: Store,
|
|
25
|
+
): ReadonlySelectorToken<T> | WritableSelectorToken<T> {
|
|
26
|
+
const isWritable = `set` in options
|
|
27
|
+
|
|
28
|
+
if (isWritable) {
|
|
29
|
+
return createWritableSelector(options, undefined, store)
|
|
30
|
+
}
|
|
31
|
+
return createReadonlySelector(options, undefined, store)
|
|
32
|
+
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
FamilyMetadata,
|
|
3
|
+
WritableSelectorOptions,
|
|
4
|
+
WritableSelectorToken,
|
|
5
|
+
} from "atom.io"
|
|
2
6
|
|
|
7
|
+
import type { WritableSelector } from ".."
|
|
3
8
|
import { cacheValue } from "../caching"
|
|
4
9
|
import { newest } from "../lineage"
|
|
5
10
|
import { markDone } from "../operation"
|
|
6
11
|
import { become } from "../set-state/become"
|
|
7
12
|
import type { Store } from "../store"
|
|
8
13
|
import { Subject } from "../subject"
|
|
9
|
-
import type { Selector } from "./create-selector"
|
|
10
|
-
import { createSelector } from "./create-selector"
|
|
11
14
|
import { registerSelector } from "./register-selector"
|
|
12
15
|
|
|
13
|
-
export const
|
|
14
|
-
options:
|
|
16
|
+
export const createWritableSelector = <T>(
|
|
17
|
+
options: WritableSelectorOptions<T>,
|
|
15
18
|
family: FamilyMetadata | undefined,
|
|
16
19
|
store: Store,
|
|
17
|
-
):
|
|
20
|
+
): WritableSelectorToken<T> => {
|
|
18
21
|
const target = newest(store)
|
|
19
22
|
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
20
23
|
const transactors = registerSelector(options.key, store)
|
|
@@ -47,10 +50,10 @@ export const createReadWriteSelector = <T>(
|
|
|
47
50
|
}
|
|
48
51
|
options.set(transactors, newValue)
|
|
49
52
|
}
|
|
50
|
-
const mySelector:
|
|
53
|
+
const mySelector: WritableSelector<T> = {
|
|
51
54
|
...options,
|
|
52
55
|
subject,
|
|
53
|
-
install: (s: Store) =>
|
|
56
|
+
install: (s: Store) => createWritableSelector(options, family, s),
|
|
54
57
|
get: getSelf,
|
|
55
58
|
set: setSelf,
|
|
56
59
|
type: `selector`,
|
|
@@ -59,7 +62,7 @@ export const createReadWriteSelector = <T>(
|
|
|
59
62
|
target.selectors.set(options.key, mySelector)
|
|
60
63
|
const initialValue = getSelf()
|
|
61
64
|
store.logger.info(`✨`, mySelector.type, mySelector.key, `=`, initialValue)
|
|
62
|
-
const token:
|
|
65
|
+
const token: WritableSelectorToken<T> = {
|
|
63
66
|
key: options.key,
|
|
64
67
|
type: `selector`,
|
|
65
68
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { ReadonlySelectorToken,
|
|
1
|
+
import type { ReadonlySelectorToken, WritableSelectorToken } from "atom.io"
|
|
2
2
|
|
|
3
3
|
import { newest } from ".."
|
|
4
4
|
import type { Store } from ".."
|
|
5
5
|
|
|
6
6
|
export function deleteSelector(
|
|
7
|
-
selectorToken: ReadonlySelectorToken<unknown> |
|
|
7
|
+
selectorToken: ReadonlySelectorToken<unknown> | WritableSelectorToken<unknown>,
|
|
8
8
|
store: Store,
|
|
9
9
|
): void {
|
|
10
10
|
const target = newest(store)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export * from "./create-selector"
|
|
1
|
+
export * from "./create-readonly-selector"
|
|
2
|
+
export * from "./create-standalone-selector"
|
|
3
|
+
export * from "./create-writable-selector"
|
|
2
4
|
export * from "./delete-selector"
|
|
3
5
|
export * from "./get-selector-dependency-keys"
|
|
4
6
|
export * from "./register-selector"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Store } from ".."
|
|
1
|
+
import type { Selector, Store } from ".."
|
|
2
2
|
import type { AtomKey, StateKey } from "../keys"
|
|
3
3
|
import { isAtomKey } from "../keys"
|
|
4
4
|
import { getSelectorDependencyKeys } from "./get-selector-dependency-keys"
|
|
@@ -38,9 +38,10 @@ export const traceSelectorAtoms = (
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export const traceAllSelectorAtoms = (
|
|
41
|
-
|
|
41
|
+
selector: Selector<any>,
|
|
42
42
|
store: Store,
|
|
43
43
|
): AtomKey<unknown>[] => {
|
|
44
|
+
const selectorKey = selector.key
|
|
44
45
|
const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store)
|
|
45
46
|
return directDependencyKeys.flatMap((depKey) =>
|
|
46
47
|
isAtomKey(depKey, store)
|
|
@@ -10,7 +10,7 @@ export const updateSelectorAtoms = (
|
|
|
10
10
|
store: Store,
|
|
11
11
|
): void => {
|
|
12
12
|
const target = newest(store)
|
|
13
|
-
if (dependency.type === `atom`) {
|
|
13
|
+
if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
|
|
14
14
|
target.selectorAtoms.set({
|
|
15
15
|
selectorKey,
|
|
16
16
|
atomKey: dependency.key,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { JsonInterface } from "atom.io/json"
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { MutableAtom, Transceiver } from ".."
|
|
4
4
|
import { Tracker } from "../mutable"
|
|
5
5
|
import type { Store } from "../store"
|
|
6
6
|
|
|
7
|
-
export function copyMutableIfNeeded<T
|
|
8
|
-
atom:
|
|
9
|
-
transform: JsonInterface<T>,
|
|
7
|
+
export function copyMutableIfNeeded<T extends Transceiver<any>>(
|
|
8
|
+
atom: MutableAtom<T, any>,
|
|
10
9
|
origin: Store,
|
|
11
10
|
target: Store,
|
|
12
11
|
): T {
|
|
@@ -14,8 +13,8 @@ export function copyMutableIfNeeded<T>(
|
|
|
14
13
|
const targetValue = target.valueMap.get(atom.key)
|
|
15
14
|
if (originValue === targetValue) {
|
|
16
15
|
origin.logger.info(`📃`, `atom`, `${atom.key}`, `copying`)
|
|
17
|
-
const jsonValue =
|
|
18
|
-
const copiedValue =
|
|
16
|
+
const jsonValue = atom.toJson(originValue)
|
|
17
|
+
const copiedValue = atom.fromJson(jsonValue)
|
|
19
18
|
target.valueMap.set(atom.key, copiedValue)
|
|
20
19
|
new Tracker(atom, origin)
|
|
21
20
|
return copiedValue
|
|
@@ -1,51 +1,19 @@
|
|
|
1
|
-
import type { AtomFamily } from "atom.io"
|
|
2
|
-
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
1
|
import { newest } from ".."
|
|
4
|
-
import type { Store } from ".."
|
|
5
|
-
import type { Atom } from "../atom"
|
|
2
|
+
import type { Atom, Store } from ".."
|
|
6
3
|
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
7
4
|
|
|
8
5
|
export function copyMutableIfWithinTransaction<T>(
|
|
9
6
|
oldValue: T,
|
|
10
|
-
atom: Atom<T
|
|
7
|
+
atom: Atom<T>,
|
|
11
8
|
store: Store,
|
|
12
9
|
): T {
|
|
13
10
|
const target = newest(store)
|
|
14
11
|
const parent = target.parent
|
|
15
12
|
if (parent !== null) {
|
|
16
|
-
if (`
|
|
17
|
-
const
|
|
18
|
-
if (family && family.type === `atom_family`) {
|
|
19
|
-
const result = copyMutableFamilyMemberWithinTransaction<T>(
|
|
20
|
-
atom,
|
|
21
|
-
family,
|
|
22
|
-
parent,
|
|
23
|
-
target,
|
|
24
|
-
)
|
|
25
|
-
if (result) {
|
|
26
|
-
return result
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (`toJson` in atom && `fromJson` in atom) {
|
|
31
|
-
const copiedValue = copyMutableIfNeeded(atom, atom, parent, target)
|
|
13
|
+
if (atom.type === `mutable_atom`) {
|
|
14
|
+
const copiedValue = copyMutableIfNeeded(atom, parent, target)
|
|
32
15
|
return copiedValue
|
|
33
16
|
}
|
|
34
17
|
}
|
|
35
18
|
return oldValue
|
|
36
19
|
}
|
|
37
|
-
|
|
38
|
-
export function copyMutableFamilyMemberWithinTransaction<T>(
|
|
39
|
-
atom: Atom<T>,
|
|
40
|
-
family:
|
|
41
|
-
| AtomFamily<T, any>
|
|
42
|
-
| (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
|
|
43
|
-
origin: Store,
|
|
44
|
-
target: Store,
|
|
45
|
-
): T | null {
|
|
46
|
-
if (`toJson` in family && `fromJson` in family) {
|
|
47
|
-
const copyCreated = copyMutableIfNeeded(atom, family, origin, target)
|
|
48
|
-
return copyCreated
|
|
49
|
-
}
|
|
50
|
-
return null
|
|
51
|
-
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { StateUpdate } from "atom.io"
|
|
2
2
|
import type { Store } from "atom.io/internal"
|
|
3
3
|
|
|
4
|
-
import type { Atom } from "
|
|
5
|
-
import type { ReadonlySelector, Selector } from "../selector"
|
|
4
|
+
import type { Atom, Selector } from ".."
|
|
6
5
|
|
|
7
6
|
export const emitUpdate = <T>(
|
|
8
|
-
state: Atom<T> |
|
|
7
|
+
state: Atom<T> | Selector<T>,
|
|
9
8
|
update: StateUpdate<T>,
|
|
10
9
|
store: Store,
|
|
11
10
|
): void => {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Selector } from "../selector"
|
|
1
|
+
import type { WritableState } from ".."
|
|
3
2
|
import type { Store } from "../store"
|
|
4
3
|
import { setAtom } from "./set-atom"
|
|
5
4
|
|
|
6
5
|
export const setAtomOrSelector = <T>(
|
|
7
|
-
state:
|
|
6
|
+
state: WritableState<T>,
|
|
8
7
|
value: T | ((oldValue: T) => T),
|
|
9
8
|
store: Store,
|
|
10
9
|
): void => {
|
|
11
10
|
switch (state.type) {
|
|
12
11
|
case `atom`:
|
|
12
|
+
case `mutable_atom`:
|
|
13
13
|
setAtom(state, value, store)
|
|
14
14
|
break
|
|
15
15
|
case `selector`:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { Atom } from "
|
|
1
|
+
import type { Atom } from ".."
|
|
2
2
|
import { isAtomDefault, markAtomAsNotDefault } from "../atom"
|
|
3
3
|
import { cacheValue } from "../caching"
|
|
4
|
+
import type { Transceiver } from "../mutable"
|
|
4
5
|
import { markDone } from "../operation"
|
|
5
6
|
import { readOrComputeValue } from "../read-or-compute-value"
|
|
6
7
|
import type { Store } from "../store"
|
|
@@ -28,9 +29,12 @@ export const setAtom = <T>(
|
|
|
28
29
|
const update = { oldValue, newValue }
|
|
29
30
|
if (target.transactionMeta === null) {
|
|
30
31
|
emitUpdate(atom, update, target)
|
|
31
|
-
} else if (target.
|
|
32
|
-
emitUpdate(atom, update, target.parent)
|
|
33
|
-
} else {
|
|
32
|
+
} else if (target.on.transactionApplying && target.parent) {
|
|
34
33
|
stowUpdate(atom, update, target)
|
|
34
|
+
if (atom.key.startsWith(`*`)) {
|
|
35
|
+
const mutableKey = atom.key.slice(1)
|
|
36
|
+
const mutable: Transceiver<any> = target.valueMap.get(mutableKey)
|
|
37
|
+
mutable.do(update.newValue)
|
|
38
|
+
}
|
|
35
39
|
}
|
|
36
40
|
}
|