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