atom.io 0.30.7 → 0.31.1
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 +20 -18
- package/data/dist/index.js +104 -172
- package/data/src/join.ts +138 -210
- package/dist/{chunk-UDHCFTYT.js → chunk-Y5MBNTVU.js} +582 -762
- package/dist/index.d.ts +254 -173
- package/dist/index.js +91 -14
- package/ephemeral/dist/index.d.ts +35 -25
- package/ephemeral/src/find-state.ts +35 -25
- package/eslint-plugin/dist/index.d.ts +22 -3
- package/eslint-plugin/dist/index.js +7 -7
- package/immortal/dist/index.d.ts +1 -2
- package/immortal/dist/index.js +0 -3
- package/immortal/src/seek-state.ts +2 -14
- package/internal/dist/index.d.ts +57 -88
- package/internal/dist/index.js +1 -2
- package/internal/src/atom/dispose-atom.ts +31 -15
- package/internal/src/families/dispose-from-store.ts +15 -44
- package/internal/src/families/find-in-store.ts +9 -7
- package/internal/src/families/init-family-member.ts +1 -1
- package/internal/src/families/seek-in-store.ts +2 -14
- package/internal/src/get-state/get-from-store.ts +13 -79
- package/internal/src/get-trace.ts +7 -0
- package/internal/src/index.ts +17 -8
- package/internal/src/ingest-updates/ingest-creation-disposal.ts +65 -73
- package/internal/src/ingest-updates/ingest-transaction-update.ts +4 -0
- package/internal/src/install-into-store.ts +48 -0
- package/internal/src/junction.ts +52 -12
- package/internal/src/lineage.ts +0 -7
- package/internal/src/molecule.ts +306 -0
- package/internal/src/mutable/transceiver.ts +5 -5
- package/internal/src/not-found-error.ts +8 -30
- package/internal/src/pretty-print.ts +1 -16
- package/internal/src/selector/dispose-selector.ts +3 -5
- package/internal/src/selector/register-selector.ts +3 -34
- package/internal/src/set-state/set-into-store.ts +3 -2
- package/internal/src/store/counterfeit.ts +11 -25
- package/internal/src/store/deposit.ts +10 -42
- package/internal/src/store/store.ts +51 -12
- package/internal/src/store/withdraw.ts +18 -60
- package/internal/src/timeline/create-timeline.ts +133 -237
- package/internal/src/timeline/time-travel.ts +1 -8
- package/internal/src/transaction/build-transaction.ts +10 -5
- package/internal/src/transaction/index.ts +1 -1
- package/internal/src/utility-types.ts +2 -0
- package/introspection/dist/index.d.ts +2 -3
- package/introspection/dist/index.js +9 -9
- package/introspection/src/refinery.ts +1 -3
- package/json/dist/index.js +8 -40
- package/json/src/index.ts +2 -0
- package/json/src/select-json-family.ts +7 -44
- package/package.json +33 -28
- package/react/dist/index.js +2 -10
- package/react/src/parse-state-overloads.ts +3 -11
- package/react-devtools/dist/index.js +13 -13
- package/react-devtools/src/Updates.tsx +2 -0
- package/realtime-client/dist/index.d.ts +20 -12
- package/realtime-client/dist/index.js +241 -244
- package/realtime-client/src/continuity/index.ts +3 -0
- package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +231 -0
- package/realtime-client/src/continuity/use-conceal-state.ts +11 -0
- package/realtime-client/src/continuity/use-reveal-state.ts +19 -0
- package/realtime-client/src/index.ts +1 -0
- package/realtime-client/src/sync-continuity.ts +18 -262
- package/realtime-react/dist/index.js +2 -2
- package/realtime-server/dist/index.d.ts +1 -1
- package/realtime-server/dist/index.js +2 -2
- package/realtime-server/src/index.ts +1 -1
- package/realtime-server/src/ipc-sockets/child-socket.ts +0 -1
- package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +1 -1
- package/realtime-testing/dist/index.js +5 -7
- package/realtime-testing/src/setup-realtime-test.tsx +5 -6
- package/src/atom.ts +53 -29
- package/src/dispose-state.ts +17 -23
- package/src/get-state.ts +19 -21
- package/src/index.ts +73 -3
- package/src/realm.ts +169 -0
- package/src/selector.ts +20 -0
- package/src/set-state.ts +16 -8
- package/src/silo.ts +9 -14
- package/src/timeline.ts +2 -3
- package/src/transaction.ts +25 -38
- package/transceivers/set-rtx/dist/index.js +4 -1
- package/transceivers/set-rtx/src/set-rtx.ts +4 -1
- package/dist/chunk-ADMEAXYU.js +0 -167
- package/internal/src/molecule/create-molecule-family.ts +0 -30
- package/internal/src/molecule/dispose-molecule.ts +0 -79
- package/internal/src/molecule/grow-molecule-in-store.ts +0 -95
- package/internal/src/molecule/index.ts +0 -5
- package/internal/src/molecule/make-molecule-in-store.ts +0 -191
- package/internal/src/molecule/molecule-internal.ts +0 -52
- package/src/allocate.ts +0 -277
- package/src/molecule.ts +0 -138
|
@@ -3,7 +3,6 @@ import * as http from "node:http"
|
|
|
3
3
|
import type { RenderResult } from "@testing-library/react"
|
|
4
4
|
import { prettyDOM, render } from "@testing-library/react"
|
|
5
5
|
import * as AtomIO from "atom.io"
|
|
6
|
-
import { realm } from "atom.io"
|
|
7
6
|
import { editRelationsInStore, findRelationsInStore } from "atom.io/data"
|
|
8
7
|
import type { Store } from "atom.io/internal"
|
|
9
8
|
import {
|
|
@@ -105,7 +104,7 @@ export const setupRealtimeTestServer = (
|
|
|
105
104
|
},
|
|
106
105
|
IMPLICIT.STORE,
|
|
107
106
|
)
|
|
108
|
-
const socketRealm =
|
|
107
|
+
const socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)
|
|
109
108
|
|
|
110
109
|
const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
|
|
111
110
|
const address = httpServer.listen(options.port).address()
|
|
@@ -131,7 +130,7 @@ export const setupRealtimeTestServer = (
|
|
|
131
130
|
setIntoStore(silo.store, RTS.socketIndex, (index) =>
|
|
132
131
|
index.add(socketClaim),
|
|
133
132
|
)
|
|
134
|
-
console.log(`${username} connected on ${socket.id}`)
|
|
133
|
+
// console.log(`${username} connected on ${socket.id}`)
|
|
135
134
|
next()
|
|
136
135
|
} else {
|
|
137
136
|
next(new Error(`Authentication error`))
|
|
@@ -154,11 +153,11 @@ export const setupRealtimeTestServer = (
|
|
|
154
153
|
socket.onAnyOutgoing((event, ...args) => {
|
|
155
154
|
console.log(`🛰 >>`, userKey, event, ...args)
|
|
156
155
|
})
|
|
156
|
+
socket.on(`disconnect`, () => {
|
|
157
|
+
console.log(`${userKey} disconnected`)
|
|
158
|
+
})
|
|
157
159
|
}
|
|
158
160
|
options.server({ socket, enableLogging, silo })
|
|
159
|
-
socket.on(`disconnect`, () => {
|
|
160
|
-
console.log(`${userKey} disconnected`)
|
|
161
|
-
})
|
|
162
161
|
})
|
|
163
162
|
|
|
164
163
|
const dispose = async () => {
|
package/src/atom.ts
CHANGED
|
@@ -6,59 +6,83 @@ import {
|
|
|
6
6
|
} from "atom.io/internal"
|
|
7
7
|
import type { Canonical, Json, JsonInterface } from "atom.io/json"
|
|
8
8
|
|
|
9
|
-
import type { AtomToken, MutableAtomToken, RegularAtomToken } from "."
|
|
10
|
-
|
|
11
|
-
export type Effectors<T> = {
|
|
12
|
-
setSelf: <V extends T>(next: V | ((oldValue: T) => V)) => void
|
|
13
|
-
onSet: (callback: (options: { newValue: T; oldValue: T }) => void) => void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type AtomEffect<T> = (tools: Effectors<T>) => (() => void) | void
|
|
17
|
-
|
|
18
|
-
export type RegularAtomOptions<T> = {
|
|
19
|
-
key: string
|
|
20
|
-
default: T | (() => T)
|
|
21
|
-
effects?: AtomEffect<T>[]
|
|
22
|
-
}
|
|
23
|
-
// biome-ignore format: complex intersection
|
|
24
|
-
export type MutableAtomOptions<T extends Transceiver<any>, J extends Json.Serializable> =
|
|
25
|
-
& JsonInterface<T, J>
|
|
26
|
-
& Omit<RegularAtomOptions<T>, `default`>
|
|
27
|
-
& {
|
|
28
|
-
default: () => T
|
|
29
|
-
mutable: true
|
|
30
|
-
}
|
|
9
|
+
import type { AtomToken, MutableAtomToken, RegularAtomToken, Setter } from "."
|
|
31
10
|
|
|
32
11
|
/**
|
|
33
12
|
* @public
|
|
34
|
-
*
|
|
35
|
-
*
|
|
13
|
+
* Create a mutable atom, a global reactive variable in the implicit store
|
|
14
|
+
*
|
|
15
|
+
* The value of a mutable atom must be some kind of {@link Transceiver}.
|
|
16
|
+
*
|
|
17
|
+
* @param options - {@link MutableAtomOptions}.
|
|
36
18
|
* @returns
|
|
37
|
-
*
|
|
19
|
+
* A reference to the atom created: a {@link MutableAtomToken}
|
|
38
20
|
* @overload Mutable
|
|
39
21
|
*/
|
|
40
22
|
export function atom<T extends Transceiver<any>, J extends Json.Serializable>(
|
|
41
23
|
options: MutableAtomOptions<T, J>,
|
|
42
24
|
): MutableAtomToken<T, J>
|
|
25
|
+
|
|
43
26
|
/**
|
|
44
27
|
* @public
|
|
45
|
-
*
|
|
46
|
-
* @param options -
|
|
28
|
+
* Create a regular atom, a global reactive variable in the implicit store
|
|
29
|
+
* @param options - {@link RegularAtomOptions}.
|
|
47
30
|
* @returns
|
|
48
|
-
*
|
|
31
|
+
* A reference to the atom created: a {@link RegularAtomToken}
|
|
49
32
|
* @overload Regular
|
|
50
33
|
*/
|
|
51
34
|
export function atom<T>(options: RegularAtomOptions<T>): RegularAtomToken<T>
|
|
52
|
-
|
|
53
35
|
export function atom(
|
|
54
36
|
options: MutableAtomOptions<any, any> | RegularAtomOptions<any>,
|
|
55
37
|
): AtomToken<any> {
|
|
56
38
|
return createStandaloneAtom(IMPLICIT.STORE, options)
|
|
57
39
|
}
|
|
58
40
|
|
|
41
|
+
/** @public */
|
|
42
|
+
export type Effectors<T> = {
|
|
43
|
+
/**
|
|
44
|
+
* Set the value of the atom
|
|
45
|
+
* @param next - The new value of the atom, or a setter function
|
|
46
|
+
*/
|
|
47
|
+
setSelf: <New extends T>(next: New | Setter<T, New>) => void
|
|
48
|
+
/** Subscribe to changes to the atom */
|
|
49
|
+
onSet: (callback: (options: { newValue: T; oldValue: T }) => void) => void
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @public
|
|
54
|
+
* A function that runs side effects when the atom is set
|
|
55
|
+
* @param tools - {@link Effectors} that can be used to run side effects
|
|
56
|
+
* @returns
|
|
57
|
+
* Optionally, a cleanup function that will be called when the atom is disposed
|
|
58
|
+
*/
|
|
59
|
+
export type AtomEffect<T> = (tools: Effectors<T>) => (() => void) | void
|
|
60
|
+
|
|
61
|
+
/** @public */
|
|
62
|
+
export type RegularAtomOptions<T> = {
|
|
63
|
+
/** The unique identifier of the atom */
|
|
64
|
+
key: string
|
|
65
|
+
/** The starting value of the atom */
|
|
66
|
+
default: T | (() => T)
|
|
67
|
+
/** Hooks used to run side effects when the atom is set */
|
|
68
|
+
effects?: AtomEffect<T>[]
|
|
69
|
+
}
|
|
70
|
+
// biome-ignore format: complex intersection
|
|
71
|
+
export type MutableAtomOptions<T extends Transceiver<any>, J extends Json.Serializable> =
|
|
72
|
+
& JsonInterface<T, J>
|
|
73
|
+
& Omit<RegularAtomOptions<T>, `default`>
|
|
74
|
+
& {
|
|
75
|
+
default: () => T
|
|
76
|
+
mutable: true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @public */
|
|
59
80
|
export type RegularAtomFamilyOptions<T, K extends Canonical> = {
|
|
81
|
+
/** The unique identifier of the atom family */
|
|
60
82
|
key: string
|
|
83
|
+
/** The starting value of the atom family */
|
|
61
84
|
default: T | ((key: K) => T)
|
|
85
|
+
/** Hooks used to run side effects when an atom in the family is set */
|
|
62
86
|
effects?: (key: K) => AtomEffect<T>[]
|
|
63
87
|
}
|
|
64
88
|
|
package/src/dispose-state.ts
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
import * as Internal from "atom.io/internal"
|
|
2
|
-
import type { Canonical
|
|
2
|
+
import type { Canonical } from "atom.io/json"
|
|
3
3
|
|
|
4
4
|
import type { ReadableFamilyToken, ReadableToken } from "."
|
|
5
|
-
import type {
|
|
6
|
-
MoleculeConstructor,
|
|
7
|
-
MoleculeFamilyToken,
|
|
8
|
-
MoleculeKey,
|
|
9
|
-
MoleculeToken,
|
|
10
|
-
} from "./molecule"
|
|
11
|
-
|
|
12
|
-
export function disposeState(
|
|
13
|
-
token: MoleculeToken<any> | ReadableToken<any>,
|
|
14
|
-
): void
|
|
15
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
* Disposes of a state in the implicit store
|
|
9
|
+
* @param token - The token of the state to dispose
|
|
10
|
+
* @overload Default
|
|
11
|
+
*/
|
|
12
|
+
export function disposeState(token: ReadableToken<any>): void
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
* Disposes of a state family in the implicit store
|
|
16
|
+
* @param token - The token of the state family to dispose
|
|
17
|
+
* @param key - The unique key of the state to dispose
|
|
18
|
+
*/
|
|
16
19
|
export function disposeState<K extends Canonical>(
|
|
17
20
|
token: ReadableFamilyToken<any, K>,
|
|
18
21
|
key: K,
|
|
19
22
|
): void
|
|
20
|
-
|
|
21
|
-
export function disposeState<M extends MoleculeConstructor>(
|
|
22
|
-
token: MoleculeFamilyToken<M>,
|
|
23
|
-
key: MoleculeKey<M>,
|
|
24
|
-
): void
|
|
25
|
-
|
|
26
23
|
export function disposeState(
|
|
27
|
-
token:
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
| ReadableFamilyToken<any, any>
|
|
31
|
-
| ReadableToken<any>,
|
|
32
|
-
key?: Json.Serializable,
|
|
24
|
+
...[token, key]:
|
|
25
|
+
| [token: ReadableFamilyToken<any, any>, key: Canonical]
|
|
26
|
+
| [token: ReadableToken<any>]
|
|
33
27
|
): void {
|
|
34
28
|
if (key) {
|
|
35
29
|
Internal.disposeFromStore(Internal.IMPLICIT.STORE, token as any, key)
|
package/src/get-state.ts
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
import * as Internal from "atom.io/internal"
|
|
2
2
|
import type { Canonical } from "atom.io/json"
|
|
3
3
|
|
|
4
|
-
import type {
|
|
5
|
-
MoleculeConstructor,
|
|
6
|
-
MoleculeFamilyToken,
|
|
7
|
-
MoleculeToken,
|
|
8
|
-
ReadableFamilyToken,
|
|
9
|
-
ReadableToken,
|
|
10
|
-
} from "."
|
|
4
|
+
import type { ReadableFamilyToken, ReadableToken } from "."
|
|
11
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
* Get the current value of a state
|
|
9
|
+
* @param token - The token of the state to get
|
|
10
|
+
* @return The current value of the state
|
|
11
|
+
* @overload Default
|
|
12
|
+
* @default
|
|
13
|
+
*/
|
|
12
14
|
export function getState<T>(token: ReadableToken<T>): T
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
* Get the current value of a state family
|
|
19
|
+
* @param token - The token of a state family
|
|
20
|
+
* @param key - The unique key of the state to get
|
|
21
|
+
* @return The current value of the state
|
|
22
|
+
* @overload Streamlined
|
|
23
|
+
*/
|
|
18
24
|
export function getState<T, K extends Canonical, Key extends K>(
|
|
19
25
|
token: ReadableFamilyToken<T, K>,
|
|
20
26
|
key: Key,
|
|
21
27
|
): T
|
|
22
28
|
|
|
23
|
-
export function getState<M extends MoleculeConstructor>(
|
|
24
|
-
token: MoleculeFamilyToken<M>,
|
|
25
|
-
key: Canonical,
|
|
26
|
-
): InstanceType<M>
|
|
27
|
-
|
|
28
29
|
export function getState(
|
|
29
30
|
...params:
|
|
30
|
-
| [
|
|
31
|
-
|
|
32
|
-
key: Canonical,
|
|
33
|
-
]
|
|
34
|
-
| [token: MoleculeToken<any> | ReadableToken<any>]
|
|
31
|
+
| [token: ReadableFamilyToken<any, any>, key: Canonical]
|
|
32
|
+
| [token: ReadableToken<any>]
|
|
35
33
|
): any {
|
|
36
34
|
if (params.length === 2) {
|
|
37
35
|
return Internal.getFromStore(Internal.IMPLICIT.STORE, ...params)
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import type { Transceiver } from "atom.io/internal"
|
|
2
2
|
import type { Canonical, Json, stringified } from "atom.io/json"
|
|
3
3
|
|
|
4
|
-
import type { AtomFamilyToken } from "./atom"
|
|
4
|
+
import type { atom, AtomFamilyToken } from "./atom"
|
|
5
|
+
import type { getState } from "./get-state"
|
|
5
6
|
import type {
|
|
6
7
|
SelectorFamilyToken,
|
|
7
8
|
WritableSelectorFamilyToken,
|
|
8
9
|
} from "./selector"
|
|
10
|
+
import type { setState } from "./set-state"
|
|
11
|
+
import type { TimelineToken } from "./timeline"
|
|
12
|
+
import type {
|
|
13
|
+
runTransaction,
|
|
14
|
+
transaction,
|
|
15
|
+
TransactionToken,
|
|
16
|
+
} from "./transaction"
|
|
9
17
|
|
|
10
|
-
export * from "./allocate"
|
|
11
18
|
export * from "./atom"
|
|
12
19
|
export * from "./dispose-state"
|
|
13
20
|
export * from "./get-state"
|
|
14
21
|
export * from "./logger"
|
|
15
|
-
export * from "./
|
|
22
|
+
export * from "./realm"
|
|
16
23
|
export * from "./selector"
|
|
17
24
|
export * from "./set-state"
|
|
18
25
|
export * from "./silo"
|
|
@@ -21,58 +28,121 @@ export * from "./timeline"
|
|
|
21
28
|
export * from "./transaction"
|
|
22
29
|
export * from "./validators"
|
|
23
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
* A token is an object that uniquely identifies a particular state, family, timeline, or transaction.
|
|
34
|
+
*
|
|
35
|
+
* While they represent one of these resources, they are not the resource itself. Think of them like paper currency representing money in the bank.
|
|
36
|
+
*
|
|
37
|
+
* Tokens are returned from resource creation functions, such as {@link atom} and {@link transaction}.
|
|
38
|
+
*
|
|
39
|
+
* Tokens can be used as parameters to functions that take a token, such as {@link getState}, {@link setState}, or {@link runTransaction}.
|
|
40
|
+
*
|
|
41
|
+
* Tokens are fully serializable, so they can be passed between processes.
|
|
42
|
+
*/
|
|
43
|
+
export type AtomIOToken =
|
|
44
|
+
| ReadableFamilyToken<any, any>
|
|
45
|
+
| ReadableToken<any>
|
|
46
|
+
| TimelineToken<any>
|
|
47
|
+
| TransactionToken<any>
|
|
48
|
+
|
|
49
|
+
/** @public */
|
|
24
50
|
export type RegularAtomToken<T, K extends Canonical = any> = {
|
|
51
|
+
/** The unique identifier of the atom. */
|
|
25
52
|
key: string
|
|
53
|
+
/** Discriminator. */
|
|
26
54
|
type: `atom`
|
|
55
|
+
/** Present if the atom belongs to a family. */
|
|
27
56
|
family?: FamilyMetadata<K>
|
|
57
|
+
/** Never present. This is a marker that preserves the type of the atom's value. */
|
|
28
58
|
__T?: T
|
|
29
59
|
}
|
|
60
|
+
/** @public */
|
|
30
61
|
export type MutableAtomToken<
|
|
31
62
|
T extends Transceiver<any>,
|
|
32
63
|
J extends Json.Serializable,
|
|
33
64
|
K extends Canonical = any,
|
|
34
65
|
> = {
|
|
66
|
+
/** The unique identifier of the atom. */
|
|
35
67
|
key: string
|
|
68
|
+
/** Discriminator. */
|
|
36
69
|
type: `mutable_atom`
|
|
70
|
+
/** Present if the atom belongs to a family. */
|
|
37
71
|
family?: FamilyMetadata<K>
|
|
72
|
+
/** Never present. This is a marker that preserves the JSON form of the atom's transceiver value. */
|
|
38
73
|
__J?: J
|
|
74
|
+
/** Never present. This is a marker that preserves the type of the atom's transceiver value. */
|
|
39
75
|
__U?: T extends Transceiver<infer Update> ? Update : never
|
|
40
76
|
}
|
|
77
|
+
/** @public */
|
|
41
78
|
export type AtomToken<T, K extends Canonical = any> =
|
|
42
79
|
| MutableAtomToken<T extends Transceiver<any> ? T : never, any, K>
|
|
43
80
|
| RegularAtomToken<T, K>
|
|
44
81
|
|
|
82
|
+
/** @public */
|
|
45
83
|
export type WritableSelectorToken<T, K extends Canonical = any> = {
|
|
84
|
+
/** The unique identifier of the selector. */
|
|
46
85
|
key: string
|
|
86
|
+
/** Discriminator. */
|
|
47
87
|
type: `selector`
|
|
88
|
+
/** Present if the selector belongs to a family. */
|
|
48
89
|
family?: FamilyMetadata<K>
|
|
90
|
+
/** Never present. This is a marker that preserves the type of the selector's value. */
|
|
49
91
|
__T?: T
|
|
50
92
|
}
|
|
93
|
+
/** @public */
|
|
51
94
|
export type ReadonlySelectorToken<T, K extends Canonical = any> = {
|
|
95
|
+
/** The unique identifier of the selector. */
|
|
52
96
|
key: string
|
|
97
|
+
/** Discriminator. */
|
|
53
98
|
type: `readonly_selector`
|
|
99
|
+
/** Present if the selector belongs to a family. */
|
|
54
100
|
family?: FamilyMetadata<K>
|
|
101
|
+
/** Never present. This is a marker that preserves the type of the selector's value. */
|
|
55
102
|
__T?: T
|
|
56
103
|
}
|
|
104
|
+
/** @public */
|
|
57
105
|
export type SelectorToken<T, K extends Canonical = any> =
|
|
58
106
|
| ReadonlySelectorToken<T, K>
|
|
59
107
|
| WritableSelectorToken<T, K>
|
|
60
108
|
|
|
109
|
+
/**
|
|
110
|
+
* @public
|
|
111
|
+
* These states can be set.
|
|
112
|
+
*/
|
|
61
113
|
export type WritableToken<T, K extends Canonical = any> =
|
|
62
114
|
| AtomToken<T, K>
|
|
63
115
|
| WritableSelectorToken<T, K>
|
|
116
|
+
/**
|
|
117
|
+
* @public
|
|
118
|
+
* These states cannot be set.
|
|
119
|
+
*/
|
|
64
120
|
export type ReadableToken<T, K extends Canonical = any> =
|
|
65
121
|
| AtomToken<T, K>
|
|
66
122
|
| SelectorToken<T, K>
|
|
67
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @public
|
|
126
|
+
* States belonging to this family can be set.
|
|
127
|
+
*/
|
|
68
128
|
export type WritableFamilyToken<T, K extends Canonical> =
|
|
69
129
|
| AtomFamilyToken<T, K>
|
|
70
130
|
| WritableSelectorFamilyToken<T, K>
|
|
131
|
+
/**
|
|
132
|
+
* @public
|
|
133
|
+
* States belonging to this family cannot be set.
|
|
134
|
+
*/
|
|
71
135
|
export type ReadableFamilyToken<T, K extends Canonical> =
|
|
72
136
|
| AtomFamilyToken<T, K>
|
|
73
137
|
| SelectorFamilyToken<T, K>
|
|
74
138
|
|
|
139
|
+
/**
|
|
140
|
+
* @public
|
|
141
|
+
* Identifies a state's connection to its family.
|
|
142
|
+
*/
|
|
75
143
|
export type FamilyMetadata<K extends Canonical = any> = {
|
|
144
|
+
/** The family's unique key. */
|
|
76
145
|
key: string
|
|
146
|
+
/** The family member's unique identifier, in the form of a string. */
|
|
77
147
|
subKey: stringified<K>
|
|
78
148
|
}
|
package/src/realm.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { Each, Store } from "atom.io/internal"
|
|
2
|
+
import {
|
|
3
|
+
allocateIntoStore,
|
|
4
|
+
claimWithinStore,
|
|
5
|
+
deallocateFromStore,
|
|
6
|
+
fuseWithinStore,
|
|
7
|
+
IMPLICIT,
|
|
8
|
+
makeRootMoleculeInStore,
|
|
9
|
+
} from "atom.io/internal"
|
|
10
|
+
import type { Canonical } from "atom.io/json"
|
|
11
|
+
|
|
12
|
+
export const $claim = Symbol(`claim`)
|
|
13
|
+
export type Claim<K extends Canonical> = K & { [$claim]?: true }
|
|
14
|
+
|
|
15
|
+
export class Realm<H extends Hierarchy> {
|
|
16
|
+
public store: Store
|
|
17
|
+
public constructor(store: Store = IMPLICIT.STORE) {
|
|
18
|
+
this.store = store
|
|
19
|
+
makeRootMoleculeInStore(`root`, store)
|
|
20
|
+
}
|
|
21
|
+
public allocate<V extends Vassal<H>, A extends Above<V, H>>(
|
|
22
|
+
provenance: A,
|
|
23
|
+
key: V,
|
|
24
|
+
attachmentStyle?: `all` | `any`,
|
|
25
|
+
): Claim<V> {
|
|
26
|
+
return allocateIntoStore<H, V, A>(
|
|
27
|
+
this.store,
|
|
28
|
+
provenance,
|
|
29
|
+
key,
|
|
30
|
+
attachmentStyle,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
public fuse<
|
|
34
|
+
C extends CompoundFrom<H>,
|
|
35
|
+
T extends C extends CompoundTypedKey<infer t, any, any> ? t : never,
|
|
36
|
+
A extends C extends CompoundTypedKey<any, infer v, any> ? v : never,
|
|
37
|
+
B extends C extends CompoundTypedKey<any, any, infer m> ? m : never,
|
|
38
|
+
>(
|
|
39
|
+
type: T,
|
|
40
|
+
reagentA: SingularTypedKey<A>,
|
|
41
|
+
reagentB: SingularTypedKey<B>,
|
|
42
|
+
): Claim<CompoundTypedKey<T, A, B>> {
|
|
43
|
+
return fuseWithinStore<H, C, T, A, B>(this.store, type, reagentA, reagentB)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public deallocate<V extends Vassal<H>>(claim: Claim<V>): void {
|
|
47
|
+
deallocateFromStore<H, V>(this.store, claim)
|
|
48
|
+
}
|
|
49
|
+
public claim<
|
|
50
|
+
V extends Exclude<Vassal<H>, CompoundTypedKey>,
|
|
51
|
+
A extends Above<V, H>,
|
|
52
|
+
>(newProvenance: A, claim: Claim<V>, exclusive?: `exclusive`): Claim<V> {
|
|
53
|
+
return claimWithinStore<H, V, A>(this.store, newProvenance, claim, exclusive)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class Anarchy {
|
|
58
|
+
public store: Store
|
|
59
|
+
public realm: Realm<any>
|
|
60
|
+
|
|
61
|
+
public constructor(store: Store = IMPLICIT.STORE) {
|
|
62
|
+
this.store = store
|
|
63
|
+
this.realm = new Realm(store)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public allocate(
|
|
67
|
+
provenance: Canonical,
|
|
68
|
+
key: Canonical,
|
|
69
|
+
attachmentStyle?: `all` | `any`,
|
|
70
|
+
): void {
|
|
71
|
+
allocateIntoStore<any, any, any>(
|
|
72
|
+
this.store,
|
|
73
|
+
provenance,
|
|
74
|
+
key,
|
|
75
|
+
attachmentStyle,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public deallocate(key: Canonical): void {
|
|
80
|
+
deallocateFromStore<any, any>(this.store, key)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public claim(
|
|
84
|
+
newProvenance: Canonical,
|
|
85
|
+
key: Canonical,
|
|
86
|
+
exclusive?: `exclusive`,
|
|
87
|
+
): void {
|
|
88
|
+
claimWithinStore<any, any, any>(this.store, newProvenance, key, exclusive)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const T$ = `T$`
|
|
93
|
+
export type T$ = typeof T$
|
|
94
|
+
export type TypeTag<T extends string> = `${T$}--${T}`
|
|
95
|
+
export type SingularTypedKey<T extends string = string> = `${T}::${string}`
|
|
96
|
+
export type CompoundTypedKey<
|
|
97
|
+
A extends string = string,
|
|
98
|
+
B extends string = string,
|
|
99
|
+
C extends string = string,
|
|
100
|
+
> = `${TypeTag<A>}==${SingularTypedKey<B>}++${SingularTypedKey<C>}`
|
|
101
|
+
export type TypedKey<
|
|
102
|
+
A extends string = string,
|
|
103
|
+
B extends string = string,
|
|
104
|
+
C extends string = string,
|
|
105
|
+
> = CompoundTypedKey<A, B, C> | SingularTypedKey<A>
|
|
106
|
+
type Scope = SingularTypedKey[]
|
|
107
|
+
type MutualFealty = {
|
|
108
|
+
above: Scope
|
|
109
|
+
below: CompoundTypedKey
|
|
110
|
+
}
|
|
111
|
+
type ExclusiveFealty = {
|
|
112
|
+
above: TypedKey | `root`
|
|
113
|
+
below: Scope
|
|
114
|
+
}
|
|
115
|
+
type Fealty = ExclusiveFealty | MutualFealty
|
|
116
|
+
|
|
117
|
+
export type Hierarchy<F extends Fealty[] = Fealty[]> = Each<F>
|
|
118
|
+
|
|
119
|
+
export type Vassal<H extends Hierarchy> = {
|
|
120
|
+
[K in keyof H]: H[K] extends MutualFealty
|
|
121
|
+
? H[K][`below`]
|
|
122
|
+
: H[K] extends { below: Array<infer V> }
|
|
123
|
+
? V extends TypedKey
|
|
124
|
+
? V
|
|
125
|
+
: never
|
|
126
|
+
: never
|
|
127
|
+
}[keyof H]
|
|
128
|
+
|
|
129
|
+
export type Above<TK extends TypedKey, H extends Hierarchy> = {
|
|
130
|
+
[K in keyof H]: H[K] extends MutualFealty
|
|
131
|
+
? TK extends H[K][`below`]
|
|
132
|
+
? H[K][`above`]
|
|
133
|
+
: never
|
|
134
|
+
: H[K] extends { below: Array<infer V> }
|
|
135
|
+
? TK extends V
|
|
136
|
+
? H[K] extends ExclusiveFealty
|
|
137
|
+
? H[K][`above`]
|
|
138
|
+
: never
|
|
139
|
+
: never
|
|
140
|
+
: never
|
|
141
|
+
}[keyof H]
|
|
142
|
+
|
|
143
|
+
export type Below<TK extends TypedKey | TypedKey[], H extends Hierarchy> = {
|
|
144
|
+
[K in keyof H]: H[K] extends MutualFealty
|
|
145
|
+
? TK extends H[K][`above`]
|
|
146
|
+
? H[K][`below`]
|
|
147
|
+
: TK extends H[K][`above`][number]
|
|
148
|
+
? H[K][`below`]
|
|
149
|
+
: never
|
|
150
|
+
: H[K] extends { above: infer V }
|
|
151
|
+
? TK extends V
|
|
152
|
+
? H[K] extends ExclusiveFealty
|
|
153
|
+
? H[K][`below`][number]
|
|
154
|
+
: never
|
|
155
|
+
: never
|
|
156
|
+
: never
|
|
157
|
+
}[keyof H]
|
|
158
|
+
|
|
159
|
+
export type Mutuals<TK extends TypedKey | TypedKey[], H extends Hierarchy> = {
|
|
160
|
+
[K in keyof H]: H[K] extends MutualFealty
|
|
161
|
+
? TK extends H[K][`above`][number]
|
|
162
|
+
? [mutual: Exclude<H[K][`above`][number], TK>, below: H[K][`below`]]
|
|
163
|
+
: never
|
|
164
|
+
: never
|
|
165
|
+
}[keyof H]
|
|
166
|
+
|
|
167
|
+
export type CompoundFrom<H extends Hierarchy> = {
|
|
168
|
+
[K in keyof H]: H[K] extends MutualFealty ? H[K][`below`] : never
|
|
169
|
+
}[keyof H]
|
package/src/selector.ts
CHANGED
|
@@ -18,9 +18,29 @@ export type ReadonlySelectorOptions<T> = {
|
|
|
18
18
|
get: Read<() => T>
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
* Declare a selector. The value of a selector should depend
|
|
24
|
+
* on the value of atoms or other selectors in the store.
|
|
25
|
+
*
|
|
26
|
+
* A writable selector can be "set" to a new value.
|
|
27
|
+
* It is advised to set its dependencies to values
|
|
28
|
+
* that would produce the new value of the selector.
|
|
29
|
+
* @param options - {@link WritableSelectorOptions}.
|
|
30
|
+
* @returns
|
|
31
|
+
* The token for your selector.
|
|
32
|
+
* @overload Writable
|
|
33
|
+
*/
|
|
21
34
|
export function selector<T>(
|
|
22
35
|
options: WritableSelectorOptions<T>,
|
|
23
36
|
): WritableSelectorToken<T>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @public
|
|
40
|
+
* Declare a selector. The value of a selector should depend
|
|
41
|
+
* on the value of atoms or other selectors in the store.
|
|
42
|
+
* @param options - {@link ReadonlySelectorOptions}.
|
|
43
|
+
*/
|
|
24
44
|
export function selector<T>(
|
|
25
45
|
options: ReadonlySelectorOptions<T>,
|
|
26
46
|
): ReadonlySelectorToken<T>
|
package/src/set-state.ts
CHANGED
|
@@ -3,41 +3,49 @@ import type { Canonical } from "atom.io/json"
|
|
|
3
3
|
|
|
4
4
|
import type { WritableFamilyToken, WritableToken } from "."
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
* A function that sets the value of a state.
|
|
9
|
+
* @param oldValue - The current value of the state.
|
|
10
|
+
* @returns
|
|
11
|
+
* The new value of the state.
|
|
12
|
+
*/
|
|
13
|
+
export type Setter<T, New extends T> = (oldValue: T) => New
|
|
14
|
+
|
|
6
15
|
/**
|
|
7
16
|
* @public
|
|
8
17
|
* Set the value of a state into the implicit store.
|
|
9
|
-
* @param token -
|
|
18
|
+
* @param token - An atom or writable selector token.
|
|
10
19
|
* @param value - The new value of the state.
|
|
11
20
|
* @overload Default
|
|
12
21
|
* @default
|
|
13
22
|
*/
|
|
14
23
|
export function setState<T, New extends T>(
|
|
15
24
|
token: WritableToken<T>,
|
|
16
|
-
value: New |
|
|
25
|
+
value: New | Setter<T, New>,
|
|
17
26
|
): void
|
|
18
27
|
|
|
19
28
|
/**
|
|
20
29
|
* @public
|
|
21
30
|
* Set the value of a state into the implicit store.
|
|
22
|
-
* @param token -
|
|
23
|
-
* @param key - The key of the state to set.
|
|
31
|
+
* @param token - An atom family or writable selector family token.
|
|
32
|
+
* @param key - The unique key of the state to set.
|
|
24
33
|
* @param value - The new value of the state.
|
|
25
34
|
* @overload Streamlined
|
|
26
35
|
*/
|
|
27
36
|
export function setState<T, K extends Canonical, New extends T, Key extends K>(
|
|
28
37
|
token: WritableFamilyToken<T, K>,
|
|
29
38
|
key: Key,
|
|
30
|
-
value: New |
|
|
39
|
+
value: New | Setter<T, New>,
|
|
31
40
|
): void
|
|
32
|
-
|
|
33
41
|
export function setState<T, New extends T>(
|
|
34
42
|
...params:
|
|
35
43
|
| [
|
|
36
44
|
token: WritableFamilyToken<T, Canonical>,
|
|
37
45
|
key: Canonical,
|
|
38
|
-
value: New |
|
|
46
|
+
value: New | Setter<T, New>,
|
|
39
47
|
]
|
|
40
|
-
| [token: WritableToken<T>, value: New |
|
|
48
|
+
| [token: WritableToken<T>, value: New | Setter<T, New>]
|
|
41
49
|
): void {
|
|
42
50
|
if (params.length === 2) {
|
|
43
51
|
Internal.setIntoStore(Internal.IMPLICIT.STORE, ...params)
|