wirejs-deploy-amplify-basic 0.0.117-realtime → 0.0.118-realtime
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/realtime.js
CHANGED
|
@@ -7,18 +7,23 @@
|
|
|
7
7
|
*/
|
|
8
8
|
const connections = new Map();
|
|
9
9
|
/**
|
|
10
|
+
* Channel subscription ID look-up table.
|
|
11
|
+
*
|
|
10
12
|
* `${URL}#${channel}` -> subscription ID
|
|
11
13
|
*/
|
|
12
|
-
const
|
|
14
|
+
const channelSubIdLUT = new Map();
|
|
13
15
|
/**
|
|
14
16
|
* subscription ID -> subscriber
|
|
15
17
|
*/
|
|
16
|
-
const
|
|
18
|
+
const subIdSubscribers = new Map();
|
|
17
19
|
/**
|
|
18
20
|
* subcription ID -> connection state
|
|
19
21
|
*
|
|
20
|
-
* For when new
|
|
22
|
+
* For when new subIdSubscribers are added, we'll want to broadcast the current
|
|
21
23
|
* state of the connection.
|
|
24
|
+
*
|
|
25
|
+
* "closed"-typed states are not represented here, as they are removed from the map
|
|
26
|
+
* when the WebSocket connection is closed.
|
|
22
27
|
*/
|
|
23
28
|
const subscriptionState = new Map();
|
|
24
29
|
/**
|
|
@@ -74,7 +79,7 @@ export function subscribe(url, channel, token, authHost, subscriber) {
|
|
|
74
79
|
const sid = subscriptionIdString(data.id);
|
|
75
80
|
if (data.type === 'data') {
|
|
76
81
|
const eventData = JSON.parse(data.event);
|
|
77
|
-
for (const subscriber of
|
|
82
|
+
for (const subscriber of subIdSubscribers.get(sid) || []) {
|
|
78
83
|
try {
|
|
79
84
|
subscriber.onmessage(eventData);
|
|
80
85
|
}
|
|
@@ -85,7 +90,7 @@ export function subscribe(url, channel, token, authHost, subscriber) {
|
|
|
85
90
|
}
|
|
86
91
|
else if (data.type === 'subscribe_success') {
|
|
87
92
|
subscriptionState.set(sid, 'open');
|
|
88
|
-
for (const subscriber of
|
|
93
|
+
for (const subscriber of subIdSubscribers.get(sid) || []) {
|
|
89
94
|
try {
|
|
90
95
|
subscriber.onopen?.();
|
|
91
96
|
}
|
|
@@ -95,33 +100,35 @@ export function subscribe(url, channel, token, authHost, subscriber) {
|
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
102
|
};
|
|
98
|
-
const notifyClosed = () => {
|
|
99
|
-
const subscriptionIds = Array.from(
|
|
103
|
+
const notifyClosed = (reason) => {
|
|
104
|
+
const subscriptionIds = Array.from(channelSubIdLUT.entries())
|
|
100
105
|
.filter(([urlChannel, _subId]) => urlChannel.startsWith(`${url}#`))
|
|
101
106
|
.map(([_urlChannel, subId]) => subscriptionIdString(subId));
|
|
102
107
|
for (const subscriptionId of subscriptionIds) {
|
|
103
|
-
|
|
104
|
-
const subs = subscribers.get(subscriptionId);
|
|
108
|
+
const subs = subIdSubscribers.get(subscriptionId);
|
|
105
109
|
if (subs) {
|
|
106
110
|
for (const subscriber of subs) {
|
|
107
111
|
if (subscriber.onclose) {
|
|
108
112
|
try {
|
|
109
|
-
subscriber.onclose();
|
|
113
|
+
subscriber.onclose(reason);
|
|
110
114
|
}
|
|
111
115
|
catch (error) {
|
|
112
116
|
console.error('Error in subscriber onclose:', error);
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
|
-
subscribers.delete(subscriptionId);
|
|
117
120
|
}
|
|
121
|
+
subIdSubscribers.delete(subscriptionId);
|
|
122
|
+
subscriptionState.delete(subscriptionId);
|
|
118
123
|
}
|
|
119
|
-
|
|
124
|
+
channelSubIdLUT.delete(fullChannelName);
|
|
125
|
+
connections.delete(urlKey);
|
|
126
|
+
console.debug('closed', ws);
|
|
120
127
|
};
|
|
121
|
-
ws.onclose = () => notifyClosed();
|
|
122
|
-
ws.onerror = () => notifyClosed();
|
|
128
|
+
ws.onclose = () => notifyClosed('closed');
|
|
129
|
+
ws.onerror = () => notifyClosed('error');
|
|
123
130
|
}
|
|
124
|
-
if (!
|
|
131
|
+
if (!channelSubIdLUT.has(fullChannelName)) {
|
|
125
132
|
const subscriptionId = subscriptionIdString(crypto.randomUUID());
|
|
126
133
|
subscriptionState.set(subscriptionId, 'connecting');
|
|
127
134
|
const ws = connections.get(urlKey);
|
|
@@ -132,8 +139,8 @@ export function subscribe(url, channel, token, authHost, subscriber) {
|
|
|
132
139
|
channel,
|
|
133
140
|
authorization
|
|
134
141
|
}));
|
|
135
|
-
|
|
136
|
-
|
|
142
|
+
channelSubIdLUT.set(fullChannelName, subscriptionId);
|
|
143
|
+
subIdSubscribers.set(subscriptionId, [subscriber]);
|
|
137
144
|
};
|
|
138
145
|
if (ws.readyState === WebSocket.OPEN) {
|
|
139
146
|
subscribe();
|
|
@@ -143,43 +150,42 @@ export function subscribe(url, channel, token, authHost, subscriber) {
|
|
|
143
150
|
}
|
|
144
151
|
}
|
|
145
152
|
else {
|
|
146
|
-
const subscriptionId =
|
|
147
|
-
|
|
153
|
+
const subscriptionId = channelSubIdLUT.get(fullChannelName);
|
|
154
|
+
subIdSubscribers.get(subscriptionId).push(subscriber);
|
|
148
155
|
if (subscriptionState.get(subscriptionId) === 'open') {
|
|
149
156
|
subscriber.onopen?.();
|
|
150
157
|
}
|
|
151
|
-
else if (subscriptionState.get(subscriptionId) === 'closed') {
|
|
152
|
-
subscriber.onclose?.();
|
|
153
|
-
}
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
export function unsubscribe(url, channel, subscriber) {
|
|
157
161
|
const urlKey = urlString(url);
|
|
158
162
|
const ws = connections.get(urlKey);
|
|
159
163
|
const fullChannelName = fullChannelNameString(urlKey, channel);
|
|
160
|
-
const subId =
|
|
161
|
-
const subs = subId &&
|
|
164
|
+
const subId = channelSubIdLUT.get(fullChannelName);
|
|
165
|
+
const subs = subId && subIdSubscribers.get(subId);
|
|
162
166
|
const sub = subs ? subs.find(s => s === subscriber) : undefined;
|
|
163
167
|
if (sub && subs) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
168
|
+
sub.onclose?.('unsubscribed');
|
|
169
|
+
const i = subs.indexOf(sub);
|
|
170
|
+
if (i > -1)
|
|
171
|
+
subs.splice(i, 1);
|
|
167
172
|
}
|
|
168
173
|
if (subs && subs.length === 0) {
|
|
169
|
-
// No
|
|
174
|
+
// No subIdSubscribers left for this channel. We can unsubscribe from channel.
|
|
170
175
|
ws?.send(JSON.stringify({
|
|
171
176
|
id: subId,
|
|
172
177
|
type: 'unsubscribe',
|
|
173
178
|
}));
|
|
174
179
|
subscriptionState.delete(subId);
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
subIdSubscribers.delete(subId);
|
|
181
|
+
channelSubIdLUT.delete(fullChannelName);
|
|
177
182
|
}
|
|
178
|
-
const socketSubs = Array.from(
|
|
179
|
-
.filter(k => k.startsWith(
|
|
183
|
+
const socketSubs = Array.from(channelSubIdLUT.keys())
|
|
184
|
+
.filter(k => k.startsWith(`${url}#`));
|
|
180
185
|
if (socketSubs.length === 0) {
|
|
181
186
|
// No channels left for this URL. We can close the WebSocket connection.
|
|
182
187
|
ws?.close();
|
|
183
188
|
connections.delete(urlKey);
|
|
189
|
+
console.debug('closed', ws);
|
|
184
190
|
}
|
|
185
191
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wirejs-deploy-amplify-basic",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.118-realtime",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"recursive-copy": "^2.0.14",
|
|
42
42
|
"rimraf": "^6.0.1",
|
|
43
43
|
"wirejs-dom": "^1.0.41",
|
|
44
|
-
"wirejs-resources": "^0.1.
|
|
44
|
+
"wirejs-resources": "^0.1.86-realtime"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@aws-amplify/backend": "^1.14.0",
|