atom.io 0.46.8 → 0.46.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/realtime/index.d.ts +2 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +2 -2
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +110 -70
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +2 -2
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +9 -5
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +4 -2
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +83 -82
- package/dist/realtime-server/index.js.map +1 -1
- package/package.json +9 -9
- package/src/realtime/employ-socket.ts +11 -1
- package/src/realtime-client/create-subscriber.ts +45 -0
- package/src/realtime-client/pull-atom-family-member.ts +17 -10
- package/src/realtime-client/pull-atom.ts +13 -10
- package/src/realtime-client/pull-mutable-atom-family-member.ts +26 -13
- package/src/realtime-client/pull-mutable-atom.ts +24 -12
- package/src/realtime-client/pull-selector-roots.ts +1 -5
- package/src/realtime-client/push-state.ts +17 -28
- package/src/realtime-client/realtime-client-stores/client-main-store.ts +27 -4
- package/src/realtime-react/use-pull-mutable-family-member.ts +3 -3
- package/src/realtime-react/use-realtime-rooms.ts +11 -8
- package/src/realtime-server/ipc-sockets/child-socket.ts +2 -0
- package/src/realtime-server/ipc-sockets/parent-socket.ts +17 -11
- package/src/realtime-server/provide-rooms.ts +35 -35
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import type * as AtomIO from "atom.io"
|
|
2
2
|
import { setIntoStore, type Store } from "atom.io/internal"
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
|
-
import type
|
|
4
|
+
import { employSocket, type Socket } from "atom.io/realtime"
|
|
5
|
+
|
|
6
|
+
import { createSubscriber } from "./create-subscriber"
|
|
5
7
|
|
|
6
8
|
export function pullAtom<J extends Json.Serializable>(
|
|
7
9
|
store: Store,
|
|
8
10
|
socket: Socket,
|
|
9
11
|
token: AtomIO.RegularAtomToken<J, any, any>,
|
|
10
12
|
): () => void {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
return createSubscriber(socket, token.key, (key) => {
|
|
14
|
+
const stopWatching = employSocket(socket, `serve:${key}`, (data: J) => {
|
|
15
|
+
setIntoStore(store, token, data)
|
|
16
|
+
})
|
|
17
|
+
socket.emit(`sub:${token.key}`)
|
|
18
|
+
return () => {
|
|
19
|
+
socket.emit(`unsub:${key}`)
|
|
20
|
+
stopWatching()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
20
23
|
}
|
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
setIntoStore,
|
|
8
8
|
} from "atom.io/internal"
|
|
9
9
|
import type { Canonical } from "atom.io/json"
|
|
10
|
-
import type
|
|
10
|
+
import { employSocket, type Socket } from "atom.io/realtime"
|
|
11
|
+
|
|
12
|
+
import { createSubscriber } from "./create-subscriber"
|
|
11
13
|
|
|
12
14
|
export function pullMutableAtomFamilyMember<
|
|
13
15
|
T extends Transceiver<any, any, any>,
|
|
@@ -19,17 +21,28 @@ export function pullMutableAtomFamilyMember<
|
|
|
19
21
|
key: NoInfer<K>,
|
|
20
22
|
): () => void {
|
|
21
23
|
const token = findInStore(store, family, key)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const jsonToken = getJsonToken(store, token)
|
|
25
|
+
const trackerToken = getUpdateToken(token)
|
|
26
|
+
return createSubscriber(socket, token.key, () => {
|
|
27
|
+
const stopWatchingForInit = employSocket(
|
|
28
|
+
socket,
|
|
29
|
+
`init:${token.key}`,
|
|
30
|
+
(data: AsJSON<T>) => {
|
|
31
|
+
setIntoStore(store, jsonToken, data)
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
const stopWatchingForUpdate = employSocket(
|
|
35
|
+
socket,
|
|
36
|
+
`next:${token.key}`,
|
|
37
|
+
(data: SignalFrom<T>) => {
|
|
38
|
+
setIntoStore(store, trackerToken, data)
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
socket.emit(`sub:${family.key}`, key)
|
|
42
|
+
return () => {
|
|
43
|
+
socket.emit(`unsub:${token.key}`)
|
|
44
|
+
stopWatchingForInit()
|
|
45
|
+
stopWatchingForUpdate()
|
|
46
|
+
}
|
|
29
47
|
})
|
|
30
|
-
socket.emit(`sub:${family.key}`, key)
|
|
31
|
-
return () => {
|
|
32
|
-
socket.off(`serve:${token.key}`)
|
|
33
|
-
socket.emit(`unsub:${token.key}`)
|
|
34
|
-
}
|
|
35
48
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type * as AtomIO from "atom.io"
|
|
2
2
|
import type { AsJSON, SignalFrom, Store, Transceiver } from "atom.io/internal"
|
|
3
3
|
import { getJsonToken, getUpdateToken, setIntoStore } from "atom.io/internal"
|
|
4
|
-
import type
|
|
4
|
+
import { employSocket, type Socket } from "atom.io/realtime"
|
|
5
|
+
|
|
6
|
+
import { createSubscriber } from "./create-subscriber"
|
|
5
7
|
|
|
6
8
|
export function pullMutableAtom<T extends Transceiver<any, any, any>>(
|
|
7
9
|
store: Store,
|
|
@@ -10,16 +12,26 @@ export function pullMutableAtom<T extends Transceiver<any, any, any>>(
|
|
|
10
12
|
): () => void {
|
|
11
13
|
const jsonToken = getJsonToken(store, token)
|
|
12
14
|
const updateToken = getUpdateToken(token)
|
|
13
|
-
socket
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
return createSubscriber(socket, token.key, () => {
|
|
16
|
+
const stopWatchingForInit = employSocket(
|
|
17
|
+
socket,
|
|
18
|
+
`init:${token.key}`,
|
|
19
|
+
(data: AsJSON<T>) => {
|
|
20
|
+
setIntoStore(store, jsonToken, data)
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
const stopWatchingForUpdate = employSocket(
|
|
24
|
+
socket,
|
|
25
|
+
`next:${token.key}`,
|
|
26
|
+
(data: SignalFrom<T>) => {
|
|
27
|
+
setIntoStore(store, updateToken, data)
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
socket.emit(`sub:${token.key}`)
|
|
31
|
+
return () => {
|
|
32
|
+
socket.emit(`unsub:${token.key}`)
|
|
33
|
+
stopWatchingForInit()
|
|
34
|
+
stopWatchingForUpdate()
|
|
35
|
+
}
|
|
18
36
|
})
|
|
19
|
-
socket.emit(`sub:${token.key}`)
|
|
20
|
-
return () => {
|
|
21
|
-
socket.off(`init:${token.key}`)
|
|
22
|
-
socket.off(`next:${token.key}`)
|
|
23
|
-
socket.emit(`unsub:${token.key}`)
|
|
24
|
-
}
|
|
25
37
|
}
|
|
@@ -15,10 +15,6 @@ export function pullSelectorRoots(
|
|
|
15
15
|
selectorToken: SelectorToken<any>,
|
|
16
16
|
): () => void {
|
|
17
17
|
const atomSubscriptions = new Map<string, () => void>()
|
|
18
|
-
const clearAtomSubscriptions = () => {
|
|
19
|
-
for (const [, unsub] of atomSubscriptions) unsub()
|
|
20
|
-
atomSubscriptions.clear()
|
|
21
|
-
}
|
|
22
18
|
|
|
23
19
|
const start = () => {
|
|
24
20
|
const atomKeys = store.selectorAtoms.getRelatedKeys(selectorToken.key)
|
|
@@ -84,7 +80,7 @@ export function pullSelectorRoots(
|
|
|
84
80
|
start()
|
|
85
81
|
|
|
86
82
|
return () => {
|
|
87
|
-
|
|
83
|
+
for (const [, unsub] of atomSubscriptions) unsub()
|
|
88
84
|
unsubFromSelector()
|
|
89
85
|
}
|
|
90
86
|
}
|
|
@@ -5,43 +5,32 @@ import type { Json } from "atom.io/json"
|
|
|
5
5
|
import type { Socket } from "atom.io/realtime"
|
|
6
6
|
import { employSocket, mutexAtoms } from "atom.io/realtime"
|
|
7
7
|
|
|
8
|
+
import { createSubscriber } from "./create-subscriber"
|
|
9
|
+
|
|
8
10
|
export function pushState<J extends Json.Serializable>(
|
|
9
11
|
store: Store,
|
|
10
12
|
socket: Socket,
|
|
11
13
|
token: WritableToken<J>,
|
|
12
14
|
): () => void {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const clearSubscriptions = () => {
|
|
19
|
-
for (const unsub of subscriptions) unsub()
|
|
20
|
-
subscriptions.clear()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const init = () => {
|
|
24
|
-
subscriptions.add(
|
|
25
|
-
employSocket(socket, `claim-result:${token.key}`, (success: boolean) => {
|
|
15
|
+
return createSubscriber(socket, `push:${token.key}`, () => {
|
|
16
|
+
let stopWatching = employSocket(
|
|
17
|
+
socket,
|
|
18
|
+
`claim-result:${token.key}`,
|
|
19
|
+
(success: boolean) => {
|
|
26
20
|
if (!success) return
|
|
27
|
-
|
|
28
|
-
clearSubscriptions()
|
|
21
|
+
stopWatching()
|
|
29
22
|
setIntoStore(store, mutexAtoms, token.key, true)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
35
|
-
}),
|
|
23
|
+
stopWatching = subscribeToState(store, token, `push`, ({ newValue }) => {
|
|
24
|
+
socket.emit(`pub:${token.key}`, newValue)
|
|
25
|
+
})
|
|
26
|
+
},
|
|
36
27
|
)
|
|
37
28
|
|
|
38
29
|
socket.emit(`claim:${token.key}`)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
init()
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
return () => {
|
|
32
|
+
socket.emit(`unclaim:${token.key}`)
|
|
33
|
+
stopWatching()
|
|
34
|
+
}
|
|
35
|
+
})
|
|
47
36
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as AtomIO from "atom.io"
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
type RoomKey,
|
|
4
|
+
type SocketKey,
|
|
5
|
+
type UserKey,
|
|
6
|
+
usersInRooms,
|
|
7
|
+
} from "atom.io/realtime"
|
|
3
8
|
|
|
4
9
|
export const mySocketKeyAtom: AtomIO.RegularAtomToken<SocketKey | undefined> =
|
|
5
10
|
AtomIO.atom<SocketKey | undefined>({
|
|
@@ -22,8 +27,26 @@ export const myUserKeyAtom: AtomIO.RegularAtomToken<UserKey | null> =
|
|
|
22
27
|
],
|
|
23
28
|
})
|
|
24
29
|
|
|
25
|
-
export const
|
|
26
|
-
AtomIO.
|
|
30
|
+
export const myRoomKeySelector: AtomIO.ReadonlyPureSelectorToken<RoomKey | null> =
|
|
31
|
+
AtomIO.selector<RoomKey | null>({
|
|
27
32
|
key: `myRoomKey`,
|
|
28
|
-
|
|
33
|
+
get: ({ get }) => {
|
|
34
|
+
if (
|
|
35
|
+
`env` in globalThis &&
|
|
36
|
+
`REALTIME_ROOM_KEY` in (globalThis as any).env
|
|
37
|
+
) {
|
|
38
|
+
// if a room running server-side wants its own key, this is where it lives
|
|
39
|
+
return (globalThis as any).env[`REALTIME_ROOM_KEY`]
|
|
40
|
+
}
|
|
41
|
+
const myUserKey = get(myUserKeyAtom)
|
|
42
|
+
if (!myUserKey) return null
|
|
43
|
+
const [, usersInRoomsAtoms] = AtomIO.getInternalRelations(
|
|
44
|
+
usersInRooms,
|
|
45
|
+
`split`,
|
|
46
|
+
)
|
|
47
|
+
const roomKeys = get(usersInRoomsAtoms, myUserKey)
|
|
48
|
+
for (const roomKey of roomKeys) {
|
|
49
|
+
return roomKey
|
|
50
|
+
}
|
|
51
|
+
},
|
|
29
52
|
})
|
|
@@ -14,8 +14,8 @@ export function usePullMutableAtomFamilyMember<
|
|
|
14
14
|
>(familyToken: AtomIO.MutableAtomFamilyToken<T, K>, key: NoInfer<K>): T {
|
|
15
15
|
const store = React.useContext(StoreContext)
|
|
16
16
|
const token = findInStore(store, familyToken, key)
|
|
17
|
-
useRealtimeService(`pull:${token.key}`, (socket) =>
|
|
18
|
-
RTC.pullMutableAtomFamilyMember(store, socket, familyToken, key)
|
|
19
|
-
)
|
|
17
|
+
useRealtimeService(`pull:${token.key}`, (socket) => {
|
|
18
|
+
return RTC.pullMutableAtomFamilyMember(store, socket, familyToken, key)
|
|
19
|
+
})
|
|
20
20
|
return useO(token)
|
|
21
21
|
}
|
|
@@ -3,56 +3,59 @@ import { findInStore, getInternalRelationsFromStore } from "atom.io/internal"
|
|
|
3
3
|
import { StoreContext, useO } from "atom.io/react"
|
|
4
4
|
import type { RoomKey, RoomSocketInterface, UserKey } from "atom.io/realtime"
|
|
5
5
|
import { ownersOfRooms, roomKeysAtom, usersInRooms } from "atom.io/realtime"
|
|
6
|
+
import { myUserKeyAtom } from "atom.io/realtime-client"
|
|
6
7
|
import type { UList } from "atom.io/transceivers/u-list"
|
|
7
8
|
import * as React from "react"
|
|
8
9
|
import type { Socket } from "socket.io-client"
|
|
9
10
|
|
|
10
11
|
import { RealtimeContext } from "./realtime-context"
|
|
12
|
+
import { usePullAtom } from "./use-pull-atom"
|
|
11
13
|
import { usePullMutable } from "./use-pull-mutable-atom"
|
|
12
14
|
import { usePullMutableAtomFamilyMember } from "./use-pull-mutable-family-member"
|
|
13
15
|
|
|
14
16
|
export type RealtimeRoomsTools = {
|
|
15
|
-
|
|
17
|
+
roomSocket: Socket<{}, RoomSocketInterface<string>>
|
|
16
18
|
myRoomKey: RoomKey | undefined
|
|
17
19
|
myMutualsAtom: MutableAtomToken<UList<UserKey>>
|
|
18
20
|
myOwnedRoomsAtom: MutableAtomToken<UList<RoomKey>>
|
|
19
21
|
allRoomKeysAtom: MutableAtomToken<UList<RoomKey>>
|
|
20
22
|
}
|
|
21
|
-
export function useRealtimeRooms<
|
|
22
|
-
|
|
23
|
-
): RealtimeRoomsTools {
|
|
23
|
+
export function useRealtimeRooms<
|
|
24
|
+
RoomNames extends string,
|
|
25
|
+
>(): RealtimeRoomsTools {
|
|
24
26
|
const store = React.useContext(StoreContext)
|
|
25
27
|
const { socket } = React.useContext(RealtimeContext)
|
|
26
28
|
usePullMutable(roomKeysAtom)
|
|
29
|
+
const userKey = usePullAtom(myUserKeyAtom) ?? `user::$_NONE_$`
|
|
27
30
|
|
|
28
31
|
const [userKeysFamily, roomKeysFamily] = getInternalRelationsFromStore(
|
|
29
32
|
store,
|
|
30
33
|
usersInRooms,
|
|
31
34
|
`split`,
|
|
32
35
|
)
|
|
33
|
-
|
|
34
36
|
usePullMutableAtomFamilyMember(roomKeysFamily, userKey)
|
|
37
|
+
|
|
35
38
|
const myJoinedRoomKeys = useO(roomKeysFamily, userKey)
|
|
36
39
|
let myRoomKey: RoomKey | undefined
|
|
37
40
|
for (const roomKey of myJoinedRoomKeys) {
|
|
38
41
|
myRoomKey = roomKey
|
|
39
42
|
break
|
|
40
43
|
}
|
|
41
|
-
|
|
42
44
|
const roomKey = myRoomKey ?? `room::$_NONE_$`
|
|
43
45
|
const myMutualsAtom = findInStore(store, userKeysFamily, roomKey)
|
|
44
46
|
usePullMutableAtomFamilyMember(userKeysFamily, roomKey)
|
|
45
47
|
|
|
46
|
-
const [ownedRoomsFamily] = getInternalRelationsFromStore(
|
|
48
|
+
const [ownedRoomsFamily, roomOwnersFamily] = getInternalRelationsFromStore(
|
|
47
49
|
store,
|
|
48
50
|
ownersOfRooms,
|
|
49
51
|
`split`,
|
|
50
52
|
)
|
|
51
53
|
const myOwnedRoomsAtom = findInStore(store, ownedRoomsFamily, userKey)
|
|
52
54
|
usePullMutableAtomFamilyMember(ownedRoomsFamily, userKey)
|
|
55
|
+
usePullMutableAtomFamilyMember(roomOwnersFamily, roomKey)
|
|
53
56
|
|
|
54
57
|
return {
|
|
55
|
-
|
|
58
|
+
roomSocket: socket as Socket<{}, RoomSocketInterface<RoomNames>>,
|
|
56
59
|
myRoomKey,
|
|
57
60
|
allRoomKeysAtom: roomKeysAtom,
|
|
58
61
|
myMutualsAtom,
|
|
@@ -98,6 +98,7 @@ export class ChildSocket<
|
|
|
98
98
|
}
|
|
99
99
|
try {
|
|
100
100
|
const jsonPiece = parseJson(piece as stringified<EventPayload<I, K>>)
|
|
101
|
+
this.logger.info(`💸`, `emitted`, jsonPiece)
|
|
101
102
|
this.handleEvent(...jsonPiece)
|
|
102
103
|
this.incompleteData = ``
|
|
103
104
|
} catch (thrown0) {
|
|
@@ -118,6 +119,7 @@ export class ChildSocket<
|
|
|
118
119
|
const maybeActualJsonPiece = parseJson(
|
|
119
120
|
initialMaybeWellFormed as stringified<EventPayload<I, K>>,
|
|
120
121
|
)
|
|
122
|
+
this.logger.info(`💸`, `emitted`, maybeActualJsonPiece)
|
|
121
123
|
this.handleEvent(...maybeActualJsonPiece)
|
|
122
124
|
this.incompleteData = ``
|
|
123
125
|
} else {
|
|
@@ -51,7 +51,7 @@ export type ParentProcess = {
|
|
|
51
51
|
|
|
52
52
|
export class ParentSocket<
|
|
53
53
|
I extends Events & {
|
|
54
|
-
[
|
|
54
|
+
[user: UserKey]: [string, ...Json.Array[]]
|
|
55
55
|
},
|
|
56
56
|
O extends Events & {
|
|
57
57
|
[id in string as `user::${id}`]: [string, ...Json.Array[]]
|
|
@@ -65,7 +65,7 @@ export class ParentSocket<
|
|
|
65
65
|
> extends CustomSocket<I, O> {
|
|
66
66
|
protected incompleteData = ``
|
|
67
67
|
protected unprocessedEvents: string[] = []
|
|
68
|
-
protected relays: Map<
|
|
68
|
+
protected relays: Map<UserKey, SubjectSocket<any, any>>
|
|
69
69
|
protected initRelay: (
|
|
70
70
|
socket: SubjectSocket<any, any>,
|
|
71
71
|
userKey: UserKey,
|
|
@@ -177,9 +177,13 @@ export class ParentSocket<
|
|
|
177
177
|
|
|
178
178
|
this.on(`user-joins`, (userKey: UserKey) => {
|
|
179
179
|
this.logger.info(`👤`, userKey, `joined`)
|
|
180
|
+
const existingRelay = this.relays.get(userKey)
|
|
181
|
+
if (existingRelay) {
|
|
182
|
+
return
|
|
183
|
+
}
|
|
180
184
|
const relay = new SubjectSocket(userKey)
|
|
181
185
|
this.relays.set(userKey, relay)
|
|
182
|
-
this.logger.info(`🔗`, `attaching services for
|
|
186
|
+
this.logger.info(`🔗`, `attaching relay services for`, userKey)
|
|
183
187
|
const cleanupRelay = this.initRelay(relay, userKey)
|
|
184
188
|
if (cleanupRelay) {
|
|
185
189
|
relay.disposalFunctions.push(cleanupRelay)
|
|
@@ -187,17 +191,19 @@ export class ParentSocket<
|
|
|
187
191
|
this.on(userKey, (...data) => {
|
|
188
192
|
relay.in.next(data)
|
|
189
193
|
})
|
|
190
|
-
relay.
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
relay.disposalFunctions.push(
|
|
195
|
+
relay.out.subscribe(`socket`, (data) => {
|
|
196
|
+
this.emit(userKey, ...(data as any))
|
|
197
|
+
}),
|
|
198
|
+
)
|
|
193
199
|
})
|
|
194
200
|
|
|
195
|
-
this.on(`user-leaves`, (
|
|
196
|
-
const relay = this.relays.get(
|
|
197
|
-
this.off(
|
|
201
|
+
this.on(`user-leaves`, (userKey: UserKey) => {
|
|
202
|
+
const relay = this.relays.get(userKey)
|
|
203
|
+
this.off(userKey)
|
|
198
204
|
if (relay) {
|
|
199
205
|
relay.dispose()
|
|
200
|
-
this.relays.delete(
|
|
206
|
+
this.relays.delete(userKey)
|
|
201
207
|
}
|
|
202
208
|
})
|
|
203
209
|
|
|
@@ -210,7 +216,7 @@ export class ParentSocket<
|
|
|
210
216
|
userKey: UserKey,
|
|
211
217
|
) => (() => void) | void,
|
|
212
218
|
): void {
|
|
213
|
-
this.logger.info(`🔗`, `running relay method`)
|
|
214
219
|
this.initRelay = attachServices
|
|
220
|
+
this.logger.info(`🔗`, `ready to relay`)
|
|
215
221
|
}
|
|
216
222
|
}
|
|
@@ -32,12 +32,10 @@ import {
|
|
|
32
32
|
visibilityFromRoomSelector,
|
|
33
33
|
visibleUsersInRoomsSelector,
|
|
34
34
|
} from "atom.io/realtime"
|
|
35
|
-
import { myRoomKeyAtom } from "atom.io/realtime-client"
|
|
36
35
|
|
|
37
36
|
import { ChildSocket, PROOF_OF_LIFE_SIGNAL } from "./ipc-sockets"
|
|
38
37
|
import { realtimeMutableFamilyProvider } from "./realtime-mutable-family-provider"
|
|
39
38
|
import { realtimeMutableProvider } from "./realtime-mutable-provider"
|
|
40
|
-
import { realtimeStateProvider } from "./realtime-state-provider"
|
|
41
39
|
|
|
42
40
|
export type RoomMap = Map<
|
|
43
41
|
string,
|
|
@@ -78,7 +76,9 @@ export function spawnRoom<RoomNames extends string>({
|
|
|
78
76
|
const [command, args] = resolveRoomScript(roomName)
|
|
79
77
|
const child = await new Promise<ChildProcessWithoutNullStreams>(
|
|
80
78
|
(resolve) => {
|
|
81
|
-
const room = spawn(command, args, {
|
|
79
|
+
const room = spawn(command, args, {
|
|
80
|
+
env: { ...process.env, REALTIME_ROOM_KEY: roomKey },
|
|
81
|
+
})
|
|
82
82
|
const resolver = (data: Buffer) => {
|
|
83
83
|
const chunk = data.toString()
|
|
84
84
|
if (chunk === PROOF_OF_LIFE_SIGNAL) {
|
|
@@ -102,12 +102,6 @@ export function spawnRoom<RoomNames extends string>({
|
|
|
102
102
|
consumer: roomKey,
|
|
103
103
|
store,
|
|
104
104
|
})
|
|
105
|
-
const provideState = realtimeStateProvider({
|
|
106
|
-
socket: room,
|
|
107
|
-
consumer: roomKey,
|
|
108
|
-
store,
|
|
109
|
-
})
|
|
110
|
-
const unsubFromRoomKey = provideState(myRoomKeyAtom, roomKey)
|
|
111
105
|
|
|
112
106
|
const ownersOfRoomsAtoms = getInternalRelationsFromStore(
|
|
113
107
|
store,
|
|
@@ -123,7 +117,6 @@ export function spawnRoom<RoomNames extends string>({
|
|
|
123
117
|
)
|
|
124
118
|
|
|
125
119
|
room.on(`close`, () => {
|
|
126
|
-
unsubFromRoomKey()
|
|
127
120
|
unsubFromOwnerKeys()
|
|
128
121
|
unsubFromUsersInRooms()
|
|
129
122
|
destroyRoom({ store, socket, userKey })(roomKey)
|
|
@@ -150,11 +143,36 @@ export function provideEnterAndExit({
|
|
|
150
143
|
`📡`,
|
|
151
144
|
`socket`,
|
|
152
145
|
socket.id ?? `[ID MISSING?!]`,
|
|
153
|
-
`👤 ${userKey} enters
|
|
146
|
+
`👤 ${userKey} enters ${roomKey}`,
|
|
154
147
|
)
|
|
148
|
+
const childSocket = ROOMS.get(roomKey)
|
|
149
|
+
if (!childSocket) {
|
|
150
|
+
store.logger.error(`❌`, `unknown`, roomKey, `no room found with this id`)
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
const toUser = socket.emit.bind(socket)
|
|
154
|
+
childSocket.on(userKey, toUser)
|
|
155
|
+
|
|
156
|
+
const roomQueue: [string, ...Json.Array][] = []
|
|
157
|
+
const pushToRoomQueue = (payload: [string, ...Json.Array]): void => {
|
|
158
|
+
roomQueue.push(payload)
|
|
159
|
+
}
|
|
160
|
+
let toRoom = pushToRoomQueue
|
|
161
|
+
const forward: AllEventsListener<EventsMap> = (...payload) => {
|
|
162
|
+
toRoom([userKey, ...payload])
|
|
163
|
+
}
|
|
164
|
+
socket.onAny(forward)
|
|
155
165
|
|
|
156
166
|
const dcUserFromRoom = () => {
|
|
157
|
-
|
|
167
|
+
store.logger.info(
|
|
168
|
+
`📡`,
|
|
169
|
+
`socket`,
|
|
170
|
+
socket.id ?? `[ID MISSING?!]`,
|
|
171
|
+
`👤 ${userKey} is has lost connection to ${roomKey}`,
|
|
172
|
+
)
|
|
173
|
+
socket.offAny(forward)
|
|
174
|
+
childSocket.off(userKey, toUser)
|
|
175
|
+
toRoom([`user-leaves`, userKey])
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
const exitRoom = () => {
|
|
@@ -162,9 +180,8 @@ export function provideEnterAndExit({
|
|
|
162
180
|
`📡`,
|
|
163
181
|
`socket`,
|
|
164
182
|
socket.id ?? `[ID MISSING?!]`,
|
|
165
|
-
`👤 ${userKey} leaves
|
|
183
|
+
`👤 ${userKey} leaves ${roomKey}`,
|
|
166
184
|
)
|
|
167
|
-
socket.offAny(forward)
|
|
168
185
|
dcUserFromRoom()
|
|
169
186
|
editRelationsInStore(store, usersInRooms, (relations) => {
|
|
170
187
|
relations.delete({ room: roomKey, user: userKey })
|
|
@@ -174,27 +191,10 @@ export function provideEnterAndExit({
|
|
|
174
191
|
roomSocket.on(`joinRoom`, enterRoom)
|
|
175
192
|
}
|
|
176
193
|
|
|
177
|
-
const roomQueue: [string, ...Json.Array][] = []
|
|
178
|
-
const pushToRoomQueue = (payload: [string, ...Json.Array]): void => {
|
|
179
|
-
roomQueue.push(payload)
|
|
180
|
-
}
|
|
181
|
-
let toRoom = pushToRoomQueue
|
|
182
|
-
const forward: AllEventsListener<EventsMap> = (...payload) => {
|
|
183
|
-
toRoom([userKey, ...payload])
|
|
184
|
-
}
|
|
185
|
-
socket.onAny(forward)
|
|
186
|
-
|
|
187
194
|
editRelationsInStore(store, usersInRooms, (relations) => {
|
|
188
195
|
relations.set({ room: roomKey, user: userKey })
|
|
189
196
|
})
|
|
190
|
-
|
|
191
|
-
if (!childSocket) {
|
|
192
|
-
store.logger.error(`❌`, `unknown`, roomKey, `no room found with this id`)
|
|
193
|
-
return
|
|
194
|
-
}
|
|
195
|
-
childSocket.onAny((...payload) => {
|
|
196
|
-
socket.emit(...payload)
|
|
197
|
-
})
|
|
197
|
+
|
|
198
198
|
childSocket.emit(`user-joins`, userKey)
|
|
199
199
|
|
|
200
200
|
toRoom = (payload) => {
|
|
@@ -228,7 +228,7 @@ export function destroyRoom({
|
|
|
228
228
|
`📡`,
|
|
229
229
|
`socket`,
|
|
230
230
|
socket.id ?? `[ID MISSING?!]`,
|
|
231
|
-
`👤 ${userKey} attempts to delete
|
|
231
|
+
`👤 ${userKey} attempts to delete ${roomKey}`,
|
|
232
232
|
)
|
|
233
233
|
const owner = getFromStore(
|
|
234
234
|
store,
|
|
@@ -239,7 +239,7 @@ export function destroyRoom({
|
|
|
239
239
|
`📡`,
|
|
240
240
|
`socket`,
|
|
241
241
|
socket.id ?? `[ID MISSING?!]`,
|
|
242
|
-
`👤 ${userKey} deletes
|
|
242
|
+
`👤 ${userKey} deletes ${roomKey}`,
|
|
243
243
|
)
|
|
244
244
|
setIntoStore(store, roomKeysAtom, (s) => (s.delete(roomKey), s))
|
|
245
245
|
editRelationsInStore(store, usersInRooms, (relations) => {
|
|
@@ -256,7 +256,7 @@ export function destroyRoom({
|
|
|
256
256
|
`📡`,
|
|
257
257
|
`socket`,
|
|
258
258
|
socket.id ?? `[ID MISSING?!]`,
|
|
259
|
-
`👤 ${userKey} failed to delete
|
|
259
|
+
`👤 ${userKey} failed to delete ${roomKey}; its owner is ${owner}`,
|
|
260
260
|
)
|
|
261
261
|
}
|
|
262
262
|
}
|