UNPKG

ts-raii-scope

Version:
96 lines (95 loc) 3.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const raiiScope_1 = require("./raiiScope"); class ScopeStack { constructor() { this._syncStack = []; // key: scope, value: was saved by client this._asyncScopes = new Map(); } enterScope(isAsync, scope) { if (!scope) { scope = new raiiScope_1.RaiiScope(); } else if (this.findSyncStackIndex(scope) !== -1) { throw new Error('Scope is already in stack'); } else if (this._asyncScopes.has(scope)) { throw new Error('Scope is already in async scopes set'); } this._syncStack.push(scope); if (isAsync) { this._asyncScopes.set(scope, false); } return scope; } exitScope(scope) { const syncIndex = this.findSyncStackIndex(scope); if (syncIndex === -1) { throw new Error('Scope is not in stack'); } const scopesAbove = this._syncStack.length - 1 - syncIndex; if (scopesAbove > 0) { throw new Error(`Can't exit scope because there are ${scopesAbove} scopes above.`); } this._syncStack.splice(syncIndex, 1); const asyncScopeSaved = this._asyncScopes.get(scope); if (asyncScopeSaved === false) { console.warn('Async scope exited not being saved in method'); } if (asyncScopeSaved === undefined) { return scope.dispose(); } } // noinspection JSUnusedGlobalSymbols asyncScopeDone(scope) { const syncIndex = this.findSyncStackIndex(scope); if (syncIndex !== -1) { throw new Error('Scope from sync stack passed as async'); } if (!this._asyncScopes.has(scope)) { throw new Error('Async scope not found'); } this._asyncScopes.delete(scope); return scope.dispose(); } // noinspection JSUnusedGlobalSymbols /** * Call from sync methods */ pushToTopScope(resource) { const topScope = this.getTopScope(); if (this._asyncScopes.has(topScope)) { throw new Error('In order to push to async scope, save it using saveCurrentAsyncScope() ' + 'in your method variable and push resources to it'); } return topScope.push(resource); } // noinspection JSUnusedGlobalSymbols /** * Call inside async method to keep scope in local variable */ saveCurrentAsyncScope() { const scope = this.getTopScope(); if (!this._asyncScopes.has(scope)) { throw new Error('Current scope is not async'); } this._asyncScopes.set(scope, true); return scope; } getTopScope() { if (this._syncStack.length > 0) { return this._syncStack[this._syncStack.length - 1]; } throw new Error('Sync scopes stack is empty'); } findSyncStackIndex(scope) { for (let i = this._syncStack.length - 1; i >= 0; --i) { if (this._syncStack[i] === scope) { return i; } } return -1; } } exports.scopeStack = new ScopeStack();