UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

146 lines (144 loc) 3.88 kB
import { YMap } from "../../chunks/chunk-OYP4EJOA.js"; import "../../chunks/chunk-O6EXLFU2.js"; import "../../chunks/chunk-U5RRZUYZ.js"; // src/core/shape/UnionShape.ts import { Hint } from "../Hint.js"; import { createId } from "../Id.js"; import { entries, fromEntries } from "../util/Objects.js"; import { RecordShape } from "./RecordShape.js"; import { ScalarShape } from "./ScalarShape.js"; var UnionShape = class { constructor(label, shapes, initialValue, postProcess) { this.label = label; this.initialValue = initialValue; this.postProcess = postProcess; this.shapes = fromEntries( entries(shapes).map(([key, type]) => { return [ key, new RecordShape(label, { id: new ScalarShape("Id"), type: new ScalarShape("Type"), ...type.properties }) ]; }) ); } shapes; innerTypes(parents) { return entries(this.shapes).flatMap(([name, shape]) => { const info = { name, shape, parents }; const inner = shape.innerTypes(parents.concat(name)); if (Hint.isDefinitionName(name)) return [info, ...inner]; return inner; }); } create() { return this.initialValue ?? {}; } typeOfChild(yValue, child) { const type = yValue && yValue.get("type"); const shape = type && this.shapes[type]; if (shape) return shape.typeOfChild(yValue, child); throw new Error(`Could not determine type of child "${child}"`); } toY(value) { if (Array.isArray(value)) value = value[0] ?? {}; else value = value ?? {}; const type = value.type; const shape = this.shapes[type]; const self = value || {}; const map = new YMap(); map.set("type", type); map.set("id", value.id || createId()); if (!shape) return map; for (const [key, field] of entries(shape.properties)) { map.set(key, field.toY(self[key])); } return map; } fromY(map) { if (!map || typeof map.get !== "function") return {}; const type = map.get("type"); const recordType = this.shapes[type]; if (recordType) return recordType.fromY(map); return {}; } applyY(value, parent, key) { const current = parent.get(key); if (!current || !value) return void parent.set(key, this.toY(value)); const currentType = current.get("type"); if (currentType !== value.type) return void parent.set(key, this.toY(value)); const shape = this.shapes[currentType]; if (!shape) return; shape.applyY(value, parent, key); } init(parent, key) { if (!parent.has(key)) parent.set(key, this.toY(this.create())); } watch(parent, key) { return (fun) => { const observe = (event) => { if (event.keysChanged.has(key)) fun(); }; parent.observe(observe); return () => parent.unobserve(observe); }; } mutator(parent, key, readOnly) { return { replace: (v) => { if (readOnly) return; if (!v) parent.set(key, null); else parent.set(key, this.toY(v)); }, set: (k, v) => { if (readOnly) return; const record = parent.get(key); const type = record.get("type"); const shape = this.shapes[type]; if (!shape) throw new Error(`Could not find type "${type}"`); record.set(k, shape.toY(v)); } }; } async applyLinks(value, loader) { if (!value) return; const type = value.type; if (!type) return; const shape = this.shapes[type]; if (!shape) return; const tasks = []; if (shape) tasks.push(shape.applyLinks(value, loader)); await Promise.all(tasks); if (this.postProcess) await this.postProcess(value, loader); } }; export { UnionShape };