atom.io 0.40.6 → 0.40.7

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 (163) hide show
  1. package/README.md +1 -1
  2. package/dist/data/index.d.ts +1 -1
  3. package/dist/employ-socket-D6wgByWh.js +12 -0
  4. package/dist/employ-socket-D6wgByWh.js.map +1 -0
  5. package/dist/has-role-hv4-hJMw.js +1149 -0
  6. package/dist/has-role-hv4-hJMw.js.map +1 -0
  7. package/dist/internal/index.d.ts +248 -248
  8. package/dist/internal/index.d.ts.map +1 -1
  9. package/dist/internal/index.js +570 -1712
  10. package/dist/internal/index.js.map +1 -1
  11. package/dist/introspection/index.d.ts +1 -1
  12. package/dist/is-fn-DY1wZ-md.js +10 -0
  13. package/dist/is-fn-DY1wZ-md.js.map +1 -0
  14. package/dist/main/index.d.ts +33 -33
  15. package/dist/main/index.d.ts.map +1 -1
  16. package/dist/main/index.js +2 -2
  17. package/dist/main/index.js.map +1 -1
  18. package/dist/mutex-store-CSvxY9i3.js +11 -0
  19. package/dist/mutex-store-CSvxY9i3.js.map +1 -0
  20. package/dist/react/index.d.ts +5 -5
  21. package/dist/react/index.d.ts.map +1 -1
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/react-devtools/index.js +7 -7
  24. package/dist/react-devtools/index.js.map +1 -1
  25. package/dist/realtime/index.d.ts +7 -15
  26. package/dist/realtime/index.d.ts.map +1 -1
  27. package/dist/realtime/index.js +3 -33
  28. package/dist/realtime/index.js.map +1 -1
  29. package/dist/realtime-client/index.d.ts +5 -5
  30. package/dist/realtime-client/index.d.ts.map +1 -1
  31. package/dist/realtime-client/index.js +92 -69
  32. package/dist/realtime-client/index.js.map +1 -1
  33. package/dist/realtime-react/index.d.ts +17 -10
  34. package/dist/realtime-react/index.d.ts.map +1 -1
  35. package/dist/realtime-react/index.js +41 -41
  36. package/dist/realtime-react/index.js.map +1 -1
  37. package/dist/realtime-server/index.d.ts +60 -53
  38. package/dist/realtime-server/index.d.ts.map +1 -1
  39. package/dist/realtime-server/index.js +592 -485
  40. package/dist/realtime-server/index.js.map +1 -1
  41. package/dist/realtime-testing/index.d.ts +1 -2
  42. package/dist/realtime-testing/index.d.ts.map +1 -1
  43. package/dist/realtime-testing/index.js +25 -18
  44. package/dist/realtime-testing/index.js.map +1 -1
  45. package/dist/shared-room-store-COGGKqes.js +32 -0
  46. package/dist/shared-room-store-COGGKqes.js.map +1 -0
  47. package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
  48. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
  49. package/dist/web/index.d.ts +3 -3
  50. package/dist/web/index.d.ts.map +1 -1
  51. package/dist/web/index.js +4 -3
  52. package/dist/web/index.js.map +1 -1
  53. package/package.json +12 -12
  54. package/src/internal/atom/create-regular-atom.ts +5 -4
  55. package/src/internal/atom/dispose-atom.ts +7 -2
  56. package/src/internal/atom/has-role.ts +3 -3
  57. package/src/internal/caching.ts +4 -2
  58. package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
  59. package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
  60. package/src/internal/families/create-regular-atom-family.ts +2 -1
  61. package/src/internal/families/create-writable-held-selector-family.ts +2 -1
  62. package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
  63. package/src/internal/families/dispose-from-store.ts +4 -4
  64. package/src/internal/families/find-in-store.ts +10 -10
  65. package/src/internal/families/get-family-of-token.ts +2 -2
  66. package/src/internal/families/index.ts +1 -0
  67. package/src/internal/families/mint-in-store.ts +54 -19
  68. package/src/internal/families/seek-in-store.ts +1 -1
  69. package/src/internal/get-state/get-fallback.ts +2 -2
  70. package/src/internal/get-state/get-from-store.ts +5 -5
  71. package/src/internal/get-state/read-or-compute-value.ts +1 -1
  72. package/src/internal/get-state/reduce-reference.ts +8 -6
  73. package/src/internal/index.ts +2 -220
  74. package/src/internal/molecule.ts +1 -2
  75. package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
  76. package/src/internal/mutable/create-mutable-atom.ts +4 -2
  77. package/src/internal/mutable/get-json-family.ts +1 -1
  78. package/src/internal/mutable/get-update-family.ts +1 -1
  79. package/src/internal/mutable/tracker-family.ts +2 -1
  80. package/src/internal/mutable/tracker.ts +5 -8
  81. package/src/internal/safe-compute.ts +1 -1
  82. package/src/internal/selector/create-readonly-held-selector.ts +2 -1
  83. package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
  84. package/src/internal/selector/create-writable-held-selector.ts +2 -1
  85. package/src/internal/selector/create-writable-pure-selector.ts +2 -1
  86. package/src/internal/selector/dispose-selector.ts +3 -2
  87. package/src/internal/selector/register-selector.ts +8 -5
  88. package/src/internal/selector/trace-selector-atoms.ts +2 -1
  89. package/src/internal/set-state/dispatch-state-update.ts +3 -2
  90. package/src/internal/set-state/evict-downstream.ts +1 -1
  91. package/src/internal/set-state/operate-on-store.ts +16 -22
  92. package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
  93. package/src/internal/set-state/reset-in-store.ts +5 -5
  94. package/src/internal/set-state/set-atom-or-selector.ts +2 -2
  95. package/src/internal/set-state/set-atom.ts +4 -2
  96. package/src/internal/set-state/set-into-store.ts +21 -39
  97. package/src/internal/set-state/set-selector.ts +3 -2
  98. package/src/internal/state-types.ts +228 -0
  99. package/src/internal/store/deposit.ts +4 -4
  100. package/src/internal/store/index.ts +0 -1
  101. package/src/internal/store/store.ts +9 -9
  102. package/src/internal/store/withdraw.ts +4 -4
  103. package/src/internal/subscribe/recall-state.ts +1 -1
  104. package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
  105. package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
  106. package/src/internal/transaction/build-transaction.ts +3 -2
  107. package/src/internal/transaction/index.ts +1 -23
  108. package/src/internal/transaction/is-root-store.ts +4 -1
  109. package/src/internal/transaction/transaction-meta-progress.ts +22 -0
  110. package/src/main/atom.ts +1 -2
  111. package/src/main/find-state.ts +5 -5
  112. package/src/main/get-state.ts +4 -4
  113. package/src/main/realm.ts +2 -2
  114. package/src/main/set-state.ts +10 -10
  115. package/src/react/parse-state-overloads.ts +3 -3
  116. package/src/react/use-i.ts +6 -4
  117. package/src/react/use-loadable.ts +4 -10
  118. package/src/react/use-o.ts +6 -4
  119. package/src/react-devtools/store.ts +6 -6
  120. package/src/realtime/index.ts +1 -0
  121. package/src/realtime/mutex-store.ts +11 -0
  122. package/src/realtime/realtime-continuity.ts +1 -5
  123. package/src/realtime-client/pull-atom-family-member.ts +14 -17
  124. package/src/realtime-client/pull-atom.ts +1 -1
  125. package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
  126. package/src/realtime-client/pull-selector-family-member.ts +8 -35
  127. package/src/realtime-client/pull-selector-roots.ts +90 -0
  128. package/src/realtime-client/pull-selector.ts +2 -27
  129. package/src/realtime-client/push-state.ts +33 -5
  130. package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
  131. package/src/realtime-react/index.ts +2 -1
  132. package/src/realtime-react/realtime-context.tsx +9 -5
  133. package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
  134. package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
  135. package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
  136. package/src/realtime-react/use-push.ts +7 -3
  137. package/src/realtime-react/use-realtime-service.ts +11 -11
  138. package/src/realtime-react/use-single-effect.ts +11 -14
  139. package/src/realtime-server/{realtime-server-stores/server-sync-store.ts → continuity/continuity-store.ts} +1 -1
  140. package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +1 -1
  141. package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +3 -5
  142. package/src/realtime-server/continuity/subscribe-to-continuity-actions.ts +1 -1
  143. package/src/realtime-server/employ-socket.ts +14 -0
  144. package/src/realtime-server/index.ts +2 -20
  145. package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
  146. package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
  147. package/src/realtime-server/ipc-sockets/parent-socket.ts +81 -58
  148. package/src/realtime-server/realtime-family-provider.ts +78 -29
  149. package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
  150. package/src/realtime-server/realtime-mutable-provider.ts +30 -22
  151. package/src/realtime-server/realtime-server-stores/index.ts +0 -2
  152. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
  153. package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
  154. package/src/realtime-server/realtime-state-provider.ts +30 -29
  155. package/src/realtime-server/realtime-state-receiver.ts +62 -16
  156. package/src/realtime-server/server-config.ts +9 -0
  157. package/src/realtime-server/socket-interface.ts +14 -0
  158. package/src/realtime-testing/setup-realtime-test.tsx +56 -23
  159. package/src/web/index.ts +1 -1
  160. package/src/web/{persist-sync.ts → storage-sync.ts} +5 -2
  161. package/src/internal/store/mint-or-counterfeit.ts +0 -108
  162. package/src/realtime-react/on-mount.ts +0 -5
  163. package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +0 -79
@@ -9,7 +9,7 @@ import type { WritableFamilyToken, WritableToken } from "./tokens"
9
9
  * @returns
10
10
  * The new value of the state.
11
11
  */
12
- export type Setter<T, New extends T> = (oldValue: T) => New
12
+ export type Setter<T> = (oldValue: T) => T
13
13
 
14
14
  /**
15
15
  * Set the value of a state into the implicit store.
@@ -18,9 +18,9 @@ export type Setter<T, New extends T> = (oldValue: T) => New
18
18
  * @overload Default
19
19
  * @default
20
20
  */
21
- export function setState<T, New extends T>(
21
+ export function setState<T, TT extends T>(
22
22
  token: WritableToken<T, any, any>,
23
- value: New | Setter<T, New>,
23
+ value: Setter<TT> | TT,
24
24
  ): void
25
25
 
26
26
  /**
@@ -30,20 +30,20 @@ export function setState<T, New extends T>(
30
30
  * @param value - The new value of the state.
31
31
  * @overload Streamlined
32
32
  */
33
- export function setState<T, K extends Canonical, New extends T, Key extends K>(
33
+ export function setState<T, TT extends T, K extends Canonical>(
34
34
  token: WritableFamilyToken<T, K, any>,
35
- key: Key,
36
- value: New | Setter<T, New>,
35
+ key: NoInfer<K>,
36
+ value: Setter<TT> | TT,
37
37
  ): void
38
38
 
39
- export function setState<T, K extends Canonical, New extends T, Key extends K>(
39
+ export function setState<T, TT extends T, K extends Canonical>(
40
40
  ...params:
41
41
  | [
42
42
  token: WritableFamilyToken<T, K, any>,
43
- key: Key,
44
- value: New | Setter<T, New>,
43
+ key: NoInfer<K>,
44
+ value: Setter<TT> | TT,
45
45
  ]
46
- | [token: WritableToken<T, any, any>, value: New | Setter<T, New>]
46
+ | [token: WritableToken<T, any, any>, value: Setter<TT> | TT]
47
47
  ): void {
48
48
  setIntoStore(IMPLICIT.STORE, ...params)
49
49
  }
@@ -11,17 +11,17 @@ import type { Canonical } from "atom.io/json"
11
11
  export function parseStateOverloads<T, K extends Canonical, Key extends K, E>(
12
12
  store: Store,
13
13
  ...rest: [WritableFamilyToken<T, K, E>, Key] | [WritableToken<T, any, E>]
14
- ): WritableToken<T, K, E>
14
+ ): WritableToken<T, Key, E>
15
15
 
16
16
  export function parseStateOverloads<T, K extends Canonical, Key extends K, E>(
17
17
  store: Store,
18
18
  ...rest: [ReadableFamilyToken<T, K, E>, Key] | [ReadableToken<T, any, E>]
19
- ): ReadableToken<T, K, E>
19
+ ): ReadableToken<T, Key, E>
20
20
 
21
21
  export function parseStateOverloads<T, K extends Canonical, Key extends K, E>(
22
22
  store: Store,
23
23
  ...rest: [ReadableFamilyToken<T, K, E>, Key] | [ReadableToken<T, any, E>]
24
- ): ReadableToken<T, K, E> {
24
+ ): ReadableToken<T, Key, E> {
25
25
  let token: ReadableToken<any, any, any>
26
26
  if (rest.length === 2) {
27
27
  const family = rest[0]
@@ -10,13 +10,15 @@ export function useI<T>(
10
10
  token: WritableToken<T, any, any>,
11
11
  ): <New extends T>(next: New | ((old: T) => New)) => void
12
12
 
13
- export function useI<T, K extends Canonical, Key extends K>(
13
+ export function useI<T, K extends Canonical>(
14
14
  token: WritableFamilyToken<T, K, any>,
15
- key: Key,
15
+ key: NoInfer<K>,
16
16
  ): <New extends T>(next: New | ((old: T) => New)) => void
17
17
 
18
- export function useI<T, K extends Canonical, Key extends K>(
19
- ...params: [WritableFamilyToken<T, K, any>, Key] | [WritableToken<T, any, any>]
18
+ export function useI<T, K extends Canonical>(
19
+ ...params:
20
+ | [WritableFamilyToken<T, K, any>, NoInfer<K>]
21
+ | [WritableToken<T, any, any>]
20
22
  ): <New extends T>(next: New | ((old: T) => New)) => void {
21
23
  const store = React.useContext(StoreContext)
22
24
  const token = parseStateOverloads(store, ...params)
@@ -9,9 +9,9 @@ export function useLoadable<T, E>(
9
9
  token: ReadableToken<Loadable<T>, any, E>,
10
10
  ): `LOADING` | { loading: boolean; value: E | T }
11
11
 
12
- export function useLoadable<T, K extends Canonical, Key extends K, E>(
12
+ export function useLoadable<T, K extends Canonical, E>(
13
13
  token: ReadableFamilyToken<Loadable<T>, K, E>,
14
- key: Key,
14
+ key: NoInfer<K>,
15
15
  ): `LOADING` | { loading: boolean; value: E | T }
16
16
 
17
17
  export function useLoadable<T, F extends T, E>(
@@ -19,15 +19,9 @@ export function useLoadable<T, F extends T, E>(
19
19
  fallback: F,
20
20
  ): { loading: boolean; value: T; error?: E }
21
21
 
22
- export function useLoadable<
23
- T,
24
- K extends Canonical,
25
- F extends T,
26
- Key extends K,
27
- E,
28
- >(
22
+ export function useLoadable<T, K extends Canonical, F extends T, E>(
29
23
  token: ReadableFamilyToken<Loadable<T>, K, E>,
30
- key: Key,
24
+ key: NoInfer<K>,
31
25
  fallback: F,
32
26
  ): { loading: boolean; value: T; error?: E }
33
27
 
@@ -8,13 +8,15 @@ import { StoreContext } from "./store-context"
8
8
 
9
9
  export function useO<T, E>(token: ReadableToken<T, any, E>): E | T
10
10
 
11
- export function useO<T, K extends Canonical, Key extends K, E>(
11
+ export function useO<T, K extends Canonical, E>(
12
12
  token: ReadableFamilyToken<T, K, E>,
13
- key: Key,
13
+ key: NoInfer<K>,
14
14
  ): E | T
15
15
 
16
- export function useO<T, K extends Canonical, Key extends K, E>(
17
- ...params: [ReadableFamilyToken<T, K, E>, Key] | [ReadableToken<T, any, E>]
16
+ export function useO<T, K extends Canonical, E>(
17
+ ...params:
18
+ | [ReadableFamilyToken<T, K, E>, NoInfer<K>]
19
+ | [ReadableToken<T, any, E>]
18
20
  ): E | T {
19
21
  const store = React.useContext(StoreContext)
20
22
  const token = parseStateOverloads(store, ...params)
@@ -16,7 +16,7 @@ import type {
16
16
  WritableTokenIndex,
17
17
  } from "atom.io/introspection"
18
18
  import { attachIntrospectionStates, isPlainObject } from "atom.io/introspection"
19
- import { persistSync } from "atom.io/web"
19
+ import { storageSync } from "atom.io/web"
20
20
  import type { Context } from "react"
21
21
  import { createContext } from "react"
22
22
 
@@ -48,7 +48,7 @@ export function attachDevtoolsStates(
48
48
  typeof window === `undefined`
49
49
  ? []
50
50
  : [
51
- persistSync(window.localStorage, JSON, `🔍 Devtools Are Hidden`),
51
+ storageSync(window.localStorage, JSON, `🔍 Devtools Are Hidden`),
52
52
  ({ setSelf }) => {
53
53
  window.addEventListener(`keydown`, (e) => {
54
54
  if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === `a`) {
@@ -70,7 +70,7 @@ export function attachDevtoolsStates(
70
70
  effects:
71
71
  typeof window === `undefined`
72
72
  ? []
73
- : [persistSync(window.localStorage, JSON, `🔍 Devtools Are Open`)],
73
+ : [storageSync(window.localStorage, JSON, `🔍 Devtools Are Open`)],
74
74
  },
75
75
  undefined,
76
76
  )
@@ -87,7 +87,7 @@ export function attachDevtoolsStates(
87
87
  effects:
88
88
  typeof window === `undefined`
89
89
  ? []
90
- : [persistSync(window.localStorage, JSON, `🔍 Devtools View`)],
90
+ : [storageSync(window.localStorage, JSON, `🔍 Devtools View`)],
91
91
  },
92
92
  undefined,
93
93
  )
@@ -104,7 +104,7 @@ export function attachDevtoolsStates(
104
104
  effects:
105
105
  typeof window === `undefined`
106
106
  ? []
107
- : [persistSync(window.localStorage, JSON, `🔍 Devtools View Options`)],
107
+ : [storageSync(window.localStorage, JSON, `🔍 Devtools View Options`)],
108
108
  },
109
109
  undefined,
110
110
  )
@@ -119,7 +119,7 @@ export function attachDevtoolsStates(
119
119
  effects: (key) =>
120
120
  typeof window === `undefined`
121
121
  ? []
122
- : [persistSync(window.localStorage, JSON, `view-is-open:${key.join()}`)],
122
+ : [storageSync(window.localStorage, JSON, `view-is-open:${key.join()}`)],
123
123
  })
124
124
 
125
125
  const openCloseAllTX: TransactionToken<
@@ -1,2 +1,3 @@
1
+ export * from "./mutex-store"
1
2
  export * from "./realtime-continuity"
2
3
  export * from "./shared-room-store"
@@ -0,0 +1,11 @@
1
+ import type { AtomFamilyToken } from "atom.io"
2
+ import { atomFamily } from "atom.io"
3
+ import type { Canonical } from "atom.io/json"
4
+
5
+ export const mutexAtoms: AtomFamilyToken<boolean, Canonical> = atomFamily<
6
+ boolean,
7
+ Canonical
8
+ >({
9
+ key: `mutex`,
10
+ default: false,
11
+ })
@@ -16,7 +16,7 @@ import type { UserKey } from "atom.io/realtime-server"
16
16
 
17
17
  /* eslint-disable no-console */
18
18
 
19
- export class InvariantMap<K, V> extends Map<K, V> {
19
+ export class InvariantMap<K, V> extends Map<K, V> implements ReadonlyMap<K, V> {
20
20
  public set(key: K, value: V): this {
21
21
  if (this.has(key)) {
22
22
  console.warn(`Tried to set a key that already exists in an InvariantMap`, {
@@ -27,10 +27,6 @@ export class InvariantMap<K, V> extends Map<K, V> {
27
27
  }
28
28
  return super.set(key, value)
29
29
  }
30
-
31
- public clear(): void {
32
- throw new Error(`Cannot clear an InvariantMap`)
33
- }
34
30
  }
35
31
 
36
32
  export type PerspectiveToken<F extends AtomFamilyToken<any>> = {
@@ -1,28 +1,25 @@
1
1
  import type * as AtomIO from "atom.io"
2
- import { setIntoStore, type Store } from "atom.io/internal"
3
- import type { Json } from "atom.io/json"
4
- import { parseJson } from "atom.io/json"
2
+ import { findInStore, setIntoStore, type Store } from "atom.io/internal"
3
+ import type { Canonical, Json } from "atom.io/json"
5
4
  import type { Socket } from "socket.io-client"
6
5
 
7
- /* eslint-disable no-console */
8
-
9
- export function pullAtomFamilyMember<J extends Json.Serializable>(
6
+ export function pullAtomFamilyMember<
7
+ J extends Json.Serializable,
8
+ K extends Canonical,
9
+ >(
10
10
  store: Store,
11
11
  socket: Socket,
12
- token: AtomIO.RegularAtomToken<J>,
12
+ family: AtomIO.AtomFamilyToken<J, K, any>,
13
+ key: NoInfer<K>,
13
14
  ): () => void {
14
- if (!(`family` in token)) {
15
- console.error(`Token is not a family member:`, token)
16
- return () => {}
17
- }
18
- const { key: familyKey, subKey: serializedSubKey } = token.family
19
- const subKey = parseJson(serializedSubKey)
20
- socket?.on(`serve:${token.key}`, (data: J) => {
15
+ const token = findInStore(store, family, key)
16
+ const setServedValue = (data: J) => {
21
17
  setIntoStore(store, token, data)
22
- })
23
- socket?.emit(`sub:${familyKey}`, subKey)
18
+ }
19
+ socket?.on(`serve:${token.key}`, setServedValue)
20
+ socket?.emit(`sub:${family.key}`, key)
24
21
  return () => {
25
- socket?.off(`serve:${token.key}`)
22
+ socket?.off(`serve:${token.key}`, setServedValue)
26
23
  socket?.emit(`unsub:${token.key}`)
27
24
  }
28
25
  }
@@ -6,7 +6,7 @@ import type { Socket } from "socket.io-client"
6
6
  export function pullAtom<J extends Json.Serializable>(
7
7
  store: Store,
8
8
  socket: Socket,
9
- token: AtomIO.RegularAtomToken<J>,
9
+ token: AtomIO.RegularAtomToken<J, any, any>,
10
10
  ): () => void {
11
11
  const setServedValue = (data: J) => {
12
12
  setIntoStore(store, token, data)
@@ -1,20 +1,24 @@
1
1
  import type * as AtomIO from "atom.io"
2
2
  import type { AsJSON, SignalFrom, Store, Transceiver } from "atom.io/internal"
3
- import { getJsonToken, getUpdateToken, setIntoStore } from "atom.io/internal"
4
- import { parseJson } from "atom.io/json"
3
+ import {
4
+ findInStore,
5
+ getJsonToken,
6
+ getUpdateToken,
7
+ setIntoStore,
8
+ } from "atom.io/internal"
9
+ import type { Canonical } from "atom.io/json"
5
10
  import type { Socket } from "socket.io-client"
6
11
 
7
- /* eslint-disable no-console */
8
-
9
12
  export function pullMutableAtomFamilyMember<
10
13
  T extends Transceiver<any, any, any>,
11
- >(store: Store, socket: Socket, token: AtomIO.MutableAtomToken<T>): () => void {
12
- if (!(`family` in token)) {
13
- console.error(`Token is not a family member:`, token)
14
- return () => {}
15
- }
16
- const { key: familyKey, subKey: serializedSubKey } = token.family
17
- const subKey = parseJson(serializedSubKey)
14
+ K extends Canonical,
15
+ >(
16
+ store: Store,
17
+ socket: Socket,
18
+ family: AtomIO.MutableAtomFamilyToken<T, K>,
19
+ key: NoInfer<K>,
20
+ ): () => void {
21
+ const token = findInStore(store, family, key)
18
22
  socket.on(`init:${token.key}`, (data: AsJSON<T>) => {
19
23
  const jsonToken = getJsonToken(store, token)
20
24
  setIntoStore(store, jsonToken, data)
@@ -23,7 +27,7 @@ export function pullMutableAtomFamilyMember<
23
27
  const trackerToken = getUpdateToken(token)
24
28
  setIntoStore(store, trackerToken, data)
25
29
  })
26
- socket.emit(`sub:${familyKey}`, subKey)
30
+ socket.emit(`sub:${family.key}`, key)
27
31
  return () => {
28
32
  socket.off(`serve:${token.key}`)
29
33
  socket.emit(`unsub:${token.key}`)
@@ -1,44 +1,17 @@
1
1
  import type * as AtomIO from "atom.io"
2
2
  import type { Store } from "atom.io/internal"
3
+ import { findInStore } from "atom.io/internal"
4
+ import type { Canonical } from "atom.io/json"
3
5
  import type { Socket } from "socket.io-client"
4
6
 
5
- import { pullAtomFamilyMember } from "./pull-atom-family-member"
6
- import { pullMutableAtomFamilyMember } from "./pull-mutable-atom-family-member"
7
+ import { pullSelectorRoots } from "./pull-selector-roots"
7
8
 
8
- /* eslint-disable no-console */
9
-
10
- export function pullSelectorFamilyMember<T>(
9
+ export function pullSelectorFamilyMember<T, K extends Canonical>(
11
10
  store: Store,
12
11
  socket: Socket,
13
- token: AtomIO.SelectorToken<T>,
12
+ familyToken: AtomIO.SelectorFamilyToken<T, K>,
13
+ key: NoInfer<K>,
14
14
  ): () => void {
15
- if (!(`family` in token)) {
16
- console.error(`Token is not a family member:`, token)
17
- return () => {}
18
- }
19
- const atomKeys = store.selectorAtoms.getRelatedKeys(token.key)
20
- const unsubscribes: Array<() => void> = []
21
- if (atomKeys) {
22
- for (const atomKey of atomKeys) {
23
- const atom = store.atoms.get(atomKey)
24
- if (!atom) {
25
- continue
26
- }
27
- switch (atom.type) {
28
- case `atom`: {
29
- unsubscribes.push(pullAtomFamilyMember(store, socket, atom))
30
- break
31
- }
32
- case `mutable_atom`: {
33
- unsubscribes.push(pullMutableAtomFamilyMember(store, socket, atom))
34
- break
35
- }
36
- }
37
- }
38
- }
39
- return () => {
40
- for (const unsubscribe of unsubscribes) {
41
- unsubscribe()
42
- }
43
- }
15
+ const token = findInStore(store, familyToken, key)
16
+ return pullSelectorRoots(store, socket, token)
44
17
  }
@@ -0,0 +1,90 @@
1
+ import type { AtomToken, SelectorToken } from "atom.io"
2
+ import type { Store } from "atom.io/internal"
3
+ import { getFamilyOfToken, subscribeToState } from "atom.io/internal"
4
+ import { parseJson } from "atom.io/json"
5
+ import type { Socket } from "socket.io-client"
6
+
7
+ import { pullAtom } from "./pull-atom"
8
+ import { pullAtomFamilyMember } from "./pull-atom-family-member"
9
+ import { pullMutableAtom } from "./pull-mutable-atom"
10
+ import { pullMutableAtomFamilyMember } from "./pull-mutable-atom-family-member"
11
+
12
+ export function pullSelectorRoots(
13
+ store: Store,
14
+ socket: Socket,
15
+ selectorToken: SelectorToken<any>,
16
+ ): () => void {
17
+ const atomSubscriptions = new Map<string, () => void>()
18
+ const clearAtomSubscriptions = () => {
19
+ for (const [, unsub] of atomSubscriptions) unsub()
20
+ atomSubscriptions.clear()
21
+ }
22
+
23
+ const start = () => {
24
+ const atomKeys = store.selectorAtoms.getRelatedKeys(selectorToken.key)
25
+ if (atomKeys) {
26
+ for (const [atomKey, unsub] of atomSubscriptions) {
27
+ if (!atomKeys.has(atomKey)) {
28
+ unsub()
29
+ atomSubscriptions.delete(atomKey)
30
+ }
31
+ }
32
+
33
+ for (const atomKey of atomKeys) {
34
+ if (atomSubscriptions.has(atomKey)) {
35
+ continue
36
+ }
37
+ const atom = store.atoms.get(atomKey) as AtomToken<any, any>
38
+ switch (atom.type) {
39
+ case `atom`: {
40
+ if (atom.family) {
41
+ const { subKey: serializedSubKey } = atom.family
42
+ const subKey = parseJson(serializedSubKey)
43
+ const family = getFamilyOfToken(store, atom)
44
+ atomSubscriptions.set(
45
+ atomKey,
46
+ pullAtomFamilyMember(store, socket, family, subKey),
47
+ )
48
+ } else {
49
+ atomSubscriptions.set(atomKey, pullAtom(store, socket, atom))
50
+ }
51
+ break
52
+ }
53
+ case `mutable_atom`: {
54
+ if (atom.family) {
55
+ const { subKey: serializedSubKey } = atom.family
56
+ const subKey = parseJson(serializedSubKey)
57
+ const family = getFamilyOfToken(store, atom)
58
+ atomSubscriptions.set(
59
+ atomKey,
60
+ pullMutableAtomFamilyMember(store, socket, family, subKey),
61
+ )
62
+ } else {
63
+ atomSubscriptions.set(
64
+ atomKey,
65
+ pullMutableAtom(store, socket, atom),
66
+ )
67
+ }
68
+ break
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ const unsubFromSelector = subscribeToState(
76
+ store,
77
+ selectorToken,
78
+ `pull-watches-dependencies`,
79
+ () => {
80
+ start()
81
+ },
82
+ )
83
+
84
+ start()
85
+
86
+ return () => {
87
+ clearAtomSubscriptions()
88
+ unsubFromSelector()
89
+ }
90
+ }
@@ -2,37 +2,12 @@ import type * as AtomIO from "atom.io"
2
2
  import type { Store } from "atom.io/internal"
3
3
  import type { Socket } from "socket.io-client"
4
4
 
5
- import { pullAtom } from "./pull-atom"
6
- import { pullMutableAtom } from "./pull-mutable-atom"
5
+ import { pullSelectorRoots } from "./pull-selector-roots"
7
6
 
8
7
  export function pullSelector<T>(
9
8
  store: Store,
10
9
  socket: Socket,
11
10
  token: AtomIO.SelectorToken<T>,
12
11
  ): () => void {
13
- const atomKeys = store.selectorAtoms.getRelatedKeys(token.key)
14
- const unsubscribes: Array<() => void> = []
15
- if (atomKeys) {
16
- for (const atomKey of atomKeys) {
17
- const atom = store.atoms.get(atomKey)
18
- if (!atom) {
19
- continue
20
- }
21
- switch (atom.type) {
22
- case `atom`: {
23
- unsubscribes.push(pullAtom(store, socket, atom))
24
- break
25
- }
26
- case `mutable_atom`: {
27
- unsubscribes.push(pullMutableAtom(store, socket, atom))
28
- break
29
- }
30
- }
31
- }
32
- }
33
- return () => {
34
- for (const unsubscribe of unsubscribes) {
35
- unsubscribe()
36
- }
37
- }
12
+ return pullSelectorRoots(store, socket, token)
38
13
  }
@@ -1,7 +1,9 @@
1
1
  import type { WritableToken } from "atom.io"
2
2
  import type { Store } from "atom.io/internal"
3
- import { subscribeToState } from "atom.io/internal"
3
+ import { setIntoStore, subscribeToState } from "atom.io/internal"
4
4
  import type { Json } from "atom.io/json"
5
+ import { mutexAtoms } from "atom.io/realtime/mutex-store"
6
+ import { employSocket } from "atom.io/realtime-server/employ-socket"
5
7
  import type { Socket } from "socket.io-client"
6
8
 
7
9
  export function pushState<J extends Json.Serializable>(
@@ -9,12 +11,38 @@ export function pushState<J extends Json.Serializable>(
9
11
  socket: Socket,
10
12
  token: WritableToken<J>,
11
13
  ): () => void {
12
- socket.emit(`claim:${token.key}`)
13
- subscribeToState(store, token, `push`, ({ newValue }) => {
14
+ const publish = (newValue: J) => {
14
15
  socket.emit(`pub:${token.key}`, newValue)
15
- })
16
+ }
17
+
18
+ const subscriptions = new Set<() => void>()
19
+ const clearSubscriptions = () => {
20
+ for (const unsub of subscriptions) unsub()
21
+ subscriptions.clear()
22
+ }
23
+
24
+ const init = () => {
25
+ subscriptions.add(
26
+ employSocket(socket, `claim-result:${token.key}`, (success: boolean) => {
27
+ if (!success) return
28
+
29
+ clearSubscriptions()
30
+ setIntoStore(store, mutexAtoms, token.key, true)
31
+ subscriptions.add(
32
+ subscribeToState(store, token, `push`, ({ newValue }) => {
33
+ publish(newValue)
34
+ }),
35
+ )
36
+ }),
37
+ )
38
+
39
+ socket.emit(`claim:${token.key}`)
40
+ }
41
+
42
+ init()
43
+
16
44
  return () => {
17
- socket.off(`pub:${token.key}`)
45
+ clearSubscriptions()
18
46
  socket.emit(`unclaim:${token.key}`)
19
47
  }
20
48
  }
@@ -1,5 +1,5 @@
1
1
  import * as AtomIO from "atom.io"
2
- import { persistSync } from "atom.io/web"
2
+ import { storageSync } from "atom.io/web"
3
3
 
4
4
  export const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined> =
5
5
  AtomIO.atom<string | undefined>({
@@ -16,8 +16,5 @@ export const myUsernameState: AtomIO.RegularAtomToken<string | null> =
16
16
  AtomIO.atom<string | null>({
17
17
  key: `myName`,
18
18
  default: null,
19
- effects:
20
- typeof window === `undefined`
21
- ? []
22
- : [persistSync(window.localStorage, JSON, `myUsername`)],
19
+ effects: [storageSync(globalThis.localStorage, JSON, `myUsername`)],
23
20
  })
@@ -1,4 +1,3 @@
1
- export * from "./on-mount"
2
1
  export * from "./realtime-context"
3
2
  export * from "./use-pull-atom"
4
3
  export * from "./use-pull-atom-family-member"
@@ -7,5 +6,7 @@ export * from "./use-pull-mutable-family-member"
7
6
  export * from "./use-pull-selector"
8
7
  export * from "./use-pull-selector-family-member"
9
8
  export * from "./use-push"
9
+ export * from "./use-realtime-service"
10
10
  export * from "./use-server-action"
11
+ export * from "./use-single-effect"
11
12
  export * from "./use-sync-continuity"
@@ -3,12 +3,14 @@ import * as RTC from "atom.io/realtime-client"
3
3
  import * as React from "react"
4
4
  import type { Socket } from "socket.io-client"
5
5
 
6
+ export type RealtimeServiceCounter = {
7
+ consumerCount: number
8
+ dispose: () => void
9
+ }
10
+
6
11
  export type RealtimeReactStore = {
7
12
  socket: Socket | null
8
- services: Map<
9
- string,
10
- [consumerCount: number, dispose: (() => void) | undefined]
11
- > | null
13
+ services: Map<string, RealtimeServiceCounter> | null
12
14
  }
13
15
 
14
16
  export const RealtimeContext: React.Context<RealtimeReactStore> =
@@ -21,7 +23,9 @@ export const RealtimeProvider: React.FC<{
21
23
  children: React.ReactNode
22
24
  socket: Socket | null
23
25
  }> = ({ children, socket }) => {
24
- const services = React.useRef(new Map<string, [number, () => void]>()).current
26
+ const services = React.useRef(
27
+ new Map<string, RealtimeServiceCounter>(),
28
+ ).current
25
29
  const setMyId = useI(RTC.myIdState__INTERNAL)
26
30
  React.useEffect(() => {
27
31
  setMyId(socket?.id)
@@ -10,12 +10,11 @@ import { useRealtimeService } from "./use-realtime-service"
10
10
  export function usePullAtomFamilyMember<
11
11
  J extends Json.Serializable,
12
12
  K extends Canonical,
13
- Key extends K,
14
- >(family: AtomIO.RegularAtomFamilyToken<J, K>, subKey: Key): J {
13
+ >(family: AtomIO.RegularAtomFamilyToken<J, K>, subKey: NoInfer<K>): J {
15
14
  const store = React.useContext(StoreContext)
16
15
  const token = findInStore(store, family, subKey)
17
16
  useRealtimeService(`pull:${token.key}`, (socket) =>
18
- RTC.pullAtomFamilyMember(store, socket, token),
17
+ RTC.pullAtomFamilyMember(store, socket, family, subKey),
19
18
  )
20
19
  return useO(token)
21
20
  }
@@ -11,12 +11,11 @@ import { useRealtimeService } from "./use-realtime-service"
11
11
  export function usePullMutableAtomFamilyMember<
12
12
  T extends Transceiver<any, any, any>,
13
13
  K extends Canonical,
14
- Key extends K,
15
- >(familyToken: AtomIO.MutableAtomFamilyToken<T, K>, key: Key): T {
14
+ >(familyToken: AtomIO.MutableAtomFamilyToken<T, K>, key: NoInfer<K>): T {
16
15
  const store = React.useContext(StoreContext)
17
16
  const token = findInStore(store, familyToken, key)
18
17
  useRealtimeService(`pull:${token.key}`, (socket) =>
19
- RTC.pullMutableAtomFamilyMember(store, socket, token),
18
+ RTC.pullMutableAtomFamilyMember(store, socket, familyToken, key),
20
19
  )
21
20
  return useO(token)
22
21
  }