@platform/cell.typesystem
Version:
The 'strongly typed sheets' system of the CellOS.
97 lines (96 loc) • 2.89 kB
JavaScript
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();