UNPKG

@platform/cell.typesystem

Version:

The 'strongly typed sheets' system of the CellOS.

97 lines (96 loc) 2.89 kB
import { Subject } from 'rxjs'; import { share, take } from 'rxjs/operators'; export class SheetPool { constructor() { this._dispose$ = new Subject(); this._items = {}; this.dispose$ = this._dispose$.pipe(share()); } dispose() { if (!this.isDisposed) { this._dispose$.next(); this._dispose$.complete(); this._items = {}; } } get isDisposed() { return this._dispose$.isStopped; } get count() { return Object.keys(this._items).length; } get sheets() { const items = this._items; return Object.keys(items).reduce((acc, key) => { acc[key] = items[key].sheet; return acc; }, {}); } exists(sheet) { this.throwIfDisposed('exists'); return Boolean(this.sheet(sheet)); } sheet(sheet) { this.throwIfDisposed('sheet'); const ns = this.ns(sheet); const item = this._items[ns]; return item ? item.sheet : undefined; } add(sheet, options = {}) { this.throwIfDisposed('add'); if (this.exists(sheet)) { return this; } const ns = this.ns(sheet); this._items[ns] = { sheet, children: [] }; sheet.dispose$.pipe(take(1)).subscribe(() => this.remove(sheet)); if (options.parent) { const parent = this._items[this.ns(options.parent)]; if (parent && !parent.children.includes(ns)) { parent.children.push(ns); } } return this; } remove(sheet) { this.throwIfDisposed('remove'); const ns = this.ns(sheet); const item = this._items[ns]; delete this._items[ns]; if (item) { item.children.forEach(child => this.remove(child)); } return this; } children(sheet) { this.throwIfDisposed('children'); const build = (sheet, sheets = []) => { const ns = this.ns(sheet); if (!sheets.some(sheet => sheet.toString() === ns)) { const item = this._items[ns]; if (item) { item.children.forEach(ns => { const child = this._items[ns]; if (child) { sheets.push(child.sheet); } build(ns); }); } } return sheets; }; return build(sheet); } throwIfDisposed(action) { if (this.isDisposed) { throw new Error(`Cannot '${action}' because [SheetPool] is disposed.`); } } ns(sheet) { let ns = sheet.toString(); ns = ns.includes(':') ? ns : `ns:${ns}`; return ns; } } SheetPool.create = () => new SheetPool();