atom.io 0.40.0 → 0.40.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js.map +1 -1
- package/dist/internal/index.d.ts +205 -196
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +145 -107
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +6 -6
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js.map +1 -1
- package/dist/main/index.d.ts +93 -66
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +16 -13
- package/dist/main/index.js.map +1 -1
- package/dist/react/index.d.ts +14 -14
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.js +1 -1
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +3 -3
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +3 -4
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +2 -2
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/data/struct.ts +2 -2
- package/src/internal/atom/create-regular-atom.ts +11 -9
- package/src/internal/atom/dispose-atom.ts +11 -8
- package/src/internal/atom/has-role.ts +1 -1
- package/src/internal/caching.ts +15 -15
- package/src/internal/events/ingest-creation-disposal.ts +1 -1
- package/src/internal/families/create-readonly-held-selector-family.ts +3 -4
- package/src/internal/families/create-readonly-pure-selector-family.ts +25 -23
- package/src/internal/families/create-regular-atom-family.ts +21 -15
- package/src/internal/families/create-selector-family.ts +15 -15
- package/src/internal/families/create-writable-held-selector-family.ts +2 -2
- package/src/internal/families/create-writable-pure-selector-family.ts +25 -21
- package/src/internal/families/dispose-from-store.ts +17 -7
- package/src/internal/families/find-in-store.ts +23 -23
- package/src/internal/families/get-family-of-token.ts +17 -17
- package/src/internal/families/mint-in-store.ts +10 -10
- package/src/internal/families/seek-in-store.ts +26 -26
- package/src/internal/get-state/get-fallback.ts +8 -8
- package/src/internal/get-state/get-from-store.ts +20 -8
- package/src/internal/get-state/read-or-compute-value.ts +78 -14
- package/src/internal/get-state/reduce-reference.ts +10 -10
- package/src/internal/index.ts +65 -60
- package/src/internal/install-into-store.ts +2 -1
- package/src/internal/join/create-join.ts +2 -2
- package/src/internal/join/find-relations-in-store.ts +2 -2
- package/src/internal/join/get-internal-relations-from-store.ts +2 -2
- package/src/internal/join/get-join.ts +5 -2
- package/src/internal/join/join-internal.ts +30 -26
- package/src/internal/lineage.ts +12 -1
- package/src/internal/molecule.ts +64 -36
- package/src/internal/mutable/create-mutable-atom-family.ts +5 -5
- package/src/internal/mutable/create-mutable-atom.ts +2 -2
- package/src/internal/mutable/get-json-family.ts +3 -2
- package/src/internal/mutable/get-update-family.ts +7 -5
- package/src/internal/mutable/tracker-family.ts +8 -4
- package/src/internal/mutable/tracker.ts +5 -1
- package/src/internal/operation.ts +4 -2
- package/src/internal/selector/create-readonly-held-selector.ts +2 -2
- package/src/internal/selector/create-readonly-pure-selector.ts +10 -8
- package/src/internal/selector/create-standalone-selector.ts +10 -10
- package/src/internal/selector/create-writable-held-selector.ts +2 -2
- package/src/internal/selector/create-writable-pure-selector.ts +11 -9
- package/src/internal/selector/dispose-selector.ts +2 -2
- package/src/internal/selector/register-selector.ts +2 -2
- package/src/internal/selector/trace-selector-atoms.ts +3 -3
- package/src/internal/selector/update-selector-atoms.ts +1 -1
- package/src/internal/set-state/become.ts +1 -3
- package/src/internal/set-state/dispatch-state-update.ts +10 -6
- package/src/internal/set-state/evict-downstream.ts +4 -1
- package/src/internal/set-state/operate-on-store.ts +16 -10
- package/src/internal/set-state/reset-atom-or-selector.ts +7 -7
- package/src/internal/set-state/reset-in-store.ts +17 -16
- package/src/internal/set-state/set-atom-or-selector.ts +1 -1
- package/src/internal/set-state/set-atom.ts +1 -1
- package/src/internal/set-state/set-into-store.ts +34 -7
- package/src/internal/set-state/set-selector.ts +1 -1
- package/src/internal/store/deposit.ts +38 -30
- package/src/internal/store/mint-or-counterfeit.ts +23 -23
- package/src/internal/store/store.ts +23 -21
- package/src/internal/store/withdraw.ts +68 -62
- package/src/internal/subscribe/recall-state.ts +4 -1
- package/src/internal/subscribe/subscribe-to-root-atoms.ts +2 -2
- package/src/internal/subscribe/subscribe-to-state.ts +4 -4
- package/src/internal/timeline/create-timeline.ts +11 -10
- package/src/internal/timeline/time-travel.ts +4 -3
- package/src/internal/transaction/abort-transaction.ts +3 -15
- package/src/internal/transaction/act-upon-store.ts +1 -5
- package/src/internal/transaction/apply-transaction.ts +3 -15
- package/src/internal/transaction/assign-transaction-to-continuity.ts +2 -7
- package/src/internal/transaction/build-transaction.ts +2 -3
- package/src/internal/transaction/create-transaction.ts +5 -6
- package/src/internal/transaction/get-epoch-number.ts +1 -7
- package/src/internal/transaction/set-epoch-number.ts +4 -12
- package/src/introspection/attach-atom-index.ts +2 -2
- package/src/introspection/attach-introspection-states.ts +4 -2
- package/src/introspection/attach-selector-index.ts +4 -2
- package/src/introspection/attach-timeline-family.ts +15 -13
- package/src/introspection/attach-timeline-index.ts +1 -1
- package/src/introspection/attach-transaction-index.ts +1 -1
- package/src/introspection/attach-transaction-logs.ts +6 -4
- package/src/introspection/attach-type-selectors.ts +4 -3
- package/src/introspection/index.ts +3 -5
- package/src/main/atom.ts +14 -8
- package/src/main/dispose-state.ts +1 -5
- package/src/main/events.ts +26 -26
- package/src/main/get-state.ts +10 -11
- package/src/main/realm.ts +36 -12
- package/src/main/reset-state.ts +5 -9
- package/src/main/selector.ts +40 -24
- package/src/main/set-state.ts +8 -11
- package/src/main/silo.ts +4 -3
- package/src/main/timeline.ts +5 -3
- package/src/main/tokens.ts +72 -44
- package/src/main/validators.ts +4 -4
- package/src/react/parse-state-overloads.ts +10 -10
- package/src/react/store-context.tsx +3 -3
- package/src/react/use-i.ts +6 -6
- package/src/react/use-loadable.ts +15 -15
- package/src/react/use-o.ts +9 -9
- package/src/react-devtools/Button.tsx +3 -2
- package/src/react-devtools/StateEditor.tsx +5 -3
- package/src/react-devtools/StateIndex.tsx +6 -4
- package/src/react-devtools/TimelineIndex.tsx +0 -2
- package/src/react-devtools/Updates.tsx +1 -1
- package/src/react-devtools/store.ts +18 -9
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +4 -8
- package/src/realtime-client/sync-continuity.ts +2 -2
- package/src/realtime-server/index.ts +2 -2
package/src/internal/lineage.ts
CHANGED
|
@@ -4,9 +4,20 @@ export interface Lineage {
|
|
|
4
4
|
child: typeof this | null
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function newest<T extends Lineage>(
|
|
7
|
+
export function newest<T extends Lineage>(
|
|
8
|
+
scion: T,
|
|
9
|
+
): Exclude<T[`child`], null> | T {
|
|
8
10
|
while (scion.child !== null) {
|
|
9
11
|
scion = scion.child
|
|
10
12
|
}
|
|
11
13
|
return scion
|
|
12
14
|
}
|
|
15
|
+
|
|
16
|
+
export function eldest<T extends Lineage>(
|
|
17
|
+
scion: T,
|
|
18
|
+
): Exclude<T[`parent`], T[`child`] | null> {
|
|
19
|
+
while (scion.parent !== null) {
|
|
20
|
+
scion = scion.parent
|
|
21
|
+
}
|
|
22
|
+
return scion as Exclude<T[`parent`], T[`child`] | null>
|
|
23
|
+
}
|
package/src/internal/molecule.ts
CHANGED
|
@@ -8,18 +8,20 @@ import type {
|
|
|
8
8
|
MoleculeDisposalEvent,
|
|
9
9
|
MoleculeTransferEvent,
|
|
10
10
|
SingularTypedKey,
|
|
11
|
+
TransactionToken,
|
|
11
12
|
Vassal,
|
|
12
13
|
} from "atom.io"
|
|
13
14
|
import type { Canonical, stringified } from "atom.io/json"
|
|
14
15
|
import { parseJson, stringifyJson } from "atom.io/json"
|
|
15
16
|
|
|
16
|
-
import { disposeFromStore
|
|
17
|
+
import { disposeFromStore } from "./families"
|
|
17
18
|
import { getFromStore } from "./get-state"
|
|
18
19
|
import { getTrace } from "./get-trace"
|
|
19
20
|
import { newest } from "./lineage"
|
|
20
21
|
import type { Store } from "./store"
|
|
21
22
|
import { IMPLICIT } from "./store"
|
|
22
|
-
import {
|
|
23
|
+
import type { RootStore } from "./transaction"
|
|
24
|
+
import { createTransaction, isChildStore } from "./transaction"
|
|
23
25
|
|
|
24
26
|
export type Molecule<K extends Canonical> = {
|
|
25
27
|
readonly key: K
|
|
@@ -135,23 +137,35 @@ export function fuseWithinStore<
|
|
|
135
137
|
return compoundKey
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
export function createDeallocateTX<
|
|
141
|
+
H extends Hierarchy,
|
|
142
|
+
V extends Exclude<Vassal<H>, CompoundTypedKey>,
|
|
143
|
+
>(store: RootStore): TransactionToken<(claim: Claim<V>) => void> {
|
|
144
|
+
return createTransaction(store, {
|
|
145
|
+
key: `[Internal] deallocate`,
|
|
146
|
+
do: (_, claim: Claim<V>): void => {
|
|
147
|
+
deallocateFromStore<H, V>(newest(store), claim)
|
|
148
|
+
},
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
138
152
|
export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
|
|
139
|
-
|
|
153
|
+
target: Store,
|
|
140
154
|
claim: Claim<V>,
|
|
141
155
|
): void {
|
|
142
156
|
const stringKey = stringifyJson(claim)
|
|
143
157
|
|
|
144
|
-
const molecule =
|
|
158
|
+
const molecule = target.molecules.get(stringKey)
|
|
145
159
|
if (!molecule) {
|
|
146
|
-
const disposal =
|
|
160
|
+
const disposal = target.disposalTraces.buffer.find(
|
|
147
161
|
(item) => item?.key === stringKey,
|
|
148
162
|
)
|
|
149
|
-
|
|
163
|
+
target.logger.error(
|
|
150
164
|
`❌`,
|
|
151
165
|
`key`,
|
|
152
166
|
claim,
|
|
153
167
|
`deallocation failed:`,
|
|
154
|
-
`Could not find allocation for ${stringKey} in store "${
|
|
168
|
+
`Could not find allocation for ${stringKey} in store "${target.config.name}".`,
|
|
155
169
|
disposal
|
|
156
170
|
? `\n This state was most recently deallocated\n${disposal.trace}`
|
|
157
171
|
: `No previous disposal trace for ${stringKey} was found.`,
|
|
@@ -159,45 +173,29 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
|
|
|
159
173
|
return
|
|
160
174
|
}
|
|
161
175
|
|
|
162
|
-
const joinKeys =
|
|
163
|
-
molecule.key as string /* 💥 RECONCILE */,
|
|
164
|
-
)
|
|
176
|
+
const joinKeys = target.moleculeJoins.getRelatedKeys(stringKey)
|
|
165
177
|
if (joinKeys) {
|
|
166
178
|
for (const joinKey of joinKeys) {
|
|
167
|
-
const join =
|
|
179
|
+
const join = target.joins.get(joinKey)
|
|
168
180
|
if (join) {
|
|
169
|
-
join.relations.delete(
|
|
170
|
-
join.molecules.delete(molecule.stringKey) // get rid of
|
|
181
|
+
join.relations.delete(claim)
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
}
|
|
174
|
-
|
|
185
|
+
target.moleculeJoins.delete(stringKey)
|
|
175
186
|
|
|
176
187
|
const provenance: stringified<Canonical>[] = []
|
|
177
188
|
|
|
178
189
|
const values: [string, any][] = []
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
values,
|
|
183
|
-
provenance,
|
|
184
|
-
timestamp: Date.now(),
|
|
185
|
-
}
|
|
186
|
-
const target = newest(store)
|
|
187
|
-
target.molecules.delete(stringKey)
|
|
188
|
-
const isTransaction =
|
|
189
|
-
isChildStore(target) && target.transactionMeta.phase === `building`
|
|
190
|
-
if (isTransaction) {
|
|
191
|
-
target.transactionMeta.update.subEvents.push(disposalEvent)
|
|
192
|
-
}
|
|
193
|
-
const relatedMolecules = store.moleculeGraph.getRelationEntries({
|
|
194
|
-
downstreamMoleculeKey: molecule.stringKey,
|
|
190
|
+
|
|
191
|
+
const relatedMolecules = target.moleculeGraph.getRelationEntries({
|
|
192
|
+
downstreamMoleculeKey: stringKey,
|
|
195
193
|
})
|
|
196
194
|
if (relatedMolecules) {
|
|
197
195
|
for (const [relatedStringKey, { source }] of relatedMolecules) {
|
|
198
|
-
if (source ===
|
|
196
|
+
if (source === stringKey) {
|
|
199
197
|
const relatedKey = parseJson(relatedStringKey)
|
|
200
|
-
deallocateFromStore<any, any>(
|
|
198
|
+
deallocateFromStore<any, any>(target, relatedKey)
|
|
201
199
|
} else {
|
|
202
200
|
provenance.push(source)
|
|
203
201
|
}
|
|
@@ -208,12 +206,24 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
|
|
|
208
206
|
for (const familyKey of familyKeys) {
|
|
209
207
|
// biome-ignore lint/style/noNonNullAssertion: tokens of molecules must have a family
|
|
210
208
|
const family = target.families.get(familyKey)!
|
|
211
|
-
const
|
|
212
|
-
const value = getFromStore(store, token)
|
|
209
|
+
const value = getFromStore(target, family, claim)
|
|
213
210
|
values.push([family.key, value])
|
|
214
|
-
disposeFromStore(
|
|
211
|
+
disposeFromStore(target, family, claim)
|
|
215
212
|
}
|
|
216
213
|
}
|
|
214
|
+
const disposalEvent: MoleculeDisposalEvent = {
|
|
215
|
+
type: `molecule_disposal`,
|
|
216
|
+
key: molecule.key,
|
|
217
|
+
values,
|
|
218
|
+
provenance,
|
|
219
|
+
timestamp: Date.now(),
|
|
220
|
+
}
|
|
221
|
+
target.molecules.delete(stringKey)
|
|
222
|
+
const isTransaction =
|
|
223
|
+
isChildStore(target) && target.transactionMeta.phase === `building`
|
|
224
|
+
if (isTransaction) {
|
|
225
|
+
target.transactionMeta.update.subEvents.push(disposalEvent)
|
|
226
|
+
}
|
|
217
227
|
|
|
218
228
|
target.moleculeGraph.delete(molecule.stringKey)
|
|
219
229
|
target.moleculeJoins.delete(molecule.stringKey)
|
|
@@ -225,8 +235,26 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
|
|
|
225
235
|
target.molecules.delete(molecule.stringKey)
|
|
226
236
|
|
|
227
237
|
const trace = getTrace(new Error())
|
|
228
|
-
|
|
238
|
+
target.disposalTraces.add({ key: stringKey, trace })
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function createClaimTX<
|
|
242
|
+
H extends Hierarchy,
|
|
243
|
+
V extends Exclude<Vassal<H>, CompoundTypedKey>,
|
|
244
|
+
A extends Above<V, H>,
|
|
245
|
+
>(
|
|
246
|
+
store: RootStore,
|
|
247
|
+
): TransactionToken<
|
|
248
|
+
(newProvenance: A, claim: Claim<V>, exclusive?: `exclusive`) => void
|
|
249
|
+
> {
|
|
250
|
+
return createTransaction(store, {
|
|
251
|
+
key: `[Internal] claim`,
|
|
252
|
+
do: (_, newProvenance, claim, exclusive) => {
|
|
253
|
+
claimWithinStore<H, V, A>(store, newProvenance, claim, exclusive)
|
|
254
|
+
},
|
|
255
|
+
})
|
|
229
256
|
}
|
|
257
|
+
|
|
230
258
|
export function claimWithinStore<
|
|
231
259
|
H extends Hierarchy,
|
|
232
260
|
V extends Exclude<Vassal<H>, CompoundTypedKey>,
|
|
@@ -10,10 +10,10 @@ import { PRETTY_TOKEN_TYPES } from "atom.io"
|
|
|
10
10
|
import type { Canonical } from "atom.io/json"
|
|
11
11
|
import { stringifyJson } from "atom.io/json"
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import type { MutableAtomFamily, RootStore } from ".."
|
|
14
|
+
import { createWritablePureSelectorFamily } from ".."
|
|
14
15
|
import { newest } from "../lineage"
|
|
15
16
|
import { createMutableAtom } from "../mutable"
|
|
16
|
-
import type { Store } from "../store"
|
|
17
17
|
import { Subject } from "../subject"
|
|
18
18
|
import { FamilyTracker } from "./tracker-family"
|
|
19
19
|
import type { AsJSON, Transceiver } from "./transceiver"
|
|
@@ -22,7 +22,7 @@ export function createMutableAtomFamily<
|
|
|
22
22
|
T extends Transceiver<any, any, any>,
|
|
23
23
|
K extends Canonical,
|
|
24
24
|
>(
|
|
25
|
-
store:
|
|
25
|
+
store: RootStore,
|
|
26
26
|
options: MutableAtomFamilyOptions<T, K>,
|
|
27
27
|
internalRoles?: string[],
|
|
28
28
|
): MutableAtomFamilyToken<T, K> {
|
|
@@ -67,13 +67,13 @@ export function createMutableAtomFamily<
|
|
|
67
67
|
const atomFamily = Object.assign(familyFunction, familyToken, {
|
|
68
68
|
class: options.class,
|
|
69
69
|
subject,
|
|
70
|
-
install: (s:
|
|
70
|
+
install: (s: RootStore) => createMutableAtomFamily(s, options),
|
|
71
71
|
internalRoles,
|
|
72
72
|
}) satisfies MutableAtomFamily<T, K>
|
|
73
73
|
|
|
74
74
|
store.families.set(options.key, atomFamily)
|
|
75
75
|
|
|
76
|
-
createWritablePureSelectorFamily<AsJSON<T>, K>(
|
|
76
|
+
createWritablePureSelectorFamily<AsJSON<T>, K, never>(
|
|
77
77
|
store,
|
|
78
78
|
{
|
|
79
79
|
key: `${options.key}:JSON`,
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
UpdateHandler,
|
|
6
6
|
} from "atom.io"
|
|
7
7
|
|
|
8
|
-
import type { MutableAtom } from ".."
|
|
8
|
+
import type { MutableAtom, RootStore } from ".."
|
|
9
9
|
import { createStandaloneSelector, resetInStore, setIntoStore } from ".."
|
|
10
10
|
import { newest } from "../lineage"
|
|
11
11
|
import { deposit, type Store } from "../store"
|
|
@@ -45,7 +45,7 @@ export function createMutableAtom<T extends Transceiver<any, any, any>>(
|
|
|
45
45
|
const newAtom: MutableAtom<T> = {
|
|
46
46
|
...options,
|
|
47
47
|
type,
|
|
48
|
-
install: (s:
|
|
48
|
+
install: (s: RootStore) => {
|
|
49
49
|
s.logger.info(`🛠️`, `atom`, key, `installing in store "${s.config.name}"`)
|
|
50
50
|
return createMutableAtom(s, options, family)
|
|
51
51
|
},
|
|
@@ -12,12 +12,13 @@ export const getJsonFamily = <
|
|
|
12
12
|
>(
|
|
13
13
|
mutableAtomFamily: MutableAtomFamilyToken<Core, Key>,
|
|
14
14
|
store: Store,
|
|
15
|
-
): WritablePureSelectorFamily<ReturnType<Core[`toJSON`]>, Key> => {
|
|
15
|
+
): WritablePureSelectorFamily<ReturnType<Core[`toJSON`]>, Key, never> => {
|
|
16
16
|
const target = newest(store)
|
|
17
17
|
const key = `${mutableAtomFamily.key}:JSON`
|
|
18
18
|
const jsonFamily = target.families.get(key) as WritablePureSelectorFamily<
|
|
19
19
|
ReturnType<Core[`toJSON`]>,
|
|
20
|
-
Key
|
|
20
|
+
Key,
|
|
21
|
+
never
|
|
21
22
|
>
|
|
22
23
|
return jsonFamily
|
|
23
24
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MutableAtomFamilyToken } from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { RegularAtomFamily } from ".."
|
|
5
5
|
import { newest } from "../lineage"
|
|
6
6
|
import type { Store } from "../store"
|
|
7
7
|
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
@@ -12,11 +12,13 @@ export const getUpdateFamily = <
|
|
|
12
12
|
>(
|
|
13
13
|
mutableAtomFamily: MutableAtomFamilyToken<T, K>,
|
|
14
14
|
store: Store,
|
|
15
|
-
):
|
|
15
|
+
): RegularAtomFamily<SignalFrom<T>, K, never> => {
|
|
16
16
|
const target = newest(store)
|
|
17
17
|
const key = `*${mutableAtomFamily.key}`
|
|
18
|
-
const updateFamily
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const updateFamily = target.families.get(key) as RegularAtomFamily<
|
|
19
|
+
SignalFrom<T>,
|
|
20
|
+
K,
|
|
21
|
+
never
|
|
22
|
+
>
|
|
21
23
|
return updateFamily
|
|
22
24
|
}
|
|
@@ -2,9 +2,9 @@ import type { MutableAtomToken, StateLifecycleEvent } from "atom.io"
|
|
|
2
2
|
import type { Canonical } from "atom.io/json"
|
|
3
3
|
import { parseJson } from "atom.io/json"
|
|
4
4
|
|
|
5
|
-
import type { MutableAtomFamily, RegularAtomFamily } from ".."
|
|
5
|
+
import type { MutableAtomFamily, RegularAtomFamily, RootStore } from ".."
|
|
6
6
|
import { createRegularAtomFamily } from "../families"
|
|
7
|
-
import {
|
|
7
|
+
import { withdraw } from "../store"
|
|
8
8
|
import { Tracker } from "./tracker"
|
|
9
9
|
import type { SignalFrom, Transceiver } from "./transceiver"
|
|
10
10
|
|
|
@@ -17,8 +17,12 @@ export class FamilyTracker<
|
|
|
17
17
|
public readonly latestSignalAtoms: RegularAtomFamily<SignalFrom<T> | null, K>
|
|
18
18
|
public readonly mutableAtoms: MutableAtomFamily<T, K>
|
|
19
19
|
|
|
20
|
-
public constructor(mutableAtoms: MutableAtomFamily<T, K>, store:
|
|
21
|
-
const latestSignalAtoms = createRegularAtomFamily<
|
|
20
|
+
public constructor(mutableAtoms: MutableAtomFamily<T, K>, store: RootStore) {
|
|
21
|
+
const latestSignalAtoms = createRegularAtomFamily<
|
|
22
|
+
SignalFrom<T> | null,
|
|
23
|
+
K,
|
|
24
|
+
never
|
|
25
|
+
>(
|
|
22
26
|
store,
|
|
23
27
|
{
|
|
24
28
|
key: `*${mutableAtoms.key}`,
|
|
@@ -31,7 +31,11 @@ export class Tracker<T extends Transceiver<any, any, any>> {
|
|
|
31
31
|
subKey: mutableState.family.subKey,
|
|
32
32
|
}
|
|
33
33
|
: undefined
|
|
34
|
-
const latestSignalState = createRegularAtom<
|
|
34
|
+
const latestSignalState = createRegularAtom<
|
|
35
|
+
SignalFrom<T> | null,
|
|
36
|
+
any,
|
|
37
|
+
never
|
|
38
|
+
>(
|
|
35
39
|
store,
|
|
36
40
|
{
|
|
37
41
|
key: latestSignalStateKey,
|
|
@@ -8,7 +8,9 @@ export type OperationProgress =
|
|
|
8
8
|
| {
|
|
9
9
|
open: false
|
|
10
10
|
}
|
|
11
|
-
export type OpenOperation<
|
|
11
|
+
export type OpenOperation<
|
|
12
|
+
R extends ReadableToken<any, any> = ReadableToken<any, any>,
|
|
13
|
+
> = {
|
|
12
14
|
open: true
|
|
13
15
|
token: R
|
|
14
16
|
done: Set<string>
|
|
@@ -19,7 +21,7 @@ export type OpenOperation<R extends ReadableToken<any> = ReadableToken<any>> = {
|
|
|
19
21
|
|
|
20
22
|
export function openOperation(
|
|
21
23
|
store: Store,
|
|
22
|
-
token: ReadableToken<any>,
|
|
24
|
+
token: ReadableToken<any, any, any>,
|
|
23
25
|
): number | (Store & { operation: OpenOperation }) {
|
|
24
26
|
if (store.operation.open) {
|
|
25
27
|
const rejectionTime = performance.now()
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
ReadonlyHeldSelectorToken,
|
|
5
5
|
} from "atom.io"
|
|
6
6
|
|
|
7
|
-
import type { ReadonlyHeldSelector } from ".."
|
|
7
|
+
import type { ReadonlyHeldSelector, RootStore } from ".."
|
|
8
8
|
import { writeToCache } from "../caching"
|
|
9
9
|
import { newest } from "../lineage"
|
|
10
10
|
import type { Store } from "../store"
|
|
@@ -47,7 +47,7 @@ export function createReadonlyHeldSelector<T extends object>(
|
|
|
47
47
|
type,
|
|
48
48
|
subject,
|
|
49
49
|
getFrom,
|
|
50
|
-
install: (s:
|
|
50
|
+
install: (s: RootStore) => createReadonlyHeldSelector(s, options, family),
|
|
51
51
|
}
|
|
52
52
|
if (family) readonlySelector.family = family
|
|
53
53
|
|
|
@@ -2,22 +2,24 @@ import type {
|
|
|
2
2
|
FamilyMetadata,
|
|
3
3
|
ReadonlyPureSelectorOptions,
|
|
4
4
|
ReadonlyPureSelectorToken,
|
|
5
|
+
StateUpdate,
|
|
5
6
|
} from "atom.io"
|
|
7
|
+
import type { Canonical } from "atom.io/json"
|
|
6
8
|
|
|
7
|
-
import type { ReadonlyPureSelector } from ".."
|
|
9
|
+
import type { ReadonlyPureSelector, RootStore } from ".."
|
|
8
10
|
import { writeToCache } from "../caching"
|
|
9
11
|
import { newest } from "../lineage"
|
|
10
12
|
import type { Store } from "../store"
|
|
11
13
|
import { Subject } from "../subject"
|
|
12
14
|
import { registerSelector } from "./register-selector"
|
|
13
15
|
|
|
14
|
-
export function createReadonlyPureSelector<T>(
|
|
16
|
+
export function createReadonlyPureSelector<T, K extends Canonical, E>(
|
|
15
17
|
store: Store,
|
|
16
|
-
options: ReadonlyPureSelectorOptions<T>,
|
|
17
|
-
family: FamilyMetadata | undefined,
|
|
18
|
-
): ReadonlyPureSelectorToken<T> {
|
|
18
|
+
options: ReadonlyPureSelectorOptions<T, E>,
|
|
19
|
+
family: FamilyMetadata<K> | undefined,
|
|
20
|
+
): ReadonlyPureSelectorToken<T, K, E> {
|
|
19
21
|
const target = newest(store)
|
|
20
|
-
const subject = new Subject<
|
|
22
|
+
const subject = new Subject<StateUpdate<E | T>>()
|
|
21
23
|
const covered = new Set<string>()
|
|
22
24
|
const key = options.key
|
|
23
25
|
const type = `readonly_pure_selector` as const
|
|
@@ -43,12 +45,12 @@ export function createReadonlyPureSelector<T>(
|
|
|
43
45
|
return cached
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
const readonlySelector: ReadonlyPureSelector<T> = {
|
|
48
|
+
const readonlySelector: ReadonlyPureSelector<T, E> = {
|
|
47
49
|
...options,
|
|
48
50
|
type,
|
|
49
51
|
subject,
|
|
50
52
|
getFrom,
|
|
51
|
-
install: (s:
|
|
53
|
+
install: (s: RootStore) => createReadonlyPureSelector(s, options, family),
|
|
52
54
|
}
|
|
53
55
|
if (family) readonlySelector.family = family
|
|
54
56
|
|
|
@@ -23,26 +23,26 @@ export function createStandaloneSelector<T extends object>(
|
|
|
23
23
|
store: Store,
|
|
24
24
|
options: ReadonlyHeldSelectorOptions<T>,
|
|
25
25
|
): ReadonlyHeldSelectorToken<T>
|
|
26
|
-
export function createStandaloneSelector<T>(
|
|
26
|
+
export function createStandaloneSelector<T, E>(
|
|
27
27
|
store: Store,
|
|
28
|
-
options: WritablePureSelectorOptions<T>,
|
|
29
|
-
): WritablePureSelectorToken<T>
|
|
30
|
-
export function createStandaloneSelector<T>(
|
|
28
|
+
options: WritablePureSelectorOptions<T, E>,
|
|
29
|
+
): WritablePureSelectorToken<T, any, E>
|
|
30
|
+
export function createStandaloneSelector<T, E>(
|
|
31
31
|
store: Store,
|
|
32
|
-
options: ReadonlyPureSelectorOptions<T>,
|
|
33
|
-
): ReadonlyPureSelectorToken<T>
|
|
32
|
+
options: ReadonlyPureSelectorOptions<T, E>,
|
|
33
|
+
): ReadonlyPureSelectorToken<T, any, E>
|
|
34
34
|
export function createStandaloneSelector(
|
|
35
35
|
store: Store,
|
|
36
36
|
options:
|
|
37
37
|
| ReadonlyHeldSelectorOptions<any>
|
|
38
|
-
| ReadonlyPureSelectorOptions<any>
|
|
38
|
+
| ReadonlyPureSelectorOptions<any, any>
|
|
39
39
|
| WritableHeldSelectorOptions<any>
|
|
40
|
-
| WritablePureSelectorOptions<any>,
|
|
40
|
+
| WritablePureSelectorOptions<any, any>,
|
|
41
41
|
):
|
|
42
42
|
| ReadonlyHeldSelectorToken<any>
|
|
43
|
-
| ReadonlyPureSelectorToken<any>
|
|
43
|
+
| ReadonlyPureSelectorToken<any, any, any>
|
|
44
44
|
| WritableHeldSelectorToken<any>
|
|
45
|
-
| WritablePureSelectorToken<any> {
|
|
45
|
+
| WritablePureSelectorToken<any, any, any> {
|
|
46
46
|
const isWritable = `set` in options
|
|
47
47
|
const isHeld = `const` in options
|
|
48
48
|
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
WritableHeldSelectorToken,
|
|
5
5
|
} from "atom.io"
|
|
6
6
|
|
|
7
|
-
import type { WritableHeldSelector } from ".."
|
|
7
|
+
import type { RootStore, WritableHeldSelector } from ".."
|
|
8
8
|
import { writeToCache } from "../caching"
|
|
9
9
|
import { newest } from "../lineage"
|
|
10
10
|
import type { Store } from "../store"
|
|
@@ -54,7 +54,7 @@ export function createWritableHeldSelector<T extends object>(
|
|
|
54
54
|
subject,
|
|
55
55
|
getFrom,
|
|
56
56
|
setSelf,
|
|
57
|
-
install: (s:
|
|
57
|
+
install: (s: RootStore) => createWritableHeldSelector(s, options, family),
|
|
58
58
|
}
|
|
59
59
|
if (family) mySelector.family = family
|
|
60
60
|
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
FamilyMetadata,
|
|
3
|
+
StateUpdate,
|
|
3
4
|
WritablePureSelectorOptions,
|
|
4
5
|
WritablePureSelectorToken,
|
|
5
6
|
} from "atom.io"
|
|
7
|
+
import type { Canonical } from "atom.io/json"
|
|
6
8
|
|
|
7
|
-
import type { WritablePureSelector } from ".."
|
|
9
|
+
import type { RootStore, WritablePureSelector } from ".."
|
|
8
10
|
import { writeToCache } from "../caching"
|
|
9
11
|
import { newest } from "../lineage"
|
|
10
12
|
import type { Store } from "../store"
|
|
11
13
|
import { Subject } from "../subject"
|
|
12
14
|
import { registerSelector } from "./register-selector"
|
|
13
15
|
|
|
14
|
-
export function createWritablePureSelector<T>(
|
|
16
|
+
export function createWritablePureSelector<T, K extends Canonical, E>(
|
|
15
17
|
store: Store,
|
|
16
|
-
options: WritablePureSelectorOptions<T>,
|
|
17
|
-
family: FamilyMetadata | undefined,
|
|
18
|
-
): WritablePureSelectorToken<T> {
|
|
18
|
+
options: WritablePureSelectorOptions<T, E>,
|
|
19
|
+
family: FamilyMetadata<K> | undefined,
|
|
20
|
+
): WritablePureSelectorToken<T, K, E> {
|
|
19
21
|
const target = newest(store)
|
|
20
|
-
const subject = new Subject<
|
|
22
|
+
const subject = new Subject<StateUpdate<E | T>>()
|
|
21
23
|
const covered = new Set<string>()
|
|
22
24
|
const key = options.key
|
|
23
25
|
const type = `writable_pure_selector` as const
|
|
@@ -27,7 +29,7 @@ export function createWritablePureSelector<T>(
|
|
|
27
29
|
const { find, get, json } = setterToolkit
|
|
28
30
|
const getterToolkit = { find, get, json }
|
|
29
31
|
|
|
30
|
-
const getFrom = (innerTarget: Store): T => {
|
|
32
|
+
const getFrom = (innerTarget: Store): E | T => {
|
|
31
33
|
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({
|
|
32
34
|
downstreamSelectorKey: key,
|
|
33
35
|
})
|
|
@@ -48,13 +50,13 @@ export function createWritablePureSelector<T>(
|
|
|
48
50
|
options.set(setterToolkit, newValue)
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
const mySelector: WritablePureSelector<T> = {
|
|
53
|
+
const mySelector: WritablePureSelector<T, E> = {
|
|
52
54
|
...options,
|
|
53
55
|
type,
|
|
54
56
|
subject,
|
|
55
57
|
getFrom,
|
|
56
58
|
setSelf,
|
|
57
|
-
install: (s:
|
|
59
|
+
install: (s: RootStore) => createWritablePureSelector(s, options, family),
|
|
58
60
|
}
|
|
59
61
|
if (family) mySelector.family = family
|
|
60
62
|
|
|
@@ -5,7 +5,7 @@ import { isChildStore, newest, withdraw } from ".."
|
|
|
5
5
|
|
|
6
6
|
export function disposeSelector(
|
|
7
7
|
store: Store,
|
|
8
|
-
selectorToken: SelectorToken<unknown>,
|
|
8
|
+
selectorToken: SelectorToken<unknown, any, any>,
|
|
9
9
|
): void {
|
|
10
10
|
const target = newest(store)
|
|
11
11
|
const { key, type, family: familyMeta } = selectorToken
|
|
@@ -21,7 +21,7 @@ export function disposeSelector(
|
|
|
21
21
|
if (molecule) {
|
|
22
22
|
target.moleculeData.delete(familyMeta.subKey, familyMeta.key)
|
|
23
23
|
}
|
|
24
|
-
let familyToken: SelectorFamilyToken<any, any>
|
|
24
|
+
let familyToken: SelectorFamilyToken<any, any, any>
|
|
25
25
|
switch (selectorToken.type) {
|
|
26
26
|
case `writable_held_selector`:
|
|
27
27
|
{
|
|
@@ -33,8 +33,8 @@ export function registerSelector(
|
|
|
33
33
|
return {
|
|
34
34
|
get: (
|
|
35
35
|
...params:
|
|
36
|
-
| [ReadableFamilyToken<any, any>, Canonical]
|
|
37
|
-
| [ReadableToken<any>]
|
|
36
|
+
| [ReadableFamilyToken<any, any, any>, Canonical]
|
|
37
|
+
| [ReadableToken<any, any, any>]
|
|
38
38
|
) => {
|
|
39
39
|
const target = newest(store)
|
|
40
40
|
const { token, family, subKey } = reduceReference(store, ...params)
|
|
@@ -6,10 +6,10 @@ export function traceRootSelectorAtoms(
|
|
|
6
6
|
store: Store,
|
|
7
7
|
selectorKey: string,
|
|
8
8
|
covered: Set<string> = new Set<string>(),
|
|
9
|
-
): Map<string, Atom<
|
|
9
|
+
): Map<string, Atom<any, any>> {
|
|
10
10
|
const dependencies = getSelectorDependencyKeys(store, selectorKey)
|
|
11
11
|
|
|
12
|
-
const roots = new Map<string, Atom<unknown>>()
|
|
12
|
+
const roots = new Map<string, Atom<unknown, unknown>>()
|
|
13
13
|
|
|
14
14
|
while (dependencies.length > 0) {
|
|
15
15
|
// biome-ignore lint/style/noNonNullAssertion: just checked length ^^^
|
|
@@ -19,7 +19,7 @@ export function traceRootSelectorAtoms(
|
|
|
19
19
|
}
|
|
20
20
|
covered.add(dependencyKey)
|
|
21
21
|
if (isAtomKey(store, dependencyKey)) {
|
|
22
|
-
const atom = store.atoms.get(dependencyKey) as Atom<unknown>
|
|
22
|
+
const atom = store.atoms.get(dependencyKey) as Atom<unknown, unknown>
|
|
23
23
|
roots.set(atom.key, atom)
|
|
24
24
|
} else {
|
|
25
25
|
dependencies.push(...getSelectorDependencyKeys(store, dependencyKey))
|
|
@@ -12,7 +12,7 @@ export function updateSelectorAtoms(
|
|
|
12
12
|
| `writable_held_selector`
|
|
13
13
|
| `writable_pure_selector`,
|
|
14
14
|
selectorKey: string,
|
|
15
|
-
dependency: ReadableToken<unknown>,
|
|
15
|
+
dependency: ReadableToken<unknown, any, unknown>,
|
|
16
16
|
covered: Set<string>,
|
|
17
17
|
): void {
|
|
18
18
|
const target = newest(store)
|
|
@@ -17,18 +17,18 @@ import { isChildStore, isRootStore } from "../transaction"
|
|
|
17
17
|
import { evictDownstreamFromAtom } from "./evict-downstream"
|
|
18
18
|
import type { ProtoUpdate } from "./operate-on-store"
|
|
19
19
|
|
|
20
|
-
export function dispatchOrDeferStateUpdate<T>(
|
|
20
|
+
export function dispatchOrDeferStateUpdate<T, E>(
|
|
21
21
|
target: Store & { operation: OpenOperation<any> },
|
|
22
|
-
state: WritableState<T>,
|
|
23
|
-
{ oldValue, newValue }: ProtoUpdate<T>,
|
|
22
|
+
state: WritableState<T, E>,
|
|
23
|
+
{ oldValue, newValue }: ProtoUpdate<E | T>,
|
|
24
24
|
stateIsNewlyCreated: boolean,
|
|
25
|
-
family?: WritableFamily<T, any>,
|
|
25
|
+
family?: WritableFamily<T, any, E>,
|
|
26
26
|
): void {
|
|
27
27
|
const token = deposit(state)
|
|
28
28
|
if (stateIsNewlyCreated && family) {
|
|
29
29
|
state.subject.next({ newValue })
|
|
30
30
|
const stateCreationEvent: StateCreationEvent<any> & TimelineEvent<any> = {
|
|
31
|
-
|
|
31
|
+
checkpoint: true,
|
|
32
32
|
type: `state_creation`,
|
|
33
33
|
subType: `writable`,
|
|
34
34
|
token,
|
|
@@ -128,7 +128,11 @@ export function dispatchOrDeferStateUpdate<T>(
|
|
|
128
128
|
const mutable = target.atoms.get(keyOfMutable) as MutableAtom<
|
|
129
129
|
Transceiver<unknown, any, any>
|
|
130
130
|
>
|
|
131
|
-
const transceiver = readOrComputeValue
|
|
131
|
+
const transceiver = readOrComputeValue<Transceiver<any, any, any>, never>(
|
|
132
|
+
target,
|
|
133
|
+
mutable,
|
|
134
|
+
`mut`,
|
|
135
|
+
)
|
|
132
136
|
const accepted = transceiver.do(update.newValue) === null
|
|
133
137
|
if (accepted === true) {
|
|
134
138
|
evictDownstreamFromAtom(target, mutable)
|
|
@@ -4,7 +4,10 @@ import { newest } from "../lineage"
|
|
|
4
4
|
import { isDone, markDone } from "../operation"
|
|
5
5
|
import type { Store } from "../store"
|
|
6
6
|
|
|
7
|
-
export function evictDownstreamFromAtom(
|
|
7
|
+
export function evictDownstreamFromAtom(
|
|
8
|
+
store: Store,
|
|
9
|
+
atom: Atom<any, any>,
|
|
10
|
+
): void {
|
|
8
11
|
const target = newest(store)
|
|
9
12
|
const { key, type } = atom
|
|
10
13
|
const downstreamKeys = target.selectorAtoms.getRelatedKeys(key)
|