atom.io 0.14.7 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/data/dist/index.cjs +200 -218
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +16 -7
- package/data/dist/index.js +202 -221
- package/data/dist/index.js.map +1 -1
- package/data/src/join.ts +295 -292
- package/data/src/struct-family.ts +2 -2
- package/data/src/struct.ts +2 -2
- package/dist/chunk-S7R5MU6A.js +137 -0
- package/dist/chunk-S7R5MU6A.js.map +1 -0
- package/dist/index.cjs +3 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1 -151
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +275 -200
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +43 -36
- package/internal/dist/index.js +221 -193
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-atom.ts +5 -86
- package/internal/src/atom/create-regular-atom.ts +92 -0
- package/internal/src/atom/index.ts +16 -0
- package/internal/src/atom/is-default.ts +0 -5
- package/internal/src/caching.ts +14 -16
- package/internal/src/families/create-atom-family.ts +20 -46
- package/internal/src/families/create-readonly-selector-family.ts +1 -0
- package/internal/src/families/create-regular-atom-family.ts +72 -0
- package/internal/src/families/create-selector-family.ts +2 -0
- package/internal/src/families/index.ts +1 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
- package/internal/src/mutable/create-mutable-atom.ts +8 -3
- package/internal/src/mutable/get-update-family.ts +1 -1
- package/internal/src/mutable/is-mutable.ts +3 -30
- package/internal/src/mutable/tracker-family.ts +2 -2
- package/internal/src/mutable/tracker.ts +5 -5
- package/internal/src/operation.ts +14 -18
- package/internal/src/selector/create-read-write-selector.ts +2 -3
- package/internal/src/selector/create-selector.ts +1 -1
- package/internal/src/selector/register-selector.ts +9 -14
- package/internal/src/set-state/evict-downstream.ts +3 -5
- package/internal/src/set-state/set-atom.ts +14 -17
- package/internal/src/store/store.ts +23 -19
- package/internal/src/store/withdraw.ts +32 -70
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +5 -3
- package/internal/src/subscribe/subscribe-to-state.ts +5 -3
- package/internal/src/transaction/apply-transaction.ts +20 -2
- package/internal/src/transaction/build-transaction.ts +19 -11
- package/internal/src/transaction/create-transaction.ts +6 -11
- package/internal/src/transaction/index.ts +2 -3
- package/introspection/dist/index.cjs +6 -6
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +3 -3
- package/introspection/dist/index.js +7 -7
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +7 -2
- package/introspection/src/attach-selector-index.ts +7 -2
- package/introspection/src/attach-timeline-family.ts +5 -2
- package/introspection/src/attach-timeline-index.ts +2 -2
- package/introspection/src/attach-transaction-index.ts +2 -2
- package/introspection/src/attach-transaction-logs.ts +2 -2
- package/package.json +10 -8
- package/react/dist/index.cjs +9 -12
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.js +9 -12
- package/react/dist/index.js.map +1 -1
- package/react/src/store-hooks.ts +10 -12
- package/react-devtools/dist/index.d.ts +17 -11
- package/src/atom.ts +8 -17
- package/src/selector.ts +3 -1
- package/src/set-state.ts +1 -3
- package/src/silo.ts +2 -14
- package/src/transaction.ts +17 -6
- package/transceivers/set-rtx/dist/index.cjs +2 -1
- package/transceivers/set-rtx/dist/index.cjs.map +1 -1
- package/transceivers/set-rtx/dist/index.js +2 -1
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/src/set-rtx.ts +2 -1
- package/internal/src/transaction/redo-transaction.ts +0 -27
- package/internal/src/transaction/undo-transaction.ts +0 -27
|
@@ -3,100 +3,19 @@ import type {
|
|
|
3
3
|
AtomToken,
|
|
4
4
|
FamilyMetadata,
|
|
5
5
|
MutableAtomOptions,
|
|
6
|
-
UpdateHandler,
|
|
7
6
|
} from "atom.io"
|
|
8
|
-
import { setState } from "atom.io"
|
|
9
|
-
import { Json } from "atom.io/json"
|
|
10
7
|
|
|
11
|
-
import {
|
|
12
|
-
import { newest } from "../lineage"
|
|
13
|
-
import { Transceiver, createMutableAtom } from "../mutable"
|
|
8
|
+
import { createMutableAtom } from "../mutable"
|
|
14
9
|
import type { Store } from "../store"
|
|
15
|
-
import {
|
|
16
|
-
import { Subject } from "../subject"
|
|
17
|
-
import { subscribeToState } from "../subscribe"
|
|
18
|
-
import { markAtomAsDefault } from "./is-default"
|
|
19
|
-
|
|
20
|
-
export type Atom<T> = {
|
|
21
|
-
key: string
|
|
22
|
-
type: `atom`
|
|
23
|
-
mutable?: boolean
|
|
24
|
-
family?: FamilyMetadata
|
|
25
|
-
install: (store: Store) => void
|
|
26
|
-
subject: Subject<{ newValue: T; oldValue: T }>
|
|
27
|
-
default: T | (() => T)
|
|
28
|
-
cleanup?: () => void
|
|
29
|
-
}
|
|
10
|
+
import { createRegularAtom } from "./create-regular-atom"
|
|
30
11
|
|
|
31
12
|
export function createAtom<T>(
|
|
32
13
|
options: AtomOptions<T> | MutableAtomOptions<any, any>,
|
|
33
14
|
family: FamilyMetadata | undefined,
|
|
34
15
|
store: Store,
|
|
35
16
|
): AtomToken<T> {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`atom`,
|
|
39
|
-
options.key,
|
|
40
|
-
`creating in store "${store.config.name}"`,
|
|
41
|
-
)
|
|
42
|
-
const target = newest(store)
|
|
43
|
-
const existing = target.atoms.get(options.key)
|
|
44
|
-
if (existing) {
|
|
45
|
-
store.logger.error(
|
|
46
|
-
`❌`,
|
|
47
|
-
`atom`,
|
|
48
|
-
options.key,
|
|
49
|
-
`Tried to create atom, but it already exists in the store.`,
|
|
50
|
-
`(Ignore if you are in development using hot module replacement.)`,
|
|
51
|
-
)
|
|
52
|
-
return deposit(existing)
|
|
53
|
-
}
|
|
54
|
-
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
55
|
-
const newAtom: Atom<T> = {
|
|
56
|
-
...options,
|
|
57
|
-
type: `atom`,
|
|
58
|
-
install: (store: Store) => {
|
|
59
|
-
store.logger.info(
|
|
60
|
-
`🛠️`,
|
|
61
|
-
`atom`,
|
|
62
|
-
options.key,
|
|
63
|
-
`installing in store "${store.config.name}"`,
|
|
64
|
-
)
|
|
65
|
-
return `mutable` in options
|
|
66
|
-
? createMutableAtom(options, store)
|
|
67
|
-
: createAtom(options, undefined, store)
|
|
68
|
-
},
|
|
69
|
-
subject,
|
|
70
|
-
...(family && { family }),
|
|
71
|
-
} as const
|
|
72
|
-
let initialValue = options.default
|
|
73
|
-
if (options.default instanceof Function) {
|
|
74
|
-
initialValue = options.default()
|
|
75
|
-
}
|
|
76
|
-
target.atoms.set(newAtom.key, newAtom)
|
|
77
|
-
markAtomAsDefault(options.key, store)
|
|
78
|
-
cacheValue(options.key, initialValue, subject, store)
|
|
79
|
-
const token = deposit(newAtom)
|
|
80
|
-
if (options.effects) {
|
|
81
|
-
let effectIndex = 0
|
|
82
|
-
const cleanupFunctions: (() => void)[] = []
|
|
83
|
-
for (const effect of options.effects) {
|
|
84
|
-
const cleanup = effect({
|
|
85
|
-
setSelf: (next) => setState(token, next, store),
|
|
86
|
-
onSet: (handle: UpdateHandler<T>) =>
|
|
87
|
-
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
88
|
-
})
|
|
89
|
-
if (cleanup) {
|
|
90
|
-
cleanupFunctions.push(cleanup)
|
|
91
|
-
}
|
|
92
|
-
++effectIndex
|
|
93
|
-
}
|
|
94
|
-
newAtom.cleanup = () => {
|
|
95
|
-
for (const cleanup of cleanupFunctions) {
|
|
96
|
-
cleanup()
|
|
97
|
-
}
|
|
98
|
-
}
|
|
17
|
+
if (`mutable` in options) {
|
|
18
|
+
return createMutableAtom(options, family, store)
|
|
99
19
|
}
|
|
100
|
-
store
|
|
101
|
-
return token as AtomToken<T>
|
|
20
|
+
return createRegularAtom<T>(options, family, store)
|
|
102
21
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomOptions,
|
|
3
|
+
AtomToken,
|
|
4
|
+
FamilyMetadata,
|
|
5
|
+
MutableAtomOptions,
|
|
6
|
+
UpdateHandler,
|
|
7
|
+
} from "atom.io"
|
|
8
|
+
import { setState } from "atom.io"
|
|
9
|
+
|
|
10
|
+
import type { Atom } from "."
|
|
11
|
+
import { cacheValue } from "../caching"
|
|
12
|
+
import { newest } from "../lineage"
|
|
13
|
+
import { createMutableAtom } from "../mutable"
|
|
14
|
+
import type { Store } from "../store"
|
|
15
|
+
import { deposit } from "../store"
|
|
16
|
+
import { Subject } from "../subject"
|
|
17
|
+
import { subscribeToState } from "../subscribe"
|
|
18
|
+
import { markAtomAsDefault } from "./is-default"
|
|
19
|
+
|
|
20
|
+
export function createRegularAtom<T>(
|
|
21
|
+
options: AtomOptions<T> | MutableAtomOptions<any, any>,
|
|
22
|
+
family: FamilyMetadata | undefined,
|
|
23
|
+
store: Store,
|
|
24
|
+
): AtomToken<T> {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`🔨`,
|
|
27
|
+
`atom`,
|
|
28
|
+
options.key,
|
|
29
|
+
`creating in store "${store.config.name}"`,
|
|
30
|
+
)
|
|
31
|
+
const target = newest(store)
|
|
32
|
+
const existing = target.atoms.get(options.key)
|
|
33
|
+
if (existing) {
|
|
34
|
+
store.logger.error(
|
|
35
|
+
`❌`,
|
|
36
|
+
`atom`,
|
|
37
|
+
options.key,
|
|
38
|
+
`Tried to create atom, but it already exists in the store.`,
|
|
39
|
+
)
|
|
40
|
+
return deposit(existing)
|
|
41
|
+
}
|
|
42
|
+
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
43
|
+
const newAtom: Atom<T> = {
|
|
44
|
+
...options,
|
|
45
|
+
type: `atom`,
|
|
46
|
+
install: (store: Store) => {
|
|
47
|
+
store.logger.info(
|
|
48
|
+
`🛠️`,
|
|
49
|
+
`atom`,
|
|
50
|
+
options.key,
|
|
51
|
+
`installing in store "${store.config.name}"`,
|
|
52
|
+
)
|
|
53
|
+
return `mutable` in options
|
|
54
|
+
? createMutableAtom(options, family, store)
|
|
55
|
+
: createRegularAtom(options, family, store)
|
|
56
|
+
},
|
|
57
|
+
subject,
|
|
58
|
+
} as const
|
|
59
|
+
if (family) {
|
|
60
|
+
newAtom.family = family
|
|
61
|
+
}
|
|
62
|
+
let initialValue = options.default
|
|
63
|
+
if (options.default instanceof Function) {
|
|
64
|
+
initialValue = options.default()
|
|
65
|
+
}
|
|
66
|
+
target.atoms.set(newAtom.key, newAtom)
|
|
67
|
+
markAtomAsDefault(options.key, store)
|
|
68
|
+
cacheValue(options.key, initialValue, subject, target)
|
|
69
|
+
const token = deposit(newAtom)
|
|
70
|
+
if (options.effects) {
|
|
71
|
+
let effectIndex = 0
|
|
72
|
+
const cleanupFunctions: (() => void)[] = []
|
|
73
|
+
for (const effect of options.effects) {
|
|
74
|
+
const cleanup = effect({
|
|
75
|
+
setSelf: (next) => setState(token, next, store),
|
|
76
|
+
onSet: (handle: UpdateHandler<T>) =>
|
|
77
|
+
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
78
|
+
})
|
|
79
|
+
if (cleanup) {
|
|
80
|
+
cleanupFunctions.push(cleanup)
|
|
81
|
+
}
|
|
82
|
+
++effectIndex
|
|
83
|
+
}
|
|
84
|
+
newAtom.cleanup = () => {
|
|
85
|
+
for (const cleanup of cleanupFunctions) {
|
|
86
|
+
cleanup()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
store.subject.atomCreation.next(token)
|
|
91
|
+
return token as AtomToken<T>
|
|
92
|
+
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
import type { FamilyMetadata } from "~/packages/atom.io/src"
|
|
2
|
+
import type { Store } from "../store"
|
|
3
|
+
import type { Subject } from "../subject"
|
|
4
|
+
|
|
1
5
|
export * from "./create-atom"
|
|
6
|
+
export * from "./create-regular-atom"
|
|
2
7
|
export * from "./delete-atom"
|
|
3
8
|
export * from "./is-default"
|
|
9
|
+
|
|
10
|
+
export type Atom<T> = {
|
|
11
|
+
key: string
|
|
12
|
+
type: `atom`
|
|
13
|
+
mutable?: boolean
|
|
14
|
+
family?: FamilyMetadata
|
|
15
|
+
install: (store: Store) => void
|
|
16
|
+
subject: Subject<{ newValue: T; oldValue: T }>
|
|
17
|
+
default: T | (() => T)
|
|
18
|
+
cleanup?: () => void
|
|
19
|
+
}
|
|
@@ -17,8 +17,3 @@ export const markAtomAsNotDefault = (key: string, store: Store): void => {
|
|
|
17
17
|
core.atomsThatAreDefault = new Set(newest(store).atomsThatAreDefault)
|
|
18
18
|
core.atomsThatAreDefault.delete(key)
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
export const isSelectorDefault = (key: string, store: Store): boolean => {
|
|
22
|
-
const rootKeys = traceAllSelectorAtoms(key, store)
|
|
23
|
-
return rootKeys.every((rootKey) => isAtomDefault(rootKey, store))
|
|
24
|
-
}
|
package/internal/src/caching.ts
CHANGED
|
@@ -20,27 +20,26 @@ export function cacheValue<T>(
|
|
|
20
20
|
key: string,
|
|
21
21
|
value: T,
|
|
22
22
|
subject: Subject<StateUpdate<unknown>>,
|
|
23
|
-
|
|
23
|
+
target: Store,
|
|
24
24
|
): Future<T> | T {
|
|
25
|
-
const target = newest(store)
|
|
26
25
|
const currentValue = target.valueMap.get(key)
|
|
27
26
|
if (currentValue instanceof Future) {
|
|
28
27
|
currentValue.cancel()
|
|
29
28
|
}
|
|
30
29
|
if (value instanceof Promise) {
|
|
31
30
|
const future = new Future<T>(value)
|
|
32
|
-
|
|
31
|
+
target.valueMap.set(key, future)
|
|
33
32
|
future
|
|
34
33
|
.then((resolved) => {
|
|
35
34
|
if (future.isCanceled) {
|
|
36
35
|
return
|
|
37
36
|
}
|
|
38
|
-
cacheValue(key, resolved, subject,
|
|
37
|
+
cacheValue(key, resolved, subject, target)
|
|
39
38
|
subject.next({ newValue: resolved, oldValue: future })
|
|
40
39
|
})
|
|
41
40
|
.catch((thrown) => {
|
|
42
41
|
if (thrown !== `canceled`) {
|
|
43
|
-
|
|
42
|
+
target.logger.error(`💥`, `state`, key, `rejected:`, thrown)
|
|
44
43
|
}
|
|
45
44
|
})
|
|
46
45
|
return future
|
|
@@ -49,22 +48,21 @@ export function cacheValue<T>(
|
|
|
49
48
|
return value
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
export const readCachedValue = <T>(key: string,
|
|
53
|
-
return
|
|
51
|
+
export const readCachedValue = <T>(key: string, target: Store): T => {
|
|
52
|
+
return target.valueMap.get(key) as T
|
|
54
53
|
}
|
|
55
|
-
export const isValueCached = (key: string,
|
|
56
|
-
return
|
|
54
|
+
export const isValueCached = (key: string, target: Store): boolean => {
|
|
55
|
+
return target.valueMap.has(key)
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
export const evictCachedValue = (key: string,
|
|
60
|
-
const
|
|
61
|
-
const currentValue = core.valueMap.get(key)
|
|
58
|
+
export const evictCachedValue = (key: string, target: Store): void => {
|
|
59
|
+
const currentValue = target.valueMap.get(key)
|
|
62
60
|
if (currentValue instanceof Future) {
|
|
63
61
|
currentValue.cancel()
|
|
64
62
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
63
|
+
if (target.operation.open) {
|
|
64
|
+
target.operation.prev.set(key, currentValue)
|
|
67
65
|
}
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
target.valueMap.delete(key)
|
|
67
|
+
target.logger.info(`🗑`, `state`, key, `evicted`)
|
|
70
68
|
}
|
|
@@ -1,59 +1,33 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AtomFamily,
|
|
3
3
|
AtomFamilyOptions,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
FamilyMetadata,
|
|
4
|
+
MutableAtomFamily,
|
|
5
|
+
MutableAtomFamilyOptions,
|
|
7
6
|
} from "atom.io"
|
|
8
7
|
import type { Json } from "atom.io/json"
|
|
9
|
-
import { stringifyJson } from "atom.io/json"
|
|
10
8
|
|
|
11
|
-
import {
|
|
12
|
-
import { newest } from "../lineage"
|
|
13
|
-
import { deposit, withdraw } from "../store"
|
|
9
|
+
import { type Transceiver, createMutableAtomFamily } from "../mutable"
|
|
14
10
|
import type { Store } from "../store"
|
|
15
|
-
import {
|
|
11
|
+
import { createRegularAtomFamily } from "./create-regular-atom-family"
|
|
16
12
|
|
|
13
|
+
export function createAtomFamily<
|
|
14
|
+
T extends Transceiver<any>,
|
|
15
|
+
J extends Json.Serializable,
|
|
16
|
+
K extends Json.Serializable,
|
|
17
|
+
>(
|
|
18
|
+
options: MutableAtomFamilyOptions<T, J, K>,
|
|
19
|
+
store: Store,
|
|
20
|
+
): MutableAtomFamily<T, J, K>
|
|
17
21
|
export function createAtomFamily<T, K extends Json.Serializable>(
|
|
18
22
|
options: AtomFamilyOptions<T, K>,
|
|
19
23
|
store: Store,
|
|
20
|
-
): AtomFamily<T, K>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const existing = withdraw({ key: fullKey, type: `atom` }, store)
|
|
28
|
-
let token: AtomToken<any>
|
|
29
|
-
if (existing) {
|
|
30
|
-
token = deposit(existing)
|
|
31
|
-
} else {
|
|
32
|
-
const individualOptions: AtomOptions<any> = {
|
|
33
|
-
key: fullKey,
|
|
34
|
-
default:
|
|
35
|
-
options.default instanceof Function
|
|
36
|
-
? options.default(key)
|
|
37
|
-
: options.default,
|
|
38
|
-
}
|
|
39
|
-
if (options.effects) {
|
|
40
|
-
individualOptions.effects = options.effects(key)
|
|
41
|
-
}
|
|
42
|
-
token = createAtom<T>(individualOptions, family, store)
|
|
43
|
-
subject.next(token)
|
|
44
|
-
}
|
|
45
|
-
return token
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
key: options.key,
|
|
49
|
-
type: `atom_family`,
|
|
50
|
-
subject,
|
|
51
|
-
} as const,
|
|
52
|
-
)
|
|
53
|
-
if (`mutable` in options && typeof options.mutable === `boolean`) {
|
|
54
|
-
Object.assign(atomFamily, { mutable: options.mutable })
|
|
24
|
+
): AtomFamily<T, K>
|
|
25
|
+
export function createAtomFamily<T, K extends Json.Serializable>(
|
|
26
|
+
options: AtomFamilyOptions<T, K> | MutableAtomFamilyOptions<any, any, any>,
|
|
27
|
+
store: Store,
|
|
28
|
+
): AtomFamily<T, K> | MutableAtomFamily<any, any, any> {
|
|
29
|
+
if (`mutable` in options) {
|
|
30
|
+
return createMutableAtomFamily(options, store)
|
|
55
31
|
}
|
|
56
|
-
|
|
57
|
-
target.families.set(options.key, atomFamily)
|
|
58
|
-
return atomFamily
|
|
32
|
+
return createRegularAtomFamily<T, K>(options, store)
|
|
59
33
|
}
|
|
@@ -40,6 +40,7 @@ export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
|
|
|
40
40
|
key: options.key,
|
|
41
41
|
type: `readonly_selector_family`,
|
|
42
42
|
subject,
|
|
43
|
+
install: (store: Store) => createReadonlySelectorFamily(options, store),
|
|
43
44
|
} as const,
|
|
44
45
|
) as ReadonlySelectorFamily<T, K>
|
|
45
46
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AtomFamily,
|
|
3
|
+
AtomFamilyOptions,
|
|
4
|
+
AtomOptions,
|
|
5
|
+
AtomToken,
|
|
6
|
+
FamilyMetadata,
|
|
7
|
+
MutableAtomFamilyOptions,
|
|
8
|
+
} from "atom.io"
|
|
9
|
+
import type { Json } from "atom.io/json"
|
|
10
|
+
import { stringifyJson } from "atom.io/json"
|
|
11
|
+
|
|
12
|
+
import { createRegularAtom } from "../atom"
|
|
13
|
+
import { newest } from "../lineage"
|
|
14
|
+
import { createMutableAtom } from "../mutable"
|
|
15
|
+
import { deposit, withdraw } from "../store"
|
|
16
|
+
import type { Store } from "../store"
|
|
17
|
+
import { Subject } from "../subject"
|
|
18
|
+
|
|
19
|
+
export function createRegularAtomFamily<T, K extends Json.Serializable>(
|
|
20
|
+
options: AtomFamilyOptions<T, K> | MutableAtomFamilyOptions<any, any, K>,
|
|
21
|
+
store: Store,
|
|
22
|
+
): AtomFamily<T, K> {
|
|
23
|
+
const subject = new Subject<AtomToken<T>>()
|
|
24
|
+
const atomFamily = Object.assign(
|
|
25
|
+
(key: K): AtomToken<T> => {
|
|
26
|
+
const subKey = stringifyJson(key)
|
|
27
|
+
const family: FamilyMetadata = { key: options.key, subKey }
|
|
28
|
+
const fullKey = `${options.key}(${subKey})`
|
|
29
|
+
const existing = withdraw({ key: fullKey, type: `atom` }, store)
|
|
30
|
+
let token: AtomToken<any>
|
|
31
|
+
if (existing) {
|
|
32
|
+
token = deposit(existing)
|
|
33
|
+
} else {
|
|
34
|
+
const individualOptions: AtomOptions<any> = {
|
|
35
|
+
key: fullKey,
|
|
36
|
+
default:
|
|
37
|
+
options.default instanceof Function
|
|
38
|
+
? options.default(key)
|
|
39
|
+
: options.default,
|
|
40
|
+
}
|
|
41
|
+
if (options.effects) {
|
|
42
|
+
individualOptions.effects = options.effects(key)
|
|
43
|
+
}
|
|
44
|
+
if (`mutable` in options) {
|
|
45
|
+
const mutableOptions = {
|
|
46
|
+
...individualOptions,
|
|
47
|
+
mutable: true,
|
|
48
|
+
toJson: options.toJson,
|
|
49
|
+
fromJson: options.fromJson,
|
|
50
|
+
} as const
|
|
51
|
+
token = createMutableAtom(mutableOptions, family, store)
|
|
52
|
+
} else {
|
|
53
|
+
token = createRegularAtom<T>(individualOptions, family, store)
|
|
54
|
+
}
|
|
55
|
+
subject.next(token)
|
|
56
|
+
}
|
|
57
|
+
return token
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: options.key,
|
|
61
|
+
type: `atom_family`,
|
|
62
|
+
subject,
|
|
63
|
+
install: (store: Store) => createRegularAtomFamily(options, store),
|
|
64
|
+
} as const,
|
|
65
|
+
)
|
|
66
|
+
if (`mutable` in options && typeof options.mutable === `boolean`) {
|
|
67
|
+
Object.assign(atomFamily, { mutable: options.mutable })
|
|
68
|
+
}
|
|
69
|
+
const target = newest(store)
|
|
70
|
+
target.families.set(options.key, atomFamily)
|
|
71
|
+
return atomFamily
|
|
72
|
+
}
|
|
@@ -60,6 +60,8 @@ export function createSelectorFamily<T, K extends Json.Serializable>(
|
|
|
60
60
|
{
|
|
61
61
|
key: options.key,
|
|
62
62
|
type: `selector_family`,
|
|
63
|
+
subject,
|
|
64
|
+
install: (store: Store) => createSelectorFamily(options, store),
|
|
63
65
|
} as const,
|
|
64
66
|
) as SelectorFamily<T, K>
|
|
65
67
|
target.families.set(options.key, selectorFamily)
|
|
@@ -3,7 +3,7 @@ import type { Json } from "atom.io/json"
|
|
|
3
3
|
import { selectJsonFamily } from "atom.io/json"
|
|
4
4
|
|
|
5
5
|
import type { Store } from ".."
|
|
6
|
-
import {
|
|
6
|
+
import { createRegularAtomFamily } from ".."
|
|
7
7
|
import { FamilyTracker } from "./tracker-family"
|
|
8
8
|
import type { Transceiver } from "./transceiver"
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ export function createMutableAtomFamily<
|
|
|
16
16
|
store: Store,
|
|
17
17
|
): MutableAtomFamily<Core, SerializableCore, Key> {
|
|
18
18
|
const coreFamily = Object.assign(
|
|
19
|
-
|
|
19
|
+
createRegularAtomFamily<Core, Key>(options, store),
|
|
20
20
|
options,
|
|
21
21
|
) as MutableAtomFamily<Core, SerializableCore, Key>
|
|
22
22
|
selectJsonFamily(coreFamily, options)
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
FamilyMetadata,
|
|
3
|
+
MutableAtomOptions,
|
|
4
|
+
MutableAtomToken,
|
|
5
|
+
} from "atom.io"
|
|
2
6
|
import type { Json } from "atom.io/json"
|
|
3
7
|
import { selectJson } from "atom.io/json"
|
|
4
8
|
|
|
5
|
-
import {
|
|
9
|
+
import { createRegularAtom } from "../atom"
|
|
6
10
|
import { newest } from "../lineage"
|
|
7
11
|
import type { Store } from "../store"
|
|
8
12
|
import { subscribeToState } from "../subscribe"
|
|
@@ -14,6 +18,7 @@ export function createMutableAtom<
|
|
|
14
18
|
SerializableCore extends Json.Serializable,
|
|
15
19
|
>(
|
|
16
20
|
options: MutableAtomOptions<Core, SerializableCore>,
|
|
21
|
+
family: FamilyMetadata | undefined,
|
|
17
22
|
store: Store,
|
|
18
23
|
): MutableAtomToken<Core, SerializableCore> {
|
|
19
24
|
store.logger.info(
|
|
@@ -22,7 +27,7 @@ export function createMutableAtom<
|
|
|
22
27
|
options.key,
|
|
23
28
|
`creating in store "${store.config.name}"`,
|
|
24
29
|
)
|
|
25
|
-
const coreState =
|
|
30
|
+
const coreState = createRegularAtom<Core>(options, family, store)
|
|
26
31
|
new Tracker(coreState, store)
|
|
27
32
|
const jsonState = selectJson(coreState, options, store)
|
|
28
33
|
const target = newest(store)
|
|
@@ -1,44 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
AtomToken,
|
|
4
|
-
MutableAtomFamily,
|
|
5
|
-
MutableAtomToken,
|
|
6
|
-
} from "~/packages/atom.io/src"
|
|
1
|
+
import type { AtomFamily, MutableAtomFamily } from "atom.io"
|
|
2
|
+
|
|
7
3
|
import type { MutableAtom } from "."
|
|
8
4
|
import type { Atom } from "../atom"
|
|
9
|
-
import type { Store } from "../store"
|
|
10
|
-
import { withdraw } from "../store"
|
|
11
5
|
|
|
12
|
-
export function isMutable(
|
|
13
|
-
token: AtomToken<any>,
|
|
14
|
-
store: Store,
|
|
15
|
-
): token is MutableAtomToken<any, any>
|
|
16
6
|
export function isMutable(atom: Atom<any>): atom is MutableAtom<any>
|
|
17
7
|
export function isMutable(
|
|
18
8
|
family: AtomFamily<any, any>,
|
|
19
9
|
): family is MutableAtomFamily<any, any, any>
|
|
20
10
|
export function isMutable(
|
|
21
|
-
atomOrTokenOrFamily: Atom<any> | AtomFamily<any, any
|
|
22
|
-
store?: Store,
|
|
11
|
+
atomOrTokenOrFamily: Atom<any> | AtomFamily<any, any>,
|
|
23
12
|
): boolean {
|
|
24
13
|
if (`mutable` in atomOrTokenOrFamily) {
|
|
25
14
|
return atomOrTokenOrFamily.mutable
|
|
26
15
|
}
|
|
27
|
-
if (atomOrTokenOrFamily.type === `atom_family`) {
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
if (`default` in atomOrTokenOrFamily) {
|
|
31
|
-
return false
|
|
32
|
-
}
|
|
33
|
-
if (!store) {
|
|
34
|
-
throw new Error(`Cannot check mutability without a store`)
|
|
35
|
-
}
|
|
36
|
-
const atom = withdraw(atomOrTokenOrFamily, store)
|
|
37
|
-
if (!atom) {
|
|
38
|
-
throw new Error(`Cannot check mutability without an atom`)
|
|
39
|
-
}
|
|
40
|
-
if (`mutable` in atom) {
|
|
41
|
-
return atom.mutable
|
|
42
|
-
}
|
|
43
16
|
return false
|
|
44
17
|
}
|
|
@@ -2,7 +2,7 @@ import type { AtomFamily } from "atom.io"
|
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
import { parseJson } from "atom.io/json"
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { createRegularAtomFamily } from "../families"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
7
|
import { Tracker } from "./tracker"
|
|
8
8
|
import type { Transceiver } from "./transceiver"
|
|
@@ -25,7 +25,7 @@ export class FamilyTracker<
|
|
|
25
25
|
findMutableState: AtomFamily<Core, FamilyMemberKey>,
|
|
26
26
|
store: Store,
|
|
27
27
|
) {
|
|
28
|
-
this.findLatestUpdateState =
|
|
28
|
+
this.findLatestUpdateState = createRegularAtomFamily<
|
|
29
29
|
typeof this.Update | null,
|
|
30
30
|
FamilyMemberKey
|
|
31
31
|
>(
|
|
@@ -4,7 +4,7 @@ import type { Json } from "atom.io/json"
|
|
|
4
4
|
|
|
5
5
|
import type { Store } from ".."
|
|
6
6
|
import { newest, subscribeToState, subscribeToTimeline } from ".."
|
|
7
|
-
import {
|
|
7
|
+
import { createRegularAtom, deleteAtom } from "../atom"
|
|
8
8
|
import type { Transceiver } from "./transceiver"
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -28,7 +28,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
28
28
|
subKey: mutableState.family.subKey,
|
|
29
29
|
}
|
|
30
30
|
: undefined
|
|
31
|
-
const latestUpdateState =
|
|
31
|
+
const latestUpdateState = createRegularAtom<
|
|
32
32
|
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
33
33
|
>(
|
|
34
34
|
{
|
|
@@ -38,7 +38,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
38
38
|
familyMetaData,
|
|
39
39
|
store,
|
|
40
40
|
)
|
|
41
|
-
if (store.parent) {
|
|
41
|
+
if (store.parent?.valueMap.has(latestUpdateStateKey)) {
|
|
42
42
|
const parentValue = store.parent.valueMap.get(latestUpdateStateKey)
|
|
43
43
|
store.valueMap.set(latestUpdateStateKey, parentValue)
|
|
44
44
|
}
|
|
@@ -61,11 +61,11 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
61
61
|
: target.transactionMeta.update.key
|
|
62
62
|
}`,
|
|
63
63
|
(update) => {
|
|
64
|
-
const unsubscribe =
|
|
64
|
+
const unsubscribe = target.subject.operationStatus.subscribe(
|
|
65
65
|
mutableState.key,
|
|
66
66
|
() => {
|
|
67
67
|
unsubscribe()
|
|
68
|
-
setState(latestUpdateState, update,
|
|
68
|
+
setState(latestUpdateState, update, target)
|
|
69
69
|
},
|
|
70
70
|
)
|
|
71
71
|
},
|