UNPKG

@reclaimprotocol/attestor-core

Version:

<div> <div> <img src="https://raw.githubusercontent.com/reclaimprotocol/.github/main/assets/banners/Attestor-Core.png" /> </div> </div>

129 lines 8.03 kB
"use strict"; /** * Connection state machine for managing atomic state transitions. * Prevents race conditions in connection state management. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ConnectionStateMachine = exports.ConnectionState = void 0; var ConnectionState; (function (ConnectionState) { ConnectionState["CONNECTING"] = "connecting"; ConnectionState["CONNECTED"] = "connected"; ConnectionState["CLOSING"] = "closing"; ConnectionState["CLOSED"] = "closed"; })(ConnectionState || (exports.ConnectionState = ConnectionState = {})); class ConnectionStateMachine { constructor(initialState = ConnectionState.CONNECTING) { this.listeners = []; this.transitionLock = null; this.currentState = initialState; } /** * Get current state. */ getState() { return this.currentState; } /** * Check if the connection is in any of the specified states. */ isInState(...states) { return states.includes(this.currentState); } /** * Register a state change listener. */ onStateChange(listener) { this.listeners.push(listener); return () => { const index = this.listeners.indexOf(listener); if (index >= 0) { this.listeners.splice(index, 1); } }; } /** * Attempt to transition from allowed states to a new state. * @param fromStates Allowed states to transition from * @param toState Target state * @param action Optional action to execute during transition * @returns Promise that resolves to true if transition succeeded */ async transition(fromStates, toState, action) { // Wait for any existing transition to complete if (this.transitionLock) { await this.transitionLock.catch(() => { // Ignore errors from previous transitions }); } // Create a new transition lock let resolve; let reject; this.transitionLock = new Promise((res, rej) => { resolve = res; reject = rej; }); try { const allowedStates = Array.isArray(fromStates) ? fromStates : [fromStates]; // Check if transition is allowed if (!allowedStates.includes(this.currentState)) { resolve(); return false; } // If already in target state, no need to transition if (this.currentState === toState) { resolve(); return true; } const oldState = this.currentState; // Execute action if provided if (action) { await action(); } // Update state this.currentState = toState; // Notify listeners for (const listener of this.listeners) { try { listener(oldState, toState); } catch (error) { // Don't let listener errors break the state machine console.error('Error in state change listener:', error); } } resolve(); return true; } catch (error) { reject(error); throw error; } finally { // Clear the transition lock this.transitionLock = null; } } /** * Force a state change without checking allowed transitions. * Use with caution - mainly for error recovery. */ async forceState(newState) { if (this.transitionLock) { await this.transitionLock.catch(() => { }); } const oldState = this.currentState; this.currentState = newState; // Notify listeners for (const listener of this.listeners) { try { listener(oldState, newState); } catch (error) { console.error('Error in state change listener:', error); } } } } exports.ConnectionStateMachine = ConnectionStateMachine; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi1zdGF0ZS1tYWNoaW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2Nvbm5lY3Rpb24tc3RhdGUtbWFjaGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7QUFFSCxJQUFZLGVBS1g7QUFMRCxXQUFZLGVBQWU7SUFDMUIsNENBQXlCLENBQUE7SUFDekIsMENBQXVCLENBQUE7SUFDdkIsc0NBQW1CLENBQUE7SUFDbkIsb0NBQWlCLENBQUE7QUFDbEIsQ0FBQyxFQUxXLGVBQWUsK0JBQWYsZUFBZSxRQUsxQjtBQUlELE1BQWEsc0JBQXNCO0lBS2xDLFlBQVksZUFBZ0MsZUFBZSxDQUFDLFVBQVU7UUFIOUQsY0FBUyxHQUEwQixFQUFFLENBQUE7UUFDckMsbUJBQWMsR0FBeUIsSUFBSSxDQUFBO1FBR2xELElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFBO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDUCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUE7SUFDekIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLEdBQUcsTUFBeUI7UUFDckMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUMxQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLENBQUMsUUFBNkI7UUFDMUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDN0IsT0FBTyxHQUFHLEVBQUU7WUFDWCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUM5QyxJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBQ2hDLENBQUM7UUFD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