@inditextech/weave-store-azure-web-pubsub 2.0.2 → 2.1.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 +59 -15
- package/dist/client.js +132 -70
- package/dist/server.d.ts +148 -21
- package/dist/server.js +189 -90
- package/package.json +3 -3
package/dist/client.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { WeaveStore } from "@inditextech/weave-sdk";
|
|
2
|
-
import { WeaveStoreOptions } from "@inditextech/weave-types";
|
|
2
|
+
import { DeepPartial, WeaveStoreOptions } from "@inditextech/weave-types";
|
|
3
3
|
import ReconnectingWebSocket from "reconnecting-websocket";
|
|
4
4
|
import { Doc } from "yjs";
|
|
5
5
|
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;
|
|
@@ -92,13 +100,13 @@ declare const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG: {
|
|
|
92
100
|
//#region src/types.d.ts
|
|
93
101
|
type WeaveStoreAzureWebPubsubConfig = {
|
|
94
102
|
endpoint: string;
|
|
103
|
+
persistIntervalMs?: number;
|
|
95
104
|
hubName: string;
|
|
96
105
|
auth?: {
|
|
97
106
|
key?: string;
|
|
98
107
|
custom?: TokenCredential;
|
|
99
108
|
};
|
|
100
|
-
connectionHandlers?:
|
|
101
|
-
persistIntervalMs?: number;
|
|
109
|
+
connectionHandlers?: DeepPartial<WeaveAzureWebPubsubSyncHandlerOptions>;
|
|
102
110
|
};
|
|
103
111
|
type WeaveAzureWebPubsubSyncHandlerOptions = {
|
|
104
112
|
onConnect?: (connectionId: string, queries: Record<string, string[]> | undefined) => Promise<void>;
|
|
@@ -161,13 +169,42 @@ type WeaveStoreAzureWebPubsubOnWebsocketErrorEvent = {
|
|
|
161
169
|
type WeaveStoreAzureWebPubsubOnWebsocketOnTokenRefreshEvent = {
|
|
162
170
|
group: string;
|
|
163
171
|
};
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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?:
|
|
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
|
-
|
|
205
|
-
|
|
244
|
+
cleanupResyncInterval(): void;
|
|
245
|
+
simulateWebsocketError(): void;
|
|
246
|
+
disconnect(): void;
|
|
206
247
|
setFetchClient(fetchClient?: FetchClient): void;
|
|
207
|
-
fetchConnectionUrl(): Promise<string>;
|
|
208
|
-
createWebSocket(): Promise<ReconnectingWebSocket>;
|
|
209
|
-
|
|
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/
|
|
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 =
|
|
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
|
-
|
|
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)
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
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
|
-
|
|
3811
|
-
if (this._resyncInterval)
|
|
3812
|
-
|
|
3813
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
3930
|
+
console.error("WebSocket error", e);
|
|
3868
3931
|
if (this._initialized && websocket.retryCount > 0) {
|
|
3869
|
-
this.
|
|
3870
|
-
this.emit("status", this._status);
|
|
3932
|
+
this.setAndEmitStatusInfo(WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS.CONNECTING);
|
|
3871
3933
|
return;
|
|
3872
3934
|
}
|
|
3873
|
-
this.
|
|
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 = (
|
|
3887
|
-
this.
|
|
3888
|
-
this.
|
|
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
|
-
|
|
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.
|
|
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
|
|
3919
|
-
sendToControlGroup(this, this.topic, MessageDataType.Awareness,
|
|
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
|
-
|
|
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
|
-
|
|
3961
|
-
|
|
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.
|
|
4088
|
+
await this.provider.connect(extraParams);
|
|
4028
4089
|
}
|
|
4029
4090
|
disconnect() {
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
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,20 +5,116 @@ import { Doc } from "yjs";
|
|
|
5
5
|
import { WebSocket } from "ws";
|
|
6
6
|
import koa from "koa";
|
|
7
7
|
import Emittery from "emittery";
|
|
8
|
-
import
|
|
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 { DeepPartial, 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;
|
|
111
|
+
persistIntervalMs?: number;
|
|
15
112
|
hubName: string;
|
|
16
113
|
auth?: {
|
|
17
114
|
key?: string;
|
|
18
115
|
custom?: TokenCredential;
|
|
19
116
|
};
|
|
20
|
-
connectionHandlers?:
|
|
21
|
-
persistIntervalMs?: number;
|
|
117
|
+
connectionHandlers?: DeepPartial<WeaveAzureWebPubsubSyncHandlerOptions>;
|
|
22
118
|
};
|
|
23
119
|
type WeaveAzureWebPubsubSyncHandlerOptions = {
|
|
24
120
|
onConnect?: (connectionId: string, queries: Record<string, string[]> | undefined) => Promise<void>;
|
|
@@ -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
|
-
}
|
|
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.
|
|
@@ -869,16 +1000,21 @@ declare class WebPubSubEventHandler {
|
|
|
869
1000
|
//#region src/server/azure-web-pubsub-host.d.ts
|
|
870
1001
|
declare class WeaveStoreAzureWebPubSubSyncHost {
|
|
871
1002
|
private readonly server;
|
|
1003
|
+
private readonly syncHandler;
|
|
872
1004
|
doc: Y.Doc;
|
|
873
1005
|
topic: string;
|
|
874
1006
|
topicAwarenessChannel: string;
|
|
875
1007
|
private _client;
|
|
876
1008
|
private _conn;
|
|
1009
|
+
private _reconnectAttempts;
|
|
1010
|
+
private _forceClose;
|
|
877
1011
|
private _awareness;
|
|
878
|
-
|
|
1012
|
+
private _updateHandler;
|
|
1013
|
+
private _awarenessUpdateHandler;
|
|
1014
|
+
constructor(server: WeaveAzureWebPubsubServer, syncHandler: WeaveAzureWebPubsubSyncHandler, client: WebPubSubServiceClient, topic: string, doc: Y.Doc);
|
|
879
1015
|
get awareness(): awarenessProtocol.Awareness;
|
|
880
1016
|
sendInitAwarenessInfo(origin: string): void;
|
|
881
|
-
createWebSocket(
|
|
1017
|
+
createWebSocket(): Promise<void>;
|
|
882
1018
|
start(): Promise<void>;
|
|
883
1019
|
stop(): Promise<void>;
|
|
884
1020
|
simulateWebsocketError(): void;
|
|
@@ -901,17 +1037,19 @@ declare class WeaveAzureWebPubsubSyncHandler extends WebPubSubEventHandler {
|
|
|
901
1037
|
private readonly syncOptions?;
|
|
902
1038
|
private initialState;
|
|
903
1039
|
private readonly server;
|
|
1040
|
+
private readonly roomsLastState;
|
|
904
1041
|
constructor(hub: string, server: WeaveAzureWebPubsubServer, client: WebPubSubServiceClient, initialState: FetchInitialState, syncHandlerOptions?: WeaveAzureWebPubsubSyncHandlerOptions, eventHandlerOptions?: WebPubSubEventHandlerOptions);
|
|
905
1042
|
private getNewYDoc;
|
|
906
1043
|
private setupRoomInstance;
|
|
907
|
-
|
|
1044
|
+
isPersistingOnInterval(): boolean;
|
|
908
1045
|
private setupRoomInstancePersistence;
|
|
1046
|
+
persistRoomTask(roomId: string): Promise<void>;
|
|
909
1047
|
private handleConnectionDisconnection;
|
|
910
1048
|
destroyRoomInstance(roomId: string): Promise<void>;
|
|
911
1049
|
private getHostConnection;
|
|
912
1050
|
getRoomsLoaded(): string[];
|
|
913
1051
|
getRoomSyncHost(roomId: string): WeaveStoreAzureWebPubSubSyncHost | undefined;
|
|
914
|
-
clientConnect(roomId: string): Promise<string>;
|
|
1052
|
+
clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string>;
|
|
915
1053
|
}
|
|
916
1054
|
|
|
917
1055
|
//#endregion
|
|
@@ -941,19 +1079,8 @@ declare class WeaveAzureWebPubsubServer extends Emittery {
|
|
|
941
1079
|
emitEvent<T>(event: string, payload?: T): void;
|
|
942
1080
|
addEventListener<T>(event: string, callback: (payload: T) => void): void;
|
|
943
1081
|
removeEventListener<T>(event: string, callback: (payload: T) => void): void;
|
|
944
|
-
clientConnect(roomId: string): Promise<string | null>;
|
|
1082
|
+
clientConnect(roomId: string, connectionOptions?: WeaveStoreAzureWebPubSubSyncHostClientConnectOptions): Promise<string | null>;
|
|
945
1083
|
}
|
|
946
1084
|
|
|
947
1085
|
//#endregion
|
|
948
|
-
|
|
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 };
|
|
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_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
|
@@ -8,6 +8,7 @@ import { URL as URL$1 } from "node:url";
|
|
|
8
8
|
import { EOL } from "node:os";
|
|
9
9
|
import process$1 from "node:process";
|
|
10
10
|
import { WebSocket } from "ws";
|
|
11
|
+
import crypto from "node:crypto";
|
|
11
12
|
import { defaultInitialState } from "@inditextech/weave-sdk/server";
|
|
12
13
|
|
|
13
14
|
//#region rolldown:runtime
|
|
@@ -18609,6 +18610,12 @@ var require_response = __commonJS({ "../../node_modules/koa/lib/response.js"(exp
|
|
|
18609
18610
|
set body(val) {
|
|
18610
18611
|
const original = this._body;
|
|
18611
18612
|
this._body = val;
|
|
18613
|
+
const cleanupPreviousStream = () => {
|
|
18614
|
+
if (original && isStream$1(original)) {
|
|
18615
|
+
original.once("error", () => {});
|
|
18616
|
+
if (!isStream$1(val)) destroy$1(original);
|
|
18617
|
+
}
|
|
18618
|
+
};
|
|
18612
18619
|
if (val == null) {
|
|
18613
18620
|
if (!statuses$3.empty[this.status]) {
|
|
18614
18621
|
if (this.type === "application/json") {
|
|
@@ -18621,6 +18628,7 @@ var require_response = __commonJS({ "../../node_modules/koa/lib/response.js"(exp
|
|
|
18621
18628
|
this.remove("Content-Type");
|
|
18622
18629
|
this.remove("Content-Length");
|
|
18623
18630
|
this.remove("Transfer-Encoding");
|
|
18631
|
+
cleanupPreviousStream();
|
|
18624
18632
|
return;
|
|
18625
18633
|
}
|
|
18626
18634
|
if (!this._explicitStatus) this.status = 200;
|
|
@@ -18628,29 +18636,33 @@ var require_response = __commonJS({ "../../node_modules/koa/lib/response.js"(exp
|
|
|
18628
18636
|
if (typeof val === "string") {
|
|
18629
18637
|
if (setType) this.type = /^\s*</.test(val) ? "html" : "text";
|
|
18630
18638
|
this.length = Buffer.byteLength(val);
|
|
18639
|
+
cleanupPreviousStream();
|
|
18631
18640
|
return;
|
|
18632
18641
|
}
|
|
18633
18642
|
if (Buffer.isBuffer(val)) {
|
|
18634
18643
|
if (setType) this.type = "bin";
|
|
18635
18644
|
this.length = val.length;
|
|
18645
|
+
cleanupPreviousStream();
|
|
18636
18646
|
return;
|
|
18637
18647
|
}
|
|
18638
18648
|
if (isStream$1(val)) {
|
|
18639
18649
|
onFinish(this.res, destroy$1.bind(null, val));
|
|
18640
18650
|
if (original !== val) {
|
|
18641
|
-
val.once("error", (err) => this.ctx.onerror(err));
|
|
18642
18651
|
if (original != null) this.remove("Content-Length");
|
|
18652
|
+
cleanupPreviousStream();
|
|
18643
18653
|
}
|
|
18644
18654
|
if (setType) this.type = "bin";
|
|
18645
18655
|
return;
|
|
18646
18656
|
}
|
|
18647
18657
|
if (val instanceof ReadableStream) {
|
|
18648
18658
|
if (setType) this.type = "bin";
|
|
18659
|
+
cleanupPreviousStream();
|
|
18649
18660
|
return;
|
|
18650
18661
|
}
|
|
18651
18662
|
if (val instanceof Blob) {
|
|
18652
18663
|
if (setType) this.type = "bin";
|
|
18653
18664
|
this.length = val.size;
|
|
18665
|
+
cleanupPreviousStream();
|
|
18654
18666
|
return;
|
|
18655
18667
|
}
|
|
18656
18668
|
if (val instanceof Response) {
|
|
@@ -18658,10 +18670,12 @@ var require_response = __commonJS({ "../../node_modules/koa/lib/response.js"(exp
|
|
|
18658
18670
|
if (setType) this.type = "bin";
|
|
18659
18671
|
const headers = val.headers;
|
|
18660
18672
|
for (const key of headers.keys()) this.set(key, headers.get(key));
|
|
18673
|
+
cleanupPreviousStream();
|
|
18661
18674
|
return;
|
|
18662
18675
|
}
|
|
18663
18676
|
this.remove("Content-Length");
|
|
18664
18677
|
if (!this.type || !/\bjson\b/i.test(this.type)) this.type = "json";
|
|
18678
|
+
cleanupPreviousStream();
|
|
18665
18679
|
},
|
|
18666
18680
|
set length(n) {
|
|
18667
18681
|
if (!this.has("Transfer-Encoding")) this.set("Content-Length", n);
|
|
@@ -19818,19 +19832,19 @@ var require_delegates = __commonJS({ "../../node_modules/delegates/index.js"(exp
|
|
|
19818
19832
|
//#endregion
|
|
19819
19833
|
//#region ../../node_modules/tsscmp/lib/index.js
|
|
19820
19834
|
var require_lib = __commonJS({ "../../node_modules/tsscmp/lib/index.js"(exports, module) {
|
|
19821
|
-
var crypto$
|
|
19835
|
+
var crypto$2 = __require("crypto");
|
|
19822
19836
|
function bufferEqual(a, b) {
|
|
19823
19837
|
if (a.length !== b.length) return false;
|
|
19824
|
-
if (crypto$
|
|
19838
|
+
if (crypto$2.timingSafeEqual) return crypto$2.timingSafeEqual(a, b);
|
|
19825
19839
|
for (var i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
19826
19840
|
return true;
|
|
19827
19841
|
}
|
|
19828
19842
|
function timeSafeCompare(a, b) {
|
|
19829
19843
|
var sa = String(a);
|
|
19830
19844
|
var sb = String(b);
|
|
19831
|
-
var key = crypto$
|
|
19832
|
-
var ah = crypto$
|
|
19833
|
-
var bh = crypto$
|
|
19845
|
+
var key = crypto$2.pseudoRandomBytes(32);
|
|
19846
|
+
var ah = crypto$2.createHmac("sha256", key).update(sa).digest();
|
|
19847
|
+
var bh = crypto$2.createHmac("sha256", key).update(sb).digest();
|
|
19834
19848
|
return bufferEqual(ah, bh) && a === b;
|
|
19835
19849
|
}
|
|
19836
19850
|
module.exports = timeSafeCompare;
|
|
@@ -19840,14 +19854,14 @@ var require_lib = __commonJS({ "../../node_modules/tsscmp/lib/index.js"(exports,
|
|
|
19840
19854
|
//#region ../../node_modules/keygrip/index.js
|
|
19841
19855
|
var require_keygrip = __commonJS({ "../../node_modules/keygrip/index.js"(exports, module) {
|
|
19842
19856
|
var compare = require_lib();
|
|
19843
|
-
var crypto = __require("crypto");
|
|
19857
|
+
var crypto$1 = __require("crypto");
|
|
19844
19858
|
function Keygrip$1(keys$1, algorithm, encoding) {
|
|
19845
19859
|
if (!algorithm) algorithm = "sha1";
|
|
19846
19860
|
if (!encoding) encoding = "base64";
|
|
19847
19861
|
if (!(this instanceof Keygrip$1)) return new Keygrip$1(keys$1, algorithm, encoding);
|
|
19848
19862
|
if (!keys$1 || !(0 in keys$1)) throw new Error("Keys must be provided.");
|
|
19849
19863
|
function sign(data, key) {
|
|
19850
|
-
return crypto.createHmac(algorithm, key).update(data).digest(encoding).replace(/\/|\+|=/g, function(x) {
|
|
19864
|
+
return crypto$1.createHmac(algorithm, key).update(data).digest(encoding).replace(/\/|\+|=/g, function(x) {
|
|
19851
19865
|
return {
|
|
19852
19866
|
"/": "_",
|
|
19853
19867
|
"+": "-",
|
|
@@ -20389,10 +20403,14 @@ var require_application = __commonJS({ "../../node_modules/koa/lib/application.j
|
|
|
20389
20403
|
}
|
|
20390
20404
|
if (Buffer.isBuffer(body)) return res.end(body);
|
|
20391
20405
|
if (typeof body === "string") return res.end(body);
|
|
20392
|
-
|
|
20393
|
-
if (body instanceof
|
|
20394
|
-
if (body instanceof
|
|
20395
|
-
if (
|
|
20406
|
+
let stream = null;
|
|
20407
|
+
if (body instanceof Blob) stream = Stream.Readable.from(body.stream());
|
|
20408
|
+
else if (body instanceof ReadableStream) stream = Stream.Readable.from(body);
|
|
20409
|
+
else if (body instanceof Response) stream = Stream.Readable.from(body?.body || "");
|
|
20410
|
+
else if (isStream(body)) stream = body;
|
|
20411
|
+
if (stream) return Stream.pipeline(stream, res, (err) => {
|
|
20412
|
+
if (err && ctx.app.listenerCount("error")) ctx.onerror(err);
|
|
20413
|
+
});
|
|
20396
20414
|
body = JSON.stringify(body);
|
|
20397
20415
|
if (!res.headersSent) ctx.length = Buffer.byteLength(body);
|
|
20398
20416
|
res.end(body);
|
|
@@ -20769,6 +20787,21 @@ Object.defineProperty(Emittery, "listenerRemoved", {
|
|
|
20769
20787
|
configurable: false
|
|
20770
20788
|
});
|
|
20771
20789
|
|
|
20790
|
+
//#endregion
|
|
20791
|
+
//#region src/types.ts
|
|
20792
|
+
let MessageType = /* @__PURE__ */ function(MessageType$2) {
|
|
20793
|
+
MessageType$2["System"] = "system";
|
|
20794
|
+
MessageType$2["JoinGroup"] = "joinGroup";
|
|
20795
|
+
MessageType$2["SendToGroup"] = "sendToGroup";
|
|
20796
|
+
return MessageType$2;
|
|
20797
|
+
}({});
|
|
20798
|
+
let MessageDataType = /* @__PURE__ */ function(MessageDataType$2) {
|
|
20799
|
+
MessageDataType$2["Init"] = "init";
|
|
20800
|
+
MessageDataType$2["Sync"] = "sync";
|
|
20801
|
+
MessageDataType$2["Awareness"] = "awareness";
|
|
20802
|
+
return MessageDataType$2;
|
|
20803
|
+
}({});
|
|
20804
|
+
|
|
20772
20805
|
//#endregion
|
|
20773
20806
|
//#region src/yjs.ts
|
|
20774
20807
|
var yjs_default = Y$1;
|
|
@@ -22809,61 +22842,74 @@ const expirationTimeInMinutes = 60;
|
|
|
22809
22842
|
const messageSync = 0;
|
|
22810
22843
|
const messageAwareness = 1;
|
|
22811
22844
|
const AzureWebPubSubJsonProtocol = "json.webpubsub.azure.v1";
|
|
22812
|
-
let MessageType = /* @__PURE__ */ function(MessageType$
|
|
22813
|
-
MessageType$
|
|
22814
|
-
MessageType$
|
|
22815
|
-
MessageType$
|
|
22816
|
-
return MessageType$
|
|
22845
|
+
let MessageType$1 = /* @__PURE__ */ function(MessageType$2) {
|
|
22846
|
+
MessageType$2["System"] = "system";
|
|
22847
|
+
MessageType$2["JoinGroup"] = "joinGroup";
|
|
22848
|
+
MessageType$2["SendToGroup"] = "sendToGroup";
|
|
22849
|
+
return MessageType$2;
|
|
22817
22850
|
}({});
|
|
22818
|
-
let MessageDataType = /* @__PURE__ */ function(MessageDataType$
|
|
22819
|
-
MessageDataType$
|
|
22820
|
-
MessageDataType$
|
|
22821
|
-
MessageDataType$
|
|
22822
|
-
return MessageDataType$
|
|
22851
|
+
let MessageDataType$1 = /* @__PURE__ */ function(MessageDataType$2) {
|
|
22852
|
+
MessageDataType$2["Init"] = "init";
|
|
22853
|
+
MessageDataType$2["Sync"] = "sync";
|
|
22854
|
+
MessageDataType$2["Awareness"] = "awareness";
|
|
22855
|
+
return MessageDataType$2;
|
|
22823
22856
|
}({});
|
|
22824
22857
|
const HostUserId = "host";
|
|
22825
22858
|
var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
22826
|
-
|
|
22859
|
+
_reconnectAttempts = 0;
|
|
22860
|
+
_forceClose = false;
|
|
22861
|
+
constructor(server, syncHandler, client, topic, doc) {
|
|
22827
22862
|
this.server = server;
|
|
22863
|
+
this.syncHandler = syncHandler;
|
|
22828
22864
|
this.doc = doc;
|
|
22829
22865
|
this.topic = topic;
|
|
22830
22866
|
this.topicAwarenessChannel = `${topic}-awareness`;
|
|
22831
22867
|
this._client = client;
|
|
22832
22868
|
this._conn = null;
|
|
22833
22869
|
this._awareness = new Awareness(this.doc);
|
|
22834
|
-
this.
|
|
22835
|
-
|
|
22836
|
-
|
|
22837
|
-
|
|
22838
|
-
|
|
22839
|
-
|
|
22840
|
-
|
|
22841
|
-
|
|
22870
|
+
this._awarenessUpdateHandler = ({ added, updated, removed }, origin) => {
|
|
22871
|
+
try {
|
|
22872
|
+
const changedClients = added.concat(added, updated, removed);
|
|
22873
|
+
const encoder = createEncoder();
|
|
22874
|
+
writeVarUint(encoder, messageAwareness);
|
|
22875
|
+
const payload = encodeAwarenessUpdate(this._awareness, changedClients);
|
|
22876
|
+
writeVarUint8Array(encoder, payload);
|
|
22877
|
+
const u8 = toUint8Array(encoder);
|
|
22878
|
+
this.broadcast(this.topic, origin, u8);
|
|
22879
|
+
} catch (err) {
|
|
22880
|
+
console.error("Error in awareness update handler:", err);
|
|
22881
|
+
}
|
|
22842
22882
|
};
|
|
22843
|
-
this._awareness.on("update",
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
22883
|
+
this._awareness.on("update", this._awarenessUpdateHandler);
|
|
22884
|
+
this._updateHandler = (update, origin) => {
|
|
22885
|
+
try {
|
|
22886
|
+
const encoder = createEncoder();
|
|
22887
|
+
writeVarUint(encoder, messageSync);
|
|
22888
|
+
writeUpdate(encoder, update);
|
|
22889
|
+
const u8 = toUint8Array(encoder);
|
|
22890
|
+
this.broadcast(this.topic, origin, u8);
|
|
22891
|
+
if (!this.syncHandler.isPersistingOnInterval()) this.syncHandler.persistRoomTask(this.topic);
|
|
22892
|
+
} catch (err) {
|
|
22893
|
+
console.error("Error in document update handler:", err);
|
|
22894
|
+
}
|
|
22850
22895
|
};
|
|
22851
|
-
this.doc.on("update",
|
|
22896
|
+
this.doc.on("update", this._updateHandler);
|
|
22852
22897
|
}
|
|
22853
22898
|
get awareness() {
|
|
22854
22899
|
return this._awareness;
|
|
22855
22900
|
}
|
|
22856
22901
|
sendInitAwarenessInfo(origin) {
|
|
22902
|
+
if (!this._awareness) return;
|
|
22857
22903
|
const encoderAwarenessState = createEncoder();
|
|
22858
22904
|
writeVarUint(encoderAwarenessState, messageAwareness);
|
|
22859
22905
|
writeVarUint8Array(encoderAwarenessState, encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
22860
22906
|
const u8 = toUint8Array(encoderAwarenessState);
|
|
22861
22907
|
this.broadcast(this.topic, origin, u8);
|
|
22862
22908
|
}
|
|
22863
|
-
async createWebSocket(
|
|
22909
|
+
async createWebSocket() {
|
|
22864
22910
|
const group = this.topic;
|
|
22865
22911
|
const { url: url$1 } = await this.negotiate(this.topic);
|
|
22866
|
-
|
|
22912
|
+
this._reconnectAttempts++;
|
|
22867
22913
|
return new Promise((resolve) => {
|
|
22868
22914
|
const ws = new WebSocket(url$1, AzureWebPubSubJsonProtocol);
|
|
22869
22915
|
ws.addEventListener("open", (event) => {
|
|
@@ -22872,7 +22918,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22872
22918
|
event
|
|
22873
22919
|
});
|
|
22874
22920
|
ws.send(JSON.stringify({
|
|
22875
|
-
type: MessageType.JoinGroup,
|
|
22921
|
+
type: MessageType$1.JoinGroup,
|
|
22876
22922
|
group: `${group}.host`
|
|
22877
22923
|
}));
|
|
22878
22924
|
this.server.emitEvent("onWsJoinGroup", { group: `${group}.host` });
|
|
@@ -22886,15 +22932,15 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22886
22932
|
});
|
|
22887
22933
|
const event = JSON.parse(e.data.toString());
|
|
22888
22934
|
if (event.type === "message" && event.from === "group") switch (event.data.t) {
|
|
22889
|
-
case MessageDataType.Init:
|
|
22935
|
+
case MessageDataType$1.Init:
|
|
22890
22936
|
this.onClientInit(group, event.data);
|
|
22891
22937
|
this.onClientSync(group, event.data);
|
|
22892
22938
|
this.sendInitAwarenessInfo(event.data.f);
|
|
22893
22939
|
return;
|
|
22894
|
-
case MessageDataType.Sync:
|
|
22940
|
+
case MessageDataType$1.Sync:
|
|
22895
22941
|
this.onClientSync(group, event.data);
|
|
22896
22942
|
return;
|
|
22897
|
-
case MessageDataType.Awareness:
|
|
22943
|
+
case MessageDataType$1.Awareness:
|
|
22898
22944
|
this.onAwareness(group, event.data);
|
|
22899
22945
|
return;
|
|
22900
22946
|
}
|
|
@@ -22904,9 +22950,12 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22904
22950
|
group: `${group}.host`,
|
|
22905
22951
|
event: e
|
|
22906
22952
|
});
|
|
22907
|
-
if (
|
|
22908
|
-
|
|
22909
|
-
this.
|
|
22953
|
+
if (this._forceClose) return;
|
|
22954
|
+
else {
|
|
22955
|
+
const timeout = 1e3 * Math.pow(1.5, this._reconnectAttempts);
|
|
22956
|
+
setTimeout(() => {
|
|
22957
|
+
this.createWebSocket();
|
|
22958
|
+
}, timeout);
|
|
22910
22959
|
}
|
|
22911
22960
|
});
|
|
22912
22961
|
ws.addEventListener("error", (error) => {
|
|
@@ -22915,7 +22964,6 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22915
22964
|
error
|
|
22916
22965
|
});
|
|
22917
22966
|
if (ws.readyState === WebSocket.OPEN) ws.close();
|
|
22918
|
-
this.createWebSocket(2e4);
|
|
22919
22967
|
});
|
|
22920
22968
|
setTimeout(() => {
|
|
22921
22969
|
if (ws.readyState === WebSocket.OPEN) {
|
|
@@ -22930,6 +22978,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22930
22978
|
await this.createWebSocket();
|
|
22931
22979
|
}
|
|
22932
22980
|
async stop() {
|
|
22981
|
+
this._forceClose = true;
|
|
22933
22982
|
if (this._conn?.readyState === WebSocket.OPEN) {
|
|
22934
22983
|
this._conn?.close();
|
|
22935
22984
|
this._conn = null;
|
|
@@ -22948,30 +22997,38 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
22948
22997
|
return true;
|
|
22949
22998
|
}
|
|
22950
22999
|
broadcast(group, from$1, u8) {
|
|
22951
|
-
|
|
22952
|
-
|
|
22953
|
-
|
|
22954
|
-
|
|
22955
|
-
|
|
22956
|
-
|
|
22957
|
-
|
|
22958
|
-
|
|
22959
|
-
|
|
22960
|
-
|
|
22961
|
-
|
|
23000
|
+
try {
|
|
23001
|
+
const payload = JSON.stringify({
|
|
23002
|
+
type: MessageType$1.SendToGroup,
|
|
23003
|
+
group,
|
|
23004
|
+
noEcho: true,
|
|
23005
|
+
data: {
|
|
23006
|
+
f: from$1,
|
|
23007
|
+
c: Buffer.from(u8).toString("base64")
|
|
23008
|
+
}
|
|
23009
|
+
});
|
|
23010
|
+
if (!this.safeSend(payload)) return;
|
|
23011
|
+
this._conn?.send?.(payload);
|
|
23012
|
+
} catch (ex) {
|
|
23013
|
+
console.error("Error broadcasting message:", ex);
|
|
23014
|
+
}
|
|
22962
23015
|
}
|
|
22963
23016
|
send(group, to, u8) {
|
|
22964
|
-
|
|
22965
|
-
|
|
22966
|
-
|
|
22967
|
-
|
|
22968
|
-
|
|
22969
|
-
|
|
22970
|
-
|
|
22971
|
-
|
|
22972
|
-
|
|
22973
|
-
|
|
22974
|
-
|
|
23017
|
+
try {
|
|
23018
|
+
const payload = JSON.stringify({
|
|
23019
|
+
type: MessageType$1.SendToGroup,
|
|
23020
|
+
group,
|
|
23021
|
+
noEcho: true,
|
|
23022
|
+
data: {
|
|
23023
|
+
t: to,
|
|
23024
|
+
c: Buffer.from(u8).toString("base64")
|
|
23025
|
+
}
|
|
23026
|
+
});
|
|
23027
|
+
if (!this.safeSend(payload)) return;
|
|
23028
|
+
this._conn?.send?.(payload);
|
|
23029
|
+
} catch (ex) {
|
|
23030
|
+
console.error("Error sending message:", ex);
|
|
23031
|
+
}
|
|
22975
23032
|
}
|
|
22976
23033
|
onClientInit(group, data) {
|
|
22977
23034
|
const encoder = createEncoder();
|
|
@@ -23003,6 +23060,7 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
23003
23060
|
const decoder = createDecoder(buf);
|
|
23004
23061
|
readVarUint(decoder);
|
|
23005
23062
|
const update = readVarUint8Array(decoder);
|
|
23063
|
+
if (!this._awareness) return;
|
|
23006
23064
|
applyAwarenessUpdate(this._awareness, update, void 0);
|
|
23007
23065
|
} catch (err) {
|
|
23008
23066
|
this.doc.emit("error", [err]);
|
|
@@ -23023,12 +23081,27 @@ var WeaveStoreAzureWebPubSubSyncHost = class {
|
|
|
23023
23081
|
}
|
|
23024
23082
|
};
|
|
23025
23083
|
|
|
23084
|
+
//#endregion
|
|
23085
|
+
//#region src/server/utils.ts
|
|
23086
|
+
function getStateAsJson(actualState) {
|
|
23087
|
+
const document = new yjs_default.Doc();
|
|
23088
|
+
yjs_default.applyUpdate(document, actualState);
|
|
23089
|
+
const actualStateString = JSON.stringify(document.getMap("weave").toJSON());
|
|
23090
|
+
const actualStateJson = JSON.parse(actualStateString);
|
|
23091
|
+
return actualStateJson;
|
|
23092
|
+
}
|
|
23093
|
+
function hashJson(obj) {
|
|
23094
|
+
const jsonString = JSON.stringify(obj);
|
|
23095
|
+
return crypto.createHash("sha256").update(jsonString).digest("hex");
|
|
23096
|
+
}
|
|
23097
|
+
|
|
23026
23098
|
//#endregion
|
|
23027
23099
|
//#region src/server/azure-web-pubsub-sync-handler.ts
|
|
23028
23100
|
var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
|
|
23029
23101
|
_rooms = new Map();
|
|
23030
23102
|
_roomsSyncHost = new Map();
|
|
23031
23103
|
_store_persistence = new Map();
|
|
23104
|
+
roomsLastState = new Map();
|
|
23032
23105
|
constructor(hub, server, client, initialState, syncHandlerOptions, eventHandlerOptions) {
|
|
23033
23106
|
super(hub, {
|
|
23034
23107
|
...eventHandlerOptions,
|
|
@@ -23053,6 +23126,7 @@ var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
|
|
|
23053
23126
|
this.server = server;
|
|
23054
23127
|
this.initialState = initialState;
|
|
23055
23128
|
this._client = client;
|
|
23129
|
+
if (this.isPersistingOnInterval()) console.warn(`Room persistence defined via interval, be aware that this can lead to data loss. Consider persisting on document updates instead.`);
|
|
23056
23130
|
}
|
|
23057
23131
|
getNewYDoc() {
|
|
23058
23132
|
return new yjs_default.Doc();
|
|
@@ -23064,29 +23138,44 @@ var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
|
|
|
23064
23138
|
if (this.server?.fetchRoom) documentData = await this.server.fetchRoom(roomId);
|
|
23065
23139
|
if (documentData) yjs_default.applyUpdate(doc, documentData);
|
|
23066
23140
|
else this.initialState(doc);
|
|
23067
|
-
this._roomsSyncHost.set(roomId, new WeaveStoreAzureWebPubSubSyncHost(this.server, this._client, roomId, doc));
|
|
23141
|
+
this._roomsSyncHost.set(roomId, new WeaveStoreAzureWebPubSubSyncHost(this.server, this, this._client, roomId, doc));
|
|
23068
23142
|
const connection = this._roomsSyncHost.get(roomId);
|
|
23069
23143
|
await connection.start();
|
|
23070
|
-
|
|
23144
|
+
if (this.isPersistingOnInterval()) this.setupRoomInstancePersistence(roomId);
|
|
23145
|
+
}
|
|
23146
|
+
isPersistingOnInterval() {
|
|
23147
|
+
return this.syncOptions?.persistIntervalMs !== void 0;
|
|
23148
|
+
}
|
|
23149
|
+
async setupRoomInstancePersistence(roomId) {
|
|
23150
|
+
if (!this._store_persistence.has(roomId)) {
|
|
23151
|
+
const intervalId = setInterval(async () => {
|
|
23152
|
+
await this.persistRoomTask(roomId);
|
|
23153
|
+
}, this.syncOptions?.persistIntervalMs ?? 5e3);
|
|
23154
|
+
this._store_persistence.set(roomId, intervalId);
|
|
23155
|
+
}
|
|
23071
23156
|
}
|
|
23072
23157
|
async persistRoomTask(roomId) {
|
|
23073
23158
|
try {
|
|
23074
23159
|
const doc = this._rooms.get(roomId);
|
|
23075
23160
|
if (!doc) return;
|
|
23076
23161
|
const actualState = yjs_default.encodeStateAsUpdate(doc);
|
|
23162
|
+
if (!this.isPersistingOnInterval()) {
|
|
23163
|
+
const savedRoomData = this.roomsLastState.get(roomId);
|
|
23164
|
+
if (savedRoomData) {
|
|
23165
|
+
const savedStateJson = getStateAsJson(savedRoomData);
|
|
23166
|
+
const savedHash = hashJson(savedStateJson);
|
|
23167
|
+
const actualStateJson = getStateAsJson(actualState);
|
|
23168
|
+
const actualHash = hashJson(actualStateJson);
|
|
23169
|
+
const same = savedHash === actualHash;
|
|
23170
|
+
if (same) return;
|
|
23171
|
+
this.roomsLastState.set(roomId, actualState);
|
|
23172
|
+
}
|
|
23173
|
+
}
|
|
23077
23174
|
if (this.server?.persistRoom) await this.server.persistRoom(roomId, actualState);
|
|
23078
23175
|
} catch (ex) {
|
|
23079
23176
|
console.error(ex);
|
|
23080
23177
|
}
|
|
23081
23178
|
}
|
|
23082
|
-
async setupRoomInstancePersistence(roomId) {
|
|
23083
|
-
if (!this._store_persistence.has(roomId)) {
|
|
23084
|
-
const intervalId = setInterval(async () => {
|
|
23085
|
-
await this.persistRoomTask(roomId);
|
|
23086
|
-
}, this.syncOptions?.persistIntervalMs ?? 5e3);
|
|
23087
|
-
this._store_persistence.set(roomId, intervalId);
|
|
23088
|
-
}
|
|
23089
|
-
}
|
|
23090
23179
|
async handleConnectionDisconnection(connectionId) {
|
|
23091
23180
|
const connectionRoom = await this.syncOptions?.getConnectionRoom?.(connectionId);
|
|
23092
23181
|
if (connectionRoom) await this.syncOptions?.removeConnection?.(connectionId);
|
|
@@ -23094,10 +23183,13 @@ var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
|
|
|
23094
23183
|
if (connectionRoom && roomConnections?.length === 0) await this.destroyRoomInstance(connectionRoom);
|
|
23095
23184
|
}
|
|
23096
23185
|
async destroyRoomInstance(roomId) {
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23186
|
+
if (this.isPersistingOnInterval()) {
|
|
23187
|
+
const intervalId = this._store_persistence.get(roomId);
|
|
23188
|
+
if (intervalId) clearInterval(intervalId);
|
|
23189
|
+
this._store_persistence.delete(roomId);
|
|
23190
|
+
}
|
|
23100
23191
|
await this.persistRoomTask(roomId);
|
|
23192
|
+
if (!this.isPersistingOnInterval()) this.roomsLastState.delete(roomId);
|
|
23101
23193
|
const syncHost = this._roomsSyncHost.get(roomId);
|
|
23102
23194
|
if (syncHost) {
|
|
23103
23195
|
await syncHost.stop();
|
|
@@ -23114,11 +23206,12 @@ var WeaveAzureWebPubsubSyncHandler = class extends WebPubSubEventHandler {
|
|
|
23114
23206
|
getRoomSyncHost(roomId) {
|
|
23115
23207
|
return this._roomsSyncHost.get(roomId);
|
|
23116
23208
|
}
|
|
23117
|
-
async clientConnect(roomId) {
|
|
23209
|
+
async clientConnect(roomId, connectionOptions) {
|
|
23118
23210
|
await this.getHostConnection(roomId);
|
|
23119
23211
|
const token = await this._client.getClientAccessToken({
|
|
23120
23212
|
groups: [roomId],
|
|
23121
|
-
roles: [`webpubsub.joinLeaveGroup.${roomId}`, `webpubsub.sendToGroup.${roomId}.host`]
|
|
23213
|
+
roles: [`webpubsub.joinLeaveGroup.${roomId}`, `webpubsub.sendToGroup.${roomId}.host`],
|
|
23214
|
+
...connectionOptions
|
|
23122
23215
|
});
|
|
23123
23216
|
const finalURL = `${token.url}&group=${roomId}`;
|
|
23124
23217
|
return finalURL;
|
|
@@ -23143,7 +23236,7 @@ var WeaveAzureWebPubsubServer = class extends Emittery {
|
|
|
23143
23236
|
credentials ??= new DefaultAzureCredential();
|
|
23144
23237
|
this.syncClient = new WebPubSubServiceClient(pubSubConfig.endpoint, credentials, pubSubConfig.hubName);
|
|
23145
23238
|
this.syncHandler = new WeaveAzureWebPubsubSyncHandler(pubSubConfig.hubName, this, this.syncClient, initialState, {
|
|
23146
|
-
persistIntervalMs: pubSubConfig.persistIntervalMs,
|
|
23239
|
+
...pubSubConfig.persistIntervalMs && { persistIntervalMs: pubSubConfig.persistIntervalMs },
|
|
23147
23240
|
...pubSubConfig.connectionHandlers
|
|
23148
23241
|
}, eventsHandlerConfig);
|
|
23149
23242
|
}
|
|
@@ -23165,14 +23258,20 @@ var WeaveAzureWebPubsubServer = class extends Emittery {
|
|
|
23165
23258
|
removeEventListener(event, callback) {
|
|
23166
23259
|
this.off(event, callback);
|
|
23167
23260
|
}
|
|
23168
|
-
async clientConnect(roomId) {
|
|
23169
|
-
return await this.syncHandler.clientConnect(roomId);
|
|
23261
|
+
async clientConnect(roomId, connectionOptions) {
|
|
23262
|
+
return await this.syncHandler.clientConnect(roomId, connectionOptions);
|
|
23170
23263
|
}
|
|
23171
23264
|
};
|
|
23172
23265
|
|
|
23173
23266
|
//#endregion
|
|
23174
23267
|
//#region src/constants.ts
|
|
23175
23268
|
const WEAVE_STORE_AZURE_WEB_PUBSUB = "store-azure-web-pubsub";
|
|
23269
|
+
const WEAVE_STORE_AZURE_WEB_PUBSUB_CONNECTION_STATUS = {
|
|
23270
|
+
["CONNECTING"]: "connecting",
|
|
23271
|
+
["CONNECTED"]: "connected",
|
|
23272
|
+
["DISCONNECTED"]: "disconnected",
|
|
23273
|
+
["ERROR"]: "error"
|
|
23274
|
+
};
|
|
23176
23275
|
const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
|
|
23177
23276
|
["PUB"]: "pub",
|
|
23178
23277
|
["SUB"]: "sub"
|
|
@@ -23180,4 +23279,4 @@ const WEAVE_STORE_HORIZONTAL_SYNC_HANDLER_CLIENT_TYPE = {
|
|
|
23180
23279
|
const WEAVE_STORE_AZURE_WEB_PUBSUB_DEFAULT_CONFIG = { resyncIntervalMs: 15e3 };
|
|
23181
23280
|
|
|
23182
23281
|
//#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 };
|
|
23282
|
+
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
|
|
3
|
+
"version": "2.1.0",
|
|
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
|
|
61
|
-
"@inditextech/weave-sdk": "2.0
|
|
60
|
+
"@inditextech/weave-types": "2.1.0",
|
|
61
|
+
"@inditextech/weave-sdk": "2.1.0",
|
|
62
62
|
"@syncedstore/core": "0.6.0",
|
|
63
63
|
"buffer": "6.0.3",
|
|
64
64
|
"reconnecting-websocket": "4.4.0",
|