orange-orm
Version:
Object Relational Mapper
194 lines (163 loc) • 4.13 kB
JavaScript
const Ajv = require('ajv');
function defineColumn(column, table) {
var c = {};
c.string = function() {
require('./column/string')(table, column);
return c;
};
c.json = function() {
require('./column/json')(column);
return c;
};
c.guid = function() {
require('./column/guid')(column);
return c;
};
c.uuid = c.guid;
c.date = function() {
require('./column/date')(column);
return c;
};
c.date = function() {
require('./column/date')(column);
return c;
};
c.dateWithTimeZone = function() {
require('./column/dateWithTimeZone')(column);
return c;
};
c.numeric = function(optionalPrecision,optionalScale) {
require('./column/numeric')(column,optionalPrecision,optionalScale);
return c;
};
c.bigint = function() {
require('./column/bigint')(column);
return c;
};
c.boolean = function() {
require('./column/boolean')(column);
return c;
};
c.binary = function() {
require('./column/binary')(column);
return c;
};
c.enum = function(values) {
let list = values;
if (Array.isArray(values))
list = values;
else if (values && typeof values === 'object') {
const keys = Object.keys(values);
const nonNumericKeys = keys.filter((key) => !/^-?\d+$/.test(key));
list = (nonNumericKeys.length ? nonNumericKeys : keys).map((key) => values[key]);
}
else
throw new Error('enum values must be an array');
const allowed = new Set(list);
column.enum = list;
function validate(value) {
if (value === undefined || value === null)
return;
if (!allowed.has(value)) {
const formatted = list.map((v) => JSON.stringify(v)).join(', ');
throw new Error(`Column ${column.alias} must be one of: ${formatted}`);
}
}
return c.validate(validate);
};
c.enum2 = function(...values) {
const list = values.length === 1 && Array.isArray(values[0])
? values[0]
: values;
return c.enum(list);
};
c.default = function(value) {
column.default = value;
return c;
};
c.primary = function() {
column.isPrimary = true;
table._primaryColumns.push(column);
return c;
};
c.as = function(alias) {
var oldAlias = column.alias;
table._aliases.delete(oldAlias);
table._aliases.add(alias);
table[alias] = column;
column.alias = alias;
return c;
};
c.dbNull = function(value) {
column.dbNull = value;
return c;
};
c.serializable = function(value) {
column.serializable = value;
return c;
};
c.notNull = function() {
column._notNull = true;
function validate(value) {
if (value === undefined || value === null) {
const error = new Error(`Column ${column.alias} cannot be null or undefined`);
error.status = 400;
throw error;
}
}
return c.validate(validate);
};
c.notNullExceptInsert = function() {
column._notNullExceptInsert = true;
function validate(value, _row, isInsert) {
if (isInsert)
return;
if (value === undefined || value === null)
throw new Error(`Column ${column.alias} cannot be null or undefined`);
}
return c.validate(validate);
};
c.validate = function(value) {
let previousValue = column.validate;
if (previousValue)
column.validate = nestedValidate;
else
column.validate = value;
function nestedValidate() {
try {
previousValue.apply(null, arguments);
value.apply(null, arguments);
}
catch (e) {
const error = new Error(e.message || e);
// @ts-ignore
error.status = 400;
throw error;
}
}
return c;
};
c.JSONSchema = function(schema, options) {
let previousValidate = column.validate;
let ajv = new Ajv(options);
let validate = ajv.compile(schema);
column.validate = _validate;
function _validate() {
if (previousValidate)
previousValidate.apply(null, arguments);
let valid = validate.apply(null, arguments);
if (!valid) {
let e = new Error(`Column ${table._dbName}.${column._dbName} violates JSON Schema: ${inspect(validate.errors)}`);
e.errors = validate.errors;
e.status = 400;
throw e;
}
}
return c;
};
return c;
}
function inspect(obj) {
return JSON.stringify(obj, null, 2);
}
module.exports = defineColumn;