atom.io 0.46.4 → 0.46.6

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 (46) hide show
  1. package/dist/realtime/index.d.ts +7 -6
  2. package/dist/realtime/index.d.ts.map +1 -1
  3. package/dist/realtime/index.js +19 -10
  4. package/dist/realtime/index.js.map +1 -1
  5. package/dist/realtime-client/index.d.ts +13 -13
  6. package/dist/realtime-client/index.d.ts.map +1 -1
  7. package/dist/realtime-client/index.js +10 -3
  8. package/dist/realtime-client/index.js.map +1 -1
  9. package/dist/realtime-react/index.d.ts +12 -3
  10. package/dist/realtime-react/index.d.ts.map +1 -1
  11. package/dist/realtime-react/index.js +26 -3
  12. package/dist/realtime-react/index.js.map +1 -1
  13. package/dist/realtime-server/index.d.ts +50 -42
  14. package/dist/realtime-server/index.d.ts.map +1 -1
  15. package/dist/realtime-server/index.js +132 -101
  16. package/dist/realtime-server/index.js.map +1 -1
  17. package/dist/realtime-testing/index.js +2 -2
  18. package/dist/realtime-testing/index.js.map +1 -1
  19. package/package.json +20 -19
  20. package/src/realtime/realtime-continuity.ts +2 -2
  21. package/src/realtime/shared-room-store.ts +38 -17
  22. package/src/realtime/socket-interface.ts +1 -1
  23. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +3 -1
  24. package/src/realtime-client/continuity/use-conceal-state.ts +2 -1
  25. package/src/realtime-client/pull-atom-family-member.ts +1 -1
  26. package/src/realtime-client/pull-atom.ts +1 -1
  27. package/src/realtime-client/pull-mutable-atom-family-member.ts +1 -1
  28. package/src/realtime-client/pull-mutable-atom.ts +1 -1
  29. package/src/realtime-client/pull-selector-family-member.ts +1 -1
  30. package/src/realtime-client/pull-selector-roots.ts +1 -1
  31. package/src/realtime-client/pull-selector.ts +1 -1
  32. package/src/realtime-client/push-state.ts +1 -1
  33. package/src/realtime-client/realtime-client-stores/client-main-store.ts +16 -3
  34. package/src/realtime-client/sync-continuity.ts +1 -2
  35. package/src/realtime-react/use-realtime-rooms.ts +54 -6
  36. package/src/realtime-server/continuity/provide-outcomes.ts +1 -1
  37. package/src/realtime-server/ipc-sockets/parent-socket.ts +11 -15
  38. package/src/realtime-server/provide-rooms.ts +64 -16
  39. package/src/realtime-server/realtime-family-provider.ts +51 -35
  40. package/src/realtime-server/realtime-mutable-family-provider.ts +50 -34
  41. package/src/realtime-server/realtime-mutable-provider.ts +4 -4
  42. package/src/realtime-server/realtime-state-provider.ts +7 -7
  43. package/src/realtime-server/realtime-state-receiver.ts +2 -2
  44. package/src/realtime-server/server-config.ts +20 -13
  45. package/src/realtime-server/server-socket-state.ts +3 -3
  46. package/src/realtime-testing/setup-realtime-test.tsx +2 -2
@@ -14,7 +14,7 @@ import type { ServerConfig } from "."
14
14
  export type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>
15
15
  export function realtimeAtomFamilyProvider({
16
16
  socket,
17
- userKey,
17
+ consumer,
18
18
  store = IMPLICIT.STORE,
19
19
  }: ServerConfig) {
20
20
  return function familyProvider<
@@ -22,8 +22,17 @@ export function realtimeAtomFamilyProvider({
22
22
  K extends Canonical,
23
23
  >(
24
24
  family: AtomIO.RegularAtomFamilyToken<J, K>,
25
- index: AtomIO.ReadableToken<Iterable<NoInfer<K>>>,
25
+ index: AtomIO.ReadableToken<Iterable<NoInfer<K>>> | Iterable<NoInfer<K>>,
26
26
  ): () => void {
27
+ const [dynamicIndex, staticIndex]:
28
+ | [AtomIO.ReadableToken<Iterable<NoInfer<K>>>, undefined]
29
+ | [undefined, Iterable<NoInfer<K>>] = (() => {
30
+ if (typeof index === `object` && `key` in index && `type` in index) {
31
+ return [index, undefined] as const
32
+ }
33
+ return [undefined, index] as const
34
+ })()
35
+
27
36
  const coreSubscriptions = new Set<() => void>()
28
37
  const clearCoreSubscriptions = () => {
29
38
  for (const unsub of coreSubscriptions) unsub()
@@ -70,7 +79,7 @@ export function realtimeAtomFamilyProvider({
70
79
  store.logger.info(
71
80
  `🙈`,
72
81
  `user`,
73
- userKey,
82
+ consumer,
74
83
  `unsubscribed from state "${token.key}"`,
75
84
  )
76
85
  fillUnsubRequest(token.key)
@@ -91,18 +100,23 @@ export function realtimeAtomFamilyProvider({
91
100
  store.logger.info(
92
101
  `👀`,
93
102
  `user`,
94
- userKey,
103
+ consumer,
95
104
  `can subscribe to family "${family.key}"`,
96
105
  )
97
106
  coreSubscriptions.add(
98
107
  employSocket(socket, `sub:${family.key}`, (subKey: K) => {
99
- const exposedSubKeys = getFromStore(store, index)
108
+ let exposedSubKeys: Iterable<K>
109
+ if (dynamicIndex) {
110
+ exposedSubKeys = getFromStore(store, dynamicIndex)
111
+ } else {
112
+ exposedSubKeys = staticIndex
113
+ }
100
114
  const shouldExpose = isAvailable(exposedSubKeys, subKey)
101
115
  if (shouldExpose) {
102
116
  store.logger.info(
103
117
  `👀`,
104
118
  `user`,
105
- userKey,
119
+ consumer,
106
120
  `is approved for a subscription to`,
107
121
  subKey,
108
122
  `in family "${family.key}"`,
@@ -112,7 +126,7 @@ export function realtimeAtomFamilyProvider({
112
126
  store.logger.info(
113
127
  `❌`,
114
128
  `user`,
115
- userKey,
129
+ consumer,
116
130
  `is denied for a subscription to`,
117
131
  subKey,
118
132
  `in family "${family.key}"`,
@@ -122,35 +136,37 @@ export function realtimeAtomFamilyProvider({
122
136
  }
123
137
  }),
124
138
  )
125
- coreSubscriptions.add(
126
- subscribeToState(
127
- store,
128
- index,
129
- `expose-family:${family.key}:${socket.id}`,
130
- ({ newValue: newExposedSubKeys }) => {
131
- store.logger.info(
132
- `👀`,
133
- `user`,
134
- userKey,
135
- `has the following keys available for family "${family.key}"`,
136
- newExposedSubKeys,
137
- )
138
- for (const subKey of newExposedSubKeys) {
139
- if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
140
- store.logger.info(
141
- `👀`,
142
- `user`,
143
- userKey,
144
- `is retroactively approved for a subscription to`,
145
- subKey,
146
- `in family "${family.key}"`,
147
- )
148
- exposeFamilyMembers(subKey)
139
+ if (dynamicIndex) {
140
+ coreSubscriptions.add(
141
+ subscribeToState(
142
+ store,
143
+ dynamicIndex,
144
+ `expose-family:${family.key}:${socket.id}`,
145
+ ({ newValue: newExposedSubKeys }) => {
146
+ store.logger.info(
147
+ `👀`,
148
+ `user`,
149
+ consumer,
150
+ `has the following keys available for family "${family.key}"`,
151
+ newExposedSubKeys,
152
+ )
153
+ for (const subKey of newExposedSubKeys) {
154
+ if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
155
+ store.logger.info(
156
+ `👀`,
157
+ `user`,
158
+ consumer,
159
+ `is retroactively approved for a subscription to`,
160
+ subKey,
161
+ `in family "${family.key}"`,
162
+ )
163
+ exposeFamilyMembers(subKey)
164
+ }
149
165
  }
150
- }
151
- },
152
- ),
153
- )
166
+ },
167
+ ),
168
+ )
169
+ }
154
170
  }
155
171
 
156
172
  start()
@@ -31,7 +31,7 @@ export type MutableFamilyProvider = ReturnType<
31
31
  >
32
32
  export function realtimeMutableFamilyProvider({
33
33
  socket,
34
- userKey,
34
+ consumer,
35
35
  store = IMPLICIT.STORE,
36
36
  }: ServerConfig) {
37
37
  return function mutableFamilyProvider<
@@ -39,8 +39,17 @@ export function realtimeMutableFamilyProvider({
39
39
  K extends Canonical,
40
40
  >(
41
41
  family: AtomIO.MutableAtomFamilyToken<T, K>,
42
- index: AtomIO.ReadableToken<Iterable<NoInfer<K>>>,
42
+ index: AtomIO.ReadableToken<Iterable<NoInfer<K>>> | Iterable<NoInfer<K>>,
43
43
  ): () => void {
44
+ const [dynamicIndex, staticIndex]:
45
+ | [AtomIO.ReadableToken<Iterable<NoInfer<K>>>, undefined]
46
+ | [undefined, Iterable<NoInfer<K>>] = (() => {
47
+ if (typeof index === `object` && `key` in index && `type` in index) {
48
+ return [index, undefined] as const
49
+ }
50
+ return [undefined, index] as const
51
+ })()
52
+
44
53
  const coreSubscriptions = new Set<() => void>()
45
54
  const clearCoreSubscriptions = () => {
46
55
  for (const unsub of coreSubscriptions) unsub()
@@ -95,18 +104,23 @@ export function realtimeMutableFamilyProvider({
95
104
  store.logger.info(
96
105
  `👀`,
97
106
  `user`,
98
- userKey,
107
+ consumer,
99
108
  `can subscribe to family "${family.key}"`,
100
109
  )
101
110
  coreSubscriptions.add(
102
111
  employSocket(socket, `sub:${family.key}`, (subKey: K) => {
103
- const exposedSubKeys = getFromStore(store, index)
112
+ let exposedSubKeys: Iterable<K>
113
+ if (dynamicIndex) {
114
+ exposedSubKeys = getFromStore(store, dynamicIndex)
115
+ } else {
116
+ exposedSubKeys = staticIndex
117
+ }
104
118
  const shouldExpose = isAvailable(exposedSubKeys, subKey)
105
119
  if (shouldExpose) {
106
120
  store.logger.info(
107
121
  `👀`,
108
122
  `user`,
109
- userKey,
123
+ consumer,
110
124
  `is approved for a subscription to`,
111
125
  subKey,
112
126
  `in family "${family.key}"`,
@@ -116,7 +130,7 @@ export function realtimeMutableFamilyProvider({
116
130
  store.logger.info(
117
131
  `❌`,
118
132
  `user`,
119
- userKey,
133
+ consumer,
120
134
  `is denied for a subscription to`,
121
135
  subKey,
122
136
  `in family "${family.key}"`,
@@ -126,35 +140,37 @@ export function realtimeMutableFamilyProvider({
126
140
  }
127
141
  }),
128
142
  )
129
- coreSubscriptions.add(
130
- subscribeToState(
131
- store,
132
- index,
133
- `expose-family:${family.key}:${socket.id}`,
134
- ({ newValue: newExposedSubKeys }) => {
135
- store.logger.info(
136
- `👀`,
137
- `user`,
138
- userKey,
139
- `has the following keys available for family "${family.key}"`,
140
- newExposedSubKeys,
141
- )
142
- for (const subKey of newExposedSubKeys) {
143
- if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
144
- store.logger.info(
145
- `👀`,
146
- `user`,
147
- userKey,
148
- `is retroactively approved for a subscription to`,
149
- subKey,
150
- `in family "${family.key}"`,
151
- )
152
- exposeFamilyMembers(subKey)
143
+ if (dynamicIndex) {
144
+ coreSubscriptions.add(
145
+ subscribeToState(
146
+ store,
147
+ dynamicIndex,
148
+ `expose-family:${family.key}:${socket.id}`,
149
+ ({ newValue: newExposedSubKeys }) => {
150
+ store.logger.info(
151
+ `👀`,
152
+ `user`,
153
+ consumer,
154
+ `has the following keys available for family "${family.key}"`,
155
+ newExposedSubKeys,
156
+ )
157
+ for (const subKey of newExposedSubKeys) {
158
+ if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
159
+ store.logger.info(
160
+ `👀`,
161
+ `user`,
162
+ consumer,
163
+ `is retroactively approved for a subscription to`,
164
+ subKey,
165
+ `in family "${family.key}"`,
166
+ )
167
+ exposeFamilyMembers(subKey)
168
+ }
153
169
  }
154
- }
155
- },
156
- ),
157
- )
170
+ },
171
+ ),
172
+ )
173
+ }
158
174
  }
159
175
 
160
176
  start()
@@ -15,7 +15,7 @@ import type { ServerConfig } from "."
15
15
  export type MutableProvider = ReturnType<typeof realtimeMutableProvider>
16
16
  export function realtimeMutableProvider({
17
17
  socket,
18
- userKey,
18
+ consumer,
19
19
  store = IMPLICIT.STORE,
20
20
  }: ServerConfig) {
21
21
  return function mutableProvider<
@@ -34,7 +34,7 @@ export function realtimeMutableProvider({
34
34
  store.logger.info(
35
35
  `👀`,
36
36
  `user`,
37
- userKey,
37
+ consumer,
38
38
  `can subscribe to state "${token.key}"`,
39
39
  )
40
40
  subscriptions.add(
@@ -42,7 +42,7 @@ export function realtimeMutableProvider({
42
42
  store.logger.info(
43
43
  `👀`,
44
44
  `user`,
45
- userKey,
45
+ consumer,
46
46
  `subscribes to state "${token.key}"`,
47
47
  )
48
48
  clearSubscriptions()
@@ -62,7 +62,7 @@ export function realtimeMutableProvider({
62
62
  store.logger.info(
63
63
  `🙈`,
64
64
  `user`,
65
- userKey,
65
+ consumer,
66
66
  `unsubscribes from state "${token.key}"`,
67
67
  )
68
68
  clearSubscriptions()
@@ -17,10 +17,10 @@ function isReadableToken(input: unknown): input is AtomIO.ReadableToken<any> {
17
17
  export type StateProvider = ReturnType<typeof realtimeStateProvider>
18
18
  export function realtimeStateProvider({
19
19
  socket,
20
- userKey,
20
+ consumer,
21
21
  store = IMPLICIT.STORE,
22
22
  }: ServerConfig) {
23
- store.logger.info(`🔌`, `user`, userKey, `initialized state provider`)
23
+ store.logger.info(`🔌`, `user`, consumer, `initialized state provider`)
24
24
  return function stateProvider<C extends Json.Serializable, S extends C>(
25
25
  clientToken: AtomIO.WritableToken<C>,
26
26
  serverData:
@@ -40,7 +40,7 @@ export function realtimeStateProvider({
40
40
  store.logger.info(
41
41
  `👀`,
42
42
  `user`,
43
- userKey,
43
+ consumer,
44
44
  `will be served`,
45
45
  serverData,
46
46
  `as "${clientToken.key}"`,
@@ -49,7 +49,7 @@ export function realtimeStateProvider({
49
49
  store.logger.info(
50
50
  `👀`,
51
51
  `user`,
52
- userKey,
52
+ consumer,
53
53
  `can subscribe to state "${serverData.key}" as "${clientToken.key}"`,
54
54
  )
55
55
  }
@@ -59,7 +59,7 @@ export function realtimeStateProvider({
59
59
  store.logger.info(
60
60
  `👀`,
61
61
  `user`,
62
- userKey,
62
+ consumer,
63
63
  `requests`,
64
64
  `"${clientToken.key}"`,
65
65
  )
@@ -68,7 +68,7 @@ export function realtimeStateProvider({
68
68
  store.logger.info(
69
69
  `👀`,
70
70
  `user`,
71
- userKey,
71
+ consumer,
72
72
  `subscribes to state "${serverData.key}"`,
73
73
  clientToken === serverData
74
74
  ? `directly`
@@ -94,7 +94,7 @@ export function realtimeStateProvider({
94
94
  store.logger.info(
95
95
  `🙈`,
96
96
  `user`,
97
- userKey,
97
+ consumer,
98
98
  `unsubscribes from state "${serverData.key}", served`,
99
99
  clientToken === serverData
100
100
  ? `directly`
@@ -17,7 +17,7 @@ import type { ServerConfig } from "."
17
17
  export type StateReceiver = ReturnType<typeof realtimeStateReceiver>
18
18
  export function realtimeStateReceiver({
19
19
  socket,
20
- userKey,
20
+ consumer,
21
21
  store = IMPLICIT.STORE,
22
22
  }: ServerConfig) {
23
23
  return function stateReceiver<S extends Json.Serializable, C extends S>(
@@ -43,7 +43,7 @@ export function realtimeStateReceiver({
43
43
  store.logger.error(
44
44
  `❌`,
45
45
  `user`,
46
- userKey,
46
+ consumer,
47
47
  `attempted to publish invalid value`,
48
48
  newValue,
49
49
  `to state "${serverToken.key}"`,
@@ -12,21 +12,27 @@ import {
12
12
  IMPLICIT,
13
13
  setIntoStore,
14
14
  } from "atom.io/internal"
15
- import type { Socket, SocketKey, UserKey } from "atom.io/realtime"
15
+ import type { RoomKey, Socket, SocketKey, UserKey } from "atom.io/realtime"
16
+ import { myUserKeyAtom } from "atom.io/realtime-client"
16
17
  import type { Server } from "socket.io"
17
18
 
18
19
  import { realtimeStateProvider } from "./realtime-state-provider"
19
20
  import type { SocketSystemHierarchy } from "./server-socket-state"
20
21
  import {
22
+ onlineUsersAtom,
21
23
  socketAtoms,
22
24
  socketKeysAtom,
23
- userKeysAtom,
24
25
  usersOfSockets,
25
26
  } from "./server-socket-state"
26
27
 
27
28
  export type ServerConfig = {
28
29
  socket: Socket
29
- userKey: UserKey
30
+ consumer: RoomKey | UserKey
31
+ store?: RootStore
32
+ }
33
+ export type UserServerConfig = {
34
+ socket: Socket
35
+ consumer: UserKey
30
36
  store?: RootStore
31
37
  }
32
38
 
@@ -57,7 +63,7 @@ export type Handshake = {
57
63
  export function realtime(
58
64
  server: Server,
59
65
  auth: (handshake: Handshake) => Loadable<Error | UserKey>,
60
- onConnect: (config: ServerConfig) => Loadable<() => Loadable<void>>,
66
+ onConnect: (config: UserServerConfig) => Loadable<() => Loadable<void>>,
61
67
  store: RootStore = IMPLICIT.STORE,
62
68
  ): () => Promise<void> {
63
69
  const socketRealm = new Realm<SocketSystemHierarchy>(store)
@@ -76,24 +82,21 @@ export function realtime(
76
82
  editRelationsInStore(store, usersOfSockets, (relations) => {
77
83
  relations.set(userClaim, socketClaim)
78
84
  })
79
- setIntoStore(store, userKeysAtom, (index) => index.add(userClaim))
85
+ setIntoStore(store, onlineUsersAtom, (index) => index.add(userClaim))
80
86
  setIntoStore(store, socketKeysAtom, (index) => index.add(socketClaim))
81
87
  next()
82
88
  })
83
89
  .on(`connection`, async (socket) => {
84
90
  const socketKey = `socket::${socket.id}` satisfies SocketKey
85
- const userKeyState = findRelationsInStore(
91
+ const userKeySelector = findRelationsInStore(
86
92
  store,
87
93
  usersOfSockets,
88
94
  socketKey,
89
95
  ).userKeyOfSocket
90
- const userKey = getFromStore(store, userKeyState)!
91
- const serverConfig: ServerConfig = { store, socket, userKey }
96
+ const userKey = getFromStore(store, userKeySelector)!
97
+ const serverConfig: UserServerConfig = { store, socket, consumer: userKey }
92
98
  const provideState = realtimeStateProvider(serverConfig)
93
- const unsubFromMyUserKey = provideState(
94
- { key: `myUserKey`, type: `atom` },
95
- userKey,
96
- )
99
+ const unsubFromMyUserKey = provideState(myUserKeyAtom, userKey)
97
100
 
98
101
  const disposeServices = await onConnect(serverConfig)
99
102
 
@@ -104,7 +107,11 @@ export function realtime(
104
107
  editRelationsInStore(store, usersOfSockets, (rel) =>
105
108
  rel.delete(socketKey),
106
109
  )
107
- setIntoStore(store, userKeysAtom, (keys) => (keys.delete(userKey), keys))
110
+ setIntoStore(
111
+ store,
112
+ onlineUsersAtom,
113
+ (keys) => (keys.delete(userKey), keys),
114
+ )
108
115
  setIntoStore(
109
116
  store,
110
117
  socketKeysAtom,
@@ -25,11 +25,11 @@ export const socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey> =
25
25
  })
26
26
 
27
27
  export const socketKeysAtom: MutableAtomToken<UList<SocketKey>> = mutableAtom({
28
- key: `socketsIndex`,
28
+ key: `socketKeys`,
29
29
  class: UList,
30
30
  })
31
- export const userKeysAtom: MutableAtomToken<UList<UserKey>> = mutableAtom({
32
- key: `usersIndex`,
31
+ export const onlineUsersAtom: MutableAtomToken<UList<UserKey>> = mutableAtom({
32
+ key: `onlineUsers`,
33
33
  class: UList,
34
34
  })
35
35
  export const usersOfSockets: JoinToken<
@@ -133,7 +133,7 @@ export const setupRealtimeTestServer = (
133
133
  return new Error(`Authentication error`)
134
134
  },
135
135
  (config) => {
136
- const { socket, userKey } = config
136
+ const { socket, consumer: userKey } = config
137
137
  function enableLogging() {
138
138
  prefixLogger(silo.store, `server`)
139
139
  socket.onAny((event, ...args) => {
@@ -148,7 +148,7 @@ export const setupRealtimeTestServer = (
148
148
  }
149
149
  const disposeServices = options.server({
150
150
  socket: config.socket,
151
- userKey: config.userKey,
151
+ userKey: config.consumer,
152
152
  enableLogging,
153
153
  silo,
154
154
  })