stackpress
Version:
Incept is a content management framework.
182 lines (181 loc) • 5.78 kB
JavaScript
import Mustache from 'mustache';
import { camelize, capitalize, dasherize, generators, snakerize } from '../helpers.js';
import Attributes from './Attributes.js';
import Column from './Column.js';
export default class Fieldset {
registry;
name;
attributes;
columns;
get assertions() {
return Array.from(this.columns.values()).filter(column => column.assertions.length > 0);
}
get camel() {
return camelize(this.name);
}
get dash() {
return dasherize(this.name);
}
get encrypted() {
return Array.from(this.columns.values()).filter(column => column.encrypted);
}
get defaults() {
const defaults = {};
for (const column of this.columns.values()) {
if (column.default === undefined
|| generators.includes(column.default)) {
continue;
}
defaults[column.name] = column.default;
}
return defaults;
}
get descriptions() {
const descriptions = {};
for (const column of this.columns.values()) {
if (column.description) {
descriptions[column.name] = column.description;
}
}
return descriptions;
}
get enums() {
return Array.from(this.columns.values()).filter(column => column.enum !== null);
}
get examples() {
const examples = {};
for (const column of this.columns.values()) {
if (column.example !== undefined) {
examples[column.name] = column.example;
}
}
return examples;
}
get fields() {
return Array.from(this.columns.values()).filter(column => column.field.method !== 'none');
}
get fieldsets() {
return Array.from(this.columns.values()).filter(column => !!column.fieldset);
}
get icon() {
return this.attributes.icon;
}
get label() {
return this.attributes.labels;
}
get lists() {
return Array.from(this.columns.values()).filter(column => column.list.method !== 'hide');
}
get lower() {
return this.name.toLocaleLowerCase();
}
get plural() {
return this.attributes.labels[1] || this.name;
}
get singular() {
return this.attributes.labels[0] || this.name;
}
get snake() {
return snakerize(this.name);
}
get template() {
return this.attributes.template;
}
get title() {
return capitalize(camelize(this.name));
}
get views() {
return Array.from(this.columns.values()).filter(column => column.view.method !== 'hide');
}
constructor(registry, name, attributes, columns) {
this.registry = registry;
this.name = name;
this.attributes = new Attributes(Object.entries(attributes));
this.columns = new Map(columns.map(info => [info.name, new Column(this, info)]));
}
assert(values = {}, strict = true) {
const errors = {};
for (const column of this.columns.values()) {
if (column.model)
continue;
const value = column.unserialize(values[column.name]);
const message = column.assert(value, strict);
if (typeof message !== 'undefined' && message !== null) {
errors[column.name] = message;
}
}
return Object.keys(errors).length > 0 ? errors : null;
}
column(name) {
return this.columns.get(name);
}
filter(values) {
const filtered = {};
for (const [name, value] of Object.entries(values)) {
if (this.columns.has(name)) {
filtered[name] = value;
}
}
return filtered;
}
fromSnake(name) {
const columns = Array.from(this.columns.values());
for (const column of columns) {
if (column.snake === name) {
return column;
}
}
return null;
}
input(values, strict = true) {
const inputs = {};
for (const [name, value] of Object.entries(values)) {
if (this.fields.find(column => column.name === name)) {
inputs[name] = value;
continue;
}
else if (!strict) {
const column = this.column(name);
if (!column || column.model)
continue;
inputs[name] = value;
}
}
return inputs;
}
render(data) {
if (!this.template) {
return '';
}
return Mustache.render(this.template, data);
}
transformTemplate(to = '${data.%s}') {
const template = this.template || '';
return Array.from(template.matchAll(/\{\{([a-zA-Z0-9_\.]+)\}\}/g)).reduce((result, match) => {
return result.replace(match[0], to.replaceAll('%s', match[1]));
}, template);
}
serialize(values, options = {}, seed) {
const serialized = {};
for (const [name, value] of Object.entries(values)) {
const column = this.columns.get(name);
if (!column) {
continue;
}
serialized[column.snake] = column.serialize(value, options, seed);
}
return serialized;
}
unserialize(values, options = {}, seed) {
const unserialized = {};
for (const [name, value] of Object.entries(values)) {
const column = this.fromSnake(name);
if (!column) {
unserialized[name] = value;
continue;
}
unserialized[column.name] = column.unserialize(value, options, seed);
}
return unserialized;
}
}