atom.io 0.12.1 → 0.13.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/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/internal/dist/index.cjs +1561 -1512
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.cts +24 -14
- package/internal/dist/index.d.ts +24 -14
- package/internal/dist/index.js +1560 -1513
- package/internal/dist/index.js.map +1 -1
- package/internal/dist/metafile-cjs.json +1 -1
- package/internal/dist/metafile-esm.json +1 -1
- package/internal/src/atom/create-atom.ts +4 -4
- package/internal/src/atom/delete-atom.ts +11 -11
- package/internal/src/atom/is-default.ts +5 -5
- package/internal/src/caching.ts +12 -10
- package/internal/src/families/create-atom-family.ts +3 -3
- package/internal/src/families/create-readonly-selector-family.ts +3 -3
- package/internal/src/families/create-selector-family.ts +4 -4
- package/internal/src/index.ts +1 -0
- package/internal/src/keys.ts +4 -4
- package/internal/src/lazy-map.ts +6 -2
- package/internal/src/lineage.ts +18 -0
- package/internal/src/mutable/create-mutable-atom.ts +5 -4
- package/internal/src/mutable/get-json-family.ts +3 -3
- package/internal/src/mutable/tracker.ts +13 -10
- package/internal/src/operation.ts +19 -19
- package/internal/src/selector/create-read-write-selector.ts +5 -4
- package/internal/src/selector/create-readonly-selector.ts +4 -3
- package/internal/src/selector/create-selector.ts +6 -6
- package/internal/src/selector/delete-selector.ts +10 -10
- package/internal/src/selector/get-selector-dependency-keys.ts +2 -2
- package/internal/src/selector/register-selector.ts +4 -4
- package/internal/src/selector/update-selector-atoms.ts +2 -2
- package/internal/src/set-state/copy-mutable-if-needed.ts +4 -3
- package/internal/src/set-state/copy-mutable-in-transaction.ts +10 -16
- package/internal/src/set-state/copy-mutable-into-new-store.ts +1 -1
- package/internal/src/set-state/evict-downstream.ts +5 -5
- package/internal/src/set-state/set-atom.ts +6 -1
- package/internal/src/set-state/stow-update.ts +7 -2
- package/internal/src/store/store.ts +31 -24
- package/internal/src/store/withdraw-new-family-member.ts +3 -4
- package/internal/src/store/withdraw.ts +58 -59
- package/internal/src/subject.ts +14 -0
- package/internal/src/subscribe/recall-state.ts +5 -5
- package/internal/src/timeline/add-atom-to-timeline.ts +37 -27
- package/internal/src/timeline/create-timeline.ts +6 -8
- package/internal/src/timeline/time-travel.ts +22 -4
- package/internal/src/transaction/abort-transaction.ts +5 -3
- package/internal/src/transaction/apply-transaction.ts +80 -58
- package/internal/src/transaction/build-transaction.ts +33 -23
- package/internal/src/transaction/create-transaction.ts +6 -9
- package/internal/src/transaction/index.ts +2 -10
- package/internal/src/transaction/redo-transaction.ts +15 -10
- package/internal/src/transaction/undo-transaction.ts +15 -16
- package/introspection/dist/index.cjs +2 -2
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.js +3 -3
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +2 -2
- package/introspection/src/attach-selector-index.ts +2 -2
- package/package.json +3 -3
- package/react-devtools/dist/index.cjs +22 -8
- package/react-devtools/dist/index.cjs.map +1 -1
- package/react-devtools/dist/index.d.cts +17 -9
- package/react-devtools/dist/index.d.ts +17 -9
- package/react-devtools/dist/index.js +22 -8
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/metafile-cjs.json +1 -1
- package/react-devtools/dist/metafile-esm.json +1 -1
- package/react-devtools/src/Updates.tsx +22 -10
- package/src/transaction.ts +7 -2
- package/transceivers/set-rtx/dist/index.cjs.map +1 -1
- package/transceivers/set-rtx/dist/index.d.cts +2 -2
- package/transceivers/set-rtx/dist/index.d.ts +2 -2
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/dist/metafile-cjs.json +1 -1
- package/transceivers/set-rtx/dist/metafile-esm.json +1 -1
- package/transceivers/set-rtx/src/set-rtx.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AtomFamily } from "atom.io"
|
|
2
2
|
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
|
-
import {
|
|
4
|
-
import type { Store
|
|
3
|
+
import { newest } from ".."
|
|
4
|
+
import type { Store } from ".."
|
|
5
5
|
import type { Atom } from "../atom"
|
|
6
6
|
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
7
7
|
|
|
@@ -10,27 +10,21 @@ export function copyMutableIfWithinTransaction<T>(
|
|
|
10
10
|
atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
|
|
11
11
|
store: Store,
|
|
12
12
|
): T {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
) {
|
|
13
|
+
const target = newest(store)
|
|
14
|
+
const parent = target.parent
|
|
15
|
+
if (parent !== null) {
|
|
17
16
|
if (`toJson` in atom && `fromJson` in atom) {
|
|
18
|
-
const copiedValue = copyMutableIfNeeded(
|
|
19
|
-
atom,
|
|
20
|
-
atom,
|
|
21
|
-
store,
|
|
22
|
-
store.transactionStatus.core,
|
|
23
|
-
)
|
|
17
|
+
const copiedValue = copyMutableIfNeeded(atom, atom, parent, target)
|
|
24
18
|
return copiedValue
|
|
25
19
|
}
|
|
26
20
|
if (`family` in atom) {
|
|
27
|
-
const family =
|
|
21
|
+
const family = parent.families.get(atom.family.key)
|
|
28
22
|
if (family && family.type === `atom_family`) {
|
|
29
23
|
const result = copyMutableFamilyMemberWithinTransaction<T>(
|
|
30
24
|
atom,
|
|
31
25
|
family,
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
parent,
|
|
27
|
+
target,
|
|
34
28
|
)
|
|
35
29
|
if (result) {
|
|
36
30
|
return result
|
|
@@ -47,7 +41,7 @@ export function copyMutableFamilyMemberWithinTransaction<T>(
|
|
|
47
41
|
| AtomFamily<T, any>
|
|
48
42
|
| (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
|
|
49
43
|
origin: Store,
|
|
50
|
-
target:
|
|
44
|
+
target: Store,
|
|
51
45
|
): T | null {
|
|
52
46
|
if (`toJson` in family && `fromJson` in family) {
|
|
53
47
|
const copyCreated = copyMutableIfNeeded(atom, family, origin, target)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AtomFamily } from "atom.io"
|
|
2
2
|
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
|
-
import type { Store
|
|
3
|
+
import type { Store } from ".."
|
|
4
4
|
import type { Atom } from "../atom"
|
|
5
5
|
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
6
6
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import { evictCachedValue } from "../caching"
|
|
3
|
+
import { newest } from "../lineage"
|
|
3
4
|
import { isDone, markDone } from "../operation"
|
|
4
5
|
import type { Store } from "../store"
|
|
5
|
-
import { target } from "../transaction"
|
|
6
6
|
|
|
7
7
|
export const evictDownStream = <T>(atom: Atom<T>, store: Store): void => {
|
|
8
|
-
const
|
|
9
|
-
const downstreamKeys =
|
|
8
|
+
const target = newest(store)
|
|
9
|
+
const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom.key)
|
|
10
10
|
store.logger.info(
|
|
11
11
|
`🧹`,
|
|
12
12
|
atom.type,
|
|
@@ -17,12 +17,12 @@ export const evictDownStream = <T>(atom: Atom<T>, store: Store): void => {
|
|
|
17
17
|
downstreamKeys ?? `to evict`,
|
|
18
18
|
)
|
|
19
19
|
if (downstreamKeys) {
|
|
20
|
-
if (
|
|
20
|
+
if (target.operation.open) {
|
|
21
21
|
store.logger.info(
|
|
22
22
|
`🧹`,
|
|
23
23
|
atom.type,
|
|
24
24
|
atom.key,
|
|
25
|
-
`[ ${[...
|
|
25
|
+
`[ ${[...target.operation.done].join(`, `)} ] already done`,
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
28
|
for (const key of downstreamKeys) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import { isAtomDefault, markAtomAsNotDefault } from "../atom"
|
|
3
3
|
import { cacheValue } from "../caching"
|
|
4
|
+
import { newest } from "../lineage"
|
|
4
5
|
import { markDone } from "../operation"
|
|
5
6
|
import { readOrComputeValue } from "../read-or-compute-value"
|
|
6
7
|
import type { Store } from "../store"
|
|
@@ -15,6 +16,7 @@ export const setAtom = <T>(
|
|
|
15
16
|
next: T | ((oldValue: T) => T),
|
|
16
17
|
store: Store,
|
|
17
18
|
): void => {
|
|
19
|
+
const target = newest(store)
|
|
18
20
|
const oldValue = readOrComputeValue(atom, store)
|
|
19
21
|
let newValue = copyMutableIfWithinTransaction(oldValue, atom, store)
|
|
20
22
|
newValue = become(next)(newValue)
|
|
@@ -26,7 +28,10 @@ export const setAtom = <T>(
|
|
|
26
28
|
markDone(atom.key, store)
|
|
27
29
|
evictDownStream(atom, store)
|
|
28
30
|
const update = { oldValue, newValue }
|
|
29
|
-
if (
|
|
31
|
+
if (
|
|
32
|
+
target.transactionMeta === null ||
|
|
33
|
+
target.transactionMeta.phase === `applying`
|
|
34
|
+
) {
|
|
30
35
|
emitUpdate(atom, update, store)
|
|
31
36
|
} else {
|
|
32
37
|
stowUpdate(atom, update, store)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { KeyedStateUpdate, StateUpdate } from "atom.io"
|
|
2
2
|
|
|
3
3
|
import type { Atom } from "../atom"
|
|
4
|
+
import { newest } from "../lineage"
|
|
4
5
|
import { isTransceiver } from "../mutable"
|
|
5
6
|
import type { Store } from "../store"
|
|
6
7
|
|
|
@@ -22,7 +23,11 @@ export const stowUpdate = <T>(
|
|
|
22
23
|
store: Store,
|
|
23
24
|
): void => {
|
|
24
25
|
const { key } = state
|
|
25
|
-
|
|
26
|
+
const target = newest(store)
|
|
27
|
+
if (
|
|
28
|
+
target.transactionMeta === null ||
|
|
29
|
+
target.transactionMeta.phase !== `building`
|
|
30
|
+
) {
|
|
26
31
|
store.logger.error(
|
|
27
32
|
`🐞`,
|
|
28
33
|
`atom`,
|
|
@@ -39,7 +44,7 @@ export const stowUpdate = <T>(
|
|
|
39
44
|
if (state.family) {
|
|
40
45
|
atomUpdate.family = state.family
|
|
41
46
|
}
|
|
42
|
-
|
|
47
|
+
target.transactionMeta.update.updates.push(atomUpdate)
|
|
43
48
|
store.logger.info(
|
|
44
49
|
`📁`,
|
|
45
50
|
`atom`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AtomIOLogger
|
|
1
|
+
import { AtomIOLogger } from "atom.io"
|
|
2
2
|
import type {
|
|
3
3
|
AtomFamily,
|
|
4
4
|
AtomToken,
|
|
@@ -15,31 +15,35 @@ import type {
|
|
|
15
15
|
import { Junction } from "~/packages/rel8/junction/src"
|
|
16
16
|
|
|
17
17
|
import type { Atom } from "../atom"
|
|
18
|
+
import type { Lineage } from "../lineage"
|
|
18
19
|
import type { MutableAtom, Tracker, Transceiver } from "../mutable"
|
|
19
20
|
import type { OperationProgress } from "../operation"
|
|
20
21
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
21
|
-
import { Subject } from "../subject"
|
|
22
|
+
import { StatefulSubject, Subject } from "../subject"
|
|
22
23
|
import type { Timeline } from "../timeline"
|
|
23
|
-
import type { Transaction,
|
|
24
|
-
|
|
25
|
-
export type StoreCore = Pick<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
>
|
|
41
|
-
|
|
42
|
-
export class Store {
|
|
24
|
+
import type { Transaction, TransactionMeta } from "../transaction"
|
|
25
|
+
|
|
26
|
+
// export type StoreCore = Pick<
|
|
27
|
+
// Store,
|
|
28
|
+
// | `atoms`
|
|
29
|
+
// | `atomsThatAreDefault`
|
|
30
|
+
// | `families`
|
|
31
|
+
// | `operation`
|
|
32
|
+
// | `readonlySelectors`
|
|
33
|
+
// | `selectorAtoms`
|
|
34
|
+
// | `selectorGraph`
|
|
35
|
+
// | `selectors`
|
|
36
|
+
// | `timelineAtoms`
|
|
37
|
+
// | `timelines`
|
|
38
|
+
// | `trackers`
|
|
39
|
+
// | `transactions`
|
|
40
|
+
// | `valueMap`
|
|
41
|
+
// >
|
|
42
|
+
|
|
43
|
+
export class Store implements Lineage {
|
|
44
|
+
public parent: Store | null = null
|
|
45
|
+
public child: Store | null = null
|
|
46
|
+
|
|
43
47
|
public valueMap = new Map<string, any>()
|
|
44
48
|
|
|
45
49
|
public atoms = new Map<string, Atom<any> | MutableAtom<any>>()
|
|
@@ -88,10 +92,11 @@ export class Store {
|
|
|
88
92
|
>(),
|
|
89
93
|
transactionCreation: new Subject<TransactionToken<ƒn>>(),
|
|
90
94
|
timelineCreation: new Subject<TimelineToken>(),
|
|
95
|
+
transactionApplying: new StatefulSubject<TransactionMeta<ƒn> | null>(null),
|
|
91
96
|
operationStatus: new Subject<OperationProgress>(),
|
|
92
97
|
}
|
|
93
98
|
public operation: OperationProgress = { open: false }
|
|
94
|
-
public
|
|
99
|
+
public transactionMeta: TransactionMeta<ƒn> | null = null
|
|
95
100
|
|
|
96
101
|
public config: {
|
|
97
102
|
name: string
|
|
@@ -118,7 +123,9 @@ export class Store {
|
|
|
118
123
|
if (store !== null) {
|
|
119
124
|
this.valueMap = new Map(store?.valueMap)
|
|
120
125
|
this.operation = { ...store?.operation }
|
|
121
|
-
this.
|
|
126
|
+
this.transactionMeta = store?.transactionMeta
|
|
127
|
+
? { ...store?.transactionMeta }
|
|
128
|
+
: null
|
|
122
129
|
this.config = {
|
|
123
130
|
...store?.config,
|
|
124
131
|
name,
|
|
@@ -5,8 +5,7 @@ import type {
|
|
|
5
5
|
StateToken,
|
|
6
6
|
} from "atom.io"
|
|
7
7
|
import type { Atom, ReadonlySelector, Selector, Store } from ".."
|
|
8
|
-
import { withdraw } from ".."
|
|
9
|
-
import { target } from "../transaction"
|
|
8
|
+
import { newest, withdraw } from ".."
|
|
10
9
|
|
|
11
10
|
export function withdrawNewFamilyMember<T>(
|
|
12
11
|
token: AtomToken<T>,
|
|
@@ -43,8 +42,8 @@ export function withdrawNewFamilyMember<T>(
|
|
|
43
42
|
token.key,
|
|
44
43
|
`creating new family member in store "${store.config.name}"`,
|
|
45
44
|
)
|
|
46
|
-
const
|
|
47
|
-
const family =
|
|
45
|
+
const target = newest(store)
|
|
46
|
+
const family = target.families.get(token.family.key)
|
|
48
47
|
if (family) {
|
|
49
48
|
const jsonSubKey = JSON.parse(token.family.subKey)
|
|
50
49
|
family(jsonSubKey)
|
|
@@ -9,11 +9,10 @@ import type {
|
|
|
9
9
|
} from "atom.io"
|
|
10
10
|
|
|
11
11
|
import type { Atom } from "../atom"
|
|
12
|
+
import { newest } from "../lineage"
|
|
12
13
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
13
|
-
import { addAtomToTimeline } from "../timeline"
|
|
14
14
|
import type { Timeline } from "../timeline"
|
|
15
15
|
import type { Transaction } from "../transaction"
|
|
16
|
-
import { target } from "../transaction"
|
|
17
16
|
import type { Store } from "./store"
|
|
18
17
|
|
|
19
18
|
export function withdraw<T>(
|
|
@@ -58,67 +57,67 @@ export function withdraw<T>(
|
|
|
58
57
|
| Timeline
|
|
59
58
|
| Transaction<T extends ƒn ? T : never>
|
|
60
59
|
| undefined {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
const target = newest(store)
|
|
61
|
+
const state =
|
|
62
|
+
target.atoms.get(token.key) ??
|
|
63
|
+
target.selectors.get(token.key) ??
|
|
64
|
+
target.readonlySelectors.get(token.key) ??
|
|
65
|
+
target.transactions.get(token.key) ??
|
|
66
|
+
target.timelines.get(token.key)
|
|
68
67
|
if (state) {
|
|
69
68
|
return state
|
|
70
69
|
}
|
|
71
|
-
if (
|
|
72
|
-
core = store.transactionStatus.core
|
|
73
|
-
state =
|
|
74
|
-
core.atoms.get(token.key) ??
|
|
75
|
-
core.selectors.get(token.key) ??
|
|
76
|
-
core.readonlySelectors.get(token.key) ??
|
|
77
|
-
core.transactions.get(token.key) ??
|
|
78
|
-
core.timelines.get(token.key)
|
|
70
|
+
// if (target.transactionMeta?.phase === `applying`) {
|
|
79
71
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)
|
|
87
|
-
switch (state.type) {
|
|
88
|
-
case `atom`: {
|
|
89
|
-
store.atoms.set(token.key, state)
|
|
90
|
-
store.valueMap.set(token.key, state.default)
|
|
91
|
-
const stateKey = state.key
|
|
92
|
-
const familyKey = state.family?.key
|
|
93
|
-
let timelineKey = core.timelineAtoms.getRelatedKey(stateKey)
|
|
94
|
-
if (timelineKey === undefined && typeof familyKey === `string`) {
|
|
95
|
-
timelineKey = core.timelineAtoms.getRelatedKey(familyKey)
|
|
96
|
-
}
|
|
97
|
-
const timeline =
|
|
98
|
-
typeof timelineKey === `string`
|
|
99
|
-
? store.timelines.get(timelineKey)
|
|
100
|
-
: undefined
|
|
72
|
+
// state =
|
|
73
|
+
// target.atoms.get(token.key) ??
|
|
74
|
+
// core.selectors.get(token.key) ??
|
|
75
|
+
// core.readonlySelectors.get(token.key) ??
|
|
76
|
+
// core.transactions.get(token.key) ??
|
|
77
|
+
// core.timelines.get(token.key)
|
|
101
78
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
79
|
+
// if (state) {
|
|
80
|
+
// store.logger.info(
|
|
81
|
+
// `🛠️`,
|
|
82
|
+
// token.type,
|
|
83
|
+
// token.key,
|
|
84
|
+
// `add ${token.type} "${token.key}"`,
|
|
85
|
+
// )
|
|
86
|
+
// switch (state.type) {
|
|
87
|
+
// case `atom`: {
|
|
88
|
+
// store.atoms.set(token.key, state)
|
|
89
|
+
// store.valueMap.set(token.key, state.default)
|
|
90
|
+
// const stateKey = state.key
|
|
91
|
+
// const familyKey = state.family?.key
|
|
92
|
+
// let timelineKey = core.timelineAtoms.getRelatedKey(stateKey)
|
|
93
|
+
// if (timelineKey === undefined && typeof familyKey === `string`) {
|
|
94
|
+
// timelineKey = core.timelineAtoms.getRelatedKey(familyKey)
|
|
95
|
+
// }
|
|
96
|
+
// const timeline =
|
|
97
|
+
// typeof timelineKey === `string`
|
|
98
|
+
// ? store.timelines.get(timelineKey)
|
|
99
|
+
// : undefined
|
|
100
|
+
|
|
101
|
+
// if (timeline) {
|
|
102
|
+
// addAtomToTimeline(state, timeline, store)
|
|
103
|
+
// }
|
|
104
|
+
// break
|
|
105
|
+
// }
|
|
106
|
+
// case `selector`:
|
|
107
|
+
// core.selectors.set(token.key, state)
|
|
108
|
+
// break
|
|
109
|
+
// case `readonly_selector`:
|
|
110
|
+
// core.readonlySelectors.set(token.key, state)
|
|
111
|
+
// break
|
|
112
|
+
// case `transaction`:
|
|
113
|
+
// core.transactions.set(token.key, state)
|
|
114
|
+
// break
|
|
115
|
+
// case `timeline`:
|
|
116
|
+
// core.timelines.set(token.key, state)
|
|
117
|
+
// break
|
|
118
|
+
// }
|
|
119
|
+
// return state
|
|
120
|
+
// }
|
|
121
|
+
// }
|
|
123
122
|
return undefined
|
|
124
123
|
}
|
package/internal/src/subject.ts
CHANGED
|
@@ -19,3 +19,17 @@ export class Subject<T> {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export class StatefulSubject<T> extends Subject<T> {
|
|
24
|
+
public state: T
|
|
25
|
+
|
|
26
|
+
public constructor(initialState: T) {
|
|
27
|
+
super()
|
|
28
|
+
this.state = initialState
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public next(value: T): void {
|
|
32
|
+
this.state = value
|
|
33
|
+
super.next(value)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
|
+
import { newest } from "../lineage"
|
|
2
3
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
4
|
import type { Store } from "../store"
|
|
4
|
-
import { target } from "../transaction"
|
|
5
5
|
|
|
6
6
|
export const recallState = <T>(
|
|
7
7
|
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
8
8
|
store: Store,
|
|
9
9
|
): T => {
|
|
10
|
-
const
|
|
11
|
-
if (!
|
|
10
|
+
const target = newest(store)
|
|
11
|
+
if (!target.operation.open) {
|
|
12
12
|
store.logger.warn(
|
|
13
13
|
`🐞`,
|
|
14
14
|
state.type,
|
|
15
15
|
state.key,
|
|
16
16
|
`recall called outside of an operation. This is probably a bug.`,
|
|
17
17
|
)
|
|
18
|
-
return
|
|
18
|
+
return target.valueMap.get(state.key)
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return target.operation.prev.get(state.key)
|
|
21
21
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { TransactionUpdate, ƒn } from "atom.io"
|
|
1
2
|
import type { AtomToken, TimelineUpdate } from "atom.io"
|
|
2
3
|
|
|
4
|
+
import { newest } from "../lineage"
|
|
3
5
|
import type { Store } from "../store"
|
|
4
6
|
import { withdraw } from "../store"
|
|
5
|
-
import { target } from "../transaction"
|
|
6
7
|
import type {
|
|
7
8
|
Timeline,
|
|
8
9
|
TimelineAtomUpdate,
|
|
@@ -21,6 +22,7 @@ export const addAtomToTimeline = (
|
|
|
21
22
|
)
|
|
22
23
|
}
|
|
23
24
|
atom.subject.subscribe(`timeline`, (update) => {
|
|
25
|
+
const target = newest(store)
|
|
24
26
|
const currentSelectorKey =
|
|
25
27
|
store.operation.open && store.operation.token.type === `selector`
|
|
26
28
|
? store.operation.token.key
|
|
@@ -30,13 +32,8 @@ export const addAtomToTimeline = (
|
|
|
30
32
|
? store.operation.time
|
|
31
33
|
: null
|
|
32
34
|
const currentTransactionKey =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: null
|
|
36
|
-
const currentTransactionTime =
|
|
37
|
-
store.transactionStatus.phase === `applying`
|
|
38
|
-
? store.transactionStatus.time
|
|
39
|
-
: null
|
|
35
|
+
target.subject.transactionApplying.state?.update.key
|
|
36
|
+
const currentTransactionTime = target.subject.transactionApplying.state?.time
|
|
40
37
|
|
|
41
38
|
store.logger.info(
|
|
42
39
|
`⏳`,
|
|
@@ -54,7 +51,6 @@ export const addAtomToTimeline = (
|
|
|
54
51
|
? `in selector "${currentSelectorKey}"`
|
|
55
52
|
: ``,
|
|
56
53
|
)
|
|
57
|
-
|
|
58
54
|
if (tl.timeTraveling === null) {
|
|
59
55
|
if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
|
|
60
56
|
const mostRecentUpdate: TimelineUpdate | undefined = tl.history.at(-1)
|
|
@@ -64,10 +60,7 @@ export const addAtomToTimeline = (
|
|
|
64
60
|
)
|
|
65
61
|
}
|
|
66
62
|
}
|
|
67
|
-
if (
|
|
68
|
-
currentTransactionKey &&
|
|
69
|
-
store.transactionStatus.phase === `applying`
|
|
70
|
-
) {
|
|
63
|
+
if (currentTransactionKey) {
|
|
71
64
|
const currentTransaction = withdraw(
|
|
72
65
|
{ key: currentTransactionKey, type: `transaction` },
|
|
73
66
|
store,
|
|
@@ -96,26 +89,43 @@ export const addAtomToTimeline = (
|
|
|
96
89
|
tl.history.splice(tl.at)
|
|
97
90
|
}
|
|
98
91
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
const filterUpdates = (
|
|
93
|
+
updates: TransactionUpdate<ƒn>[`updates`],
|
|
94
|
+
) =>
|
|
95
|
+
updates
|
|
96
|
+
.filter((updateFromTx) => {
|
|
97
|
+
const target = newest(store)
|
|
98
|
+
if (`updates` in updateFromTx) {
|
|
99
|
+
return true
|
|
100
|
+
}
|
|
101
|
+
const atomOrFamilyKeys =
|
|
102
|
+
target.timelineAtoms.getRelatedKeys(tl.key)
|
|
103
|
+
|
|
104
|
+
return atomOrFamilyKeys
|
|
105
|
+
? [...atomOrFamilyKeys].some(
|
|
106
|
+
(key) =>
|
|
107
|
+
key === updateFromTx.key ||
|
|
108
|
+
key === updateFromTx.family?.key,
|
|
109
|
+
)
|
|
110
|
+
: false
|
|
111
|
+
})
|
|
112
|
+
.map((updateFromTx) => {
|
|
113
|
+
if (`updates` in updateFromTx) {
|
|
114
|
+
return {
|
|
115
|
+
...updateFromTx,
|
|
116
|
+
updates: filterUpdates(updateFromTx.updates),
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return updateFromTx
|
|
120
|
+
})
|
|
104
121
|
|
|
105
|
-
|
|
106
|
-
? [...atomOrFamilyKeys].some(
|
|
107
|
-
(key) =>
|
|
108
|
-
key === atomUpdate.key ||
|
|
109
|
-
key === atomUpdate.family?.key,
|
|
110
|
-
)
|
|
111
|
-
: false
|
|
112
|
-
})
|
|
122
|
+
const updates = filterUpdates(update.updates)
|
|
113
123
|
|
|
114
124
|
const timelineTransactionUpdate: TimelineTransactionUpdate = {
|
|
115
125
|
type: `transaction_update`,
|
|
116
126
|
timestamp: currentTransactionTime,
|
|
117
127
|
...update,
|
|
118
|
-
|
|
128
|
+
updates,
|
|
119
129
|
}
|
|
120
130
|
const willCapture =
|
|
121
131
|
tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true
|
|
@@ -8,9 +8,9 @@ import type {
|
|
|
8
8
|
ƒn,
|
|
9
9
|
} from "atom.io"
|
|
10
10
|
|
|
11
|
+
import { newest } from "../lineage"
|
|
11
12
|
import type { Store } from "../store"
|
|
12
13
|
import { Subject } from "../subject"
|
|
13
|
-
import { target } from "../transaction"
|
|
14
14
|
import { addAtomToTimeline } from "./add-atom-to-timeline"
|
|
15
15
|
|
|
16
16
|
export type TimelineAtomUpdate = StateUpdate<unknown> & {
|
|
@@ -71,9 +71,9 @@ export function createTimeline(
|
|
|
71
71
|
tl.shouldCapture = options.shouldCapture
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const
|
|
74
|
+
const target = newest(store)
|
|
75
75
|
for (const tokenOrFamily of options.atoms) {
|
|
76
|
-
const timelineKey =
|
|
76
|
+
const timelineKey = target.timelineAtoms.getRelatedKey(tokenOrFamily.key)
|
|
77
77
|
if (timelineKey) {
|
|
78
78
|
store.logger.error(
|
|
79
79
|
`❌`,
|
|
@@ -86,11 +86,9 @@ export function createTimeline(
|
|
|
86
86
|
if (tokenOrFamily.type === `atom_family`) {
|
|
87
87
|
const family = tokenOrFamily
|
|
88
88
|
family.subject.subscribe(`timeline:${options.key}`, (token) => {
|
|
89
|
-
// if (!core.atoms.has(token.key)) {
|
|
90
89
|
addAtomToTimeline(token, tl, store)
|
|
91
|
-
// }
|
|
92
90
|
})
|
|
93
|
-
for (const atom of
|
|
91
|
+
for (const atom of target.atoms.values()) {
|
|
94
92
|
if (atom.family?.key === family.key) {
|
|
95
93
|
addAtomToTimeline(atom, tl, store)
|
|
96
94
|
}
|
|
@@ -98,7 +96,7 @@ export function createTimeline(
|
|
|
98
96
|
} else {
|
|
99
97
|
const token = tokenOrFamily
|
|
100
98
|
if (`family` in token && token.family) {
|
|
101
|
-
const familyTimelineKey =
|
|
99
|
+
const familyTimelineKey = target.timelineAtoms.getRelatedKey(
|
|
102
100
|
token.family.key,
|
|
103
101
|
)
|
|
104
102
|
if (familyTimelineKey) {
|
|
@@ -113,7 +111,7 @@ export function createTimeline(
|
|
|
113
111
|
}
|
|
114
112
|
addAtomToTimeline(token, tl, store)
|
|
115
113
|
}
|
|
116
|
-
|
|
114
|
+
target.timelineAtoms = target.timelineAtoms.set({
|
|
117
115
|
atomKey: tokenOrFamily.key,
|
|
118
116
|
timelineKey: options.key,
|
|
119
117
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TimelineToken } from "atom.io"
|
|
1
|
+
import type { KeyedStateUpdate, TimelineToken, TransactionUpdate } from "atom.io"
|
|
2
2
|
import { setState } from "atom.io"
|
|
3
3
|
|
|
4
4
|
import type { Store } from "../store"
|
|
@@ -50,19 +50,33 @@ export const timeTravel = (
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const update = timelineData.history[timelineData.at]
|
|
53
|
-
const updateValues = (atomUpdate: any) => {
|
|
53
|
+
const updateValues = (atomUpdate: KeyedStateUpdate<any>) => {
|
|
54
54
|
const { key, newValue, oldValue } = atomUpdate
|
|
55
55
|
const value = direction === `forward` ? newValue : oldValue
|
|
56
56
|
setState({ key, type: `atom` }, value, store)
|
|
57
57
|
}
|
|
58
|
+
const updateValuesFromTransactionUpdate = (
|
|
59
|
+
transactionUpdate: TransactionUpdate<any>,
|
|
60
|
+
) => {
|
|
61
|
+
const updates =
|
|
62
|
+
direction === `forward`
|
|
63
|
+
? transactionUpdate.updates
|
|
64
|
+
: [...transactionUpdate.updates].reverse()
|
|
65
|
+
for (const updateFromTransaction of updates) {
|
|
66
|
+
if (`newValue` in updateFromTransaction) {
|
|
67
|
+
updateValues(updateFromTransaction)
|
|
68
|
+
} else {
|
|
69
|
+
updateValuesFromTransactionUpdate(updateFromTransaction)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
58
73
|
|
|
59
74
|
switch (update.type) {
|
|
60
75
|
case `atom_update`: {
|
|
61
76
|
updateValues(update)
|
|
62
77
|
break
|
|
63
78
|
}
|
|
64
|
-
case `selector_update`:
|
|
65
|
-
case `transaction_update`: {
|
|
79
|
+
case `selector_update`: {
|
|
66
80
|
const updates =
|
|
67
81
|
direction === `forward`
|
|
68
82
|
? update.atomUpdates
|
|
@@ -72,6 +86,10 @@ export const timeTravel = (
|
|
|
72
86
|
}
|
|
73
87
|
break
|
|
74
88
|
}
|
|
89
|
+
case `transaction_update`: {
|
|
90
|
+
updateValuesFromTransactionUpdate(update)
|
|
91
|
+
break
|
|
92
|
+
}
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
if (direction === `forward`) {
|