cbcore-ts 1.0.62 → 1.1.1

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.
@@ -4,6 +4,7 @@ import { CBCore } from "./CBCore"
4
4
  import {
5
5
  CBSocketHandshakeInitMessage,
6
6
  CBSocketHandshakeResponseMessage,
7
+ CBSocketKeepalivePayload,
7
8
  CBSocketMessage,
8
9
  CBSocketMessageCompletionFunction,
9
10
  CBSocketMessageHandlerFunction,
@@ -62,6 +63,30 @@ export function IS_NOT_SOCKET_ERROR(object: any) {
62
63
  }
63
64
 
64
65
 
66
+ /**
67
+ * A Promise returned by resultForMessageForKey.
68
+ * Exposes didReceiveKeepalive() for registering a keepalive callback
69
+ * in the same fluent style as the rest of the API.
70
+ */
71
+ export interface CBSocketRequestPromise<T> extends Promise<T> {
72
+ /**
73
+ * Register a handler to be called each time a keepalive frame arrives
74
+ * for this request.
75
+ *
76
+ * @param handler Called with the payload sent by the server.
77
+ * @param extendsDefaultHandler When true (default) the application-level
78
+ * defaultKeepaliveHandler fires first, then
79
+ * this handler. When false this handler fires
80
+ * alone and the default is suppressed for this
81
+ * request.
82
+ */
83
+ didReceiveKeepalive(
84
+ handler: (payload: CBSocketKeepalivePayload) => void,
85
+ extendsDefaultHandler?: boolean
86
+ ): CBSocketRequestPromise<T>
87
+ }
88
+
89
+
65
90
  export class CBSocketClient extends UIObject {
66
91
 
67
92
  _socket: Socket
@@ -107,8 +132,21 @@ export class CBSocketClient extends UIObject {
107
132
  * How long (in milliseconds) to wait for a server response before treating
108
133
  * the request as failed. Set to 0 to disable timeouts entirely.
109
134
  * Default: 30 000 ms (30 seconds).
135
+ *
136
+ * Each keepalive frame from the server resets this window, so long-running
137
+ * requests only time out if the server goes completely silent for this duration.
110
138
  */
111
139
  requestTimeoutMs: number = 30_000
140
+
141
+ /**
142
+ * Application-level keepalive handler. Called for every keepalive frame
143
+ * received on any request, unless the per-call handler was registered with
144
+ * extendsDefaultHandler = false.
145
+ *
146
+ * Configure once at application startup:
147
+ * CBSocketClient.sharedInstance.defaultKeepaliveHandler = payload => { ... }
148
+ */
149
+ defaultKeepaliveHandler?: (payload: CBSocketKeepalivePayload) => void
112
150
 
113
151
 
114
152
  constructor(core: CBCore) {
@@ -254,7 +292,6 @@ export class CBSocketClient extends UIObject {
254
292
 
255
293
  if (shouldSendMessage) {
256
294
 
257
-
258
295
  groupedMessages.push({
259
296
 
260
297
  key: messageToBeSentObject.key,
@@ -262,12 +299,10 @@ export class CBSocketClient extends UIObject {
262
299
 
263
300
  })
264
301
 
265
-
266
302
  }
267
303
 
268
304
  didSendFunctions.push(messageToBeSentObject.didSendFunction!)
269
305
 
270
-
271
306
  }
272
307
 
273
308
  })
@@ -350,7 +385,6 @@ export class CBSocketClient extends UIObject {
350
385
  completion?: CBSocketMessageCompletionFunction
351
386
  ) {
352
387
 
353
-
354
388
  this._sendMessageForKey(key as string, message, undefined, NO, completionPolicy, YES, nil, completion)
355
389
 
356
390
  }
@@ -372,7 +406,6 @@ export class CBSocketClient extends UIObject {
372
406
  completion?: CBSocketMessageCompletionFunction
373
407
  ) {
374
408
 
375
-
376
409
  this._sendMessageForKey(key as string, message, undefined, NO, completionPolicy, NO, nil, completion)
377
410
 
378
411
  }
@@ -389,18 +422,25 @@ export class CBSocketClient extends UIObject {
389
422
  message: any,
390
423
  completionPolicy?: keyof typeof CBSocketClient.completionPolicy,
391
424
  isUserBound = NO
392
- ) {
393
-
394
- const result = new Promise<{
395
-
425
+ ): CBSocketRequestPromise<{
426
+ responseMessage: any,
427
+ result: any,
428
+ errorResult: any,
429
+ respondWithMessage: CBSocketMessageSendResponseFunction
430
+ }> {
431
+
432
+ // The identifier is assigned synchronously inside _sendMessageForKey.
433
+ // We capture it via didObtainIdentifier so we can look up the descriptor
434
+ // immediately after the send, before any async gap.
435
+ let capturedIdentifier: string | undefined
436
+
437
+ const basePromise = new Promise<{
396
438
  responseMessage: any,
397
439
  result: any,
398
440
  errorResult: any,
399
-
400
441
  respondWithMessage: CBSocketMessageSendResponseFunction
401
-
402
442
  }>((resolve, reject) => {
403
-
443
+
404
444
  this._sendMessageForKey(
405
445
  key as string,
406
446
  message,
@@ -410,22 +450,71 @@ export class CBSocketClient extends UIObject {
410
450
  isUserBound,
411
451
  nil,
412
452
  (responseMessage, respondWithMessage) => resolve({
413
-
453
+
414
454
  responseMessage: responseMessage,
415
455
  result: IF(IS_NOT_SOCKET_ERROR(responseMessage))(() => responseMessage).ELSE(RETURNER(undefined)),
416
456
  errorResult: IF(IS_SOCKET_ERROR(responseMessage))(() => responseMessage).ELSE(RETURNER(undefined)),
417
-
457
+
418
458
  respondWithMessage: respondWithMessage
419
-
420
- })
459
+
460
+ }),
461
+ (identifier) => { capturedIdentifier = identifier }
421
462
  )
422
-
463
+
423
464
  })
424
-
425
- return result
426
-
465
+
466
+ const requestPromise = basePromise as CBSocketRequestPromise<any>
467
+
468
+ requestPromise.didReceiveKeepalive = (
469
+ handler: (payload: CBSocketKeepalivePayload) => void,
470
+ extendsDefaultHandler = YES
471
+ ): CBSocketRequestPromise<any> => {
472
+
473
+ // The descriptor is pushed synchronously before _sendMessageForKey returns,
474
+ // so capturedIdentifier is already set at this point.
475
+ if (capturedIdentifier) {
476
+ this._attachKeepaliveHandlerForIdentifier(capturedIdentifier, handler, extendsDefaultHandler)
477
+ }
478
+
479
+ return requestPromise
480
+
481
+ }
482
+
483
+ return requestPromise
484
+
427
485
  }
428
-
486
+
487
+
488
+ /**
489
+ * Finds the descriptor for the given request identifier and attaches the
490
+ * keepalive handler fields to it.
491
+ */
492
+ _attachKeepaliveHandlerForIdentifier(
493
+ identifier: string,
494
+ handler: (payload: CBSocketKeepalivePayload) => void,
495
+ extendsDefaultHandler: boolean
496
+ ) {
497
+
498
+ const descriptorKey = this._callbackHolder.keysForIdentifiers[identifier]
499
+ if (!descriptorKey) {
500
+ return
501
+ }
502
+
503
+ const descriptors = this._callbackHolder.messageDescriptors[descriptorKey]
504
+ if (!descriptors) {
505
+ return
506
+ }
507
+
508
+ const descriptor = descriptors.find(d => d.message.identifier === identifier)
509
+ if (!descriptor) {
510
+ return
511
+ }
512
+
513
+ descriptor.keepaliveHandler = handler
514
+ descriptor.keepaliveHandlerOverridesDefault = !extendsDefaultHandler
515
+
516
+ }
517
+
429
518
 
430
519
  _sendMessageForKey(
431
520
  key: string,
@@ -435,7 +524,8 @@ export class CBSocketClient extends UIObject {
435
524
  completionPolicy: keyof typeof CBSocketClient.completionPolicy = CBSocketClient.completionPolicy.directOnly,
436
525
  isUserBound = NO,
437
526
  didSendFunction: () => void = nil,
438
- completion: CBSocketMessageCompletionFunction = nil
527
+ completion: CBSocketMessageCompletionFunction = nil,
528
+ didObtainIdentifier?: (identifier: string) => void
439
529
  ) {
440
530
 
441
531
  if (IS_NIL(message)) {
@@ -447,6 +537,8 @@ export class CBSocketClient extends UIObject {
447
537
  if (this._isConnectionEstablished && !this._collectMessagesToSendLater) {
448
538
 
449
539
  const identifier = MAKE_ID()
540
+
541
+ didObtainIdentifier?.(identifier)
450
542
 
451
543
  const messageObject: CBSocketMessage<any> = {
452
544
 
@@ -704,4 +796,3 @@ export const SocketClient: SocketClientInterface = new Proxy({ "name": "SocketCl
704
796
  }
705
797
 
706
798
  }) as any
707
-