alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
146 lines (144 loc) • 3.88 kB
JavaScript
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
};