stackpress
Version:
Incept is a content management framework.
556 lines (555 loc) • 19.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const cuid2_1 = require("@paralleldrive/cuid2");
const nanoid_1 = require("nanoid");
const typemap = __importStar(require("../config/typemaps.js"));
const assert_js_1 = __importDefault(require("../assert.js"));
const helpers_js_1 = require("../helpers.js");
const Attributes_js_1 = __importDefault(require("./Attributes.js"));
class Column {
get active() {
return this.attributes.active;
}
get assertions() {
if (this.attributes.generated || this.relation || this.related) {
return [];
}
const assertions = this.attributes.assertions;
for (const type in typemap) {
if (this.type === type) {
if (this.multiple) {
if (!assertions.find(v => v.method === 'array')) {
assertions.unshift({
method: 'array',
args: [typemap.method[type]],
message: 'Invalid format'
});
}
}
else if (!assertions.find(v => v.method === typemap.method[type])) {
assertions.unshift({
method: typemap.method[type],
args: [],
message: 'Invalid format'
});
}
}
}
if (this.enum && !assertions.find(v => v.method === 'option')) {
assertions.unshift({
method: 'option',
args: Object.values(this.enum),
message: 'Invalid option'
});
}
if (this.attributes.unique) {
if (!assertions.find(v => v.method === 'unique')) {
assertions.unshift({
method: 'unique',
args: [],
message: 'Already exists'
});
}
}
if (!this.multiple
&& this.required
&& typeof this.attributes.default === 'undefined') {
if (!assertions.find(v => v.method === 'required')) {
assertions.unshift({
method: 'required',
args: [],
message: `${this.name} is required`
});
}
}
return assertions;
}
get clen() {
return this.attributes.clen;
}
get dash() {
return (0, helpers_js_1.dasherize)(this.name);
}
get default() {
const defaults = this.attributes.default;
if (typeof defaults === 'string') {
if (defaults.toLowerCase() === 'cuid()') {
return (0, cuid2_1.createId)();
}
else if (defaults.toLowerCase() === 'nanoid()') {
return (0, nanoid_1.nanoid)();
}
else if (defaults.toLowerCase() === 'now()') {
return new Date();
}
else if (/^cuid\(([0-9]+)\)$/.test(defaults)) {
return (0, cuid2_1.createId)();
}
const forCuid = defaults.match(/^cuid\(([0-9]+)\)$/);
if (forCuid) {
const uuid = (0, cuid2_1.init)({ length: parseInt(forCuid[1]) || 10 });
return uuid();
}
const forNano = defaults.match(/^nanoid\(([0-9]+)\)$/);
if (forNano) {
return (0, nanoid_1.nanoid)(parseInt(forNano[1]) || 10);
}
}
return defaults;
}
get description() {
return this.attributes.description;
}
get enum() {
return this._fieldset.registry.enum.get(this.type) || null;
}
get encrypted() {
return this.attributes.encrypted;
}
get example() {
return this.attributes.example;
}
get field() {
return this.attributes.field;
}
get fieldset() {
return this._fieldset.registry.fieldset.get(this.type) || null;
}
get filter() {
return this.attributes.filter;
}
get generated() {
return this.attributes.generated;
}
get hash() {
return this.attributes.hash;
}
get id() {
return this.attributes.id;
}
get indexable() {
return this.attributes.indexable;
}
get label() {
return this.attributes.label || this.name;
}
get list() {
if (this.model) {
return {
component: false,
method: 'hide',
args: [],
attributes: {}
};
}
return this.attributes.list;
}
get max() {
return this.attributes.max;
}
get min() {
return this.attributes.min;
}
get model() {
return this._fieldset.registry.model.get(this.type) || null;
}
get related() {
const model = this._fieldset.registry.model.get(this.type);
if (!model) {
return null;
}
const column = Array.from(model.columns.values())
.filter(column => !!column.relation)
.find(column => column.type === this._fieldset.name);
if (!(column === null || column === void 0 ? void 0 : column.relation)) {
return null;
}
return column.relation;
}
get relation() {
const relation = this.attributes.relation;
if (!relation || !this.model) {
return null;
}
const models = { parent: this.model, child: this._fieldset };
let foreignColumns = Array.from(models.parent.columns.values()).filter(column => column.type === this._fieldset.name).filter(column => !relation.name || relation.name === column.name);
if (foreignColumns.length === 0) {
return null;
}
const columns = {
parent: foreignColumns[0],
child: this
};
const keys = {
parent: models.parent.column(relation.foreign),
child: models.child.column(relation.local)
};
if (!keys.parent || !keys.child) {
return null;
}
const types = {
parent: columns.parent.multiple ? 2 : columns.parent.required ? 1 : 0,
child: columns.child.multiple ? 2 : columns.child.required ? 1 : 0
};
return {
parent: {
model: models.parent,
column: columns.parent,
key: keys.parent,
type: types.parent
},
child: {
model: models.child,
column: columns.child,
key: keys.child,
type: types.child
}
};
}
get searchable() {
return this.attributes.searchable;
}
get schema() {
const type = (() => {
if (Boolean(this.fieldset
|| this.multiple || this.type === 'Json'
|| this.type === 'Object' || this.type === 'Hash')) {
return 'json';
}
else if ([
'Char', 'Text', 'Integer', 'Float', 'Boolean',
'Date', 'Time', 'Datetime', 'Binary', 'Timestamp'
].includes(this.type)) {
return this.type.toLowerCase();
}
else if (this.type === 'Number') {
return String(this.step).split('.')[1].length > 0
? 'float'
: 'integer';
}
else if (this.enum) {
return 'enum';
}
return 'varchar';
})();
const length = (() => {
if (type === 'enum' && this.enum) {
return [Math.max(...Object.values(this.enum).map(value => String(value).length)), 0];
}
else if (type === 'char' || type === 'varchar') {
return [Math.min(this.clen || 255, 255), 0];
}
else if (type === 'integer') {
return [String(this.max).split('.')[0].length, 0];
}
else if (type === 'float') {
return [
String(this.max).split('.')[0].length,
String(this.step).split('.')[1].length
];
}
return [0, 0];
})();
const defaults = this.default ? this.default
: this.required ? null
: undefined;
const unsigned = this.min >= 0;
const increment = Boolean(this.attributes.get('increment'));
const index = this.id ? 'primary'
: this.unique ? 'unique'
: this.indexable ? 'index'
: undefined;
return { type, length, defaults, unsigned, increment, index };
}
get sortable() {
return this.attributes.sortable;
}
get snake() {
return (0, helpers_js_1.snakerize)(this.name);
}
get span() {
return this.attributes.span;
}
get step() {
const step = this.attributes.step;
if (step === 1 && this.type === 'Float') {
return 0.01;
}
return step || 1;
}
get title() {
return (0, helpers_js_1.capitalize)((0, helpers_js_1.camelize)(this.name));
}
get typemap() {
return {
type: typemap.type[this.type],
model: typemap.model[this.type],
format: typemap.format[this.type],
method: typemap.method[this.type],
literal: typemap.literal[this.type],
mysql: typemap.mysql[this.type],
pgsql: typemap.pgsql[this.type],
sqlite: typemap.sqlite[this.type],
helper: typemap.helper[this.type]
};
}
get unique() {
return this.attributes.unique;
}
get view() {
if (this.model) {
return {
component: false,
method: 'hide',
args: [],
attributes: {}
};
}
return this.attributes.view;
}
get zindex() {
return this.attributes.zindex;
}
constructor(fieldset, info) {
this._fieldset = fieldset;
this.type = info.type;
this.name = info.name;
this.multiple = info.multiple;
this.required = info.required;
this.attributes = new Attributes_js_1.default(Object.entries(info.attributes));
}
assert(value, strict = true) {
for (const assertion of this.assertions) {
const { method, args, message } = assertion;
const hasDefault = typeof this.default !== 'undefined';
const hasNoValue = value === null
|| typeof value === 'undefined'
|| value === '';
if (typeof assert_js_1.default[method] !== 'function'
|| (!strict && method === 'required')
|| (!strict && hasNoValue)
|| (strict && hasNoValue && (!this.required || hasDefault))) {
continue;
}
if (!assert_js_1.default[method](value, ...args)) {
return message || '';
}
}
if (this.fieldset && value) {
const fieldset = this.fieldset;
if (this.multiple) {
if (!Array.isArray(value)) {
return 'Invalid format';
}
const errors = [];
value.forEach(value => errors.push(fieldset.assert(value, strict)));
if (errors.some(error => error)) {
return errors;
}
}
else {
const message = fieldset.assert(value, strict);
if (message)
return message;
}
}
return null;
}
attribute(name) {
return this.attributes.get(name);
}
serialize(value, options = {}, seed) {
const { bool = true, date = true, object = false } = options;
if (!this.required && (value === null || typeof value === 'undefined')) {
return value;
}
else if (typeof value === 'undefined') {
return value;
}
if (typeof value === 'string' && this.hash) {
return (0, helpers_js_1.hash)(value);
}
else if (typeof value === 'string' && this.encrypted && seed) {
return (0, helpers_js_1.encrypt)(value, seed);
}
if (this.fieldset || this.multiple) {
return object ? value : JSON.stringify(value);
}
if (this.typemap.method) {
const type = this.typemap.method;
if (['number', 'integer', 'float'].includes(type)) {
const serialized = Number(value);
return !isNaN(serialized) ? serialized : 0;
}
else if (type === 'boolean') {
if (value === 'false') {
return bool ? false : 0;
}
else if (value === 'true') {
return bool ? true : 1;
}
return bool ? Boolean(value) : Number(Boolean(value));
}
else if (type === 'date') {
if (value instanceof Date) {
return date ? value : [
value.toISOString().split('T')[0],
value.toTimeString().split(' ')[0]
].join(' ');
}
else if (typeof value === 'number') {
const stamp = new Date(value);
return date ? stamp : [
stamp.toISOString().split('T')[0],
stamp.toTimeString().split(' ')[0]
].join(' ');
}
let stamp = new Date(value);
if (isNaN(stamp.getTime())) {
stamp = new Date(0);
}
return date ? stamp : [
stamp.toISOString().split('T')[0],
stamp.toTimeString().split(' ')[0]
].join(' ');
}
else if (type === 'object') {
if (typeof value === 'string') {
try {
if (object) {
return JSON.parse(value);
}
JSON.parse(value);
return value;
}
catch (e) { }
}
return object ? value : JSON.stringify(value);
}
return (value === null || value === void 0 ? void 0 : value.toString()) || value;
}
if (value === null
|| typeof value === 'string'
|| typeof value === 'number'
|| typeof value === 'undefined') {
return value;
}
else if (typeof value === 'boolean') {
return bool ? value : Number(value);
}
else if (value instanceof Date) {
return date ? value : [
value.toISOString().split('T')[0],
value.toTimeString().split(' ')[0]
].join(' ');
}
return object ? value : ((value === null || value === void 0 ? void 0 : value.toString()) || value);
}
unserialize(value, options = {}, seed) {
const { bool = true, date = true } = options;
if (value === null || typeof value === 'undefined') {
return value;
}
else if (this.fieldset || this.multiple) {
if (typeof value === 'string') {
try {
return JSON.parse(value);
}
catch (e) {
return this.multiple ? [] : {};
}
}
}
if (this.fieldset) {
const fieldset = this.fieldset;
return !this.multiple
? this.fieldset.unserialize(value, options, seed)
: Array.isArray(value)
? value.map(value => fieldset.unserialize(value, options, seed))
: [];
}
if (typeof value === 'string' && this.encrypted && seed) {
return (0, helpers_js_1.decrypt)(value, seed);
}
if (this.typemap.method) {
const type = this.typemap.method;
if (['number', 'integer', 'float'].includes(type)) {
const serialized = Number(value);
return !isNaN(serialized) ? serialized : 0;
}
else if (type === 'boolean') {
return bool ? Boolean(value) : Number(Boolean(value));
}
else if (type === 'date') {
if (value instanceof Date) {
return date ? value : [
value.toISOString().split('T')[0],
value.toTimeString().split(' ')[0]
].join(' ');
}
else if (typeof value === 'number') {
const stamp = new Date(value);
return date ? stamp : [
stamp.toISOString().split('T')[0],
stamp.toTimeString().split(' ')[0]
].join(' ');
}
let stamp = new Date(value);
if (isNaN(stamp.getTime())) {
stamp = new Date(0);
}
return date ? stamp : [
stamp.toISOString().split('T')[0],
stamp.toTimeString().split(' ')[0]
].join(' ');
}
else if (type === 'object') {
if (typeof value === 'string') {
try {
return JSON.parse(value);
}
catch (e) { }
}
return value;
}
}
return value;
}
}
exports.default = Column;