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.
Files changed (92) hide show
  1. package/data/dist/index.d.ts +20 -18
  2. package/data/dist/index.js +104 -172
  3. package/data/src/join.ts +138 -210
  4. package/dist/{chunk-UDHCFTYT.js → chunk-Y5MBNTVU.js} +582 -762
  5. package/dist/index.d.ts +254 -173
  6. package/dist/index.js +91 -14
  7. package/ephemeral/dist/index.d.ts +35 -25
  8. package/ephemeral/src/find-state.ts +35 -25
  9. package/eslint-plugin/dist/index.d.ts +22 -3
  10. package/eslint-plugin/dist/index.js +7 -7
  11. package/immortal/dist/index.d.ts +1 -2
  12. package/immortal/dist/index.js +0 -3
  13. package/immortal/src/seek-state.ts +2 -14
  14. package/internal/dist/index.d.ts +57 -88
  15. package/internal/dist/index.js +1 -2
  16. package/internal/src/atom/dispose-atom.ts +31 -15
  17. package/internal/src/families/dispose-from-store.ts +15 -44
  18. package/internal/src/families/find-in-store.ts +9 -7
  19. package/internal/src/families/init-family-member.ts +1 -1
  20. package/internal/src/families/seek-in-store.ts +2 -14
  21. package/internal/src/get-state/get-from-store.ts +13 -79
  22. package/internal/src/get-trace.ts +7 -0
  23. package/internal/src/index.ts +17 -8
  24. package/internal/src/ingest-updates/ingest-creation-disposal.ts +65 -73
  25. package/internal/src/ingest-updates/ingest-transaction-update.ts +4 -0
  26. package/internal/src/install-into-store.ts +48 -0
  27. package/internal/src/junction.ts +52 -12
  28. package/internal/src/lineage.ts +0 -7
  29. package/internal/src/molecule.ts +306 -0
  30. package/internal/src/mutable/transceiver.ts +5 -5
  31. package/internal/src/not-found-error.ts +8 -30
  32. package/internal/src/pretty-print.ts +1 -16
  33. package/internal/src/selector/dispose-selector.ts +3 -5
  34. package/internal/src/selector/register-selector.ts +3 -34
  35. package/internal/src/set-state/set-into-store.ts +3 -2
  36. package/internal/src/store/counterfeit.ts +11 -25
  37. package/internal/src/store/deposit.ts +10 -42
  38. package/internal/src/store/store.ts +51 -12
  39. package/internal/src/store/withdraw.ts +18 -60
  40. package/internal/src/timeline/create-timeline.ts +133 -237
  41. package/internal/src/timeline/time-travel.ts +1 -8
  42. package/internal/src/transaction/build-transaction.ts +10 -5
  43. package/internal/src/transaction/index.ts +1 -1
  44. package/internal/src/utility-types.ts +2 -0
  45. package/introspection/dist/index.d.ts +2 -3
  46. package/introspection/dist/index.js +9 -9
  47. package/introspection/src/refinery.ts +1 -3
  48. package/json/dist/index.js +8 -40
  49. package/json/src/index.ts +2 -0
  50. package/json/src/select-json-family.ts +7 -44
  51. package/package.json +33 -28
  52. package/react/dist/index.js +2 -10
  53. package/react/src/parse-state-overloads.ts +3 -11
  54. package/react-devtools/dist/index.js +13 -13
  55. package/react-devtools/src/Updates.tsx +2 -0
  56. package/realtime-client/dist/index.d.ts +20 -12
  57. package/realtime-client/dist/index.js +241 -244
  58. package/realtime-client/src/continuity/index.ts +3 -0
  59. package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +231 -0
  60. package/realtime-client/src/continuity/use-conceal-state.ts +11 -0
  61. package/realtime-client/src/continuity/use-reveal-state.ts +19 -0
  62. package/realtime-client/src/index.ts +1 -0
  63. package/realtime-client/src/sync-continuity.ts +18 -262
  64. package/realtime-react/dist/index.js +2 -2
  65. package/realtime-server/dist/index.d.ts +1 -1
  66. package/realtime-server/dist/index.js +2 -2
  67. package/realtime-server/src/index.ts +1 -1
  68. package/realtime-server/src/ipc-sockets/child-socket.ts +0 -1
  69. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +1 -1
  70. package/realtime-testing/dist/index.js +5 -7
  71. package/realtime-testing/src/setup-realtime-test.tsx +5 -6
  72. package/src/atom.ts +53 -29
  73. package/src/dispose-state.ts +17 -23
  74. package/src/get-state.ts +19 -21
  75. package/src/index.ts +73 -3
  76. package/src/realm.ts +169 -0
  77. package/src/selector.ts +20 -0
  78. package/src/set-state.ts +16 -8
  79. package/src/silo.ts +9 -14
  80. package/src/timeline.ts +2 -3
  81. package/src/transaction.ts +25 -38
  82. package/transceivers/set-rtx/dist/index.js +4 -1
  83. package/transceivers/set-rtx/src/set-rtx.ts +4 -1
  84. package/dist/chunk-ADMEAXYU.js +0 -167
  85. package/internal/src/molecule/create-molecule-family.ts +0 -30
  86. package/internal/src/molecule/dispose-molecule.ts +0 -79
  87. package/internal/src/molecule/grow-molecule-in-store.ts +0 -95
  88. package/internal/src/molecule/index.ts +0 -5
  89. package/internal/src/molecule/make-molecule-in-store.ts +0 -191
  90. package/internal/src/molecule/molecule-internal.ts +0 -52
  91. package/src/allocate.ts +0 -277
  92. 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 = realm<RTS.SocketSystemHierarchy>(silo.store)
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
- * Declare a mutable global reactive variable.
35
- * @param options - Configuration for this mutable atom.
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
- * The token for your mutable atom.
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
- * Declare a regular global reactive variable.
46
- * @param options - Configuration for this regular atom.
28
+ * Create a regular atom, a global reactive variable in the implicit store
29
+ * @param options - {@link RegularAtomOptions}.
47
30
  * @returns
48
- * The token for your regular atom.
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
 
@@ -1,35 +1,29 @@
1
1
  import * as Internal from "atom.io/internal"
2
- import type { Canonical, Json } from "atom.io/json"
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
- | MoleculeFamilyToken<any>
29
- | MoleculeToken<any>
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
- export function getState<M extends MoleculeConstructor>(
15
- token: MoleculeToken<M>,
16
- ): InstanceType<M>
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
- token: MoleculeFamilyToken<any> | ReadableFamilyToken<any, any>,
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 "./molecule"
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 - The unique identifier of the state to set.
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 | ((oldValue: T) => 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 - The unique identifier of a state family.
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 | ((oldValue: T) => 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 | ((oldValue: T) => New),
46
+ value: New | Setter<T, New>,
39
47
  ]
40
- | [token: WritableToken<T>, value: New | ((oldValue: T) => 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)