@pelican-identity/auth-core 1.2.10 → 1.2.11
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/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -0
- package/dist/engine/engine.d.ts +38 -0
- package/dist/engine/engine.d.ts.map +1 -0
- package/dist/engine/engine.js +285 -0
- package/dist/engine/engine.js.map +1 -0
- package/dist/index.d.mts +17 -6
- package/dist/index.d.ts +17 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +222 -124
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +222 -124
- package/dist/index.mjs.map +1 -1
- package/dist/utilities/transport.d.ts +26 -0
- package/dist/utilities/transport.d.ts.map +1 -0
- package/dist/utilities/transport.js +111 -0
- package/dist/utilities/transport.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -188,16 +188,32 @@ var StateMachine = class {
|
|
|
188
188
|
var Transport = class {
|
|
189
189
|
constructor(handlers) {
|
|
190
190
|
this.reconnectAttempts = 0;
|
|
191
|
-
this.maxReconnectAttempts =
|
|
191
|
+
this.maxReconnectAttempts = 3;
|
|
192
|
+
// Reduced from 5 for mobile
|
|
192
193
|
this.isExplicitlyClosed = false;
|
|
194
|
+
this.isReconnecting = false;
|
|
193
195
|
this.handlers = handlers;
|
|
194
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Establish WebSocket connection
|
|
199
|
+
* @param url - WebSocket URL
|
|
200
|
+
*/
|
|
195
201
|
connect(url) {
|
|
196
202
|
this.url = url;
|
|
197
203
|
this.isExplicitlyClosed = false;
|
|
204
|
+
if (this.socket) {
|
|
205
|
+
this.socket.onclose = null;
|
|
206
|
+
this.socket.onerror = null;
|
|
207
|
+
this.socket.onmessage = null;
|
|
208
|
+
this.socket.onopen = null;
|
|
209
|
+
if (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING) {
|
|
210
|
+
this.socket.close();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
198
213
|
this.socket = new WebSocket(url);
|
|
199
214
|
this.socket.onopen = () => {
|
|
200
215
|
this.reconnectAttempts = 0;
|
|
216
|
+
this.isReconnecting = false;
|
|
201
217
|
this.handlers.onOpen?.();
|
|
202
218
|
};
|
|
203
219
|
this.socket.onmessage = (e) => {
|
|
@@ -205,43 +221,103 @@ var Transport = class {
|
|
|
205
221
|
const data = JSON.parse(e.data);
|
|
206
222
|
this.handlers.onMessage?.(data);
|
|
207
223
|
} catch (err) {
|
|
208
|
-
console.error("Failed to parse message", err);
|
|
224
|
+
console.error("Failed to parse WebSocket message", err);
|
|
209
225
|
}
|
|
210
226
|
};
|
|
211
227
|
this.socket.onerror = (e) => {
|
|
212
|
-
this.
|
|
228
|
+
if (!this.isReconnecting && !this.isExplicitlyClosed) {
|
|
229
|
+
this.handlers.onError?.(e);
|
|
230
|
+
}
|
|
213
231
|
};
|
|
214
232
|
this.socket.onclose = (e) => {
|
|
215
|
-
this.
|
|
216
|
-
|
|
233
|
+
if (this.reconnectTimeout) {
|
|
234
|
+
clearTimeout(this.reconnectTimeout);
|
|
235
|
+
this.reconnectTimeout = void 0;
|
|
236
|
+
}
|
|
237
|
+
if (!this.isReconnecting) {
|
|
238
|
+
this.handlers.onClose?.(e);
|
|
239
|
+
}
|
|
240
|
+
if (!this.isExplicitlyClosed && !this.isReconnecting && this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
217
241
|
this.attemptReconnect();
|
|
218
242
|
}
|
|
219
243
|
};
|
|
220
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Attempt to reconnect with exponential backoff
|
|
247
|
+
*/
|
|
221
248
|
attemptReconnect() {
|
|
222
249
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
223
|
-
console.
|
|
250
|
+
console.warn("Max WebSocket reconnect attempts reached");
|
|
224
251
|
return;
|
|
225
252
|
}
|
|
253
|
+
this.isReconnecting = true;
|
|
226
254
|
this.reconnectAttempts++;
|
|
227
|
-
const delay = Math.pow(2, this.reconnectAttempts) * 500;
|
|
228
|
-
|
|
229
|
-
|
|
255
|
+
const delay = Math.min(Math.pow(2, this.reconnectAttempts - 1) * 500, 2e3);
|
|
256
|
+
console.log(
|
|
257
|
+
`Reconnecting WebSocket (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}) in ${delay}ms...`
|
|
258
|
+
);
|
|
259
|
+
this.reconnectTimeout = window.setTimeout(() => {
|
|
260
|
+
if (this.url && !this.isExplicitlyClosed) {
|
|
261
|
+
this.connect(this.url);
|
|
262
|
+
}
|
|
230
263
|
}, delay);
|
|
231
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Send a message through the WebSocket
|
|
267
|
+
* Queues message if connection is not open
|
|
268
|
+
*/
|
|
232
269
|
send(payload) {
|
|
233
270
|
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
234
|
-
|
|
271
|
+
try {
|
|
272
|
+
this.socket.send(JSON.stringify(payload));
|
|
273
|
+
} catch (err) {
|
|
274
|
+
console.error("Failed to send WebSocket message:", err);
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
console.warn(
|
|
278
|
+
"WebSocket not open, message not sent:",
|
|
279
|
+
this.socket?.readyState
|
|
280
|
+
);
|
|
235
281
|
}
|
|
236
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Close the WebSocket connection
|
|
285
|
+
* Prevents automatic reconnection
|
|
286
|
+
*/
|
|
237
287
|
close() {
|
|
238
288
|
this.isExplicitlyClosed = true;
|
|
239
|
-
this.
|
|
289
|
+
this.isReconnecting = false;
|
|
290
|
+
if (this.reconnectTimeout) {
|
|
291
|
+
clearTimeout(this.reconnectTimeout);
|
|
292
|
+
this.reconnectTimeout = void 0;
|
|
293
|
+
}
|
|
294
|
+
if (this.socket) {
|
|
295
|
+
this.socket.onclose = null;
|
|
296
|
+
this.socket.onerror = null;
|
|
297
|
+
this.socket.onmessage = null;
|
|
298
|
+
this.socket.onopen = null;
|
|
299
|
+
if (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING) {
|
|
300
|
+
this.socket.close();
|
|
301
|
+
}
|
|
302
|
+
this.socket = void 0;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Get current connection state
|
|
307
|
+
*/
|
|
308
|
+
get readyState() {
|
|
309
|
+
return this.socket?.readyState;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Check if connection is open
|
|
313
|
+
*/
|
|
314
|
+
get isOpen() {
|
|
315
|
+
return this.socket?.readyState === WebSocket.OPEN;
|
|
240
316
|
}
|
|
241
317
|
};
|
|
242
318
|
|
|
243
319
|
// src/constants.ts
|
|
244
|
-
var BASEURL = "
|
|
320
|
+
var BASEURL = "http://192.168.1.9:8080";
|
|
245
321
|
|
|
246
322
|
// src/engine/engine.ts
|
|
247
323
|
var PelicanAuthentication = class {
|
|
@@ -250,6 +326,7 @@ var PelicanAuthentication = class {
|
|
|
250
326
|
this.stateMachine = new StateMachine();
|
|
251
327
|
this.sessionId = "";
|
|
252
328
|
this.sessionKey = null;
|
|
329
|
+
this.useWebSocket = true;
|
|
253
330
|
this.listeners = {};
|
|
254
331
|
if (!config.publicKey) throw new Error("Missing publicKey");
|
|
255
332
|
if (!config.projectId) throw new Error("Missing projectId");
|
|
@@ -262,104 +339,67 @@ var PelicanAuthentication = class {
|
|
|
262
339
|
this.stateMachine.subscribe((s) => this.emit("state", s));
|
|
263
340
|
this.attachVisibilityRecovery();
|
|
264
341
|
}
|
|
265
|
-
/* --------------------
|
|
266
|
-
/**
|
|
267
|
-
* Subscribe to SDK events (qr, deeplink, success, error, state)
|
|
268
|
-
* @returns Unsubscribe function
|
|
269
|
-
*/
|
|
342
|
+
/* -------------------- Public API -------------------- */
|
|
270
343
|
on(event, cb) {
|
|
271
344
|
var _a;
|
|
272
345
|
(_a = this.listeners)[event] ?? (_a[event] = /* @__PURE__ */ new Set());
|
|
273
346
|
this.listeners[event].add(cb);
|
|
274
347
|
return () => this.listeners[event].delete(cb);
|
|
275
348
|
}
|
|
276
|
-
/**
|
|
277
|
-
* Initializes the authentication flow.
|
|
278
|
-
* Fetches a relay, establishes a WebSocket, and generates the E2EE session key.
|
|
279
|
-
*/
|
|
280
349
|
async start() {
|
|
281
350
|
if (this.stateMachine.current !== "idle") return;
|
|
282
351
|
this.resetSession();
|
|
283
352
|
clearAuthSession();
|
|
284
353
|
this.stateMachine.transition("initializing");
|
|
285
354
|
try {
|
|
286
|
-
const relay = await this.fetchRelayUrl();
|
|
287
355
|
this.sessionKey = this.crypto.generateSymmetricKey();
|
|
288
356
|
this.sessionId = crypto.randomUUID() + crypto.randomUUID();
|
|
289
|
-
this.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
});
|
|
296
|
-
this.stateMachine.transition("awaiting-pair");
|
|
297
|
-
},
|
|
298
|
-
onMessage: (msg) => this.handleMessage(msg),
|
|
299
|
-
onError: () => this.fail(new Error("WebSocket connection failed"))
|
|
300
|
-
});
|
|
301
|
-
this.transport.connect(relay);
|
|
302
|
-
await this.emitEntryPoint();
|
|
357
|
+
this.useWebSocket = this.shouldUseWebSocket();
|
|
358
|
+
if (this.useWebSocket) {
|
|
359
|
+
await this.startWebSocketFlow();
|
|
360
|
+
} else {
|
|
361
|
+
await this.startDeepLinkFlow();
|
|
362
|
+
}
|
|
303
363
|
} catch (err) {
|
|
304
364
|
this.fail(err instanceof Error ? err : new Error("Start failed"));
|
|
305
365
|
}
|
|
306
366
|
}
|
|
307
|
-
/**
|
|
308
|
-
* Manually stops the authentication process and closes connections.
|
|
309
|
-
*/
|
|
310
367
|
stop() {
|
|
311
368
|
this.terminate(false);
|
|
312
369
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
);
|
|
320
|
-
if (!res.ok) {
|
|
321
|
-
const error = await res.text();
|
|
322
|
-
throw new Error(error);
|
|
323
|
-
}
|
|
324
|
-
const json = await res.json();
|
|
325
|
-
return json.relay_url;
|
|
370
|
+
destroy() {
|
|
371
|
+
this.detachVisibilityRecovery();
|
|
372
|
+
this.clearBackupCheck();
|
|
373
|
+
this.transport?.close();
|
|
374
|
+
this.transport = void 0;
|
|
375
|
+
this.listeners = {};
|
|
326
376
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
)
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
);
|
|
352
|
-
} else {
|
|
353
|
-
const qr = await QRCode__default.default.toDataURL(JSON.stringify(payload), {
|
|
354
|
-
type: "image/png",
|
|
355
|
-
scale: 3,
|
|
356
|
-
color: { light: "#ffffff", dark: "#424242ff" }
|
|
357
|
-
});
|
|
358
|
-
this.emit("qr", qr);
|
|
359
|
-
}
|
|
377
|
+
/* -------------------- Flow Selection -------------------- */
|
|
378
|
+
shouldUseWebSocket() {
|
|
379
|
+
return this.config.forceQRCode || !/Android|iPhone|iPad/i.test(navigator.userAgent);
|
|
380
|
+
}
|
|
381
|
+
/* -------------------- WebSocket Flow (QR Code) -------------------- */
|
|
382
|
+
async startWebSocketFlow() {
|
|
383
|
+
const relay = await this.fetchRelayUrl();
|
|
384
|
+
this.transport = new Transport({
|
|
385
|
+
onOpen: () => {
|
|
386
|
+
this.transport.send({
|
|
387
|
+
type: "register",
|
|
388
|
+
sessionID: this.sessionId,
|
|
389
|
+
...this.config
|
|
390
|
+
});
|
|
391
|
+
this.stateMachine.transition("awaiting-pair");
|
|
392
|
+
},
|
|
393
|
+
onMessage: (msg) => this.handleWebSocketMessage(msg),
|
|
394
|
+
onError: (err) => {
|
|
395
|
+
console.error("WebSocket error:", err);
|
|
396
|
+
this.fail(new Error("WebSocket connection failed"));
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
this.transport.connect(relay);
|
|
400
|
+
await this.emitQRCode();
|
|
360
401
|
}
|
|
361
|
-
|
|
362
|
-
handleMessage(msg) {
|
|
402
|
+
handleWebSocketMessage(msg) {
|
|
363
403
|
switch (msg.type) {
|
|
364
404
|
case "paired":
|
|
365
405
|
this.stateMachine.transition("paired");
|
|
@@ -374,7 +414,7 @@ var PelicanAuthentication = class {
|
|
|
374
414
|
this.handleAuthSuccess(msg);
|
|
375
415
|
return;
|
|
376
416
|
case "phone-terminated":
|
|
377
|
-
this.fail(new Error("
|
|
417
|
+
this.fail(new Error("Authentication cancelled on device"));
|
|
378
418
|
this.restartIfContinuous();
|
|
379
419
|
return;
|
|
380
420
|
case "confirmed":
|
|
@@ -383,9 +423,6 @@ var PelicanAuthentication = class {
|
|
|
383
423
|
return;
|
|
384
424
|
}
|
|
385
425
|
}
|
|
386
|
-
/**
|
|
387
|
-
* Decrypts the identity payload received from the phone using the session key.
|
|
388
|
-
*/
|
|
389
426
|
handleAuthSuccess(msg) {
|
|
390
427
|
if (!this.sessionKey || !msg.cipher || !msg.nonce) {
|
|
391
428
|
this.fail(new Error("Invalid authentication payload"));
|
|
@@ -414,40 +451,89 @@ var PelicanAuthentication = class {
|
|
|
414
451
|
this.restartIfContinuous();
|
|
415
452
|
}
|
|
416
453
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
454
|
+
/* -------------------- Deep Link Flow (Mobile) -------------------- */
|
|
455
|
+
async startDeepLinkFlow() {
|
|
456
|
+
await this.fetchRelayUrl();
|
|
457
|
+
if (this.sessionKey) {
|
|
458
|
+
storeAuthSession(this.sessionId, this.sessionKey, 10 * 6e4);
|
|
459
|
+
}
|
|
460
|
+
await this.emitDeepLink();
|
|
461
|
+
this.stateMachine.transition("awaiting-pair");
|
|
462
|
+
}
|
|
463
|
+
clearBackupCheck() {
|
|
464
|
+
if (this.backupCheckTimeout) {
|
|
465
|
+
clearTimeout(this.backupCheckTimeout);
|
|
466
|
+
this.backupCheckTimeout = void 0;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
async checkSession() {
|
|
470
|
+
const cached = getAuthSession();
|
|
471
|
+
if (!cached) return;
|
|
472
|
+
this.stateMachine.transition("awaiting-auth");
|
|
422
473
|
try {
|
|
423
474
|
const res = await fetch(
|
|
424
475
|
`${BASEURL}/session?session_id=${cached.sessionId}`
|
|
425
476
|
);
|
|
426
|
-
if (!res.ok)
|
|
477
|
+
if (!res.ok) return;
|
|
427
478
|
const data = await res.json();
|
|
428
479
|
const decrypted = this.crypto.decryptSymmetric({
|
|
429
480
|
encrypted: { cipher: data.cipher, nonce: data.nonce },
|
|
430
481
|
keyString: cached.sessionKey
|
|
431
482
|
});
|
|
432
483
|
if (!decrypted) {
|
|
433
|
-
|
|
434
|
-
this.restartIfContinuous();
|
|
484
|
+
console.warn("Failed to decrypt session");
|
|
435
485
|
return;
|
|
436
486
|
}
|
|
437
487
|
const result = JSON.parse(decrypted);
|
|
438
|
-
this.
|
|
488
|
+
this.clearBackupCheck();
|
|
439
489
|
clearAuthSession();
|
|
440
|
-
|
|
441
|
-
this.
|
|
442
|
-
this.
|
|
490
|
+
this.emit("success", result);
|
|
491
|
+
this.stateMachine.transition("authenticated");
|
|
492
|
+
if (this.config.continuousMode) {
|
|
493
|
+
setTimeout(() => {
|
|
494
|
+
this.stateMachine.transition("confirmed");
|
|
495
|
+
this.start();
|
|
496
|
+
}, 1500);
|
|
497
|
+
} else {
|
|
498
|
+
this.stateMachine.transition("confirmed");
|
|
499
|
+
}
|
|
500
|
+
} catch (err) {
|
|
501
|
+
console.debug("Session check failed:", err);
|
|
443
502
|
}
|
|
444
503
|
}
|
|
504
|
+
/* -------------------- Entry Point Generation -------------------- */
|
|
505
|
+
async emitQRCode() {
|
|
506
|
+
const payload = {
|
|
507
|
+
sessionID: this.sessionId,
|
|
508
|
+
sessionKey: this.sessionKey,
|
|
509
|
+
publicKey: this.config.publicKey,
|
|
510
|
+
authType: this.config.authType,
|
|
511
|
+
projectId: this.config.projectId,
|
|
512
|
+
url: window.location.href
|
|
513
|
+
};
|
|
514
|
+
const qr = await QRCode__default.default.toDataURL(JSON.stringify(payload), {
|
|
515
|
+
type: "image/png",
|
|
516
|
+
scale: 3,
|
|
517
|
+
color: { light: "#ffffff", dark: "#424242ff" }
|
|
518
|
+
});
|
|
519
|
+
this.emit("qr", qr);
|
|
520
|
+
}
|
|
521
|
+
async emitDeepLink() {
|
|
522
|
+
const deeplink = `pelicanvault://auth/deep-link?sessionID=${encodeURIComponent(
|
|
523
|
+
this.sessionId
|
|
524
|
+
)}&sessionKey=${encodeURIComponent(
|
|
525
|
+
this.sessionKey
|
|
526
|
+
)}&publicKey=${encodeURIComponent(this.config.publicKey)}&authType=${this.config.authType}&projectId=${encodeURIComponent(
|
|
527
|
+
this.config.projectId
|
|
528
|
+
)}&url=${encodeURIComponent(window.location.href)}`;
|
|
529
|
+
this.emit("deeplink", deeplink);
|
|
530
|
+
}
|
|
531
|
+
/* -------------------- Visibility Recovery -------------------- */
|
|
445
532
|
attachVisibilityRecovery() {
|
|
446
533
|
this.visibilityHandler = async () => {
|
|
447
534
|
if (document.visibilityState !== "visible") return;
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
await this.getCachedEntry(cached);
|
|
535
|
+
if (this.useWebSocket) return;
|
|
536
|
+
await this.checkSession();
|
|
451
537
|
};
|
|
452
538
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
453
539
|
}
|
|
@@ -457,18 +543,34 @@ var PelicanAuthentication = class {
|
|
|
457
543
|
this.visibilityHandler = void 0;
|
|
458
544
|
}
|
|
459
545
|
}
|
|
460
|
-
|
|
546
|
+
/* -------------------- Helpers -------------------- */
|
|
547
|
+
async fetchRelayUrl() {
|
|
548
|
+
const { publicKey, projectId, authType } = this.config;
|
|
549
|
+
const res = await fetch(
|
|
550
|
+
`${BASEURL}/relay?public_key=${publicKey}&auth_type=${authType}&project_id=${projectId}`
|
|
551
|
+
);
|
|
552
|
+
if (!res.ok) {
|
|
553
|
+
const error = await res.text();
|
|
554
|
+
throw new Error(error);
|
|
555
|
+
}
|
|
556
|
+
const json = await res.json();
|
|
557
|
+
return json.relay_url;
|
|
558
|
+
}
|
|
461
559
|
terminate(success) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
560
|
+
this.clearBackupCheck();
|
|
561
|
+
if (this.transport) {
|
|
562
|
+
if (!success) {
|
|
563
|
+
this.transport.send({
|
|
564
|
+
type: "client-terminated",
|
|
565
|
+
sessionID: this.sessionId,
|
|
566
|
+
projectId: this.config.projectId,
|
|
567
|
+
publicKey: this.config.publicKey,
|
|
568
|
+
authType: this.config.authType
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
this.transport.close();
|
|
572
|
+
this.transport = void 0;
|
|
470
573
|
}
|
|
471
|
-
this.transport?.close();
|
|
472
574
|
clearAuthSession();
|
|
473
575
|
this.resetSession();
|
|
474
576
|
if (!this.config.continuousMode) {
|
|
@@ -477,9 +579,11 @@ var PelicanAuthentication = class {
|
|
|
477
579
|
this.stateMachine.transition(success ? "confirmed" : "idle");
|
|
478
580
|
}
|
|
479
581
|
restartIfContinuous() {
|
|
480
|
-
this.stateMachine.transition("idle");
|
|
481
|
-
this.transport?.close();
|
|
482
582
|
if (!this.config.continuousMode) return;
|
|
583
|
+
this.clearBackupCheck();
|
|
584
|
+
this.transport?.close();
|
|
585
|
+
this.transport = void 0;
|
|
586
|
+
this.stateMachine.transition("idle");
|
|
483
587
|
setTimeout(() => {
|
|
484
588
|
this.start();
|
|
485
589
|
}, 150);
|
|
@@ -488,12 +592,6 @@ var PelicanAuthentication = class {
|
|
|
488
592
|
this.sessionId = "";
|
|
489
593
|
this.sessionKey = null;
|
|
490
594
|
}
|
|
491
|
-
/** Completely destroys the instance and removes all listeners */
|
|
492
|
-
destroy() {
|
|
493
|
-
this.detachVisibilityRecovery();
|
|
494
|
-
this.transport?.close();
|
|
495
|
-
this.listeners = {};
|
|
496
|
-
}
|
|
497
595
|
emit(event, payload) {
|
|
498
596
|
this.listeners[event]?.forEach((cb) => cb(payload));
|
|
499
597
|
}
|