@inditextech/weave-store-azure-web-pubsub 3.4.0-SNAPSHOT.38.1 → 3.4.0

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/client.d.ts CHANGED
@@ -92,6 +92,13 @@ declare const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE: {
92
92
  "PUB": string;
93
93
  "SUB": string;
94
94
  };
95
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS: {
96
+ "NOT_FOUND": string;
97
+ "NOT_CONNECTED": string;
98
+ "DESTROYED": string;
99
+ };
100
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS: WeaveStoreAzureWebPubSubSyncClientOptions;
101
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS: WeaveStoreAzureWebPubsubSyncHostOptions;
95
102
 
96
103
  //#endregion
97
104
  //#region src/types.d.ts
@@ -117,6 +124,7 @@ type WeaveStoreAzureWebPubsubOptions = {
117
124
  roomId: string;
118
125
  url: string;
119
126
  fetchClient?: FetchClient;
127
+ syncClientOptions?: DeepPartial<WeaveStoreAzureWebPubSubSyncClientOptions>;
120
128
  };
121
129
  type WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent = {
122
130
  loading: boolean;
@@ -146,9 +154,11 @@ type WeaveStoreAzureWebPubsubOnDisconnectedEvent = {
146
154
  type WeaveStoreAzureWebPubsubOnWebsocketOpenEvent = {
147
155
  group: string;
148
156
  event: WebSocket.Event;
157
+ connectionAttempt: number;
149
158
  };
150
159
  type WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent = {
151
160
  group: string;
161
+ connectionAttempt: number;
152
162
  };
153
163
  type WeaveStoreAzureWebPubsubOnWebsocketMessageEvent = {
154
164
  group: string;
@@ -157,13 +167,17 @@ type WeaveStoreAzureWebPubsubOnWebsocketMessageEvent = {
157
167
  type WeaveStoreAzureWebPubsubOnWebsocketCloseEvent = {
158
168
  group: string;
159
169
  event: CloseEvent;
170
+ connectionAttempt: number;
160
171
  };
161
- type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
172
+ type WeaveStoreAzureWebPubsubOnWebsocketReconnectEvent = {
162
173
  group: string;
163
- error: ErrorEvent;
174
+ connectionAttempt: number;
175
+ timeoutMs: number;
164
176
  };
165
- type WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent = {
177
+ type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
166
178
  group: string;
179
+ error: ErrorEvent;
180
+ connectionAttempt: number;
167
181
  };
168
182
  type WeaveStoreAzureWebPubSubSyncHostClientConnectOptions = {
169
183
  expirationTimeInMinutes?: number;
@@ -183,7 +197,7 @@ declare enum MessageDataType {
183
197
  interface MessageData {
184
198
  payloadId?: string;
185
199
  index?: number;
186
- type?: "chunk" | "end";
200
+ type?: "heartbeat" | "resync" | "chunk" | "end";
187
201
  totalChunks?: number;
188
202
  group: string;
189
203
  t: string;
@@ -198,7 +212,23 @@ interface Message {
198
212
  data: MessageData;
199
213
  }
200
214
  type MessageHandler = (encoder: Encoder, decoder: Decoder, client: WeaveStoreAzureWebPubSubSyncClient, clientId: string, emitSynced: boolean, messageType: number) => void;
201
-
215
+ type WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys = keyof typeof WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS;
216
+ type WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatus = (typeof WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS)[WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys];
217
+ type WeaveStoreAzureWebPubSubSyncClientOptions = {
218
+ heartbeat: {
219
+ checkWindowTimeMs: number;
220
+ checkIntervalMs: number;
221
+ };
222
+ };
223
+ type WeaveStoreAzureWebPubsubSyncHostOptions = {
224
+ heartbeat: {
225
+ sendIntervalMs: number;
226
+ };
227
+ resync: {
228
+ checkIntervalMs: number;
229
+ attemptsLimit: number;
230
+ };
231
+ };
202
232
  //#endregion
203
233
  //#region src/client.d.ts
204
234
  declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
@@ -217,6 +247,9 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
217
247
  private _awareness;
218
248
  private _initialized;
219
249
  private _chunkedMessages;
250
+ private readonly _synClientOptions;
251
+ private _checkHeartbeatId;
252
+ private _lastHeartbeatTime;
220
253
  private _updateHandler;
221
254
  private _awarenessUpdateHandler;
222
255
  /**
@@ -226,7 +259,7 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
226
259
  * @param {number} [options.resyncInterval] Request server state every `resyncInterval` milliseconds.
227
260
  * @param {number} [options.tokenProvider] token generator for negotiation.
228
261
  */
229
- constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc);
262
+ constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc, options?: DeepPartial<WeaveStoreAzureWebPubSubSyncClientOptions>);
230
263
  get awareness(): awarenessProtocol.Awareness;
231
264
  get synced(): boolean;
232
265
  set synced(state: boolean);
@@ -240,6 +273,8 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
240
273
  fetchConnectionUrl(connectionUrlExtraParams?: Record<string, string>): Promise<string>;
241
274
  createWebSocket(connectionUrlExtraParams?: Record<string, string>): Promise<ReconnectingWebSocket>;
242
275
  setAndEmitStatusInfo(status: WeaveStoreAzureWebPubSubSyncClientConnectionStatus): void;
276
+ private setupCheckHeartbeat;
277
+ private destroyCheckHeartbeat;
243
278
  connect(connectionUrlExtraParams?: Record<string, string>): Promise<void>;
244
279
  }
245
280
 
@@ -250,7 +285,6 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
250
285
  private roomId;
251
286
  private started;
252
287
  private initialRoomData;
253
- private actualStatus;
254
288
  protected provider: WeaveStoreAzureWebPubSubSyncClient;
255
289
  protected name: string;
256
290
  protected supportsUndoManager: boolean;
@@ -261,7 +295,6 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
261
295
  private init;
262
296
  emitEvent<T>(name: string, payload?: T): void;
263
297
  getClientId(): string | null;
264
- switchToRoom(roomId: string, roomData: Uint8Array | FetchInitialState | undefined): Promise<void>;
265
298
  connect(extraParams?: Record<string, string>): Promise<void>;
266
299
  disconnect(): void;
267
300
  simulateWebsocketError(): void;
@@ -271,4 +304,4 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
271
304
  }
272
305
 
273
306
  //#endregion
274
- export { FetchClient, FetchInitialState, FetchRoom, Message, MessageData, MessageDataType, MessageHandler, MessageType, PersistRoom, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsub, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions };
307
+ export { FetchClient, FetchInitialState, FetchRoom, Message, MessageData, MessageDataType, MessageHandler, MessageType, PersistRoom, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncClientOptions, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsub, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOnWebsocketReconnectEvent, WeaveStoreAzureWebPubsubOptions, WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatus, WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys, WeaveStoreAzureWebPubsubSyncHostOptions };
package/dist/client.js CHANGED
@@ -1,7 +1,8 @@
1
- import { WeaveStore } from "@inditextech/weave-sdk";
1
+ import { WeaveStore, mergeExceptArrays } from "@inditextech/weave-sdk";
2
2
  import { WEAVE_STORE_CONNECTION_STATUS } from "@inditextech/weave-types";
3
3
  import { v4 } from "uuid";
4
4
  import ReconnectingWebSocket from "reconnecting-websocket";
5
+ import * as Y$1 from "yjs";
5
6
  import * as Y from "yjs";
6
7
 
7
8
  //#region rolldown:runtime
@@ -2559,10 +2560,12 @@ var Emittery = class Emittery {
2559
2560
  });
2560
2561
  }
2561
2562
  }
2562
- once(eventNames) {
2563
+ once(eventNames, predicate) {
2564
+ if (predicate !== void 0 && typeof predicate !== "function") throw new TypeError("predicate must be a function");
2563
2565
  let off_;
2564
2566
  const promise = new Promise((resolve) => {
2565
2567
  off_ = this.on(eventNames, (data) => {
2568
+ if (predicate && !predicate(data)) return;
2566
2569
  off_();
2567
2570
  resolve(data);
2568
2571
  });
@@ -2595,10 +2598,11 @@ var Emittery = class Emittery {
2595
2598
  assertEventName(eventName);
2596
2599
  if (isMetaEvent(eventName) && !canEmitMetaEvents) throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
2597
2600
  this.logIfDebugEnabled("emitSerial", eventName, eventData);
2601
+ enqueueProducers(this, eventName, eventData);
2598
2602
  const listeners = getListeners(this, eventName) ?? new Set();
2599
2603
  const anyListeners = anyMap.get(this);
2600
2604
  const staticListeners = [...listeners];
2601
- const staticAnyListeners = [...anyListeners];
2605
+ const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
2602
2606
  await resolvedPromise;
2603
2607
  for (const listener of staticListeners) if (listeners.has(listener)) await listener(eventData);
2604
2608
  for (const listener of staticAnyListeners) if (anyListeners.has(listener)) await listener(eventName, eventData);
@@ -3201,7 +3205,7 @@ const messageYjsUpdate = 2;
3201
3205
  */
3202
3206
  const writeSyncStep1 = (encoder, doc) => {
3203
3207
  writeVarUint(encoder, messageYjsSyncStep1);
3204
- const sv = Y.encodeStateVector(doc);
3208
+ const sv = Y$1.encodeStateVector(doc);
3205
3209
  writeVarUint8Array(encoder, sv);
3206
3210
  };
3207
3211
  /**
@@ -3211,7 +3215,7 @@ const writeSyncStep1 = (encoder, doc) => {
3211
3215
  */
3212
3216
  const writeSyncStep2 = (encoder, doc, encodedStateVector) => {
3213
3217
  writeVarUint(encoder, messageYjsSyncStep2);
3214
- writeVarUint8Array(encoder, Y.encodeStateAsUpdate(doc, encodedStateVector));
3218
+ writeVarUint8Array(encoder, Y$1.encodeStateAsUpdate(doc, encodedStateVector));
3215
3219
  };
3216
3220
  /**
3217
3221
  * Read SyncStep1 message and reply with SyncStep2.
@@ -3231,7 +3235,7 @@ const readSyncStep1 = (decoder, encoder, doc) => writeSyncStep2(encoder, doc, re
3231
3235
  */
3232
3236
  const readSyncStep2 = (decoder, doc, transactionOrigin, errorHandler) => {
3233
3237
  try {
3234
- Y.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
3238
+ Y$1.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
3235
3239
  } catch (error) {
3236
3240
  if (errorHandler != null) errorHandler(
3237
3241
  /** @type {Error} */
@@ -3732,6 +3736,22 @@ const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
3732
3736
  ["PUB"]: "pub",
3733
3737
  ["SUB"]: "sub"
3734
3738
  };
3739
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS = {
3740
+ ["NOT_FOUND"]: "not-found",
3741
+ ["NOT_CONNECTED"]: "not-connected",
3742
+ ["DESTROYED"]: "destroyed"
3743
+ };
3744
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS = { heartbeat: {
3745
+ checkWindowTimeMs: 1e4,
3746
+ checkIntervalMs: 5e3
3747
+ } };
3748
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS = {
3749
+ heartbeat: { sendIntervalMs: 2500 },
3750
+ resync: {
3751
+ checkIntervalMs: 5e3,
3752
+ attemptsLimit: 12
3753
+ }
3754
+ };
3735
3755
 
3736
3756
  //#endregion
3737
3757
  //#region src/utils.ts
@@ -3769,6 +3789,10 @@ function uint8ToBase64(u8) {
3769
3789
  return btoa(binary);
3770
3790
  }
3771
3791
 
3792
+ //#endregion
3793
+ //#region src/yjs.ts
3794
+ var yjs_default = Y;
3795
+
3772
3796
  //#endregion
3773
3797
  //#region src/client.ts
3774
3798
  const messageSyncStep1 = 0;
@@ -3806,14 +3830,16 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3806
3830
  * @param {number} [options.resyncInterval] Request server state every `resyncInterval` milliseconds.
3807
3831
  * @param {number} [options.tokenProvider] token generator for negotiation.
3808
3832
  */
3809
- constructor(instance, url, topic, doc) {
3833
+ constructor(instance, url, topic, doc, options) {
3810
3834
  super();
3835
+ this._synClientOptions = mergeExceptArrays(WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS, options ?? {});
3811
3836
  this.instance = instance;
3812
3837
  this.doc = doc;
3813
3838
  this.topic = topic;
3814
3839
  this._fetchClient = fetch;
3815
3840
  this._url = url;
3816
3841
  this._uuid = v4();
3842
+ this._lastHeartbeatTime = 0;
3817
3843
  this._status = WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.DISCONNECTED;
3818
3844
  this._wsConnected = false;
3819
3845
  this._initialized = false;
@@ -3895,7 +3921,9 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3895
3921
  connectionURL.searchParams.append(key, connectionUrlExtraParams[key]);
3896
3922
  }
3897
3923
  }
3898
- const res = await this._fetchClient(connectionURL.toString());
3924
+ const controller = new AbortController();
3925
+ const timeout = setTimeout(() => controller.abort(), 5e3);
3926
+ const res = await this._fetchClient(connectionURL.toString(), { signal: controller.signal }).finally(() => clearTimeout(timeout));
3899
3927
  if (res.ok) {
3900
3928
  const data = await res.json();
3901
3929
  return data.url;
@@ -3923,6 +3951,7 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3923
3951
  error
3924
3952
  });
3925
3953
  }
3954
+ console.log("🔌 [Azure Web PubSub] connecting", url);
3926
3955
  return url;
3927
3956
  }, AzureWebPubSubJsonProtocol);
3928
3957
  websocket.binaryType = "arraybuffer";
@@ -3931,7 +3960,8 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3931
3960
  this._initialized = false;
3932
3961
  this.synced = false;
3933
3962
  websocket.addEventListener("error", (e) => {
3934
- console.error("WebSocket error", e);
3963
+ console.error(" client error", e);
3964
+ this.destroyCheckHeartbeat();
3935
3965
  if (this._initialized && websocket.retryCount > 0) {
3936
3966
  this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
3937
3967
  return;
@@ -3943,6 +3973,18 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3943
3973
  const message = JSON.parse(event.data.toString());
3944
3974
  if (message.type === MessageType.System) return;
3945
3975
  const messageData = message.data;
3976
+ if (messageData.type === "heartbeat") {
3977
+ console.log("[Azure Web PubSub] received heartbeat, updating last heartbeat time.");
3978
+ this._lastHeartbeatTime = Date.now();
3979
+ return;
3980
+ }
3981
+ if (messageData.type === "resync") {
3982
+ const encoder$1 = createEncoder();
3983
+ writeVarUint(encoder$1, messageSyncStep1);
3984
+ writeUpdate(encoder$1, yjs_default.encodeStateAsUpdate(this.doc));
3985
+ sendToControlGroup(this, this.topic, MessageDataType.Sync, toUint8Array(encoder$1));
3986
+ return;
3987
+ }
3946
3988
  if (messageData.t !== void 0 && messageData.t !== this._uuid) return;
3947
3989
  const joinedMessagePayload = handleChunkedMessage(this._chunkedMessages, messageData);
3948
3990
  if (messageData.type === "chunk") return;
@@ -3951,7 +3993,9 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3951
3993
  const encoder = readMessage(this, buffer, true, messageData.f);
3952
3994
  if (length(encoder) > 1) sendToControlGroup(this, this.topic, MessageDataType.Sync, toUint8Array(encoder));
3953
3995
  };
3954
- websocket.onclose = () => {
3996
+ websocket.onclose = (e) => {
3997
+ console.log(`🚫 [Azure Web PubSub] closed, code: ${e.code}`);
3998
+ this.destroyCheckHeartbeat();
3955
3999
  if ((this._ws?.retryCount ?? 0) > 0) this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
3956
4000
  else this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.DISCONNECTED);
3957
4001
  if (this._wsConnected) {
@@ -3965,7 +4009,11 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3965
4009
  this._wsConnected = true;
3966
4010
  this._initialized = true;
3967
4011
  this._connectionRetries = this._connectionRetries++;
4012
+ console.log("✅ [Azure Web PubSub] connected");
4013
+ this.setupCheckHeartbeat();
4014
+ console.log(`🔌 [Azure Web PubSub] join room <${this.topic}>`);
3968
4015
  joinGroup(this, this.topic);
4016
+ console.log(`✅ [Azure Web PubSub] room <${this.topic}> joined`);
3969
4017
  const encoder = createEncoder();
3970
4018
  writeVarUint(encoder, messageSyncStep1);
3971
4019
  writeSyncStep1(encoder, this.doc);
@@ -3993,6 +4041,20 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3993
4041
  this._status = status;
3994
4042
  this.emit("status", this._status);
3995
4043
  }
4044
+ setupCheckHeartbeat() {
4045
+ this._checkHeartbeatId = setInterval(() => {
4046
+ const now = Date.now();
4047
+ if (now - this._lastHeartbeatTime > this._synClientOptions.heartbeat.checkWindowTimeMs) {
4048
+ console.log(`[Azure Web PubSub] heartbeat not received in ${this._synClientOptions.heartbeat.checkWindowTimeMs}ms window, handling it...`);
4049
+ this.disconnect();
4050
+ this.createWebSocket();
4051
+ }
4052
+ }, this._synClientOptions.heartbeat.checkIntervalMs);
4053
+ }
4054
+ destroyCheckHeartbeat() {
4055
+ this._lastHeartbeatTime = 0;
4056
+ if (this._checkHeartbeatId) clearInterval(this._checkHeartbeatId);
4057
+ }
3996
4058
  async connect(connectionUrlExtraParams) {
3997
4059
  if (this._wsConnected || this._ws) return;
3998
4060
  await this.createWebSocket(connectionUrlExtraParams);
@@ -4085,7 +4147,6 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4085
4147
  this.roomId = roomId;
4086
4148
  this.initialRoomData = initialRoomData;
4087
4149
  this.started = false;
4088
- this.actualStatus = WEAVE_STORE_CONNECTION_STATUS.DISCONNECTED;
4089
4150
  this.init();
4090
4151
  }
4091
4152
  setup() {
@@ -4099,8 +4160,7 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4099
4160
  }
4100
4161
  init() {
4101
4162
  const { url } = this.azureWebPubsubOptions;
4102
- const patchedUrl = url.replace("[roomId]", this.roomId);
4103
- this.provider = new WeaveStoreAzureWebPubSubSyncClient(this, patchedUrl, this.roomId, this.getDocument());
4163
+ this.provider = new WeaveStoreAzureWebPubSubSyncClient(this, url, this.roomId, this.getDocument(), this.azureWebPubsubOptions.syncClientOptions);
4104
4164
  const awareness = this.provider.awareness;
4105
4165
  awareness.on("update", this.handleAwarenessChange.bind(this));
4106
4166
  awareness.on("change", this.handleAwarenessChange.bind(this));
@@ -4110,14 +4170,9 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4110
4170
  });
4111
4171
  this.provider.on("error", () => {
4112
4172
  this.handleConnectionStatusChange(WEAVE_STORE_CONNECTION_STATUS.DISCONNECTED);
4113
- this.disconnect();
4114
4173
  });
4115
4174
  this.provider.on("status", (status) => {
4116
- if (this.actualStatus !== WEAVE_STORE_CONNECTION_STATUS.SWITCHING_ROOM || this.actualStatus === WEAVE_STORE_CONNECTION_STATUS.SWITCHING_ROOM && status === WEAVE_STORE_CONNECTION_STATUS.CONNECTED) {
4117
- this.handleConnectionStatusChange(status);
4118
- if (this.actualStatus === WEAVE_STORE_CONNECTION_STATUS.SWITCHING_ROOM && status === WEAVE_STORE_CONNECTION_STATUS.CONNECTED) this.instance.emitEvent("onRoomSwitchingEnd", { room: this.roomId });
4119
- this.actualStatus = status;
4120
- }
4175
+ this.handleConnectionStatusChange(status);
4121
4176
  if (status === WEAVE_STORE_CONNECTION_STATUS.CONNECTED && !this.started) {
4122
4177
  this.loadRoomInitialData();
4123
4178
  this.started = true;
@@ -4131,23 +4186,9 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4131
4186
  if (this.provider) return this.provider.getClientId();
4132
4187
  return null;
4133
4188
  }
4134
- async switchToRoom(roomId, roomData) {
4135
- this.instance.emitEvent("onRoomSwitchingStart", { room: roomId });
4136
- this.actualStatus = WEAVE_STORE_CONNECTION_STATUS.SWITCHING_ROOM;
4137
- this.disconnect();
4138
- this.restartDocument();
4139
- await this.instance.switchRoom();
4140
- this.roomId = roomId;
4141
- this.initialRoomData = roomData;
4142
- this.started = false;
4143
- this.init();
4144
- this.setup();
4145
- this.connect();
4146
- }
4147
4189
  async connect(extraParams) {
4148
4190
  const { fetchClient } = this.azureWebPubsubOptions;
4149
4191
  this.provider.setFetchClient(fetchClient ?? window.fetch);
4150
- this.instance.emitEvent("onStoreRoomChanged", { room: this.roomId });
4151
4192
  await this.provider.connect(extraParams);
4152
4193
  }
4153
4194
  disconnect() {
@@ -4171,4 +4212,4 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4171
4212
  };
4172
4213
 
4173
4214
  //#endregion
4174
- export { MessageDataType, MessageType, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveStoreAzureWebPubsub };
4215
+ export { MessageDataType, MessageType, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveStoreAzureWebPubsub };
package/dist/server.d.ts CHANGED
@@ -3,12 +3,12 @@ import { TokenCredential } from "@azure/identity";
3
3
  import * as Y from "yjs";
4
4
  import { Doc } from "yjs";
5
5
  import { WebSocket } from "ws";
6
+ import { WeaveStore } from "@inditextech/weave-sdk";
6
7
  import koa from "koa";
7
8
  import Emittery from "emittery";
8
9
  import ReconnectingWebSocket from "reconnecting-websocket";
9
10
  import * as awarenessProtocol$1 from "y-protocols/awareness";
10
11
  import * as awarenessProtocol from "y-protocols/awareness";
11
- import { WeaveStore } from "@inditextech/weave-sdk";
12
12
  import { DeepPartial, WeaveStoreOptions } from "@inditextech/weave-types";
13
13
  import { Encoder } from "lib0/encoding";
14
14
  import { Decoder } from "lib0/decoding";
@@ -27,6 +27,13 @@ declare const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE: {
27
27
  "PUB": string;
28
28
  "SUB": string;
29
29
  };
30
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS: {
31
+ "NOT_FOUND": string;
32
+ "NOT_CONNECTED": string;
33
+ "DESTROYED": string;
34
+ };
35
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS: WeaveStoreAzureWebPubSubSyncClientOptions;
36
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS: WeaveStoreAzureWebPubsubSyncHostOptions;
30
37
 
31
38
  //#endregion
32
39
  //#region src/store-azure-web-pubsub.d.ts
@@ -35,7 +42,6 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
35
42
  private roomId;
36
43
  private started;
37
44
  private initialRoomData;
38
- private actualStatus;
39
45
  protected provider: WeaveStoreAzureWebPubSubSyncClient;
40
46
  protected name: string;
41
47
  protected supportsUndoManager: boolean;
@@ -46,7 +52,6 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
46
52
  private init;
47
53
  emitEvent<T>(name: string, payload?: T): void;
48
54
  getClientId(): string | null;
49
- switchToRoom(roomId: string, roomData: Uint8Array | FetchInitialState | undefined): Promise<void>;
50
55
  connect(extraParams?: Record<string, string>): Promise<void>;
51
56
  disconnect(): void;
52
57
  simulateWebsocketError(): void;
@@ -73,6 +78,9 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
73
78
  private _awareness;
74
79
  private _initialized;
75
80
  private _chunkedMessages;
81
+ private readonly _synClientOptions;
82
+ private _checkHeartbeatId;
83
+ private _lastHeartbeatTime;
76
84
  private _updateHandler;
77
85
  private _awarenessUpdateHandler;
78
86
  /**
@@ -82,7 +90,7 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
82
90
  * @param {number} [options.resyncInterval] Request server state every `resyncInterval` milliseconds.
83
91
  * @param {number} [options.tokenProvider] token generator for negotiation.
84
92
  */
85
- constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc);
93
+ constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc, options?: DeepPartial<WeaveStoreAzureWebPubSubSyncClientOptions>);
86
94
  get awareness(): awarenessProtocol$1.Awareness;
87
95
  get synced(): boolean;
88
96
  set synced(state: boolean);
@@ -96,6 +104,8 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
96
104
  fetchConnectionUrl(connectionUrlExtraParams?: Record<string, string>): Promise<string>;
97
105
  createWebSocket(connectionUrlExtraParams?: Record<string, string>): Promise<ReconnectingWebSocket>;
98
106
  setAndEmitStatusInfo(status: WeaveStoreAzureWebPubSubSyncClientConnectionStatus): void;
107
+ private setupCheckHeartbeat;
108
+ private destroyCheckHeartbeat;
99
109
  connect(connectionUrlExtraParams?: Record<string, string>): Promise<void>;
100
110
  }
101
111
 
@@ -123,6 +133,7 @@ type WeaveStoreAzureWebPubsubOptions = {
123
133
  roomId: string;
124
134
  url: string;
125
135
  fetchClient?: FetchClient;
136
+ syncClientOptions?: DeepPartial<WeaveStoreAzureWebPubSubSyncClientOptions>;
126
137
  };
127
138
  type WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent = {
128
139
  loading: boolean;
@@ -152,9 +163,11 @@ type WeaveStoreAzureWebPubsubOnDisconnectedEvent = {
152
163
  type WeaveStoreAzureWebPubsubOnWebsocketOpenEvent = {
153
164
  group: string;
154
165
  event: WebSocket.Event;
166
+ connectionAttempt: number;
155
167
  };
156
168
  type WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent = {
157
169
  group: string;
170
+ connectionAttempt: number;
158
171
  };
159
172
  type WeaveStoreAzureWebPubsubOnWebsocketMessageEvent = {
160
173
  group: string;
@@ -163,13 +176,17 @@ type WeaveStoreAzureWebPubsubOnWebsocketMessageEvent = {
163
176
  type WeaveStoreAzureWebPubsubOnWebsocketCloseEvent = {
164
177
  group: string;
165
178
  event: CloseEvent;
179
+ connectionAttempt: number;
166
180
  };
167
- type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
181
+ type WeaveStoreAzureWebPubsubOnWebsocketReconnectEvent = {
168
182
  group: string;
169
- error: ErrorEvent;
183
+ connectionAttempt: number;
184
+ timeoutMs: number;
170
185
  };
171
- type WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent = {
186
+ type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
172
187
  group: string;
188
+ error: ErrorEvent;
189
+ connectionAttempt: number;
173
190
  };
174
191
  type WeaveStoreAzureWebPubSubSyncHostClientConnectOptions = {
175
192
  expirationTimeInMinutes?: number;
@@ -189,7 +206,7 @@ declare enum MessageDataType {
189
206
  interface MessageData {
190
207
  payloadId?: string;
191
208
  index?: number;
192
- type?: "chunk" | "end";
209
+ type?: "heartbeat" | "resync" | "chunk" | "end";
193
210
  totalChunks?: number;
194
211
  group: string;
195
212
  t: string;
@@ -204,6 +221,23 @@ interface Message {
204
221
  data: MessageData;
205
222
  }
206
223
  type MessageHandler = (encoder: Encoder, decoder: Decoder, client: WeaveStoreAzureWebPubSubSyncClient, clientId: string, emitSynced: boolean, messageType: number) => void;
224
+ type WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys = keyof typeof WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS;
225
+ type WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatus = (typeof WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS)[WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys];
226
+ type WeaveStoreAzureWebPubSubSyncClientOptions = {
227
+ heartbeat: {
228
+ checkWindowTimeMs: number;
229
+ checkIntervalMs: number;
230
+ };
231
+ };
232
+ type WeaveStoreAzureWebPubsubSyncHostOptions = {
233
+ heartbeat: {
234
+ sendIntervalMs: number;
235
+ };
236
+ resync: {
237
+ checkIntervalMs: number;
238
+ attemptsLimit: number;
239
+ };
240
+ };
207
241
 
208
242
  //#endregion
209
243
  //#region src/server/event-handler/enum/mqtt-error-codes/mqtt-disconnect-reason-code.d.ts
@@ -1004,13 +1038,21 @@ declare class WeaveStoreAzureWebPubSubSyncHost {
1004
1038
  private _forceClose;
1005
1039
  private _awareness;
1006
1040
  private _chunkedMessages;
1041
+ private readonly _syncHostOptions;
1042
+ private _heartbeatIntervalId;
1043
+ private _reconnectionTimeoutId;
1044
+ private _resyncAttempt;
1045
+ private _resyncIntervalId;
1007
1046
  private _updateHandler;
1008
1047
  private _awarenessUpdateHandler;
1009
- constructor(server: WeaveAzureWebPubsubServer, syncHandler: WeaveAzureWebPubsubSyncHandler, client: WebPubSubServiceClient, topic: string, doc: Y.Doc);
1048
+ constructor(server: WeaveAzureWebPubsubServer, syncHandler: WeaveAzureWebPubsubSyncHandler, client: WebPubSubServiceClient, topic: string, doc: Y.Doc, syncHostOptions?: DeepPartial<WeaveStoreAzureWebPubsubSyncHostOptions>);
1010
1049
  get awareness(): awarenessProtocol.Awareness;
1011
1050
  sendInitAwarenessInfo(origin: string): void;
1051
+ private setupHeartbeat;
1012
1052
  createWebSocket(): Promise<void>;
1013
1053
  start(): Promise<void>;
1054
+ isConnected(): boolean;
1055
+ isReconnecting(): boolean;
1014
1056
  stop(): Promise<void>;
1015
1057
  simulateWebsocketError(): void;
1016
1058
  private safeSend;
@@ -1032,23 +1074,27 @@ declare class WeaveAzureWebPubsubSyncHandler extends WebPubSubEventHandler {
1032
1074
  private readonly _rooms;
1033
1075
  private readonly _roomsSyncHost;
1034
1076
  private _store_persistence;
1077
+ private readonly syncHostOptions;
1035
1078
  private readonly syncOptions?;
1036
1079
  private initialState;
1037
1080
  private readonly server;
1038
1081
  private readonly roomsLastState;
1039
- constructor(hub: string, server: WeaveAzureWebPubsubServer, client: WebPubSubServiceClient, initialState: FetchInitialState, syncHandlerOptions?: WeaveAzureWebPubsubSyncHandlerOptions, eventHandlerOptions?: WebPubSubEventHandlerOptions);
1082
+ constructor(hub: string, server: WeaveAzureWebPubsubServer, client: WebPubSubServiceClient, initialState: FetchInitialState, syncHandlerOptions?: WeaveAzureWebPubsubSyncHandlerOptions, eventHandlerOptions?: WebPubSubEventHandlerOptions, syncHostOptions?: DeepPartial<WeaveStoreAzureWebPubsubSyncHostOptions>);
1040
1083
  private getNewYDoc;
1041
1084
  private setupRoomInstance;
1042
1085
  isPersistingOnInterval(): boolean;
1043
1086
  private setupRoomInstancePersistence;
1044
1087
  persistRoomTask(roomId: string): Promise<void>;
1045
1088
  private handleConnectionDisconnection;
1046
- destroyRoomInstance(roomId: string): Promise<void>;
1089
+ destroyRoomInstance(roomId: string): Promise<WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatus>;
1047
1090
  private getHostConnection;
1048
1091
  getRoomsLoaded(): string[];
1049
1092
  getRoomSyncHost(roomId: string): WeaveStoreAzureWebPubSubSyncHost | undefined;
1050
1093
  getRoomDocument(roomId: string): Promise<Y.Doc>;
1051
1094
  clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string>;
1095
+ clientDisconnect(roomId: string): Promise<void>;
1096
+ clientTransportConnect(roomId: string): Promise<void>;
1097
+ clientTransportDisconnect(roomId: string): void;
1052
1098
  }
1053
1099
 
1054
1100
  //#endregion
@@ -1059,6 +1105,7 @@ type WeaveAzureWebPubsubServerParams = {
1059
1105
  eventsHandlerConfig?: WebPubSubEventHandlerOptions;
1060
1106
  persistRoom?: PersistRoom;
1061
1107
  fetchRoom?: FetchRoom;
1108
+ syncHostConfig?: DeepPartial<WeaveStoreAzureWebPubsubSyncHostOptions>;
1062
1109
  };
1063
1110
  declare class WeaveAzureWebPubsubServer extends Emittery {
1064
1111
  private syncClient;
@@ -1070,7 +1117,8 @@ declare class WeaveAzureWebPubsubServer extends Emittery {
1070
1117
  eventsHandlerConfig,
1071
1118
  initialState,
1072
1119
  persistRoom,
1073
- fetchRoom
1120
+ fetchRoom,
1121
+ syncHostConfig
1074
1122
  }: WeaveAzureWebPubsubServerParams);
1075
1123
  getKoaMiddleware(): koa.Middleware;
1076
1124
  getExpressJsMiddleware(): RequestHandler;
@@ -1080,7 +1128,10 @@ declare class WeaveAzureWebPubsubServer extends Emittery {
1080
1128
  removeEventListener<T>(event: string, callback: (payload: T) => void): void;
1081
1129
  getRoomDocument(roomId: string): Promise<Y.Doc>;
1082
1130
  clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string | null>;
1131
+ clientDisconnect(roomId: string): Promise<void>;
1132
+ clientTransportConnect(roomId: string): Promise<void>;
1133
+ clientTransportDisconnect(roomId: string): void;
1083
1134
  }
1084
1135
 
1085
1136
  //#endregion
1086
- export { Certificate, ConnectErrorResponse, ConnectRequest, ConnectResponse, ConnectResponseHandler, ConnectedRequest, ConnectionContext, DisconnectedRequest, FetchClient, FetchInitialState, FetchRoom, Message, MessageData, MessageDataType, MessageHandler, MessageType, MqttConnectErrorResponse, MqttConnectErrorResponseProperties, MqttConnectProperties, MqttConnectRequest, MqttConnectResponse, MqttConnectResponseProperties, MqttConnectionContextProperties, MqttDisconnectPacket, MqttDisconnectReasonCode, MqttDisconnectedProperties, MqttDisconnectedRequest, MqttUserProperty, MqttV311ConnectReturnCode, MqttV500ConnectReasonCode, PersistRoom, UserEventRequest, UserEventResponseHandler, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncHost, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions, WebPubSubClientProtocol, WebPubSubEventHandler, WebPubSubEventHandlerOptions };
1137
+ export { Certificate, ConnectErrorResponse, ConnectRequest, ConnectResponse, ConnectResponseHandler, ConnectedRequest, ConnectionContext, DisconnectedRequest, FetchClient, FetchInitialState, FetchRoom, Message, MessageData, MessageDataType, MessageHandler, MessageType, MqttConnectErrorResponse, MqttConnectErrorResponseProperties, MqttConnectProperties, MqttConnectRequest, MqttConnectResponse, MqttConnectResponseProperties, MqttConnectionContextProperties, MqttDisconnectPacket, MqttDisconnectReasonCode, MqttDisconnectedProperties, MqttDisconnectedRequest, MqttUserProperty, MqttV311ConnectReturnCode, MqttV500ConnectReasonCode, PersistRoom, UserEventRequest, UserEventResponseHandler, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_DESTROY_ROOM_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_CLIENT_DEFAULT_OPTIONS, WEAVE_STORE_AZURE_WEB_PUBSUB_SYNC_HOST_DEFAULT_OPTIONS, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncClientOptions, WeaveStoreAzureWebPubSubSyncHost, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOnWebsocketReconnectEvent, WeaveStoreAzureWebPubsubOptions, WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatus, WeaveStoreAzureWebPubsubSyncHandlerDestroyRoomStatusKeys, WeaveStoreAzureWebPubsubSyncHostOptions, WebPubSubClientProtocol, WebPubSubEventHandler, WebPubSubEventHandlerOptions };