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.
@@ -3,6 +3,6 @@
3
3
  "dependencies": {
4
4
  "jsdom": "^25.0.1",
5
5
  "wirejs-dom": "^1.0.41",
6
- "wirejs-resources": "^0.1.85-realtime"
6
+ "wirejs-resources": "^0.1.86-realtime"
7
7
  }
8
8
  }
@@ -1,5 +1,5 @@
1
1
  import type { MessageStreamSubscriber } from "wirejs-resources";
2
- export type ChannelEvent<T = any> = {
2
+ export type ChannelEvent = {
3
3
  type: "subscribe_success" | "data" | "broadcast_error" | "ka";
4
4
  id: string;
5
5
  event: any;
@@ -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 channelSubs = new Map();
14
+ const channelSubIdLUT = new Map();
13
15
  /**
14
16
  * subscription ID -> subscriber
15
17
  */
16
- const subscribers = new Map();
18
+ const subIdSubscribers = new Map();
17
19
  /**
18
20
  * subcription ID -> connection state
19
21
  *
20
- * For when new subscribers are added, we'll want to broadcast the current
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 subscribers.get(sid) || []) {
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 subscribers.get(sid) || []) {
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(channelSubs.entries())
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
- subscriptionState.set(subscriptionId, 'closed');
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
- console.log('closed', event);
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 (!channelSubs.has(fullChannelName)) {
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
- channelSubs.set(fullChannelName, subscriptionId);
136
- subscribers.set(subscriptionId, [subscriber]);
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 = channelSubs.get(fullChannelName);
147
- subscribers.get(subscriptionId).push(subscriber);
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 = channelSubs.get(fullChannelName);
161
- const subs = subId && subscribers.get(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
- subs.splice(subs.indexOf(sub), 1);
165
- subscribers.set(subId, subs);
166
- sub.onclose?.();
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 subscribers left for this channel. We can unsubscribe from channel.
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
- subscribers.delete(subId);
176
- channelSubs.delete(fullChannelName);
180
+ subIdSubscribers.delete(subId);
181
+ channelSubIdLUT.delete(fullChannelName);
177
182
  }
178
- const socketSubs = Array.from(channelSubs.keys())
179
- .filter(k => k.startsWith(urlKey));
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.117-realtime",
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.85-realtime"
44
+ "wirejs-resources": "^0.1.86-realtime"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@aws-amplify/backend": "^1.14.0",