UNPKG

alinea

Version:
142 lines (140 loc) 4.2 kB
import { YMap } from "../../chunks/chunk-QUIANN6B.js"; import "../../chunks/chunk-AJJSW27C.js"; import "../../chunks/chunk-NZLE2WMY.js"; // src/core/shape/UnionShape.ts import { createId } from "../Id.js"; import { entries, fromEntries } from "../util/Objects.js"; import { RecordShape } from "./RecordShape.js"; import { ScalarShape } from "./ScalarShape.js"; var UnionRow; ((UnionRow2) => { UnionRow2.id = "_id"; UnionRow2.type = "_type"; })(UnionRow || (UnionRow = {})); 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, { [UnionRow.id]: new ScalarShape("Id"), [UnionRow.type]: new ScalarShape("Type"), ...type.shapes }) ]; }) ); } shapes; create() { return this.initialValue ?? {}; } toY(value) { if (Array.isArray(value)) value = value[0] ?? {}; else value = value ?? {}; const type = value[UnionRow.type]; const shape = this.shapes[type]; const self = value || {}; const map = new YMap(); map.set(UnionRow.type, type); map.set(UnionRow.id, value[UnionRow.id] || createId()); if (!shape) return map; for (const [key, field] of entries(shape.shapes)) { map.set(key, field.toY(self[key])); } return map; } fromY(map) { if (!map || typeof map.get !== "function") return {}; const type = map.get(UnionRow.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(UnionRow.type); if (currentType !== value[UnionRow.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 = (events, tx) => { if (tx.origin === "self") return; const self = parent.get(key); for (const event of events) { if (event.target === parent && event.keys.has(key)) return fun(); if (event.target === self) return fun(); } }; parent.observeDeep(observe); return () => parent.unobserveDeep(observe); }; } mutator(parent, key) { return { replace: (value) => { if (!value) return parent.set(key, null); const type = value[UnionRow.type]; const shape = this.shapes[type]; if (!shape) throw new Error(`Could not find type "${type}"`); shape.applyY(value, parent, key); } }; } async applyLinks(value, loader) { if (!value) return; const type = value[UnionRow.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); } toV1(value) { if (Array.isArray(value)) value = value[0] ?? {}; if (!value) return {}; if (UnionRow.type in value) return value; const { id, type, ...data } = value; if (!id || !type) return {}; const shape = this.shapes[type]; if (!shape) return {}; return { [UnionRow.type]: type, [UnionRow.id]: id, ...shape.toV1(data) }; } searchableText(value) { let res = ""; if (Array.isArray(value)) value = value[0] ?? {}; else value = value ?? {}; const type = value[UnionRow.type]; const shape = this.shapes[type]; const self = value || {}; if (!shape) return ""; for (const [key, field] of entries(shape.shapes)) { res += field.searchableText(self[key]); } return res; } }; export { UnionRow, UnionShape };