@hypen-space/core 0.2.12 → 0.3.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.
Files changed (45) hide show
  1. package/README.md +182 -11
  2. package/dist/src/app.js +470 -44
  3. package/dist/src/app.js.map +7 -5
  4. package/dist/src/components/builtin.js +470 -44
  5. package/dist/src/components/builtin.js.map +7 -5
  6. package/dist/src/discovery.js +559 -65
  7. package/dist/src/discovery.js.map +8 -6
  8. package/dist/src/engine.js +18 -9
  9. package/dist/src/engine.js.map +3 -3
  10. package/dist/src/index.browser.js +862 -81
  11. package/dist/src/index.browser.js.map +10 -6
  12. package/dist/src/index.js +1590 -124
  13. package/dist/src/index.js.map +16 -9
  14. package/dist/src/remote/client.js +525 -35
  15. package/dist/src/remote/client.js.map +7 -4
  16. package/dist/src/remote/index.js +1796 -35
  17. package/dist/src/remote/index.js.map +13 -4
  18. package/dist/src/router.js +55 -29
  19. package/dist/src/router.js.map +3 -3
  20. package/dist/src/state.js +57 -29
  21. package/dist/src/state.js.map +3 -3
  22. package/package.json +8 -2
  23. package/src/app.ts +292 -13
  24. package/src/discovery.ts +123 -18
  25. package/src/disposable.ts +281 -0
  26. package/src/engine.ts +29 -10
  27. package/src/hypen.ts +209 -0
  28. package/src/index.ts +147 -11
  29. package/src/logger.ts +338 -0
  30. package/src/remote/client.ts +263 -56
  31. package/src/remote/index.ts +25 -1
  32. package/src/remote/server.ts +652 -0
  33. package/src/remote/session.ts +256 -0
  34. package/src/remote/types.ts +68 -1
  35. package/src/result.ts +260 -0
  36. package/src/retry.ts +306 -0
  37. package/src/state.ts +103 -45
  38. package/wasm-browser/README.md +4 -0
  39. package/wasm-browser/hypen_engine_bg.wasm +0 -0
  40. package/wasm-browser/package.json +1 -1
  41. package/wasm-node/README.md +4 -0
  42. package/wasm-node/hypen_engine_bg.wasm +0 -0
  43. package/wasm-node/package.json +1 -1
  44. package/wasm-browser/hypen_engine_bg.js +0 -736
  45. package/wasm-node/hypen_engine_bg.js +0 -736
@@ -10,6 +10,419 @@ var __export = (target, all) => {
10
10
  };
11
11
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
12
 
13
+ // src/result.ts
14
+ function Ok(value) {
15
+ return { ok: true, value };
16
+ }
17
+ function Err(error) {
18
+ return { ok: false, error };
19
+ }
20
+ function isOk(result) {
21
+ return result.ok;
22
+ }
23
+ function isErr(result) {
24
+ return !result.ok;
25
+ }
26
+ async function fromPromise(promise, mapError) {
27
+ try {
28
+ const value = await promise;
29
+ return Ok(value);
30
+ } catch (e) {
31
+ if (mapError) {
32
+ return Err(mapError(e));
33
+ }
34
+ return Err(e);
35
+ }
36
+ }
37
+ function fromTry(fn, mapError) {
38
+ try {
39
+ return Ok(fn());
40
+ } catch (e) {
41
+ if (mapError) {
42
+ return Err(mapError(e));
43
+ }
44
+ return Err(e);
45
+ }
46
+ }
47
+ function map(result, fn) {
48
+ if (result.ok) {
49
+ return Ok(fn(result.value));
50
+ }
51
+ return result;
52
+ }
53
+ function mapErr(result, fn) {
54
+ if (!result.ok) {
55
+ return Err(fn(result.error));
56
+ }
57
+ return result;
58
+ }
59
+ function flatMap(result, fn) {
60
+ if (result.ok) {
61
+ return fn(result.value);
62
+ }
63
+ return result;
64
+ }
65
+ function unwrap(result) {
66
+ if (result.ok) {
67
+ return result.value;
68
+ }
69
+ throw result.error;
70
+ }
71
+ function unwrapOr(result, defaultValue) {
72
+ if (result.ok) {
73
+ return result.value;
74
+ }
75
+ return defaultValue;
76
+ }
77
+ function unwrapOrElse(result, fn) {
78
+ if (result.ok) {
79
+ return result.value;
80
+ }
81
+ return fn(result.error);
82
+ }
83
+ function match(result, handlers) {
84
+ if (result.ok) {
85
+ return handlers.ok(result.value);
86
+ }
87
+ return handlers.err(result.error);
88
+ }
89
+ function all(results) {
90
+ const values = [];
91
+ for (const result of results) {
92
+ if (!result.ok) {
93
+ return result;
94
+ }
95
+ values.push(result.value);
96
+ }
97
+ return Ok(values);
98
+ }
99
+ var HypenError, ActionError, ConnectionError, StateError;
100
+ var init_result = __esm(() => {
101
+ HypenError = class HypenError extends Error {
102
+ code;
103
+ context;
104
+ cause;
105
+ constructor(code, message, options) {
106
+ super(message);
107
+ this.name = "HypenError";
108
+ this.code = code;
109
+ this.context = options?.context;
110
+ this.cause = options?.cause;
111
+ Object.setPrototypeOf(this, new.target.prototype);
112
+ }
113
+ };
114
+ ActionError = class ActionError extends HypenError {
115
+ actionName;
116
+ constructor(actionName, cause) {
117
+ super("ACTION_ERROR", `Action handler "${actionName}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
118
+ context: { actionName },
119
+ cause: cause instanceof Error ? cause : undefined
120
+ });
121
+ this.name = "ActionError";
122
+ this.actionName = actionName;
123
+ }
124
+ };
125
+ ConnectionError = class ConnectionError extends HypenError {
126
+ url;
127
+ attempt;
128
+ constructor(url, cause, attempt) {
129
+ super("CONNECTION_ERROR", `Connection to "${url}" failed${attempt ? ` (attempt ${attempt})` : ""}: ${cause instanceof Error ? cause.message : String(cause)}`, {
130
+ context: { url, attempt },
131
+ cause: cause instanceof Error ? cause : undefined
132
+ });
133
+ this.name = "ConnectionError";
134
+ this.url = url;
135
+ this.attempt = attempt;
136
+ }
137
+ };
138
+ StateError = class StateError extends HypenError {
139
+ path;
140
+ constructor(message, path, cause) {
141
+ super("STATE_ERROR", message, {
142
+ context: { path },
143
+ cause: cause instanceof Error ? cause : undefined
144
+ });
145
+ this.name = "StateError";
146
+ this.path = path;
147
+ }
148
+ };
149
+ });
150
+
151
+ // src/remote/client.ts
152
+ init_result();
153
+
154
+ // src/disposable.ts
155
+ function isDisposable(obj) {
156
+ return obj !== null && typeof obj === "object" && "dispose" in obj && typeof obj.dispose === "function";
157
+ }
158
+
159
+ class DisposableStack {
160
+ stack = [];
161
+ disposed = false;
162
+ add(disposable) {
163
+ if (this.disposed) {
164
+ disposable.dispose();
165
+ return disposable;
166
+ }
167
+ this.stack.push(disposable);
168
+ return disposable;
169
+ }
170
+ addCallback(callback) {
171
+ this.add({ dispose: callback });
172
+ }
173
+ addValue(value, dispose) {
174
+ this.add({ dispose: () => dispose(value) });
175
+ return value;
176
+ }
177
+ dispose() {
178
+ if (this.disposed)
179
+ return;
180
+ this.disposed = true;
181
+ while (this.stack.length > 0) {
182
+ const item = this.stack.pop();
183
+ try {
184
+ item.dispose();
185
+ } catch (error) {
186
+ console.error("[DisposableStack] Error during dispose:", error);
187
+ }
188
+ }
189
+ }
190
+ get isDisposed() {
191
+ return this.disposed;
192
+ }
193
+ get size() {
194
+ return this.stack.length;
195
+ }
196
+ }
197
+ function disposableListener(target, event, handler, options) {
198
+ target.addEventListener(event, handler, options);
199
+ return {
200
+ dispose: () => target.removeEventListener(event, handler, options)
201
+ };
202
+ }
203
+ function disposableTimeout(callback, ms) {
204
+ const id = setTimeout(callback, ms);
205
+ return {
206
+ id,
207
+ dispose: () => clearTimeout(id)
208
+ };
209
+ }
210
+ function disposableInterval(callback, ms) {
211
+ const id = setInterval(callback, ms);
212
+ return {
213
+ id,
214
+ dispose: () => clearInterval(id)
215
+ };
216
+ }
217
+ function disposableWebSocket(ws) {
218
+ return {
219
+ dispose: () => {
220
+ if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
221
+ ws.close();
222
+ }
223
+ }
224
+ };
225
+ }
226
+ function disposableAbortController() {
227
+ const controller = new AbortController;
228
+ return {
229
+ controller,
230
+ signal: controller.signal,
231
+ dispose: () => controller.abort()
232
+ };
233
+ }
234
+ function disposableSubscription(unsubscribe) {
235
+ return { dispose: unsubscribe };
236
+ }
237
+ var ELEMENT_DISPOSABLES = Symbol("hypen.disposables");
238
+ function getElementDisposables(element) {
239
+ const existing = element[ELEMENT_DISPOSABLES];
240
+ if (existing instanceof DisposableStack) {
241
+ return existing;
242
+ }
243
+ const stack = new DisposableStack;
244
+ element[ELEMENT_DISPOSABLES] = stack;
245
+ return stack;
246
+ }
247
+ function disposeElement(element) {
248
+ const stack = element[ELEMENT_DISPOSABLES];
249
+ if (stack instanceof DisposableStack) {
250
+ stack.dispose();
251
+ delete element[ELEMENT_DISPOSABLES];
252
+ }
253
+ }
254
+ function hasElementDisposables(element) {
255
+ return element[ELEMENT_DISPOSABLES] instanceof DisposableStack;
256
+ }
257
+
258
+ class DisposableMixin {
259
+ disposables = new DisposableStack;
260
+ track(disposable) {
261
+ return this.disposables.add(disposable);
262
+ }
263
+ onDispose(callback) {
264
+ this.disposables.addCallback(callback);
265
+ }
266
+ dispose() {
267
+ this.disposables.dispose();
268
+ }
269
+ }
270
+ function compositeDisposable(...disposables) {
271
+ return {
272
+ dispose: () => {
273
+ for (const d of disposables) {
274
+ try {
275
+ d.dispose();
276
+ } catch (error) {
277
+ console.error("[compositeDisposable] Error during dispose:", error);
278
+ }
279
+ }
280
+ }
281
+ };
282
+ }
283
+ async function using(resource, fn) {
284
+ const r = typeof resource === "function" ? resource() : resource;
285
+ try {
286
+ return await fn(r);
287
+ } finally {
288
+ r.dispose();
289
+ }
290
+ }
291
+ function usingSync(resource, fn) {
292
+ const r = typeof resource === "function" ? resource() : resource;
293
+ try {
294
+ return fn(r);
295
+ } finally {
296
+ r.dispose();
297
+ }
298
+ }
299
+
300
+ // src/retry.ts
301
+ init_result();
302
+ var DEFAULT_OPTIONS = {
303
+ maxAttempts: 3,
304
+ delayMs: 1000,
305
+ backoff: "exponential",
306
+ maxDelayMs: 30000,
307
+ jitter: 0.1
308
+ };
309
+ function calculateDelay(attempt, options) {
310
+ let delay;
311
+ switch (options.backoff) {
312
+ case "exponential":
313
+ delay = options.delayMs * Math.pow(2, attempt - 1);
314
+ break;
315
+ case "linear":
316
+ delay = options.delayMs * attempt;
317
+ break;
318
+ case "none":
319
+ delay = options.delayMs;
320
+ break;
321
+ }
322
+ if (options.jitter > 0) {
323
+ const jitterRange = delay * options.jitter;
324
+ delay += (Math.random() * 2 - 1) * jitterRange;
325
+ }
326
+ return Math.min(delay, options.maxDelayMs);
327
+ }
328
+ function sleep(ms, signal) {
329
+ return new Promise((resolve, reject) => {
330
+ if (signal?.aborted) {
331
+ reject(new Error("Retry aborted"));
332
+ return;
333
+ }
334
+ const timeoutId = setTimeout(resolve, ms);
335
+ signal?.addEventListener("abort", () => {
336
+ clearTimeout(timeoutId);
337
+ reject(new Error("Retry aborted"));
338
+ });
339
+ });
340
+ }
341
+ async function retry(fn, options = {}) {
342
+ const opts = { ...DEFAULT_OPTIONS, ...options };
343
+ let lastError = new Error("No attempts made");
344
+ for (let attempt = 1;attempt <= opts.maxAttempts; attempt++) {
345
+ try {
346
+ if (opts.signal?.aborted) {
347
+ throw new Error("Retry aborted");
348
+ }
349
+ return await fn();
350
+ } catch (e) {
351
+ lastError = e instanceof Error ? e : new Error(String(e));
352
+ if (opts.shouldRetry && !opts.shouldRetry(lastError)) {
353
+ throw lastError;
354
+ }
355
+ if (attempt === opts.maxAttempts) {
356
+ break;
357
+ }
358
+ const delayMs = calculateDelay(attempt, opts);
359
+ opts.onRetry?.(attempt, lastError, delayMs);
360
+ await sleep(delayMs, opts.signal);
361
+ }
362
+ }
363
+ throw lastError;
364
+ }
365
+ async function retryResult(fn, options = {}) {
366
+ try {
367
+ const value = await retry(fn, options);
368
+ return Ok(value);
369
+ } catch (e) {
370
+ return Err(e instanceof Error ? e : new Error(String(e)));
371
+ }
372
+ }
373
+ function withRetry(fn, options = {}) {
374
+ return (...args) => retry(() => fn(...args), options);
375
+ }
376
+ var RetryConditions = {
377
+ networkErrors: (error) => {
378
+ const message = error.message.toLowerCase();
379
+ return message.includes("network") || message.includes("fetch") || message.includes("timeout") || message.includes("econnrefused") || message.includes("econnreset") || message.includes("socket");
380
+ },
381
+ httpRetryable: (error) => {
382
+ const status = error.status;
383
+ if (!status)
384
+ return false;
385
+ return [408, 429, 500, 502, 503, 504].includes(status);
386
+ },
387
+ websocketErrors: (error) => {
388
+ const message = error.message.toLowerCase();
389
+ return message.includes("websocket") || message.includes("connection") || message.includes("close");
390
+ },
391
+ any: (...conditions) => (error) => conditions.some((c) => c(error)),
392
+ all: (...conditions) => (error) => conditions.every((c) => c(error))
393
+ };
394
+ var RetryPresets = {
395
+ aggressive: {
396
+ maxAttempts: 10,
397
+ delayMs: 500,
398
+ backoff: "exponential",
399
+ maxDelayMs: 60000,
400
+ jitter: 0.2
401
+ },
402
+ conservative: {
403
+ maxAttempts: 3,
404
+ delayMs: 2000,
405
+ backoff: "linear",
406
+ maxDelayMs: 1e4,
407
+ jitter: 0.1
408
+ },
409
+ fast: {
410
+ maxAttempts: 5,
411
+ delayMs: 100,
412
+ backoff: "exponential",
413
+ maxDelayMs: 2000,
414
+ jitter: 0
415
+ },
416
+ websocket: {
417
+ maxAttempts: 10,
418
+ delayMs: 1000,
419
+ backoff: "exponential",
420
+ maxDelayMs: 30000,
421
+ jitter: 0.1,
422
+ shouldRetry: RetryConditions.websocketErrors
423
+ }
424
+ };
425
+
13
426
  // src/remote/client.ts
14
427
  class RemoteEngine {
15
428
  ws = null;
@@ -17,12 +430,17 @@ class RemoteEngine {
17
430
  state = "disconnected";
18
431
  options;
19
432
  reconnectAttempts = 0;
20
- reconnectTimer = null;
433
+ disposables = new DisposableStack;
434
+ reconnectDisposable = null;
435
+ currentSessionId = null;
436
+ sessionOptions;
21
437
  patchCallbacks = [];
22
438
  stateCallbacks = [];
23
439
  connectionCallbacks = [];
24
440
  disconnectionCallbacks = [];
25
441
  errorCallbacks = [];
442
+ sessionEstablishedCallbacks = [];
443
+ sessionExpiredCallbacks = [];
26
444
  currentState = null;
27
445
  currentRevision = 0;
28
446
  moduleName = "";
@@ -31,54 +449,85 @@ class RemoteEngine {
31
449
  this.options = {
32
450
  autoReconnect: options.autoReconnect ?? true,
33
451
  reconnectInterval: options.reconnectInterval ?? 3000,
34
- maxReconnectAttempts: options.maxReconnectAttempts ?? 10
452
+ maxReconnectAttempts: options.maxReconnectAttempts ?? 10,
453
+ session: options.session
35
454
  };
455
+ this.sessionOptions = options.session;
456
+ if (options.session?.id) {
457
+ this.currentSessionId = options.session.id;
458
+ }
36
459
  }
37
460
  async connect() {
38
461
  if (this.state === "connected" || this.state === "connecting") {
39
- return;
462
+ return Ok(undefined);
40
463
  }
41
464
  this.state = "connecting";
42
- return new Promise((resolve, reject) => {
465
+ return new Promise((resolve) => {
43
466
  try {
44
467
  this.ws = new WebSocket(this.url);
45
- this.ws.onopen = () => {
46
- this.state = "connected";
47
- this.reconnectAttempts = 0;
48
- this.connectionCallbacks.forEach((cb) => cb());
49
- resolve();
50
- };
51
- this.ws.onmessage = (event) => {
468
+ this.disposables.add(disposableWebSocket(this.ws));
469
+ const messageHandler = (event) => {
52
470
  this.handleMessage(event.data);
53
471
  };
54
- this.ws.onerror = () => {
472
+ this.disposables.add(disposableListener(this.ws, "message", messageHandler));
473
+ const errorHandler = () => {
55
474
  this.state = "error";
56
- const error = new Error("WebSocket error");
475
+ const error = new ConnectionError(this.url, new Error("WebSocket error"));
57
476
  this.errorCallbacks.forEach((cb) => cb(error));
58
- reject(error);
477
+ resolve(Err(error));
59
478
  };
60
- this.ws.onclose = () => {
479
+ this.disposables.add(disposableListener(this.ws, "error", errorHandler));
480
+ const closeHandler = () => {
61
481
  this.state = "disconnected";
62
482
  this.disconnectionCallbacks.forEach((cb) => cb());
63
483
  this.attemptReconnect();
64
484
  };
65
- } catch (error) {
485
+ this.disposables.add(disposableListener(this.ws, "close", closeHandler));
486
+ this.ws.onopen = () => {
487
+ this.state = "connected";
488
+ this.reconnectAttempts = 0;
489
+ if (this.reconnectDisposable) {
490
+ this.reconnectDisposable.dispose();
491
+ this.reconnectDisposable = null;
492
+ }
493
+ this.sendHello();
494
+ this.connectionCallbacks.forEach((cb) => cb());
495
+ resolve(Ok(undefined));
496
+ };
497
+ } catch (e) {
66
498
  this.state = "error";
67
- reject(error);
499
+ const error = new ConnectionError(this.url, e);
500
+ resolve(Err(error));
68
501
  }
69
502
  });
70
503
  }
504
+ sendHello() {
505
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
506
+ return;
507
+ const hello = {
508
+ type: "hello",
509
+ sessionId: this.currentSessionId ?? this.sessionOptions?.id,
510
+ props: this.sessionOptions?.props
511
+ };
512
+ this.ws.send(JSON.stringify(hello));
513
+ }
71
514
  disconnect() {
72
- if (this.reconnectTimer) {
73
- clearTimeout(this.reconnectTimer);
74
- this.reconnectTimer = null;
515
+ if (this.reconnectDisposable) {
516
+ this.reconnectDisposable.dispose();
517
+ this.reconnectDisposable = null;
75
518
  }
76
519
  if (this.ws) {
77
- this.ws.close();
520
+ if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
521
+ this.ws.close();
522
+ }
78
523
  this.ws = null;
79
524
  }
80
525
  this.state = "disconnected";
81
526
  }
527
+ dispose() {
528
+ this.disconnect();
529
+ this.disposables.dispose();
530
+ }
82
531
  dispatchAction(action, payload) {
83
532
  if (this.state !== "connected" || !this.ws) {
84
533
  console.warn("Cannot dispatch action: not connected");
@@ -112,6 +561,14 @@ class RemoteEngine {
112
561
  this.errorCallbacks.push(callback);
113
562
  return this;
114
563
  }
564
+ onSessionEstablished(callback) {
565
+ this.sessionEstablishedCallbacks.push(callback);
566
+ return this;
567
+ }
568
+ onSessionExpired(callback) {
569
+ this.sessionExpiredCallbacks.push(callback);
570
+ return this;
571
+ }
115
572
  getConnectionState() {
116
573
  return this.state;
117
574
  }
@@ -121,10 +578,19 @@ class RemoteEngine {
121
578
  getRevision() {
122
579
  return this.currentRevision;
123
580
  }
581
+ getSessionId() {
582
+ return this.currentSessionId;
583
+ }
124
584
  handleMessage(data) {
125
585
  try {
126
586
  const message = JSON.parse(data);
127
587
  switch (message.type) {
588
+ case "sessionAck":
589
+ this.handleSessionAck(message);
590
+ break;
591
+ case "sessionExpired":
592
+ this.handleSessionExpired(message);
593
+ break;
128
594
  case "initialTree":
129
595
  this.handleInitialTree(message);
130
596
  break;
@@ -133,14 +599,28 @@ class RemoteEngine {
133
599
  break;
134
600
  case "stateUpdate":
135
601
  this.currentState = message.state;
136
- this.stateCallbacks.forEach((cb) => cb(message.state));
602
+ this.stateCallbacks.forEach((cb) => cb(this.currentState));
137
603
  break;
138
604
  }
139
- } catch (error) {
140
- console.error("Error handling remote message:", error);
141
- this.errorCallbacks.forEach((cb) => cb(error instanceof Error ? error : new Error(String(error))));
605
+ } catch (e) {
606
+ console.error("Error handling remote message:", e);
607
+ const error = e instanceof Error ? e : new Error(String(e));
608
+ this.errorCallbacks.forEach((cb) => cb(error));
142
609
  }
143
610
  }
611
+ handleSessionAck(message) {
612
+ this.currentSessionId = message.sessionId;
613
+ const info = {
614
+ sessionId: message.sessionId,
615
+ isNew: message.isNew,
616
+ isRestored: message.isRestored
617
+ };
618
+ this.sessionEstablishedCallbacks.forEach((cb) => cb(info));
619
+ }
620
+ handleSessionExpired(message) {
621
+ this.currentSessionId = null;
622
+ this.sessionExpiredCallbacks.forEach((cb) => cb(message.reason));
623
+ }
144
624
  handleInitialTree(message) {
145
625
  this.moduleName = message.module;
146
626
  this.currentState = message.state;
@@ -164,15 +644,25 @@ class RemoteEngine {
164
644
  if (!this.options.autoReconnect) {
165
645
  return;
166
646
  }
167
- if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
168
- console.error("Max reconnection attempts reached");
169
- return;
170
- }
171
- this.reconnectAttempts++;
172
- console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})...`);
173
- this.reconnectTimer = setTimeout(() => {
174
- this.connect().catch((error) => {
175
- console.error("Reconnection failed:", error);
647
+ this.reconnectDisposable = disposableTimeout(() => {
648
+ this.reconnectDisposable = null;
649
+ retry(async () => {
650
+ const result = await this.connect();
651
+ if (!result.ok) {
652
+ throw result.error;
653
+ }
654
+ }, {
655
+ maxAttempts: this.options.maxReconnectAttempts,
656
+ delayMs: this.options.reconnectInterval,
657
+ backoff: "exponential",
658
+ maxDelayMs: 30000,
659
+ jitter: 0.1,
660
+ onRetry: (attempt, error) => {
661
+ console.log(`Reconnection attempt ${attempt}/${this.options.maxReconnectAttempts} failed: ${error.message}`);
662
+ }
663
+ }).catch((error) => {
664
+ console.error("Max reconnection attempts reached:", error.message);
665
+ this.errorCallbacks.forEach((cb) => cb(new ConnectionError(this.url, error, this.options.maxReconnectAttempts)));
176
666
  });
177
667
  }, this.options.reconnectInterval);
178
668
  }
@@ -181,4 +671,4 @@ export {
181
671
  RemoteEngine
182
672
  };
183
673
 
184
- //# debugId=F4162E97D225BE4664756E2164756E21
674
+ //# debugId=B73E531E82606EFA64756E2164756E21