UNPKG

@platform/cell.typesystem

Version:

The 'strongly typed sheets' system of the CellOS.

80 lines (79 loc) 2.81 kB
import { value, Uri } from '../common'; import { TypeBuilderNs } from './TypeBuilderNs'; import { TypeValue } from '../TypeSystem.core'; export class TypeBuilder { constructor() { this.builders = []; } toObject() { return this.builders.reduce((acc, builder) => { const ns = builder.uri.toString(); acc[ns] = this.toDef(builder); return acc; }, {}); } ns(uri) { uri = Uri.ns(uri); const exists = this.builders.some(ns => ns.uri.toString() === uri.toString()); if (exists) { const err = `The namespace '${uri.toString()}' already exists`; throw new Error(err); } const ns = TypeBuilderNs.create({ uri }); this.builders.push(ns); return ns; } type(typename, options) { const ns = Uri.create.ns(Uri.cuid()); return this.ns(ns).type(typename, options); } formatType(value) { value = (value || '').trim(); if (value.startsWith('/')) { const typename = value.replace(/^\/*/, ''); const singular = TypeValue.trimArray(typename); const match = this.builders.find(ns => ns.types.find(type => type.typename === singular)); if (!match) { const err = `Failed to prefix type '${value}' with namespace. The typename '${typename}' was not found in any of the available namespaces.`; throw new Error(err); } value = `${match.uri.toString()}/${typename}`; } return value; } toDef(ns) { const columns = {}; const getOrCreateObject = (target, key) => { return target[key] ? target[key] : (target[key] = {}); }; const attachDef = (def, column) => { const props = getOrCreateObject(column, 'props'); if (!props.def) { props.def = def; } else { if (!Array.isArray(props.def)) { props.def = [props.def]; } props.def.push(def); } }; ns.types.forEach(type => { const typename = type.typename; type.props .map(prop => prop.toObject()) .forEach(prop => { const def = value.deleteUndefined({ prop: `${typename}.${prop.name}`, type: this.formatType(prop.type), target: prop.target, default: prop.default, }); const column = getOrCreateObject(columns, prop.column); attachDef(def, column); }); }); return { columns }; } } TypeBuilder.create = () => new TypeBuilder();