alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
191 lines (189 loc) • 5.01 kB
JavaScript
import "../chunks/chunk-U5RRZUYZ.js";
// src/core/Type.ts
import { Cursor } from "alinea/core/pages/Cursor";
import { Expr, and } from "alinea/core/pages/Expr";
import { Field } from "./Field.js";
import { Hint } from "./Hint.js";
import { createId } from "./Id.js";
import { Meta } from "./Meta.js";
import { Section, section } from "./Section.js";
import { createExprData } from "./pages/CreateExprData.js";
import { BinaryOp, ExprData } from "./pages/ExprData.js";
import { RecordShape } from "./shape/RecordShape.js";
import {
assign,
defineProperty,
entries,
fromEntries,
keys
} from "./util/Objects.js";
var TypeTarget = class {
};
var Type;
((Type2) => {
Type2.Data = Symbol.for("@alinea/Type.Data");
function label(type2) {
return type2[Type2.Data].label;
}
Type2.label = label;
function meta(type2) {
return type2[Type2.Data].meta;
}
Type2.meta = meta;
function shape(type2) {
return type2[Type2.Data].shape;
}
Type2.shape = shape;
function hint(type2) {
return type2[Type2.Data].hint;
}
Type2.hint = hint;
function sections(type2) {
return type2[Type2.Data].sections;
}
Type2.sections = sections;
function isContainer(type2) {
return Boolean(type2[Type2.Data].meta.isContainer);
}
Type2.isContainer = isContainer;
function target(type2) {
return type2[Type2.Data].target;
}
Type2.target = target;
function field(type2, name) {
return type2[name];
}
Type2.field = field;
function isType(type2) {
return Boolean(type2 && type2[Type2.Data]);
}
Type2.isType = isType;
function blankEntry(name, type2) {
return {
...Type2.shape(type2).create(),
type: name,
id: createId()
};
}
Type2.blankEntry = blankEntry;
})(Type || (Type = {}));
function fieldsOfDefinition(definition) {
return entries(definition).flatMap(([key, value]) => {
if (Field.isField(value))
return [[key, value]];
if (Section.isSection(value))
return entries(Section.fields(value));
return [];
});
}
var TypeInstance = class {
constructor(label, definition) {
this.label = label;
this.definition = definition;
this.meta = this.definition[Meta] || {};
this.shape = new RecordShape(
label,
fromEntries(
fieldsOfDefinition(definition).map(([key, field]) => {
return [key, Field.shape(field)];
})
)
);
this.hint = Hint.Object(
fromEntries(
fieldsOfDefinition(definition).map(([key, field]) => {
return [key, Field.hint(field)];
})
)
);
let current = {};
const addCurrent = () => {
if (keys(current).length > 0)
this.sections.push(section({ definition: current }));
current = {};
};
for (const [key, value] of entries(definition)) {
if (Field.isField(value)) {
current[key] = value;
} else if (Section.isSection(value)) {
addCurrent();
this.sections.push(value);
}
}
addCurrent();
const name = label;
const callable = {
[name]: (...condition) => this.call(...condition)
}[name];
delete callable.length;
this.target = callable;
this.defineProperties(callable);
}
shape;
hint;
meta;
sections = [];
target;
condition(input) {
if (input.length === 0)
return void 0;
const isConditionalRecord = input.length === 1 && !Expr.isExpr(input[0]);
const conditions = isConditionalRecord ? entries(input[0]).map(([key, value]) => {
const field = Expr(ExprData.Field({ type: this.target }, key));
return Expr(
ExprData.BinOp(
field[Expr.Data],
BinaryOp.Equals,
createExprData(value)
)
);
}) : input.map((ev) => Expr(createExprData(ev)));
return and(...conditions)[Expr.Data];
}
call(...input) {
const isConditionalRecord = input.length === 1 && !Expr.isExpr(input[0]);
if (isConditionalRecord)
return new Cursor.Partial(this.target, input[0]);
else
return new Cursor.Find({
target: { type: this.target },
where: this.condition(input)
});
}
field(def, name) {
return assign(Expr(ExprData.Field({ type: this.target }, name)), {
[Field.Data]: def[Field.Data],
[Field.Ref]: def[Field.Ref]
});
}
defineProperties(instance) {
for (const [key, value] of fieldsOfDefinition(this.definition)) {
defineProperty(instance, key, {
value: this.field(value, key),
enumerable: true,
configurable: true
});
}
defineProperty(instance, Type.Data, {
value: this,
enumerable: false
});
}
};
function type(label, definition) {
const title = typeof label === "string" ? label : "Anonymous";
const def = typeof label === "string" ? definition : label;
const instance = new TypeInstance(
title,
def
);
return instance.target;
}
((type2) => {
type2.meta = Meta;
})(type || (type = {}));
export {
Type,
TypeTarget,
type
};