atom.io 0.11.0 → 0.12.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 +614 -0
- package/data/dist/index.cjs.map +1 -0
- package/data/dist/index.d.cts +158 -0
- package/data/dist/index.d.ts +118 -1
- package/data/dist/index.js +551 -30
- package/data/dist/index.js.map +1 -1
- package/data/dist/metafile-cjs.json +1 -0
- package/data/dist/metafile-esm.json +1 -0
- package/data/package.json +4 -3
- package/data/src/index.ts +1 -0
- package/data/src/join.ts +450 -0
- package/data/src/struct-family.ts +34 -24
- package/data/src/struct.ts +6 -8
- package/dist/index.cjs +257 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.mts → index.d.cts} +10 -11
- package/dist/index.d.ts +10 -11
- package/dist/index.js +63 -104
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/internal/dist/{index.mjs → index.cjs} +692 -503
- package/internal/dist/index.cjs.map +1 -0
- package/internal/dist/{index.d.mts → index.d.cts} +114 -105
- package/internal/dist/index.d.ts +114 -105
- package/internal/dist/index.js +628 -563
- package/internal/dist/index.js.map +1 -1
- package/internal/dist/metafile-cjs.json +1 -0
- package/internal/dist/metafile-esm.json +1 -0
- package/internal/package.json +4 -3
- package/internal/src/atom/create-atom.ts +29 -16
- package/internal/src/atom/delete-atom.ts +25 -6
- package/internal/src/atom/is-default.ts +4 -17
- package/internal/src/caching.ts +28 -23
- package/internal/src/families/create-atom-family.ts +3 -2
- package/internal/src/families/create-readonly-selector-family.ts +1 -1
- package/internal/src/families/create-selector-family.ts +4 -4
- package/internal/src/index.ts +2 -1
- package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
- package/internal/src/mutable/create-mutable-atom.ts +1 -2
- package/internal/src/mutable/get-json-family.ts +22 -0
- package/internal/src/mutable/get-json-token.ts +1 -0
- package/internal/src/mutable/index.ts +1 -0
- package/internal/src/mutable/tracker-family.ts +1 -2
- package/internal/src/mutable/tracker.ts +8 -6
- package/internal/src/mutable/transceiver.ts +2 -0
- package/internal/src/not-found-error.ts +27 -0
- package/internal/src/operation.ts +2 -3
- package/internal/src/{get-state-internal.ts → read-or-compute-value.ts} +13 -6
- package/internal/src/selector/create-selector.ts +6 -7
- package/internal/src/selector/delete-selector.ts +37 -0
- package/internal/src/selector/index.ts +2 -1
- package/internal/src/selector/register-selector.ts +7 -7
- package/internal/src/set-state/copy-mutable-in-transaction.ts +3 -2
- package/internal/src/set-state/emit-update.ts +1 -3
- package/internal/src/set-state/evict-downstream.ts +6 -8
- package/internal/src/set-state/index.ts +1 -1
- package/internal/src/set-state/{set-state-internal.ts → set-atom-or-selector.ts} +2 -3
- package/internal/src/set-state/set-atom.ts +5 -6
- package/internal/src/store/store.ts +1 -1
- package/internal/src/store/withdraw-new-family-member.ts +6 -6
- package/internal/src/subscribe/recall-state.ts +1 -2
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +2 -2
- package/internal/src/timeline/add-atom-to-timeline.ts +5 -16
- package/internal/src/timeline/{timeline-internal.ts → create-timeline.ts} +4 -5
- package/internal/src/timeline/index.ts +2 -2
- package/internal/src/timeline/time-travel.ts +89 -0
- package/internal/src/transaction/{transaction-internal.ts → create-transaction.ts} +6 -5
- package/internal/src/transaction/index.ts +2 -3
- package/introspection/dist/{index.mjs → index.cjs} +54 -29
- package/introspection/dist/index.cjs.map +1 -0
- package/introspection/dist/{index.d.mts → index.d.cts} +2 -2
- package/introspection/dist/index.d.ts +2 -2
- package/introspection/dist/index.js +32 -49
- package/introspection/dist/index.js.map +1 -1
- package/introspection/dist/metafile-cjs.json +1 -0
- package/introspection/dist/metafile-esm.json +1 -0
- package/introspection/package.json +4 -3
- package/introspection/src/attach-introspection-states.ts +2 -2
- package/introspection/src/attach-selector-index.ts +8 -4
- package/json/dist/{index.mjs → index.cjs} +20 -7
- package/json/dist/{index.mjs.map → index.cjs.map} +1 -1
- package/json/dist/{index.d.mts → index.d.cts} +1 -1
- package/json/dist/index.d.ts +1 -1
- package/json/dist/index.js +6 -19
- package/json/dist/index.js.map +1 -1
- package/json/dist/metafile-cjs.json +1 -0
- package/json/dist/metafile-esm.json +1 -0
- package/json/package.json +4 -3
- package/package.json +48 -47
- package/react/dist/index.cjs +59 -0
- package/react/dist/index.cjs.map +1 -0
- package/react/dist/index.js +20 -42
- package/react/dist/index.js.map +1 -1
- package/react/dist/metafile-cjs.json +1 -0
- package/react/dist/metafile-esm.json +1 -0
- package/react/package.json +4 -3
- package/react/src/store-hooks.ts +8 -2
- package/react-devtools/dist/{index.mjs → index.cjs} +286 -240
- package/react-devtools/dist/index.cjs.map +1 -0
- package/react-devtools/dist/{index.d.mts → index.d.cts} +29 -17
- package/react-devtools/dist/index.d.ts +29 -17
- package/react-devtools/dist/index.js +251 -273
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/metafile-cjs.json +1 -0
- package/react-devtools/dist/metafile-esm.json +1 -0
- package/react-devtools/package.json +4 -3
- package/react-devtools/src/StateEditor.tsx +8 -8
- package/realtime-client/dist/{index.mjs → index.cjs} +50 -21
- package/realtime-client/dist/index.js +20 -49
- package/realtime-client/dist/metafile-cjs.json +1 -0
- package/realtime-client/dist/metafile-esm.json +1 -0
- package/realtime-client/package.json +4 -3
- package/realtime-react/dist/index.cjs +99 -0
- package/realtime-react/dist/index.js +35 -66
- package/realtime-react/dist/metafile-cjs.json +1 -0
- package/realtime-react/dist/metafile-esm.json +1 -0
- package/realtime-react/package.json +4 -3
- package/realtime-server/dist/{index.mjs → index.cjs} +67 -40
- package/realtime-server/dist/index.js +39 -66
- package/realtime-server/dist/metafile-cjs.json +1 -0
- package/realtime-server/dist/metafile-esm.json +1 -0
- package/realtime-server/package.json +4 -3
- package/realtime-testing/dist/{index.mjs → index.cjs} +54 -23
- package/realtime-testing/dist/index.js +22 -53
- package/realtime-testing/dist/metafile-cjs.json +1 -0
- package/realtime-testing/dist/metafile-esm.json +1 -0
- package/realtime-testing/package.json +4 -3
- package/src/atom.ts +6 -8
- package/src/dispose.ts +18 -0
- package/src/get-state.ts +16 -0
- package/src/index.ts +3 -1
- package/src/logger.ts +1 -1
- package/src/selector.ts +3 -3
- package/src/set-state.ts +22 -0
- package/src/silo.ts +7 -8
- package/src/timeline.ts +6 -11
- package/src/transaction.ts +2 -2
- package/transceivers/set-rtx/dist/{index.mjs → index.cjs} +40 -36
- package/transceivers/set-rtx/dist/index.cjs.map +1 -0
- package/transceivers/set-rtx/dist/{index.d.mts → index.d.cts} +2 -1
- package/transceivers/set-rtx/dist/index.d.ts +2 -1
- package/transceivers/set-rtx/dist/index.js +37 -37
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/dist/metafile-cjs.json +1 -0
- package/transceivers/set-rtx/dist/metafile-esm.json +1 -0
- package/transceivers/set-rtx/package.json +4 -3
- package/transceivers/set-rtx/src/set-rtx.ts +29 -26
- package/data/dist/index.d.mts +0 -41
- package/data/dist/index.mjs +0 -82
- package/data/dist/index.mjs.map +0 -1
- package/dist/index.mjs +0 -215
- package/dist/index.mjs.map +0 -1
- package/internal/dist/index.mjs.map +0 -1
- package/internal/src/set-state/set-selector-state.ts +0 -8
- package/internal/src/timeline/time-travel-internal.ts +0 -109
- package/introspection/dist/index.mjs.map +0 -1
- package/react/dist/index.mjs +0 -29
- package/react/dist/index.mjs.map +0 -1
- package/react-devtools/dist/index.mjs.map +0 -1
- package/realtime-react/dist/index.mjs +0 -68
- package/src/get-set.ts +0 -48
- package/transceivers/set-rtx/dist/index.mjs.map +0 -1
- /package/react/dist/{index.d.mts → index.d.cts} +0 -0
- /package/realtime-client/dist/{index.mjs.map → index.cjs.map} +0 -0
- /package/realtime-client/dist/{index.d.mts → index.d.cts} +0 -0
- /package/realtime-react/dist/{index.mjs.map → index.cjs.map} +0 -0
- /package/realtime-react/dist/{index.d.mts → index.d.cts} +0 -0
- /package/realtime-server/dist/{index.mjs.map → index.cjs.map} +0 -0
- /package/realtime-server/dist/{index.d.mts → index.d.cts} +0 -0
- /package/realtime-testing/dist/{index.mjs.map → index.cjs.map} +0 -0
- /package/realtime-testing/dist/{index.d.mts → index.d.cts} +0 -0
|
@@ -4,7 +4,6 @@ import { parseJson } from "atom.io/json"
|
|
|
4
4
|
|
|
5
5
|
import { createAtomFamily } from "../families"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
|
-
import { IMPLICIT } from "../store"
|
|
8
7
|
import { Tracker } from "./tracker"
|
|
9
8
|
import type { Transceiver } from "./transceiver"
|
|
10
9
|
|
|
@@ -24,7 +23,7 @@ export class FamilyTracker<
|
|
|
24
23
|
|
|
25
24
|
public constructor(
|
|
26
25
|
findMutableState: AtomFamily<Core, FamilyMemberKey>,
|
|
27
|
-
store: Store
|
|
26
|
+
store: Store,
|
|
28
27
|
) {
|
|
29
28
|
this.findLatestUpdateState = createAtomFamily<
|
|
30
29
|
typeof this.Update | null,
|
|
@@ -3,7 +3,6 @@ import { getState, setState, subscribe, subscribeToTimeline } from "atom.io"
|
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
4
|
|
|
5
5
|
import type { Store } from ".."
|
|
6
|
-
import { IMPLICIT } from ".."
|
|
7
6
|
import { createAtom, deleteAtom } from "../atom"
|
|
8
7
|
import { target } from "../transaction"
|
|
9
8
|
import type { Transceiver } from "./transceiver"
|
|
@@ -18,7 +17,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
18
17
|
|
|
19
18
|
private initializeState(
|
|
20
19
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
21
|
-
store: Store
|
|
20
|
+
store: Store,
|
|
22
21
|
): AtomToken<typeof this.Update | null> {
|
|
23
22
|
const latestUpdateStateKey = `*${mutableState.key}`
|
|
24
23
|
deleteAtom({ type: `atom`, key: latestUpdateStateKey }, store)
|
|
@@ -46,7 +45,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
46
45
|
private observeCore(
|
|
47
46
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
48
47
|
latestUpdateState: AtomToken<typeof this.Update | null>,
|
|
49
|
-
store: Store
|
|
48
|
+
store: Store,
|
|
50
49
|
): void {
|
|
51
50
|
const originalInnerValue = getState(mutableState, store)
|
|
52
51
|
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
@@ -96,7 +95,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
96
95
|
private updateCore<Core extends Transceiver<any>>(
|
|
97
96
|
mutableState: MutableAtomToken<Core, Json.Serializable>,
|
|
98
97
|
latestUpdateState: AtomToken<typeof this.Update | null>,
|
|
99
|
-
store: Store
|
|
98
|
+
store: Store,
|
|
100
99
|
): void {
|
|
101
100
|
subscribe(
|
|
102
101
|
latestUpdateState,
|
|
@@ -133,7 +132,10 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
133
132
|
latestUpdateState.key,
|
|
134
133
|
() => {
|
|
135
134
|
unsubscribe()
|
|
136
|
-
|
|
135
|
+
const mutable = getState(mutableState, store)
|
|
136
|
+
const updateNumber = mutable.getUpdateNumber(newValue)
|
|
137
|
+
const eventOffset = updateNumber - mutable.cacheUpdateNumber
|
|
138
|
+
if (newValue && eventOffset === 1) {
|
|
137
139
|
setState(
|
|
138
140
|
mutableState,
|
|
139
141
|
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
@@ -153,7 +155,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
153
155
|
|
|
154
156
|
public constructor(
|
|
155
157
|
mutableState: MutableAtomToken<Mutable, Json.Serializable>,
|
|
156
|
-
store: Store
|
|
158
|
+
store: Store,
|
|
157
159
|
) {
|
|
158
160
|
this.mutableState = mutableState
|
|
159
161
|
this.latestUpdateState = this.initializeState(mutableState, store)
|
|
@@ -4,6 +4,8 @@ export interface Transceiver<Signal extends Json.Serializable> {
|
|
|
4
4
|
do: (update: Signal) => void
|
|
5
5
|
undo: (update: Signal) => void
|
|
6
6
|
subscribe: (key: string, fn: (update: Signal) => void) => () => void
|
|
7
|
+
cacheUpdateNumber: number
|
|
8
|
+
getUpdateNumber: (update: Signal) => number
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
export function isTransceiver(
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReadonlySelectorToken, StateToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from "./store"
|
|
4
|
+
|
|
5
|
+
const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1)
|
|
6
|
+
|
|
7
|
+
function prettyPrintTokenType(
|
|
8
|
+
token: ReadonlySelectorToken<any> | StateToken<any>,
|
|
9
|
+
) {
|
|
10
|
+
if (token.type === `readonly_selector`) {
|
|
11
|
+
return `Readonly Selector`
|
|
12
|
+
}
|
|
13
|
+
return capitalize(token.type)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class NotFoundError extends Error {
|
|
17
|
+
public constructor(
|
|
18
|
+
token: ReadonlySelectorToken<any> | StateToken<any>,
|
|
19
|
+
store: Store,
|
|
20
|
+
) {
|
|
21
|
+
super(
|
|
22
|
+
`${prettyPrintTokenType(token)} "${token.key}" not found in store "${
|
|
23
|
+
store.config.name
|
|
24
|
+
}".`,
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { StateToken } from "atom.io"
|
|
2
2
|
|
|
3
3
|
import type { Store } from "./store"
|
|
4
|
-
import { IMPLICIT } from "./store"
|
|
5
4
|
import { target } from "./transaction"
|
|
6
5
|
|
|
7
6
|
export type OperationProgress =
|
|
@@ -62,7 +61,7 @@ export const closeOperation = (store: Store): void => {
|
|
|
62
61
|
store.subject.operationStatus.next(core.operation)
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
export const isDone = (key: string, store: Store
|
|
64
|
+
export const isDone = (key: string, store: Store): boolean => {
|
|
66
65
|
const core = target(store)
|
|
67
66
|
if (!core.operation.open) {
|
|
68
67
|
store.logger.warn(
|
|
@@ -75,7 +74,7 @@ export const isDone = (key: string, store: Store = IMPLICIT.STORE): boolean => {
|
|
|
75
74
|
}
|
|
76
75
|
return core.operation.done.has(key)
|
|
77
76
|
}
|
|
78
|
-
export const markDone = (key: string, store: Store
|
|
77
|
+
export const markDone = (key: string, store: Store): void => {
|
|
79
78
|
const core = target(store)
|
|
80
79
|
if (!core.operation.open) {
|
|
81
80
|
store.logger.warn(
|
|
@@ -2,20 +2,27 @@ import type { Atom } from "./atom"
|
|
|
2
2
|
import { isValueCached, readCachedValue } from "./caching"
|
|
3
3
|
import type { ReadonlySelector, Selector } from "./selector"
|
|
4
4
|
import type { Store } from "./store"
|
|
5
|
-
import { IMPLICIT } from "./store"
|
|
6
5
|
|
|
7
|
-
export const
|
|
6
|
+
export const readOrComputeValue = <T>(
|
|
8
7
|
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
9
|
-
store: Store
|
|
8
|
+
store: Store,
|
|
10
9
|
): T => {
|
|
11
10
|
if (isValueCached(state.key, store)) {
|
|
12
11
|
store.logger.info(`📖`, state.type, state.key, `reading cached value`)
|
|
13
12
|
return readCachedValue(state.key, store)
|
|
14
13
|
}
|
|
15
14
|
if (state.type !== `atom`) {
|
|
16
|
-
store.logger.info(`🧮`, state.type, state.key, `
|
|
15
|
+
store.logger.info(`🧮`, state.type, state.key, `computing value`)
|
|
17
16
|
return state.get()
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const fallback =
|
|
19
|
+
state.default instanceof Function ? state.default() : state.default
|
|
20
|
+
store.logger.info(
|
|
21
|
+
`💁`,
|
|
22
|
+
`atom`,
|
|
23
|
+
state.key,
|
|
24
|
+
`could not find cached value; using default`,
|
|
25
|
+
fallback,
|
|
26
|
+
)
|
|
27
|
+
return state.default instanceof Function ? state.default() : state.default
|
|
21
28
|
}
|
|
@@ -7,7 +7,6 @@ import type {
|
|
|
7
7
|
} from "atom.io"
|
|
8
8
|
|
|
9
9
|
import type { Store } from "../store"
|
|
10
|
-
import { IMPLICIT } from "../store"
|
|
11
10
|
import type { Subject } from "../subject"
|
|
12
11
|
import { target } from "../transaction"
|
|
13
12
|
import { createReadWriteSelector } from "./create-read-write-selector"
|
|
@@ -33,18 +32,18 @@ export type ReadonlySelector<T> = {
|
|
|
33
32
|
|
|
34
33
|
export function createSelector<T>(
|
|
35
34
|
options: SelectorOptions<T>,
|
|
36
|
-
family
|
|
37
|
-
store
|
|
35
|
+
family: FamilyMetadata | undefined,
|
|
36
|
+
store: Store,
|
|
38
37
|
): SelectorToken<T>
|
|
39
38
|
export function createSelector<T>(
|
|
40
39
|
options: ReadonlySelectorOptions<T>,
|
|
41
|
-
family
|
|
42
|
-
store
|
|
40
|
+
family: FamilyMetadata | undefined,
|
|
41
|
+
store: Store,
|
|
43
42
|
): ReadonlySelectorToken<T>
|
|
44
43
|
export function createSelector<T>(
|
|
45
44
|
options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
|
|
46
|
-
family
|
|
47
|
-
store: Store
|
|
45
|
+
family: FamilyMetadata | undefined,
|
|
46
|
+
store: Store,
|
|
48
47
|
): ReadonlySelectorToken<T> | SelectorToken<T> {
|
|
49
48
|
const core = target(store)
|
|
50
49
|
const existingWritable = core.selectors.get(options.key)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ReadonlySelectorToken, SelectorToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from ".."
|
|
4
|
+
import { target } from ".."
|
|
5
|
+
|
|
6
|
+
export function deleteSelector(
|
|
7
|
+
selectorToken: ReadonlySelectorToken<unknown> | SelectorToken<unknown>,
|
|
8
|
+
store: Store,
|
|
9
|
+
): void {
|
|
10
|
+
const core = target(store)
|
|
11
|
+
const { key } = selectorToken
|
|
12
|
+
switch (selectorToken.type) {
|
|
13
|
+
case `selector`:
|
|
14
|
+
core.selectors.delete(key)
|
|
15
|
+
break
|
|
16
|
+
case `readonly_selector`:
|
|
17
|
+
core.readonlySelectors.delete(key)
|
|
18
|
+
break
|
|
19
|
+
}
|
|
20
|
+
core.valueMap.delete(key)
|
|
21
|
+
core.selectorAtoms.delete(key)
|
|
22
|
+
const downstreamTokens = core.selectorGraph
|
|
23
|
+
.getRelationEntries({ upstreamSelectorKey: key })
|
|
24
|
+
.filter(([_, { source }]) => source === key)
|
|
25
|
+
.map(
|
|
26
|
+
([downstreamSelectorKey]) =>
|
|
27
|
+
core.selectors.get(downstreamSelectorKey) ??
|
|
28
|
+
core.readonlySelectors.get(downstreamSelectorKey),
|
|
29
|
+
)
|
|
30
|
+
for (const downstreamToken of downstreamTokens) {
|
|
31
|
+
if (downstreamToken) {
|
|
32
|
+
deleteSelector(downstreamToken, store)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
core.selectorGraph.delete(key)
|
|
36
|
+
store.logger.info(`🔥`, selectorToken.type, `${key}`, `deleted`)
|
|
37
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export * from "./create-selector"
|
|
2
|
+
export * from "./delete-selector"
|
|
1
3
|
export * from "./get-selector-dependency-keys"
|
|
2
4
|
export * from "./register-selector"
|
|
3
|
-
export * from "./create-selector"
|
|
4
5
|
export * from "./trace-selector-atoms"
|
|
5
6
|
export * from "./update-selector-atoms"
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { Transactors } from "atom.io"
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { readOrComputeValue } from "../read-or-compute-value"
|
|
4
|
+
import { setAtomOrSelector } from "../set-state"
|
|
5
5
|
import type { Store } from "../store"
|
|
6
|
-
import {
|
|
7
|
-
import { target } from "../transaction/transaction
|
|
6
|
+
import { withdraw } from "../store"
|
|
7
|
+
import { target } from "../transaction/create-transaction"
|
|
8
8
|
import { updateSelectorAtoms } from "./update-selector-atoms"
|
|
9
9
|
|
|
10
10
|
export const registerSelector = (
|
|
11
11
|
selectorKey: string,
|
|
12
|
-
store: Store
|
|
12
|
+
store: Store,
|
|
13
13
|
): Transactors => ({
|
|
14
14
|
get: (dependency) => {
|
|
15
15
|
const core = target(store)
|
|
@@ -23,7 +23,7 @@ export const registerSelector = (
|
|
|
23
23
|
`State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
24
24
|
)
|
|
25
25
|
}
|
|
26
|
-
const dependencyValue =
|
|
26
|
+
const dependencyValue = readOrComputeValue(dependencyState, store)
|
|
27
27
|
|
|
28
28
|
store.logger.info(
|
|
29
29
|
`🔌`,
|
|
@@ -55,6 +55,6 @@ export const registerSelector = (
|
|
|
55
55
|
`State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
56
56
|
)
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
setAtomOrSelector(state, newValue, store)
|
|
59
59
|
},
|
|
60
60
|
})
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { AtomFamily } from "atom.io"
|
|
2
2
|
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
|
-
import {
|
|
3
|
+
import { readOrComputeValue } from ".."
|
|
4
4
|
import type { Store, StoreCore } from ".."
|
|
5
5
|
import type { Atom } from "../atom"
|
|
6
6
|
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
7
7
|
|
|
8
8
|
export function copyMutableIfWithinTransaction<T>(
|
|
9
|
+
oldValue: T,
|
|
9
10
|
atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
|
|
10
11
|
store: Store,
|
|
11
12
|
): T {
|
|
@@ -37,7 +38,7 @@ export function copyMutableIfWithinTransaction<T>(
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
return
|
|
41
|
+
return oldValue
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export function copyMutableFamilyMemberWithinTransaction<T>(
|
|
@@ -2,23 +2,21 @@ import type { Atom } from "../atom"
|
|
|
2
2
|
import { evictCachedValue } from "../caching"
|
|
3
3
|
import { isDone, markDone } from "../operation"
|
|
4
4
|
import type { Store } from "../store"
|
|
5
|
-
import { IMPLICIT } from "../store"
|
|
6
5
|
import { target } from "../transaction"
|
|
7
6
|
|
|
8
|
-
export const evictDownStream = <T>(
|
|
9
|
-
atom: Atom<T>,
|
|
10
|
-
store: Store = IMPLICIT.STORE,
|
|
11
|
-
): void => {
|
|
7
|
+
export const evictDownStream = <T>(atom: Atom<T>, store: Store): void => {
|
|
12
8
|
const core = target(store)
|
|
13
9
|
const downstreamKeys = core.selectorAtoms.getRelatedKeys(atom.key)
|
|
14
10
|
store.logger.info(
|
|
15
11
|
`🧹`,
|
|
16
12
|
atom.type,
|
|
17
13
|
atom.key,
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
downstreamKeys
|
|
15
|
+
? `evicting ${downstreamKeys.size} states downstream:`
|
|
16
|
+
: `no downstream states`,
|
|
17
|
+
downstreamKeys ?? `to evict`,
|
|
20
18
|
)
|
|
21
|
-
if (downstreamKeys
|
|
19
|
+
if (downstreamKeys) {
|
|
22
20
|
if (core.operation.open) {
|
|
23
21
|
store.logger.info(
|
|
24
22
|
`🧹`,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./become"
|
|
2
|
-
export * from "./set-
|
|
2
|
+
export * from "./set-atom-or-selector"
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import type { Selector } from "../selector"
|
|
3
3
|
import type { Store } from "../store"
|
|
4
|
-
import { IMPLICIT } from "../store"
|
|
5
4
|
import { setAtom } from "./set-atom"
|
|
6
5
|
|
|
7
|
-
export const
|
|
6
|
+
export const setAtomOrSelector = <T>(
|
|
8
7
|
state: Atom<T> | Selector<T>,
|
|
9
8
|
value: T | ((oldValue: T) => T),
|
|
10
|
-
store: Store
|
|
9
|
+
store: Store,
|
|
11
10
|
): void => {
|
|
12
11
|
if (state.type === `selector`) {
|
|
13
12
|
state.set(value)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import { isAtomDefault, markAtomAsNotDefault } from "../atom"
|
|
3
3
|
import { cacheValue } from "../caching"
|
|
4
|
-
import { getState__INTERNAL } from "../get-state-internal"
|
|
5
4
|
import { markDone } from "../operation"
|
|
5
|
+
import { readOrComputeValue } from "../read-or-compute-value"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
|
-
import { IMPLICIT } from "../store"
|
|
8
7
|
import { become } from "./become"
|
|
9
8
|
import { copyMutableIfWithinTransaction } from "./copy-mutable-in-transaction"
|
|
10
9
|
import { emitUpdate } from "./emit-update"
|
|
@@ -14,13 +13,13 @@ import { stowUpdate } from "./stow-update"
|
|
|
14
13
|
export const setAtom = <T>(
|
|
15
14
|
atom: Atom<T>,
|
|
16
15
|
next: T | ((oldValue: T) => T),
|
|
17
|
-
store: Store
|
|
16
|
+
store: Store,
|
|
18
17
|
): void => {
|
|
19
|
-
const oldValue =
|
|
20
|
-
let newValue = copyMutableIfWithinTransaction(atom, store)
|
|
18
|
+
const oldValue = readOrComputeValue(atom, store)
|
|
19
|
+
let newValue = copyMutableIfWithinTransaction(oldValue, atom, store)
|
|
21
20
|
newValue = become(next)(newValue)
|
|
22
21
|
store.logger.info(`📝`, `atom`, atom.key, `set to`, newValue)
|
|
23
|
-
cacheValue(atom.key, newValue, atom.subject, store)
|
|
22
|
+
newValue = cacheValue(atom.key, newValue, atom.subject, store)
|
|
24
23
|
if (isAtomDefault(atom.key, store)) {
|
|
25
24
|
markAtomAsNotDefault(atom.key, store)
|
|
26
25
|
}
|
|
@@ -152,7 +152,7 @@ export const IMPLICIT = {
|
|
|
152
152
|
},
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
export const clearStore = (store: Store
|
|
155
|
+
export const clearStore = (store: Store): void => {
|
|
156
156
|
const { config } = store
|
|
157
157
|
Object.assign(store, new Store(config.name))
|
|
158
158
|
store.config = config
|
|
@@ -36,13 +36,13 @@ export function withdrawNewFamilyMember<T>(
|
|
|
36
36
|
| StateToken<T>,
|
|
37
37
|
store: Store,
|
|
38
38
|
): Atom<T> | ReadonlySelector<T> | Selector<T> | undefined {
|
|
39
|
-
store.logger.info(
|
|
40
|
-
`👪`,
|
|
41
|
-
token.type,
|
|
42
|
-
token.key,
|
|
43
|
-
`creating new family member in store "${store.config.name}"`,
|
|
44
|
-
)
|
|
45
39
|
if (token.family) {
|
|
40
|
+
store.logger.info(
|
|
41
|
+
`👪`,
|
|
42
|
+
token.type,
|
|
43
|
+
token.key,
|
|
44
|
+
`creating new family member in store "${store.config.name}"`,
|
|
45
|
+
)
|
|
46
46
|
const core = target(store)
|
|
47
47
|
const family = core.families.get(token.family.key)
|
|
48
48
|
if (family) {
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
3
|
import type { Store } from "../store"
|
|
4
|
-
import { IMPLICIT } from "../store"
|
|
5
4
|
import { target } from "../transaction"
|
|
6
5
|
|
|
7
6
|
export const recallState = <T>(
|
|
8
7
|
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
9
|
-
store: Store
|
|
8
|
+
store: Store,
|
|
10
9
|
): T => {
|
|
11
10
|
const core = target(store)
|
|
12
11
|
if (!core.operation.open) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readOrComputeValue } from "../read-or-compute-value"
|
|
2
2
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
3
|
import { traceAllSelectorAtoms } from "../selector"
|
|
4
4
|
import type { Store } from "../store"
|
|
@@ -34,7 +34,7 @@ export const subscribeToRootAtoms = <T>(
|
|
|
34
34
|
)
|
|
35
35
|
const oldValue = recallState(state, store)
|
|
36
36
|
// ❌ this retrieves a stale cached value when applying a transaction on the server
|
|
37
|
-
const newValue =
|
|
37
|
+
const newValue = readOrComputeValue(state, store)
|
|
38
38
|
store.logger.info(
|
|
39
39
|
`✨`,
|
|
40
40
|
state.type,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { AtomToken, TimelineUpdate } from "atom.io"
|
|
2
2
|
|
|
3
3
|
import type { Store } from "../store"
|
|
4
|
-
import {
|
|
4
|
+
import { withdraw } from "../store"
|
|
5
5
|
import { target } from "../transaction"
|
|
6
6
|
import type {
|
|
7
7
|
Timeline,
|
|
8
8
|
TimelineAtomUpdate,
|
|
9
9
|
TimelineTransactionUpdate,
|
|
10
|
-
} from "./timeline
|
|
10
|
+
} from "./create-timeline"
|
|
11
11
|
|
|
12
12
|
export const addAtomToTimeline = (
|
|
13
13
|
atomToken: AtomToken<any>,
|
|
14
14
|
tl: Timeline,
|
|
15
|
-
store: Store
|
|
15
|
+
store: Store,
|
|
16
16
|
): void => {
|
|
17
17
|
const atom = withdraw(atomToken, store)
|
|
18
18
|
if (atom === undefined) {
|
|
@@ -38,17 +38,6 @@ export const addAtomToTimeline = (
|
|
|
38
38
|
? store.transactionStatus.time
|
|
39
39
|
: null
|
|
40
40
|
|
|
41
|
-
// store.logger.info(
|
|
42
|
-
// `⏳ timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
|
|
43
|
-
// update.oldValue,
|
|
44
|
-
// `->`,
|
|
45
|
-
// update.newValue,
|
|
46
|
-
// currentTransactionKey
|
|
47
|
-
// ? `) in transaction "${currentTransactionKey}"`
|
|
48
|
-
// : currentSelectorKey
|
|
49
|
-
// ? `) in selector "${currentSelectorKey}"`
|
|
50
|
-
// : `)`,
|
|
51
|
-
// )
|
|
52
41
|
store.logger.info(
|
|
53
42
|
`⏳`,
|
|
54
43
|
`timeline`,
|
|
@@ -62,8 +51,8 @@ export const addAtomToTimeline = (
|
|
|
62
51
|
currentTransactionKey
|
|
63
52
|
? `in transaction "${currentTransactionKey}"`
|
|
64
53
|
: currentSelectorKey
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
? `in selector "${currentSelectorKey}"`
|
|
55
|
+
: ``,
|
|
67
56
|
)
|
|
68
57
|
|
|
69
58
|
if (tl.timeTraveling === null) {
|
|
@@ -9,7 +9,6 @@ import type {
|
|
|
9
9
|
} from "atom.io"
|
|
10
10
|
|
|
11
11
|
import type { Store } from "../store"
|
|
12
|
-
import { IMPLICIT } from "../store"
|
|
13
12
|
import { Subject } from "../subject"
|
|
14
13
|
import { target } from "../transaction"
|
|
15
14
|
import { addAtomToTimeline } from "./add-atom-to-timeline"
|
|
@@ -51,10 +50,10 @@ export type Timeline = {
|
|
|
51
50
|
>
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
export function
|
|
53
|
+
export function createTimeline(
|
|
55
54
|
options: TimelineOptions,
|
|
56
|
-
store: Store
|
|
57
|
-
data
|
|
55
|
+
store: Store,
|
|
56
|
+
data?: Timeline,
|
|
58
57
|
): TimelineToken {
|
|
59
58
|
const tl: Timeline = {
|
|
60
59
|
type: `timeline`,
|
|
@@ -65,7 +64,7 @@ export function timeline__INTERNAL(
|
|
|
65
64
|
transactionKey: null,
|
|
66
65
|
...data,
|
|
67
66
|
history: data?.history.map((update) => ({ ...update })) ?? [],
|
|
68
|
-
install: (store) =>
|
|
67
|
+
install: (store) => createTimeline(options, store, tl),
|
|
69
68
|
subject: new Subject(),
|
|
70
69
|
}
|
|
71
70
|
if (options.shouldCapture) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from "./add-atom-to-timeline"
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
2
|
+
export * from "./create-timeline"
|
|
3
|
+
export * from "./time-travel"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { TimelineToken } from "atom.io"
|
|
2
|
+
import { setState } from "atom.io"
|
|
3
|
+
|
|
4
|
+
import type { Store } from "../store"
|
|
5
|
+
|
|
6
|
+
export const timeTravel = (
|
|
7
|
+
direction: `backward` | `forward`,
|
|
8
|
+
token: TimelineToken,
|
|
9
|
+
store: Store,
|
|
10
|
+
): void => {
|
|
11
|
+
const action = direction === `forward` ? `redo` : `undo`
|
|
12
|
+
store.logger.info(
|
|
13
|
+
direction === `forward` ? `⏩` : `⏪`,
|
|
14
|
+
`timeline`,
|
|
15
|
+
token.key,
|
|
16
|
+
action,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
const timelineData = store.timelines.get(token.key)
|
|
20
|
+
if (!timelineData) {
|
|
21
|
+
store.logger.error(
|
|
22
|
+
`🐞`,
|
|
23
|
+
`timeline`,
|
|
24
|
+
token.key,
|
|
25
|
+
`Failed to ${action}. This timeline has not been initialized.`,
|
|
26
|
+
)
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (
|
|
31
|
+
(direction === `forward` &&
|
|
32
|
+
timelineData.at === timelineData.history.length) ||
|
|
33
|
+
(direction === `backward` && timelineData.at === 0)
|
|
34
|
+
) {
|
|
35
|
+
store.logger.warn(
|
|
36
|
+
`💁`,
|
|
37
|
+
`timeline`,
|
|
38
|
+
token.key,
|
|
39
|
+
`Failed to ${action} at the ${
|
|
40
|
+
direction === `forward` ? `end` : `beginning`
|
|
41
|
+
} of timeline "${token.key}". There is nothing to ${action}.`,
|
|
42
|
+
)
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
timelineData.timeTraveling =
|
|
47
|
+
direction === `forward` ? `into_future` : `into_past`
|
|
48
|
+
if (direction === `backward`) {
|
|
49
|
+
--timelineData.at
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const update = timelineData.history[timelineData.at]
|
|
53
|
+
const updateValues = (atomUpdate: any) => {
|
|
54
|
+
const { key, newValue, oldValue } = atomUpdate
|
|
55
|
+
const value = direction === `forward` ? newValue : oldValue
|
|
56
|
+
setState({ key, type: `atom` }, value, store)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
switch (update.type) {
|
|
60
|
+
case `atom_update`: {
|
|
61
|
+
updateValues(update)
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
case `selector_update`:
|
|
65
|
+
case `transaction_update`: {
|
|
66
|
+
const updates =
|
|
67
|
+
direction === `forward`
|
|
68
|
+
? update.atomUpdates
|
|
69
|
+
: [...update.atomUpdates].reverse()
|
|
70
|
+
for (const atomUpdate of updates) {
|
|
71
|
+
updateValues(atomUpdate)
|
|
72
|
+
}
|
|
73
|
+
break
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (direction === `forward`) {
|
|
78
|
+
++timelineData.at
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
timelineData.subject.next(action)
|
|
82
|
+
timelineData.timeTraveling = null
|
|
83
|
+
store.logger.info(
|
|
84
|
+
`⏹️`,
|
|
85
|
+
`timeline`,
|
|
86
|
+
token.key,
|
|
87
|
+
`"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`,
|
|
88
|
+
)
|
|
89
|
+
}
|