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
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FamilyMetadata, SelectorOptions, SelectorToken } from "atom.io"
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "
|
|
11
|
-
import type { FamilyMetadata, SelectorToken } from "../.."
|
|
12
|
-
import type { SelectorOptions } from "../../selector"
|
|
13
|
-
import { cacheValue, markDone } from "../operation"
|
|
3
|
+
import { cacheValue } from "../caching"
|
|
4
|
+
import { markDone } from "../operation"
|
|
5
|
+
import { become } from "../set-state/become"
|
|
6
|
+
import type { Store, StoreCore } from "../store"
|
|
7
|
+
import { Subject } from "../subject"
|
|
8
|
+
import type { Selector } from "./create-selector"
|
|
9
|
+
import { createSelector } from "./create-selector"
|
|
10
|
+
import { registerSelector } from "./register-selector"
|
|
14
11
|
|
|
15
12
|
export const createReadWriteSelector = <T>(
|
|
16
13
|
options: SelectorOptions<T>,
|
|
@@ -47,7 +44,7 @@ export const createReadWriteSelector = <T>(
|
|
|
47
44
|
const mySelector: Selector<T> = {
|
|
48
45
|
...options,
|
|
49
46
|
subject,
|
|
50
|
-
install: (s: Store) =>
|
|
47
|
+
install: (s: Store) => createSelector(options, family, s),
|
|
51
48
|
get: getSelf,
|
|
52
49
|
set: setSelf,
|
|
53
50
|
type: `selector`,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { registerSelector } from "./register-selector"
|
|
2
|
-
import { Subject } from ".."
|
|
3
1
|
import type {
|
|
4
2
|
FamilyMetadata,
|
|
5
3
|
ReadonlySelectorOptions,
|
|
6
4
|
ReadonlySelectorToken,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { cacheValue } from "../
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
5
|
+
} from "atom.io"
|
|
6
|
+
|
|
7
|
+
import { cacheValue } from "../caching"
|
|
8
|
+
import type { Store, StoreCore } from "../store"
|
|
9
|
+
import { Subject } from "../subject"
|
|
10
|
+
import type { ReadonlySelector } from "./create-selector"
|
|
11
|
+
import { createSelector } from "./create-selector"
|
|
12
|
+
import { registerSelector } from "./register-selector"
|
|
12
13
|
|
|
13
14
|
export const createReadonlySelector = <T>(
|
|
14
15
|
options: ReadonlySelectorOptions<T>,
|
|
@@ -28,7 +29,7 @@ export const createReadonlySelector = <T>(
|
|
|
28
29
|
const readonlySelector: ReadonlySelector<T> = {
|
|
29
30
|
...options,
|
|
30
31
|
subject,
|
|
31
|
-
install: (s: Store) =>
|
|
32
|
+
install: (s: Store) => createSelector(options, family, s),
|
|
32
33
|
get: getSelf,
|
|
33
34
|
type: `readonly_selector`,
|
|
34
35
|
...(family && { family }),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FamilyMetadata,
|
|
3
|
+
ReadonlySelectorOptions,
|
|
4
|
+
ReadonlySelectorToken,
|
|
5
|
+
SelectorOptions,
|
|
6
|
+
SelectorToken,
|
|
7
|
+
} from "atom.io"
|
|
8
|
+
|
|
9
|
+
import type { Store } from "../store"
|
|
10
|
+
import { IMPLICIT } from "../store"
|
|
11
|
+
import type { Subject } from "../subject"
|
|
12
|
+
import { target } from "../transaction"
|
|
13
|
+
import { createReadWriteSelector } from "./create-read-write-selector"
|
|
14
|
+
import { createReadonlySelector } from "./create-readonly-selector"
|
|
15
|
+
|
|
16
|
+
export type Selector<T> = {
|
|
17
|
+
key: string
|
|
18
|
+
type: `selector`
|
|
19
|
+
family?: FamilyMetadata
|
|
20
|
+
install: (store: Store) => void
|
|
21
|
+
subject: Subject<{ newValue: T; oldValue: T }>
|
|
22
|
+
get: () => T
|
|
23
|
+
set: (newValue: T | ((oldValue: T) => T)) => void
|
|
24
|
+
}
|
|
25
|
+
export type ReadonlySelector<T> = {
|
|
26
|
+
key: string
|
|
27
|
+
type: `readonly_selector`
|
|
28
|
+
family?: FamilyMetadata
|
|
29
|
+
install: (store: Store) => void
|
|
30
|
+
subject: Subject<{ newValue: T; oldValue: T }>
|
|
31
|
+
get: () => T
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createSelector<T>(
|
|
35
|
+
options: SelectorOptions<T>,
|
|
36
|
+
family?: FamilyMetadata,
|
|
37
|
+
store?: Store,
|
|
38
|
+
): SelectorToken<T>
|
|
39
|
+
export function createSelector<T>(
|
|
40
|
+
options: ReadonlySelectorOptions<T>,
|
|
41
|
+
family?: FamilyMetadata,
|
|
42
|
+
store?: Store,
|
|
43
|
+
): ReadonlySelectorToken<T>
|
|
44
|
+
export function createSelector<T>(
|
|
45
|
+
options: ReadonlySelectorOptions<T> | SelectorOptions<T>,
|
|
46
|
+
family?: FamilyMetadata,
|
|
47
|
+
store: Store = IMPLICIT.STORE,
|
|
48
|
+
): ReadonlySelectorToken<T> | SelectorToken<T> {
|
|
49
|
+
const core = target(store)
|
|
50
|
+
const existingWritable = core.selectors.get(options.key)
|
|
51
|
+
const existingReadonly = core.readonlySelectors.get(options.key)
|
|
52
|
+
|
|
53
|
+
if (existingWritable || existingReadonly) {
|
|
54
|
+
store.config.logger?.error?.(
|
|
55
|
+
`Tried to create ${existingReadonly ? `readonly selector` : `selector`}`,
|
|
56
|
+
`"${options.key}", but it already exists in the store.`,
|
|
57
|
+
`(Ignore if you are using hot module replacement.)`,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (`set` in options) {
|
|
62
|
+
return createReadWriteSelector(options, family, store, core)
|
|
63
|
+
}
|
|
64
|
+
return createReadonlySelector(options, family, store, core)
|
|
65
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { lookup } from "../store"
|
|
5
|
+
import { target } from "../transaction"
|
|
6
|
+
|
|
7
|
+
export const lookupSelectorSources = (
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): (
|
|
11
|
+
| AtomToken<unknown>
|
|
12
|
+
| ReadonlySelectorToken<unknown>
|
|
13
|
+
| SelectorToken<unknown>
|
|
14
|
+
)[] => {
|
|
15
|
+
const sources = target(store)
|
|
16
|
+
.selectorGraph.getRelationEntries({ downstreamSelectorKey: key })
|
|
17
|
+
.filter(([_, { source }]) => source !== key)
|
|
18
|
+
.map(([_, { source }]) => lookup(source, store))
|
|
19
|
+
return sources
|
|
20
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { getState__INTERNAL
|
|
4
|
-
import { setState__INTERNAL } from "../set"
|
|
1
|
+
import type { Transactors } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import { getState__INTERNAL } from "../get-state-internal"
|
|
4
|
+
import { setState__INTERNAL } from "../set-state"
|
|
5
5
|
import type { Store } from "../store"
|
|
6
|
-
import { IMPLICIT } from "../store"
|
|
7
|
-
import { target } from "../transaction-internal"
|
|
6
|
+
import { IMPLICIT, withdraw } from "../store"
|
|
7
|
+
import { target } from "../transaction/transaction-internal"
|
|
8
|
+
import { updateSelectorAtoms } from "./update-selector-atoms"
|
|
8
9
|
|
|
9
10
|
export const registerSelector = (
|
|
10
11
|
selectorKey: string,
|
|
@@ -13,8 +14,8 @@ export const registerSelector = (
|
|
|
13
14
|
get: (dependency) => {
|
|
14
15
|
const core = target(store)
|
|
15
16
|
const alreadyRegistered = core.selectorGraph
|
|
16
|
-
.
|
|
17
|
-
.some(({ source }) => source === dependency.key)
|
|
17
|
+
.getRelationEntries({ downstreamSelectorKey: selectorKey })
|
|
18
|
+
.some(([_, { source }]) => source === dependency.key)
|
|
18
19
|
|
|
19
20
|
const dependencyState = withdraw(dependency, store)
|
|
20
21
|
if (dependencyState === null) {
|
|
@@ -36,7 +37,10 @@ export const registerSelector = (
|
|
|
36
37
|
`)`,
|
|
37
38
|
)
|
|
38
39
|
core.selectorGraph = core.selectorGraph.set(
|
|
39
|
-
{
|
|
40
|
+
{
|
|
41
|
+
upstreamSelectorKey: dependency.key,
|
|
42
|
+
downstreamSelectorKey: selectorKey,
|
|
43
|
+
},
|
|
40
44
|
{
|
|
41
45
|
source: dependency.key,
|
|
42
46
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { AtomToken, ReadonlySelectorToken, StateToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from ".."
|
|
1
4
|
import { lookupSelectorSources } from "./lookup-selector-sources"
|
|
2
|
-
import type { Store, AtomToken, ReadonlySelectorToken, StateToken } from "../.."
|
|
3
5
|
|
|
4
6
|
export const traceSelectorAtoms = (
|
|
5
7
|
selectorKey: string,
|
|
@@ -11,7 +13,7 @@ export const traceSelectorAtoms = (
|
|
|
11
13
|
const sources = lookupSelectorSources(dependency.key, store)
|
|
12
14
|
let depth = 0
|
|
13
15
|
while (sources.length > 0) {
|
|
14
|
-
//
|
|
16
|
+
// biome-ignore lint/style/noNonNullAssertion: just checked length ^^^
|
|
15
17
|
const source = sources.shift()!
|
|
16
18
|
++depth
|
|
17
19
|
if (depth > 999) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { ReadonlySelectorToken, StateToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { target } from "../transaction"
|
|
1
5
|
import { traceSelectorAtoms } from "./trace-selector-atoms"
|
|
2
|
-
import type { Store } from ".."
|
|
3
|
-
import { target } from ".."
|
|
4
|
-
import type { ReadonlySelectorToken, StateToken } from "../.."
|
|
5
6
|
|
|
6
7
|
export const updateSelectorAtoms = (
|
|
7
8
|
selectorKey: string,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Modify<T> = (thing: T) => T
|
|
2
|
+
|
|
3
|
+
export const become =
|
|
4
|
+
<T>(nextVersionOfThing: Modify<T> | T) =>
|
|
5
|
+
(originalThing: T): T =>
|
|
6
|
+
nextVersionOfThing instanceof Function
|
|
7
|
+
? nextVersionOfThing(
|
|
8
|
+
originalThing instanceof Function ? originalThing() : originalThing,
|
|
9
|
+
)
|
|
10
|
+
: nextVersionOfThing
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { JsonInterface } from "atom.io/json"
|
|
2
|
+
|
|
3
|
+
import type { Atom } from "../atom"
|
|
4
|
+
import { Tracker } from "../mutable"
|
|
5
|
+
import type { Store, StoreCore } from "../store"
|
|
6
|
+
|
|
7
|
+
export function copyMutableIfNeeded<T>(
|
|
8
|
+
atom: Atom<T>,
|
|
9
|
+
transform: JsonInterface<T>,
|
|
10
|
+
origin: Store,
|
|
11
|
+
target: StoreCore,
|
|
12
|
+
): T {
|
|
13
|
+
const originValue = origin.valueMap.get(atom.key)
|
|
14
|
+
const targetValue = target.valueMap.get(atom.key)
|
|
15
|
+
if (originValue === targetValue) {
|
|
16
|
+
origin.config.logger?.info(`📃 copying`, `${atom.key}`)
|
|
17
|
+
const copiedValue = transform.fromJson(transform.toJson(originValue))
|
|
18
|
+
target.valueMap.set(atom.key, copiedValue)
|
|
19
|
+
new Tracker(atom, origin)
|
|
20
|
+
return copiedValue
|
|
21
|
+
}
|
|
22
|
+
return targetValue
|
|
23
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AtomFamily } from "atom.io"
|
|
2
|
+
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
|
+
import { getState__INTERNAL } from ".."
|
|
4
|
+
import type { Store, StoreCore } from ".."
|
|
5
|
+
import type { Atom } from "../atom"
|
|
6
|
+
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
7
|
+
|
|
8
|
+
export function copyMutableIfWithinTransaction<T>(
|
|
9
|
+
atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
|
|
10
|
+
store: Store,
|
|
11
|
+
): T {
|
|
12
|
+
if (
|
|
13
|
+
store.transactionStatus.phase === `building` ||
|
|
14
|
+
store.transactionStatus.phase === `applying`
|
|
15
|
+
) {
|
|
16
|
+
if (`toJson` in atom && `fromJson` in atom) {
|
|
17
|
+
store.config.logger?.info(
|
|
18
|
+
`📄 copyMutableIfWithinTransaction: ${atom.key} is mutable`,
|
|
19
|
+
)
|
|
20
|
+
const copiedValue = copyMutableIfNeeded(
|
|
21
|
+
atom,
|
|
22
|
+
atom,
|
|
23
|
+
store,
|
|
24
|
+
store.transactionStatus.core,
|
|
25
|
+
)
|
|
26
|
+
return copiedValue
|
|
27
|
+
}
|
|
28
|
+
if (`family` in atom) {
|
|
29
|
+
const family = store.transactionStatus.core.families.get(atom.family.key)
|
|
30
|
+
if (family && family.type === `atom_family`) {
|
|
31
|
+
const result = copyMutableFamilyMemberWithinTransaction<T>(
|
|
32
|
+
atom,
|
|
33
|
+
family,
|
|
34
|
+
store,
|
|
35
|
+
store.transactionStatus.core,
|
|
36
|
+
)
|
|
37
|
+
if (result) {
|
|
38
|
+
return result
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return getState__INTERNAL(atom, store)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function copyMutableFamilyMemberWithinTransaction<T>(
|
|
47
|
+
atom: Atom<T>,
|
|
48
|
+
family:
|
|
49
|
+
| AtomFamily<T, any>
|
|
50
|
+
| (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
|
|
51
|
+
origin: Store,
|
|
52
|
+
target: StoreCore,
|
|
53
|
+
): T | null {
|
|
54
|
+
if (`toJson` in family && `fromJson` in family) {
|
|
55
|
+
const copyCreated = copyMutableIfNeeded(atom, family, origin, target)
|
|
56
|
+
return copyCreated
|
|
57
|
+
}
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AtomFamily } from "atom.io"
|
|
2
|
+
import type { Json, JsonInterface } from "atom.io/json"
|
|
3
|
+
import type { Store, StoreCore } from ".."
|
|
4
|
+
import type { Atom } from "../atom"
|
|
5
|
+
import { copyMutableIfNeeded } from "./copy-mutable-if-needed"
|
|
6
|
+
|
|
7
|
+
export function copyMutableIntoNewStore<T>(
|
|
8
|
+
atom: Atom<T> | (Atom<T> & JsonInterface<T, Json.Serializable>),
|
|
9
|
+
origin: Store,
|
|
10
|
+
target: Store,
|
|
11
|
+
): void {
|
|
12
|
+
if (`toJson` in atom && `fromJson` in atom) {
|
|
13
|
+
copyMutableIfNeeded(atom, atom, origin, target)
|
|
14
|
+
}
|
|
15
|
+
if (`family` in atom) {
|
|
16
|
+
const family = target.families.get(atom.family.key)
|
|
17
|
+
if (family && family.type === `atom_family`) {
|
|
18
|
+
copyMutableFamilyMemberIntoNewStore(atom, family, origin, target)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function copyMutableFamilyMemberIntoNewStore<T>(
|
|
24
|
+
atom: Atom<T>,
|
|
25
|
+
family:
|
|
26
|
+
| AtomFamily<T, any>
|
|
27
|
+
| (AtomFamily<T, any> & JsonInterface<T, Json.Serializable>),
|
|
28
|
+
origin: Store,
|
|
29
|
+
target: Store,
|
|
30
|
+
): void {
|
|
31
|
+
if (`toJson` in family && `fromJson` in family) {
|
|
32
|
+
copyMutableIfNeeded(atom, family, origin, target)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { StateUpdate } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
|
|
4
|
+
import type { Atom } from "../atom"
|
|
5
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
6
|
+
|
|
7
|
+
export const emitUpdate = <T>(
|
|
8
|
+
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
9
|
+
update: StateUpdate<T>,
|
|
10
|
+
store: Store,
|
|
11
|
+
): void => {
|
|
12
|
+
const { key } = state
|
|
13
|
+
const { logger } = store.config
|
|
14
|
+
logger?.info(
|
|
15
|
+
`📢 ${state.type} "${key}" went (`,
|
|
16
|
+
update.oldValue,
|
|
17
|
+
`->`,
|
|
18
|
+
update.newValue,
|
|
19
|
+
`)`,
|
|
20
|
+
)
|
|
21
|
+
logger?.info(`📢 notifying subscribers:`, state.subject.subscribers)
|
|
22
|
+
state.subject.next(update)
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Atom } from "../atom"
|
|
2
|
+
import { isDone, markDone } from "../operation"
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { IMPLICIT } from "../store"
|
|
5
|
+
import { target } from "../transaction"
|
|
6
|
+
|
|
7
|
+
export const evictDownStream = <T>(
|
|
8
|
+
state: Atom<T>,
|
|
9
|
+
store: Store = IMPLICIT.STORE,
|
|
10
|
+
): void => {
|
|
11
|
+
const core = target(store)
|
|
12
|
+
const downstreamKeys = core.selectorAtoms.getRelatedKeys(state.key)
|
|
13
|
+
store.config.logger?.info(
|
|
14
|
+
` || ${downstreamKeys?.size ?? `none`} downstream:`,
|
|
15
|
+
downstreamKeys,
|
|
16
|
+
)
|
|
17
|
+
if (core.operation.open) {
|
|
18
|
+
store.config.logger?.info(` ||`, [...core.operation.done], `already done`)
|
|
19
|
+
}
|
|
20
|
+
if (downstreamKeys) {
|
|
21
|
+
for (const key of downstreamKeys) {
|
|
22
|
+
if (isDone(key, store)) {
|
|
23
|
+
store.config.logger?.info(` || ${key} already done`)
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
const state = core.selectors.get(key) ?? core.readonlySelectors.get(key)
|
|
27
|
+
if (!state) {
|
|
28
|
+
store.config.logger?.info(
|
|
29
|
+
` || ${key} was not found in selectors or readonlySelectors`,
|
|
30
|
+
)
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
core.valueMap.delete(key)
|
|
34
|
+
store.config.logger?.info(` xx evicted "${key}"`)
|
|
35
|
+
|
|
36
|
+
markDone(key, store)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Atom } from "../atom"
|
|
2
|
+
import { isAtomDefault, markAtomAsNotDefault } from "../atom"
|
|
3
|
+
import { cacheValue } from "../caching"
|
|
4
|
+
import { getState__INTERNAL } from "../get-state-internal"
|
|
5
|
+
import { markDone } from "../operation"
|
|
6
|
+
import type { Store } from "../store"
|
|
7
|
+
import { IMPLICIT } from "../store"
|
|
8
|
+
import { become } from "./become"
|
|
9
|
+
import { copyMutableIfWithinTransaction } from "./copy-mutable-in-transaction"
|
|
10
|
+
import { emitUpdate } from "./emit-update"
|
|
11
|
+
import { evictDownStream } from "./evict-downstream"
|
|
12
|
+
import { stowUpdate } from "./stow-update"
|
|
13
|
+
|
|
14
|
+
export const setAtomState = <T>(
|
|
15
|
+
atom: Atom<T>,
|
|
16
|
+
next: T | ((oldValue: T) => T),
|
|
17
|
+
store: Store = IMPLICIT.STORE,
|
|
18
|
+
): void => {
|
|
19
|
+
const oldValue = getState__INTERNAL(atom, store)
|
|
20
|
+
let newValue = copyMutableIfWithinTransaction(atom, store)
|
|
21
|
+
newValue = become(next)(newValue)
|
|
22
|
+
store.config.logger?.info(`<< setting atom "${atom.key}" to`, newValue)
|
|
23
|
+
cacheValue(atom.key, newValue, store)
|
|
24
|
+
if (isAtomDefault(atom.key, store)) {
|
|
25
|
+
markAtomAsNotDefault(atom.key, store)
|
|
26
|
+
}
|
|
27
|
+
markDone(atom.key, store)
|
|
28
|
+
store.config.logger?.info(
|
|
29
|
+
` || evicting caches downstream from "${atom.key}"`,
|
|
30
|
+
)
|
|
31
|
+
evictDownStream(atom, store)
|
|
32
|
+
const update = { oldValue, newValue }
|
|
33
|
+
if (store.transactionStatus.phase !== `building`) {
|
|
34
|
+
emitUpdate(atom, update, store)
|
|
35
|
+
} else {
|
|
36
|
+
stowUpdate(atom, update, store)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getState__INTERNAL } from "../get-state-internal"
|
|
2
|
+
import type { Selector } from "../selector"
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { IMPLICIT } from "../store"
|
|
5
|
+
import { become } from "./become"
|
|
6
|
+
|
|
7
|
+
export const setSelectorState = <T>(
|
|
8
|
+
selector: Selector<T>,
|
|
9
|
+
next: T | ((oldValue: T) => T),
|
|
10
|
+
store: Store = IMPLICIT.STORE,
|
|
11
|
+
): void => {
|
|
12
|
+
const oldValue = getState__INTERNAL(selector, store)
|
|
13
|
+
const newValue = become(next)(oldValue)
|
|
14
|
+
|
|
15
|
+
store.config.logger?.info(`<< setting selector "${selector.key}" to`, newValue)
|
|
16
|
+
store.config.logger?.info(` || propagating change made to "${selector.key}"`)
|
|
17
|
+
|
|
18
|
+
selector.set(newValue)
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Atom } from "../atom"
|
|
2
|
+
import type { Selector } from "../selector"
|
|
3
|
+
import type { Store } from "../store"
|
|
4
|
+
import { IMPLICIT } from "../store"
|
|
5
|
+
import { setAtomState } from "./set-atom-state"
|
|
6
|
+
import { setSelectorState } from "./set-selector-state"
|
|
7
|
+
|
|
8
|
+
export const setState__INTERNAL = <T>(
|
|
9
|
+
state: Atom<T> | Selector<T>,
|
|
10
|
+
value: T | ((oldValue: T) => T),
|
|
11
|
+
store: Store = IMPLICIT.STORE,
|
|
12
|
+
): void => {
|
|
13
|
+
if (`set` in state) {
|
|
14
|
+
setSelectorState(state, value, store)
|
|
15
|
+
} else {
|
|
16
|
+
setAtomState(state, value, store)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { KeyedStateUpdate, StateUpdate } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import type { Atom } from "../atom"
|
|
4
|
+
import { isTransceiver } from "../mutable"
|
|
5
|
+
import type { Store } from "../store"
|
|
6
|
+
|
|
7
|
+
function shouldUpdateBeStowed(key: string, update: StateUpdate<any>): boolean {
|
|
8
|
+
// do not stow updates that aren't json, unless they're not equal by reference
|
|
9
|
+
if (isTransceiver(update.newValue)) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
// do not stow updates where the key contains 👁🗨
|
|
13
|
+
if (key.includes(`👁🗨`)) {
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const stowUpdate = <T>(
|
|
20
|
+
state: Atom<T>,
|
|
21
|
+
update: StateUpdate<T>,
|
|
22
|
+
store: Store,
|
|
23
|
+
): void => {
|
|
24
|
+
const { key } = state
|
|
25
|
+
const { logger } = store.config
|
|
26
|
+
if (store.transactionStatus.phase !== `building`) {
|
|
27
|
+
store.config.logger?.warn(
|
|
28
|
+
`stowUpdate called outside of a transaction. This is probably a bug.`,
|
|
29
|
+
)
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
const shouldStow = shouldUpdateBeStowed(key, update)
|
|
33
|
+
if (!shouldStow) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
const atomUpdate: KeyedStateUpdate<T> = { key, ...update }
|
|
37
|
+
if (state.family) {
|
|
38
|
+
atomUpdate.family = state.family
|
|
39
|
+
}
|
|
40
|
+
store.transactionStatus.atomUpdates.push(atomUpdate)
|
|
41
|
+
logger?.info(`📝 ${key} stowed (`, update.oldValue, `->`, update.newValue, `)`)
|
|
42
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomToken,
|
|
3
|
+
ReadonlySelectorToken,
|
|
4
|
+
SelectorToken,
|
|
5
|
+
StateToken,
|
|
6
|
+
TransactionToken,
|
|
7
|
+
ƒn,
|
|
8
|
+
} from "atom.io"
|
|
9
|
+
|
|
10
|
+
import type { Atom } from "../atom"
|
|
11
|
+
import type { ReadonlySelector, Selector } from "../selector"
|
|
12
|
+
import type { Transaction } from "../transaction"
|
|
13
|
+
|
|
14
|
+
export function deposit<T>(state: Atom<T>): AtomToken<T>
|
|
15
|
+
export function deposit<T>(state: Selector<T>): SelectorToken<T>
|
|
16
|
+
export function deposit<T>(state: Atom<T> | Selector<T>): StateToken<T>
|
|
17
|
+
export function deposit<T>(state: ReadonlySelector<T>): ReadonlySelectorToken<T>
|
|
18
|
+
export function deposit<T>(
|
|
19
|
+
state: Transaction<T extends ƒn ? T : never>,
|
|
20
|
+
): TransactionToken<T>
|
|
21
|
+
export function deposit<T>(
|
|
22
|
+
state: Atom<T> | ReadonlySelector<T> | Selector<T>,
|
|
23
|
+
): ReadonlySelectorToken<T> | StateToken<T>
|
|
24
|
+
export function deposit<T>(
|
|
25
|
+
state:
|
|
26
|
+
| Atom<T>
|
|
27
|
+
| ReadonlySelector<T>
|
|
28
|
+
| Selector<T>
|
|
29
|
+
| Transaction<T extends ƒn ? T : never>,
|
|
30
|
+
):
|
|
31
|
+
| AtomToken<T>
|
|
32
|
+
| ReadonlySelectorToken<T>
|
|
33
|
+
| SelectorToken<T>
|
|
34
|
+
| TransactionToken<T> {
|
|
35
|
+
const token = {
|
|
36
|
+
key: state.key,
|
|
37
|
+
type: state.type,
|
|
38
|
+
} as any
|
|
39
|
+
if (`family` in state) {
|
|
40
|
+
token.family = state.family
|
|
41
|
+
}
|
|
42
|
+
return token
|
|
43
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AtomToken, ReadonlySelectorToken, SelectorToken } from "atom.io"
|
|
2
|
+
|
|
3
|
+
import { target } from "../transaction"
|
|
4
|
+
import type { Store } from "./store"
|
|
5
|
+
|
|
6
|
+
export function lookup(
|
|
7
|
+
key: string,
|
|
8
|
+
store: Store,
|
|
9
|
+
): AtomToken<unknown> | ReadonlySelectorToken<unknown> | SelectorToken<unknown> {
|
|
10
|
+
const core = target(store)
|
|
11
|
+
let type: string = core.atoms.has(key)
|
|
12
|
+
? `atom`
|
|
13
|
+
: core.selectors.has(key)
|
|
14
|
+
? `selector`
|
|
15
|
+
: core.readonlySelectors.has(key)
|
|
16
|
+
? `readonly_selector`
|
|
17
|
+
: ``
|
|
18
|
+
if (!type) {
|
|
19
|
+
const errorId = Math.random().toString(36)
|
|
20
|
+
type = `🚨 This state could not be found by lookup! Check the console for "${errorId}"`
|
|
21
|
+
store.config.logger?.error(
|
|
22
|
+
`${errorId}: Key "${key}" does not exist in the store.`,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
return { key, type } as any
|
|
26
|
+
}
|