atom.io 0.40.7 → 0.40.9
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/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
- package/dist/data/index.js +1 -2
- package/dist/data/index.js.map +1 -1
- package/dist/eslint-plugin/index.js +2 -3
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/internal/index.d.ts +4 -3
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1231 -176
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +13 -32
- package/dist/introspection/index.js.map +1 -1
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +1 -2
- package/dist/main/index.js.map +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.d.ts.map +1 -1
- package/dist/react-devtools/index.js +2 -4
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +29 -5
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +47 -5
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +2 -6
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +6 -22
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +6 -9
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +4 -16
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +38 -57
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +128 -178
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +2 -0
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +15 -9
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/transceivers/set-rtx/index.d.ts +1 -1
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +5 -9
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/transceivers/u-list/index.d.ts +29 -0
- package/dist/transceivers/u-list/index.d.ts.map +1 -0
- package/dist/transceivers/u-list/index.js +87 -0
- package/dist/transceivers/u-list/index.js.map +1 -0
- package/dist/web/index.js.map +1 -1
- package/package.json +17 -13
- package/src/internal/mutable/tracker.ts +61 -46
- package/src/internal/mutable/transceiver.ts +4 -4
- package/src/internal/set-state/index.ts +1 -0
- package/src/internal/subscribe/subscribe-to-state.ts +9 -0
- package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
- package/src/realtime/index.ts +2 -0
- package/src/realtime/shared-room-store.ts +12 -11
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
- package/src/realtime-client/index.ts +0 -1
- package/src/realtime-client/push-state.ts +1 -2
- package/src/realtime-react/index.ts +0 -1
- package/src/realtime-react/use-single-effect.ts +1 -1
- package/src/realtime-server/continuity/continuity-store.ts +2 -27
- package/src/realtime-server/continuity/provide-continuity.ts +50 -0
- package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +16 -14
- package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +11 -10
- package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +8 -6
- package/src/realtime-server/continuity/receive-action-requests.ts +66 -0
- package/src/realtime-server/continuity/{prepare-to-track-client-acknowledgement.ts → track-acknowledgements.ts} +15 -9
- package/src/realtime-server/index.ts +1 -3
- package/src/realtime-server/ipc-sockets/custom-socket.ts +4 -5
- package/src/realtime-server/ipc-sockets/parent-socket.ts +21 -17
- package/src/realtime-server/realtime-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-provider.ts +1 -1
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
- package/src/realtime-server/realtime-state-provider.ts +1 -1
- package/src/realtime-server/realtime-state-receiver.ts +3 -6
- package/src/realtime-server/server-config.ts +1 -3
- package/src/realtime-testing/setup-realtime-test.tsx +23 -18
- package/src/transceivers/set-rtx/set-rtx.ts +3 -3
- package/src/transceivers/u-list/index.ts +1 -0
- package/src/transceivers/u-list/u-list.ts +123 -0
- package/dist/employ-socket-D6wgByWh.js +0 -12
- package/dist/employ-socket-D6wgByWh.js.map +0 -1
- package/dist/has-role-hv4-hJMw.js +0 -1149
- package/dist/has-role-hv4-hJMw.js.map +0 -1
- package/dist/is-fn-DY1wZ-md.js +0 -10
- package/dist/is-fn-DY1wZ-md.js.map +0 -1
- package/dist/mutex-store-CSvxY9i3.js +0 -11
- package/dist/mutex-store-CSvxY9i3.js.map +0 -1
- package/dist/shared-room-store-COGGKqes.js +0 -32
- package/dist/shared-room-store-COGGKqes.js.map +0 -1
- package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
- package/src/realtime-client/server-action.ts +0 -23
- package/src/realtime-react/use-server-action.ts +0 -19
- package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
- package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
- package/src/realtime-server/realtime-action-receiver.ts +0 -40
- /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getFromStore, IMPLICIT } from "atom.io/internal"
|
|
2
|
+
import type { Json } from "atom.io/json"
|
|
3
|
+
import type { ContinuityToken } from "atom.io/realtime"
|
|
4
|
+
|
|
5
|
+
import type { ServerConfig, UserKey } from ".."
|
|
6
|
+
import { unacknowledgedUpdatesAtoms } from "./continuity-store"
|
|
7
|
+
import { provideOutcomes } from "./provide-outcomes"
|
|
8
|
+
import { providePerspectives } from "./provide-perspectives"
|
|
9
|
+
import { provideStartupPayloads } from "./provide-startup-payloads"
|
|
10
|
+
import { receiveActionRequests } from "./receive-action-requests"
|
|
11
|
+
import { trackAcknowledgements } from "./track-acknowledgements"
|
|
12
|
+
|
|
13
|
+
export type ProvideContinuity = (
|
|
14
|
+
continuity: ContinuityToken,
|
|
15
|
+
userKey: UserKey,
|
|
16
|
+
) => () => void
|
|
17
|
+
export function prepareToProvideContinuity({
|
|
18
|
+
socket,
|
|
19
|
+
store = IMPLICIT.STORE,
|
|
20
|
+
}: ServerConfig): ProvideContinuity {
|
|
21
|
+
return function syncRealtimeContinuity(continuity, userKey) {
|
|
22
|
+
const continuityKey = continuity.key
|
|
23
|
+
|
|
24
|
+
const unacknowledgedUpdates = getFromStore(
|
|
25
|
+
store,
|
|
26
|
+
unacknowledgedUpdatesAtoms,
|
|
27
|
+
userKey,
|
|
28
|
+
)
|
|
29
|
+
for (const unacknowledgedUpdate of unacknowledgedUpdates) {
|
|
30
|
+
socket.emit(
|
|
31
|
+
`tx-new:${continuityKey}`,
|
|
32
|
+
unacknowledgedUpdate as Json.Serializable,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const subscriptions = new Set<() => void>()
|
|
37
|
+
const clearSubscriptions = () => {
|
|
38
|
+
for (const unsubscribe of subscriptions) unsubscribe()
|
|
39
|
+
subscriptions.clear()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
subscriptions.add(providePerspectives(store, socket, continuity, userKey))
|
|
43
|
+
subscriptions.add(provideOutcomes(store, socket, continuity, userKey))
|
|
44
|
+
subscriptions.add(provideStartupPayloads(store, socket, continuity, userKey))
|
|
45
|
+
subscriptions.add(receiveActionRequests(store, socket, continuity, userKey))
|
|
46
|
+
subscriptions.add(trackAcknowledgements(store, socket, continuity, userKey))
|
|
47
|
+
|
|
48
|
+
return clearSubscriptions
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts}
RENAMED
|
@@ -7,29 +7,29 @@ import {
|
|
|
7
7
|
subscribeToTransaction,
|
|
8
8
|
} from "atom.io/internal"
|
|
9
9
|
import type { Json } from "atom.io/json"
|
|
10
|
-
import type { ContinuityToken } from "atom.io/realtime"
|
|
10
|
+
import type { ContinuityToken, Socket } from "atom.io/realtime"
|
|
11
11
|
|
|
12
|
-
import type {
|
|
12
|
+
import type { UserKey } from ".."
|
|
13
13
|
import {
|
|
14
14
|
redactTransactionUpdateContent,
|
|
15
|
-
|
|
15
|
+
unacknowledgedUpdatesAtoms,
|
|
16
16
|
} from "./continuity-store"
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function provideOutcomes(
|
|
19
19
|
store: Store,
|
|
20
|
+
socket: Socket,
|
|
20
21
|
continuity: ContinuityToken,
|
|
21
22
|
userKey: UserKey,
|
|
22
|
-
|
|
23
|
-
): (() => void)[] {
|
|
23
|
+
): () => void {
|
|
24
24
|
const continuityKey = continuity.key
|
|
25
|
-
const unsubscribeFunctions
|
|
25
|
+
const unsubscribeFunctions = new Set<() => void>()
|
|
26
26
|
|
|
27
27
|
for (const transaction of continuity.actions) {
|
|
28
28
|
const unsubscribeFromTransaction = subscribeToTransaction(
|
|
29
29
|
store,
|
|
30
30
|
transaction,
|
|
31
31
|
`sync-continuity:${continuityKey}:${userKey}`,
|
|
32
|
-
(
|
|
32
|
+
(outcomes) => {
|
|
33
33
|
try {
|
|
34
34
|
const visibleKeys = continuity.globals
|
|
35
35
|
.map((atom) => {
|
|
@@ -59,13 +59,13 @@ export function subscribeToContinuityActions(
|
|
|
59
59
|
)
|
|
60
60
|
const redactedUpdates = redactTransactionUpdateContent(
|
|
61
61
|
visibleKeys,
|
|
62
|
-
|
|
62
|
+
outcomes.subEvents,
|
|
63
63
|
)
|
|
64
64
|
const redactedUpdate = {
|
|
65
|
-
...
|
|
65
|
+
...outcomes,
|
|
66
66
|
updates: redactedUpdates,
|
|
67
67
|
}
|
|
68
|
-
setIntoStore(store,
|
|
68
|
+
setIntoStore(store, unacknowledgedUpdatesAtoms, userKey, (updates) => {
|
|
69
69
|
if (redactedUpdate) {
|
|
70
70
|
updates.push(redactedUpdate)
|
|
71
71
|
updates.sort((a, b) => a.epoch - b.epoch)
|
|
@@ -81,7 +81,7 @@ export function subscribeToContinuityActions(
|
|
|
81
81
|
return updates
|
|
82
82
|
})
|
|
83
83
|
|
|
84
|
-
socket
|
|
84
|
+
socket.emit(
|
|
85
85
|
`tx-new:${continuityKey}`,
|
|
86
86
|
redactedUpdate as Json.Serializable,
|
|
87
87
|
)
|
|
@@ -98,7 +98,9 @@ export function subscribeToContinuityActions(
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
)
|
|
101
|
-
unsubscribeFunctions.
|
|
101
|
+
unsubscribeFunctions.add(unsubscribeFromTransaction)
|
|
102
|
+
}
|
|
103
|
+
return () => {
|
|
104
|
+
for (const unsubscribe of unsubscribeFunctions) unsubscribe()
|
|
102
105
|
}
|
|
103
|
-
return unsubscribeFunctions
|
|
104
106
|
}
|
|
@@ -5,19 +5,18 @@ import {
|
|
|
5
5
|
getJsonToken,
|
|
6
6
|
subscribeToState,
|
|
7
7
|
} from "atom.io/internal"
|
|
8
|
-
import type { ContinuityToken } from "atom.io/realtime"
|
|
8
|
+
import type { ContinuityToken, Socket } from "atom.io/realtime"
|
|
9
9
|
|
|
10
|
-
import type { Socket } from ".."
|
|
11
10
|
import type { UserKey } from "../realtime-server-stores"
|
|
12
11
|
|
|
13
|
-
export function
|
|
12
|
+
export function providePerspectives(
|
|
14
13
|
store: Store,
|
|
14
|
+
socket: Socket,
|
|
15
15
|
continuity: ContinuityToken,
|
|
16
16
|
userKey: UserKey,
|
|
17
|
-
|
|
18
|
-
): (() => void)[] {
|
|
17
|
+
): () => void {
|
|
19
18
|
const continuityKey = continuity.key
|
|
20
|
-
const unsubFns
|
|
19
|
+
const unsubFns = new Set<() => void>()
|
|
21
20
|
for (const perspective of continuity.perspectives) {
|
|
22
21
|
const { viewAtoms } = perspective
|
|
23
22
|
const userViewState = findInStore(store, viewAtoms, userKey)
|
|
@@ -47,14 +46,16 @@ export function subscribeToContinuityPerspectives(
|
|
|
47
46
|
{ oldKeys, newKeys, revealed, concealed },
|
|
48
47
|
)
|
|
49
48
|
if (revealed.length > 0) {
|
|
50
|
-
socket
|
|
49
|
+
socket.emit(`reveal:${continuityKey}`, revealed)
|
|
51
50
|
}
|
|
52
51
|
if (concealed && concealed.length > 0) {
|
|
53
|
-
socket
|
|
52
|
+
socket.emit(`conceal:${continuityKey}`, concealed)
|
|
54
53
|
}
|
|
55
54
|
},
|
|
56
55
|
)
|
|
57
|
-
unsubFns.
|
|
56
|
+
unsubFns.add(unsubscribeFromUserView)
|
|
57
|
+
}
|
|
58
|
+
return () => {
|
|
59
|
+
for (const unsubscribe of unsubFns) unsubscribe()
|
|
58
60
|
}
|
|
59
|
-
return unsubFns
|
|
60
61
|
}
|
|
@@ -6,18 +6,19 @@ import {
|
|
|
6
6
|
isRootStore,
|
|
7
7
|
} from "atom.io/internal"
|
|
8
8
|
import type { Json } from "atom.io/json"
|
|
9
|
-
import type { ContinuityToken } from "atom.io/realtime"
|
|
9
|
+
import type { ContinuityToken, Socket } from "atom.io/realtime"
|
|
10
|
+
import { employSocket } from "atom.io/realtime"
|
|
10
11
|
|
|
11
|
-
import type {
|
|
12
|
+
import type { UserKey } from ".."
|
|
12
13
|
|
|
13
|
-
export function
|
|
14
|
+
export function provideStartupPayloads(
|
|
14
15
|
store: Store,
|
|
16
|
+
socket: Socket,
|
|
15
17
|
continuity: ContinuityToken,
|
|
16
18
|
userKey: UserKey,
|
|
17
|
-
socket: Socket | null,
|
|
18
19
|
): () => void {
|
|
19
20
|
const continuityKey = continuity.key
|
|
20
|
-
|
|
21
|
+
function sendInitialPayload(): void {
|
|
21
22
|
const initialPayload: Json.Serializable[] = []
|
|
22
23
|
for (const atom of continuity.globals) {
|
|
23
24
|
const resourceToken =
|
|
@@ -49,6 +50,7 @@ export function prepareToSendInitialPayload(
|
|
|
49
50
|
? (store.transactionMeta.epoch.get(continuityKey) ?? null)
|
|
50
51
|
: null
|
|
51
52
|
|
|
52
|
-
socket
|
|
53
|
+
socket.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)
|
|
53
54
|
}
|
|
55
|
+
return employSocket(socket, `get:${continuityKey}`, sendInitialPayload)
|
|
54
56
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { TransactionOutcomeEvent, TransactionToken } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { actUponStore } from "atom.io/internal"
|
|
4
|
+
import type { Json, JsonIO } from "atom.io/json"
|
|
5
|
+
import type { ContinuityToken, Socket } from "atom.io/realtime"
|
|
6
|
+
import { employSocket } from "atom.io/realtime"
|
|
7
|
+
|
|
8
|
+
export function receiveActionRequests(
|
|
9
|
+
store: Store,
|
|
10
|
+
socket: Socket,
|
|
11
|
+
continuity: ContinuityToken,
|
|
12
|
+
userKey: string,
|
|
13
|
+
): () => void {
|
|
14
|
+
const continuityKey = continuity.key
|
|
15
|
+
|
|
16
|
+
return employSocket(
|
|
17
|
+
socket,
|
|
18
|
+
`tx-run:${continuityKey}`,
|
|
19
|
+
function serveTransactionRequest(
|
|
20
|
+
txOutcome: Json.Serializable &
|
|
21
|
+
Pick<
|
|
22
|
+
TransactionOutcomeEvent<TransactionToken<JsonIO>>,
|
|
23
|
+
`id` | `params` | `token`
|
|
24
|
+
>,
|
|
25
|
+
) {
|
|
26
|
+
store.logger.info(`🛎️`, `continuity`, continuityKey, `received`, txOutcome)
|
|
27
|
+
const transactionKey = txOutcome.token.key
|
|
28
|
+
const updateId = txOutcome.id
|
|
29
|
+
const performanceKey = `tx-run:${transactionKey}:${updateId}`
|
|
30
|
+
const performanceKeyStart = `${performanceKey}:start`
|
|
31
|
+
const performanceKeyEnd = `${performanceKey}:end`
|
|
32
|
+
performance.mark(performanceKeyStart)
|
|
33
|
+
try {
|
|
34
|
+
actUponStore(
|
|
35
|
+
store,
|
|
36
|
+
{ type: `transaction`, key: transactionKey },
|
|
37
|
+
updateId,
|
|
38
|
+
)(...txOutcome.params)
|
|
39
|
+
} catch (thrown) {
|
|
40
|
+
if (thrown instanceof Error) {
|
|
41
|
+
store.logger.error(
|
|
42
|
+
`❌`,
|
|
43
|
+
`continuity`,
|
|
44
|
+
continuityKey,
|
|
45
|
+
`failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,
|
|
46
|
+
thrown.message,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
performance.mark(performanceKeyEnd)
|
|
51
|
+
const metric = performance.measure(
|
|
52
|
+
performanceKey,
|
|
53
|
+
performanceKeyStart,
|
|
54
|
+
performanceKeyEnd,
|
|
55
|
+
)
|
|
56
|
+
store.logger.info(
|
|
57
|
+
`🚀`,
|
|
58
|
+
`transaction`,
|
|
59
|
+
transactionKey,
|
|
60
|
+
updateId,
|
|
61
|
+
userKey,
|
|
62
|
+
metric.duration,
|
|
63
|
+
)
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import type { Store } from "atom.io/internal"
|
|
2
|
-
import { setIntoStore } from "atom.io/internal"
|
|
3
|
-
import type { ContinuityToken } from "atom.io/realtime"
|
|
2
|
+
import { getFromStore, setIntoStore } from "atom.io/internal"
|
|
3
|
+
import type { ContinuityToken, Socket } from "atom.io/realtime"
|
|
4
|
+
import { employSocket } from "atom.io/realtime"
|
|
4
5
|
|
|
5
6
|
import type { UserKey } from "../realtime-server-stores"
|
|
6
|
-
import
|
|
7
|
-
import { userUnacknowledgedQueues } from "./continuity-store"
|
|
7
|
+
import { unacknowledgedUpdatesAtoms } from "./continuity-store"
|
|
8
8
|
|
|
9
|
-
export function
|
|
9
|
+
export function trackAcknowledgements(
|
|
10
10
|
store: Store,
|
|
11
|
+
socket: Socket,
|
|
11
12
|
continuity: ContinuityToken,
|
|
12
13
|
userKey: UserKey,
|
|
13
|
-
|
|
14
|
-
): (epoch: number) => void {
|
|
14
|
+
): () => void {
|
|
15
15
|
const continuityKey = continuity.key
|
|
16
|
-
|
|
16
|
+
const userUnacknowledgedUpdates = getFromStore(
|
|
17
|
+
store,
|
|
18
|
+
unacknowledgedUpdatesAtoms,
|
|
19
|
+
userKey,
|
|
20
|
+
)
|
|
21
|
+
function trackClientAcknowledgement(epoch: number): void {
|
|
17
22
|
store.logger.info(
|
|
18
23
|
`👍`,
|
|
19
24
|
`continuity`,
|
|
@@ -22,7 +27,7 @@ export function prepareToTrackClientAcknowledgement(
|
|
|
22
27
|
)
|
|
23
28
|
const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch
|
|
24
29
|
if (isUnacknowledged) {
|
|
25
|
-
setIntoStore(store,
|
|
30
|
+
setIntoStore(store, unacknowledgedUpdatesAtoms, userKey, (updates) => {
|
|
26
31
|
updates.shift()
|
|
27
32
|
store.logger.info(
|
|
28
33
|
`👍`,
|
|
@@ -36,4 +41,5 @@ export function prepareToTrackClientAcknowledgement(
|
|
|
36
41
|
})
|
|
37
42
|
}
|
|
38
43
|
}
|
|
44
|
+
return employSocket(socket, `ack:${continuityKey}`, trackClientAcknowledgement)
|
|
39
45
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from "./continuity/
|
|
1
|
+
export * from "./continuity/provide-continuity"
|
|
2
2
|
export * from "./ipc-sockets"
|
|
3
|
-
export * from "./realtime-action-receiver"
|
|
4
3
|
export * from "./realtime-family-provider"
|
|
5
4
|
export * from "./realtime-mutable-family-provider"
|
|
6
5
|
export * from "./realtime-mutable-provider"
|
|
@@ -8,4 +7,3 @@ export * from "./realtime-server-stores"
|
|
|
8
7
|
export * from "./realtime-state-provider"
|
|
9
8
|
export * from "./realtime-state-receiver"
|
|
10
9
|
export type * from "./server-config"
|
|
11
|
-
export type * from "./socket-interface"
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Json, stringified } from "atom.io/json"
|
|
2
|
-
|
|
3
|
-
import type { Socket } from "../socket-interface"
|
|
2
|
+
import type { Socket } from "atom.io/realtime"
|
|
4
3
|
|
|
5
4
|
export type Events = Json.Object<string, Json.Serializable[]>
|
|
6
5
|
|
|
7
6
|
export type EventPayload<
|
|
8
|
-
|
|
9
|
-
K extends string & keyof
|
|
10
|
-
> = [string, ...
|
|
7
|
+
receiveRelay extends Events,
|
|
8
|
+
K extends string & keyof receiveRelay = string & keyof receiveRelay,
|
|
9
|
+
> = [string, ...receiveRelay[K]]
|
|
11
10
|
|
|
12
11
|
export interface EventBuffer<
|
|
13
12
|
E extends Events,
|
|
@@ -3,8 +3,9 @@ import type { Readable, Writable } from "node:stream"
|
|
|
3
3
|
import { Subject } from "atom.io/internal"
|
|
4
4
|
import type { Json } from "atom.io/json"
|
|
5
5
|
import { parseJson, stringifyJson } from "atom.io/json"
|
|
6
|
-
import {
|
|
6
|
+
import { UList } from "atom.io/transceivers/u-list"
|
|
7
7
|
|
|
8
|
+
import type { UserKey } from "../realtime-server-stores"
|
|
8
9
|
import type { StderrLog } from "./child-socket"
|
|
9
10
|
import type { EventBuffer, EventPayload, Events } from "./custom-socket"
|
|
10
11
|
import { CustomSocket } from "./custom-socket"
|
|
@@ -48,14 +49,14 @@ export type ParentProcess = {
|
|
|
48
49
|
|
|
49
50
|
export class ParentSocket<
|
|
50
51
|
I extends Events & {
|
|
51
|
-
[id in string as `relay
|
|
52
|
+
[id in string as `relay::${id}`]: [string, ...Json.Array[]]
|
|
52
53
|
},
|
|
53
54
|
O extends Events & {
|
|
54
|
-
[id in string as `user
|
|
55
|
+
[id in string as `user::${id}`]: [string, ...Json.Array[]]
|
|
55
56
|
} & {
|
|
56
57
|
/* eslint-disable quotes */
|
|
57
|
-
"user-joins": [
|
|
58
|
-
"user-leaves": [
|
|
58
|
+
"user-joins": [key: UserKey]
|
|
59
|
+
"user-leaves": [key: UserKey]
|
|
59
60
|
/* eslint-enable quotes */
|
|
60
61
|
},
|
|
61
62
|
P extends ParentProcess = ParentProcess,
|
|
@@ -65,6 +66,7 @@ export class ParentSocket<
|
|
|
65
66
|
protected relays: Map<string, SubjectSocket<any, any>>
|
|
66
67
|
protected relayServices: ((
|
|
67
68
|
socket: SubjectSocket<any, any>,
|
|
69
|
+
userKey: UserKey,
|
|
68
70
|
) => (() => void) | void)[]
|
|
69
71
|
public proc: P
|
|
70
72
|
|
|
@@ -74,9 +76,7 @@ export class ParentSocket<
|
|
|
74
76
|
this.proc.stderr.write(
|
|
75
77
|
stringifyJson(
|
|
76
78
|
args.map((arg) =>
|
|
77
|
-
arg instanceof
|
|
78
|
-
? `{ ${arg.toJSON().members.join(` | `)} }`
|
|
79
|
-
: arg,
|
|
79
|
+
arg instanceof UList ? `{ ${arg.toJSON().members.join(` | `)} }` : arg,
|
|
80
80
|
),
|
|
81
81
|
) + `\x03`,
|
|
82
82
|
)
|
|
@@ -171,22 +171,23 @@ export class ParentSocket<
|
|
|
171
171
|
this.id = this.proc.pid?.toString()
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
this.on(`user-joins`, (username) => {
|
|
174
|
+
this.on(`user-joins`, (username: string) => {
|
|
175
175
|
this.logger.info(`👤`, `user`, username, `joined`)
|
|
176
|
-
const
|
|
176
|
+
const userKey = `user::${username}` satisfies UserKey
|
|
177
|
+
const relay = new SubjectSocket(userKey)
|
|
177
178
|
this.relays.set(username, relay)
|
|
178
179
|
this.logger.info(
|
|
179
180
|
`🔗`,
|
|
180
181
|
`attaching services:`,
|
|
181
182
|
`[${[...this.relayServices.keys()].join(`, `)}]`,
|
|
182
183
|
)
|
|
183
|
-
for (const
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
186
|
-
relay.disposalFunctions.push(
|
|
184
|
+
for (const attachRelay of this.relayServices) {
|
|
185
|
+
const cleanupRelay = attachRelay(relay, userKey)
|
|
186
|
+
if (cleanupRelay) {
|
|
187
|
+
relay.disposalFunctions.push(cleanupRelay)
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
|
-
this.on(
|
|
190
|
+
this.on(userKey, (...data) => {
|
|
190
191
|
relay.in.next(data)
|
|
191
192
|
})
|
|
192
193
|
relay.out.subscribe(`socket`, (data) => {
|
|
@@ -206,8 +207,11 @@ export class ParentSocket<
|
|
|
206
207
|
this.proc.stdout.write(`ALIVE`)
|
|
207
208
|
}
|
|
208
209
|
|
|
209
|
-
public
|
|
210
|
-
attachServices: (
|
|
210
|
+
public receiveRelay(
|
|
211
|
+
attachServices: (
|
|
212
|
+
socket: SubjectSocket<any, any>,
|
|
213
|
+
userKey: UserKey,
|
|
214
|
+
) => (() => void) | void,
|
|
211
215
|
): void {
|
|
212
216
|
this.logger.info(`🔗`, `running relay method`)
|
|
213
217
|
this.relayServices.push(attachServices)
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
} from "atom.io/internal"
|
|
8
8
|
import type { Canonical, Json, stringified } from "atom.io/json"
|
|
9
9
|
import { stringifyJson } from "atom.io/json"
|
|
10
|
+
import { employSocket } from "atom.io/realtime"
|
|
10
11
|
|
|
11
12
|
import type { ServerConfig } from "."
|
|
12
|
-
import { employSocket } from "./employ-socket"
|
|
13
13
|
|
|
14
14
|
export type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>
|
|
15
15
|
export function realtimeAtomFamilyProvider({
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
} from "atom.io/internal"
|
|
11
11
|
import type { Canonical, stringified } from "atom.io/json"
|
|
12
12
|
import { stringifyJson } from "atom.io/json"
|
|
13
|
+
import { employSocket } from "atom.io/realtime"
|
|
13
14
|
|
|
14
15
|
import type { ServerConfig } from "."
|
|
15
|
-
import { employSocket } from "./employ-socket"
|
|
16
16
|
|
|
17
17
|
export type MutableFamilyProvider = ReturnType<
|
|
18
18
|
typeof realtimeMutableFamilyProvider
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
subscribeToState,
|
|
9
9
|
} from "atom.io/internal"
|
|
10
10
|
import type { Json } from "atom.io/json"
|
|
11
|
+
import { employSocket } from "atom.io/realtime"
|
|
11
12
|
|
|
12
13
|
import type { ServerConfig } from "."
|
|
13
|
-
import { employSocket } from "./employ-socket"
|
|
14
14
|
|
|
15
15
|
export type MutableProvider = ReturnType<typeof realtimeMutableProvider>
|
|
16
16
|
export function realtimeMutableProvider({
|
|
@@ -4,8 +4,8 @@ import { spawn } from "node:child_process"
|
|
|
4
4
|
import type { TransactionIO, TransactionToken } from "atom.io"
|
|
5
5
|
import { transaction } from "atom.io"
|
|
6
6
|
import { editRelationsInStore } from "atom.io/internal"
|
|
7
|
-
import type { UserInRoomMeta } from "atom.io/realtime
|
|
8
|
-
import { roomIndex, usersInRooms } from "atom.io/realtime
|
|
7
|
+
import type { UserInRoomMeta } from "atom.io/realtime"
|
|
8
|
+
import { roomIndex, usersInRooms } from "atom.io/realtime"
|
|
9
9
|
|
|
10
10
|
import { ChildSocket } from "../ipc-sockets"
|
|
11
11
|
import type { RoomKey } from "./server-user-store"
|
|
@@ -6,9 +6,8 @@ import type {
|
|
|
6
6
|
RegularAtomFamilyToken,
|
|
7
7
|
} from "atom.io"
|
|
8
8
|
import { atomFamily, join, mutableAtom, selectorFamily } from "atom.io"
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import type { Socket } from ".."
|
|
9
|
+
import type { Socket } from "atom.io/realtime"
|
|
10
|
+
import { UList } from "atom.io/transceivers/u-list"
|
|
12
11
|
|
|
13
12
|
export type SocketKey = `socket::${string}`
|
|
14
13
|
export type UserKey = `user::${string}`
|
|
@@ -29,17 +28,17 @@ export const socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey> =
|
|
|
29
28
|
default: null,
|
|
30
29
|
})
|
|
31
30
|
|
|
32
|
-
export const socketIndex: MutableAtomToken<
|
|
33
|
-
|
|
31
|
+
export const socketIndex: MutableAtomToken<UList<SocketKey>> = mutableAtom<
|
|
32
|
+
UList<SocketKey>
|
|
34
33
|
>({
|
|
35
34
|
key: `socketsIndex`,
|
|
36
|
-
class:
|
|
35
|
+
class: UList,
|
|
37
36
|
})
|
|
38
|
-
export const userIndex: MutableAtomToken<
|
|
39
|
-
|
|
37
|
+
export const userIndex: MutableAtomToken<UList<UserKey>> = mutableAtom<
|
|
38
|
+
UList<UserKey>
|
|
40
39
|
>({
|
|
41
40
|
key: `usersIndex`,
|
|
42
|
-
class:
|
|
41
|
+
class: UList,
|
|
43
42
|
})
|
|
44
43
|
export const usersOfSockets: JoinToken<
|
|
45
44
|
`user`,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type * as AtomIO from "atom.io"
|
|
2
2
|
import { getFromStore, IMPLICIT, subscribeToState } from "atom.io/internal"
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
|
+
import { employSocket } from "atom.io/realtime"
|
|
4
5
|
|
|
5
6
|
import type { ServerConfig } from "."
|
|
6
|
-
import { employSocket } from "./employ-socket"
|
|
7
7
|
|
|
8
8
|
export type StateProvider = ReturnType<typeof realtimeStateProvider>
|
|
9
9
|
export function realtimeStateProvider({
|
|
@@ -3,18 +3,15 @@ import {
|
|
|
3
3
|
findInStore,
|
|
4
4
|
getFromStore,
|
|
5
5
|
IMPLICIT,
|
|
6
|
+
operateOnStore,
|
|
7
|
+
OWN_OP,
|
|
6
8
|
setIntoStore,
|
|
7
9
|
subscribeToState,
|
|
8
10
|
} from "atom.io/internal"
|
|
9
|
-
import {
|
|
10
|
-
operateOnStore,
|
|
11
|
-
OWN_OP,
|
|
12
|
-
} from "atom.io/internal/set-state/operate-on-store"
|
|
13
11
|
import type { Json } from "atom.io/json"
|
|
14
|
-
import { mutexAtoms } from "atom.io/realtime
|
|
12
|
+
import { employSocket, mutexAtoms } from "atom.io/realtime"
|
|
15
13
|
|
|
16
14
|
import type { ServerConfig } from "."
|
|
17
|
-
import { employSocket } from "./employ-socket"
|
|
18
15
|
|
|
19
16
|
export type StateReceiver = ReturnType<typeof realtimeStateReceiver>
|
|
20
17
|
export function realtimeStateReceiver({
|
|
@@ -19,7 +19,7 @@ import * as AR from "atom.io/react"
|
|
|
19
19
|
import * as RTC from "atom.io/realtime-client"
|
|
20
20
|
import * as RTR from "atom.io/realtime-react"
|
|
21
21
|
import * as RTS from "atom.io/realtime-server"
|
|
22
|
-
import {
|
|
22
|
+
import { UList } from "atom.io/transceivers/u-list"
|
|
23
23
|
import * as Happy from "happy-dom"
|
|
24
24
|
import * as React from "react"
|
|
25
25
|
import * as SocketIO from "socket.io"
|
|
@@ -45,9 +45,8 @@ function prefixLogger(store: Store, prefix: string) {
|
|
|
45
45
|
if (param instanceof ChildProcess) {
|
|
46
46
|
params[idx] = `ChildProcess:${param.pid}`
|
|
47
47
|
}
|
|
48
|
-
if (param instanceof
|
|
49
|
-
params[idx] =
|
|
50
|
-
`SetRTX(${param.size}) {${[...param].join(`, `)}} at ${param.cacheIdx}`
|
|
48
|
+
if (param instanceof UList) {
|
|
49
|
+
params[idx] = `UList(${param.size}) {${[...param].join(`, `)}}`
|
|
51
50
|
}
|
|
52
51
|
idx++
|
|
53
52
|
}
|
|
@@ -72,6 +71,7 @@ export type TestSetupOptions = {
|
|
|
72
71
|
server: (tools: {
|
|
73
72
|
socket: SocketIO.Socket
|
|
74
73
|
silo: AtomIO.Silo
|
|
74
|
+
userKey: RTS.UserKey
|
|
75
75
|
enableLogging: () => void
|
|
76
76
|
}) => (() => void) | void
|
|
77
77
|
}
|
|
@@ -155,24 +155,25 @@ export const setupRealtimeTestServer = (
|
|
|
155
155
|
setIntoStore(silo.store, RTS.socketIndex, (index) =>
|
|
156
156
|
index.add(socketClaim),
|
|
157
157
|
)
|
|
158
|
-
// console.log(`${username} connected on ${socket.id}`)
|
|
159
158
|
next()
|
|
160
159
|
} else {
|
|
161
160
|
next(new Error(`Authentication error`))
|
|
162
161
|
}
|
|
163
162
|
})
|
|
164
163
|
|
|
165
|
-
const
|
|
164
|
+
const socketServices = new Set<() => void>()
|
|
165
|
+
const disposeAllSocketServices = () => {
|
|
166
|
+
for (const disposeService of socketServices) disposeService()
|
|
167
|
+
}
|
|
166
168
|
|
|
167
169
|
server.on(`connection`, (socket: SocketIO.Socket) => {
|
|
168
|
-
|
|
170
|
+
const userKeyState = findRelationsInStore(
|
|
171
|
+
RTS.usersOfSockets,
|
|
172
|
+
`socket::${socket.id}`,
|
|
173
|
+
silo.store,
|
|
174
|
+
).userKeyOfSocket
|
|
175
|
+
const userKey = getFromStore(silo.store, userKeyState)!
|
|
169
176
|
function enableLogging() {
|
|
170
|
-
const userKeyState = findRelationsInStore(
|
|
171
|
-
RTS.usersOfSockets,
|
|
172
|
-
`socket::${socket.id}`,
|
|
173
|
-
silo.store,
|
|
174
|
-
).userKeyOfSocket
|
|
175
|
-
userKey = getFromStore(silo.store, userKeyState)
|
|
176
177
|
prefixLogger(silo.store, `server`)
|
|
177
178
|
socket.onAny((event, ...args) => {
|
|
178
179
|
console.log(`🛰 `, userKey, event, ...args)
|
|
@@ -184,16 +185,20 @@ export const setupRealtimeTestServer = (
|
|
|
184
185
|
console.log(`${userKey} disconnected`)
|
|
185
186
|
})
|
|
186
187
|
}
|
|
187
|
-
const disposeServices = options.server({
|
|
188
|
+
const disposeServices = options.server({
|
|
189
|
+
socket,
|
|
190
|
+
enableLogging,
|
|
191
|
+
silo,
|
|
192
|
+
userKey,
|
|
193
|
+
})
|
|
188
194
|
if (disposeServices) {
|
|
189
|
-
|
|
195
|
+
socketServices.add(disposeServices)
|
|
196
|
+
socket.on(`disconnect`, disposeServices)
|
|
190
197
|
}
|
|
191
198
|
})
|
|
192
199
|
|
|
193
200
|
const dispose = async () => {
|
|
194
|
-
|
|
195
|
-
disposeSocketServices()
|
|
196
|
-
}
|
|
201
|
+
disposeAllSocketServices()
|
|
197
202
|
await server.close()
|
|
198
203
|
|
|
199
204
|
// const roomKeys = getFromStore(silo.store, RT.roomIndex)
|