atom.io 0.6.8 → 0.7.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 +21 -2
- package/dist/index.d.mts +42 -461
- package/dist/index.d.ts +42 -461
- package/dist/index.js +128 -1792
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -1742
- package/dist/index.mjs.map +1 -1
- package/internal/dist/index.d.mts +342 -0
- package/internal/dist/index.d.ts +342 -0
- package/internal/dist/index.js +1873 -0
- package/internal/dist/index.js.map +1 -0
- package/internal/dist/index.mjs +1798 -0
- package/internal/dist/index.mjs.map +1 -0
- package/internal/package.json +15 -0
- package/internal/src/atom/create-atom.ts +75 -0
- package/internal/src/atom/delete-atom.ts +10 -0
- package/internal/src/atom/index.ts +3 -0
- package/{src/internal → internal/src/atom}/is-default.ts +4 -2
- package/internal/src/caching.ts +21 -0
- package/internal/src/families/create-atom-family.ts +59 -0
- package/internal/src/families/create-readonly-selector-family.ts +45 -0
- package/internal/src/families/create-selector-family.ts +67 -0
- package/internal/src/families/index.ts +3 -0
- package/internal/src/get-state-internal.ts +23 -0
- package/internal/src/index.ts +13 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +25 -0
- package/internal/src/mutable/create-mutable-atom.ts +49 -0
- package/internal/src/mutable/get-json-token.ts +22 -0
- package/internal/src/mutable/get-update-token.ts +20 -0
- package/internal/src/mutable/index.ts +17 -0
- package/internal/src/mutable/is-atom-token-mutable.ts +7 -0
- package/internal/src/mutable/tracker-family.ts +61 -0
- package/internal/src/mutable/tracker.ts +164 -0
- package/internal/src/mutable/transceiver.ts +110 -0
- package/internal/src/operation.ts +68 -0
- package/{src/internal → internal/src}/selector/create-read-write-selector.ts +10 -13
- package/{src/internal → internal/src}/selector/create-readonly-selector.ts +9 -8
- package/internal/src/selector/create-selector.ts +65 -0
- package/{src/internal → internal/src}/selector/index.ts +1 -0
- package/internal/src/selector/lookup-selector-sources.ts +20 -0
- package/{src/internal → internal/src}/selector/register-selector.ts +13 -9
- package/{src/internal → internal/src}/selector/trace-selector-atoms.ts +4 -2
- package/{src/internal → internal/src}/selector/update-selector-atoms.ts +4 -3
- package/internal/src/set-state/become.ts +10 -0
- package/internal/src/set-state/copy-mutable-if-needed.ts +23 -0
- package/internal/src/set-state/copy-mutable-in-transaction.ts +59 -0
- package/internal/src/set-state/copy-mutable-into-new-store.ts +34 -0
- package/internal/src/set-state/emit-update.ts +23 -0
- package/internal/src/set-state/evict-downstream.ts +39 -0
- package/internal/src/set-state/index.ts +2 -0
- package/internal/src/set-state/set-atom-state.ts +38 -0
- package/internal/src/set-state/set-selector-state.ts +19 -0
- package/internal/src/set-state/set-state-internal.ts +18 -0
- package/internal/src/set-state/stow-update.ts +42 -0
- package/internal/src/store/deposit.ts +43 -0
- package/internal/src/store/index.ts +5 -0
- package/internal/src/store/lookup.ts +26 -0
- package/internal/src/store/store.ts +154 -0
- package/internal/src/store/withdraw-new-family-member.ts +53 -0
- package/internal/src/store/withdraw.ts +113 -0
- package/internal/src/subject.ts +21 -0
- package/internal/src/subscribe/index.ts +1 -0
- package/internal/src/subscribe/recall-state.ts +19 -0
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +47 -0
- package/{src/internal → internal/src}/timeline/add-atom-to-timeline.ts +50 -29
- package/internal/src/timeline/index.ts +3 -0
- package/{src/internal → internal/src/timeline}/time-travel-internal.ts +6 -6
- package/{src/internal → internal/src/timeline}/timeline-internal.ts +20 -12
- package/{src/internal → internal/src}/transaction/abort-transaction.ts +1 -1
- package/{src/internal → internal/src}/transaction/apply-transaction.ts +25 -18
- package/{src/internal → internal/src}/transaction/build-transaction.ts +12 -6
- package/{src/internal → internal/src}/transaction/index.ts +3 -2
- package/{src/internal → internal/src}/transaction/redo-transaction.ts +4 -5
- package/{src/internal → internal/src/transaction}/transaction-internal.ts +16 -13
- package/{src/internal → internal/src}/transaction/undo-transaction.ts +4 -5
- package/introspection/dist/index.d.mts +12 -260
- package/introspection/dist/index.d.ts +12 -260
- package/introspection/dist/index.js +125 -140
- package/introspection/dist/index.js.map +1 -1
- package/introspection/dist/index.mjs +103 -116
- package/introspection/dist/index.mjs.map +1 -1
- package/{src/introspection → introspection/src}/attach-atom-index.ts +41 -30
- package/{src/introspection → introspection/src}/attach-introspection-states.ts +6 -10
- package/introspection/src/attach-selector-index.ts +90 -0
- package/{src/introspection → introspection/src}/attach-timeline-family.ts +16 -16
- package/introspection/src/attach-timeline-index.ts +38 -0
- package/introspection/src/attach-transaction-index.ts +40 -0
- package/{src/introspection → introspection/src}/attach-transaction-logs.ts +11 -8
- package/json/dist/index.d.mts +41 -2
- package/json/dist/index.d.ts +41 -2
- package/json/dist/index.js +88 -48
- package/json/dist/index.js.map +1 -1
- package/json/dist/index.mjs +76 -13
- package/json/dist/index.mjs.map +1 -1
- package/json/src/index.ts +5 -0
- package/json/src/select-json-family.ts +35 -0
- package/json/src/select-json.ts +22 -0
- package/package.json +105 -57
- package/react/dist/index.d.mts +9 -17
- package/react/dist/index.d.ts +9 -17
- package/react/dist/index.js +45 -77
- package/react/dist/index.js.map +1 -1
- package/react/dist/index.mjs +18 -34
- package/react/dist/index.mjs.map +1 -1
- package/react/src/store-context.tsx +12 -0
- package/react/src/store-hooks.ts +36 -0
- package/react-devtools/dist/index.css +1 -1
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +199 -230
- package/react-devtools/dist/index.d.ts +199 -230
- package/react-devtools/dist/index.js +610 -2466
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +543 -2401
- package/react-devtools/dist/index.mjs.map +1 -1
- package/{src/react-devtools → react-devtools/src}/AtomIODevtools.tsx +5 -3
- package/{src/react-devtools → react-devtools/src}/Button.tsx +2 -3
- package/{src/react-devtools → react-devtools/src}/StateEditor.tsx +3 -2
- package/{src/react-devtools → react-devtools/src}/StateIndex.tsx +7 -4
- package/{src/react-devtools → react-devtools/src}/TimelineIndex.tsx +7 -11
- package/{src/react-devtools → react-devtools/src}/TransactionIndex.tsx +4 -4
- package/{src/react-devtools → react-devtools/src}/Updates.tsx +9 -4
- package/{src/react-devtools → react-devtools/src}/index.ts +5 -5
- package/realtime-react/dist/index.d.mts +9 -25
- package/realtime-react/dist/index.d.ts +9 -25
- package/realtime-react/dist/index.js +75 -193
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/dist/index.mjs +44 -148
- package/realtime-react/dist/index.mjs.map +1 -1
- package/realtime-react/src/index.ts +7 -0
- package/{src/realtime-react → realtime-react/src}/realtime-context.tsx +3 -4
- package/realtime-react/src/use-pull-family-member.ts +15 -0
- package/realtime-react/src/use-pull-mutable-family-member.ts +20 -0
- package/realtime-react/src/use-pull-mutable.ts +17 -0
- package/realtime-react/src/use-pull.ts +15 -0
- package/realtime-react/src/use-push.ts +19 -0
- package/realtime-react/src/use-server-action.ts +18 -0
- package/realtime-testing/dist/index.d.mts +49 -0
- package/realtime-testing/dist/index.d.ts +49 -0
- package/realtime-testing/dist/index.js +147 -0
- package/realtime-testing/dist/index.js.map +1 -0
- package/realtime-testing/dist/index.mjs +116 -0
- package/realtime-testing/dist/index.mjs.map +1 -0
- package/{src/realtime-testing → realtime-testing/src}/setup-realtime-test.tsx +10 -8
- package/src/atom.ts +64 -8
- package/src/index.ts +36 -29
- package/src/logger.ts +7 -7
- package/src/selector.ts +5 -5
- package/src/silo.ts +49 -43
- package/src/subscribe.ts +27 -22
- package/src/timeline.ts +9 -4
- package/src/transaction.ts +3 -4
- package/transceivers/set-rtx/dist/index.d.mts +39 -0
- package/transceivers/set-rtx/dist/index.d.ts +39 -0
- package/transceivers/set-rtx/dist/index.js +213 -0
- package/transceivers/set-rtx/dist/index.js.map +1 -0
- package/transceivers/set-rtx/dist/index.mjs +211 -0
- package/transceivers/set-rtx/dist/index.mjs.map +1 -0
- package/{realtime → transceivers/set-rtx}/package.json +1 -1
- package/transceivers/set-rtx/src/index.ts +1 -0
- package/transceivers/set-rtx/src/set-rtx.ts +242 -0
- package/realtime/dist/index.d.mts +0 -25
- package/realtime/dist/index.d.ts +0 -25
- package/realtime/dist/index.js +0 -190
- package/realtime/dist/index.js.map +0 -1
- package/realtime/dist/index.mjs +0 -151
- package/realtime/dist/index.mjs.map +0 -1
- package/src/internal/atom-internal.ts +0 -54
- package/src/internal/families-internal.ts +0 -144
- package/src/internal/get.ts +0 -129
- package/src/internal/index.ts +0 -15
- package/src/internal/operation.ts +0 -139
- package/src/internal/selector/lookup-selector-sources.ts +0 -16
- package/src/internal/selector-internal.ts +0 -58
- package/src/internal/set.ts +0 -99
- package/src/internal/store.ts +0 -151
- package/src/internal/subscribe-internal.ts +0 -88
- package/src/internal/timeline/index.ts +0 -1
- package/src/introspection/attach-selector-index.ts +0 -77
- package/src/introspection/attach-timeline-index.ts +0 -36
- package/src/introspection/attach-transaction-index.ts +0 -38
- package/src/json/index.ts +0 -1
- package/src/json/select-json.ts +0 -18
- package/src/react/store-context.tsx +0 -13
- package/src/react/store-hooks.ts +0 -47
- package/src/react-explorer/AtomIOExplorer.tsx +0 -218
- package/src/react-explorer/explorer-effects.ts +0 -20
- package/src/react-explorer/explorer-states.ts +0 -217
- package/src/react-explorer/index.ts +0 -23
- package/src/react-explorer/space-states.ts +0 -72
- package/src/react-explorer/view-states.ts +0 -41
- package/src/realtime/README.md +0 -33
- package/src/realtime/hook-composition/expose-family.ts +0 -101
- package/src/realtime/hook-composition/expose-single.ts +0 -38
- package/src/realtime/hook-composition/expose-timeline.ts +0 -60
- package/src/realtime/hook-composition/index.ts +0 -12
- package/src/realtime/hook-composition/receive-state.ts +0 -29
- package/src/realtime/hook-composition/receive-transaction.ts +0 -18
- package/src/realtime/index.ts +0 -1
- package/src/realtime-react/index.ts +0 -3
- package/src/realtime-react/realtime-hooks.ts +0 -39
- package/src/realtime-react/realtime-state.ts +0 -10
- package/src/realtime-react/use-pull-family-member.ts +0 -26
- package/src/realtime-react/use-pull-family.ts +0 -24
- package/src/realtime-react/use-pull.ts +0 -24
- package/src/realtime-react/use-push.ts +0 -27
- package/src/realtime-react/use-server-action.ts +0 -33
- package/src/tracker/index.ts +0 -3
- package/src/tracker/tracker.ts +0 -61
- package/src/web-effects/index.ts +0 -1
- package/src/web-effects/storage.ts +0 -30
- /package/{src/introspection → introspection/src}/index.ts +0 -0
- /package/{src/react → react/src}/index.ts +0 -0
- /package/{src/react-devtools → react-devtools/src}/devtools.scss +0 -0
- /package/{src/realtime-testing → realtime-testing/src}/index.ts +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomFamily,
|
|
3
|
+
AtomToken,
|
|
4
|
+
Logger,
|
|
5
|
+
ReadonlySelectorFamily,
|
|
6
|
+
ReadonlySelectorToken,
|
|
7
|
+
SelectorFamily,
|
|
8
|
+
SelectorToken,
|
|
9
|
+
TimelineToken,
|
|
10
|
+
TransactionToken,
|
|
11
|
+
ƒn,
|
|
12
|
+
} from "atom.io"
|
|
13
|
+
|
|
14
|
+
import { Junction } from "~/packages/rel8/junction/src"
|
|
15
|
+
|
|
16
|
+
import type { Atom } from "../atom"
|
|
17
|
+
import type { MutableAtom, Tracker, Transceiver } from "../mutable"
|
|
18
|
+
import type { OperationProgress } from "../operation"
|
|
19
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
20
|
+
import { Subject } from "../subject"
|
|
21
|
+
import type { Timeline } from "../timeline"
|
|
22
|
+
import type { Transaction, TransactionStatus } from "../transaction"
|
|
23
|
+
|
|
24
|
+
export type StoreCore = Pick<
|
|
25
|
+
Store,
|
|
26
|
+
| `atoms`
|
|
27
|
+
| `atomsThatAreDefault`
|
|
28
|
+
| `families`
|
|
29
|
+
| `operation`
|
|
30
|
+
| `readonlySelectors`
|
|
31
|
+
| `selectorAtoms`
|
|
32
|
+
| `selectorGraph`
|
|
33
|
+
| `selectors`
|
|
34
|
+
| `timelineAtoms`
|
|
35
|
+
| `timelines`
|
|
36
|
+
| `trackers`
|
|
37
|
+
| `transactions`
|
|
38
|
+
| `valueMap`
|
|
39
|
+
>
|
|
40
|
+
|
|
41
|
+
export class Store {
|
|
42
|
+
public valueMap = new Map<string, any>()
|
|
43
|
+
|
|
44
|
+
public atoms = new Map<string, Atom<any> | MutableAtom<any>>()
|
|
45
|
+
public selectors = new Map<string, Selector<any>>()
|
|
46
|
+
public readonlySelectors = new Map<string, ReadonlySelector<any>>()
|
|
47
|
+
|
|
48
|
+
public trackers = new Map<string, Tracker<Transceiver<any>>>()
|
|
49
|
+
public families = new Map<
|
|
50
|
+
string,
|
|
51
|
+
| AtomFamily<any, any>
|
|
52
|
+
| ReadonlySelectorFamily<any, any>
|
|
53
|
+
| SelectorFamily<any, any>
|
|
54
|
+
>()
|
|
55
|
+
|
|
56
|
+
public timelines = new Map<string, Timeline>()
|
|
57
|
+
public transactions = new Map<string, Transaction<ƒn>>()
|
|
58
|
+
|
|
59
|
+
public atomsThatAreDefault = new Set<string>()
|
|
60
|
+
|
|
61
|
+
public timelineAtoms = new Junction({
|
|
62
|
+
between: [`timelineKey`, `atomKey`],
|
|
63
|
+
cardinality: `1:n`,
|
|
64
|
+
})
|
|
65
|
+
public selectorAtoms = new Junction({
|
|
66
|
+
between: [`selectorKey`, `atomKey`],
|
|
67
|
+
cardinality: `n:n`,
|
|
68
|
+
})
|
|
69
|
+
public selectorGraph = new Junction<
|
|
70
|
+
`upstreamSelectorKey`,
|
|
71
|
+
`downstreamSelectorKey`,
|
|
72
|
+
{ source: string }
|
|
73
|
+
>(
|
|
74
|
+
{
|
|
75
|
+
between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
|
|
76
|
+
cardinality: `n:n`,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
makeContentKey: (...keys) => keys.sort().join(`:`),
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
public subject = {
|
|
84
|
+
atomCreation: new Subject<AtomToken<unknown>>(),
|
|
85
|
+
selectorCreation: new Subject<
|
|
86
|
+
ReadonlySelectorToken<unknown> | SelectorToken<unknown>
|
|
87
|
+
>(),
|
|
88
|
+
transactionCreation: new Subject<TransactionToken<ƒn>>(),
|
|
89
|
+
timelineCreation: new Subject<TimelineToken>(),
|
|
90
|
+
operationStatus: new Subject<OperationProgress>(),
|
|
91
|
+
}
|
|
92
|
+
public operation: OperationProgress = { open: false }
|
|
93
|
+
public transactionStatus: TransactionStatus<ƒn> = { phase: `idle` }
|
|
94
|
+
|
|
95
|
+
public config: {
|
|
96
|
+
name: string
|
|
97
|
+
logger: Logger | null
|
|
98
|
+
logger__INTERNAL: Logger
|
|
99
|
+
} = {
|
|
100
|
+
name: `IMPLICIT_STORE`,
|
|
101
|
+
logger: { ...console, info: () => undefined },
|
|
102
|
+
logger__INTERNAL: console,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public constructor(name: string, store: Store | null = null) {
|
|
106
|
+
if (store !== null) {
|
|
107
|
+
this.valueMap = new Map(store?.valueMap)
|
|
108
|
+
|
|
109
|
+
this.operation = { ...store?.operation }
|
|
110
|
+
this.transactionStatus = { ...store?.transactionStatus }
|
|
111
|
+
this.config = {
|
|
112
|
+
...store?.config,
|
|
113
|
+
logger__INTERNAL: console,
|
|
114
|
+
logger: {
|
|
115
|
+
...console,
|
|
116
|
+
info: () => undefined,
|
|
117
|
+
...store?.config?.logger,
|
|
118
|
+
},
|
|
119
|
+
name,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
store?.atoms.forEach((atom) => {
|
|
124
|
+
atom.install(this)
|
|
125
|
+
})
|
|
126
|
+
store?.readonlySelectors.forEach((selector) => {
|
|
127
|
+
selector.install(this)
|
|
128
|
+
})
|
|
129
|
+
store?.selectors.forEach((selector) => {
|
|
130
|
+
selector.install(this)
|
|
131
|
+
})
|
|
132
|
+
store?.transactions.forEach((tx) => {
|
|
133
|
+
tx.install(this)
|
|
134
|
+
})
|
|
135
|
+
store?.timelines.forEach((timeline) => {
|
|
136
|
+
timeline.install(this)
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const IMPLICIT = {
|
|
142
|
+
STORE_INTERNAL: undefined as Store | undefined,
|
|
143
|
+
get STORE(): Store {
|
|
144
|
+
return (
|
|
145
|
+
this.STORE_INTERNAL ?? (this.STORE_INTERNAL = new Store(`IMPLICIT_STORE`))
|
|
146
|
+
)
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const clearStore = (store: Store = IMPLICIT.STORE): void => {
|
|
151
|
+
const { config } = store
|
|
152
|
+
Object.assign(store, new Store(config.name))
|
|
153
|
+
store.config = config
|
|
154
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomToken,
|
|
3
|
+
ReadonlySelectorToken,
|
|
4
|
+
SelectorToken,
|
|
5
|
+
StateToken,
|
|
6
|
+
} from "atom.io"
|
|
7
|
+
import type { Atom, ReadonlySelector, Selector, Store } from ".."
|
|
8
|
+
import { withdraw } from ".."
|
|
9
|
+
import { target } from "../transaction"
|
|
10
|
+
|
|
11
|
+
export function withdrawNewFamilyMember<T>(
|
|
12
|
+
token: AtomToken<T>,
|
|
13
|
+
store: Store,
|
|
14
|
+
): Atom<T> | null
|
|
15
|
+
export function withdrawNewFamilyMember<T>(
|
|
16
|
+
token: SelectorToken<T>,
|
|
17
|
+
store: Store,
|
|
18
|
+
): Selector<T> | null
|
|
19
|
+
export function withdrawNewFamilyMember<T>(
|
|
20
|
+
token: ReadonlySelectorToken<T>,
|
|
21
|
+
store: Store,
|
|
22
|
+
): ReadonlySelector<T> | null
|
|
23
|
+
export function withdrawNewFamilyMember<T>(
|
|
24
|
+
token: StateToken<T>,
|
|
25
|
+
store: Store,
|
|
26
|
+
): Atom<T> | Selector<T> | null
|
|
27
|
+
export function withdrawNewFamilyMember<T>(
|
|
28
|
+
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
29
|
+
store: Store,
|
|
30
|
+
): Atom<T> | ReadonlySelector<T> | Selector<T> | null
|
|
31
|
+
export function withdrawNewFamilyMember<T>(
|
|
32
|
+
token:
|
|
33
|
+
| AtomToken<T>
|
|
34
|
+
| ReadonlySelectorToken<T>
|
|
35
|
+
| SelectorToken<T>
|
|
36
|
+
| StateToken<T>,
|
|
37
|
+
store: Store,
|
|
38
|
+
): Atom<T> | ReadonlySelector<T> | Selector<T> | null {
|
|
39
|
+
store.config.logger?.info(
|
|
40
|
+
`👪 creating new family member "${token.key}" in store "${store.config.name}"`,
|
|
41
|
+
)
|
|
42
|
+
if (token.family) {
|
|
43
|
+
const core = target(store)
|
|
44
|
+
const family = core.families.get(token.family.key)
|
|
45
|
+
if (family) {
|
|
46
|
+
const jsonSubKey = JSON.parse(token.family.subKey)
|
|
47
|
+
family(jsonSubKey)
|
|
48
|
+
const state = withdraw(token, store)
|
|
49
|
+
return state
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomToken,
|
|
3
|
+
ReadonlySelectorToken,
|
|
4
|
+
SelectorToken,
|
|
5
|
+
StateToken,
|
|
6
|
+
TimelineToken,
|
|
7
|
+
TransactionToken,
|
|
8
|
+
ƒn,
|
|
9
|
+
} from "atom.io"
|
|
10
|
+
|
|
11
|
+
import type { Atom } from "../atom"
|
|
12
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
13
|
+
import { addAtomToTimeline } from "../timeline"
|
|
14
|
+
import type { Timeline } from "../timeline"
|
|
15
|
+
import type { Transaction } from "../transaction"
|
|
16
|
+
import { target } from "../transaction"
|
|
17
|
+
import type { Store } from "./store"
|
|
18
|
+
|
|
19
|
+
export function withdraw<T>(token: AtomToken<T>, store: Store): Atom<T> | null
|
|
20
|
+
export function withdraw<T>(
|
|
21
|
+
token: SelectorToken<T>,
|
|
22
|
+
store: Store,
|
|
23
|
+
): Selector<T> | null
|
|
24
|
+
export function withdraw<T>(
|
|
25
|
+
token: StateToken<T>,
|
|
26
|
+
store: Store,
|
|
27
|
+
): Atom<T> | Selector<T> | null
|
|
28
|
+
export function withdraw<T>(
|
|
29
|
+
token: ReadonlySelectorToken<T>,
|
|
30
|
+
store: Store,
|
|
31
|
+
): ReadonlySelector<T> | null
|
|
32
|
+
export function withdraw<T>(
|
|
33
|
+
token: TransactionToken<T>,
|
|
34
|
+
store: Store,
|
|
35
|
+
): Transaction<T extends ƒn ? T : never> | null
|
|
36
|
+
export function withdraw<T>(
|
|
37
|
+
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
38
|
+
store: Store,
|
|
39
|
+
): Atom<T> | ReadonlySelector<T> | Selector<T> | null
|
|
40
|
+
export function withdraw<T>(token: TimelineToken, store: Store): Timeline | null
|
|
41
|
+
export function withdraw<T>(
|
|
42
|
+
token:
|
|
43
|
+
| ReadonlySelectorToken<T>
|
|
44
|
+
| StateToken<T>
|
|
45
|
+
| TimelineToken
|
|
46
|
+
| TransactionToken<T>,
|
|
47
|
+
store: Store,
|
|
48
|
+
):
|
|
49
|
+
| Atom<T>
|
|
50
|
+
| ReadonlySelector<T>
|
|
51
|
+
| Selector<T>
|
|
52
|
+
| Timeline
|
|
53
|
+
| Transaction<T extends ƒn ? T : never>
|
|
54
|
+
| null {
|
|
55
|
+
let core = target(store)
|
|
56
|
+
let state =
|
|
57
|
+
core.atoms.get(token.key) ??
|
|
58
|
+
core.selectors.get(token.key) ??
|
|
59
|
+
core.readonlySelectors.get(token.key) ??
|
|
60
|
+
core.transactions.get(token.key) ??
|
|
61
|
+
core.timelines.get(token.key)
|
|
62
|
+
if (state) {
|
|
63
|
+
return state
|
|
64
|
+
}
|
|
65
|
+
if (store.transactionStatus.phase === `applying`) {
|
|
66
|
+
core = store.transactionStatus.core
|
|
67
|
+
state =
|
|
68
|
+
core.atoms.get(token.key) ??
|
|
69
|
+
core.selectors.get(token.key) ??
|
|
70
|
+
core.readonlySelectors.get(token.key) ??
|
|
71
|
+
core.transactions.get(token.key) ??
|
|
72
|
+
core.timelines.get(token.key)
|
|
73
|
+
|
|
74
|
+
if (state) {
|
|
75
|
+
store.config.logger?.info(`🛠️ add ${token.type} "${token.key}"`)
|
|
76
|
+
switch (state.type) {
|
|
77
|
+
case `atom`: {
|
|
78
|
+
store.atoms.set(token.key, state)
|
|
79
|
+
store.valueMap.set(token.key, state.default)
|
|
80
|
+
const stateKey = state.key
|
|
81
|
+
const familyKey = state.family?.key
|
|
82
|
+
let timelineKey = core.timelineAtoms.getRelatedKey(stateKey)
|
|
83
|
+
if (timelineKey === undefined && typeof familyKey === `string`) {
|
|
84
|
+
timelineKey = core.timelineAtoms.getRelatedKey(familyKey)
|
|
85
|
+
}
|
|
86
|
+
const timeline =
|
|
87
|
+
typeof timelineKey === `string`
|
|
88
|
+
? store.timelines.get(timelineKey)
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
if (timeline) {
|
|
92
|
+
addAtomToTimeline(state, timeline, store)
|
|
93
|
+
}
|
|
94
|
+
break
|
|
95
|
+
}
|
|
96
|
+
case `selector`:
|
|
97
|
+
core.selectors.set(token.key, state)
|
|
98
|
+
break
|
|
99
|
+
case `readonly_selector`:
|
|
100
|
+
core.readonlySelectors.set(token.key, state)
|
|
101
|
+
break
|
|
102
|
+
case `transaction`:
|
|
103
|
+
core.transactions.set(token.key, state)
|
|
104
|
+
break
|
|
105
|
+
case `timeline`:
|
|
106
|
+
core.timelines.set(token.key, state)
|
|
107
|
+
break
|
|
108
|
+
}
|
|
109
|
+
return state
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export class Subject<T> {
|
|
2
|
+
public Subscriber: (value: T) => void
|
|
3
|
+
|
|
4
|
+
public subscribers: Map<string, this[`Subscriber`]> = new Map()
|
|
5
|
+
|
|
6
|
+
public subscribe(key: string, subscriber: this[`Subscriber`]): () => void {
|
|
7
|
+
this.subscribers.set(key, subscriber)
|
|
8
|
+
const unsubscribe = () => this.unsubscribe(key)
|
|
9
|
+
return unsubscribe
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
private unsubscribe(key: string) {
|
|
13
|
+
this.subscribers.delete(key)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public next(value: T): void {
|
|
17
|
+
for (const subscriber of this.subscribers.values()) {
|
|
18
|
+
subscriber(value)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./subscribe-to-root-atoms"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Atom } from "../atom"
|
|
2
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { IMPLICIT } from "../store"
|
|
5
|
+
import { target } from "../transaction"
|
|
6
|
+
|
|
7
|
+
export const recallState = <T>(
|
|
8
|
+
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
9
|
+
store: Store = IMPLICIT.STORE,
|
|
10
|
+
): T => {
|
|
11
|
+
const core = target(store)
|
|
12
|
+
if (!core.operation.open) {
|
|
13
|
+
store.config.logger?.warn(
|
|
14
|
+
`recall called outside of an operation. This is probably a bug.`,
|
|
15
|
+
)
|
|
16
|
+
return core.valueMap.get(state.key)
|
|
17
|
+
}
|
|
18
|
+
return core.operation.prev.get(state.key)
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getState__INTERNAL } from "../get-state-internal"
|
|
2
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
3
|
+
import { traceAllSelectorAtoms } from "../selector"
|
|
4
|
+
import type { Store } from "../store"
|
|
5
|
+
import { withdraw } from "../store"
|
|
6
|
+
import { recallState } from "./recall-state"
|
|
7
|
+
|
|
8
|
+
export const subscribeToRootAtoms = <T>(
|
|
9
|
+
state: ReadonlySelector<T> | Selector<T>,
|
|
10
|
+
store: Store,
|
|
11
|
+
): (() => void)[] | null => {
|
|
12
|
+
const dependencySubscriptions =
|
|
13
|
+
`default` in state
|
|
14
|
+
? null
|
|
15
|
+
: traceAllSelectorAtoms(state.key, store).map((atomToken) => {
|
|
16
|
+
const atom = withdraw(atomToken, store)
|
|
17
|
+
if (atom === null) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Atom "${atomToken.key}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
return atom.subject.subscribe(
|
|
23
|
+
`${state.type}:${state.key}`,
|
|
24
|
+
(atomChange) => {
|
|
25
|
+
store.config.logger?.info(
|
|
26
|
+
`📢 selector "${state.key}" saw root "${atomToken.key}" go (`,
|
|
27
|
+
atomChange.oldValue,
|
|
28
|
+
`->`,
|
|
29
|
+
atomChange.newValue,
|
|
30
|
+
`)`,
|
|
31
|
+
)
|
|
32
|
+
const oldValue = recallState(state, store)
|
|
33
|
+
// ❗ this retrieves a stale cached value when applying a transaction on the server
|
|
34
|
+
const newValue = getState__INTERNAL(state, store)
|
|
35
|
+
store.config.logger?.info(
|
|
36
|
+
` <- "${state.key}" went (`,
|
|
37
|
+
oldValue,
|
|
38
|
+
`->`,
|
|
39
|
+
newValue,
|
|
40
|
+
`)`,
|
|
41
|
+
)
|
|
42
|
+
state.subject.next({ newValue, oldValue })
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
return dependencySubscriptions
|
|
47
|
+
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AtomToken, TimelineUpdate } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { IMPLICIT, withdraw } from "../store"
|
|
5
|
+
import { target } from "../transaction"
|
|
2
6
|
import type {
|
|
3
7
|
Timeline,
|
|
4
|
-
Store,
|
|
5
|
-
TimelineTransactionUpdate,
|
|
6
8
|
TimelineAtomUpdate,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
TimelineTransactionUpdate,
|
|
10
|
+
} from "./timeline-internal"
|
|
9
11
|
|
|
10
12
|
export const addAtomToTimeline = (
|
|
11
13
|
atomToken: AtomToken<any>,
|
|
12
|
-
atoms: (AtomFamily<any> | AtomToken<any>)[],
|
|
13
14
|
tl: Timeline,
|
|
14
15
|
store: Store = IMPLICIT.STORE,
|
|
15
16
|
): void => {
|
|
@@ -19,7 +20,7 @@ export const addAtomToTimeline = (
|
|
|
19
20
|
`Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`,
|
|
20
21
|
)
|
|
21
22
|
}
|
|
22
|
-
atom.subject.subscribe((update) => {
|
|
23
|
+
atom.subject.subscribe(`timeline`, (update) => {
|
|
23
24
|
const currentSelectorKey =
|
|
24
25
|
store.operation.open && store.operation.token.type === `selector`
|
|
25
26
|
? store.operation.token.key
|
|
@@ -78,29 +79,46 @@ export const addAtomToTimeline = (
|
|
|
78
79
|
)
|
|
79
80
|
}
|
|
80
81
|
tl.transactionKey = currentTransactionKey
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
const unsubscribe = currentTransaction.subject.subscribe(
|
|
83
|
+
`timeline:${tl.key}`,
|
|
84
|
+
(update) => {
|
|
85
|
+
unsubscribe()
|
|
86
|
+
if (tl.timeTraveling === null && currentTransactionTime) {
|
|
87
|
+
if (tl.at !== tl.history.length) {
|
|
88
|
+
tl.history.splice(tl.at)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const atomUpdates = update.atomUpdates.filter((atomUpdate) => {
|
|
92
|
+
const core = target(store)
|
|
93
|
+
const atomOrFamilyKeys = core.timelineAtoms.getRelatedKeys(
|
|
94
|
+
tl.key,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return atomOrFamilyKeys
|
|
98
|
+
? [...atomOrFamilyKeys].some(
|
|
99
|
+
(key) =>
|
|
100
|
+
key === atomUpdate.key ||
|
|
101
|
+
key === atomUpdate.family?.key,
|
|
102
|
+
)
|
|
103
|
+
: false
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const timelineTransactionUpdate: TimelineTransactionUpdate = {
|
|
107
|
+
type: `transaction_update`,
|
|
108
|
+
timestamp: currentTransactionTime,
|
|
109
|
+
...update,
|
|
110
|
+
atomUpdates,
|
|
111
|
+
}
|
|
112
|
+
tl.history.push(timelineTransactionUpdate)
|
|
113
|
+
tl.at = tl.history.length
|
|
114
|
+
tl.subject.next(timelineTransactionUpdate)
|
|
94
115
|
}
|
|
95
|
-
tl.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
`⌛ timeline "${tl.key}" got a transaction_update "${update.key}"`,
|
|
102
|
-
)
|
|
103
|
-
})
|
|
116
|
+
tl.transactionKey = null
|
|
117
|
+
store.config.logger?.info(
|
|
118
|
+
`⌛ timeline "${tl.key}" got a transaction_update "${update.key}"`,
|
|
119
|
+
)
|
|
120
|
+
},
|
|
121
|
+
)
|
|
104
122
|
}
|
|
105
123
|
} else if (currentSelectorKey && currentSelectorTime) {
|
|
106
124
|
let latestUpdate: TimelineUpdate | undefined = tl.history.at(-1)
|
|
@@ -156,6 +174,9 @@ export const addAtomToTimeline = (
|
|
|
156
174
|
oldValue: update.oldValue,
|
|
157
175
|
newValue: update.newValue,
|
|
158
176
|
}
|
|
177
|
+
if (atom.family) {
|
|
178
|
+
atomUpdate.family = atom.family
|
|
179
|
+
}
|
|
159
180
|
tl.history.push(atomUpdate)
|
|
160
181
|
tl.subject.next(atomUpdate)
|
|
161
182
|
store.config.logger?.info(
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
1
|
+
import type { TimelineToken } from "atom.io"
|
|
2
|
+
import { setState } from "atom.io"
|
|
3
|
+
|
|
4
|
+
import type { Store } from "../store"
|
|
5
|
+
import { IMPLICIT } from "../store"
|
|
5
6
|
|
|
6
7
|
export const redo__INTERNAL = (
|
|
7
8
|
token: TimelineToken,
|
|
@@ -65,7 +66,6 @@ export const undo__INTERNAL = (
|
|
|
65
66
|
return
|
|
66
67
|
}
|
|
67
68
|
timelineData.timeTraveling = `into_past`
|
|
68
|
-
|
|
69
69
|
--timelineData.at
|
|
70
70
|
const update = timelineData.history[timelineData.at]
|
|
71
71
|
switch (update.type) {
|
|
@@ -76,7 +76,7 @@ export const undo__INTERNAL = (
|
|
|
76
76
|
}
|
|
77
77
|
case `selector_update`:
|
|
78
78
|
case `transaction_update`: {
|
|
79
|
-
for (const atomUpdate of update.atomUpdates) {
|
|
79
|
+
for (const atomUpdate of [...update.atomUpdates].reverse()) {
|
|
80
80
|
const { key, oldValue } = atomUpdate
|
|
81
81
|
setState({ key, type: `atom` }, oldValue, store)
|
|
82
82
|
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import type { ƒn } from "~/packages/anvl/src/function"
|
|
2
|
-
|
|
3
|
-
import type { Store } from "."
|
|
4
|
-
import { Subject, target, IMPLICIT } from "."
|
|
5
|
-
import { addAtomToTimeline } from "./timeline/add-atom-to-timeline"
|
|
6
1
|
import type {
|
|
2
|
+
FamilyMetadata,
|
|
7
3
|
StateUpdate,
|
|
8
4
|
TimelineOptions,
|
|
9
5
|
TimelineToken,
|
|
10
6
|
TimelineUpdate,
|
|
11
7
|
TransactionUpdate,
|
|
12
|
-
|
|
8
|
+
ƒn,
|
|
9
|
+
} from "atom.io"
|
|
10
|
+
|
|
11
|
+
import type { Store } from "../store"
|
|
12
|
+
import { IMPLICIT } from "../store"
|
|
13
|
+
import { Subject } from "../subject"
|
|
14
|
+
import { target } from "../transaction"
|
|
15
|
+
import { addAtomToTimeline } from "./add-atom-to-timeline"
|
|
13
16
|
|
|
14
17
|
export type TimelineAtomUpdate = StateUpdate<unknown> & {
|
|
15
18
|
key: string
|
|
16
19
|
type: `atom_update`
|
|
17
20
|
timestamp: number
|
|
21
|
+
family?: FamilyMetadata
|
|
18
22
|
}
|
|
19
23
|
export type TimelineSelectorUpdate = {
|
|
20
24
|
key: string
|
|
@@ -29,6 +33,7 @@ export type TimelineTransactionUpdate = TransactionUpdate<ƒn> & {
|
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
export type Timeline = {
|
|
36
|
+
type: `timeline`
|
|
32
37
|
key: string
|
|
33
38
|
at: number
|
|
34
39
|
timeTraveling: `into_future` | `into_past` | null
|
|
@@ -51,6 +56,7 @@ export function timeline__INTERNAL(
|
|
|
51
56
|
data: Timeline | null = null,
|
|
52
57
|
): TimelineToken {
|
|
53
58
|
const tl: Timeline = {
|
|
59
|
+
type: `timeline`,
|
|
54
60
|
key: options.key,
|
|
55
61
|
at: 0,
|
|
56
62
|
timeTraveling: null,
|
|
@@ -64,7 +70,7 @@ export function timeline__INTERNAL(
|
|
|
64
70
|
|
|
65
71
|
const core = target(store)
|
|
66
72
|
for (const tokenOrFamily of options.atoms) {
|
|
67
|
-
const timelineKey = core.timelineAtoms.
|
|
73
|
+
const timelineKey = core.timelineAtoms.getRelatedKey(tokenOrFamily.key)
|
|
68
74
|
if (timelineKey) {
|
|
69
75
|
store.config.logger?.error(
|
|
70
76
|
`❌ Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`,
|
|
@@ -73,13 +79,15 @@ export function timeline__INTERNAL(
|
|
|
73
79
|
}
|
|
74
80
|
if (tokenOrFamily.type === `atom_family`) {
|
|
75
81
|
const family = tokenOrFamily
|
|
76
|
-
family.subject.subscribe((token) =>
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
family.subject.subscribe(`timeline:${options.key}`, (token) => {
|
|
83
|
+
if (!core.atoms.has(token.key)) {
|
|
84
|
+
addAtomToTimeline(token, tl, store)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
79
87
|
} else {
|
|
80
88
|
const token = tokenOrFamily
|
|
81
89
|
if (`family` in token && token.family) {
|
|
82
|
-
const familyTimelineKey = core.timelineAtoms.
|
|
90
|
+
const familyTimelineKey = core.timelineAtoms.getRelatedKey(
|
|
83
91
|
token.family.key,
|
|
84
92
|
)
|
|
85
93
|
if (familyTimelineKey) {
|
|
@@ -89,7 +97,7 @@ export function timeline__INTERNAL(
|
|
|
89
97
|
continue
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
|
-
addAtomToTimeline(token,
|
|
100
|
+
addAtomToTimeline(token, tl, store)
|
|
93
101
|
}
|
|
94
102
|
core.timelineAtoms = core.timelineAtoms.set({
|
|
95
103
|
atomKey: tokenOrFamily.key,
|