@wix/realtime 1.0.46 → 1.0.47
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/cjs/build/index.d.ts +2 -2
- package/cjs/build/publisher/publisher.public.d.ts +2 -2
- package/cjs/build/subscriber/errors.d.ts +7 -4
- package/cjs/build/subscriber/errors.js +24 -1
- package/cjs/build/subscriber/subscriber.public.d.ts +2 -2
- package/cjs/build/subscriber/subscriber.public.js +84 -36
- package/cjs/build/subscriber/subscription-manager.d.ts +9 -7
- package/cjs/build/subscriber/subscription-manager.js +21 -18
- package/cjs/build/types.d.ts +1 -1
- package/dist/statics/docs-ts-model.json +269 -107
- package/es/build/index.d.ts +2 -2
- package/es/build/publisher/publisher.public.d.ts +2 -2
- package/es/build/subscriber/errors.d.ts +7 -4
- package/es/build/subscriber/errors.js +21 -1
- package/es/build/subscriber/subscriber.public.d.ts +2 -2
- package/es/build/subscriber/subscriber.public.js +85 -37
- package/es/build/subscriber/subscription-manager.d.ts +9 -7
- package/es/build/subscriber/subscription-manager.js +21 -18
- package/es/build/types.d.ts +1 -1
- package/package.json +4 -4
package/es/build/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * as site from '@wix/sdk_realtime_site';
|
|
2
2
|
export * as publisher from './publisher/publisher.context.js';
|
|
3
3
|
export * as subscriber from './subscriber/subscriber.context.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { PublishChannel, SubscribeChannel, Message, MessageHandler, Publisher, SubscriptionErrorHandler, SubscriptionHandler, SubscriptionOptions, UnsubscribeOptions } from './types.js';
|
|
5
5
|
import { RealtimeError, RealtimeErrorCode } from './types.js';
|
|
6
|
-
export type {
|
|
6
|
+
export type { PublishChannel, SubscribeChannel, Message, MessageHandler, Publisher, SubscriptionErrorHandler, SubscriptionHandler, SubscriptionOptions, UnsubscribeOptions, };
|
|
7
7
|
export { RealtimeError, RealtimeErrorCode };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PublishChannel } from '@wix/realtime-common/types';
|
|
2
2
|
import type { HttpClient } from '@wix/sdk-types';
|
|
3
3
|
interface PublishSignature {
|
|
4
|
-
(channel:
|
|
4
|
+
(channel: PublishChannel, payload: Record<string, any>): Promise<void>;
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Publish a message to a channel.
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import { RealtimeError, type Channel } from '@wix/realtime-common/types';
|
|
1
|
+
import { RealtimeError, type PublishChannel, type Channel, type SubscribeChannel } from '@wix/realtime-common/types';
|
|
2
2
|
export declare function missingChannelOrSubscriptionId(): RealtimeError;
|
|
3
3
|
export declare function channelMismatch(): RealtimeError;
|
|
4
|
+
export declare function channelAppIdMismatch(passedAppId: string, subscribedAppId: string): RealtimeError;
|
|
5
|
+
export declare function unsubscribeRequiresAppId(channel: PublishChannel, crossAppIds: string[]): RealtimeError;
|
|
6
|
+
export declare function unknownChannelAppId(channel: SubscribeChannel, existingAppIds: string[]): RealtimeError;
|
|
4
7
|
export declare function invalidChannel(channel: Channel): RealtimeError;
|
|
5
8
|
export declare function validateChannel(channel: Channel): void;
|
|
6
9
|
export declare function disconnectedError(recoverable?: boolean, message?: string): RealtimeError;
|
|
7
10
|
export declare function connectError(recoverable?: boolean, message?: string): RealtimeError;
|
|
8
|
-
export declare function subscribeFailed(channel:
|
|
11
|
+
export declare function subscribeFailed(channel: SubscribeChannel, payload?: {
|
|
9
12
|
status?: number;
|
|
10
13
|
message?: string;
|
|
11
14
|
}): RealtimeError;
|
|
12
|
-
export declare function resubscribeFailed(channel:
|
|
15
|
+
export declare function resubscribeFailed(channel: SubscribeChannel, payload?: {
|
|
13
16
|
status?: number;
|
|
14
17
|
message?: string;
|
|
15
18
|
}): RealtimeError;
|
|
16
|
-
export declare function subscribeError(error: unknown, channel:
|
|
19
|
+
export declare function subscribeError(error: unknown, channel: SubscribeChannel): RealtimeError;
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
import { RealtimeError, RealtimeErrorCode, } from '@wix/realtime-common/types';
|
|
2
|
+
import { CHANNEL_NAME_MAX_LENGTH, CHANNEL_NAME_PATTERN, } from '@wix/realtime-common';
|
|
2
3
|
export function missingChannelOrSubscriptionId() {
|
|
3
4
|
return new RealtimeError(RealtimeErrorCode.BadInput, 'channel or subscriptionId is required');
|
|
4
5
|
}
|
|
5
6
|
export function channelMismatch() {
|
|
6
7
|
return new RealtimeError(RealtimeErrorCode.BadInput, 'channel does not match subscriptionId');
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
+
export function channelAppIdMismatch(passedAppId, subscribedAppId) {
|
|
10
|
+
return new RealtimeError(RealtimeErrorCode.BadInput, `channel.appId "${passedAppId}" does not match subscription (subscribed with appId "${subscribedAppId}")`);
|
|
11
|
+
}
|
|
12
|
+
export function unsubscribeRequiresAppId(channel, crossAppIds) {
|
|
13
|
+
const target = channel.resourceId
|
|
14
|
+
? `"${channel.name}" / "${channel.resourceId}"`
|
|
15
|
+
: `"${channel.name}"`;
|
|
16
|
+
return new RealtimeError(RealtimeErrorCode.BadInput, `Unsubscribe on ${target} requires channel.appId because the matching subscription(s) were opened cross-app to ${crossAppIds
|
|
17
|
+
.map((id) => `"${id}"`)
|
|
18
|
+
.join(', ')}. Pass channel.appId to scope the removal.`);
|
|
19
|
+
}
|
|
20
|
+
export function unknownChannelAppId(channel, existingAppIds) {
|
|
21
|
+
const target = channel.resourceId
|
|
22
|
+
? `"${channel.name}" / "${channel.resourceId}"`
|
|
23
|
+
: `"${channel.name}"`;
|
|
24
|
+
const knownAppIds = existingAppIds.length
|
|
25
|
+
? existingAppIds.map((id) => `"${id}"`).join(', ')
|
|
26
|
+
: '(none)';
|
|
27
|
+
return new RealtimeError(RealtimeErrorCode.BadInput, `No subscription on ${target} matches channel.appId "${channel.appId}". Existing subscriptions on this channel are scoped to ${knownAppIds}.`);
|
|
28
|
+
}
|
|
9
29
|
export function invalidChannel(channel) {
|
|
10
30
|
const { name, resourceId } = channel;
|
|
11
31
|
const reasons = [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SubscribeChannel, type MessageHandler, type SubscriptionOptions, type UnsubscribeOptions } from '@wix/realtime-common/types';
|
|
2
2
|
import type { HttpClient } from '@wix/sdk-types';
|
|
3
3
|
interface SubscribeSignature {
|
|
4
|
-
(channel:
|
|
4
|
+
(channel: SubscribeChannel, messageHandler: MessageHandler, options?: SubscriptionOptions): string;
|
|
5
5
|
}
|
|
6
6
|
export declare function subscribe(httpClient: HttpClient): SubscribeSignature;
|
|
7
7
|
interface UnsubscribeSignature {
|
|
@@ -3,8 +3,11 @@ import { DUPLEXER_EVENTS, MESSAGE_EVENT_NAME, getAppInfoFromAuthToken, tokenToAp
|
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
4
|
import { resolveDuplexerChannelName } from '../channel-utils.js';
|
|
5
5
|
import { DUPLEXER_HOST_URL } from '../constants.js';
|
|
6
|
-
import { missingChannelOrSubscriptionId, channelMismatch, disconnectedError, connectError, subscribeFailed, resubscribeFailed, subscribeError, validateChannel, } from './errors.js';
|
|
6
|
+
import { missingChannelOrSubscriptionId, channelMismatch, channelAppIdMismatch, unsubscribeRequiresAppId, unknownChannelAppId, disconnectedError, connectError, subscribeFailed, resubscribeFailed, subscribeError, validateChannel, } from './errors.js';
|
|
7
7
|
import { SubscriptionManager } from './subscription-manager.js';
|
|
8
|
+
function socketKey(socketAppId, siteId) {
|
|
9
|
+
return `${socketAppId}:${siteId}`;
|
|
10
|
+
}
|
|
8
11
|
const instanceConnections = new Map();
|
|
9
12
|
const subscriptionManager = new SubscriptionManager();
|
|
10
13
|
export function subscribe(httpClient) {
|
|
@@ -14,6 +17,8 @@ export function subscribe(httpClient) {
|
|
|
14
17
|
subscriptionManager.set(subscriptionId, {
|
|
15
18
|
channelName: channel.name,
|
|
16
19
|
channelResourceId: channel.resourceId,
|
|
20
|
+
maybeCrossAppId: channel.appId,
|
|
21
|
+
socketAppId: channel.appId,
|
|
17
22
|
removeListeners: () => { },
|
|
18
23
|
onSubscribed: options?.onSubscribed,
|
|
19
24
|
onSubscriptionError: options?.onSubscriptionError,
|
|
@@ -50,57 +55,92 @@ function unsubscribeById(subscriptionId, channel) {
|
|
|
50
55
|
if (!subscription) {
|
|
51
56
|
return;
|
|
52
57
|
}
|
|
53
|
-
if (channel
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
if (channel) {
|
|
59
|
+
const channelNameMismatch = channel.name !== undefined && channel.name !== subscription.channelName;
|
|
60
|
+
const channelResourceIdMismatch = channel.resourceId !== undefined &&
|
|
61
|
+
channel.resourceId !== subscription.channelResourceId;
|
|
62
|
+
if (channelNameMismatch || channelResourceIdMismatch) {
|
|
63
|
+
throw channelMismatch();
|
|
64
|
+
}
|
|
65
|
+
const appIdMismatch = channel.appId !== undefined &&
|
|
66
|
+
subscription.socketAppId !== undefined &&
|
|
67
|
+
channel.appId !== subscription.socketAppId;
|
|
68
|
+
if (appIdMismatch) {
|
|
69
|
+
throw channelAppIdMismatch(channel.appId, subscription.socketAppId);
|
|
70
|
+
}
|
|
57
71
|
}
|
|
58
72
|
subscription.removeListeners();
|
|
59
|
-
const { channelName, channelResourceId,
|
|
60
|
-
|
|
61
|
-
// cancelled so the in-flight setupSubscription knows to bail out.
|
|
62
|
-
if (!channelEmitter || !instanceId) {
|
|
73
|
+
const { channelName, channelResourceId, socketAppId, siteId, channelEmitter, } = subscription;
|
|
74
|
+
if (!channelEmitter || !socketAppId || !siteId) {
|
|
63
75
|
subscription.cancelled = true;
|
|
64
76
|
subscriptionManager.delete(subscriptionId);
|
|
65
|
-
if (
|
|
66
|
-
cleanupConnectionIfIdle(
|
|
77
|
+
if (socketAppId && siteId) {
|
|
78
|
+
cleanupConnectionIfIdle(socketAppId, siteId);
|
|
67
79
|
}
|
|
68
80
|
return;
|
|
69
81
|
}
|
|
70
82
|
// If no other subscriptions remain on this channel, fire-and-forget
|
|
71
83
|
// the duplexer unsubscribe.
|
|
72
|
-
const hasOtherSubscriptionsOnChannel = subscriptionManager.deleteAndStillHasRemainingOnChannel(
|
|
84
|
+
const hasOtherSubscriptionsOnChannel = subscriptionManager.deleteAndStillHasRemainingOnChannel(socketAppId, siteId, subscriptionId, channelName, channelResourceId);
|
|
73
85
|
if (!hasOtherSubscriptionsOnChannel) {
|
|
74
|
-
const conn = instanceConnections.get(
|
|
86
|
+
const conn = instanceConnections.get(socketKey(socketAppId, siteId));
|
|
75
87
|
if (conn) {
|
|
76
88
|
conn.socket.unsubscribe(channelName, channelResourceId);
|
|
77
89
|
}
|
|
78
90
|
}
|
|
79
|
-
cleanupConnectionIfIdle(
|
|
91
|
+
cleanupConnectionIfIdle(socketAppId, siteId);
|
|
92
|
+
}
|
|
93
|
+
function distinctDefined(items, pickItemFunction) {
|
|
94
|
+
const out = new Set();
|
|
95
|
+
for (const item of items) {
|
|
96
|
+
const v = pickItemFunction(item);
|
|
97
|
+
if (v !== undefined)
|
|
98
|
+
out.add(v);
|
|
99
|
+
}
|
|
100
|
+
return [...out];
|
|
80
101
|
}
|
|
81
102
|
function unsubscribeByChannel(channel) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
103
|
+
const matches = subscriptionManager.findByChannel(channel.name, channel.resourceId);
|
|
104
|
+
if (matches.length === 0) {
|
|
105
|
+
return;
|
|
85
106
|
}
|
|
107
|
+
if (channel.appId === undefined) {
|
|
108
|
+
const sameAppMatches = matches.filter(([, sub]) => sub.maybeCrossAppId === undefined);
|
|
109
|
+
if (sameAppMatches.length === 0) {
|
|
110
|
+
const crossAppIds = distinctDefined(matches, ([, sub]) => sub.maybeCrossAppId);
|
|
111
|
+
throw unsubscribeRequiresAppId(channel, crossAppIds);
|
|
112
|
+
}
|
|
113
|
+
for (const [id] of sameAppMatches)
|
|
114
|
+
unsubscribeById(id);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// appId passed: scope to subs whose socket lives in that namespace.
|
|
118
|
+
const scoped = matches.filter(([, sub]) => sub.socketAppId === channel.appId);
|
|
119
|
+
if (scoped.length === 0) {
|
|
120
|
+
const existingAppIds = distinctDefined(matches, ([, sub]) => sub.socketAppId);
|
|
121
|
+
throw unknownChannelAppId(channel, existingAppIds);
|
|
122
|
+
}
|
|
123
|
+
for (const [id] of scoped)
|
|
124
|
+
unsubscribeById(id);
|
|
86
125
|
}
|
|
87
|
-
function closeConnection(
|
|
88
|
-
const
|
|
126
|
+
function closeConnection(socketAppId, siteId) {
|
|
127
|
+
const key = socketKey(socketAppId, siteId);
|
|
128
|
+
const conn = instanceConnections.get(key);
|
|
89
129
|
if (conn) {
|
|
90
130
|
conn.socket.removeAllListeners();
|
|
91
131
|
conn.socket.disconnect();
|
|
92
132
|
conn.duplexer.close();
|
|
93
|
-
instanceConnections.delete(
|
|
133
|
+
instanceConnections.delete(key);
|
|
94
134
|
}
|
|
95
135
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
closeConnection(instanceId);
|
|
136
|
+
function cleanupConnectionIfIdle(socketAppId, siteId) {
|
|
137
|
+
if (!subscriptionManager.hasSubscriptionsForSocket(socketAppId, siteId)) {
|
|
138
|
+
closeConnection(socketAppId, siteId);
|
|
100
139
|
}
|
|
101
140
|
}
|
|
102
|
-
function getOrCreateConnection(httpClient,
|
|
103
|
-
const
|
|
141
|
+
function getOrCreateConnection(httpClient, socketAppId, siteId) {
|
|
142
|
+
const key = socketKey(socketAppId, siteId);
|
|
143
|
+
const existing = instanceConnections.get(key);
|
|
104
144
|
if (existing) {
|
|
105
145
|
return existing;
|
|
106
146
|
}
|
|
@@ -110,10 +150,10 @@ function getOrCreateConnection(httpClient, appId, instanceId) {
|
|
|
110
150
|
},
|
|
111
151
|
});
|
|
112
152
|
const socket = duplexer.connect({
|
|
113
|
-
appDefId:
|
|
153
|
+
appDefId: socketAppId,
|
|
114
154
|
});
|
|
115
155
|
const notifySubscriptionError = (realtimeError) => {
|
|
116
|
-
for (const subId of subscriptionManager.
|
|
156
|
+
for (const subId of subscriptionManager.getSubscriptionIdsBySocket(socketAppId, siteId)) {
|
|
117
157
|
subscriptionManager
|
|
118
158
|
.get(subId)
|
|
119
159
|
?.onSubscriptionError?.(realtimeError, subId);
|
|
@@ -126,15 +166,21 @@ function getOrCreateConnection(httpClient, appId, instanceId) {
|
|
|
126
166
|
notifySubscriptionError(connectError(error?.recoverable, error?.message));
|
|
127
167
|
});
|
|
128
168
|
const connection = { duplexer, socket };
|
|
129
|
-
instanceConnections.set(
|
|
169
|
+
instanceConnections.set(key, connection);
|
|
130
170
|
return connection;
|
|
131
171
|
}
|
|
132
172
|
async function setupSubscription(httpClient, subscriptionId, channel, messageHandler) {
|
|
133
173
|
try {
|
|
134
|
-
const [{ appId,
|
|
174
|
+
const [{ appId: callerAppId, siteId }, duplexerChannelName] = await Promise.all([
|
|
135
175
|
getAppInfoFromAuthToken(httpClient),
|
|
136
176
|
resolveDuplexerChannelName(channel),
|
|
137
177
|
]);
|
|
178
|
+
const socketAppId = channel.appId ?? callerAppId;
|
|
179
|
+
const maybeCrossAppId = channel.appId === callerAppId ? undefined : channel.appId;
|
|
180
|
+
channel = {
|
|
181
|
+
...channel,
|
|
182
|
+
appId: socketAppId,
|
|
183
|
+
};
|
|
138
184
|
const subscriptionEntry = subscriptionManager.get(subscriptionId);
|
|
139
185
|
// Entry was already deleted (e.g., unsubscribe called during the await)
|
|
140
186
|
// or explicitly cancelled — bail out.
|
|
@@ -142,13 +188,13 @@ async function setupSubscription(httpClient, subscriptionId, channel, messageHan
|
|
|
142
188
|
subscriptionManager.delete(subscriptionId);
|
|
143
189
|
return;
|
|
144
190
|
}
|
|
145
|
-
// Index the subscription by instanceId now so cleanupConnectionIfIdle
|
|
146
|
-
// correctly counts it while the duplexer subscription is being set up.
|
|
147
191
|
subscriptionManager.set(subscriptionId, {
|
|
148
192
|
...subscriptionEntry,
|
|
149
|
-
|
|
193
|
+
maybeCrossAppId,
|
|
194
|
+
socketAppId,
|
|
195
|
+
siteId,
|
|
150
196
|
});
|
|
151
|
-
const { socket } = getOrCreateConnection(httpClient,
|
|
197
|
+
const { socket } = getOrCreateConnection(httpClient, socketAppId, siteId);
|
|
152
198
|
const onMessageCallback = (payload, { publisher }) => {
|
|
153
199
|
messageHandler({
|
|
154
200
|
payload,
|
|
@@ -163,7 +209,7 @@ async function setupSubscription(httpClient, subscriptionId, channel, messageHan
|
|
|
163
209
|
// server-side subscription leak.
|
|
164
210
|
if (!subscriptionManager.get(subscriptionId)) {
|
|
165
211
|
socket.unsubscribe(duplexerChannelName, channel.resourceId);
|
|
166
|
-
cleanupConnectionIfIdle(
|
|
212
|
+
cleanupConnectionIfIdle(socketAppId, siteId);
|
|
167
213
|
return;
|
|
168
214
|
}
|
|
169
215
|
subscribedChannel.on(MESSAGE_EVENT_NAME, onMessageCallback);
|
|
@@ -191,7 +237,9 @@ async function setupSubscription(httpClient, subscriptionId, channel, messageHan
|
|
|
191
237
|
subscriptionManager.set(subscriptionId, {
|
|
192
238
|
channelName: channel.name,
|
|
193
239
|
channelResourceId: channel.resourceId,
|
|
194
|
-
|
|
240
|
+
maybeCrossAppId,
|
|
241
|
+
socketAppId,
|
|
242
|
+
siteId,
|
|
195
243
|
channelEmitter: subscribedChannel,
|
|
196
244
|
onSubscribed: currentEntry?.onSubscribed,
|
|
197
245
|
onSubscriptionError: currentEntry?.onSubscriptionError,
|
|
@@ -207,7 +255,7 @@ async function setupSubscription(httpClient, subscriptionId, channel, messageHan
|
|
|
207
255
|
const failedEntry = subscriptionManager.get(subscriptionId);
|
|
208
256
|
subscriptionManager.delete(subscriptionId);
|
|
209
257
|
failedEntry?.onSubscriptionError?.(subscribeFailed(channel, payload), subscriptionId);
|
|
210
|
-
cleanupConnectionIfIdle(
|
|
258
|
+
cleanupConnectionIfIdle(socketAppId, siteId);
|
|
211
259
|
}
|
|
212
260
|
// Subscribe to the duplexer channel and register lifecycle listeners
|
|
213
261
|
// in the same synchronous block so no events can be missed.
|
|
@@ -3,7 +3,9 @@ import type { SubscriptionHandler, SubscriptionErrorHandler } from '@wix/realtim
|
|
|
3
3
|
export interface SubscriptionEntry {
|
|
4
4
|
channelName: string;
|
|
5
5
|
channelResourceId?: string;
|
|
6
|
-
|
|
6
|
+
maybeCrossAppId?: string;
|
|
7
|
+
siteId?: string;
|
|
8
|
+
socketAppId?: string;
|
|
7
9
|
channelEmitter?: ReturnType<ReturnType<Duplexer['connect']>['subscribe']>;
|
|
8
10
|
removeListeners: () => void;
|
|
9
11
|
cancelled?: boolean;
|
|
@@ -12,15 +14,15 @@ export interface SubscriptionEntry {
|
|
|
12
14
|
}
|
|
13
15
|
export declare class SubscriptionManager {
|
|
14
16
|
private subscriptionsBySubId;
|
|
15
|
-
private
|
|
17
|
+
private socketKeyToSubscriptionIds;
|
|
16
18
|
set(id: string, entry: SubscriptionEntry): void;
|
|
17
19
|
get(id: string): SubscriptionEntry | undefined;
|
|
18
20
|
delete(id: string): void;
|
|
19
21
|
findByChannel(channelName: string, channelResourceId?: string): [string, SubscriptionEntry][];
|
|
20
|
-
deleteAndStillHasRemainingOnChannel(
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
deleteAndStillHasRemainingOnChannel(socketAppId: string, siteId: string, subscriptionIdToDelete: string, channelName: string, resourceId?: string): boolean;
|
|
23
|
+
hasSubscriptionsForSocket(socketAppId: string, siteId: string): boolean;
|
|
24
|
+
getSubscriptionIdsBySocket(socketAppId: string, siteId: string): string[];
|
|
23
25
|
removeAll(): void;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
+
private addToSocketIndex;
|
|
27
|
+
private removeFromSocketIndex;
|
|
26
28
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
function socketKey(socketAppId, siteId) {
|
|
2
|
+
return `${socketAppId}:${siteId}`;
|
|
3
|
+
}
|
|
1
4
|
export class SubscriptionManager {
|
|
2
5
|
subscriptionsBySubId = new Map();
|
|
3
|
-
|
|
6
|
+
socketKeyToSubscriptionIds = new Map();
|
|
4
7
|
set(id, entry) {
|
|
5
8
|
this.subscriptionsBySubId.set(id, entry);
|
|
6
|
-
if (entry.
|
|
7
|
-
this.
|
|
9
|
+
if (entry.socketAppId && entry.siteId) {
|
|
10
|
+
this.addToSocketIndex(socketKey(entry.socketAppId, entry.siteId), id);
|
|
8
11
|
}
|
|
9
12
|
}
|
|
10
13
|
get(id) {
|
|
@@ -12,8 +15,8 @@ export class SubscriptionManager {
|
|
|
12
15
|
}
|
|
13
16
|
delete(id) {
|
|
14
17
|
const entry = this.subscriptionsBySubId.get(id);
|
|
15
|
-
if (entry?.
|
|
16
|
-
this.
|
|
18
|
+
if (entry?.socketAppId && entry.siteId) {
|
|
19
|
+
this.removeFromSocketIndex(socketKey(entry.socketAppId, entry.siteId), id);
|
|
17
20
|
}
|
|
18
21
|
this.subscriptionsBySubId.delete(id);
|
|
19
22
|
}
|
|
@@ -21,9 +24,9 @@ export class SubscriptionManager {
|
|
|
21
24
|
return [...this.subscriptionsBySubId.entries()].filter(([, sub]) => sub.channelName === channelName &&
|
|
22
25
|
sub.channelResourceId === channelResourceId);
|
|
23
26
|
}
|
|
24
|
-
deleteAndStillHasRemainingOnChannel(
|
|
27
|
+
deleteAndStillHasRemainingOnChannel(socketAppId, siteId, subscriptionIdToDelete, channelName, resourceId) {
|
|
25
28
|
this.delete(subscriptionIdToDelete);
|
|
26
|
-
const candidateIds = this.
|
|
29
|
+
const candidateIds = this.socketKeyToSubscriptionIds.get(socketKey(socketAppId, siteId));
|
|
27
30
|
if (!candidateIds)
|
|
28
31
|
return false;
|
|
29
32
|
for (const id of candidateIds) {
|
|
@@ -36,12 +39,12 @@ export class SubscriptionManager {
|
|
|
36
39
|
}
|
|
37
40
|
return false;
|
|
38
41
|
}
|
|
39
|
-
|
|
40
|
-
const ids = this.
|
|
42
|
+
hasSubscriptionsForSocket(socketAppId, siteId) {
|
|
43
|
+
const ids = this.socketKeyToSubscriptionIds.get(socketKey(socketAppId, siteId));
|
|
41
44
|
return !!ids && ids.size > 0;
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
const ids = this.
|
|
46
|
+
getSubscriptionIdsBySocket(socketAppId, siteId) {
|
|
47
|
+
const ids = this.socketKeyToSubscriptionIds.get(socketKey(socketAppId, siteId));
|
|
45
48
|
return ids ? [...ids] : [];
|
|
46
49
|
}
|
|
47
50
|
removeAll() {
|
|
@@ -49,22 +52,22 @@ export class SubscriptionManager {
|
|
|
49
52
|
sub.removeListeners();
|
|
50
53
|
}
|
|
51
54
|
this.subscriptionsBySubId.clear();
|
|
52
|
-
this.
|
|
55
|
+
this.socketKeyToSubscriptionIds.clear();
|
|
53
56
|
}
|
|
54
|
-
|
|
55
|
-
let ids = this.
|
|
57
|
+
addToSocketIndex(key, id) {
|
|
58
|
+
let ids = this.socketKeyToSubscriptionIds.get(key);
|
|
56
59
|
if (!ids) {
|
|
57
60
|
ids = new Set();
|
|
58
|
-
this.
|
|
61
|
+
this.socketKeyToSubscriptionIds.set(key, ids);
|
|
59
62
|
}
|
|
60
63
|
ids.add(id);
|
|
61
64
|
}
|
|
62
|
-
|
|
63
|
-
const ids = this.
|
|
65
|
+
removeFromSocketIndex(key, id) {
|
|
66
|
+
const ids = this.socketKeyToSubscriptionIds.get(key);
|
|
64
67
|
if (ids) {
|
|
65
68
|
ids.delete(id);
|
|
66
69
|
if (ids.size === 0) {
|
|
67
|
-
this.
|
|
70
|
+
this.socketKeyToSubscriptionIds.delete(key);
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
}
|
package/es/build/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { RealtimeErrorCode, RealtimeError, type
|
|
1
|
+
export { RealtimeErrorCode, RealtimeError, type PublishChannel, type SubscribeChannel, type Publisher, type Message, type MessageHandler, type SubscriptionHandler, type SubscriptionErrorHandler, type SubscriptionOptions, type UnsubscribeOptions, } from '@wix/realtime-common/types';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/realtime",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.47",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"@wix/auto_sdk_duplexer_publisher": "^1.0.10",
|
|
45
45
|
"@wix/auto_sdk_duplexer_realtime-permissions-provider": "^1.0.0",
|
|
46
46
|
"@wix/duplexer-js": "^2.0.6",
|
|
47
|
-
"@wix/realtime-common": "1.0.
|
|
47
|
+
"@wix/realtime-common": "1.0.17",
|
|
48
48
|
"@wix/sdk": "^1.21.4",
|
|
49
49
|
"@wix/sdk-runtime": "^1.0.9",
|
|
50
50
|
"@wix/sdk-types": "^1.17.5",
|
|
51
|
-
"@wix/sdk_realtime_site": "1.0.
|
|
51
|
+
"@wix/sdk_realtime_site": "1.0.36",
|
|
52
52
|
"uuid": "^11.1.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"isRootPublicSdk": true
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "9d0366754fb3d0e319f47cd14f651bc19f84e19ddcff7ad474301df2"
|
|
76
76
|
}
|