atom.io 0.27.4 → 0.28.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/data/dist/index.d.ts +31 -29
- package/data/dist/index.js +65 -81
- package/data/src/dict.ts +9 -12
- package/data/src/join.ts +30 -33
- package/data/src/struct-family.ts +17 -23
- package/data/src/struct.ts +9 -12
- package/dist/{chunk-JRENM6KL.js → chunk-BX3MTH2Z.js} +482 -385
- package/dist/chunk-D52JNVER.js +721 -0
- package/dist/chunk-EUVKUTW3.js +89 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +35 -53
- package/ephemeral/dist/index.js +1 -1
- package/ephemeral/src/find-state.ts +1 -1
- package/immortal/dist/index.js +2 -2
- package/immortal/src/seek-state.ts +2 -2
- package/internal/dist/index.d.ts +141 -87
- package/internal/dist/index.js +1 -1
- package/internal/src/atom/create-regular-atom.ts +3 -3
- package/internal/src/atom/create-standalone-atom.ts +7 -5
- package/internal/src/atom/dispose-atom.ts +2 -9
- package/internal/src/families/create-atom-family.ts +5 -5
- package/internal/src/families/create-readonly-selector-family.ts +20 -9
- package/internal/src/families/create-regular-atom-family.ts +15 -6
- package/internal/src/families/create-selector-family.ts +5 -5
- package/internal/src/families/create-writable-selector-family.ts +20 -10
- package/internal/src/families/dispose-from-store.ts +43 -29
- package/internal/src/families/find-in-store.ts +28 -18
- package/internal/src/families/init-family-member.ts +9 -9
- package/internal/src/families/seek-in-store.ts +10 -10
- package/internal/src/get-state/get-from-store.ts +70 -47
- package/internal/src/ingest-updates/ingest-atom-update.ts +1 -1
- package/internal/src/ingest-updates/ingest-creation-disposal.ts +15 -6
- package/internal/src/molecule/create-molecule-family.ts +1 -1
- package/internal/src/molecule/dispose-molecule.ts +7 -18
- package/internal/src/molecule/grow-molecule-in-store.ts +1 -1
- package/internal/src/molecule/make-molecule-in-store.ts +5 -5
- package/internal/src/mutable/create-mutable-atom-family.ts +15 -6
- package/internal/src/mutable/create-mutable-atom.ts +3 -3
- package/internal/src/mutable/get-json-token.ts +2 -2
- package/internal/src/mutable/tracker-family.ts +3 -3
- package/internal/src/mutable/tracker.ts +14 -18
- package/internal/src/pretty-print.ts +1 -16
- package/internal/src/selector/create-readonly-selector.ts +2 -2
- package/internal/src/selector/create-standalone-selector.ts +5 -5
- package/internal/src/selector/create-writable-selector.ts +2 -2
- package/internal/src/selector/dispose-selector.ts +2 -9
- package/internal/src/selector/register-selector.ts +9 -9
- package/internal/src/set-state/set-into-store.ts +23 -33
- package/internal/src/store/circular-buffer.ts +34 -0
- package/internal/src/store/counterfeit.ts +109 -0
- package/internal/src/store/deposit.ts +67 -13
- package/internal/src/store/index.ts +1 -0
- package/internal/src/store/store.ts +4 -1
- package/internal/src/store/withdraw.ts +15 -10
- package/internal/src/subscribe/index.ts +2 -0
- package/internal/src/subscribe/subscribe-in-store.ts +62 -0
- package/internal/src/timeline/time-travel.ts +1 -1
- package/internal/src/transaction/build-transaction.ts +7 -6
- package/introspection/dist/index.d.ts +84 -4
- package/introspection/dist/index.js +1 -413
- package/introspection/src/attach-atom-index.ts +5 -8
- package/introspection/src/attach-introspection-states.ts +7 -4
- package/introspection/src/attach-selector-index.ts +6 -8
- package/introspection/src/attach-timeline-family.ts +25 -28
- package/introspection/src/attach-timeline-index.ts +5 -8
- package/introspection/src/attach-transaction-index.ts +5 -8
- package/introspection/src/attach-transaction-logs.ts +21 -27
- package/introspection/src/attach-type-selectors.ts +26 -0
- package/introspection/src/differ.ts +167 -0
- package/introspection/src/index.ts +2 -0
- package/introspection/src/refinery.ts +100 -0
- package/json/dist/index.d.ts +31 -30
- package/json/dist/index.js +2 -80
- package/json/src/entries.ts +6 -0
- package/json/src/index.ts +47 -6
- package/json/src/select-json-family.ts +4 -4
- package/json/src/select-json.ts +6 -9
- package/package.json +17 -8
- package/react/dist/index.js +7 -7
- package/react/src/parse-state-overloads.ts +2 -2
- package/react/src/use-i.ts +1 -1
- package/react/src/use-json.ts +2 -2
- package/react/src/use-o.ts +2 -2
- package/react-devtools/dist/index.d.ts +1 -91
- package/react-devtools/dist/index.js +285 -414
- package/react-devtools/src/AtomIODevtools.tsx +2 -2
- package/react-devtools/src/StateEditor.tsx +20 -12
- package/react-devtools/src/StateIndex.tsx +8 -26
- package/react-devtools/src/TimelineIndex.tsx +3 -3
- package/react-devtools/src/TransactionIndex.tsx +6 -6
- package/react-devtools/src/Updates.tsx +1 -4
- package/react-devtools/src/index.ts +0 -71
- package/react-devtools/src/store.ts +51 -0
- package/realtime/dist/index.d.ts +7 -7
- package/realtime/dist/index.js +18 -22
- package/realtime/src/realtime-continuity.ts +27 -35
- package/realtime-client/dist/index.js +59 -65
- package/realtime-client/src/pull-atom-family-member.ts +1 -1
- package/realtime-client/src/pull-atom.ts +1 -1
- package/realtime-client/src/pull-mutable-atom-family-member.ts +3 -3
- package/realtime-client/src/pull-mutable-atom.ts +3 -3
- package/realtime-client/src/realtime-client-stores/client-main-store.ts +6 -6
- package/realtime-client/src/sync-continuity.ts +55 -53
- package/realtime-react/dist/index.js +3 -3
- package/realtime-react/src/use-pull-atom-family-member.ts +1 -1
- package/realtime-react/src/use-pull-mutable-family-member.ts +1 -1
- package/realtime-react/src/use-pull-selector-family-member.ts +1 -1
- package/realtime-server/dist/index.js +72 -36
- package/realtime-server/src/realtime-continuity-synchronizer.ts +57 -93
- package/realtime-server/src/realtime-family-provider.ts +3 -3
- package/realtime-server/src/realtime-mutable-family-provider.ts +5 -5
- package/realtime-server/src/realtime-mutable-provider.ts +2 -2
- package/realtime-server/src/realtime-state-provider.ts +1 -1
- package/realtime-server/src/realtime-state-receiver.ts +1 -1
- package/realtime-testing/dist/index.d.ts +2 -0
- package/realtime-testing/dist/index.js +57 -15
- package/realtime-testing/src/setup-realtime-test.tsx +66 -16
- package/src/atom.ts +2 -2
- package/src/dispose-state.ts +2 -2
- package/src/get-state.ts +9 -13
- package/src/molecule.ts +1 -1
- package/src/selector.ts +2 -2
- package/src/set-state.ts +10 -7
- package/src/silo.ts +29 -55
- package/src/subscribe.ts +3 -23
- package/src/timeline.ts +2 -2
- package/web/dist/index.d.ts +9 -0
- package/{dist/chunk-H6EDLPKH.js → web/dist/index.js} +5 -4
- package/web/package.json +13 -0
- package/web/src/index.ts +1 -0
- package/web/src/persist-sync.ts +25 -0
- package/dist/chunk-AK23DRMD.js +0 -21
- package/dist/chunk-IW6WYRS7.js +0 -140
- package/internal/src/families/throw-in-case-of-conflicting-family.ts +0 -18
|
@@ -22,7 +22,7 @@ export function ingestCreationEvent(
|
|
|
22
22
|
break
|
|
23
23
|
}
|
|
24
24
|
case `oldValue`: {
|
|
25
|
-
disposeFromStore(update.token
|
|
25
|
+
disposeFromStore(store, update.token)
|
|
26
26
|
break
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -35,7 +35,7 @@ export function ingestDisposalEvent(
|
|
|
35
35
|
): void {
|
|
36
36
|
switch (applying) {
|
|
37
37
|
case `newValue`: {
|
|
38
|
-
disposeFromStore(update.token
|
|
38
|
+
disposeFromStore(store, update.token)
|
|
39
39
|
break
|
|
40
40
|
}
|
|
41
41
|
case `oldValue`: {
|
|
@@ -56,9 +56,18 @@ function createInStore(token: ReadableToken<any>, store: Store): void {
|
|
|
56
56
|
return
|
|
57
57
|
}
|
|
58
58
|
if (store.config.lifespan === `immortal`) {
|
|
59
|
-
|
|
59
|
+
store.logger.error(
|
|
60
|
+
`🐞`,
|
|
61
|
+
`atom`,
|
|
62
|
+
token.family.key,
|
|
63
|
+
`tried to create member`,
|
|
64
|
+
`"${token.family.subKey}"`,
|
|
65
|
+
`but a molecule with that key was not found in store`,
|
|
66
|
+
`"${store.config.name}"`,
|
|
67
|
+
)
|
|
68
|
+
return
|
|
60
69
|
}
|
|
61
|
-
initFamilyMemberInStore(family, parseJson(token.family.subKey)
|
|
70
|
+
initFamilyMemberInStore(store, family, parseJson(token.family.subKey))
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
}
|
|
@@ -79,7 +88,7 @@ export function ingestMoleculeCreationEvent(
|
|
|
79
88
|
)
|
|
80
89
|
break
|
|
81
90
|
case `oldValue`:
|
|
82
|
-
disposeFromStore(update.token
|
|
91
|
+
disposeFromStore(store, update.token)
|
|
83
92
|
break
|
|
84
93
|
}
|
|
85
94
|
}
|
|
@@ -90,7 +99,7 @@ export function ingestMoleculeDisposalEvent(
|
|
|
90
99
|
): void {
|
|
91
100
|
switch (applying) {
|
|
92
101
|
case `newValue`:
|
|
93
|
-
disposeFromStore(update.token
|
|
102
|
+
disposeFromStore(store, update.token)
|
|
94
103
|
break
|
|
95
104
|
case `oldValue`:
|
|
96
105
|
{
|
|
@@ -10,8 +10,8 @@ import type { Store } from "../store"
|
|
|
10
10
|
import { Subject } from "../subject"
|
|
11
11
|
|
|
12
12
|
export function createMoleculeFamily<M extends MoleculeConstructor>(
|
|
13
|
-
options: MoleculeFamilyOptions<M>,
|
|
14
13
|
store: Store,
|
|
14
|
+
options: MoleculeFamilyOptions<M>,
|
|
15
15
|
): MoleculeFamilyToken<M> {
|
|
16
16
|
const subject = new Subject<MoleculeCreation<M>>()
|
|
17
17
|
|
|
@@ -15,22 +15,14 @@ export function disposeMolecule<M extends MoleculeConstructor>(
|
|
|
15
15
|
store: Store,
|
|
16
16
|
): void {
|
|
17
17
|
let molecule: Molecule<M>
|
|
18
|
-
|
|
19
|
-
molecule = withdraw(token, store)
|
|
20
|
-
} catch (thrown) {
|
|
21
|
-
if (thrown instanceof Error) {
|
|
22
|
-
store.logger.error(
|
|
23
|
-
`🐞`,
|
|
24
|
-
`molecule`,
|
|
25
|
-
JSON.stringify(token.key),
|
|
26
|
-
`Failed to dispose molecule, because it was not found in the store.`,
|
|
27
|
-
thrown.message,
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
return
|
|
31
|
-
}
|
|
18
|
+
molecule = withdraw(token, store)
|
|
32
19
|
const { family } = token
|
|
33
20
|
|
|
21
|
+
for (const join of molecule.joins.values()) {
|
|
22
|
+
join.relations.delete(molecule.key)
|
|
23
|
+
join.molecules.delete(molecule.stringKey)
|
|
24
|
+
}
|
|
25
|
+
|
|
34
26
|
const context: MoleculeToken<any>[] = []
|
|
35
27
|
for (const above of molecule.above.values()) {
|
|
36
28
|
context.push(deposit(above))
|
|
@@ -55,7 +47,7 @@ export function disposeMolecule<M extends MoleculeConstructor>(
|
|
|
55
47
|
disposalEvent.family = token.family
|
|
56
48
|
}
|
|
57
49
|
for (const state of molecule.tokens.values()) {
|
|
58
|
-
disposeFromStore(
|
|
50
|
+
disposeFromStore(store, state)
|
|
59
51
|
}
|
|
60
52
|
for (const child of molecule.below.values()) {
|
|
61
53
|
if (child.family?.dependsOn === `all`) {
|
|
@@ -79,9 +71,6 @@ export function disposeMolecule<M extends MoleculeConstructor>(
|
|
|
79
71
|
store.molecules.delete(molecule.stringKey)
|
|
80
72
|
}
|
|
81
73
|
|
|
82
|
-
for (const join of molecule.joins.values()) {
|
|
83
|
-
join.molecules.delete(molecule.stringKey)
|
|
84
|
-
}
|
|
85
74
|
for (const parent of molecule.above.values()) {
|
|
86
75
|
parent.below.delete(molecule.stringKey)
|
|
87
76
|
}
|
|
@@ -83,7 +83,7 @@ export function growMoleculeInStore(
|
|
|
83
83
|
family: ReadableFamilyToken<any, any>,
|
|
84
84
|
store: Store,
|
|
85
85
|
): ReadableToken<any> {
|
|
86
|
-
const stateToken = initFamilyMemberInStore(family, molecule.key
|
|
86
|
+
const stateToken = initFamilyMemberInStore(store, family, molecule.key)
|
|
87
87
|
molecule.tokens.set(stateToken.key, stateToken)
|
|
88
88
|
const isTransaction =
|
|
89
89
|
isChildStore(store) && store.transactionMeta.phase === `building`
|
|
@@ -68,17 +68,17 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
|
|
|
68
68
|
|
|
69
69
|
const toolkit = {
|
|
70
70
|
get: ((...ps: Parameters<typeof getState>) =>
|
|
71
|
-
getFromStore(
|
|
71
|
+
getFromStore(newest(rootStore), ...ps)) as typeof getState,
|
|
72
72
|
set: ((...ps: Parameters<typeof setState>) => {
|
|
73
|
-
setIntoStore(
|
|
73
|
+
setIntoStore(newest(rootStore), ...ps)
|
|
74
74
|
}) as typeof setState,
|
|
75
|
-
seek: ((t, k) => seekInStore(t, k
|
|
76
|
-
json: (t) => getJsonToken(
|
|
75
|
+
seek: ((t, k) => seekInStore(newest(rootStore), t, k)) as typeof seekState,
|
|
76
|
+
json: (t) => getJsonToken(newest(rootStore), t),
|
|
77
77
|
run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
|
|
78
78
|
make: (ctx, f, k, ...args) =>
|
|
79
79
|
makeMoleculeInStore(newest(rootStore), ctx, f, k, ...args),
|
|
80
80
|
dispose: (t) => {
|
|
81
|
-
disposeFromStore(
|
|
81
|
+
disposeFromStore(newest(rootStore), t)
|
|
82
82
|
},
|
|
83
83
|
env: () => getEnvironmentData(newest(rootStore)),
|
|
84
84
|
bond: ((
|
|
@@ -10,8 +10,7 @@ import type {
|
|
|
10
10
|
import type { Json } from "atom.io/json"
|
|
11
11
|
import { selectJsonFamily, stringifyJson } from "atom.io/json"
|
|
12
12
|
|
|
13
|
-
import type
|
|
14
|
-
import { throwInCaseOfConflictingFamily } from "../families/throw-in-case-of-conflicting-family"
|
|
13
|
+
import { type MutableAtomFamily, prettyPrintTokenType } from ".."
|
|
15
14
|
import { newest } from "../lineage"
|
|
16
15
|
import { createMutableAtom } from "../mutable"
|
|
17
16
|
import type { Store } from "../store"
|
|
@@ -24,8 +23,8 @@ export function createMutableAtomFamily<
|
|
|
24
23
|
J extends Json.Serializable,
|
|
25
24
|
K extends string,
|
|
26
25
|
>(
|
|
27
|
-
options: MutableAtomFamilyOptions<T, J, K>,
|
|
28
26
|
store: Store,
|
|
27
|
+
options: MutableAtomFamilyOptions<T, J, K>,
|
|
29
28
|
internalRoles?: string[],
|
|
30
29
|
): MutableAtomFamilyToken<T, J, K> {
|
|
31
30
|
const familyToken = {
|
|
@@ -33,7 +32,17 @@ export function createMutableAtomFamily<
|
|
|
33
32
|
type: `mutable_atom_family`,
|
|
34
33
|
} as const satisfies MutableAtomFamilyToken<T, J, K>
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
const existing = store.families.get(options.key)
|
|
36
|
+
if (existing) {
|
|
37
|
+
store.logger.error(
|
|
38
|
+
`❗`,
|
|
39
|
+
`mutable_atom_family`,
|
|
40
|
+
options.key,
|
|
41
|
+
`Overwriting an existing ${prettyPrintTokenType(
|
|
42
|
+
existing,
|
|
43
|
+
)} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
37
46
|
|
|
38
47
|
const subject = new Subject<
|
|
39
48
|
StateCreation<MutableAtomToken<T, J>> | StateDisposal<MutableAtomToken<T, J>>
|
|
@@ -56,7 +65,7 @@ export function createMutableAtomFamily<
|
|
|
56
65
|
individualOptions.effects = options.effects(key)
|
|
57
66
|
}
|
|
58
67
|
|
|
59
|
-
const token = createMutableAtom(individualOptions, family
|
|
68
|
+
const token = createMutableAtom(target, individualOptions, family)
|
|
60
69
|
|
|
61
70
|
subject.next({ type: `state_creation`, token })
|
|
62
71
|
return token
|
|
@@ -64,7 +73,7 @@ export function createMutableAtomFamily<
|
|
|
64
73
|
|
|
65
74
|
const atomFamily = Object.assign(familyFunction, familyToken, {
|
|
66
75
|
subject,
|
|
67
|
-
install: (s: Store) => createMutableAtomFamily(
|
|
76
|
+
install: (s: Store) => createMutableAtomFamily(s, options),
|
|
68
77
|
toJson: options.toJson,
|
|
69
78
|
fromJson: options.fromJson,
|
|
70
79
|
internalRoles,
|
|
@@ -20,9 +20,9 @@ export function createMutableAtom<
|
|
|
20
20
|
T extends Transceiver<any>,
|
|
21
21
|
J extends Json.Serializable,
|
|
22
22
|
>(
|
|
23
|
+
store: Store,
|
|
23
24
|
options: MutableAtomOptions<T, J>,
|
|
24
25
|
family: FamilyMetadata | undefined,
|
|
25
|
-
store: Store,
|
|
26
26
|
): MutableAtomToken<T, J> {
|
|
27
27
|
store.logger.info(
|
|
28
28
|
`🔨`,
|
|
@@ -52,7 +52,7 @@ export function createMutableAtom<
|
|
|
52
52
|
options.key,
|
|
53
53
|
`installing in store "${s.config.name}"`,
|
|
54
54
|
)
|
|
55
|
-
return createMutableAtom(options, family
|
|
55
|
+
return createMutableAtom(s, options, family)
|
|
56
56
|
},
|
|
57
57
|
subject,
|
|
58
58
|
} as const
|
|
@@ -70,7 +70,7 @@ export function createMutableAtom<
|
|
|
70
70
|
for (const effect of options.effects) {
|
|
71
71
|
const cleanup = effect({
|
|
72
72
|
setSelf: (next) => {
|
|
73
|
-
setIntoStore(token, next
|
|
73
|
+
setIntoStore(store, token, next)
|
|
74
74
|
},
|
|
75
75
|
onSet: (handle: UpdateHandler<T>) =>
|
|
76
76
|
subscribeToState(token, handle, `effect[${effectIndex}]`, store),
|
|
@@ -14,8 +14,8 @@ export const getJsonToken = <
|
|
|
14
14
|
Core extends Transceiver<any>,
|
|
15
15
|
SerializableCore extends Json.Serializable,
|
|
16
16
|
>(
|
|
17
|
-
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
18
17
|
store: Store,
|
|
18
|
+
mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
|
|
19
19
|
): WritableSelectorToken<SerializableCore> => {
|
|
20
20
|
if (mutableAtomToken.family) {
|
|
21
21
|
const target = newest(store)
|
|
@@ -29,7 +29,7 @@ export const getJsonToken = <
|
|
|
29
29
|
}
|
|
30
30
|
const family = withdraw(jsonFamilyToken, target)
|
|
31
31
|
const subKey = JSON.parse(mutableAtomToken.family.subKey)
|
|
32
|
-
const jsonToken = findInStore(family, subKey
|
|
32
|
+
const jsonToken = findInStore(store, family, subKey)
|
|
33
33
|
return jsonToken
|
|
34
34
|
}
|
|
35
35
|
const token: WritableSelectorToken<SerializableCore> = {
|
|
@@ -29,11 +29,11 @@ export class FamilyTracker<
|
|
|
29
29
|
typeof this.Update | null,
|
|
30
30
|
FamilyMemberKey
|
|
31
31
|
>(
|
|
32
|
+
store,
|
|
32
33
|
{
|
|
33
34
|
key: `*${mutableAtoms.key}`,
|
|
34
35
|
default: null,
|
|
35
36
|
},
|
|
36
|
-
store,
|
|
37
37
|
[`mutable`, `updates`],
|
|
38
38
|
)
|
|
39
39
|
this.latestUpdateAtoms = withdraw(updateAtoms, store)
|
|
@@ -43,7 +43,7 @@ export class FamilyTracker<
|
|
|
43
43
|
(event) => {
|
|
44
44
|
if (event.token.family) {
|
|
45
45
|
const key = parseJson(event.token.family.subKey) as FamilyMemberKey
|
|
46
|
-
seekInStore(this.latestUpdateAtoms, key
|
|
46
|
+
seekInStore(store, this.latestUpdateAtoms, key)
|
|
47
47
|
new Tracker<Core>(event.token, store)
|
|
48
48
|
}
|
|
49
49
|
},
|
|
@@ -53,7 +53,7 @@ export class FamilyTracker<
|
|
|
53
53
|
(event) => {
|
|
54
54
|
if (event.token.family) {
|
|
55
55
|
const key = parseJson(event.token.family.subKey) as FamilyMemberKey
|
|
56
|
-
const mutableAtomToken = seekInStore(this.mutableAtoms, key
|
|
56
|
+
const mutableAtomToken = seekInStore(store, this.mutableAtoms, key)
|
|
57
57
|
if (mutableAtomToken) {
|
|
58
58
|
new Tracker<Core>(mutableAtomToken, store)
|
|
59
59
|
}
|
|
@@ -37,12 +37,12 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
37
37
|
const latestUpdateState = createRegularAtom<
|
|
38
38
|
(Mutable extends Transceiver<infer Signal> ? Signal : never) | null
|
|
39
39
|
>(
|
|
40
|
+
store,
|
|
40
41
|
{
|
|
41
42
|
key: latestUpdateStateKey,
|
|
42
43
|
default: null,
|
|
43
44
|
},
|
|
44
45
|
familyMetaData,
|
|
45
|
-
store,
|
|
46
46
|
)
|
|
47
47
|
if (store.parent?.valueMap.has(latestUpdateStateKey)) {
|
|
48
48
|
const parentValue = store.parent.valueMap.get(latestUpdateStateKey)
|
|
@@ -62,11 +62,11 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
62
62
|
const subscriptionKey = `tracker:${target.config.name}:${
|
|
63
63
|
isChildStore(target) ? target.transactionMeta.update.key : `main`
|
|
64
64
|
}:${mutableState.key}`
|
|
65
|
-
const originalInnerValue = getFromStore(
|
|
65
|
+
const originalInnerValue = getFromStore(target, mutableState)
|
|
66
66
|
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
67
67
|
subscriptionKey,
|
|
68
68
|
(update) => {
|
|
69
|
-
setIntoStore(latestUpdateState, update
|
|
69
|
+
setIntoStore(target, latestUpdateState, update)
|
|
70
70
|
},
|
|
71
71
|
)
|
|
72
72
|
this.unsubscribeFromState = subscribeToState(
|
|
@@ -77,7 +77,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
77
77
|
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
78
78
|
subscriptionKey,
|
|
79
79
|
(transceiverUpdate) => {
|
|
80
|
-
setIntoStore(latestUpdateState, transceiverUpdate
|
|
80
|
+
setIntoStore(target, latestUpdateState, transceiverUpdate)
|
|
81
81
|
},
|
|
82
82
|
)
|
|
83
83
|
}
|
|
@@ -109,18 +109,14 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
109
109
|
{ key: timelineId, type: `timeline` },
|
|
110
110
|
(update) => {
|
|
111
111
|
unsubscribe()
|
|
112
|
-
setIntoStore(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return transceiver
|
|
121
|
-
},
|
|
122
|
-
target,
|
|
123
|
-
)
|
|
112
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
113
|
+
if (update === `redo` && newValue) {
|
|
114
|
+
transceiver.do(newValue)
|
|
115
|
+
} else if (update === `undo` && oldValue) {
|
|
116
|
+
transceiver.undo(oldValue)
|
|
117
|
+
}
|
|
118
|
+
return transceiver
|
|
119
|
+
})
|
|
124
120
|
},
|
|
125
121
|
subscriptionKey,
|
|
126
122
|
target,
|
|
@@ -133,15 +129,15 @@ export class Tracker<Mutable extends Transceiver<any>> {
|
|
|
133
129
|
subscriptionKey,
|
|
134
130
|
() => {
|
|
135
131
|
unsubscribe()
|
|
136
|
-
const mutable = getFromStore(
|
|
132
|
+
const mutable = getFromStore(target, mutableState)
|
|
137
133
|
const updateNumber =
|
|
138
134
|
newValue === null ? -1 : mutable.getUpdateNumber(newValue)
|
|
139
135
|
const eventOffset = updateNumber - mutable.cacheUpdateNumber
|
|
140
136
|
if (newValue && eventOffset === 1) {
|
|
141
137
|
setIntoStore(
|
|
138
|
+
target,
|
|
142
139
|
mutableState,
|
|
143
140
|
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
144
|
-
target,
|
|
145
141
|
)
|
|
146
142
|
} else {
|
|
147
143
|
target.logger.info(
|
|
@@ -18,20 +18,5 @@ export type AtomIOToken =
|
|
|
18
18
|
| TransactionToken<any>
|
|
19
19
|
|
|
20
20
|
export function prettyPrintTokenType(token: AtomIOToken): string {
|
|
21
|
-
|
|
22
|
-
case `atom_family`:
|
|
23
|
-
return `Atom Family`
|
|
24
|
-
case `molecule_family`:
|
|
25
|
-
return `Molecule Family`
|
|
26
|
-
case `mutable_atom_family`:
|
|
27
|
-
return `Mutable Atom Family`
|
|
28
|
-
case `readonly_selector`:
|
|
29
|
-
return `Readonly Selector`
|
|
30
|
-
case `readonly_selector_family`:
|
|
31
|
-
return `Readonly Selector Family`
|
|
32
|
-
case `selector_family`:
|
|
33
|
-
return `Selector Family`
|
|
34
|
-
default:
|
|
35
|
-
return capitalize(token.type)
|
|
36
|
-
}
|
|
21
|
+
return token.type.split(`_`).map(capitalize).join(` `)
|
|
37
22
|
}
|
|
@@ -12,9 +12,9 @@ import { Subject } from "../subject"
|
|
|
12
12
|
import { registerSelector } from "./register-selector"
|
|
13
13
|
|
|
14
14
|
export const createReadonlySelector = <T>(
|
|
15
|
+
store: Store,
|
|
15
16
|
options: ReadonlySelectorOptions<T>,
|
|
16
17
|
family: FamilyMetadata | undefined,
|
|
17
|
-
store: Store,
|
|
18
18
|
): ReadonlySelectorToken<T> => {
|
|
19
19
|
const target = newest(store)
|
|
20
20
|
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
@@ -34,7 +34,7 @@ export const createReadonlySelector = <T>(
|
|
|
34
34
|
const readonlySelector: ReadonlySelector<T> = {
|
|
35
35
|
...options,
|
|
36
36
|
subject,
|
|
37
|
-
install: (s: Store) => createReadonlySelector(options, family
|
|
37
|
+
install: (s: Store) => createReadonlySelector(s, options, family),
|
|
38
38
|
get: getSelf,
|
|
39
39
|
type: `readonly_selector`,
|
|
40
40
|
...(family && { family }),
|
|
@@ -10,25 +10,25 @@ import { createReadonlySelector } from "./create-readonly-selector"
|
|
|
10
10
|
import { createWritableSelector } from "./create-writable-selector"
|
|
11
11
|
|
|
12
12
|
export function createStandaloneSelector<T>(
|
|
13
|
-
options: WritableSelectorOptions<T>,
|
|
14
13
|
store: Store,
|
|
14
|
+
options: WritableSelectorOptions<T>,
|
|
15
15
|
): WritableSelectorToken<T>
|
|
16
16
|
export function createStandaloneSelector<T>(
|
|
17
|
-
options: ReadonlySelectorOptions<T>,
|
|
18
17
|
store: Store,
|
|
18
|
+
options: ReadonlySelectorOptions<T>,
|
|
19
19
|
): ReadonlySelectorToken<T>
|
|
20
20
|
export function createStandaloneSelector<T>(
|
|
21
|
-
options: ReadonlySelectorOptions<T> | WritableSelectorOptions<T>,
|
|
22
21
|
store: Store,
|
|
22
|
+
options: ReadonlySelectorOptions<T> | WritableSelectorOptions<T>,
|
|
23
23
|
): ReadonlySelectorToken<T> | WritableSelectorToken<T> {
|
|
24
24
|
const isWritable = `set` in options
|
|
25
25
|
|
|
26
26
|
if (isWritable) {
|
|
27
|
-
const state = createWritableSelector(options, undefined
|
|
27
|
+
const state = createWritableSelector(store, options, undefined)
|
|
28
28
|
store.on.selectorCreation.next(state)
|
|
29
29
|
return state
|
|
30
30
|
}
|
|
31
|
-
const state = createReadonlySelector(options, undefined
|
|
31
|
+
const state = createReadonlySelector(store, options, undefined)
|
|
32
32
|
store.on.selectorCreation.next(state)
|
|
33
33
|
return state
|
|
34
34
|
}
|
|
@@ -15,9 +15,9 @@ import { isRootStore } from "../transaction"
|
|
|
15
15
|
import { registerSelector } from "./register-selector"
|
|
16
16
|
|
|
17
17
|
export const createWritableSelector = <T>(
|
|
18
|
+
store: Store,
|
|
18
19
|
options: WritableSelectorOptions<T>,
|
|
19
20
|
family: FamilyMetadata | undefined,
|
|
20
|
-
store: Store,
|
|
21
21
|
): WritableSelectorToken<T> => {
|
|
22
22
|
const target = newest(store)
|
|
23
23
|
const subject = new Subject<{ newValue: T; oldValue: T }>()
|
|
@@ -57,7 +57,7 @@ export const createWritableSelector = <T>(
|
|
|
57
57
|
const mySelector: WritableSelector<T> = {
|
|
58
58
|
...options,
|
|
59
59
|
subject,
|
|
60
|
-
install: (s: Store) => createWritableSelector(options, family
|
|
60
|
+
install: (s: Store) => createWritableSelector(s, options, family),
|
|
61
61
|
get: getSelf,
|
|
62
62
|
set: setSelf,
|
|
63
63
|
type: `selector`,
|
|
@@ -9,15 +9,8 @@ export function disposeSelector(
|
|
|
9
9
|
): void {
|
|
10
10
|
const target = newest(store)
|
|
11
11
|
const { key } = selectorToken
|
|
12
|
-
const selector =
|
|
13
|
-
if (!selector) {
|
|
14
|
-
store.logger.info(
|
|
15
|
-
`❌`,
|
|
16
|
-
`selector`,
|
|
17
|
-
key,
|
|
18
|
-
`Tried to dispose selector, but it does not exist in the store.`,
|
|
19
|
-
)
|
|
20
|
-
} else if (!selector.family) {
|
|
12
|
+
const selector = withdraw(selectorToken, target)
|
|
13
|
+
if (!selector.family) {
|
|
21
14
|
store.logger.error(
|
|
22
15
|
`❌`,
|
|
23
16
|
`selector`,
|
|
@@ -43,12 +43,12 @@ export const registerSelector = (
|
|
|
43
43
|
const [family, key] = params
|
|
44
44
|
switch (family.type) {
|
|
45
45
|
case `molecule_family`:
|
|
46
|
-
return getFromStore(family, key
|
|
46
|
+
return getFromStore(store, family, key)
|
|
47
47
|
default:
|
|
48
48
|
if (store.config.lifespan === `ephemeral`) {
|
|
49
|
-
dependency = findInStore(family, key
|
|
49
|
+
dependency = findInStore(store, family, key)
|
|
50
50
|
} else {
|
|
51
|
-
const maybeDependency = seekInStore(family, key
|
|
51
|
+
const maybeDependency = seekInStore(store, family, key)
|
|
52
52
|
if (maybeDependency) {
|
|
53
53
|
dependency = maybeDependency
|
|
54
54
|
} else {
|
|
@@ -61,7 +61,7 @@ export const registerSelector = (
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
if (dependency.type === `molecule`) {
|
|
64
|
-
return getFromStore(
|
|
64
|
+
return getFromStore(store, dependency)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
const dependencyState = withdraw(dependency, store)
|
|
@@ -108,8 +108,8 @@ export const registerSelector = (
|
|
|
108
108
|
value = params[2]
|
|
109
109
|
const maybeToken =
|
|
110
110
|
store.config.lifespan === `ephemeral`
|
|
111
|
-
? findInStore(family, key
|
|
112
|
-
: seekInStore(family, key
|
|
111
|
+
? findInStore(store, family, key)
|
|
112
|
+
: seekInStore(store, family, key)
|
|
113
113
|
if (!maybeToken) {
|
|
114
114
|
throw new NotFoundError(family, key, store)
|
|
115
115
|
}
|
|
@@ -119,7 +119,7 @@ export const registerSelector = (
|
|
|
119
119
|
const state = withdraw(token, target)
|
|
120
120
|
setAtomOrSelector(state, value, target)
|
|
121
121
|
}) as typeof setState,
|
|
122
|
-
find: ((token, key) => findInStore(token, key
|
|
123
|
-
seek: ((token, key) => seekInStore(token, key
|
|
124
|
-
json: (token) => getJsonToken(
|
|
122
|
+
find: ((token, key) => findInStore(store, token, key)) as typeof findState,
|
|
123
|
+
seek: ((token, key) => seekInStore(store, token, key)) as typeof seekState,
|
|
124
|
+
json: (token) => getJsonToken(store, token),
|
|
125
125
|
})
|
|
@@ -1,72 +1,62 @@
|
|
|
1
1
|
import type { WritableFamilyToken, WritableToken } from "atom.io"
|
|
2
2
|
import { type Canonical, stringifyJson } from "atom.io/json"
|
|
3
3
|
|
|
4
|
-
import { findInStore
|
|
5
|
-
import { NotFoundError } from "../not-found-error"
|
|
4
|
+
import { findInStore } from "../families"
|
|
6
5
|
import { closeOperation, openOperation } from "../operation"
|
|
7
6
|
import type { Store } from "../store"
|
|
8
7
|
import { withdraw } from "../store"
|
|
9
8
|
import { setAtomOrSelector } from "./set-atom-or-selector"
|
|
10
9
|
|
|
11
10
|
export function setIntoStore<T, New extends T>(
|
|
11
|
+
store: Store,
|
|
12
12
|
token: WritableToken<T>,
|
|
13
13
|
value: New | ((oldValue: T) => New),
|
|
14
|
-
store: Store,
|
|
15
14
|
): void
|
|
16
15
|
|
|
17
16
|
export function setIntoStore<T, K extends Canonical, New extends T>(
|
|
17
|
+
store: Store,
|
|
18
18
|
token: WritableFamilyToken<T, K>,
|
|
19
19
|
key: K,
|
|
20
20
|
value: New | ((oldValue: T) => New),
|
|
21
|
-
store: Store,
|
|
22
21
|
): void
|
|
23
22
|
|
|
24
23
|
export function setIntoStore<T, New extends T>(
|
|
24
|
+
store: Store,
|
|
25
25
|
...params:
|
|
26
26
|
| [
|
|
27
27
|
token: WritableFamilyToken<T, Canonical>,
|
|
28
28
|
key: Canonical,
|
|
29
29
|
value: New | ((oldValue: T) => New),
|
|
30
|
-
store: Store,
|
|
31
|
-
]
|
|
32
|
-
| [
|
|
33
|
-
token: WritableToken<T>,
|
|
34
|
-
value: New | ((oldValue: T) => New),
|
|
35
|
-
store: Store,
|
|
36
30
|
]
|
|
31
|
+
| [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
|
|
37
32
|
): void {
|
|
38
33
|
let token: WritableToken<T>
|
|
39
34
|
let value: New | ((oldValue: T) => New)
|
|
40
|
-
|
|
41
|
-
if (params.length === 3) {
|
|
35
|
+
if (params.length === 2) {
|
|
42
36
|
token = params[0]
|
|
43
37
|
value = params[1]
|
|
44
|
-
store = params[2]
|
|
45
38
|
} else {
|
|
46
39
|
const family = params[0]
|
|
47
40
|
const key = params[1]
|
|
48
41
|
value = params[2]
|
|
49
|
-
|
|
50
|
-
const maybeToken =
|
|
51
|
-
store.config.lifespan === `ephemeral`
|
|
52
|
-
? findInStore(family, key, store)
|
|
53
|
-
: seekInStore(family, key, store)
|
|
54
|
-
if (!maybeToken) {
|
|
55
|
-
store.logger.error(
|
|
56
|
-
`❗`,
|
|
57
|
-
family.type,
|
|
58
|
-
family.key,
|
|
59
|
-
`tried to set member`,
|
|
60
|
-
stringifyJson(key),
|
|
61
|
-
`to`,
|
|
62
|
-
value,
|
|
63
|
-
`but it was not found in store`,
|
|
64
|
-
store.config.name,
|
|
65
|
-
)
|
|
66
|
-
return
|
|
67
|
-
}
|
|
42
|
+
const maybeToken = findInStore(store, family, key)
|
|
68
43
|
token = maybeToken
|
|
69
44
|
}
|
|
45
|
+
if (`counterfeit` in token) {
|
|
46
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
47
|
+
(item) => item?.key === token.key,
|
|
48
|
+
)
|
|
49
|
+
store.logger.error(
|
|
50
|
+
`❌`,
|
|
51
|
+
token.type,
|
|
52
|
+
token.key,
|
|
53
|
+
`could not be set because it was not found in the store "${store.config.name}".`,
|
|
54
|
+
disposal
|
|
55
|
+
? `This state was previously disposed:\n${disposal.trace}`
|
|
56
|
+
: `No previous disposal trace was found.`,
|
|
57
|
+
)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
70
60
|
|
|
71
61
|
const rejectionTime = openOperation(token, store)
|
|
72
62
|
if (rejectionTime) {
|
|
@@ -80,7 +70,7 @@ export function setIntoStore<T, New extends T>(
|
|
|
80
70
|
token.key,
|
|
81
71
|
`resuming deferred setState from T-${rejectionTime}`,
|
|
82
72
|
)
|
|
83
|
-
setIntoStore(token, value
|
|
73
|
+
setIntoStore(store, token, value)
|
|
84
74
|
},
|
|
85
75
|
)
|
|
86
76
|
return
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class CircularBuffer<T> {
|
|
2
|
+
protected _buffer: T[]
|
|
3
|
+
protected _index = 0
|
|
4
|
+
public constructor(array: T[])
|
|
5
|
+
public constructor(length: number)
|
|
6
|
+
public constructor(lengthOrArray: T[] | number) {
|
|
7
|
+
let length: number
|
|
8
|
+
if (typeof lengthOrArray === `number`) {
|
|
9
|
+
length = lengthOrArray
|
|
10
|
+
} else {
|
|
11
|
+
length = lengthOrArray.length
|
|
12
|
+
}
|
|
13
|
+
this._buffer = Array.from({ length })
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public get buffer(): ReadonlyArray<T | undefined> {
|
|
17
|
+
return this._buffer
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public get index(): number {
|
|
21
|
+
return this._index
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public add(item: T): void {
|
|
25
|
+
this._buffer[this._index] = item
|
|
26
|
+
this._index = (this._index + 1) % this._buffer.length
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public copy(): CircularBuffer<T> {
|
|
30
|
+
const copy = new CircularBuffer<T>([...this._buffer])
|
|
31
|
+
copy._index = this._index
|
|
32
|
+
return copy
|
|
33
|
+
}
|
|
34
|
+
}
|