atom.io 0.14.7 → 0.15.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/README.md +5 -0
- package/data/dist/index.cjs +200 -218
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +16 -7
- package/data/dist/index.js +202 -221
- package/data/dist/index.js.map +1 -1
- package/data/src/join.ts +295 -292
- package/data/src/struct-family.ts +2 -2
- package/data/src/struct.ts +2 -2
- package/dist/chunk-S7R5MU6A.js +137 -0
- package/dist/chunk-S7R5MU6A.js.map +1 -0
- package/dist/index.cjs +3 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1 -151
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +275 -200
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +43 -36
- package/internal/dist/index.js +221 -193
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-atom.ts +5 -86
- package/internal/src/atom/create-regular-atom.ts +92 -0
- package/internal/src/atom/index.ts +16 -0
- package/internal/src/atom/is-default.ts +0 -5
- package/internal/src/caching.ts +14 -16
- package/internal/src/families/create-atom-family.ts +20 -46
- package/internal/src/families/create-readonly-selector-family.ts +1 -0
- package/internal/src/families/create-regular-atom-family.ts +72 -0
- package/internal/src/families/create-selector-family.ts +2 -0
- package/internal/src/families/index.ts +1 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
- package/internal/src/mutable/create-mutable-atom.ts +8 -3
- package/internal/src/mutable/get-update-family.ts +1 -1
- package/internal/src/mutable/is-mutable.ts +3 -30
- package/internal/src/mutable/tracker-family.ts +2 -2
- package/internal/src/mutable/tracker.ts +5 -5
- package/internal/src/operation.ts +14 -18
- package/internal/src/selector/create-read-write-selector.ts +2 -3
- package/internal/src/selector/create-selector.ts +1 -1
- package/internal/src/selector/register-selector.ts +9 -14
- package/internal/src/set-state/evict-downstream.ts +3 -5
- package/internal/src/set-state/set-atom.ts +14 -17
- package/internal/src/store/store.ts +23 -19
- package/internal/src/store/withdraw.ts +32 -70
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +5 -3
- package/internal/src/subscribe/subscribe-to-state.ts +5 -3
- package/internal/src/transaction/apply-transaction.ts +20 -2
- package/internal/src/transaction/build-transaction.ts +19 -11
- package/internal/src/transaction/create-transaction.ts +6 -11
- package/internal/src/transaction/index.ts +2 -3
- package/introspection/dist/index.cjs +6 -6
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +3 -3
- package/introspection/dist/index.js +7 -7
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +7 -2
- package/introspection/src/attach-selector-index.ts +7 -2
- package/introspection/src/attach-timeline-family.ts +5 -2
- package/introspection/src/attach-timeline-index.ts +2 -2
- package/introspection/src/attach-transaction-index.ts +2 -2
- package/introspection/src/attach-transaction-logs.ts +2 -2
- package/package.json +10 -8
- package/react/dist/index.cjs +9 -12
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.js +9 -12
- package/react/dist/index.js.map +1 -1
- package/react/src/store-hooks.ts +10 -12
- package/react-devtools/dist/index.d.ts +17 -11
- package/src/atom.ts +8 -17
- package/src/selector.ts +3 -1
- package/src/set-state.ts +1 -3
- package/src/silo.ts +2 -14
- package/src/transaction.ts +17 -6
- package/transceivers/set-rtx/dist/index.cjs +2 -1
- package/transceivers/set-rtx/dist/index.cjs.map +1 -1
- package/transceivers/set-rtx/dist/index.js +2 -1
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/src/set-rtx.ts +2 -1
- package/internal/src/transaction/redo-transaction.ts +0 -27
- package/internal/src/transaction/undo-transaction.ts +0 -27
|
@@ -19,17 +19,16 @@ export const openOperation = (
|
|
|
19
19
|
token: StateToken<any>,
|
|
20
20
|
store: Store,
|
|
21
21
|
): `rejection` | undefined => {
|
|
22
|
-
|
|
23
|
-
if (target.operation.open) {
|
|
22
|
+
if (store.operation.open) {
|
|
24
23
|
store.logger.error(
|
|
25
24
|
`❌`,
|
|
26
25
|
token.type,
|
|
27
26
|
token.key,
|
|
28
|
-
`failed to setState during a setState for "${
|
|
27
|
+
`failed to setState during a setState for "${store.operation.token.key}"`,
|
|
29
28
|
)
|
|
30
29
|
return `rejection`
|
|
31
30
|
}
|
|
32
|
-
|
|
31
|
+
store.operation = {
|
|
33
32
|
open: true,
|
|
34
33
|
done: new Set(),
|
|
35
34
|
prev: new Map(),
|
|
@@ -41,29 +40,27 @@ export const openOperation = (
|
|
|
41
40
|
token.type,
|
|
42
41
|
token.key,
|
|
43
42
|
`operation start in store "${store.config.name}"${
|
|
44
|
-
|
|
43
|
+
store.transactionMeta === null
|
|
45
44
|
? ``
|
|
46
|
-
: ` ${
|
|
45
|
+
: ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`
|
|
47
46
|
}`,
|
|
48
47
|
)
|
|
49
48
|
}
|
|
50
49
|
export const closeOperation = (store: Store): void => {
|
|
51
|
-
|
|
52
|
-
if (target.operation.open) {
|
|
50
|
+
if (store.operation.open) {
|
|
53
51
|
store.logger.info(
|
|
54
52
|
`🔴`,
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
store.operation.token.type,
|
|
54
|
+
store.operation.token.key,
|
|
57
55
|
`operation done in store "${store.config.name}"`,
|
|
58
56
|
)
|
|
59
57
|
}
|
|
60
|
-
|
|
61
|
-
store.subject.operationStatus.next(
|
|
58
|
+
store.operation = { open: false }
|
|
59
|
+
store.subject.operationStatus.next(store.operation)
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
export const isDone = (key: string, store: Store): boolean => {
|
|
65
|
-
|
|
66
|
-
if (!target.operation.open) {
|
|
63
|
+
if (!store.operation.open) {
|
|
67
64
|
store.logger.warn(
|
|
68
65
|
`🐞`,
|
|
69
66
|
`unknown`,
|
|
@@ -72,11 +69,10 @@ export const isDone = (key: string, store: Store): boolean => {
|
|
|
72
69
|
)
|
|
73
70
|
return true
|
|
74
71
|
}
|
|
75
|
-
return
|
|
72
|
+
return store.operation.done.has(key)
|
|
76
73
|
}
|
|
77
74
|
export const markDone = (key: string, store: Store): void => {
|
|
78
|
-
|
|
79
|
-
if (!target.operation.open) {
|
|
75
|
+
if (!store.operation.open) {
|
|
80
76
|
store.logger.warn(
|
|
81
77
|
`🐞`,
|
|
82
78
|
`unknown`,
|
|
@@ -85,5 +81,5 @@ export const markDone = (key: string, store: Store): void => {
|
|
|
85
81
|
)
|
|
86
82
|
return
|
|
87
83
|
}
|
|
88
|
-
|
|
84
|
+
store.operation.done.add(key)
|
|
89
85
|
}
|
|
@@ -21,14 +21,13 @@ export const createReadWriteSelector = <T>(
|
|
|
21
21
|
const { get, set } = registerSelector(options.key, store)
|
|
22
22
|
const getSelf = () => {
|
|
23
23
|
const value = options.get({ get })
|
|
24
|
-
cacheValue(options.key, value, subject, store)
|
|
24
|
+
cacheValue(options.key, value, subject, newest(store))
|
|
25
25
|
return value
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const setSelf = (next: T | ((oldValue: T) => T)): void => {
|
|
29
29
|
const oldValue = getSelf()
|
|
30
30
|
const newValue = become(next)(oldValue)
|
|
31
|
-
// store.logger.info(`📝 set "${options.key}" (`, oldValue, `->`, newValue, `)`)
|
|
32
31
|
store.logger.info(
|
|
33
32
|
`📝`,
|
|
34
33
|
`selector`,
|
|
@@ -55,7 +54,7 @@ export const createReadWriteSelector = <T>(
|
|
|
55
54
|
type: `selector`,
|
|
56
55
|
...(family && { family }),
|
|
57
56
|
}
|
|
58
|
-
target.selectors.set(options.key, mySelector)
|
|
57
|
+
target.selectors.set(options.key, mySelector)
|
|
59
58
|
const initialValue = getSelf()
|
|
60
59
|
store.logger.info(`✨`, mySelector.type, mySelector.key, `=`, initialValue)
|
|
61
60
|
const token: SelectorToken<T> = {
|
|
@@ -54,7 +54,7 @@ export function createSelector<T>(
|
|
|
54
54
|
`❌`,
|
|
55
55
|
existingReadonly ? `readonly_selector` : `selector`,
|
|
56
56
|
options.key,
|
|
57
|
-
`Tried to create selector, but it already exists in the store
|
|
57
|
+
`Tried to create selector, but it already exists in the store.`,
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -13,9 +13,6 @@ export const registerSelector = (
|
|
|
13
13
|
): Transactors => ({
|
|
14
14
|
get: (dependency) => {
|
|
15
15
|
const target = newest(store)
|
|
16
|
-
const alreadyRegistered = target.selectorGraph
|
|
17
|
-
.getRelationEntries({ downstreamSelectorKey: selectorKey })
|
|
18
|
-
.some(([_, { source }]) => source === dependency.key)
|
|
19
16
|
|
|
20
17
|
const dependencyState = withdraw(dependency, store)
|
|
21
18
|
if (dependencyState === undefined) {
|
|
@@ -34,17 +31,15 @@ export const registerSelector = (
|
|
|
34
31
|
`)`,
|
|
35
32
|
)
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
}
|
|
34
|
+
target.selectorGraph.set(
|
|
35
|
+
{
|
|
36
|
+
upstreamSelectorKey: dependency.key,
|
|
37
|
+
downstreamSelectorKey: selectorKey,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
source: dependency.key,
|
|
41
|
+
},
|
|
42
|
+
)
|
|
48
43
|
updateSelectorAtoms(selectorKey, dependency, store)
|
|
49
44
|
return dependencyValue
|
|
50
45
|
},
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { Atom } from "../atom"
|
|
2
2
|
import { evictCachedValue } from "../caching"
|
|
3
|
-
import { newest } from "../lineage"
|
|
4
3
|
import { isDone, markDone } from "../operation"
|
|
5
4
|
import type { Store } from "../store"
|
|
6
5
|
|
|
7
6
|
export const evictDownStream = <T>(atom: Atom<T>, store: Store): void => {
|
|
8
|
-
const
|
|
9
|
-
const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom.key)
|
|
7
|
+
const downstreamKeys = store.selectorAtoms.getRelatedKeys(atom.key)
|
|
10
8
|
store.logger.info(
|
|
11
9
|
`🧹`,
|
|
12
10
|
atom.type,
|
|
@@ -17,12 +15,12 @@ export const evictDownStream = <T>(atom: Atom<T>, store: Store): void => {
|
|
|
17
15
|
downstreamKeys ?? `to evict`,
|
|
18
16
|
)
|
|
19
17
|
if (downstreamKeys) {
|
|
20
|
-
if (
|
|
18
|
+
if (store.operation.open) {
|
|
21
19
|
store.logger.info(
|
|
22
20
|
`🧹`,
|
|
23
21
|
atom.type,
|
|
24
22
|
atom.key,
|
|
25
|
-
`[ ${[...
|
|
23
|
+
`[ ${[...store.operation.done].join(`, `)} ] already done`,
|
|
26
24
|
)
|
|
27
25
|
}
|
|
28
26
|
for (const key of downstreamKeys) {
|
|
@@ -1,7 +1,6 @@
|
|
|
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"
|
|
5
4
|
import { markDone } from "../operation"
|
|
6
5
|
import { readOrComputeValue } from "../read-or-compute-value"
|
|
7
6
|
import type { Store } from "../store"
|
|
@@ -14,26 +13,24 @@ import { stowUpdate } from "./stow-update"
|
|
|
14
13
|
export const setAtom = <T>(
|
|
15
14
|
atom: Atom<T>,
|
|
16
15
|
next: T | ((oldValue: T) => T),
|
|
17
|
-
|
|
16
|
+
target: Store,
|
|
18
17
|
): void => {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
let newValue = copyMutableIfWithinTransaction(oldValue, atom, store)
|
|
18
|
+
const oldValue = readOrComputeValue(atom, target)
|
|
19
|
+
let newValue = copyMutableIfWithinTransaction(oldValue, atom, target)
|
|
22
20
|
newValue = become(next)(newValue)
|
|
23
|
-
|
|
24
|
-
newValue = cacheValue(atom.key, newValue, atom.subject,
|
|
25
|
-
if (isAtomDefault(atom.key,
|
|
26
|
-
markAtomAsNotDefault(atom.key,
|
|
21
|
+
target.logger.info(`📝`, `atom`, atom.key, `set to`, newValue)
|
|
22
|
+
newValue = cacheValue(atom.key, newValue, atom.subject, target)
|
|
23
|
+
if (isAtomDefault(atom.key, target)) {
|
|
24
|
+
markAtomAsNotDefault(atom.key, target)
|
|
27
25
|
}
|
|
28
|
-
markDone(atom.key,
|
|
29
|
-
evictDownStream(atom,
|
|
26
|
+
markDone(atom.key, target)
|
|
27
|
+
evictDownStream(atom, target)
|
|
30
28
|
const update = { oldValue, newValue }
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
emitUpdate(atom, update, store)
|
|
29
|
+
if (target.transactionMeta === null) {
|
|
30
|
+
emitUpdate(atom, update, target)
|
|
31
|
+
} else if (target.transactionMeta.phase === `applying` && target.parent) {
|
|
32
|
+
emitUpdate(atom, update, target.parent)
|
|
36
33
|
} else {
|
|
37
|
-
stowUpdate(atom, update,
|
|
34
|
+
stowUpdate(atom, update, target)
|
|
38
35
|
}
|
|
39
36
|
}
|
|
@@ -16,30 +16,19 @@ import { Junction } from "~/packages/rel8/junction/src"
|
|
|
16
16
|
|
|
17
17
|
import type { Atom } from "../atom"
|
|
18
18
|
import type { Lineage } from "../lineage"
|
|
19
|
-
import
|
|
19
|
+
import {
|
|
20
|
+
type MutableAtom,
|
|
21
|
+
type Tracker,
|
|
22
|
+
type Transceiver,
|
|
23
|
+
getJsonToken,
|
|
24
|
+
getUpdateToken,
|
|
25
|
+
} from "../mutable"
|
|
20
26
|
import type { OperationProgress } from "../operation"
|
|
21
27
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
22
28
|
import { StatefulSubject, Subject } from "../subject"
|
|
23
29
|
import type { Timeline } from "../timeline"
|
|
24
30
|
import type { Transaction, TransactionMeta } from "../transaction"
|
|
25
31
|
|
|
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
32
|
export class Store implements Lineage {
|
|
44
33
|
public parent: Store | null = null
|
|
45
34
|
public child: Store | null = null
|
|
@@ -130,14 +119,29 @@ export class Store implements Lineage {
|
|
|
130
119
|
...store?.config,
|
|
131
120
|
name,
|
|
132
121
|
}
|
|
133
|
-
|
|
122
|
+
for (const [, family] of store.families) {
|
|
123
|
+
family.install(this)
|
|
124
|
+
}
|
|
125
|
+
const mutableHelpers = new Set<string>()
|
|
134
126
|
for (const [, atom] of store.atoms) {
|
|
127
|
+
if (mutableHelpers.has(atom.key)) {
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
135
130
|
atom.install(this)
|
|
131
|
+
if (`mutable` in atom) {
|
|
132
|
+
const originalJsonToken = getJsonToken(atom)
|
|
133
|
+
const originalUpdateToken = getUpdateToken(atom)
|
|
134
|
+
mutableHelpers.add(originalJsonToken.key)
|
|
135
|
+
mutableHelpers.add(originalUpdateToken.key)
|
|
136
|
+
}
|
|
136
137
|
}
|
|
137
138
|
for (const [, selector] of store.readonlySelectors) {
|
|
138
139
|
selector.install(this)
|
|
139
140
|
}
|
|
140
141
|
for (const [, selector] of store.selectors) {
|
|
142
|
+
if (mutableHelpers.has(selector.key)) {
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
141
145
|
selector.install(this)
|
|
142
146
|
}
|
|
143
147
|
for (const [, tx] of store.transactions) {
|
|
@@ -9,12 +9,18 @@ import type {
|
|
|
9
9
|
} from "atom.io"
|
|
10
10
|
|
|
11
11
|
import type { Atom } from "../atom"
|
|
12
|
-
import { newest } from "../lineage"
|
|
13
12
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
14
13
|
import type { Timeline } from "../timeline"
|
|
15
14
|
import type { Transaction } from "../transaction"
|
|
16
15
|
import type { Store } from "./store"
|
|
17
16
|
|
|
17
|
+
type Withdrawable<T> =
|
|
18
|
+
| Atom<T>
|
|
19
|
+
| ReadonlySelector<T>
|
|
20
|
+
| Selector<T>
|
|
21
|
+
| Timeline
|
|
22
|
+
| Transaction<T extends ƒn ? T : never>
|
|
23
|
+
|
|
18
24
|
export function withdraw<T>(
|
|
19
25
|
token: AtomToken<T>,
|
|
20
26
|
store: Store,
|
|
@@ -50,74 +56,30 @@ export function withdraw<T>(
|
|
|
50
56
|
| TimelineToken
|
|
51
57
|
| TransactionToken<T>,
|
|
52
58
|
store: Store,
|
|
53
|
-
):
|
|
54
|
-
|
|
55
|
-
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
): Withdrawable<T> | undefined {
|
|
60
|
+
let withdrawn: Withdrawable<T> | undefined
|
|
61
|
+
let target: Store | null = store
|
|
62
|
+
while (target !== null) {
|
|
63
|
+
switch (token.type) {
|
|
64
|
+
case `atom`:
|
|
65
|
+
withdrawn = target.atoms.get(token.key)
|
|
66
|
+
break
|
|
67
|
+
case `selector`:
|
|
68
|
+
withdrawn = target.selectors.get(token.key)
|
|
69
|
+
break
|
|
70
|
+
case `readonly_selector`:
|
|
71
|
+
withdrawn = target.readonlySelectors.get(token.key)
|
|
72
|
+
break
|
|
73
|
+
case `timeline`:
|
|
74
|
+
withdrawn = target.timelines.get(token.key)
|
|
75
|
+
break
|
|
76
|
+
case `transaction`:
|
|
77
|
+
withdrawn = target.transactions.get(token.key)
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
if (withdrawn) {
|
|
81
|
+
return withdrawn
|
|
82
|
+
}
|
|
83
|
+
target = target.child
|
|
69
84
|
}
|
|
70
|
-
// if (target.transactionMeta?.phase === `applying`) {
|
|
71
|
-
|
|
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)
|
|
78
|
-
|
|
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
|
-
// }
|
|
122
|
-
return undefined
|
|
123
85
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { newest } from "../lineage"
|
|
1
2
|
import { readOrComputeValue } from "../read-or-compute-value"
|
|
2
3
|
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
4
|
import { traceAllSelectorAtoms } from "../selector"
|
|
@@ -8,11 +9,12 @@ export const subscribeToRootAtoms = <T>(
|
|
|
8
9
|
state: ReadonlySelector<T> | Selector<T>,
|
|
9
10
|
store: Store,
|
|
10
11
|
): (() => void)[] | null => {
|
|
12
|
+
const target = newest(store)
|
|
11
13
|
const dependencySubscriptions =
|
|
12
14
|
`default` in state
|
|
13
15
|
? null
|
|
14
16
|
: traceAllSelectorAtoms(state.key, store).map((atomKey) => {
|
|
15
|
-
const atom =
|
|
17
|
+
const atom = target.atoms.get(atomKey)
|
|
16
18
|
if (atom === undefined) {
|
|
17
19
|
throw new Error(
|
|
18
20
|
`Atom "${atomKey}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`,
|
|
@@ -32,9 +34,9 @@ export const subscribeToRootAtoms = <T>(
|
|
|
32
34
|
`->`,
|
|
33
35
|
atomChange.newValue,
|
|
34
36
|
)
|
|
35
|
-
const oldValue = recallState(state,
|
|
37
|
+
const oldValue = recallState(state, target)
|
|
36
38
|
// ❌ this retrieves a stale cached value when applying a transaction on the server
|
|
37
|
-
const newValue = readOrComputeValue(state,
|
|
39
|
+
const newValue = readOrComputeValue(state, target)
|
|
38
40
|
store.logger.info(
|
|
39
41
|
`✨`,
|
|
40
42
|
state.type,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReadonlySelectorToken, StateToken, UpdateHandler } from "atom.io"
|
|
2
|
-
import type { Store } from "
|
|
3
|
-
import {
|
|
2
|
+
import type { Store } from "../store"
|
|
3
|
+
import { withdraw, withdrawNewFamilyMember } from "../store"
|
|
4
|
+
import { subscribeToRootAtoms } from "./subscribe-to-root-atoms"
|
|
4
5
|
|
|
5
6
|
export function subscribeToState<T>(
|
|
6
7
|
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
@@ -8,7 +9,8 @@ export function subscribeToState<T>(
|
|
|
8
9
|
key: string,
|
|
9
10
|
store: Store,
|
|
10
11
|
): () => void {
|
|
11
|
-
const state =
|
|
12
|
+
const state =
|
|
13
|
+
withdraw<T>(token, store) ?? withdrawNewFamilyMember(token, store)
|
|
12
14
|
if (state === undefined) {
|
|
13
15
|
throw new Error(
|
|
14
16
|
`State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
@@ -82,8 +82,27 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
82
82
|
`Applying transaction with ${updates.length} updates:`,
|
|
83
83
|
updates,
|
|
84
84
|
)
|
|
85
|
+
for (const tracker of child.trackers.values()) {
|
|
86
|
+
const mutableKey = tracker.mutableState.key
|
|
87
|
+
if (!parent.atoms.has(mutableKey)) {
|
|
88
|
+
const atom = child.atoms.get(mutableKey)
|
|
89
|
+
atom?.install(parent)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const atom of child.atoms.values()) {
|
|
93
|
+
if (!parent.atoms.has(atom.key)) {
|
|
94
|
+
parent.atoms.set(atom.key, atom)
|
|
95
|
+
parent.valueMap.set(atom.key, atom.default)
|
|
96
|
+
parent.logger.info(
|
|
97
|
+
`🔨`,
|
|
98
|
+
`transaction`,
|
|
99
|
+
child.transactionMeta.update.key,
|
|
100
|
+
`Adding atom "${atom.key}"`,
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
ingestTransactionUpdate(child.transactionMeta.update, parent, child)
|
|
85
105
|
if (parent.transactionMeta === null) {
|
|
86
|
-
ingestTransactionUpdate(child.transactionMeta.update, parent, child)
|
|
87
106
|
const myTransaction = withdraw<ƒ>(
|
|
88
107
|
{ key: child.transactionMeta.update.key, type: `transaction` },
|
|
89
108
|
store,
|
|
@@ -96,7 +115,6 @@ export const applyTransaction = <ƒ extends ƒn>(
|
|
|
96
115
|
`Finished applying transaction.`,
|
|
97
116
|
)
|
|
98
117
|
} else {
|
|
99
|
-
ingestTransactionUpdate(child.transactionMeta.update, parent, child)
|
|
100
118
|
parent.transactionMeta.update.updates.push(child.transactionMeta.update)
|
|
101
119
|
}
|
|
102
120
|
parent.subject.transactionApplying.next(null)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Junction } from "~/packages/rel8/junction/src"
|
|
2
2
|
|
|
3
|
+
import { getState, runTransaction, setState } from "~/packages/atom.io/src"
|
|
3
4
|
import { LazyMap } from "../lazy-map"
|
|
4
5
|
import { newest } from "../lineage"
|
|
5
6
|
import type { Store } from "../store"
|
|
@@ -10,23 +11,14 @@ export const buildTransaction = (
|
|
|
10
11
|
store: Store,
|
|
11
12
|
): void => {
|
|
12
13
|
const parent = newest(store)
|
|
13
|
-
|
|
14
|
+
const child: Store = {
|
|
14
15
|
parent,
|
|
15
16
|
child: null,
|
|
16
17
|
subject: parent.subject,
|
|
17
18
|
loggers: parent.loggers,
|
|
18
19
|
logger: parent.logger,
|
|
19
20
|
config: parent.config,
|
|
20
|
-
transactionMeta:
|
|
21
|
-
phase: `building`,
|
|
22
|
-
time: Date.now(),
|
|
23
|
-
update: {
|
|
24
|
-
key,
|
|
25
|
-
updates: [],
|
|
26
|
-
params,
|
|
27
|
-
output: undefined,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
21
|
+
transactionMeta: null,
|
|
30
22
|
atoms: new LazyMap(parent.atoms),
|
|
31
23
|
atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
|
|
32
24
|
families: new LazyMap(parent.families),
|
|
@@ -43,6 +35,22 @@ export const buildTransaction = (
|
|
|
43
35
|
selectors: new LazyMap(parent.selectors),
|
|
44
36
|
valueMap: new LazyMap(parent.valueMap),
|
|
45
37
|
}
|
|
38
|
+
child.transactionMeta = {
|
|
39
|
+
phase: `building`,
|
|
40
|
+
time: Date.now(),
|
|
41
|
+
update: {
|
|
42
|
+
key,
|
|
43
|
+
updates: [],
|
|
44
|
+
params,
|
|
45
|
+
output: undefined,
|
|
46
|
+
},
|
|
47
|
+
transactors: {
|
|
48
|
+
get: (token) => getState(token, child),
|
|
49
|
+
set: (token, value) => setState(token, value, child),
|
|
50
|
+
run: (token) => runTransaction(token, child),
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
parent.child = child
|
|
46
54
|
store.logger.info(
|
|
47
55
|
`🛫`,
|
|
48
56
|
`transaction`,
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
TransactionUpdate,
|
|
5
5
|
ƒn,
|
|
6
6
|
} from "atom.io"
|
|
7
|
-
import { getState, runTransaction, setState } from "atom.io"
|
|
8
7
|
|
|
9
8
|
import { newest } from "../lineage"
|
|
10
9
|
import { deposit } from "../store"
|
|
@@ -32,18 +31,14 @@ export function createTransaction<ƒ extends ƒn>(
|
|
|
32
31
|
run: (...params: Parameters<ƒ>) => {
|
|
33
32
|
buildTransaction(options.key, params, store)
|
|
34
33
|
try {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
...params,
|
|
42
|
-
)
|
|
43
|
-
applyTransaction(output, store)
|
|
34
|
+
const target = newest(store)
|
|
35
|
+
// biome-ignore lint/style/noNonNullAssertion: this happens right above
|
|
36
|
+
const { transactors } = target.transactionMeta!
|
|
37
|
+
const output = options.do(transactors, ...params)
|
|
38
|
+
applyTransaction(output, target)
|
|
44
39
|
return output
|
|
45
40
|
} catch (thrown) {
|
|
46
|
-
abortTransaction(
|
|
41
|
+
abortTransaction(target)
|
|
47
42
|
store.logger.warn(`💥`, `transaction`, options.key, `caught:`, thrown)
|
|
48
43
|
throw thrown
|
|
49
44
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import type { TransactionUpdate, ƒn } from "atom.io"
|
|
1
|
+
import type { TransactionUpdate, TransactorsWithRun, ƒn } from "atom.io"
|
|
2
2
|
|
|
3
3
|
export * from "./abort-transaction"
|
|
4
4
|
export * from "./apply-transaction"
|
|
5
5
|
export * from "./build-transaction"
|
|
6
6
|
export * from "./create-transaction"
|
|
7
|
-
export * from "./redo-transaction"
|
|
8
|
-
export * from "./undo-transaction"
|
|
9
7
|
|
|
10
8
|
export const TRANSACTION_PHASES = [`idle`, `building`, `applying`] as const
|
|
11
9
|
export type TransactionPhase = (typeof TRANSACTION_PHASES)[number]
|
|
@@ -14,4 +12,5 @@ export type TransactionMeta<ƒ extends ƒn> = {
|
|
|
14
12
|
phase: `applying` | `building`
|
|
15
13
|
time: number
|
|
16
14
|
update: TransactionUpdate<ƒ>
|
|
15
|
+
transactors: TransactorsWithRun
|
|
17
16
|
}
|
|
@@ -42,7 +42,7 @@ var __spreadValues = (a, b) => {
|
|
|
42
42
|
};
|
|
43
43
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
44
44
|
var attachAtomIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
45
|
-
const atomTokenIndexState__INTERNAL = Internal.
|
|
45
|
+
const atomTokenIndexState__INTERNAL = Internal.createRegularAtom(
|
|
46
46
|
{
|
|
47
47
|
key: `\u{1F441}\u200D\u{1F5E8} Atom Token Index (Internal)`,
|
|
48
48
|
default: () => {
|
|
@@ -109,7 +109,7 @@ var attachAtomIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
|
109
109
|
);
|
|
110
110
|
};
|
|
111
111
|
var attachSelectorIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
112
|
-
const readonlySelectorTokenIndexState__INTERNAL = Internal.
|
|
112
|
+
const readonlySelectorTokenIndexState__INTERNAL = Internal.createRegularAtom(
|
|
113
113
|
{
|
|
114
114
|
key: `\u{1F441}\u200D\u{1F5E8} Selector Token Index (Internal)`,
|
|
115
115
|
default: () => Object.assign(
|
|
@@ -182,7 +182,7 @@ var attachSelectorIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
|
182
182
|
);
|
|
183
183
|
};
|
|
184
184
|
var attachTimelineFamily = (store = Internal.IMPLICIT.STORE) => {
|
|
185
|
-
const findTimelineLogState__INTERNAL = Internal.
|
|
185
|
+
const findTimelineLogState__INTERNAL = Internal.createRegularAtomFamily(
|
|
186
186
|
{
|
|
187
187
|
key: `\u{1F441}\u200D\u{1F5E8} Timeline Update Log (Internal)`,
|
|
188
188
|
default: (key) => {
|
|
@@ -233,7 +233,7 @@ var attachTimelineFamily = (store = Internal.IMPLICIT.STORE) => {
|
|
|
233
233
|
return findTimelineLogState;
|
|
234
234
|
};
|
|
235
235
|
var attachTimelineIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
236
|
-
const timelineTokenIndexState__INTERNAL = Internal.
|
|
236
|
+
const timelineTokenIndexState__INTERNAL = Internal.createRegularAtom(
|
|
237
237
|
{
|
|
238
238
|
key: `\u{1F441}\u200D\u{1F5E8} Timeline Token Index (Internal)`,
|
|
239
239
|
default: () => [...store.timelines].map(([key]) => {
|
|
@@ -264,7 +264,7 @@ var attachTimelineIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
|
264
264
|
return timelineTokenIndex;
|
|
265
265
|
};
|
|
266
266
|
var attachTransactionIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
267
|
-
const transactionTokenIndexState__INTERNAL = Internal.
|
|
267
|
+
const transactionTokenIndexState__INTERNAL = Internal.createRegularAtom(
|
|
268
268
|
{
|
|
269
269
|
key: `\u{1F441}\u200D\u{1F5E8} Transaction Token Index (Internal)`,
|
|
270
270
|
default: () => [...store.transactions].map(([key]) => {
|
|
@@ -295,7 +295,7 @@ var attachTransactionIndex = (store = Internal.IMPLICIT.STORE) => {
|
|
|
295
295
|
return transactionTokenIndex;
|
|
296
296
|
};
|
|
297
297
|
var attachTransactionLogs = (store = Internal.IMPLICIT.STORE) => {
|
|
298
|
-
const findTransactionUpdateLog = Internal.
|
|
298
|
+
const findTransactionUpdateLog = Internal.createRegularAtomFamily(
|
|
299
299
|
{
|
|
300
300
|
key: `\u{1F441}\u200D\u{1F5E8} Transaction Update Log (Internal)`,
|
|
301
301
|
default: () => [],
|