@polytric/openws-sdkgen 0.0.12 → 0.0.14
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/main.cjs +1 -1
- package/dist/main.js +1 -1
- package/dist/plans/typescript.cjs +3 -3
- package/dist/plans/typescript.js +3 -3
- package/dist/templates/typescript/package.json.ejs +1 -1
- package/dist/templates/typescript/src/network.ts.ejs +165 -18
- package/dist/templates/typescript/src/roles/role.ts.ejs +1 -1
- package/dist/templates/typescript/src/sdk/role.ts.ejs +481 -72
- package/package.json +67 -63
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ The CLI exposes the following options:
|
|
|
41
41
|
- `--out` (string): Output directory for generated code.
|
|
42
42
|
- `--project` (string): Project/namespace prefix for generated code.
|
|
43
43
|
- `--network` (string): Network name to generate.
|
|
44
|
-
- `--hostRole` (string):
|
|
44
|
+
- `--hostRole` (string): Peer role name that represents the host side.
|
|
45
45
|
- `--language` (string): Target language (`csharp`, `javascript`, or `typescript`).
|
|
46
46
|
- `--environment` (string|array): Target environment (`unity`, `node`, `browser`).
|
|
47
47
|
|
package/dist/main.cjs
CHANGED
|
@@ -457,7 +457,7 @@ function parseInput(ctx) {
|
|
|
457
457
|
}).option("hostRole", {
|
|
458
458
|
type: "array",
|
|
459
459
|
string: true,
|
|
460
|
-
description: "The target
|
|
460
|
+
description: "The target peer roles that use the generated code",
|
|
461
461
|
demandOption: true
|
|
462
462
|
}).option("language", {
|
|
463
463
|
type: "string",
|
package/dist/main.js
CHANGED
|
@@ -434,7 +434,7 @@ function parseInput(ctx) {
|
|
|
434
434
|
}).option("hostRole", {
|
|
435
435
|
type: "array",
|
|
436
436
|
string: true,
|
|
437
|
-
description: "The target
|
|
437
|
+
description: "The target peer roles that use the generated code",
|
|
438
438
|
demandOption: true
|
|
439
439
|
}).option("language", {
|
|
440
440
|
type: "string",
|
|
@@ -216,7 +216,7 @@ function createPlan(ctx) {
|
|
|
216
216
|
const remoteRoles = getPeerRoles(networkSpec, rolesByName, hostRole.roleName).map(
|
|
217
217
|
(remoteRole) => ({
|
|
218
218
|
...remoteRole,
|
|
219
|
-
|
|
219
|
+
scopedPeerName: `${hostRole.className}${remoteRole.className}Peer`,
|
|
220
220
|
allowedMethodNames: getAllowedMessageMethodNames(
|
|
221
221
|
networkSpec,
|
|
222
222
|
remoteRole.roleName,
|
|
@@ -342,9 +342,9 @@ function toRoleInfo(role) {
|
|
|
342
342
|
className,
|
|
343
343
|
roleClassName: className,
|
|
344
344
|
hostRoleClassName: `${className}Host`,
|
|
345
|
-
|
|
345
|
+
peerName: `${className}Peer`,
|
|
346
346
|
varName: camelCase(role.name),
|
|
347
|
-
|
|
347
|
+
peerVarName: `${camelCase(role.name)}Peer`,
|
|
348
348
|
fileName,
|
|
349
349
|
roleFileName: `${fileName}-role`,
|
|
350
350
|
description: role.description || "",
|
package/dist/plans/typescript.js
CHANGED
|
@@ -176,7 +176,7 @@ function createPlan(ctx) {
|
|
|
176
176
|
const remoteRoles = getPeerRoles(networkSpec, rolesByName, hostRole.roleName).map(
|
|
177
177
|
(remoteRole) => ({
|
|
178
178
|
...remoteRole,
|
|
179
|
-
|
|
179
|
+
scopedPeerName: `${hostRole.className}${remoteRole.className}Peer`,
|
|
180
180
|
allowedMethodNames: getAllowedMessageMethodNames(
|
|
181
181
|
networkSpec,
|
|
182
182
|
remoteRole.roleName,
|
|
@@ -302,9 +302,9 @@ function toRoleInfo(role) {
|
|
|
302
302
|
className,
|
|
303
303
|
roleClassName: className,
|
|
304
304
|
hostRoleClassName: `${className}Host`,
|
|
305
|
-
|
|
305
|
+
peerName: `${className}Peer`,
|
|
306
306
|
varName: camelCase(role.name),
|
|
307
|
-
|
|
307
|
+
peerVarName: `${camelCase(role.name)}Peer`,
|
|
308
308
|
fileName,
|
|
309
309
|
roleFileName: `${fileName}-role`,
|
|
310
310
|
description: role.description || "",
|
|
@@ -9,12 +9,18 @@ export const endpoints = <%- JSON.stringify(
|
|
|
9
9
|
) %>
|
|
10
10
|
|
|
11
11
|
<% if (ctx.isTypeScript) { -%>
|
|
12
|
+
/**
|
|
13
|
+
* Wire-format message envelope used by this OpenWS SDK.
|
|
14
|
+
*/
|
|
12
15
|
export interface OpenWsEnvelope<Payload = unknown> {
|
|
13
16
|
fromRole: string
|
|
14
17
|
messageName: string
|
|
15
18
|
payload: Payload
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Connection endpoint metadata from the OpenWS spec.
|
|
23
|
+
*/
|
|
18
24
|
export interface OpenWsEndpoint {
|
|
19
25
|
scheme: string
|
|
20
26
|
host?: string
|
|
@@ -23,9 +29,15 @@ export interface OpenWsEndpoint {
|
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export type Unsubscribe = () => void
|
|
26
|
-
export type TransportEvent = 'message' | 'error'
|
|
32
|
+
export type TransportEvent = 'message' | 'error' | 'close'
|
|
27
33
|
export type TransportHandler = (data: unknown) => void | Promise<void>
|
|
28
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Minimal transport contract used by generated SDK clients.
|
|
37
|
+
*
|
|
38
|
+
* Implement this interface to plug in a custom socket, browser WebSocket,
|
|
39
|
+
* server-side WebSocket client, or test transport.
|
|
40
|
+
*/
|
|
29
41
|
export interface Transport {
|
|
30
42
|
send(data: string): void | Promise<void>
|
|
31
43
|
on?(event: TransportEvent, handler: TransportHandler): unknown
|
|
@@ -38,24 +50,47 @@ export interface BindTransportOptions {
|
|
|
38
50
|
closeOnError?: boolean
|
|
39
51
|
}
|
|
40
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Callback surface used by `bindTransport`.
|
|
55
|
+
*
|
|
56
|
+
* `handle...` methods are framework entrypoints called by transport glue.
|
|
57
|
+
* Generated clients expose matching `on...` methods for application callbacks.
|
|
58
|
+
*/
|
|
41
59
|
export interface RawMessageHandler {
|
|
42
60
|
handleRawMessage(data: string): void | Promise<void>
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
handleMessageError?(error: unknown): void | Promise<void>
|
|
62
|
+
handleSocketError?(error: unknown): void | Promise<void>
|
|
63
|
+
handleSocketClose?(event: unknown): void | Promise<void>
|
|
45
64
|
}
|
|
46
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Encodes an OpenWS envelope for transport.
|
|
68
|
+
*/
|
|
47
69
|
export function encodeEnvelope(envelope: OpenWsEnvelope): string {
|
|
48
70
|
return JSON.stringify(envelope)
|
|
49
71
|
}
|
|
50
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Decodes raw transport data into an OpenWS envelope.
|
|
75
|
+
*/
|
|
51
76
|
export function decodeEnvelope(data: string): OpenWsEnvelope {
|
|
52
77
|
return JSON.parse(data) as OpenWsEnvelope
|
|
53
78
|
}
|
|
54
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Returns true when a transport can be bound to generated client callbacks.
|
|
82
|
+
*/
|
|
55
83
|
export function canBindTransport(transport: Transport): boolean {
|
|
56
84
|
return typeof transport.on === 'function'
|
|
57
85
|
}
|
|
58
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Binds transport events to a generated client or compatible raw message handler.
|
|
89
|
+
*
|
|
90
|
+
* Transport `message` events call `handleRawMessage`, message handling failures
|
|
91
|
+
* call `handleMessageError`, transport `error` events call `handleSocketError`,
|
|
92
|
+
* and transport `close` events call `handleSocketClose`.
|
|
93
|
+
*/
|
|
59
94
|
export function bindTransport(
|
|
60
95
|
transport: Transport,
|
|
61
96
|
handler: RawMessageHandler,
|
|
@@ -65,14 +100,17 @@ export function bindTransport(
|
|
|
65
100
|
try {
|
|
66
101
|
await handler.handleRawMessage(await normalizeMessageData(data))
|
|
67
102
|
} catch (error) {
|
|
68
|
-
await handler.
|
|
103
|
+
await handler.handleMessageError?.(error)
|
|
69
104
|
if (options.closeOnError) {
|
|
70
105
|
transport.close?.()
|
|
71
106
|
}
|
|
72
107
|
}
|
|
73
108
|
}
|
|
74
109
|
const handleSocketError = async (error: unknown) => {
|
|
75
|
-
await handler.
|
|
110
|
+
await handler.handleSocketError?.(error)
|
|
111
|
+
}
|
|
112
|
+
const handleSocketClose = async (event: unknown) => {
|
|
113
|
+
await handler.handleSocketClose?.(event)
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
const nodeHandler = (data: unknown, ..._args: unknown[]) => {
|
|
@@ -81,6 +119,9 @@ export function bindTransport(
|
|
|
81
119
|
const nodeErrorHandler = (error: unknown, ..._args: unknown[]) => {
|
|
82
120
|
void handleSocketError(error)
|
|
83
121
|
}
|
|
122
|
+
const nodeCloseHandler = (event: unknown, ..._args: unknown[]) => {
|
|
123
|
+
void handleSocketClose(event)
|
|
124
|
+
}
|
|
84
125
|
|
|
85
126
|
if (typeof transport.on !== 'function') {
|
|
86
127
|
throw new Error('Transport must support on("message")')
|
|
@@ -88,12 +129,17 @@ export function bindTransport(
|
|
|
88
129
|
|
|
89
130
|
const messageUnsubscribe = transport.on('message', nodeHandler)
|
|
90
131
|
const errorUnsubscribe = transport.on('error', nodeErrorHandler)
|
|
132
|
+
const closeUnsubscribe = transport.on('close', nodeCloseHandler)
|
|
91
133
|
return () => {
|
|
92
134
|
if (typeof messageUnsubscribe === 'function') messageUnsubscribe()
|
|
93
135
|
if (typeof errorUnsubscribe === 'function') errorUnsubscribe()
|
|
136
|
+
if (typeof closeUnsubscribe === 'function') closeUnsubscribe()
|
|
94
137
|
}
|
|
95
138
|
}
|
|
96
139
|
|
|
140
|
+
/**
|
|
141
|
+
* WebSocket-backed transport implementation for generated SDK clients.
|
|
142
|
+
*/
|
|
97
143
|
export class WsTransport implements Transport {
|
|
98
144
|
private socket?: unknown
|
|
99
145
|
private socketUnsubscribe?: Unsubscribe
|
|
@@ -101,6 +147,7 @@ export class WsTransport implements Transport {
|
|
|
101
147
|
private readonly listeners: Record<TransportEvent, Set<TransportHandler>> = {
|
|
102
148
|
message: new Set(),
|
|
103
149
|
error: new Set(),
|
|
150
|
+
close: new Set(),
|
|
104
151
|
}
|
|
105
152
|
|
|
106
153
|
constructor(socket?: unknown) {
|
|
@@ -109,6 +156,9 @@ export class WsTransport implements Transport {
|
|
|
109
156
|
}
|
|
110
157
|
}
|
|
111
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Opens the underlying WebSocket when needed and waits until it is ready.
|
|
161
|
+
*/
|
|
112
162
|
async connect(_roleName: string, endpoint?: OpenWsEndpoint): Promise<void> {
|
|
113
163
|
if (!this.socket) {
|
|
114
164
|
if (!endpoint) {
|
|
@@ -119,10 +169,16 @@ export class WsTransport implements Transport {
|
|
|
119
169
|
await this.waitForOpen()
|
|
120
170
|
}
|
|
121
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Closes the underlying WebSocket connection.
|
|
174
|
+
*/
|
|
122
175
|
async disconnect(): Promise<void> {
|
|
123
176
|
this.close()
|
|
124
177
|
}
|
|
125
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Sends already-encoded OpenWS envelope data.
|
|
181
|
+
*/
|
|
126
182
|
async send(data: string): Promise<void> {
|
|
127
183
|
await this.waitForOpen()
|
|
128
184
|
const socket = this.requireSocket() as { send?: (data: string) => void | Promise<void> }
|
|
@@ -132,6 +188,9 @@ export class WsTransport implements Transport {
|
|
|
132
188
|
await socket.send(data)
|
|
133
189
|
}
|
|
134
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Registers a transport event callback.
|
|
193
|
+
*/
|
|
135
194
|
on(event: TransportEvent, handler: TransportHandler): Unsubscribe {
|
|
136
195
|
this.listeners[event].add(handler)
|
|
137
196
|
return () => {
|
|
@@ -139,17 +198,17 @@ export class WsTransport implements Transport {
|
|
|
139
198
|
}
|
|
140
199
|
}
|
|
141
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Closes and clears the current socket.
|
|
203
|
+
*/
|
|
142
204
|
close(): void {
|
|
143
205
|
const socket = this.socket as { close?: () => void } | undefined
|
|
144
206
|
socket?.close?.()
|
|
145
|
-
this.
|
|
146
|
-
this.socket = undefined
|
|
147
|
-
this.socketUnsubscribe = undefined
|
|
148
|
-
this.openPromise = undefined
|
|
207
|
+
this.clearSocket()
|
|
149
208
|
}
|
|
150
209
|
|
|
151
210
|
private bindSocket(socket: unknown): void {
|
|
152
|
-
this.
|
|
211
|
+
this.clearSocket()
|
|
153
212
|
this.socket = socket
|
|
154
213
|
this.openPromise = undefined
|
|
155
214
|
|
|
@@ -159,12 +218,31 @@ export class WsTransport implements Transport {
|
|
|
159
218
|
const unsubscribeError = addSocketListener(socket, 'error', error => {
|
|
160
219
|
void this.emit('error', error)
|
|
161
220
|
})
|
|
221
|
+
const unsubscribeClose = addSocketListener(socket, 'close', event => {
|
|
222
|
+
void this.handleSocketClose(socket, event)
|
|
223
|
+
})
|
|
162
224
|
this.socketUnsubscribe = () => {
|
|
163
225
|
unsubscribeMessage()
|
|
164
226
|
unsubscribeError()
|
|
227
|
+
unsubscribeClose()
|
|
165
228
|
}
|
|
166
229
|
}
|
|
167
230
|
|
|
231
|
+
private async handleSocketClose(socket: unknown, event: unknown): Promise<void> {
|
|
232
|
+
if (this.socket !== socket) {
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
this.clearSocket()
|
|
236
|
+
await this.emit('close', event)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private clearSocket(): void {
|
|
240
|
+
this.socketUnsubscribe?.()
|
|
241
|
+
this.socket = undefined
|
|
242
|
+
this.socketUnsubscribe = undefined
|
|
243
|
+
this.openPromise = undefined
|
|
244
|
+
}
|
|
245
|
+
|
|
168
246
|
private async emit(event: TransportEvent, data: unknown): Promise<void> {
|
|
169
247
|
for (const handler of this.listeners[event]) {
|
|
170
248
|
await handler(data)
|
|
@@ -196,9 +274,14 @@ export class WsTransport implements Transport {
|
|
|
196
274
|
cleanup()
|
|
197
275
|
reject(error)
|
|
198
276
|
})
|
|
277
|
+
const unsubscribeClose = addSocketListener(socket, 'close', event => {
|
|
278
|
+
cleanup()
|
|
279
|
+
reject(event instanceof Error ? event : new Error('WebSocket closed before opening'))
|
|
280
|
+
})
|
|
199
281
|
cleanup = () => {
|
|
200
282
|
unsubscribeOpen()
|
|
201
283
|
unsubscribeError()
|
|
284
|
+
unsubscribeClose()
|
|
202
285
|
}
|
|
203
286
|
})
|
|
204
287
|
await this.openPromise
|
|
@@ -243,7 +326,7 @@ function getReadyState(socket: unknown): number | undefined {
|
|
|
243
326
|
|
|
244
327
|
function addSocketListener(
|
|
245
328
|
socket: unknown,
|
|
246
|
-
event: 'open' | 'message' | 'error',
|
|
329
|
+
event: 'open' | 'message' | 'error' | 'close',
|
|
247
330
|
handler: (...args: unknown[]) => void
|
|
248
331
|
): Unsubscribe {
|
|
249
332
|
const target = socket as {
|
|
@@ -289,31 +372,50 @@ function addSocketListener(
|
|
|
289
372
|
}
|
|
290
373
|
}
|
|
291
374
|
<% } else { -%>
|
|
375
|
+
/**
|
|
376
|
+
* Encodes an OpenWS envelope for transport.
|
|
377
|
+
*/
|
|
292
378
|
export function encodeEnvelope(envelope) {
|
|
293
379
|
return JSON.stringify(envelope)
|
|
294
380
|
}
|
|
295
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Decodes raw transport data into an OpenWS envelope.
|
|
384
|
+
*/
|
|
296
385
|
export function decodeEnvelope(data) {
|
|
297
386
|
return JSON.parse(data)
|
|
298
387
|
}
|
|
299
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Returns true when a transport can be bound to generated client callbacks.
|
|
391
|
+
*/
|
|
300
392
|
export function canBindTransport(transport) {
|
|
301
393
|
return typeof transport.on === 'function'
|
|
302
394
|
}
|
|
303
395
|
|
|
396
|
+
/**
|
|
397
|
+
* Binds transport events to a generated client or compatible raw message handler.
|
|
398
|
+
*
|
|
399
|
+
* Transport `message` events call `handleRawMessage`, message handling failures
|
|
400
|
+
* call `handleMessageError`, transport `error` events call `handleSocketError`,
|
|
401
|
+
* and transport `close` events call `handleSocketClose`.
|
|
402
|
+
*/
|
|
304
403
|
export function bindTransport(transport, handler, options = {}) {
|
|
305
404
|
const handleData = async data => {
|
|
306
405
|
try {
|
|
307
406
|
await handler.handleRawMessage(await normalizeMessageData(data))
|
|
308
407
|
} catch (error) {
|
|
309
|
-
await handler.
|
|
408
|
+
await handler.handleMessageError?.(error)
|
|
310
409
|
if (options.closeOnError) {
|
|
311
410
|
transport.close?.()
|
|
312
411
|
}
|
|
313
412
|
}
|
|
314
413
|
}
|
|
315
414
|
const handleSocketError = async error => {
|
|
316
|
-
await handler.
|
|
415
|
+
await handler.handleSocketError?.(error)
|
|
416
|
+
}
|
|
417
|
+
const handleSocketClose = async event => {
|
|
418
|
+
await handler.handleSocketClose?.(event)
|
|
317
419
|
}
|
|
318
420
|
|
|
319
421
|
const nodeHandler = data => {
|
|
@@ -322,6 +424,9 @@ export function bindTransport(transport, handler, options = {}) {
|
|
|
322
424
|
const nodeErrorHandler = error => {
|
|
323
425
|
void handleSocketError(error)
|
|
324
426
|
}
|
|
427
|
+
const nodeCloseHandler = event => {
|
|
428
|
+
void handleSocketClose(event)
|
|
429
|
+
}
|
|
325
430
|
|
|
326
431
|
if (typeof transport.on !== 'function') {
|
|
327
432
|
throw new Error('Transport must support on("message")')
|
|
@@ -329,12 +434,17 @@ export function bindTransport(transport, handler, options = {}) {
|
|
|
329
434
|
|
|
330
435
|
const messageUnsubscribe = transport.on('message', nodeHandler)
|
|
331
436
|
const errorUnsubscribe = transport.on('error', nodeErrorHandler)
|
|
437
|
+
const closeUnsubscribe = transport.on('close', nodeCloseHandler)
|
|
332
438
|
return () => {
|
|
333
439
|
if (typeof messageUnsubscribe === 'function') messageUnsubscribe()
|
|
334
440
|
if (typeof errorUnsubscribe === 'function') errorUnsubscribe()
|
|
441
|
+
if (typeof closeUnsubscribe === 'function') closeUnsubscribe()
|
|
335
442
|
}
|
|
336
443
|
}
|
|
337
444
|
|
|
445
|
+
/**
|
|
446
|
+
* WebSocket-backed transport implementation for generated SDK clients.
|
|
447
|
+
*/
|
|
338
448
|
export class WsTransport {
|
|
339
449
|
socket
|
|
340
450
|
socketUnsubscribe
|
|
@@ -342,6 +452,7 @@ export class WsTransport {
|
|
|
342
452
|
listeners = {
|
|
343
453
|
message: new Set(),
|
|
344
454
|
error: new Set(),
|
|
455
|
+
close: new Set(),
|
|
345
456
|
}
|
|
346
457
|
|
|
347
458
|
constructor(socket) {
|
|
@@ -350,6 +461,9 @@ export class WsTransport {
|
|
|
350
461
|
}
|
|
351
462
|
}
|
|
352
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Opens the underlying WebSocket when needed and waits until it is ready.
|
|
466
|
+
*/
|
|
353
467
|
async connect(_roleName, endpoint) {
|
|
354
468
|
if (!this.socket) {
|
|
355
469
|
if (!endpoint) {
|
|
@@ -360,10 +474,16 @@ export class WsTransport {
|
|
|
360
474
|
await this.waitForOpen()
|
|
361
475
|
}
|
|
362
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Closes the underlying WebSocket connection.
|
|
479
|
+
*/
|
|
363
480
|
async disconnect() {
|
|
364
481
|
this.close()
|
|
365
482
|
}
|
|
366
483
|
|
|
484
|
+
/**
|
|
485
|
+
* Sends already-encoded OpenWS envelope data.
|
|
486
|
+
*/
|
|
367
487
|
async send(data) {
|
|
368
488
|
await this.waitForOpen()
|
|
369
489
|
const socket = this.requireSocket()
|
|
@@ -373,6 +493,9 @@ export class WsTransport {
|
|
|
373
493
|
await socket.send(data)
|
|
374
494
|
}
|
|
375
495
|
|
|
496
|
+
/**
|
|
497
|
+
* Registers a transport event callback.
|
|
498
|
+
*/
|
|
376
499
|
on(event, handler) {
|
|
377
500
|
this.listeners[event].add(handler)
|
|
378
501
|
return () => {
|
|
@@ -380,16 +503,16 @@ export class WsTransport {
|
|
|
380
503
|
}
|
|
381
504
|
}
|
|
382
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Closes and clears the current socket.
|
|
508
|
+
*/
|
|
383
509
|
close() {
|
|
384
510
|
this.socket?.close?.()
|
|
385
|
-
this.
|
|
386
|
-
this.socket = undefined
|
|
387
|
-
this.socketUnsubscribe = undefined
|
|
388
|
-
this.openPromise = undefined
|
|
511
|
+
this.clearSocket()
|
|
389
512
|
}
|
|
390
513
|
|
|
391
514
|
bindSocket(socket) {
|
|
392
|
-
this.
|
|
515
|
+
this.clearSocket()
|
|
393
516
|
this.socket = socket
|
|
394
517
|
this.openPromise = undefined
|
|
395
518
|
|
|
@@ -399,12 +522,31 @@ export class WsTransport {
|
|
|
399
522
|
const unsubscribeError = addSocketListener(socket, 'error', error => {
|
|
400
523
|
void this.emit('error', error)
|
|
401
524
|
})
|
|
525
|
+
const unsubscribeClose = addSocketListener(socket, 'close', event => {
|
|
526
|
+
void this.handleSocketClose(socket, event)
|
|
527
|
+
})
|
|
402
528
|
this.socketUnsubscribe = () => {
|
|
403
529
|
unsubscribeMessage()
|
|
404
530
|
unsubscribeError()
|
|
531
|
+
unsubscribeClose()
|
|
405
532
|
}
|
|
406
533
|
}
|
|
407
534
|
|
|
535
|
+
async handleSocketClose(socket, event) {
|
|
536
|
+
if (this.socket !== socket) {
|
|
537
|
+
return
|
|
538
|
+
}
|
|
539
|
+
this.clearSocket()
|
|
540
|
+
await this.emit('close', event)
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
clearSocket() {
|
|
544
|
+
this.socketUnsubscribe?.()
|
|
545
|
+
this.socket = undefined
|
|
546
|
+
this.socketUnsubscribe = undefined
|
|
547
|
+
this.openPromise = undefined
|
|
548
|
+
}
|
|
549
|
+
|
|
408
550
|
async emit(event, data) {
|
|
409
551
|
for (const handler of this.listeners[event]) {
|
|
410
552
|
await handler(data)
|
|
@@ -436,9 +578,14 @@ export class WsTransport {
|
|
|
436
578
|
cleanup()
|
|
437
579
|
reject(error)
|
|
438
580
|
})
|
|
581
|
+
const unsubscribeClose = addSocketListener(socket, 'close', event => {
|
|
582
|
+
cleanup()
|
|
583
|
+
reject(event instanceof Error ? event : new Error('WebSocket closed before opening'))
|
|
584
|
+
})
|
|
439
585
|
cleanup = () => {
|
|
440
586
|
unsubscribeOpen()
|
|
441
587
|
unsubscribeError()
|
|
588
|
+
unsubscribeClose()
|
|
442
589
|
}
|
|
443
590
|
})
|
|
444
591
|
await this.openPromise
|
|
@@ -10,7 +10,7 @@ import type { <%= payloadImports.join(', ') %> } from '<%= modelImportPath %>'
|
|
|
10
10
|
import { <%= peerRoleImports.join(', ') %> } from './index'
|
|
11
11
|
<% } -%>
|
|
12
12
|
|
|
13
|
-
export interface <%= ctx.
|
|
13
|
+
export interface <%= ctx.peerName %> {
|
|
14
14
|
<% for (const message of ctx.messages) { -%>
|
|
15
15
|
<%= message.methodName %>(payload: <%= message.payloadType %> | <%= message.payloadType %>Init): Promise<void>
|
|
16
16
|
<% } -%>
|