atom.io 0.40.6 → 0.40.8
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/README.md +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +1 -2
- package/dist/data/index.js.map +1 -1
- package/dist/employ-socket-D6wgByWh.js +12 -0
- package/dist/employ-socket-D6wgByWh.js.map +1 -0
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/has-role-CMlaUlaf.js +1133 -0
- package/dist/has-role-CMlaUlaf.js.map +1 -0
- package/dist/internal/index.d.ts +248 -248
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +590 -1803
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +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/is-fn-DY1wZ-md.js +10 -0
- package/dist/is-fn-DY1wZ-md.js.map +1 -0
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts +33 -33
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +3 -4
- package/dist/main/index.js.map +1 -1
- package/dist/mutex-store-CSvxY9i3.js +11 -0
- package/dist/mutex-store-CSvxY9i3.js.map +1 -0
- package/dist/react/index.d.ts +5 -5
- 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 +9 -11
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +7 -15
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +4 -35
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +6 -9
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +96 -88
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +17 -13
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +39 -50
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +83 -84
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +604 -543
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +5 -4
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +35 -22
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/shared-room-store-BfW3nWif.js +31 -0
- package/dist/shared-room-store-BfW3nWif.js.map +1 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +4 -8
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/web/index.d.ts +3 -3
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +4 -3
- package/dist/web/index.js.map +1 -1
- package/package.json +13 -13
- package/src/internal/atom/create-regular-atom.ts +5 -4
- package/src/internal/atom/dispose-atom.ts +7 -2
- package/src/internal/atom/has-role.ts +3 -3
- package/src/internal/caching.ts +4 -2
- package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
- package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
- package/src/internal/families/create-regular-atom-family.ts +2 -1
- package/src/internal/families/create-writable-held-selector-family.ts +2 -1
- package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
- package/src/internal/families/dispose-from-store.ts +4 -4
- package/src/internal/families/find-in-store.ts +10 -10
- package/src/internal/families/get-family-of-token.ts +2 -2
- package/src/internal/families/index.ts +1 -0
- package/src/internal/families/mint-in-store.ts +54 -19
- package/src/internal/families/seek-in-store.ts +1 -1
- package/src/internal/get-state/get-fallback.ts +2 -2
- package/src/internal/get-state/get-from-store.ts +5 -5
- package/src/internal/get-state/read-or-compute-value.ts +1 -1
- package/src/internal/get-state/reduce-reference.ts +8 -6
- package/src/internal/index.ts +2 -220
- package/src/internal/molecule.ts +1 -2
- package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
- package/src/internal/mutable/create-mutable-atom.ts +4 -2
- package/src/internal/mutable/get-json-family.ts +1 -1
- package/src/internal/mutable/get-update-family.ts +1 -1
- package/src/internal/mutable/tracker-family.ts +2 -1
- package/src/internal/mutable/tracker.ts +71 -59
- package/src/internal/safe-compute.ts +1 -1
- package/src/internal/selector/create-readonly-held-selector.ts +2 -1
- package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
- package/src/internal/selector/create-writable-held-selector.ts +2 -1
- package/src/internal/selector/create-writable-pure-selector.ts +2 -1
- package/src/internal/selector/dispose-selector.ts +3 -2
- package/src/internal/selector/register-selector.ts +8 -5
- package/src/internal/selector/trace-selector-atoms.ts +2 -1
- package/src/internal/set-state/dispatch-state-update.ts +3 -2
- package/src/internal/set-state/evict-downstream.ts +1 -1
- package/src/internal/set-state/operate-on-store.ts +16 -22
- package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
- package/src/internal/set-state/reset-in-store.ts +5 -5
- package/src/internal/set-state/set-atom-or-selector.ts +2 -2
- package/src/internal/set-state/set-atom.ts +4 -2
- package/src/internal/set-state/set-into-store.ts +21 -39
- package/src/internal/set-state/set-selector.ts +3 -2
- package/src/internal/state-types.ts +228 -0
- package/src/internal/store/deposit.ts +4 -4
- package/src/internal/store/index.ts +0 -1
- package/src/internal/store/store.ts +9 -9
- package/src/internal/store/withdraw.ts +4 -4
- package/src/internal/subscribe/recall-state.ts +1 -1
- package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
- package/src/internal/subscribe/subscribe-to-state.ts +9 -0
- package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
- package/src/internal/transaction/build-transaction.ts +3 -2
- package/src/internal/transaction/index.ts +1 -23
- package/src/internal/transaction/is-root-store.ts +4 -1
- package/src/internal/transaction/transaction-meta-progress.ts +22 -0
- package/src/main/atom.ts +1 -2
- package/src/main/find-state.ts +5 -5
- package/src/main/get-state.ts +4 -4
- package/src/main/realm.ts +2 -2
- package/src/main/set-state.ts +10 -10
- package/src/react/parse-state-overloads.ts +3 -3
- package/src/react/use-i.ts +6 -4
- package/src/react/use-loadable.ts +4 -10
- package/src/react/use-o.ts +6 -4
- package/src/react-devtools/store.ts +6 -6
- package/src/realtime/index.ts +1 -0
- package/src/realtime/mutex-store.ts +11 -0
- package/src/realtime/realtime-continuity.ts +1 -5
- package/src/realtime-client/index.ts +0 -1
- package/src/realtime-client/pull-atom-family-member.ts +14 -17
- package/src/realtime-client/pull-atom.ts +1 -1
- package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
- package/src/realtime-client/pull-selector-family-member.ts +8 -35
- package/src/realtime-client/pull-selector-roots.ts +90 -0
- package/src/realtime-client/pull-selector.ts +2 -27
- package/src/realtime-client/push-state.ts +33 -5
- package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
- package/src/realtime-react/index.ts +2 -2
- package/src/realtime-react/realtime-context.tsx +9 -5
- package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
- package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
- package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
- package/src/realtime-react/use-push.ts +7 -3
- package/src/realtime-react/use-realtime-service.ts +11 -11
- package/src/realtime-react/use-single-effect.ts +11 -14
- package/src/realtime-server/{realtime-server-stores/server-sync-store.ts → 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} +15 -13
- package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +10 -8
- package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +6 -4
- package/src/realtime-server/continuity/receive-action-requests.ts +68 -0
- package/src/realtime-server/continuity/track-acknowledgements.ts +46 -0
- package/src/realtime-server/employ-socket.ts +14 -0
- package/src/realtime-server/index.ts +3 -22
- package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
- package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
- package/src/realtime-server/ipc-sockets/parent-socket.ts +98 -69
- package/src/realtime-server/realtime-family-provider.ts +78 -29
- package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
- package/src/realtime-server/realtime-mutable-provider.ts +30 -22
- package/src/realtime-server/realtime-server-stores/index.ts +0 -2
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
- package/src/realtime-server/realtime-state-provider.ts +30 -29
- package/src/realtime-server/realtime-state-receiver.ts +62 -16
- package/src/realtime-server/server-config.ts +8 -0
- package/src/realtime-server/socket-interface.ts +14 -0
- package/src/realtime-testing/setup-realtime-test.tsx +70 -31
- package/src/web/index.ts +1 -1
- package/src/web/{persist-sync.ts → storage-sync.ts} +5 -2
- package/src/internal/store/mint-or-counterfeit.ts +0 -108
- package/src/realtime-client/server-action.ts +0 -23
- package/src/realtime-react/on-mount.ts +0 -5
- 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/continuity/prepare-to-track-client-acknowledgement.ts +0 -41
- package/src/realtime-server/realtime-action-receiver.ts +0 -40
- package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +0 -79
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream"
|
|
2
|
+
|
|
1
3
|
import { Subject } from "atom.io/internal"
|
|
2
4
|
import type { Json } from "atom.io/json"
|
|
3
5
|
import { parseJson, stringifyJson } from "atom.io/json"
|
|
4
6
|
import { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
5
7
|
|
|
6
|
-
import type {
|
|
8
|
+
import type { UserKey } from "../realtime-server-stores"
|
|
9
|
+
import type { StderrLog } from "./child-socket"
|
|
10
|
+
import type { EventBuffer, EventPayload, Events } from "./custom-socket"
|
|
7
11
|
import { CustomSocket } from "./custom-socket"
|
|
8
12
|
|
|
9
13
|
export class SubjectSocket<
|
|
10
14
|
I extends Events,
|
|
11
15
|
O extends Events,
|
|
12
16
|
> extends CustomSocket<I, O> {
|
|
13
|
-
public in: Subject<
|
|
14
|
-
public out: Subject<
|
|
17
|
+
public in: Subject<EventPayload<I>>
|
|
18
|
+
public out: Subject<EventPayload<O>>
|
|
15
19
|
public id = `no_id_retrieved`
|
|
16
20
|
public disposalFunctions: (() => void)[] = []
|
|
17
21
|
|
|
@@ -24,7 +28,7 @@ export class SubjectSocket<
|
|
|
24
28
|
this.in = new Subject()
|
|
25
29
|
this.out = new Subject()
|
|
26
30
|
this.in.subscribe(`socket`, (event) => {
|
|
27
|
-
this.handleEvent(...
|
|
31
|
+
this.handleEvent(...event)
|
|
28
32
|
})
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -35,31 +39,41 @@ export class SubjectSocket<
|
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
export type ParentProcess = {
|
|
43
|
+
pid?: number | undefined
|
|
44
|
+
stdin: Readable
|
|
45
|
+
stdout: Writable
|
|
46
|
+
stderr: Writable
|
|
47
|
+
exit: (code?: number) => void
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
export class ParentSocket<
|
|
39
51
|
I extends Events & {
|
|
40
|
-
[id in string as `relay
|
|
52
|
+
[id in string as `relay::${id}`]: [string, ...Json.Array[]]
|
|
41
53
|
},
|
|
42
54
|
O extends Events & {
|
|
43
|
-
[id in string as `user
|
|
55
|
+
[id in string as `user::${id}`]: [string, ...Json.Array[]]
|
|
44
56
|
} & {
|
|
45
57
|
/* eslint-disable quotes */
|
|
46
|
-
"user-joins": [
|
|
47
|
-
"user-leaves": [
|
|
58
|
+
"user-joins": [key: UserKey]
|
|
59
|
+
"user-leaves": [key: UserKey]
|
|
48
60
|
/* eslint-enable quotes */
|
|
49
61
|
},
|
|
62
|
+
P extends ParentProcess = ParentProcess,
|
|
50
63
|
> extends CustomSocket<I, O> {
|
|
51
64
|
protected incompleteData = ``
|
|
52
65
|
protected unprocessedEvents: string[] = []
|
|
53
66
|
protected relays: Map<string, SubjectSocket<any, any>>
|
|
54
67
|
protected relayServices: ((
|
|
55
68
|
socket: SubjectSocket<any, any>,
|
|
69
|
+
userKey: UserKey,
|
|
56
70
|
) => (() => void) | void)[]
|
|
57
|
-
|
|
71
|
+
public proc: P
|
|
58
72
|
|
|
59
73
|
public id = `#####`
|
|
60
74
|
|
|
61
|
-
protected log(...args:
|
|
62
|
-
this.
|
|
75
|
+
protected log(...args: StderrLog): void {
|
|
76
|
+
this.proc.stderr.write(
|
|
63
77
|
stringifyJson(
|
|
64
78
|
args.map((arg) =>
|
|
65
79
|
arg instanceof SetRTX
|
|
@@ -70,100 +84,112 @@ export class ParentSocket<
|
|
|
70
84
|
)
|
|
71
85
|
}
|
|
72
86
|
public logger = {
|
|
73
|
-
info: (...args:
|
|
87
|
+
info: (...args: Json.Array): void => {
|
|
74
88
|
this.log(`i`, ...args)
|
|
75
89
|
},
|
|
76
|
-
warn: (...args:
|
|
90
|
+
warn: (...args: Json.Array): void => {
|
|
77
91
|
this.log(`w`, ...args)
|
|
78
92
|
},
|
|
79
|
-
error: (...args:
|
|
93
|
+
error: (...args: Json.Array): void => {
|
|
80
94
|
this.log(`e`, ...args)
|
|
81
95
|
},
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
public constructor() {
|
|
98
|
+
public constructor(proc: P) {
|
|
85
99
|
super((event, ...args) => {
|
|
86
100
|
const stringifiedEvent = JSON.stringify([event, ...args])
|
|
87
|
-
this.
|
|
101
|
+
this.proc.stdout.write(stringifiedEvent + `\x03`)
|
|
88
102
|
return this
|
|
89
103
|
})
|
|
90
|
-
this.
|
|
91
|
-
this.
|
|
104
|
+
this.proc = proc
|
|
105
|
+
this.proc.stdin.resume()
|
|
92
106
|
this.relays = new Map()
|
|
93
107
|
this.relayServices = []
|
|
94
|
-
// this.logger.info(`🔗`, `uplink`, process.pid)
|
|
95
108
|
|
|
96
|
-
this.
|
|
109
|
+
this.proc.stdin.on(
|
|
97
110
|
`data`,
|
|
98
|
-
<
|
|
111
|
+
<K extends string & keyof I>(buffer: EventBuffer<I, K>) => {
|
|
99
112
|
const chunk = buffer.toString()
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
this.incompleteData
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
const pieces = chunk.split(`\x03`)
|
|
114
|
+
const initialMaybeWellFormed = pieces[0]
|
|
115
|
+
pieces[0] = this.incompleteData + initialMaybeWellFormed
|
|
116
|
+
let idx = 0
|
|
117
|
+
for (const piece of pieces) {
|
|
118
|
+
if (piece === ``) {
|
|
119
|
+
continue
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const jsonPiece = parseJson(piece)
|
|
123
|
+
this.logger.info(`🎰`, `received`, jsonPiece)
|
|
124
|
+
this.handleEvent(...(jsonPiece as EventPayload<I>))
|
|
125
|
+
this.incompleteData = ``
|
|
126
|
+
} catch (thrown0) {
|
|
127
|
+
if (thrown0 instanceof Error) {
|
|
128
|
+
this.logger.error(
|
|
129
|
+
[
|
|
130
|
+
`received malformed data from parent process:`,
|
|
131
|
+
``,
|
|
132
|
+
piece,
|
|
133
|
+
``,
|
|
134
|
+
thrown0.message,
|
|
135
|
+
].join(`\n❌\t`),
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
if (idx === 0) {
|
|
140
|
+
this.incompleteData = piece
|
|
141
|
+
const maybeActualJsonPiece = parseJson(initialMaybeWellFormed)
|
|
142
|
+
this.logger.info(`🎰`, `received`, maybeActualJsonPiece)
|
|
143
|
+
this.handleEvent(...(maybeActualJsonPiece as EventPayload<I>))
|
|
144
|
+
this.incompleteData = ``
|
|
145
|
+
} else {
|
|
146
|
+
this.incompleteData += piece
|
|
147
|
+
}
|
|
148
|
+
} catch (thrown1) {
|
|
149
|
+
if (thrown1 instanceof Error) {
|
|
150
|
+
this.logger.error(
|
|
151
|
+
[
|
|
152
|
+
`received malformed data from parent process:`,
|
|
153
|
+
``,
|
|
154
|
+
initialMaybeWellFormed,
|
|
155
|
+
``,
|
|
156
|
+
thrown1.message,
|
|
157
|
+
].join(`\n❌\t`),
|
|
158
|
+
)
|
|
113
159
|
}
|
|
114
|
-
const parsedEvent = parseJson(event)
|
|
115
|
-
this.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))
|
|
116
160
|
}
|
|
117
161
|
}
|
|
118
|
-
|
|
119
|
-
} catch (thrown) {
|
|
120
|
-
if (thrown instanceof Error) {
|
|
121
|
-
this.logger.error(`❗`, thrown.message, thrown.cause, thrown.stack)
|
|
122
|
-
}
|
|
162
|
+
++idx
|
|
123
163
|
}
|
|
124
164
|
},
|
|
125
165
|
)
|
|
126
166
|
|
|
127
167
|
this.on(`exit`, () => {
|
|
128
168
|
this.logger.info(`🔥`, this.id, `received "exit"`)
|
|
129
|
-
|
|
130
|
-
})
|
|
131
|
-
process.on(`exit`, (code) => {
|
|
132
|
-
this.logger.info(`🔥`, this.id, `exited with code ${code}`)
|
|
133
|
-
})
|
|
134
|
-
process.on(`end`, () => {
|
|
135
|
-
this.logger.info(`🔥`, this.id, `ended`)
|
|
136
|
-
process.exit(0)
|
|
137
|
-
})
|
|
138
|
-
process.on(`SIGTERM`, () => {
|
|
139
|
-
this.logger.error(`🔥`, this.id, `terminated`)
|
|
140
|
-
process.exit(0)
|
|
141
|
-
})
|
|
142
|
-
process.on(`SIGINT`, () => {
|
|
143
|
-
this.logger.error(`🔥`, this.id, `interrupted`)
|
|
144
|
-
process.exit(0)
|
|
169
|
+
this.proc.exit(0)
|
|
145
170
|
})
|
|
146
171
|
|
|
147
|
-
if (
|
|
148
|
-
this.id =
|
|
172
|
+
if (this.proc.pid) {
|
|
173
|
+
this.id = this.proc.pid?.toString()
|
|
149
174
|
}
|
|
150
175
|
|
|
151
|
-
this.on(`user-joins`, (username) => {
|
|
176
|
+
this.on(`user-joins`, (username: string) => {
|
|
152
177
|
this.logger.info(`👤`, `user`, username, `joined`)
|
|
153
|
-
const
|
|
178
|
+
const userKey = `user::${username}` satisfies UserKey
|
|
179
|
+
const relay = new SubjectSocket(userKey)
|
|
154
180
|
this.relays.set(username, relay)
|
|
155
181
|
this.logger.info(
|
|
156
182
|
`🔗`,
|
|
157
183
|
`attaching services:`,
|
|
158
184
|
`[${[...this.relayServices.keys()].join(`, `)}]`,
|
|
159
185
|
)
|
|
160
|
-
for (const
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
163
|
-
relay.disposalFunctions.push(
|
|
186
|
+
for (const attachRelay of this.relayServices) {
|
|
187
|
+
const cleanupRelay = attachRelay(relay, userKey)
|
|
188
|
+
if (cleanupRelay) {
|
|
189
|
+
relay.disposalFunctions.push(cleanupRelay)
|
|
164
190
|
}
|
|
165
191
|
}
|
|
166
|
-
this.on(
|
|
192
|
+
this.on(userKey, (...data) => {
|
|
167
193
|
relay.in.next(data)
|
|
168
194
|
})
|
|
169
195
|
relay.out.subscribe(`socket`, (data) => {
|
|
@@ -180,11 +206,14 @@ export class ParentSocket<
|
|
|
180
206
|
}
|
|
181
207
|
})
|
|
182
208
|
|
|
183
|
-
|
|
209
|
+
this.proc.stdout.write(`ALIVE`)
|
|
184
210
|
}
|
|
185
211
|
|
|
186
|
-
public
|
|
187
|
-
attachServices: (
|
|
212
|
+
public receiveRelay(
|
|
213
|
+
attachServices: (
|
|
214
|
+
socket: SubjectSocket<any, any>,
|
|
215
|
+
userKey: UserKey,
|
|
216
|
+
) => (() => void) | void,
|
|
188
217
|
): void {
|
|
189
218
|
this.logger.info(`🔗`, `running relay method`)
|
|
190
219
|
this.relayServices.push(attachServices)
|
|
@@ -5,10 +5,11 @@ import {
|
|
|
5
5
|
IMPLICIT,
|
|
6
6
|
subscribeToState,
|
|
7
7
|
} from "atom.io/internal"
|
|
8
|
-
import type { Canonical, Json } from "atom.io/json"
|
|
8
|
+
import type { Canonical, Json, stringified } from "atom.io/json"
|
|
9
9
|
import { stringifyJson } from "atom.io/json"
|
|
10
10
|
|
|
11
11
|
import type { ServerConfig } from "."
|
|
12
|
+
import { employSocket } from "./employ-socket"
|
|
12
13
|
|
|
13
14
|
export type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>
|
|
14
15
|
export function realtimeAtomFamilyProvider({
|
|
@@ -22,49 +23,97 @@ export function realtimeAtomFamilyProvider({
|
|
|
22
23
|
family: AtomIO.RegularAtomFamilyToken<J, K>,
|
|
23
24
|
index: AtomIO.ReadableToken<Iterable<K>>,
|
|
24
25
|
): () => void {
|
|
25
|
-
const
|
|
26
|
+
const coreSubscriptions = new Set<() => void>()
|
|
27
|
+
const clearCoreSubscriptions = () => {
|
|
28
|
+
for (const unsub of coreSubscriptions) unsub()
|
|
29
|
+
coreSubscriptions.clear()
|
|
30
|
+
}
|
|
31
|
+
const familyMemberSubscriptionsWanted = new Set<stringified<K>>()
|
|
32
|
+
const familyMemberSubscriptions = new Map<string, () => void>()
|
|
33
|
+
const clearFamilySubscriptions = () => {
|
|
34
|
+
for (const unsub of familyMemberSubscriptions.values()) unsub()
|
|
35
|
+
familyMemberSubscriptions.clear()
|
|
36
|
+
}
|
|
26
37
|
|
|
27
38
|
const fillUnsubRequest = (key: string) => {
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
const unsubUnsub = familyMemberSubscriptions.get(`${key}:unsub`)
|
|
40
|
+
if (unsubUnsub) {
|
|
41
|
+
unsubUnsub()
|
|
42
|
+
familyMemberSubscriptions.delete(`${key}:unsub`)
|
|
43
|
+
}
|
|
44
|
+
const unsub = familyMemberSubscriptions.get(key)
|
|
30
45
|
if (unsub) {
|
|
31
46
|
unsub()
|
|
32
|
-
|
|
47
|
+
familyMemberSubscriptions.delete(key)
|
|
33
48
|
}
|
|
34
49
|
}
|
|
35
50
|
|
|
36
|
-
const
|
|
37
|
-
const
|
|
51
|
+
const exposeFamilyMembers = (subKey: K) => {
|
|
52
|
+
const token = findInStore(store, family, subKey)
|
|
53
|
+
getFromStore(store, token)
|
|
54
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token))
|
|
55
|
+
familyMemberSubscriptions.set(
|
|
56
|
+
token.key,
|
|
57
|
+
subscribeToState(
|
|
58
|
+
store,
|
|
59
|
+
token,
|
|
60
|
+
`expose-family:${family.key}:${socket.id}`,
|
|
61
|
+
({ newValue }) => {
|
|
62
|
+
socket.emit(`serve:${token.key}`, newValue)
|
|
63
|
+
},
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
familyMemberSubscriptions.set(
|
|
67
|
+
`${token.key}:unsub`,
|
|
68
|
+
employSocket(socket, `unsub:${token.key}`, () => {
|
|
69
|
+
fillUnsubRequest(token.key)
|
|
70
|
+
}),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isAvailable = (exposedSubKeys: Iterable<K>, subKey: K): boolean => {
|
|
38
75
|
for (const exposedSubKey of exposedSubKeys) {
|
|
39
76
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
40
|
-
|
|
41
|
-
socket.emit(`serve:${token.key}`, getFromStore(store, token))
|
|
42
|
-
const unsubscribe = subscribeToState(
|
|
43
|
-
store,
|
|
44
|
-
token,
|
|
45
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
46
|
-
({ newValue }) => {
|
|
47
|
-
socket.emit(`serve:${token.key}`, newValue)
|
|
48
|
-
},
|
|
49
|
-
)
|
|
50
|
-
unsubCallbacksByKey.set(token.key, unsubscribe)
|
|
51
|
-
socket.on(`unsub:${token.key}`, () => {
|
|
52
|
-
fillUnsubRequest(token.key)
|
|
53
|
-
})
|
|
54
|
-
break
|
|
77
|
+
return true
|
|
55
78
|
}
|
|
56
79
|
}
|
|
80
|
+
return false
|
|
57
81
|
}
|
|
58
82
|
|
|
59
|
-
|
|
83
|
+
const start = () => {
|
|
84
|
+
coreSubscriptions.add(
|
|
85
|
+
employSocket(socket, `sub:${family.key}`, (subKey: K) => {
|
|
86
|
+
const exposedSubKeys = getFromStore(store, index)
|
|
87
|
+
const shouldExpose = isAvailable(exposedSubKeys, subKey)
|
|
88
|
+
if (shouldExpose) {
|
|
89
|
+
exposeFamilyMembers(subKey)
|
|
90
|
+
} else {
|
|
91
|
+
familyMemberSubscriptionsWanted.add(stringifyJson(subKey))
|
|
92
|
+
socket.emit(`unavailable:${family.key}`, subKey)
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
)
|
|
96
|
+
coreSubscriptions.add(
|
|
97
|
+
subscribeToState(
|
|
98
|
+
store,
|
|
99
|
+
index,
|
|
100
|
+
`expose-family:${family.key}:${socket.id}`,
|
|
101
|
+
({ newValue: newExposedSubKeys }) => {
|
|
102
|
+
for (const subKey of newExposedSubKeys) {
|
|
103
|
+
if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
|
|
104
|
+
exposeFamilyMembers(subKey)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
60
111
|
|
|
61
|
-
|
|
62
|
-
socket.off(`sub:${family.key}`, fillSubRequest)
|
|
112
|
+
start()
|
|
63
113
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
unsubCallbacksByKey.clear()
|
|
114
|
+
return () => {
|
|
115
|
+
clearCoreSubscriptions()
|
|
116
|
+
clearFamilySubscriptions()
|
|
68
117
|
}
|
|
69
118
|
}
|
|
70
119
|
}
|
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
IMPLICIT,
|
|
9
9
|
subscribeToState,
|
|
10
10
|
} from "atom.io/internal"
|
|
11
|
-
import type { Canonical } from "atom.io/json"
|
|
11
|
+
import type { Canonical, stringified } from "atom.io/json"
|
|
12
12
|
import { stringifyJson } from "atom.io/json"
|
|
13
13
|
|
|
14
14
|
import type { ServerConfig } from "."
|
|
15
|
+
import { employSocket } from "./employ-socket"
|
|
15
16
|
|
|
16
17
|
export type MutableFamilyProvider = ReturnType<
|
|
17
18
|
typeof realtimeMutableFamilyProvider
|
|
@@ -27,51 +28,99 @@ export function realtimeMutableFamilyProvider({
|
|
|
27
28
|
family: AtomIO.MutableAtomFamilyToken<T, K>,
|
|
28
29
|
index: AtomIO.ReadableToken<Iterable<K>>,
|
|
29
30
|
): () => void {
|
|
30
|
-
const
|
|
31
|
+
const coreSubscriptions = new Set<() => void>()
|
|
32
|
+
const clearCoreSubscriptions = () => {
|
|
33
|
+
for (const unsub of coreSubscriptions) unsub()
|
|
34
|
+
coreSubscriptions.clear()
|
|
35
|
+
}
|
|
36
|
+
const familyMemberSubscriptionsWanted = new Set<stringified<K>>()
|
|
37
|
+
const familyMemberSubscriptions = new Map<string, () => void>()
|
|
38
|
+
const clearFamilySubscriptions = () => {
|
|
39
|
+
for (const unsub of familyMemberSubscriptions.values()) unsub()
|
|
40
|
+
familyMemberSubscriptions.clear()
|
|
41
|
+
}
|
|
31
42
|
|
|
32
43
|
const fillUnsubRequest = (key: string) => {
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
const unsubUnsub = familyMemberSubscriptions.get(`${key}:unsub`)
|
|
45
|
+
if (unsubUnsub) {
|
|
46
|
+
unsubUnsub()
|
|
47
|
+
familyMemberSubscriptions.delete(`${key}:unsub`)
|
|
48
|
+
}
|
|
49
|
+
const unsub = familyMemberSubscriptions.get(key)
|
|
35
50
|
if (unsub) {
|
|
36
51
|
unsub()
|
|
37
|
-
|
|
52
|
+
familyMemberSubscriptions.delete(key)
|
|
38
53
|
}
|
|
39
54
|
}
|
|
40
55
|
|
|
41
|
-
const
|
|
42
|
-
const
|
|
56
|
+
const exposeFamilyMembers = (subKey: K) => {
|
|
57
|
+
const token = findInStore(store, family, subKey)
|
|
58
|
+
getFromStore(store, token)
|
|
59
|
+
const jsonToken = getJsonToken(store, token)
|
|
60
|
+
const updateToken = getUpdateToken(token)
|
|
61
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
|
|
62
|
+
familyMemberSubscriptions.set(
|
|
63
|
+
token.key,
|
|
64
|
+
subscribeToState(
|
|
65
|
+
store,
|
|
66
|
+
updateToken,
|
|
67
|
+
`expose-family:${family.key}:${socket.id}`,
|
|
68
|
+
({ newValue }) => {
|
|
69
|
+
socket.emit(`next:${token.key}`, newValue)
|
|
70
|
+
},
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
familyMemberSubscriptions.set(
|
|
74
|
+
`${token.key}:unsub`,
|
|
75
|
+
employSocket(socket, `unsub:${token.key}`, () => {
|
|
76
|
+
fillUnsubRequest(token.key)
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const isAvailable = (exposedSubKeys: Iterable<K>, subKey: K): boolean => {
|
|
43
82
|
for (const exposedSubKey of exposedSubKeys) {
|
|
44
83
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
45
|
-
|
|
46
|
-
getFromStore(store, token)
|
|
47
|
-
const jsonToken = getJsonToken(store, token)
|
|
48
|
-
const updateToken = getUpdateToken(token)
|
|
49
|
-
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
|
|
50
|
-
const unsubscribe = subscribeToState(
|
|
51
|
-
store,
|
|
52
|
-
updateToken,
|
|
53
|
-
`expose-family:${family.key}:${socket.id}`,
|
|
54
|
-
({ newValue }) => {
|
|
55
|
-
socket.emit(`next:${token.key}`, newValue)
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
unsubCallbacksByKey.set(token.key, unsubscribe)
|
|
59
|
-
socket.on(`unsub:${token.key}`, () => {
|
|
60
|
-
fillUnsubRequest(token.key)
|
|
61
|
-
})
|
|
62
|
-
break
|
|
84
|
+
return true
|
|
63
85
|
}
|
|
64
86
|
}
|
|
87
|
+
return false
|
|
65
88
|
}
|
|
66
89
|
|
|
67
|
-
|
|
90
|
+
const start = () => {
|
|
91
|
+
coreSubscriptions.add(
|
|
92
|
+
employSocket(socket, `sub:${family.key}`, (subKey: K) => {
|
|
93
|
+
const exposedSubKeys = getFromStore(store, index)
|
|
94
|
+
const shouldExpose = isAvailable(exposedSubKeys, subKey)
|
|
95
|
+
if (shouldExpose) {
|
|
96
|
+
exposeFamilyMembers(subKey)
|
|
97
|
+
} else {
|
|
98
|
+
familyMemberSubscriptionsWanted.add(stringifyJson(subKey))
|
|
99
|
+
socket.emit(`unavailable:${family.key}`, subKey)
|
|
100
|
+
}
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
103
|
+
coreSubscriptions.add(
|
|
104
|
+
subscribeToState(
|
|
105
|
+
store,
|
|
106
|
+
index,
|
|
107
|
+
`expose-family:${family.key}:${socket.id}`,
|
|
108
|
+
({ newValue: newExposedSubKeys }) => {
|
|
109
|
+
for (const subKey of newExposedSubKeys) {
|
|
110
|
+
if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
|
|
111
|
+
exposeFamilyMembers(subKey)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
start()
|
|
68
120
|
|
|
69
121
|
return () => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
unsub()
|
|
73
|
-
}
|
|
74
|
-
unsubCallbacksByKey.clear()
|
|
122
|
+
clearCoreSubscriptions()
|
|
123
|
+
clearFamilySubscriptions()
|
|
75
124
|
}
|
|
76
125
|
}
|
|
77
126
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import type { Json } from "atom.io/json"
|
|
11
11
|
|
|
12
12
|
import type { ServerConfig } from "."
|
|
13
|
+
import { employSocket } from "./employ-socket"
|
|
13
14
|
|
|
14
15
|
export type MutableProvider = ReturnType<typeof realtimeMutableProvider>
|
|
15
16
|
export function realtimeMutableProvider({
|
|
@@ -19,35 +20,42 @@ export function realtimeMutableProvider({
|
|
|
19
20
|
return function mutableProvider<
|
|
20
21
|
Core extends Transceiver<any, Json.Serializable, Json.Serializable>,
|
|
21
22
|
>(token: AtomIO.MutableAtomToken<Core>): () => void {
|
|
22
|
-
|
|
23
|
+
const subscriptions = new Set<() => void>()
|
|
24
|
+
const clearSubscriptions = () => {
|
|
25
|
+
for (const unsub of subscriptions) unsub()
|
|
26
|
+
subscriptions.clear()
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
const jsonToken = getJsonToken(store, token)
|
|
25
30
|
const trackerToken = getUpdateToken(token)
|
|
26
31
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const start = () => {
|
|
33
|
+
subscriptions.add(
|
|
34
|
+
employSocket(socket, `sub:${token.key}`, () => {
|
|
35
|
+
clearSubscriptions()
|
|
36
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
|
|
37
|
+
subscriptions.add(
|
|
38
|
+
subscribeToState(
|
|
39
|
+
store,
|
|
40
|
+
trackerToken,
|
|
41
|
+
`expose-single:${socket.id}`,
|
|
42
|
+
({ newValue }) => {
|
|
43
|
+
socket.emit(`next:${token.key}`, newValue)
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
subscriptions.add(
|
|
48
|
+
employSocket(socket, `unsub:${token.key}`, () => {
|
|
49
|
+
clearSubscriptions()
|
|
50
|
+
start()
|
|
51
|
+
}),
|
|
52
|
+
)
|
|
53
|
+
}),
|
|
42
54
|
)
|
|
43
|
-
socket.on(`unsub:${token.key}`, fillUnsubRequest)
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
|
|
57
|
+
start()
|
|
47
58
|
|
|
48
|
-
return
|
|
49
|
-
socket.off(`sub:${token.key}`, fillSubRequest)
|
|
50
|
-
unsubscribeFromStateUpdates?.()
|
|
51
|
-
}
|
|
59
|
+
return clearSubscriptions
|
|
52
60
|
}
|
|
53
61
|
}
|