UNPKG

@bsv/sdk

Version:

BSV Blockchain Software Development Kit

130 lines 5.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SessionManager = void 0; /** * Manages sessions for peers, allowing multiple concurrent sessions * per identity key. Primary lookup is always by `sessionNonce`. */ class SessionManager { constructor() { this.sessionNonceToSession = new Map(); this.identityKeyToNonces = new Map(); } /** * Adds a session to the manager, associating it with its sessionNonce, * and also with its peerIdentityKey (if any). * * This does NOT overwrite existing sessions for the same peerIdentityKey, * allowing multiple concurrent sessions for the same peer. * * @param {PeerSession} session - The peer session to add. */ addSession(session) { if (typeof session.sessionNonce !== 'string') { throw new Error('Invalid session: sessionNonce is required to add a session.'); } // Use the sessionNonce as the primary key this.sessionNonceToSession.set(session.sessionNonce, session); // Also track it by identity key if present if (typeof session.peerIdentityKey === 'string') { let nonces = this.identityKeyToNonces.get(session.peerIdentityKey); if (nonces == null) { nonces = new Set(); this.identityKeyToNonces.set(session.peerIdentityKey, nonces); } nonces.add(session.sessionNonce); } } /** * Updates a session in the manager (primarily by re-adding it), * ensuring we record the latest data (e.g., isAuthenticated, lastUpdate, etc.). * * @param {PeerSession} session - The peer session to update. */ updateSession(session) { // Remove the old references (if any) and re-add this.removeSession(session); this.addSession(session); } /** * Retrieves a session based on a given identifier, which can be: * - A sessionNonce, or * - A peerIdentityKey. * * If it is a `sessionNonce`, returns that exact session. * If it is a `peerIdentityKey`, returns the "best" (e.g. most recently updated, * authenticated) session associated with that peer, if any. * * @param {string} identifier - The identifier for the session (sessionNonce or peerIdentityKey). * @returns {PeerSession | undefined} - The matching peer session, or undefined if not found. */ getSession(identifier) { // Check if this identifier is directly a sessionNonce const direct = this.sessionNonceToSession.get(identifier); if (direct != null) { return direct; } // Otherwise, interpret the identifier as an identity key const nonces = this.identityKeyToNonces.get(identifier); if ((nonces == null) || nonces.size === 0) { return undefined; } // Pick the "best" session. One sensible approach: // - Choose an authenticated session if available // - Among them, pick the most recently updated let best; for (const nonce of nonces) { const s = this.sessionNonceToSession.get(nonce); if (s == null) continue; // We can prefer authenticated sessions if (best == null) { best = s; } else { // If we want the "most recently updated" AND isAuthenticated if ((s.lastUpdate ?? 0) > (best.lastUpdate ?? 0)) { best = s; } } } // Optionally, you could also filter out isAuthenticated===false if you only want // an authenticated session. But for our usage, let's return the latest any session. return best; } /** * Removes a session from the manager by clearing all associated identifiers. * * @param {PeerSession} session - The peer session to remove. */ removeSession(session) { if (typeof session.sessionNonce === 'string') { this.sessionNonceToSession.delete(session.sessionNonce); } if (typeof session.peerIdentityKey === 'string') { const nonces = this.identityKeyToNonces.get(session.peerIdentityKey); if (nonces != null) { nonces.delete(session.sessionNonce ?? ''); if (nonces.size === 0) { this.identityKeyToNonces.delete(session.peerIdentityKey); } } } } /** * Checks if a session exists for a given identifier (either sessionNonce or identityKey). * * @param {string} identifier - The identifier to check. * @returns {boolean} - True if the session exists, false otherwise. */ hasSession(identifier) { const direct = this.sessionNonceToSession.has(identifier); if (direct) return true; // if not directly a nonce, interpret as identityKey const nonces = this.identityKeyToNonces.get(identifier); return !(nonces == null) && nonces.size > 0; } } exports.SessionManager = SessionManager; //# sourceMappingURL=SessionManager.js.map