atom.io 0.16.2 → 0.17.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/chunk-H4Q5FTPZ.js +11 -0
- package/dist/chunk-H4Q5FTPZ.js.map +1 -0
- package/dist/index.cjs +35 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +12 -36
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +268 -195
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +36 -11
- package/internal/dist/index.js +258 -195
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-regular-atom.ts +2 -3
- package/internal/src/families/find-in-store.ts +74 -0
- package/internal/src/families/index.ts +1 -0
- package/internal/src/get-state/get-from-store.ts +14 -0
- package/internal/src/get-state/index.ts +2 -0
- package/internal/src/{read-or-compute-value.ts → get-state/read-or-compute-value.ts} +3 -3
- package/internal/src/index.ts +1 -1
- package/internal/src/ingest-updates/ingest-atom-update.ts +2 -2
- package/internal/src/ingest-updates/ingest-transaction-update.ts +1 -0
- package/internal/src/mutable/create-mutable-atom.ts +3 -4
- package/internal/src/mutable/tracker.ts +43 -35
- package/internal/src/mutable/transceiver.ts +1 -1
- package/internal/src/not-found-error.ts +14 -3
- package/internal/src/operation.ts +2 -1
- package/internal/src/selector/create-writable-selector.ts +2 -1
- package/internal/src/selector/register-selector.ts +6 -5
- package/internal/src/set-state/index.ts +1 -0
- package/internal/src/set-state/set-atom.ts +17 -3
- package/internal/src/set-state/set-into-store.ts +24 -0
- package/internal/src/set-state/stow-update.ts +2 -4
- package/internal/src/store/store.ts +13 -4
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +1 -1
- package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
- package/internal/src/transaction/abort-transaction.ts +2 -1
- package/internal/src/transaction/apply-transaction.ts +5 -3
- package/internal/src/transaction/build-transaction.ts +20 -11
- package/internal/src/transaction/create-transaction.ts +2 -3
- package/internal/src/transaction/index.ts +3 -2
- package/internal/src/transaction/is-root-store.ts +23 -0
- package/package.json +10 -10
- package/react/dist/index.cjs +27 -21
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.ts +8 -2
- package/react/dist/index.js +28 -22
- package/react/dist/index.js.map +1 -1
- package/react/src/index.ts +4 -1
- package/react/src/use-i.ts +35 -0
- package/react/src/use-json.ts +38 -0
- package/react/src/use-o.ts +33 -0
- package/react/src/use-tl.ts +45 -0
- package/realtime-client/dist/index.cjs +167 -64
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +10 -6
- package/realtime-client/dist/index.js +158 -63
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/index.ts +2 -1
- package/realtime-client/src/pull-family-member.ts +3 -3
- package/realtime-client/src/pull-mutable-family-member.ts +4 -4
- package/realtime-client/src/pull-mutable.ts +4 -4
- package/realtime-client/src/pull-state.ts +7 -6
- package/realtime-client/src/{realtime-client-store.ts → realtime-client-stores/client-main-store.ts} +0 -8
- package/realtime-client/src/realtime-client-stores/client-sync-store.ts +15 -0
- package/realtime-client/src/realtime-client-stores/index.ts +2 -0
- package/realtime-client/src/sync-server-action.ts +134 -40
- package/realtime-client/src/sync-state.ts +19 -0
- package/realtime-react/dist/index.cjs +43 -26
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +3 -1
- package/realtime-react/dist/index.js +41 -25
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/index.ts +1 -0
- package/realtime-react/src/on-mount.ts +3 -21
- package/realtime-react/src/use-realtime-service.ts +1 -1
- package/realtime-react/src/use-single-effect.ts +29 -0
- package/realtime-react/src/use-sync-server-action.ts +4 -7
- package/realtime-react/src/use-sync.ts +17 -0
- package/realtime-server/dist/index.cjs +239 -56
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.ts +140 -9
- package/realtime-server/dist/index.js +228 -58
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/src/index.ts +2 -0
- package/realtime-server/src/realtime-action-synchronizer.ts +95 -14
- package/realtime-server/src/realtime-family-provider.ts +11 -6
- package/realtime-server/src/realtime-mutable-family-provider.ts +8 -6
- package/realtime-server/src/realtime-mutable-provider.ts +3 -2
- package/realtime-server/src/realtime-server-stores/index.ts +2 -0
- package/realtime-server/src/realtime-server-stores/server-sync-store.ts +115 -0
- package/realtime-server/src/realtime-server-stores/server-user-store.ts +45 -0
- package/realtime-server/src/realtime-state-provider.ts +18 -11
- package/realtime-server/src/realtime-state-receiver.ts +2 -2
- package/realtime-server/src/realtime-state-synchronizer.ts +23 -0
- package/realtime-testing/dist/index.cjs +65 -26
- package/realtime-testing/dist/index.cjs.map +1 -1
- package/realtime-testing/dist/index.d.ts +11 -7
- package/realtime-testing/dist/index.js +64 -26
- package/realtime-testing/dist/index.js.map +1 -1
- package/realtime-testing/src/setup-realtime-test.tsx +83 -43
- package/src/find-state.ts +8 -16
- package/src/get-state.ts +2 -11
- package/src/logger.ts +1 -0
- package/src/set-state.ts +1 -13
- package/src/silo.ts +7 -3
- package/src/transaction.ts +3 -3
- package/react/src/store-hooks.ts +0 -87
- package/realtime-server/src/realtime-server-store.ts +0 -39
|
@@ -5,9 +5,8 @@ import type {
|
|
|
5
5
|
RegularAtomToken,
|
|
6
6
|
UpdateHandler,
|
|
7
7
|
} from "atom.io"
|
|
8
|
-
import { setState } from "atom.io"
|
|
9
8
|
|
|
10
|
-
import type
|
|
9
|
+
import { type RegularAtom, setIntoStore } from ".."
|
|
11
10
|
import { cacheValue } from "../caching"
|
|
12
11
|
import { newest } from "../lineage"
|
|
13
12
|
import type { Store } from "../store"
|
|
@@ -69,7 +68,7 @@ export function createRegularAtom<T>(
|
|
|
69
68
|
const cleanupFunctions: (() => void)[] = []
|
|
70
69
|
for (const effect of options.effects) {
|
|
71
70
|
const cleanup = effect({
|
|
72
|
-
setSelf: (next) =>
|
|
71
|
+
setSelf: (next) => setIntoStore(token, next, store),
|
|
73
72
|
onSet: (handle: UpdateHandler<T>) =>
|
|
74
73
|
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
75
74
|
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Json } from "atom.io/json"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
MutableAtomFamilyToken,
|
|
5
|
+
MutableAtomToken,
|
|
6
|
+
ReadableFamilyToken,
|
|
7
|
+
ReadableToken,
|
|
8
|
+
ReadonlySelectorFamilyToken,
|
|
9
|
+
ReadonlySelectorToken,
|
|
10
|
+
RegularAtomFamilyToken,
|
|
11
|
+
RegularAtomToken,
|
|
12
|
+
WritableFamilyToken,
|
|
13
|
+
WritableSelectorFamilyToken,
|
|
14
|
+
WritableSelectorToken,
|
|
15
|
+
WritableToken,
|
|
16
|
+
} from "atom.io"
|
|
17
|
+
import type { Transceiver } from "../mutable"
|
|
18
|
+
import { NotFoundError } from "../not-found-error"
|
|
19
|
+
import type { Store } from "../store"
|
|
20
|
+
|
|
21
|
+
export function findInStore<
|
|
22
|
+
T extends Transceiver<any>,
|
|
23
|
+
J extends Json.Serializable,
|
|
24
|
+
K extends Json.Serializable,
|
|
25
|
+
Key extends K,
|
|
26
|
+
>(
|
|
27
|
+
token: MutableAtomFamilyToken<T, J, K>,
|
|
28
|
+
key: Key,
|
|
29
|
+
store: Store,
|
|
30
|
+
): MutableAtomToken<T, J>
|
|
31
|
+
|
|
32
|
+
export function findInStore<T, K extends Json.Serializable, Key extends K>(
|
|
33
|
+
token: RegularAtomFamilyToken<T, K>,
|
|
34
|
+
key: Key,
|
|
35
|
+
store: Store,
|
|
36
|
+
): RegularAtomToken<T>
|
|
37
|
+
|
|
38
|
+
export function findInStore<T, K extends Json.Serializable, Key extends K>(
|
|
39
|
+
token: WritableSelectorFamilyToken<T, K>,
|
|
40
|
+
key: Key,
|
|
41
|
+
store: Store,
|
|
42
|
+
): WritableSelectorToken<T>
|
|
43
|
+
|
|
44
|
+
export function findInStore<T, K extends Json.Serializable, Key extends K>(
|
|
45
|
+
token: ReadonlySelectorFamilyToken<T, K>,
|
|
46
|
+
key: Key,
|
|
47
|
+
store: Store,
|
|
48
|
+
): ReadonlySelectorToken<T>
|
|
49
|
+
|
|
50
|
+
export function findInStore<T, K extends Json.Serializable, Key extends K>(
|
|
51
|
+
token: WritableFamilyToken<T, K>,
|
|
52
|
+
key: Key,
|
|
53
|
+
store: Store,
|
|
54
|
+
): WritableToken<T>
|
|
55
|
+
|
|
56
|
+
export function findInStore<T, K extends Json.Serializable, Key extends K>(
|
|
57
|
+
token: ReadableFamilyToken<T, K>,
|
|
58
|
+
key: Key,
|
|
59
|
+
store: Store,
|
|
60
|
+
): ReadableToken<T>
|
|
61
|
+
|
|
62
|
+
export function findInStore(
|
|
63
|
+
token: ReadableFamilyToken<any, any>,
|
|
64
|
+
key: Json.Serializable,
|
|
65
|
+
store: Store,
|
|
66
|
+
): ReadableToken<any> {
|
|
67
|
+
const familyKey = token.key
|
|
68
|
+
const family = store.families.get(familyKey)
|
|
69
|
+
if (family === undefined) {
|
|
70
|
+
throw new NotFoundError(token, store)
|
|
71
|
+
}
|
|
72
|
+
const state = family(key)
|
|
73
|
+
return state
|
|
74
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReadableToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import { NotFoundError } from "../not-found-error"
|
|
4
|
+
import type { Store } from "../store"
|
|
5
|
+
import { withdraw, withdrawNewFamilyMember } from "../store"
|
|
6
|
+
import { readOrComputeValue } from "./read-or-compute-value"
|
|
7
|
+
|
|
8
|
+
export function getFromStore<T>(token: ReadableToken<T>, store: Store): T {
|
|
9
|
+
const state = withdraw(token, store) ?? withdrawNewFamilyMember(token, store)
|
|
10
|
+
if (state === undefined) {
|
|
11
|
+
throw new NotFoundError(token, store)
|
|
12
|
+
}
|
|
13
|
+
return readOrComputeValue(state, store)
|
|
14
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ReadableState } from "
|
|
2
|
-
import { readCachedValue } from "
|
|
3
|
-
import type { Store } from "
|
|
1
|
+
import type { ReadableState } from ".."
|
|
2
|
+
import { readCachedValue } from "../caching"
|
|
3
|
+
import type { Store } from "../store"
|
|
4
4
|
|
|
5
5
|
export const readOrComputeValue = <T>(
|
|
6
6
|
state: ReadableState<T>,
|
package/internal/src/index.ts
CHANGED
|
@@ -11,13 +11,13 @@ export * from "./lineage"
|
|
|
11
11
|
export * from "./families"
|
|
12
12
|
export * from "./future"
|
|
13
13
|
export * from "./get-environment-data"
|
|
14
|
+
export * from "./get-state"
|
|
14
15
|
export * from "./ingest-updates"
|
|
15
16
|
export * from "./keys"
|
|
16
17
|
export * from "./lazy-map"
|
|
17
18
|
export * from "./mutable"
|
|
18
19
|
export * from "./not-found-error"
|
|
19
20
|
export * from "./operation"
|
|
20
|
-
export * from "./read-or-compute-value"
|
|
21
21
|
export * from "./selector"
|
|
22
22
|
export * from "./set-state"
|
|
23
23
|
export * from "./store"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { KeyedStateUpdate } from "atom.io"
|
|
2
|
-
import { setState } from "atom.io"
|
|
3
2
|
|
|
3
|
+
import { setIntoStore } from "../set-state"
|
|
4
4
|
import type { Store } from "../store"
|
|
5
5
|
|
|
6
6
|
export function ingestAtomUpdate(
|
|
@@ -10,5 +10,5 @@ export function ingestAtomUpdate(
|
|
|
10
10
|
): void {
|
|
11
11
|
const { key, newValue, oldValue } = atomUpdate
|
|
12
12
|
const value = applying === `newValue` ? newValue : oldValue
|
|
13
|
-
|
|
13
|
+
setIntoStore({ key, type: `atom` }, value, store)
|
|
14
14
|
}
|
|
@@ -4,12 +4,11 @@ import type {
|
|
|
4
4
|
MutableAtomOptions,
|
|
5
5
|
MutableAtomToken,
|
|
6
6
|
} from "atom.io"
|
|
7
|
-
import { setState } from "atom.io"
|
|
8
7
|
import type { Json } from "atom.io/json"
|
|
9
8
|
import { selectJson } from "atom.io/json"
|
|
10
9
|
|
|
11
|
-
import { type MutableAtom, cacheValue } from ".."
|
|
12
|
-
import {
|
|
10
|
+
import { type MutableAtom, cacheValue, setIntoStore } from ".."
|
|
11
|
+
import { markAtomAsDefault } from "../atom"
|
|
13
12
|
import { newest } from "../lineage"
|
|
14
13
|
import { type Store, deposit } from "../store"
|
|
15
14
|
import { Subject } from "../subject"
|
|
@@ -70,7 +69,7 @@ export function createMutableAtom<
|
|
|
70
69
|
const cleanupFunctions: (() => void)[] = []
|
|
71
70
|
for (const effect of options.effects) {
|
|
72
71
|
const cleanup = effect({
|
|
73
|
-
setSelf: (next) =>
|
|
72
|
+
setSelf: (next) => setIntoStore(token, next, store),
|
|
74
73
|
onSet: (handle: UpdateHandler<T>) =>
|
|
75
74
|
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
76
75
|
})
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { FamilyMetadata, MutableAtomToken, RegularAtomToken } from "atom.io"
|
|
2
|
-
import { getState, setState } from "atom.io"
|
|
3
2
|
import type { Json } from "atom.io/json"
|
|
4
3
|
|
|
5
4
|
import type { Store } from ".."
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getFromStore,
|
|
7
|
+
newest,
|
|
8
|
+
setIntoStore,
|
|
9
|
+
subscribeToState,
|
|
10
|
+
subscribeToTimeline,
|
|
11
|
+
} from ".."
|
|
7
12
|
import { createRegularAtom } from "../atom"
|
|
13
|
+
import { isChildStore } from "../transaction/is-root-store"
|
|
8
14
|
import type { Transceiver } from "./transceiver"
|
|
9
15
|
|
|
10
16
|
/**
|
|
@@ -51,31 +57,26 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
51
57
|
private observeCore(
|
|
52
58
|
mutableState: MutableAtomToken<Mutable, any>,
|
|
53
59
|
latestUpdateState: RegularAtomToken<typeof this.Update | null>,
|
|
54
|
-
|
|
60
|
+
target: Store,
|
|
55
61
|
): void {
|
|
56
|
-
const subscriptionKey = `tracker:${
|
|
57
|
-
|
|
62
|
+
const subscriptionKey = `tracker:${target.config.name}:${
|
|
63
|
+
isChildStore(target) ? target.transactionMeta.update.key : `main`
|
|
58
64
|
}:${mutableState.key}`
|
|
59
|
-
const originalInnerValue =
|
|
60
|
-
const target = newest(store)
|
|
65
|
+
const originalInnerValue = getFromStore(mutableState, target)
|
|
61
66
|
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
62
|
-
|
|
63
|
-
target.transactionMeta === null
|
|
64
|
-
? `main`
|
|
65
|
-
: target.transactionMeta.update.key
|
|
66
|
-
}`,
|
|
67
|
+
subscriptionKey,
|
|
67
68
|
(update) => {
|
|
68
69
|
if (target.operation.open) {
|
|
69
70
|
const unsubscribe = target.on.operationClose.subscribe(
|
|
70
71
|
subscriptionKey,
|
|
71
72
|
() => {
|
|
72
73
|
unsubscribe()
|
|
73
|
-
|
|
74
|
+
setIntoStore(latestUpdateState, update, target)
|
|
74
75
|
},
|
|
75
76
|
)
|
|
76
77
|
} else {
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
setIntoStore(mutableState, (current) => current, target)
|
|
79
|
+
setIntoStore(latestUpdateState, update, target)
|
|
79
80
|
}
|
|
80
81
|
},
|
|
81
82
|
)
|
|
@@ -84,7 +85,6 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
84
85
|
(update) => {
|
|
85
86
|
if (update.newValue !== update.oldValue) {
|
|
86
87
|
this.unsubscribeFromInnerValue()
|
|
87
|
-
const target = newest(store)
|
|
88
88
|
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
89
89
|
subscriptionKey,
|
|
90
90
|
(update) => {
|
|
@@ -93,44 +93,45 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
93
93
|
subscriptionKey,
|
|
94
94
|
() => {
|
|
95
95
|
unsubscribe()
|
|
96
|
-
|
|
96
|
+
setIntoStore(latestUpdateState, update, target)
|
|
97
97
|
},
|
|
98
98
|
)
|
|
99
99
|
} else {
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
setIntoStore(mutableState, (current) => current, target)
|
|
101
|
+
setIntoStore(latestUpdateState, update, target)
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
104
|
)
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
107
|
subscriptionKey,
|
|
108
|
-
|
|
108
|
+
target,
|
|
109
109
|
)
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
private updateCore<Core extends Transceiver<any>>(
|
|
113
113
|
mutableState: MutableAtomToken<Core, Json.Serializable>,
|
|
114
114
|
latestUpdateState: RegularAtomToken<typeof this.Update | null>,
|
|
115
|
-
|
|
115
|
+
target: Store,
|
|
116
116
|
): void {
|
|
117
|
-
const subscriptionKey = `tracker:${
|
|
118
|
-
|
|
117
|
+
const subscriptionKey = `tracker:${target.config.name}:${
|
|
118
|
+
isChildStore(target) ? target.transactionMeta.update.key : `main`
|
|
119
119
|
}:${mutableState.key}`
|
|
120
120
|
subscribeToState(
|
|
121
121
|
latestUpdateState,
|
|
122
122
|
({ newValue, oldValue }) => {
|
|
123
|
-
const timelineId =
|
|
123
|
+
const timelineId = target.timelineAtoms.getRelatedKey(
|
|
124
124
|
latestUpdateState.key,
|
|
125
125
|
)
|
|
126
|
+
|
|
126
127
|
if (timelineId) {
|
|
127
|
-
const timelineData =
|
|
128
|
+
const timelineData = target.timelines.get(timelineId)
|
|
128
129
|
if (timelineData?.timeTraveling) {
|
|
129
130
|
const unsubscribe = subscribeToTimeline(
|
|
130
131
|
{ key: timelineId, type: `timeline` },
|
|
131
132
|
(update) => {
|
|
132
133
|
unsubscribe()
|
|
133
|
-
|
|
134
|
+
setIntoStore(
|
|
134
135
|
mutableState,
|
|
135
136
|
(transceiver) => {
|
|
136
137
|
if (update === `redo` && newValue) {
|
|
@@ -140,38 +141,45 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
140
141
|
}
|
|
141
142
|
return transceiver
|
|
142
143
|
},
|
|
143
|
-
|
|
144
|
+
target,
|
|
144
145
|
)
|
|
145
146
|
},
|
|
146
147
|
subscriptionKey,
|
|
147
|
-
|
|
148
|
+
target,
|
|
148
149
|
)
|
|
149
150
|
return
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
const unsubscribe =
|
|
154
|
+
const unsubscribe = target.on.operationClose.subscribe(
|
|
154
155
|
subscriptionKey,
|
|
155
156
|
() => {
|
|
156
157
|
unsubscribe()
|
|
157
|
-
const mutable =
|
|
158
|
-
// debugger
|
|
158
|
+
const mutable = getFromStore(mutableState, target)
|
|
159
159
|
const updateNumber =
|
|
160
160
|
newValue === null ? -1 : mutable.getUpdateNumber(newValue)
|
|
161
161
|
const eventOffset = updateNumber - mutable.cacheUpdateNumber
|
|
162
162
|
if (newValue && eventOffset === 1) {
|
|
163
|
-
|
|
164
|
-
setState(
|
|
163
|
+
setIntoStore(
|
|
165
164
|
mutableState,
|
|
166
165
|
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
167
|
-
|
|
166
|
+
target,
|
|
167
|
+
)
|
|
168
|
+
} else {
|
|
169
|
+
target.logger.info(
|
|
170
|
+
`❌`,
|
|
171
|
+
`mutable_atom`,
|
|
172
|
+
mutableState.key,
|
|
173
|
+
`could not be updated. Expected update number ${
|
|
174
|
+
mutable.cacheUpdateNumber + 1
|
|
175
|
+
}, but got ${updateNumber}`,
|
|
168
176
|
)
|
|
169
177
|
}
|
|
170
178
|
},
|
|
171
179
|
)
|
|
172
180
|
},
|
|
173
181
|
subscriptionKey,
|
|
174
|
-
|
|
182
|
+
target,
|
|
175
183
|
)
|
|
176
184
|
}
|
|
177
185
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Json } from "atom.io/json"
|
|
2
2
|
|
|
3
3
|
export interface Transceiver<Signal extends Json.Serializable> {
|
|
4
|
-
do: (update: Signal) =>
|
|
4
|
+
do: (update: Signal) => number | `OUT_OF_RANGE` | null
|
|
5
5
|
undo: (update: Signal) => void
|
|
6
6
|
subscribe: (key: string, fn: (update: Signal) => void) => () => void
|
|
7
7
|
cacheUpdateNumber: number
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ReadableFamilyToken,
|
|
3
|
+
ReadableToken,
|
|
4
|
+
TimelineToken,
|
|
5
|
+
TransactionToken,
|
|
6
|
+
} from "atom.io"
|
|
2
7
|
|
|
3
8
|
import type { Store } from "./store"
|
|
4
9
|
|
|
5
10
|
const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1)
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
type AtomIOToken =
|
|
13
|
+
| ReadableFamilyToken<any, any>
|
|
14
|
+
| ReadableToken<any>
|
|
15
|
+
| TimelineToken<any>
|
|
16
|
+
| TransactionToken<any>
|
|
17
|
+
|
|
18
|
+
function prettyPrintTokenType(token: AtomIOToken) {
|
|
8
19
|
if (token.type === `readonly_selector`) {
|
|
9
20
|
return `Readonly Selector`
|
|
10
21
|
}
|
|
@@ -12,7 +23,7 @@ function prettyPrintTokenType(token: ReadableToken<any>) {
|
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
export class NotFoundError extends Error {
|
|
15
|
-
public constructor(token:
|
|
26
|
+
public constructor(token: AtomIOToken, store: Store) {
|
|
16
27
|
super(
|
|
17
28
|
`${prettyPrintTokenType(token)} "${token.key}" not found in store "${
|
|
18
29
|
store.config.name
|
|
@@ -2,6 +2,7 @@ import type { WritableToken } from "atom.io"
|
|
|
2
2
|
|
|
3
3
|
import { newest } from "./lineage"
|
|
4
4
|
import type { Store } from "./store"
|
|
5
|
+
import { isChildStore } from "./transaction/is-root-store"
|
|
5
6
|
|
|
6
7
|
export type OperationProgress =
|
|
7
8
|
| {
|
|
@@ -40,7 +41,7 @@ export const openOperation = (
|
|
|
40
41
|
token.type,
|
|
41
42
|
token.key,
|
|
42
43
|
`operation start in store "${store.config.name}"${
|
|
43
|
-
store
|
|
44
|
+
!isChildStore(store)
|
|
44
45
|
? ``
|
|
45
46
|
: ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`
|
|
46
47
|
}`,
|
|
@@ -11,6 +11,7 @@ import { markDone } from "../operation"
|
|
|
11
11
|
import { become } from "../set-state/become"
|
|
12
12
|
import type { Store } from "../store"
|
|
13
13
|
import { Subject } from "../subject"
|
|
14
|
+
import { isRootStore } from "../transaction/is-root-store"
|
|
14
15
|
import { registerSelector } from "./register-selector"
|
|
15
16
|
|
|
16
17
|
export const createWritableSelector = <T>(
|
|
@@ -45,7 +46,7 @@ export const createWritableSelector = <T>(
|
|
|
45
46
|
)
|
|
46
47
|
cacheValue(options.key, newValue, subject, store)
|
|
47
48
|
markDone(options.key, store)
|
|
48
|
-
if (target
|
|
49
|
+
if (isRootStore(target)) {
|
|
49
50
|
subject.next({ newValue, oldValue })
|
|
50
51
|
}
|
|
51
52
|
options.set(transactors, newValue)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Transactors, findState } from "atom.io"
|
|
2
|
-
import { findInStore } from "atom.io"
|
|
3
2
|
|
|
3
|
+
import { findInStore } from "../families"
|
|
4
|
+
import { readOrComputeValue } from "../get-state/read-or-compute-value"
|
|
4
5
|
import { newest } from "../lineage"
|
|
5
|
-
import { readOrComputeValue } from "../read-or-compute-value"
|
|
6
6
|
import { setAtomOrSelector } from "../set-state"
|
|
7
7
|
import type { Store } from "../store"
|
|
8
|
-
import { withdraw } from "../store"
|
|
8
|
+
import { withdraw, withdrawNewFamilyMember } from "../store"
|
|
9
9
|
import { updateSelectorAtoms } from "./update-selector-atoms"
|
|
10
10
|
|
|
11
11
|
export const registerSelector = (
|
|
@@ -15,10 +15,11 @@ export const registerSelector = (
|
|
|
15
15
|
get: (dependency) => {
|
|
16
16
|
const target = newest(store)
|
|
17
17
|
|
|
18
|
-
const dependencyState =
|
|
18
|
+
const dependencyState =
|
|
19
|
+
withdraw(dependency, store) ?? withdrawNewFamilyMember(dependency, store)
|
|
19
20
|
if (dependencyState === undefined) {
|
|
20
21
|
throw new Error(
|
|
21
|
-
`State "${dependency.key}" not found in
|
|
22
|
+
`State "${dependency.key}" not found in store "${store.config.name}".`,
|
|
22
23
|
)
|
|
23
24
|
}
|
|
24
25
|
const dependencyValue = readOrComputeValue(dependencyState, store)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Atom } from ".."
|
|
2
2
|
import { isAtomDefault, markAtomAsNotDefault } from "../atom"
|
|
3
3
|
import { cacheValue } from "../caching"
|
|
4
|
+
import { readOrComputeValue } from "../get-state/read-or-compute-value"
|
|
4
5
|
import type { Transceiver } from "../mutable"
|
|
5
6
|
import { markDone } from "../operation"
|
|
6
|
-
import { readOrComputeValue } from "../read-or-compute-value"
|
|
7
7
|
import type { Store } from "../store"
|
|
8
|
+
import { isRootStore } from "../transaction/is-root-store"
|
|
8
9
|
import { become } from "./become"
|
|
9
10
|
import { copyMutableIfWithinTransaction } from "./copy-mutable-in-transaction"
|
|
10
11
|
import { emitUpdate } from "./emit-update"
|
|
@@ -27,7 +28,7 @@ export const setAtom = <T>(
|
|
|
27
28
|
markDone(atom.key, target)
|
|
28
29
|
evictDownStream(atom, target)
|
|
29
30
|
const update = { oldValue, newValue }
|
|
30
|
-
if (target
|
|
31
|
+
if (isRootStore(target)) {
|
|
31
32
|
emitUpdate(atom, update, target)
|
|
32
33
|
} else if (target.parent) {
|
|
33
34
|
if (target.on.transactionApplying.state === null) {
|
|
@@ -37,7 +38,20 @@ export const setAtom = <T>(
|
|
|
37
38
|
const mutableAtom = target.atoms.get(mutableKey) as Atom<any>
|
|
38
39
|
let mutable: Transceiver<any> = target.valueMap.get(mutableKey)
|
|
39
40
|
mutable = copyMutableIfWithinTransaction(mutable, mutableAtom, target)
|
|
40
|
-
mutable.do(update.newValue)
|
|
41
|
+
const output = mutable.do(update.newValue)
|
|
42
|
+
if (output !== null) {
|
|
43
|
+
target.logger.warn(
|
|
44
|
+
`❌`,
|
|
45
|
+
`mutable_atom`,
|
|
46
|
+
mutableKey,
|
|
47
|
+
`could not be updated.`,
|
|
48
|
+
typeof output === `number`
|
|
49
|
+
? `Expected update number ${
|
|
50
|
+
mutable.cacheUpdateNumber + 1
|
|
51
|
+
}, but got ${output}`
|
|
52
|
+
: output,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
41
55
|
}
|
|
42
56
|
}
|
|
43
57
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { WritableToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import { NotFoundError } from "../not-found-error"
|
|
4
|
+
import { closeOperation, openOperation } from "../operation"
|
|
5
|
+
import type { Store } from "../store"
|
|
6
|
+
import { withdraw, withdrawNewFamilyMember } from "../store"
|
|
7
|
+
import { setAtomOrSelector } from "./set-atom-or-selector"
|
|
8
|
+
|
|
9
|
+
export function setIntoStore<T, New extends T>(
|
|
10
|
+
token: WritableToken<T>,
|
|
11
|
+
value: New | ((oldValue: T) => New),
|
|
12
|
+
store: Store,
|
|
13
|
+
): void {
|
|
14
|
+
const rejection = openOperation(token, store)
|
|
15
|
+
if (rejection) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
const state = withdraw(token, store) ?? withdrawNewFamilyMember(token, store)
|
|
19
|
+
if (state === undefined) {
|
|
20
|
+
throw new NotFoundError(token, store)
|
|
21
|
+
}
|
|
22
|
+
setAtomOrSelector(state, value, store)
|
|
23
|
+
closeOperation(store)
|
|
24
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { Atom } from ".."
|
|
|
4
4
|
import { newest } from "../lineage"
|
|
5
5
|
import { isTransceiver } from "../mutable"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
|
+
import { isChildStore } from "../transaction/is-root-store"
|
|
7
8
|
|
|
8
9
|
function shouldUpdateBeStowed(key: string, update: StateUpdate<any>): boolean {
|
|
9
10
|
// do not stow updates that aren't json
|
|
@@ -24,10 +25,7 @@ export const stowUpdate = <T>(
|
|
|
24
25
|
): void => {
|
|
25
26
|
const { key } = state
|
|
26
27
|
const target = newest(store)
|
|
27
|
-
if (
|
|
28
|
-
target.transactionMeta === null ||
|
|
29
|
-
target.transactionMeta.phase !== `building`
|
|
30
|
-
) {
|
|
28
|
+
if (!isChildStore(target) || target.transactionMeta.phase !== `building`) {
|
|
31
29
|
store.logger.error(
|
|
32
30
|
`🐞`,
|
|
33
31
|
`atom`,
|
|
@@ -27,7 +27,11 @@ import { getJsonToken, getUpdateToken } from "../mutable"
|
|
|
27
27
|
import type { OperationProgress } from "../operation"
|
|
28
28
|
import { StatefulSubject, Subject } from "../subject"
|
|
29
29
|
import type { Timeline } from "../timeline"
|
|
30
|
-
import type {
|
|
30
|
+
import type {
|
|
31
|
+
Transaction,
|
|
32
|
+
TransactionEpoch,
|
|
33
|
+
TransactionProgress,
|
|
34
|
+
} from "../transaction"
|
|
31
35
|
|
|
32
36
|
export class Store implements Lineage {
|
|
33
37
|
public parent: Store | null = null
|
|
@@ -82,11 +86,15 @@ export class Store implements Lineage {
|
|
|
82
86
|
>(),
|
|
83
87
|
transactionCreation: new Subject<TransactionToken<ƒn>>(),
|
|
84
88
|
timelineCreation: new Subject<TimelineToken<unknown>>(),
|
|
85
|
-
transactionApplying: new StatefulSubject<
|
|
89
|
+
transactionApplying: new StatefulSubject<TransactionProgress<ƒn> | null>(
|
|
90
|
+
null,
|
|
91
|
+
),
|
|
86
92
|
operationClose: new Subject<OperationProgress>(),
|
|
87
93
|
}
|
|
88
94
|
public operation: OperationProgress = { open: false }
|
|
89
|
-
public transactionMeta:
|
|
95
|
+
public transactionMeta: TransactionEpoch | TransactionProgress<ƒn> = {
|
|
96
|
+
epoch: -1,
|
|
97
|
+
}
|
|
90
98
|
|
|
91
99
|
public config: {
|
|
92
100
|
name: string
|
|
@@ -113,7 +121,8 @@ export class Store implements Lineage {
|
|
|
113
121
|
if (store !== null) {
|
|
114
122
|
this.valueMap = new Map(store?.valueMap)
|
|
115
123
|
this.operation = { ...store?.operation }
|
|
116
|
-
this.transactionMeta =
|
|
124
|
+
this.transactionMeta = { ...store?.transactionMeta }
|
|
125
|
+
|
|
117
126
|
this.config = {
|
|
118
127
|
...store?.config,
|
|
119
128
|
name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Selector } from ".."
|
|
2
|
+
import { readOrComputeValue } from "../get-state/read-or-compute-value"
|
|
2
3
|
import { newest } from "../lineage"
|
|
3
|
-
import { readOrComputeValue } from "../read-or-compute-value"
|
|
4
4
|
import { traceAllSelectorAtoms } from "../selector"
|
|
5
5
|
import type { Store } from "../store"
|
|
6
6
|
import { recallState } from "./recall-state"
|
|
@@ -30,7 +30,6 @@ export const addAtomToTimeline = (
|
|
|
30
30
|
store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key })
|
|
31
31
|
|
|
32
32
|
atom.subject.subscribe(`timeline`, (update) => {
|
|
33
|
-
// debugger
|
|
34
33
|
const target = newest(store)
|
|
35
34
|
const currentSelectorKey =
|
|
36
35
|
store.operation.open && store.operation.token.type === `selector`
|
|
@@ -40,8 +39,9 @@ export const addAtomToTimeline = (
|
|
|
40
39
|
store.operation.open && store.operation.token.type === `selector`
|
|
41
40
|
? store.operation.time
|
|
42
41
|
: null
|
|
43
|
-
const
|
|
44
|
-
const
|
|
42
|
+
const { transactionApplying } = target.on
|
|
43
|
+
const currentTransactionKey = transactionApplying.state?.update.key
|
|
44
|
+
const currentTransactionInstanceId = transactionApplying.state?.update.id
|
|
45
45
|
|
|
46
46
|
store.logger.info(
|
|
47
47
|
`⏳`,
|
|
@@ -93,7 +93,7 @@ export const addAtomToTimeline = (
|
|
|
93
93
|
`timeline:${tl.key}`,
|
|
94
94
|
(update) => {
|
|
95
95
|
unsubscribe()
|
|
96
|
-
if (tl.timeTraveling === null &&
|
|
96
|
+
if (tl.timeTraveling === null && currentTransactionInstanceId) {
|
|
97
97
|
if (tl.at !== tl.history.length) {
|
|
98
98
|
tl.history.splice(tl.at)
|
|
99
99
|
}
|
|
@@ -132,7 +132,7 @@ export const addAtomToTimeline = (
|
|
|
132
132
|
|
|
133
133
|
const timelineTransactionUpdate: TimelineTransactionUpdate = {
|
|
134
134
|
type: `transaction_update`,
|
|
135
|
-
timestamp:
|
|
135
|
+
timestamp: Date.now(),
|
|
136
136
|
...update,
|
|
137
137
|
updates,
|
|
138
138
|
}
|