@inditextech/weave-store-azure-web-pubsub 2.0.2 → 2.0.3

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
@@ -6,6 +6,8 @@ import Emittery from "emittery";
6
6
  import * as awarenessProtocol from "y-protocols/awareness";
7
7
  import { WebSocket } from "ws";
8
8
  import { TokenCredential } from "@azure/identity";
9
+ import { Encoder } from "lib0/encoding";
10
+ import { Decoder } from "lib0/decoding";
9
11
 
10
12
  //#region src/server/event-handler/cloud-events-protocols.d.ts
11
13
  /**
@@ -80,6 +82,12 @@ interface MqttConnectionContextProperties {
80
82
  * Request for the connect event.
81
83
  */
82
84
  declare const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
85
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS: {
86
+ "CONNECTING": string;
87
+ "CONNECTED": string;
88
+ "DISCONNECTED": string;
89
+ "ERROR": string;
90
+ };
83
91
  declare const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE: {
84
92
  "PUB": string;
85
93
  "SUB": string;
@@ -161,13 +169,42 @@ type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
161
169
  type WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent = {
162
170
  group: string;
163
171
  };
164
-
165
- //#endregion
166
- //#region src/client.d.ts
167
- interface ClientOptions {
172
+ type WeaveStoreAzureWebPubSubSyncHostClientConnectOptions = {
173
+ expirationTimeInMinutes?: number;
174
+ };
175
+ type WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys = keyof typeof WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS;
176
+ type WeaveStoreAzureWebPubSubSyncClientConnectionStatus = (typeof WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS)[WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys];
177
+ declare enum MessageType {
178
+ System = "system",
179
+ JoinGroup = "joinGroup",
180
+ SendToGroup = "sendToGroup",
181
+ }
182
+ declare enum MessageDataType {
183
+ Init = "init",
184
+ Sync = "sync",
185
+ Awareness = "awareness",
186
+ }
187
+ interface MessageData {
188
+ group: string;
189
+ t: string;
190
+ f: string;
191
+ c: string;
192
+ }
193
+ interface Message {
194
+ type: string;
195
+ fromUserId: string;
196
+ from: string;
197
+ group: string;
198
+ data: MessageData;
199
+ }
200
+ type MessageHandler = (encoder: Encoder, decoder: Decoder, client: WeaveStoreAzureWebPubSubSyncClient, clientId: string, emitSynced: boolean, messageType: number) => void;
201
+ interface WeaveStoreAzureWebPubSubSyncClientOptions {
168
202
  resyncInterval: number;
169
203
  tokenProvider: Promise<string> | null;
170
204
  }
205
+
206
+ //#endregion
207
+ //#region src/client.d.ts
171
208
  declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
172
209
  doc: Doc;
173
210
  topic: string;
@@ -179,6 +216,8 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
179
216
  private _wsConnected;
180
217
  private _synced;
181
218
  private _resyncInterval;
219
+ private _resyncCheckInterval;
220
+ private _lastReceivedSyncResponse;
182
221
  private _connectionRetries;
183
222
  private _uuid;
184
223
  private _awareness;
@@ -193,20 +232,23 @@ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
193
232
  * @param {number} [options.resyncInterval] Request server state every `resyncInterval` milliseconds.
194
233
  * @param {number} [options.tokenProvider] token generator for negotiation.
195
234
  */
196
- constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc, options?: ClientOptions);
235
+ constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc, options?: WeaveStoreAzureWebPubSubSyncClientOptions);
197
236
  get awareness(): awarenessProtocol.Awareness;
198
237
  get synced(): boolean;
199
238
  set synced(state: boolean);
200
239
  get ws(): ReconnectingWebSocket | null;
201
240
  get id(): string;
202
241
  getClientId(): string;
242
+ saveLastSyncResponse(): void;
203
243
  setupResyncInterval(): void;
204
- destroy(): void;
205
- stop(): void;
244
+ cleanupResyncInterval(): void;
245
+ simulateWebsocketError(): void;
246
+ disconnect(): void;
206
247
  setFetchClient(fetchClient?: FetchClient): void;
207
- fetchConnectionUrl(): Promise<string>;
208
- createWebSocket(): Promise<ReconnectingWebSocket>;
209
- start(): Promise<void>;
248
+ fetchConnectionUrl(connectionUrlExtraParams?: Record<string, string>): Promise<string>;
249
+ createWebSocket(connectionUrlExtraParams?: Record<string, string>): Promise<ReconnectingWebSocket>;
250
+ setAndEmitStatusInfo(status: WeaveStoreAzureWebPubSubSyncClientConnectionStatus): void;
251
+ connect(connectionUrlExtraParams?: Record<string, string>): Promise<void>;
210
252
  }
211
253
 
212
254
  //#endregion
@@ -226,11 +268,13 @@ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
226
268
  private init;
227
269
  emitEvent<T>(name: string, payload?: T): void;
228
270
  getClientId(): string | null;
229
- connect(): Promise<void>;
271
+ connect(extraParams?: Record<string, string>): Promise<void>;
230
272
  disconnect(): void;
273
+ simulateWebsocketError(): void;
274
+ destroy(): void;
231
275
  handleAwarenessChange(emit?: boolean): void;
232
276
  setAwarenessInfo<T>(field: string, value: T): void;
233
277
  }
234
278
 
235
279
  //#endregion
236
- export { FetchClient, FetchInitialState, FetchRoom, PersistRoom, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubsub, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions };
280
+ 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_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncClientOptions, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsub, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions };
package/dist/client.js CHANGED
@@ -3693,11 +3693,7 @@ const applyAwarenessUpdate = (awareness, update, origin) => {
3693
3693
  };
3694
3694
 
3695
3695
  //#endregion
3696
- //#region src/client.ts
3697
- const messageSyncStep1 = 0;
3698
- const messageAwareness = 1;
3699
- const messageQueryAwareness = 3;
3700
- const AzureWebPubSubJsonProtocol = "json.webpubsub.azure.v1";
3696
+ //#region src/types.ts
3701
3697
  let MessageType = /* @__PURE__ */ function(MessageType$1) {
3702
3698
  MessageType$1["System"] = "system";
3703
3699
  MessageType$1["JoinGroup"] = "joinGroup";
@@ -3710,6 +3706,28 @@ let MessageDataType = /* @__PURE__ */ function(MessageDataType$1) {
3710
3706
  MessageDataType$1["Awareness"] = "awareness";
3711
3707
  return MessageDataType$1;
3712
3708
  }({});
3709
+
3710
+ //#endregion
3711
+ //#region src/constants.ts
3712
+ const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
3713
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS = {
3714
+ ["CONNECTING"]: "connecting",
3715
+ ["CONNECTED"]: "connected",
3716
+ ["DISCONNECTED"]: "disconnected",
3717
+ ["ERROR"]: "error"
3718
+ };
3719
+ const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
3720
+ ["PUB"]: "pub",
3721
+ ["SUB"]: "sub"
3722
+ };
3723
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG = { resyncIntervalMs: 15e3 };
3724
+
3725
+ //#endregion
3726
+ //#region src/client.ts
3727
+ const messageSyncStep1 = 0;
3728
+ const messageAwareness = 1;
3729
+ const messageQueryAwareness = 3;
3730
+ const AzureWebPubSubJsonProtocol = "json.webpubsub.azure.v1";
3713
3731
  const messageHandlers = [];
3714
3732
  messageHandlers[messageSyncStep1] = (encoder, decoder, client, clientId, emitSynced, messageType) => {
3715
3733
  writeVarUint(encoder, messageType);
@@ -3727,6 +3745,7 @@ const readMessage = (client, buf, emitSynced, clientId) => {
3727
3745
  const decoder = createDecoder(buf);
3728
3746
  const encoder = createEncoder();
3729
3747
  const messageType = readVarUint(decoder);
3748
+ if (messageType === 0) client.saveLastSyncResponse();
3730
3749
  const messageHandler = messageHandlers[messageType];
3731
3750
  if (messageHandler) messageHandler(encoder, decoder, client, clientId, emitSynced, messageType);
3732
3751
  else throw new Error(`unable to handle message with type: ${messageType}`);
@@ -3752,15 +3771,17 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3752
3771
  this._fetchClient = fetch;
3753
3772
  this._url = url;
3754
3773
  this._uuid = v4();
3755
- this._status = "disconnected";
3774
+ this._status = WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.DISCONNECTED;
3756
3775
  this._wsConnected = false;
3757
3776
  this._initialized = false;
3758
3777
  this._connectionRetries = 0;
3759
3778
  this._synced = false;
3760
3779
  this._ws = null;
3761
- const awareness = new Awareness(doc);
3762
- this._awareness = awareness;
3763
3780
  this._resyncInterval = null;
3781
+ this._resyncCheckInterval = null;
3782
+ this._lastReceivedSyncResponse = null;
3783
+ const awareness = new Awareness(this.doc);
3784
+ this._awareness = awareness;
3764
3785
  this._updateHandler = (update, origin) => {
3765
3786
  if (origin !== this) {
3766
3787
  const encoder = createEncoder();
@@ -3774,10 +3795,10 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3774
3795
  const changedClients = added.concat(updated).concat(removed);
3775
3796
  const encoder = createEncoder();
3776
3797
  writeVarUint(encoder, messageAwareness);
3777
- writeVarUint8Array(encoder, encodeAwarenessUpdate(awareness, changedClients));
3798
+ writeVarUint8Array(encoder, encodeAwarenessUpdate(this.awareness, changedClients));
3778
3799
  sendToControlGroup(this, topic, MessageDataType.Awareness, toUint8Array(encoder));
3779
3800
  };
3780
- awareness.on("update", this._awarenessUpdateHandler);
3801
+ this._awareness.on("update", this._awarenessUpdateHandler);
3781
3802
  }
3782
3803
  get awareness() {
3783
3804
  return this._awareness;
@@ -3797,38 +3818,80 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3797
3818
  getClientId() {
3798
3819
  return this.id;
3799
3820
  }
3821
+ saveLastSyncResponse() {
3822
+ const now = new Date();
3823
+ this._lastReceivedSyncResponse = now.getTime();
3824
+ this.instance.emitEvent("onSyncResponse", this._lastReceivedSyncResponse);
3825
+ }
3800
3826
  setupResyncInterval() {
3801
- if (this._options.resyncInterval > 0) this._resyncInterval = setInterval(() => {
3802
- if (this._ws && this._wsConnected) {
3803
- const encoder = createEncoder();
3804
- writeVarUint(encoder, messageSyncStep1);
3805
- writeSyncStep1(encoder, this.doc);
3806
- sendToControlGroup(this, this.topic, MessageDataType.Sync, toUint8Array(encoder));
3807
- }
3808
- }, this._options.resyncInterval);
3827
+ if (this._options.resyncInterval > 0) {
3828
+ this._resyncInterval = setInterval(() => {
3829
+ if (this._ws && this._wsConnected) {
3830
+ const encoder = createEncoder();
3831
+ writeVarUint(encoder, messageSyncStep1);
3832
+ writeSyncStep1(encoder, this.doc);
3833
+ sendToControlGroup(this, this.topic, MessageDataType.Sync, toUint8Array(encoder));
3834
+ }
3835
+ }, this._options.resyncInterval);
3836
+ this._resyncCheckInterval = setInterval(() => {
3837
+ if (!this._lastReceivedSyncResponse) return;
3838
+ const resyncInSeconds = this._options.resyncInterval / 1e3;
3839
+ const resyncLimitInSeconds = resyncInSeconds + 5;
3840
+ const now = new Date();
3841
+ const diffInSeconds = (now.getTime() - this._lastReceivedSyncResponse) / 1e3;
3842
+ if (diffInSeconds > resyncLimitInSeconds && this._ws?.readyState === WebSocket.OPEN) {
3843
+ this._ws.dispatchEvent(new CustomEvent("error", {
3844
+ cancelable: false,
3845
+ bubbles: false,
3846
+ detail: new Error("No sync response")
3847
+ }));
3848
+ this._ws._ws.close();
3849
+ }
3850
+ }, this._options.resyncInterval + 5e3);
3851
+ }
3809
3852
  }
3810
- destroy() {
3811
- if (this._resyncInterval) clearInterval(this._resyncInterval);
3812
- this.stop();
3813
- this.doc.off("update", this._updateHandler);
3853
+ cleanupResyncInterval() {
3854
+ if (this._resyncInterval) {
3855
+ clearInterval(this._resyncInterval);
3856
+ this._resyncInterval = null;
3857
+ }
3858
+ if (this._resyncCheckInterval) {
3859
+ clearInterval(this._resyncCheckInterval);
3860
+ this._resyncCheckInterval = null;
3861
+ }
3862
+ }
3863
+ simulateWebsocketError() {
3864
+ if (this._ws) this._ws._ws.close(4e3, new Error("Simulated error for testing"));
3814
3865
  }
3815
- stop() {
3866
+ disconnect() {
3816
3867
  if (this._ws !== null) {
3817
3868
  const encoder = createEncoder();
3818
3869
  writeVarUint(encoder, messageAwareness);
3819
3870
  writeVarUint8Array(encoder, encodeAwarenessUpdate(this.awareness, [this.doc.clientID], new Map()));
3820
3871
  const u8 = toUint8Array(encoder);
3821
3872
  sendToControlGroup(this, this.topic, MessageDataType.Awareness, u8);
3873
+ removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.doc.clientID), this);
3822
3874
  this._initialized = false;
3823
- if (this._ws.readyState === WebSocket.OPEN) this._ws.close();
3875
+ this._ws.close();
3824
3876
  }
3877
+ this.cleanupResyncInterval();
3878
+ this._wsConnected = false;
3879
+ this._ws = null;
3825
3880
  }
3826
3881
  setFetchClient(fetchClient = window.fetch) {
3827
3882
  this._fetchClient = fetchClient.bind(window);
3828
3883
  }
3829
- async fetchConnectionUrl() {
3884
+ async fetchConnectionUrl(connectionUrlExtraParams) {
3830
3885
  try {
3831
- const res = await this._fetchClient(this._url);
3886
+ const connectionURL = new URL(this._url, isRelativeUrl(this._url) ? window.location.origin : void 0);
3887
+ if (connectionUrlExtraParams) {
3888
+ const extraParamsKeys = Object.keys(connectionUrlExtraParams);
3889
+ for (const key of extraParamsKeys) {
3890
+ if (connectionURL.searchParams.has(key)) connectionURL.searchParams.delete(key);
3891
+ connectionURL.searchParams.append(key, connectionUrlExtraParams[key]);
3892
+ }
3893
+ }
3894
+ const res = await this._fetchClient(connectionURL.toString());
3832
3895
  if (res.ok) {
3833
3896
  const data = await res.json();
3834
3897
  return data.url;
@@ -3837,7 +3900,7 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3837
3900
  throw new Error(`Failed to fetch connection url from: ${this._url}`);
3838
3901
  }
3839
3902
  }
3840
- async createWebSocket() {
3903
+ async createWebSocket(connectionUrlExtraParams) {
3841
3904
  const websocket = new ReconnectingWebSocket(async () => {
3842
3905
  let url = "https://error";
3843
3906
  let error = null;
@@ -3846,7 +3909,7 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3846
3909
  loading: true,
3847
3910
  error: null
3848
3911
  });
3849
- url = await this.fetchConnectionUrl();
3912
+ url = await this.fetchConnectionUrl(connectionUrlExtraParams);
3850
3913
  } catch (ex) {
3851
3914
  error = ex;
3852
3915
  } finally {
@@ -3864,14 +3927,12 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3864
3927
  this._initialized = false;
3865
3928
  this.synced = false;
3866
3929
  websocket.addEventListener("error", (e) => {
3867
- if (e) console.error("Websocket error", e);
3930
+ console.error("WebSocket error", e);
3868
3931
  if (this._initialized && websocket.retryCount > 0) {
3869
- this._status = "connecting";
3870
- this.emit("status", this._status);
3932
+ this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
3871
3933
  return;
3872
3934
  }
3873
- this._status = "error";
3874
- this.emit("status", this._status);
3935
+ this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.ERROR);
3875
3936
  });
3876
3937
  websocket.onmessage = (event) => {
3877
3938
  if (event.data === null) return;
@@ -3883,24 +3944,18 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3883
3944
  const encoder = readMessage(this, buf, true, messageData.f);
3884
3945
  if (length$1(encoder) > 1) sendToControlGroup(this, this.topic, MessageDataType.Sync, toUint8Array(encoder));
3885
3946
  };
3886
- websocket.onclose = (ev) => {
3887
- this._status = "disconnected";
3888
- this.emit("status", this._status);
3947
+ websocket.onclose = () => {
3948
+ if ((this._ws?.retryCount ?? 0) > 0) this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
3949
+ else this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.DISCONNECTED);
3889
3950
  if (this._wsConnected) {
3890
- if (this._resyncInterval) clearInterval(this._resyncInterval);
3891
- this._resyncInterval = null;
3951
+ this.cleanupResyncInterval();
3892
3952
  this._wsConnected = false;
3893
3953
  this.synced = false;
3894
3954
  removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((x) => x !== this.doc.clientID), this);
3895
3955
  }
3896
- if (ev.code === 1008 && websocket.readyState === WebSocket.OPEN) {
3897
- websocket.close();
3898
- this.createWebSocket();
3899
- }
3900
3956
  };
3901
3957
  websocket.onopen = () => {
3902
- this._status = "connected";
3903
- this.emit("status", this._status);
3958
+ this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTED);
3904
3959
  this._wsConnected = true;
3905
3960
  this._initialized = true;
3906
3961
  this._connectionRetries = this._connectionRetries++;
@@ -3911,19 +3966,31 @@ var WeaveStoreAzureWebPubSubSyncClient = class extends Emittery {
3911
3966
  writeSyncStep1(encoder, this.doc);
3912
3967
  const u8 = toUint8Array(encoder);
3913
3968
  sendToControlGroup(this, this.topic, MessageDataType.Init, u8);
3969
+ const encoderState = createEncoder();
3970
+ writeVarUint(encoderState, messageSyncStep1);
3971
+ writeSyncStep2(encoderState, this.doc);
3972
+ sendToControlGroup(this, this.topic, MessageDataType.Init, u8);
3973
+ const encoderAwarenessQuery = createEncoder();
3974
+ writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
3975
+ sendToControlGroup(this, this.topic, MessageDataType.Init, u8);
3914
3976
  if (this.awareness.getLocalState() !== null) {
3915
3977
  const encoderAwarenessState = createEncoder();
3916
3978
  writeVarUint(encoderAwarenessState, messageAwareness);
3917
3979
  writeVarUint8Array(encoderAwarenessState, encodeAwarenessUpdate(this.awareness, [this.doc.clientID]));
3918
- const u8$1 = toUint8Array(encoder);
3919
- sendToControlGroup(this, this.topic, MessageDataType.Awareness, u8$1);
3980
+ const u82 = toUint8Array(encoder);
3981
+ sendToControlGroup(this, this.topic, MessageDataType.Awareness, u82);
3920
3982
  }
3921
3983
  };
3984
+ this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
3922
3985
  return websocket;
3923
3986
  }
3924
- async start() {
3987
+ setAndEmitStatusInfo(status) {
3988
+ this._status = status;
3989
+ this.emit("status", this._status);
3990
+ }
3991
+ async connect(connectionUrlExtraParams) {
3925
3992
  if (this._wsConnected || this._ws) return;
3926
- await this.createWebSocket();
3993
+ await this.createWebSocket(connectionUrlExtraParams);
3927
3994
  }
3928
3995
  };
3929
3996
  function safeSend(data) {
@@ -3956,15 +4023,9 @@ function sendToControlGroup(client, group, type, u8) {
3956
4023
  if (!safeSend(payload)) return;
3957
4024
  client.ws?.send(payload);
3958
4025
  }
3959
-
3960
- //#endregion
3961
- //#region src/constants.ts
3962
- const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
3963
- const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
3964
- ["PUB"]: "pub",
3965
- ["SUB"]: "sub"
3966
- };
3967
- const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG = { resyncIntervalMs: 15e3 };
4026
+ function isRelativeUrl(url) {
4027
+ return !/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
4028
+ }
3968
4029
 
3969
4030
  //#endregion
3970
4031
  //#region src/store-azure-web-pubsub.ts
@@ -3995,9 +4056,12 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
3995
4056
  resyncInterval: this.azureWebPubsubOptions.resyncIntervalMs,
3996
4057
  tokenProvider: null
3997
4058
  });
4059
+ const awareness = this.provider.awareness;
4060
+ awareness.on("update", this.handleAwarenessChange.bind(this));
4061
+ awareness.on("change", this.handleAwarenessChange.bind(this));
3998
4062
  window.addEventListener("beforeunload", () => {
3999
- const awareness = this.provider.awareness;
4000
- awareness.destroy();
4063
+ const awareness$1 = this.provider.awareness;
4064
+ if (awareness$1) awareness$1.destroy();
4001
4065
  });
4002
4066
  this.provider.on("error", () => {
4003
4067
  this.handleConnectionStatusChange(WEAVE_STORE_CONNECTION_STATUS.DISCONNECTED);
@@ -4018,22 +4082,20 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4018
4082
  if (this.provider) return this.provider.getClientId();
4019
4083
  return null;
4020
4084
  }
4021
- async connect() {
4085
+ async connect(extraParams) {
4022
4086
  const { fetchClient } = this.azureWebPubsubOptions;
4023
- const awareness = this.provider.awareness;
4024
- awareness.on("update", this.handleAwarenessChange.bind(this));
4025
- awareness.on("change", this.handleAwarenessChange.bind(this));
4026
4087
  this.provider.setFetchClient(fetchClient ?? window.fetch);
4027
- await this.provider.start();
4088
+ await this.provider.connect(extraParams);
4028
4089
  }
4029
4090
  disconnect() {
4030
- const awareness = this.provider.awareness;
4031
- awareness.destroy();
4032
- awareness.off("update", this.handleAwarenessChange.bind(this));
4033
- awareness.off("change", this.handleAwarenessChange.bind(this));
4034
- this.provider.destroy();
4091
+ this.provider.disconnect();
4092
+ }
4093
+ simulateWebsocketError() {
4094
+ this.provider.simulateWebsocketError();
4035
4095
  }
4096
+ destroy() {}
4036
4097
  handleAwarenessChange(emit = true) {
4098
+ if (!this.instance) return;
4037
4099
  const awareness = this.provider.awareness;
4038
4100
  const values = Array.from(awareness.getStates().values());
4039
4101
  values.splice(awareness.clientID, 1);
@@ -4046,4 +4108,4 @@ var WeaveStoreAzureWebPubsub = class extends WeaveStore {
4046
4108
  };
4047
4109
 
4048
4110
  //#endregion
4049
- export { WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveStoreAzureWebPubsub };
4111
+ export { MessageDataType, MessageType, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveStoreAzureWebPubsub };
package/dist/server.d.ts CHANGED
@@ -5,10 +5,106 @@ import { Doc } from "yjs";
5
5
  import { WebSocket } from "ws";
6
6
  import koa from "koa";
7
7
  import Emittery from "emittery";
8
- import express from "express-serve-static-core";
8
+ import ReconnectingWebSocket from "reconnecting-websocket";
9
+ import * as awarenessProtocol$1 from "y-protocols/awareness";
9
10
  import * as awarenessProtocol from "y-protocols/awareness";
11
+ import { WeaveStore } from "@inditextech/weave-sdk";
12
+ import { WeaveStoreOptions } from "@inditextech/weave-types";
13
+ import { Encoder } from "lib0/encoding";
14
+ import { Decoder } from "lib0/decoding";
15
+ import express from "express-serve-static-core";
10
16
  import { RequestHandler } from "express";
11
17
 
18
+ //#region src/constants.d.ts
19
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
20
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS: {
21
+ "CONNECTING": string;
22
+ "CONNECTED": string;
23
+ "DISCONNECTED": string;
24
+ "ERROR": string;
25
+ };
26
+ declare const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE: {
27
+ "PUB": string;
28
+ "SUB": string;
29
+ };
30
+ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG: {
31
+ resyncIntervalMs: number;
32
+ };
33
+
34
+ //#endregion
35
+ //#region src/store-azure-web-pubsub.d.ts
36
+ declare class WeaveStoreAzureWebPubsub extends WeaveStore {
37
+ private azureWebPubsubOptions;
38
+ private roomId;
39
+ private started;
40
+ private initialRoomData;
41
+ protected provider: WeaveStoreAzureWebPubSubSyncClient;
42
+ protected name: string;
43
+ protected supportsUndoManager: boolean;
44
+ protected awarenessCallback: (changes: any) => void;
45
+ constructor(initialRoomData: Uint8Array | FetchInitialState | undefined, storeOptions: WeaveStoreOptions, azureWebPubsubOptions: Pick<WeaveStoreAzureWebPubsubOptions, "roomId" | "url"> & Partial<Omit<WeaveStoreAzureWebPubsubOptions, "roomId" | "url">>);
46
+ setup(): void;
47
+ private loadRoomInitialData;
48
+ private init;
49
+ emitEvent<T>(name: string, payload?: T): void;
50
+ getClientId(): string | null;
51
+ connect(extraParams?: Record<string, string>): Promise<void>;
52
+ disconnect(): void;
53
+ simulateWebsocketError(): void;
54
+ destroy(): void;
55
+ handleAwarenessChange(emit?: boolean): void;
56
+ setAwarenessInfo<T>(field: string, value: T): void;
57
+ }
58
+
59
+ //#endregion
60
+ //#region src/client.d.ts
61
+ declare class WeaveStoreAzureWebPubSubSyncClient extends Emittery {
62
+ doc: Doc;
63
+ topic: string;
64
+ private instance;
65
+ private _ws;
66
+ private _url;
67
+ private _fetchClient;
68
+ private _status;
69
+ private _wsConnected;
70
+ private _synced;
71
+ private _resyncInterval;
72
+ private _resyncCheckInterval;
73
+ private _lastReceivedSyncResponse;
74
+ private _connectionRetries;
75
+ private _uuid;
76
+ private _awareness;
77
+ private _options;
78
+ private _initialized;
79
+ private _updateHandler;
80
+ private _awarenessUpdateHandler;
81
+ /**
82
+ * @param {string} url
83
+ * @param {string} topic
84
+ * @param {Doc} doc
85
+ * @param {number} [options.resyncInterval] Request server state every `resyncInterval` milliseconds.
86
+ * @param {number} [options.tokenProvider] token generator for negotiation.
87
+ */
88
+ constructor(instance: WeaveStoreAzureWebPubsub, url: string, topic: string, doc: Doc, options?: WeaveStoreAzureWebPubSubSyncClientOptions);
89
+ get awareness(): awarenessProtocol$1.Awareness;
90
+ get synced(): boolean;
91
+ set synced(state: boolean);
92
+ get ws(): ReconnectingWebSocket | null;
93
+ get id(): string;
94
+ getClientId(): string;
95
+ saveLastSyncResponse(): void;
96
+ setupResyncInterval(): void;
97
+ cleanupResyncInterval(): void;
98
+ simulateWebsocketError(): void;
99
+ disconnect(): void;
100
+ setFetchClient(fetchClient?: FetchClient): void;
101
+ fetchConnectionUrl(connectionUrlExtraParams?: Record<string, string>): Promise<string>;
102
+ createWebSocket(connectionUrlExtraParams?: Record<string, string>): Promise<ReconnectingWebSocket>;
103
+ setAndEmitStatusInfo(status: WeaveStoreAzureWebPubSubSyncClientConnectionStatus): void;
104
+ connect(connectionUrlExtraParams?: Record<string, string>): Promise<void>;
105
+ }
106
+
107
+ //#endregion
12
108
  //#region src/types.d.ts
13
109
  type WeaveStoreAzureWebPubsubConfig = {
14
110
  endpoint: string;
@@ -81,6 +177,39 @@ type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
81
177
  type WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent = {
82
178
  group: string;
83
179
  };
180
+ type WeaveStoreAzureWebPubSubSyncHostClientConnectOptions = {
181
+ expirationTimeInMinutes?: number;
182
+ };
183
+ type WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys = keyof typeof WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS;
184
+ type WeaveStoreAzureWebPubSubSyncClientConnectionStatus = (typeof WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS)[WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys];
185
+ declare enum MessageType {
186
+ System = "system",
187
+ JoinGroup = "joinGroup",
188
+ SendToGroup = "sendToGroup",
189
+ }
190
+ declare enum MessageDataType {
191
+ Init = "init",
192
+ Sync = "sync",
193
+ Awareness = "awareness",
194
+ }
195
+ interface MessageData {
196
+ group: string;
197
+ t: string;
198
+ f: string;
199
+ c: string;
200
+ }
201
+ interface Message {
202
+ type: string;
203
+ fromUserId: string;
204
+ from: string;
205
+ group: string;
206
+ data: MessageData;
207
+ }
208
+ type MessageHandler = (encoder: Encoder, decoder: Decoder, client: WeaveStoreAzureWebPubSubSyncClient, clientId: string, emitSynced: boolean, messageType: number) => void;
209
+ interface WeaveStoreAzureWebPubSubSyncClientOptions {
210
+ resyncInterval: number;
211
+ tokenProvider: Promise<string> | null;
212
+ }
84
213
 
85
214
  //#endregion
86
215
  //#region src/server/event-handler/enum/mqtt-error-codes/mqtt-disconnect-reason-code.d.ts
@@ -407,7 +536,9 @@ declare enum MqttV500ConnectReasonCode {
407
536
  * Description: The connection rate limit has been exceeded.
408
537
  */
409
538
  ConnectionRateExceeded = 159,
410
- } //#endregion
539
+ }
540
+
541
+ //#endregion
411
542
  //#region src/server/event-handler/cloud-events-protocols.d.ts
412
543
  /**
413
544
  * Response of the connect event.
@@ -874,11 +1005,15 @@ declare class WeaveStoreAzureWebPubSubSyncHost {
874
1005
  topicAwarenessChannel: string;
875
1006
  private _client;
876
1007
  private _conn;
1008
+ private _reconnectAttempts;
1009
+ private _forceClose;
877
1010
  private _awareness;
1011
+ private _updateHandler;
1012
+ private _awarenessUpdateHandler;
878
1013
  constructor(server: WeaveAzureWebPubsubServer, client: WebPubSubServiceClient, topic: string, doc: Y.Doc);
879
1014
  get awareness(): awarenessProtocol.Awareness;
880
1015
  sendInitAwarenessInfo(origin: string): void;
881
- createWebSocket(sleep?: number): Promise<void>;
1016
+ createWebSocket(): Promise<void>;
882
1017
  start(): Promise<void>;
883
1018
  stop(): Promise<void>;
884
1019
  simulateWebsocketError(): void;
@@ -911,7 +1046,7 @@ declare class WeaveAzureWebPubsubSyncHandler extends WebPubSubEventHandler {
911
1046
  private getHostConnection;
912
1047
  getRoomsLoaded(): string[];
913
1048
  getRoomSyncHost(roomId: string): WeaveStoreAzureWebPubSubSyncHost | undefined;
914
- clientConnect(roomId: string): Promise<string>;
1049
+ clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string>;
915
1050
  }
916
1051
 
917
1052
  //#endregion
@@ -941,19 +1076,8 @@ declare class WeaveAzureWebPubsubServer extends Emittery {
941
1076
  emitEvent<T>(event: string, payload?: T): void;
942
1077
  addEventListener<T>(event: string, callback: (payload: T) => void): void;
943
1078
  removeEventListener<T>(event: string, callback: (payload: T) => void): void;
944
- clientConnect(roomId: string): Promise<string | null>;
1079
+ clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string | null>;
945
1080
  }
946
1081
 
947
1082
  //#endregion
948
- //#region src/constants.d.ts
949
- declare const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
950
- declare const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE: {
951
- "PUB": string;
952
- "SUB": string;
953
- };
954
- declare const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG: {
955
- resyncIntervalMs: number;
956
- };
957
-
958
- //#endregion
959
- export { Certificate, ConnectErrorResponse, ConnectRequest, ConnectResponse, ConnectResponseHandler, ConnectedRequest, ConnectionContext, DisconnectedRequest, FetchClient, FetchInitialState, FetchRoom, 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_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncHost, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions, WebPubSubClientProtocol, WebPubSubEventHandler, WebPubSubEventHandlerOptions };
1083
+ 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_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveAzureWebPubsubSyncHandlerOptions, WeaveStoreAzureWebPubSubSyncClientConnectionStatus, WeaveStoreAzureWebPubSubSyncClientConnectionStatusKeys, WeaveStoreAzureWebPubSubSyncClientOptions, WeaveStoreAzureWebPubSubSyncHost, WeaveStoreAzureWebPubSubSyncHostClientConnectOptions, WeaveStoreAzureWebPubsubConfig, WeaveStoreAzureWebPubsubEvents, WeaveStoreAzureWebPubsubOnConnectEvent, WeaveStoreAzureWebPubsubOnConnectedEvent, WeaveStoreAzureWebPubsubOnDisconnectedEvent, WeaveStoreAzureWebPubsubOnStoreFetchConnectionUrlEvent, WeaveStoreAzureWebPubsubOnWebsocketCloseEvent, WeaveStoreAzureWebPubsubOnWebsocketErrorEvent, WeaveStoreAzureWebPubsubOnWebsocketJoinGroupEvent, WeaveStoreAzureWebPubsubOnWebsocketMessageEvent, WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent, WeaveStoreAzureWebPubsubOnWebsocketOpenEvent, WeaveStoreAzureWebPubsubOptions, WebPubSubClientProtocol, WebPubSubEventHandler, WebPubSubEventHandlerOptions };
package/dist/server.js CHANGED
@@ -20769,6 +20769,21 @@ Object.defineProperty(Emittery, "listenerRemoved", {
20769
20769
  configurable: false
20770
20770
  });
20771
20771
 
20772
+ //#endregion
20773
+ //#region src/types.ts
20774
+ let MessageType = /* @__PURE__ */ function(MessageType$2) {
20775
+ MessageType$2["System"] = "system";
20776
+ MessageType$2["JoinGroup"] = "joinGroup";
20777
+ MessageType$2["SendToGroup"] = "sendToGroup";
20778
+ return MessageType$2;
20779
+ }({});
20780
+ let MessageDataType = /* @__PURE__ */ function(MessageDataType$2) {
20781
+ MessageDataType$2["Init"] = "init";
20782
+ MessageDataType$2["Sync"] = "sync";
20783
+ MessageDataType$2["Awareness"] = "awareness";
20784
+ return MessageDataType$2;
20785
+ }({});
20786
+
20772
20787
  //#endregion
20773
20788
  //#region src/yjs.ts
20774
20789
  var yjs_default = Y$1;
@@ -22809,20 +22824,22 @@ const expirationTimeInMinutes = 60;
22809
22824
  const messageSync = 0;
22810
22825
  const messageAwareness = 1;
22811
22826
  const AzureWebPubSubJsonProtocol = "json.webpubsub.azure.v1";
22812
- let MessageType = /* @__PURE__ */ function(MessageType$1) {
22813
- MessageType$1["System"] = "system";
22814
- MessageType$1["JoinGroup"] = "joinGroup";
22815
- MessageType$1["SendToGroup"] = "sendToGroup";
22816
- return MessageType$1;
22827
+ let MessageType$1 = /* @__PURE__ */ function(MessageType$2) {
22828
+ MessageType$2["System"] = "system";
22829
+ MessageType$2["JoinGroup"] = "joinGroup";
22830
+ MessageType$2["SendToGroup"] = "sendToGroup";
22831
+ return MessageType$2;
22817
22832
  }({});
22818
- let MessageDataType = /* @__PURE__ */ function(MessageDataType$1) {
22819
- MessageDataType$1["Init"] = "init";
22820
- MessageDataType$1["Sync"] = "sync";
22821
- MessageDataType$1["Awareness"] = "awareness";
22822
- return MessageDataType$1;
22833
+ let MessageDataType$1 = /* @__PURE__ */ function(MessageDataType$2) {
22834
+ MessageDataType$2["Init"] = "init";
22835
+ MessageDataType$2["Sync"] = "sync";
22836
+ MessageDataType$2["Awareness"] = "awareness";
22837
+ return MessageDataType$2;
22823
22838
  }({});
22824
22839
  const HostUserId = "host";
22825
22840
  var WeaveStoreAzureWebPubSubSyncHost = class {
22841
+ _reconnectAttempts = 0;
22842
+ _forceClose = false;
22826
22843
  constructor(server, client, topic, doc) {
22827
22844
  this.server = server;
22828
22845
  this.doc = doc;
@@ -22831,39 +22848,48 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22831
22848
  this._client = client;
22832
22849
  this._conn = null;
22833
22850
  this._awareness = new Awareness(this.doc);
22834
- this._awareness.setLocalState(null);
22835
- const awarenessUpdateHandler = ({ added, updated, removed }, origin) => {
22836
- const changedClients = added.concat(added, updated, removed);
22837
- const encoder = createEncoder();
22838
- writeVarUint(encoder, messageAwareness);
22839
- writeVarUint8Array(encoder, encodeAwarenessUpdate(this._awareness, changedClients));
22840
- const u8 = toUint8Array(encoder);
22841
- this.broadcast(this.topic, origin, u8);
22851
+ this._awarenessUpdateHandler = ({ added, updated, removed }, origin) => {
22852
+ try {
22853
+ const changedClients = added.concat(added, updated, removed);
22854
+ const encoder = createEncoder();
22855
+ writeVarUint(encoder, messageAwareness);
22856
+ const payload = encodeAwarenessUpdate(this._awareness, changedClients);
22857
+ writeVarUint8Array(encoder, payload);
22858
+ const u8 = toUint8Array(encoder);
22859
+ this.broadcast(this.topic, origin, u8);
22860
+ } catch (err) {
22861
+ console.error("Error in awareness update handler:", err);
22862
+ }
22842
22863
  };
22843
- this._awareness.on("update", awarenessUpdateHandler);
22844
- const updateHandler = (update, origin) => {
22845
- const encoder = createEncoder();
22846
- writeVarUint(encoder, messageSync);
22847
- writeUpdate(encoder, update);
22848
- const u8 = toUint8Array(encoder);
22849
- this.broadcast(this.topic, origin, u8);
22864
+ this._awareness.on("update", this._awarenessUpdateHandler);
22865
+ this._updateHandler = (update, origin) => {
22866
+ try {
22867
+ const encoder = createEncoder();
22868
+ writeVarUint(encoder, messageSync);
22869
+ writeUpdate(encoder, update);
22870
+ const u8 = toUint8Array(encoder);
22871
+ this.broadcast(this.topic, origin, u8);
22872
+ } catch (err) {
22873
+ console.error("Error in document update handler:", err);
22874
+ }
22850
22875
  };
22851
- this.doc.on("update", updateHandler);
22876
+ this.doc.on("update", this._updateHandler);
22852
22877
  }
22853
22878
  get awareness() {
22854
22879
  return this._awareness;
22855
22880
  }
22856
22881
  sendInitAwarenessInfo(origin) {
22882
+ if (!this._awareness) return;
22857
22883
  const encoderAwarenessState = createEncoder();
22858
22884
  writeVarUint(encoderAwarenessState, messageAwareness);
22859
22885
  writeVarUint8Array(encoderAwarenessState, encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
22860
22886
  const u8 = toUint8Array(encoderAwarenessState);
22861
22887
  this.broadcast(this.topic, origin, u8);
22862
22888
  }
22863
- async createWebSocket(sleep = 0) {
22889
+ async createWebSocket() {
22864
22890
  const group = this.topic;
22865
22891
  const { url: url$1 } = await this.negotiate(this.topic);
22866
- if (sleep && sleep > 0) await new Promise((resolve) => setTimeout(resolve, sleep));
22892
+ this._reconnectAttempts++;
22867
22893
  return new Promise((resolve) => {
22868
22894
  const ws = new WebSocket(url$1, AzureWebPubSubJsonProtocol);
22869
22895
  ws.addEventListener("open", (event) => {
@@ -22872,7 +22898,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22872
22898
  event
22873
22899
  });
22874
22900
  ws.send(JSON.stringify({
22875
- type: MessageType.JoinGroup,
22901
+ type: MessageType$1.JoinGroup,
22876
22902
  group: `${group}.host`
22877
22903
  }));
22878
22904
  this.server.emitEvent("onWsJoinGroup", { group: `${group}.host` });
@@ -22886,15 +22912,15 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22886
22912
  });
22887
22913
  const event = JSON.parse(e.data.toString());
22888
22914
  if (event.type === "message" && event.from === "group") switch (event.data.t) {
22889
- case MessageDataType.Init:
22915
+ case MessageDataType$1.Init:
22890
22916
  this.onClientInit(group, event.data);
22891
22917
  this.onClientSync(group, event.data);
22892
22918
  this.sendInitAwarenessInfo(event.data.f);
22893
22919
  return;
22894
- case MessageDataType.Sync:
22920
+ case MessageDataType$1.Sync:
22895
22921
  this.onClientSync(group, event.data);
22896
22922
  return;
22897
- case MessageDataType.Awareness:
22923
+ case MessageDataType$1.Awareness:
22898
22924
  this.onAwareness(group, event.data);
22899
22925
  return;
22900
22926
  }
@@ -22904,9 +22930,12 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22904
22930
  group: `${group}.host`,
22905
22931
  event: e
22906
22932
  });
22907
- if (e.code === 1008 && ws.readyState === WebSocket.OPEN) {
22908
- ws.close();
22909
- this.createWebSocket();
22933
+ if (this._forceClose) return;
22934
+ else {
22935
+ const timeout = 1e3 * Math.pow(1.5, this._reconnectAttempts);
22936
+ setTimeout(() => {
22937
+ this.createWebSocket();
22938
+ }, timeout);
22910
22939
  }
22911
22940
  });
22912
22941
  ws.addEventListener("error", (error) => {
@@ -22915,7 +22944,6 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22915
22944
  error
22916
22945
  });
22917
22946
  if (ws.readyState === WebSocket.OPEN) ws.close();
22918
- this.createWebSocket(2e4);
22919
22947
  });
22920
22948
  setTimeout(() => {
22921
22949
  if (ws.readyState === WebSocket.OPEN) {
@@ -22930,6 +22958,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22930
22958
  await this.createWebSocket();
22931
22959
  }
22932
22960
  async stop() {
22961
+ this._forceClose = true;
22933
22962
  if (this._conn?.readyState === WebSocket.OPEN) {
22934
22963
  this._conn?.close();
22935
22964
  this._conn = null;
@@ -22948,30 +22977,38 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
22948
22977
  return true;
22949
22978
  }
22950
22979
  broadcast(group, from$1, u8) {
22951
- const payload = JSON.stringify({
22952
- type: MessageType.SendToGroup,
22953
- group,
22954
- noEcho: true,
22955
- data: {
22956
- f: from$1,
22957
- c: Buffer.from(u8).toString("base64")
22958
- }
22959
- });
22960
- if (!this.safeSend(payload)) return;
22961
- this._conn?.send?.(payload);
22980
+ try {
22981
+ const payload = JSON.stringify({
22982
+ type: MessageType$1.SendToGroup,
22983
+ group,
22984
+ noEcho: true,
22985
+ data: {
22986
+ f: from$1,
22987
+ c: Buffer.from(u8).toString("base64")
22988
+ }
22989
+ });
22990
+ if (!this.safeSend(payload)) return;
22991
+ this._conn?.send?.(payload);
22992
+ } catch (ex) {
22993
+ console.error("Error broadcasting message:", ex);
22994
+ }
22962
22995
  }
22963
22996
  send(group, to, u8) {
22964
- const payload = JSON.stringify({
22965
- type: MessageType.SendToGroup,
22966
- group,
22967
- noEcho: true,
22968
- data: {
22969
- t: to,
22970
- c: Buffer.from(u8).toString("base64")
22971
- }
22972
- });
22973
- if (!this.safeSend(payload)) return;
22974
- this._conn?.send?.(payload);
22997
+ try {
22998
+ const payload = JSON.stringify({
22999
+ type: MessageType$1.SendToGroup,
23000
+ group,
23001
+ noEcho: true,
23002
+ data: {
23003
+ t: to,
23004
+ c: Buffer.from(u8).toString("base64")
23005
+ }
23006
+ });
23007
+ if (!this.safeSend(payload)) return;
23008
+ this._conn?.send?.(payload);
23009
+ } catch (ex) {
23010
+ console.error("Error sending message:", ex);
23011
+ }
22975
23012
  }
22976
23013
  onClientInit(group, data) {
22977
23014
  const encoder = createEncoder();
@@ -23003,6 +23040,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
23003
23040
  const decoder = createDecoder(buf);
23004
23041
  readVarUint(decoder);
23005
23042
  const update = readVarUint8Array(decoder);
23043
+ if (!this._awareness) return;
23006
23044
  applyAwarenessUpdate(this._awareness, update, void 0);
23007
23045
  } catch (err) {
23008
23046
  this.doc.emit("error", [err]);
@@ -23114,11 +23152,12 @@ var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
23114
23152
  getRoomSyncHost(roomId) {
23115
23153
  return this._roomsSyncHost.get(roomId);
23116
23154
  }
23117
- async clientConnect(roomId) {
23155
+ async clientConnect(roomId, connectionOptions) {
23118
23156
  await this.getHostConnection(roomId);
23119
23157
  const token = await this._client.getClientAccessToken({
23120
23158
  groups: [roomId],
23121
- roles: [`webpubsub.joinLeaveGroup.${roomId}`, `webpubsub.sendToGroup.${roomId}.host`]
23159
+ roles: [`webpubsub.joinLeaveGroup.${roomId}`, `webpubsub.sendToGroup.${roomId}.host`],
23160
+ ...connectionOptions
23122
23161
  });
23123
23162
  const finalURL = `${token.url}&group=${roomId}`;
23124
23163
  return finalURL;
@@ -23165,14 +23204,20 @@ var WeaveAzureWebPubsubServer = class extends Emittery {
23165
23204
  removeEventListener(event, callback) {
23166
23205
  this.off(event, callback);
23167
23206
  }
23168
- async clientConnect(roomId) {
23169
- return await this.syncHandler.clientConnect(roomId);
23207
+ async clientConnect(roomId, connectionOptions) {
23208
+ return await this.syncHandler.clientConnect(roomId, connectionOptions);
23170
23209
  }
23171
23210
  };
23172
23211
 
23173
23212
  //#endregion
23174
23213
  //#region src/constants.ts
23175
23214
  const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
23215
+ const WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS = {
23216
+ ["CONNECTING"]: "connecting",
23217
+ ["CONNECTED"]: "connected",
23218
+ ["DISCONNECTED"]: "disconnected",
23219
+ ["ERROR"]: "error"
23220
+ };
23176
23221
  const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
23177
23222
  ["PUB"]: "pub",
23178
23223
  ["SUB"]: "sub"
@@ -23180,4 +23225,4 @@ const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
23180
23225
  const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG = { resyncIntervalMs: 15e3 };
23181
23226
 
23182
23227
  //#endregion
23183
- export { MqttDisconnectReasonCode, MqttV311ConnectReturnCode, MqttV500ConnectReasonCode, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveStoreAzureWebPubSubSyncHost, WebPubSubEventHandler };
23228
+ export { MessageDataType, MessageType, MqttDisconnectReasonCode, MqttV311ConnectReturnCode, MqttV500ConnectReasonCode, WEAVE_STORE_AZURE_WEB_PUBSUB, WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS, WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG, WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE, WeaveAzureWebPubsubServer, WeaveStoreAzureWebPubSubSyncHost, WebPubSubEventHandler };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inditextech/weave-store-azure-web-pubsub",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Jesus Manuel Piñeiro Cid <jesusmpc@inditex.com>",
@@ -57,8 +57,8 @@
57
57
  "dependencies": {
58
58
  "@azure/identity": "4.10.2",
59
59
  "@azure/web-pubsub": "1.2.0",
60
- "@inditextech/weave-types": "2.0.2",
61
- "@inditextech/weave-sdk": "2.0.2",
60
+ "@inditextech/weave-types": "2.0.3",
61
+ "@inditextech/weave-sdk": "2.0.3",
62
62
  "@syncedstore/core": "0.6.0",
63
63
  "buffer": "6.0.3",
64
64
  "reconnecting-websocket": "4.4.0",