atom.io 0.12.1 → 0.14.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 +9 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -6
- package/dist/index.d.ts +9 -6
- package/dist/index.js +11 -74
- 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 +1700 -1579
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.cts +32 -15
- package/internal/dist/index.d.ts +32 -15
- package/internal/dist/index.js +1695 -1579
- 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 +7 -6
- 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 +8 -6
- package/internal/src/mutable/get-json-family.ts +3 -3
- package/internal/src/mutable/tracker.ts +18 -13
- 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 +4 -4
- 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/index.ts +3 -0
- package/internal/src/subscribe/recall-state.ts +5 -11
- package/internal/src/subscribe/subscribe-to-state.ts +47 -0
- package/internal/src/subscribe/subscribe-to-timeline.ts +28 -0
- package/internal/src/subscribe/subscribe-to-transaction.ts +33 -0
- 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 +8 -8
- package/react/dist/index.cjs +39 -1
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.cts +9 -2
- package/react/dist/index.d.ts +9 -2
- package/react/dist/index.js +41 -4
- package/react/dist/index.js.map +1 -1
- package/react/dist/metafile-cjs.json +1 -1
- package/react/dist/metafile-esm.json +1 -1
- package/react/src/store-hooks.ts +52 -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/realtime-client/dist/index.cjs +8 -7
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.cts +3 -2
- package/realtime-client/dist/index.d.ts +3 -2
- package/realtime-client/dist/index.js +3 -2
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/dist/metafile-cjs.json +1 -1
- package/realtime-client/dist/metafile-esm.json +1 -1
- package/realtime-client/src/use-push.ts +4 -4
- package/realtime-client/src/use-server-action.ts +4 -4
- package/realtime-server/dist/index.cjs +46 -25
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.cts +5 -5
- package/realtime-server/dist/index.d.ts +5 -5
- package/realtime-server/dist/index.js +38 -17
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/dist/metafile-cjs.json +1 -1
- package/realtime-server/dist/metafile-esm.json +1 -1
- package/realtime-server/src/hook-composition/expose-family.ts +7 -3
- package/realtime-server/src/hook-composition/expose-mutable-family.ts +13 -5
- package/realtime-server/src/hook-composition/expose-mutable.ts +11 -3
- package/realtime-server/src/hook-composition/expose-single.ts +6 -2
- package/realtime-server/src/hook-composition/receive-transaction.ts +14 -5
- package/src/subscribe.ts +37 -91
- 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 { ReadonlySelectorToken, StateToken } from "atom.io"
|
|
2
2
|
|
|
3
|
+
import { newest } from "../lineage"
|
|
3
4
|
import type { Store } from "../store"
|
|
4
|
-
import { target } from "../transaction"
|
|
5
5
|
import { traceSelectorAtoms } from "./trace-selector-atoms"
|
|
6
6
|
|
|
7
7
|
export const updateSelectorAtoms = (
|
|
@@ -9,9 +9,9 @@ export const updateSelectorAtoms = (
|
|
|
9
9
|
dependency: ReadonlySelectorToken<unknown> | StateToken<unknown>,
|
|
10
10
|
store: Store,
|
|
11
11
|
): void => {
|
|
12
|
-
const
|
|
12
|
+
const target = newest(store)
|
|
13
13
|
if (dependency.type === `atom`) {
|
|
14
|
-
|
|
14
|
+
target.selectorAtoms.set({
|
|
15
15
|
selectorKey,
|
|
16
16
|
atomKey: dependency.key,
|
|
17
17
|
})
|
|
@@ -32,7 +32,7 @@ export const updateSelectorAtoms = (
|
|
|
32
32
|
.join(`, `)} ]`,
|
|
33
33
|
)
|
|
34
34
|
for (const atomKey of rootKeys) {
|
|
35
|
-
|
|
35
|
+
target.selectorAtoms = target.selectorAtoms.set({
|
|
36
36
|
selectorKey,
|
|
37
37
|
atomKey,
|
|
38
38
|
})
|
|
@@ -2,19 +2,20 @@ import type { JsonInterface } from "atom.io/json"
|
|
|
2
2
|
|
|
3
3
|
import type { Atom } from "../atom"
|
|
4
4
|
import { Tracker } from "../mutable"
|
|
5
|
-
import type { Store
|
|
5
|
+
import type { Store } from "../store"
|
|
6
6
|
|
|
7
7
|
export function copyMutableIfNeeded<T>(
|
|
8
8
|
atom: Atom<T>,
|
|
9
9
|
transform: JsonInterface<T>,
|
|
10
10
|
origin: Store,
|
|
11
|
-
target:
|
|
11
|
+
target: Store,
|
|
12
12
|
): T {
|
|
13
13
|
const originValue = origin.valueMap.get(atom.key)
|
|
14
14
|
const targetValue = target.valueMap.get(atom.key)
|
|
15
15
|
if (originValue === targetValue) {
|
|
16
16
|
origin.logger.info(`📃`, `atom`, `${atom.key}`, `copying`)
|
|
17
|
-
const
|
|
17
|
+
const jsonValue = transform.toJson(originValue)
|
|
18
|
+
const copiedValue = transform.fromJson(jsonValue)
|
|
18
19
|
target.valueMap.set(atom.key, copiedValue)
|
|
19
20
|
new Tracker(atom, origin)
|
|
20
21
|
return copiedValue
|
|
@@ -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,15 @@
|
|
|
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 (!
|
|
12
|
-
|
|
13
|
-
`🐞`,
|
|
14
|
-
state.type,
|
|
15
|
-
state.key,
|
|
16
|
-
`recall called outside of an operation. This is probably a bug.`,
|
|
17
|
-
)
|
|
18
|
-
return core.valueMap.get(state.key)
|
|
10
|
+
const target = newest(store)
|
|
11
|
+
if (!target.operation.open) {
|
|
12
|
+
return target.valueMap.get(state.key)
|
|
19
13
|
}
|
|
20
|
-
return
|
|
14
|
+
return target.operation.prev.get(state.key)
|
|
21
15
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReadonlySelectorToken, StateToken, UpdateHandler } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { subscribeToRootAtoms, withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export function subscribeToState<T>(
|
|
6
|
+
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
7
|
+
handleUpdate: UpdateHandler<T>,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): () => void {
|
|
11
|
+
const state = withdraw<T>(token, store)
|
|
12
|
+
if (state === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
const unsubFunction = state.subject.subscribe(key, handleUpdate)
|
|
18
|
+
store.logger.info(`👀`, state.type, state.key, `Adding subscription "${key}"`)
|
|
19
|
+
const dependencyUnsubFunctions =
|
|
20
|
+
state.type !== `atom` ? subscribeToRootAtoms(state, store) : null
|
|
21
|
+
|
|
22
|
+
const unsubscribe =
|
|
23
|
+
dependencyUnsubFunctions === null
|
|
24
|
+
? () => {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`🙈`,
|
|
27
|
+
state.type,
|
|
28
|
+
state.key,
|
|
29
|
+
`Removing subscription "${key}"`,
|
|
30
|
+
)
|
|
31
|
+
unsubFunction()
|
|
32
|
+
}
|
|
33
|
+
: () => {
|
|
34
|
+
store.logger.info(
|
|
35
|
+
`🙈`,
|
|
36
|
+
state.type,
|
|
37
|
+
state.key,
|
|
38
|
+
`Removing subscription "${key}"`,
|
|
39
|
+
)
|
|
40
|
+
unsubFunction()
|
|
41
|
+
for (const unsubFromDependency of dependencyUnsubFunctions) {
|
|
42
|
+
unsubFromDependency()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return unsubscribe
|
|
47
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TimelineToken, TimelineUpdate } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export const subscribeToTimeline = (
|
|
6
|
+
token: TimelineToken,
|
|
7
|
+
handleUpdate: (update: TimelineUpdate | `redo` | `undo`) => void,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): (() => void) => {
|
|
11
|
+
const tl = withdraw(token, store)
|
|
12
|
+
if (tl === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
store.logger.info(`👀`, `timeline`, token.key, `Adding subscription "${key}"`)
|
|
18
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate)
|
|
19
|
+
return () => {
|
|
20
|
+
store.logger.info(
|
|
21
|
+
`🙈`,
|
|
22
|
+
`timeline`,
|
|
23
|
+
token.key,
|
|
24
|
+
`Removing subscription "${key}" from timeline`,
|
|
25
|
+
)
|
|
26
|
+
unsubscribe()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TransactionToken, TransactionUpdateHandler, ƒn } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export const subscribeToTransaction = <ƒ extends ƒn>(
|
|
6
|
+
token: TransactionToken<ƒ>,
|
|
7
|
+
handleUpdate: TransactionUpdateHandler<ƒ>,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): (() => void) => {
|
|
11
|
+
const tx = withdraw(token, store)
|
|
12
|
+
if (tx === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Cannot subscribe to transaction "${token.key}": transaction not found in store "${store.config.name}".`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
store.logger.info(
|
|
18
|
+
`👀`,
|
|
19
|
+
`transaction`,
|
|
20
|
+
token.key,
|
|
21
|
+
`Adding subscription "${key}"`,
|
|
22
|
+
)
|
|
23
|
+
const unsubscribe = tx.subject.subscribe(key, handleUpdate)
|
|
24
|
+
return () => {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`🙈`,
|
|
27
|
+
`transaction`,
|
|
28
|
+
token.key,
|
|
29
|
+
`Removing subscription "${key}"`,
|
|
30
|
+
)
|
|
31
|
+
unsubscribe()
|
|
32
|
+
}
|
|
33
|
+
}
|