iframe-pubsub 1.0.7 → 1.0.9

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/index.d.mts CHANGED
@@ -50,25 +50,6 @@ declare class Client {
50
50
  * @param payload The payload of the message.
51
51
  */
52
52
  sendMessage(to: string, payload: any): void;
53
- /**
54
- * Check if a client with the given ID exists in the PubSub system.
55
- *
56
- * @param clientId The ID of the client to check.
57
- * @param maxRetries Maximum number of retries. Default is 3.
58
- * @param retryInterval Interval between retries in milliseconds. Default is 1000ms.
59
- * @returns A Promise that resolves to true if the client exists, false otherwise.
60
- */
61
- checkClientExists(clientId: string, maxRetries?: number, retryInterval?: number): Promise<boolean>;
62
- /**
63
- * Check if a client with the given ID exists in the PubSub system with retry mechanism.
64
- * Will retry up to 3 times with 1 second delay between retries.
65
- *
66
- * @param clientId The ID of the client to check.
67
- * @param retryCount The current retry count.
68
- * @returns A Promise that resolves to true if the client exists, false otherwise.
69
- * @private
70
- */
71
- private checkClientExistsWithRetry;
72
53
  private handleMessage;
73
54
  }
74
55
 
@@ -192,23 +173,25 @@ declare class PubSub {
192
173
  * @param pageId The ID of the page or component to unregister from.
193
174
  */
194
175
  unregister(pageId: string): void;
195
- sendMessage(message: IMessage): void;
176
+ sendMessage(message: IMessage): Promise<void>;
196
177
  /**
197
178
  * Try to send a message to a client with retry logic.
198
179
  * Will retry up to 3 times with 1 second delay between retries.
180
+ * If client exists, will check if it's still available with PING/PONG.
199
181
  *
200
182
  * @param message The message to send.
201
183
  * @param retryCount The current retry count.
202
184
  */
203
185
  private trySendMessageWithRetry;
204
- private handleMessage;
205
186
  /**
206
- * Check if a client with the given ID exists in the PubSub system.
187
+ * Check if a client is pingable (still available).
207
188
  *
208
189
  * @param clientId The ID of the client to check.
209
- * @returns True if the client exists, false otherwise.
190
+ * @param source The window object of the client.
191
+ * @returns A Promise that resolves to true if the client is pingable, false otherwise.
210
192
  */
211
- isClientExists(clientId: string): boolean;
193
+ private checkClientPingable;
194
+ private handleMessage;
212
195
  }
213
196
 
214
197
  export { AIChatClient, AIChatNameEnum, Client, type IMessage, type IRegistrationMessage, type MessageCallback, PubSub };
package/dist/index.d.ts CHANGED
@@ -50,25 +50,6 @@ declare class Client {
50
50
  * @param payload The payload of the message.
51
51
  */
52
52
  sendMessage(to: string, payload: any): void;
53
- /**
54
- * Check if a client with the given ID exists in the PubSub system.
55
- *
56
- * @param clientId The ID of the client to check.
57
- * @param maxRetries Maximum number of retries. Default is 3.
58
- * @param retryInterval Interval between retries in milliseconds. Default is 1000ms.
59
- * @returns A Promise that resolves to true if the client exists, false otherwise.
60
- */
61
- checkClientExists(clientId: string, maxRetries?: number, retryInterval?: number): Promise<boolean>;
62
- /**
63
- * Check if a client with the given ID exists in the PubSub system with retry mechanism.
64
- * Will retry up to 3 times with 1 second delay between retries.
65
- *
66
- * @param clientId The ID of the client to check.
67
- * @param retryCount The current retry count.
68
- * @returns A Promise that resolves to true if the client exists, false otherwise.
69
- * @private
70
- */
71
- private checkClientExistsWithRetry;
72
53
  private handleMessage;
73
54
  }
74
55
 
@@ -192,23 +173,25 @@ declare class PubSub {
192
173
  * @param pageId The ID of the page or component to unregister from.
193
174
  */
194
175
  unregister(pageId: string): void;
195
- sendMessage(message: IMessage): void;
176
+ sendMessage(message: IMessage): Promise<void>;
196
177
  /**
197
178
  * Try to send a message to a client with retry logic.
198
179
  * Will retry up to 3 times with 1 second delay between retries.
180
+ * If client exists, will check if it's still available with PING/PONG.
199
181
  *
200
182
  * @param message The message to send.
201
183
  * @param retryCount The current retry count.
202
184
  */
203
185
  private trySendMessageWithRetry;
204
- private handleMessage;
205
186
  /**
206
- * Check if a client with the given ID exists in the PubSub system.
187
+ * Check if a client is pingable (still available).
207
188
  *
208
189
  * @param clientId The ID of the client to check.
209
- * @returns True if the client exists, false otherwise.
190
+ * @param source The window object of the client.
191
+ * @returns A Promise that resolves to true if the client is pingable, false otherwise.
210
192
  */
211
- isClientExists(clientId: string): boolean;
193
+ private checkClientPingable;
194
+ private handleMessage;
212
195
  }
213
196
 
214
197
  export { AIChatClient, AIChatNameEnum, Client, type IMessage, type IRegistrationMessage, type MessageCallback, PubSub };
package/dist/index.js CHANGED
@@ -69,33 +69,83 @@ var _PubSub = class _PubSub {
69
69
  if (this.mainCallback) {
70
70
  this.mainCallback(message);
71
71
  }
72
- this.trySendMessageWithRetry(message, 0);
72
+ return this.trySendMessageWithRetry(message, 0);
73
73
  }
74
74
  /**
75
75
  * Try to send a message to a client with retry logic.
76
76
  * Will retry up to 3 times with 1 second delay between retries.
77
- *
77
+ * If client exists, will check if it's still available with PING/PONG.
78
+ *
78
79
  * @param message The message to send.
79
80
  * @param retryCount The current retry count.
80
81
  */
81
- trySendMessageWithRetry(message, retryCount) {
82
+ async trySendMessageWithRetry(message, retryCount) {
82
83
  const subscriber = this.subscribers.get(message.to);
83
84
  if (subscriber) {
84
85
  if (subscriber.source) {
85
- subscriber.source.postMessage(message, "*");
86
+ try {
87
+ const isPingable = await this.checkClientPingable(
88
+ message.to,
89
+ subscriber.source
90
+ );
91
+ if (isPingable) {
92
+ subscriber.source.postMessage(message, "*");
93
+ return;
94
+ } else {
95
+ this.subscribers.delete(message.to);
96
+ }
97
+ } catch (error) {
98
+ console.warn(`Failed to ping client ${message.to}:`, error);
99
+ this.subscribers.delete(message.to);
100
+ }
86
101
  } else {
87
102
  subscriber.callback(message);
103
+ return;
88
104
  }
89
- return;
90
105
  }
91
- if (retryCount < 10) {
92
- setTimeout(() => {
93
- this.trySendMessageWithRetry(message, retryCount + 1);
94
- }, 1e3);
106
+ if (retryCount < 3) {
107
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
108
+ return this.trySendMessageWithRetry(message, retryCount + 1);
95
109
  } else {
96
- console.warn(`Failed to send message to client ${message.to} after 10 retries`);
110
+ console.warn(
111
+ `Failed to send message to client ${message.to} after 3 retries`
112
+ );
97
113
  }
98
114
  }
115
+ /**
116
+ * Check if a client is pingable (still available).
117
+ *
118
+ * @param clientId The ID of the client to check.
119
+ * @param source The window object of the client.
120
+ * @returns A Promise that resolves to true if the client is pingable, false otherwise.
121
+ */
122
+ checkClientPingable(clientId, source) {
123
+ return new Promise((resolve) => {
124
+ const pingId = `ping-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
125
+ const messageHandler = (event) => {
126
+ const data = event.data;
127
+ if (data && data.from === clientId && data.to === "pubsub" && data.payload?.type === "PONG" && data.payload.pingId === pingId) {
128
+ window.removeEventListener("message", messageHandler);
129
+ clearTimeout(timeoutId);
130
+ resolve(true);
131
+ }
132
+ };
133
+ window.addEventListener("message", messageHandler);
134
+ const pingMessage = {
135
+ from: "pubsub",
136
+ to: clientId,
137
+ payload: {
138
+ type: "PING",
139
+ pingId
140
+ }
141
+ };
142
+ source.postMessage(pingMessage, "*");
143
+ const timeoutId = setTimeout(() => {
144
+ window.removeEventListener("message", messageHandler);
145
+ resolve(false);
146
+ }, 1e3);
147
+ });
148
+ }
99
149
  async handleMessage(event) {
100
150
  const data = event.data;
101
151
  const source = event.source;
@@ -114,14 +164,6 @@ var _PubSub = class _PubSub {
114
164
  this.subscribers.delete(unregistration.pageId);
115
165
  return;
116
166
  }
117
- if (data?.type === "CLIENT_EXISTS_CHECK") {
118
- source.postMessage({
119
- type: "CLIENT_EXISTS_RESPONSE",
120
- requestId: data.requestId,
121
- exists: this.subscribers.has(data.clientId)
122
- }, "*");
123
- return;
124
- }
125
167
  if (!data || !data.from || !data.to) return;
126
168
  const message = data;
127
169
  if (this.mainCallback) {
@@ -135,15 +177,6 @@ var _PubSub = class _PubSub {
135
177
  await subscriber.callback(message);
136
178
  }
137
179
  }
138
- /**
139
- * Check if a client with the given ID exists in the PubSub system.
140
- *
141
- * @param clientId The ID of the client to check.
142
- * @returns True if the client exists, false otherwise.
143
- */
144
- isClientExists(clientId) {
145
- return this.subscribers.has(clientId);
146
- }
147
180
  };
148
181
  __publicField(_PubSub, "instance");
149
182
  var PubSub = _PubSub;
@@ -212,71 +245,6 @@ var Client = class {
212
245
  this.pubsub.sendMessage(message);
213
246
  }
214
247
  }
215
- /**
216
- * Check if a client with the given ID exists in the PubSub system.
217
- *
218
- * @param clientId The ID of the client to check.
219
- * @param maxRetries Maximum number of retries. Default is 3.
220
- * @param retryInterval Interval between retries in milliseconds. Default is 1000ms.
221
- * @returns A Promise that resolves to true if the client exists, false otherwise.
222
- */
223
- checkClientExists(clientId, maxRetries = 3, retryInterval = 1e3) {
224
- return this.checkClientExistsWithRetry(clientId, 0, maxRetries, retryInterval);
225
- }
226
- /**
227
- * Check if a client with the given ID exists in the PubSub system with retry mechanism.
228
- * Will retry up to 3 times with 1 second delay between retries.
229
- *
230
- * @param clientId The ID of the client to check.
231
- * @param retryCount The current retry count.
232
- * @returns A Promise that resolves to true if the client exists, false otherwise.
233
- * @private
234
- */
235
- checkClientExistsWithRetry(clientId, retryCount, maxRetries, retryInterval) {
236
- return new Promise((resolve) => {
237
- if (this.isIframe) {
238
- const requestId = `check-client-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
239
- const messageHandler = (event) => {
240
- const data = event.data;
241
- if (data && data.type === "CLIENT_EXISTS_RESPONSE" && data.requestId === requestId) {
242
- window.removeEventListener("message", messageHandler);
243
- clearTimeout(removeHandlerTimeout);
244
- if (data.exists) {
245
- resolve(true);
246
- } else if (retryCount < maxRetries - 1) {
247
- setTimeout(() => {
248
- this.checkClientExistsWithRetry(clientId, retryCount + 1, maxRetries, retryInterval).then((exists) => resolve(exists));
249
- }, retryInterval);
250
- } else {
251
- resolve(false);
252
- }
253
- }
254
- };
255
- window.addEventListener("message", messageHandler);
256
- window.parent.postMessage({
257
- type: "CLIENT_EXISTS_CHECK",
258
- clientId,
259
- requestId,
260
- from: this.pageId
261
- }, "*");
262
- const removeHandlerTimeout = setTimeout(() => {
263
- window.removeEventListener("message", messageHandler);
264
- resolve(false);
265
- }, retryInterval + 1e3);
266
- } else {
267
- const exists = this.pubsub.isClientExists(clientId);
268
- if (exists) {
269
- resolve(true);
270
- } else if (retryCount < maxRetries - 1) {
271
- setTimeout(() => {
272
- this.checkClientExistsWithRetry(clientId, retryCount + 1, maxRetries, retryInterval).then((exists2) => resolve(exists2));
273
- }, retryInterval);
274
- } else {
275
- resolve(false);
276
- }
277
- }
278
- });
279
- }
280
248
  async handleMessage(event) {
281
249
  let message;
282
250
  if (event.data) {
@@ -286,6 +254,22 @@ var Client = class {
286
254
  message = event;
287
255
  }
288
256
  if (!message || !message.from || !message.to || message.to !== this.pageId) return;
257
+ if (message.payload?.type === "PING") {
258
+ const pongMsg = {
259
+ from: this.pageId,
260
+ to: message.from,
261
+ payload: {
262
+ type: "PONG",
263
+ pingId: message.payload.pingId
264
+ }
265
+ };
266
+ if (this.isIframe) {
267
+ window.parent.postMessage(pongMsg, "*");
268
+ } else {
269
+ this.pubsub.sendMessage(pongMsg);
270
+ }
271
+ return;
272
+ }
289
273
  if (this.callback) {
290
274
  try {
291
275
  await this.callback(message);
package/dist/index.mjs CHANGED
@@ -42,33 +42,83 @@ var _PubSub = class _PubSub {
42
42
  if (this.mainCallback) {
43
43
  this.mainCallback(message);
44
44
  }
45
- this.trySendMessageWithRetry(message, 0);
45
+ return this.trySendMessageWithRetry(message, 0);
46
46
  }
47
47
  /**
48
48
  * Try to send a message to a client with retry logic.
49
49
  * Will retry up to 3 times with 1 second delay between retries.
50
- *
50
+ * If client exists, will check if it's still available with PING/PONG.
51
+ *
51
52
  * @param message The message to send.
52
53
  * @param retryCount The current retry count.
53
54
  */
54
- trySendMessageWithRetry(message, retryCount) {
55
+ async trySendMessageWithRetry(message, retryCount) {
55
56
  const subscriber = this.subscribers.get(message.to);
56
57
  if (subscriber) {
57
58
  if (subscriber.source) {
58
- subscriber.source.postMessage(message, "*");
59
+ try {
60
+ const isPingable = await this.checkClientPingable(
61
+ message.to,
62
+ subscriber.source
63
+ );
64
+ if (isPingable) {
65
+ subscriber.source.postMessage(message, "*");
66
+ return;
67
+ } else {
68
+ this.subscribers.delete(message.to);
69
+ }
70
+ } catch (error) {
71
+ console.warn(`Failed to ping client ${message.to}:`, error);
72
+ this.subscribers.delete(message.to);
73
+ }
59
74
  } else {
60
75
  subscriber.callback(message);
76
+ return;
61
77
  }
62
- return;
63
78
  }
64
- if (retryCount < 10) {
65
- setTimeout(() => {
66
- this.trySendMessageWithRetry(message, retryCount + 1);
67
- }, 1e3);
79
+ if (retryCount < 3) {
80
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
81
+ return this.trySendMessageWithRetry(message, retryCount + 1);
68
82
  } else {
69
- console.warn(`Failed to send message to client ${message.to} after 10 retries`);
83
+ console.warn(
84
+ `Failed to send message to client ${message.to} after 3 retries`
85
+ );
70
86
  }
71
87
  }
88
+ /**
89
+ * Check if a client is pingable (still available).
90
+ *
91
+ * @param clientId The ID of the client to check.
92
+ * @param source The window object of the client.
93
+ * @returns A Promise that resolves to true if the client is pingable, false otherwise.
94
+ */
95
+ checkClientPingable(clientId, source) {
96
+ return new Promise((resolve) => {
97
+ const pingId = `ping-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
98
+ const messageHandler = (event) => {
99
+ const data = event.data;
100
+ if (data && data.from === clientId && data.to === "pubsub" && data.payload?.type === "PONG" && data.payload.pingId === pingId) {
101
+ window.removeEventListener("message", messageHandler);
102
+ clearTimeout(timeoutId);
103
+ resolve(true);
104
+ }
105
+ };
106
+ window.addEventListener("message", messageHandler);
107
+ const pingMessage = {
108
+ from: "pubsub",
109
+ to: clientId,
110
+ payload: {
111
+ type: "PING",
112
+ pingId
113
+ }
114
+ };
115
+ source.postMessage(pingMessage, "*");
116
+ const timeoutId = setTimeout(() => {
117
+ window.removeEventListener("message", messageHandler);
118
+ resolve(false);
119
+ }, 1e3);
120
+ });
121
+ }
72
122
  async handleMessage(event) {
73
123
  const data = event.data;
74
124
  const source = event.source;
@@ -87,14 +137,6 @@ var _PubSub = class _PubSub {
87
137
  this.subscribers.delete(unregistration.pageId);
88
138
  return;
89
139
  }
90
- if (data?.type === "CLIENT_EXISTS_CHECK") {
91
- source.postMessage({
92
- type: "CLIENT_EXISTS_RESPONSE",
93
- requestId: data.requestId,
94
- exists: this.subscribers.has(data.clientId)
95
- }, "*");
96
- return;
97
- }
98
140
  if (!data || !data.from || !data.to) return;
99
141
  const message = data;
100
142
  if (this.mainCallback) {
@@ -108,15 +150,6 @@ var _PubSub = class _PubSub {
108
150
  await subscriber.callback(message);
109
151
  }
110
152
  }
111
- /**
112
- * Check if a client with the given ID exists in the PubSub system.
113
- *
114
- * @param clientId The ID of the client to check.
115
- * @returns True if the client exists, false otherwise.
116
- */
117
- isClientExists(clientId) {
118
- return this.subscribers.has(clientId);
119
- }
120
153
  };
121
154
  __publicField(_PubSub, "instance");
122
155
  var PubSub = _PubSub;
@@ -185,71 +218,6 @@ var Client = class {
185
218
  this.pubsub.sendMessage(message);
186
219
  }
187
220
  }
188
- /**
189
- * Check if a client with the given ID exists in the PubSub system.
190
- *
191
- * @param clientId The ID of the client to check.
192
- * @param maxRetries Maximum number of retries. Default is 3.
193
- * @param retryInterval Interval between retries in milliseconds. Default is 1000ms.
194
- * @returns A Promise that resolves to true if the client exists, false otherwise.
195
- */
196
- checkClientExists(clientId, maxRetries = 3, retryInterval = 1e3) {
197
- return this.checkClientExistsWithRetry(clientId, 0, maxRetries, retryInterval);
198
- }
199
- /**
200
- * Check if a client with the given ID exists in the PubSub system with retry mechanism.
201
- * Will retry up to 3 times with 1 second delay between retries.
202
- *
203
- * @param clientId The ID of the client to check.
204
- * @param retryCount The current retry count.
205
- * @returns A Promise that resolves to true if the client exists, false otherwise.
206
- * @private
207
- */
208
- checkClientExistsWithRetry(clientId, retryCount, maxRetries, retryInterval) {
209
- return new Promise((resolve) => {
210
- if (this.isIframe) {
211
- const requestId = `check-client-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
212
- const messageHandler = (event) => {
213
- const data = event.data;
214
- if (data && data.type === "CLIENT_EXISTS_RESPONSE" && data.requestId === requestId) {
215
- window.removeEventListener("message", messageHandler);
216
- clearTimeout(removeHandlerTimeout);
217
- if (data.exists) {
218
- resolve(true);
219
- } else if (retryCount < maxRetries - 1) {
220
- setTimeout(() => {
221
- this.checkClientExistsWithRetry(clientId, retryCount + 1, maxRetries, retryInterval).then((exists) => resolve(exists));
222
- }, retryInterval);
223
- } else {
224
- resolve(false);
225
- }
226
- }
227
- };
228
- window.addEventListener("message", messageHandler);
229
- window.parent.postMessage({
230
- type: "CLIENT_EXISTS_CHECK",
231
- clientId,
232
- requestId,
233
- from: this.pageId
234
- }, "*");
235
- const removeHandlerTimeout = setTimeout(() => {
236
- window.removeEventListener("message", messageHandler);
237
- resolve(false);
238
- }, retryInterval + 1e3);
239
- } else {
240
- const exists = this.pubsub.isClientExists(clientId);
241
- if (exists) {
242
- resolve(true);
243
- } else if (retryCount < maxRetries - 1) {
244
- setTimeout(() => {
245
- this.checkClientExistsWithRetry(clientId, retryCount + 1, maxRetries, retryInterval).then((exists2) => resolve(exists2));
246
- }, retryInterval);
247
- } else {
248
- resolve(false);
249
- }
250
- }
251
- });
252
- }
253
221
  async handleMessage(event) {
254
222
  let message;
255
223
  if (event.data) {
@@ -259,6 +227,22 @@ var Client = class {
259
227
  message = event;
260
228
  }
261
229
  if (!message || !message.from || !message.to || message.to !== this.pageId) return;
230
+ if (message.payload?.type === "PING") {
231
+ const pongMsg = {
232
+ from: this.pageId,
233
+ to: message.from,
234
+ payload: {
235
+ type: "PONG",
236
+ pingId: message.payload.pingId
237
+ }
238
+ };
239
+ if (this.isIframe) {
240
+ window.parent.postMessage(pongMsg, "*");
241
+ } else {
242
+ this.pubsub.sendMessage(pongMsg);
243
+ }
244
+ return;
245
+ }
262
246
  if (this.callback) {
263
247
  try {
264
248
  await this.callback(message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iframe-pubsub",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "A PubSub library for iframe communication.",
5
5
  "author": "Lap Tran",
6
6
  "license": "ISC",