@themost/data
Version:
MOST Web Framework Codename Blueshift - Data module
285 lines (271 loc) • 8.03 kB
JavaScript
// MOST Web Framework 2.0 Codename Blueshift BSD-3-Clause license Copyright (c) 2017-2022, THEMOST LP All rights reserved
/*eslint no-var: "off"*/
// noinspection ES6ConvertVarToLetConst
var {TypeParser} = require('./types');
var {TraceUtils} = require('@themost/common');
// eslint-disable-next-line no-unused-vars
var moment = require('moment');
var _ = require('lodash');
/**
* @class
* @classdesc A utility class which offers a set of methods for calculating the default values of a data model
* @param {DataContext=} context
* @param {DataModel=} model
* @param {*=} target
* @constructor
*/
function FunctionContext(context, model, target) {
/**
* @type {DataContext}
*/
this.context = context;
/**
* @type {DataModel}
*/
this.model = model;
if (_.isNil(context) && _.isObject(model)) {
//get current context from DataModel.context property
this.context = model.context;
}
/**
* @type {*}
*/
this.target = target;
}
FunctionContext.prototype.eval = function(expr, callback) {
callback = callback || function() {};
if (typeof expr !=='string') {
callback(null);
return;
}
var re = /(fn:)\s?(.*?)\s?\((.*?)\)/, expr1=expr;
if (expr.indexOf('fn:')!==0) {
expr1 = 'fn:' + expr1;
}
var match = re.exec(expr1);
if (match) {
var expr2eval;
//check parameters (match[3])
if (match[3].length===0) {
expr2eval = expr1.replace(/(fn:)\s?(.*?)\s?\((.*?)\)/, '(function() { return this.$2(); });');
}
else {
expr2eval = expr1.replace(/(fn:)\s?(.*?)\s?\((.*?)\)/, '(function() { return this.$2($3); });');
}
//evaluate expression
try {
var f = eval(expr2eval);
var value1 = f.call(this);
if (typeof value1 !== 'undefined' && value1 !== null && typeof value1.then === 'function') {
value1.then(function(result) {
return callback(null, result);
}).catch(function(err) {
callback(err);
});
}
else {
return callback(null, value1);
}
}
catch(err) {
callback(err);
}
}
else {
callback(new Error('Cannot evaluate expression.'));
}
};
/**
* Returns the current date and time
* @returns {Promise<Date>}
*/
FunctionContext.prototype.now = function() {
return new Promise(function(resolve) {
return resolve(new Date());
});
};
/**
* Returns the current date
* @returns {Promise<Date>}
*/
FunctionContext.prototype.today = function() {
return new Promise(function(resolve) {
return resolve(moment(new Date()).startOf('day').toDate());
});
};
/**
* @returns {Promise|*}
*/
FunctionContext.prototype.newid = function() {
var self = this;
return new Promise(function(resolve, reject) {
self.model.context.db.selectIdentity(self.model.sourceAdapter, self.model.primaryKey, function(err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
});
};
var UUID_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
function newGuidInternal() {
var chars = UUID_CHARS, uuid = [], i;
// rfc4122, version 4 form
var r;
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random()*16;
uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
}
}
return uuid.join('');
}
/**
* @returns {Promise|*}
*/
FunctionContext.prototype.newGuid = function() {
return new Promise(function(resolve, reject) {
try {
resolve(newGuidInternal());
}
catch(err) {
reject(err)
}
});
};
/**
* Generates a random integer value between the given minimum and maximum value
* @param {number} min
* @param {number} max
* @returns {Promise<number>}
*/
FunctionContext.prototype.int = function(min, max) {
return new Promise(function(resolve, reject) {
try {
resolve(_.random(min, max));
}
catch (err) {
reject(err);
}
});
};
/**
* Generates a random sequence of numeric characters
* @param {number} length - A integer which represents the length of the sequence
* @returns {Promise|*}
*/
FunctionContext.prototype.numbers = function(length) {
return new Promise(function(resolve, reject) {
try {
length = length || 8;
if (length<0) {
return reject(new Error('Number sequence length must be greater than zero.'));
}
if (length>255) {
return reject(new Error('Number sequence length exceeds the maximum of 255 characters.'));
}
var times = Math.ceil(length / 10);
var res = '';
_.times(times, function() {
res += _.random(1000000000, 9000000000)
});
return resolve(res.substring(0,length));
}
catch (err) {
reject(err);
}
});
};
/**
* @param {number} length
* @returns {Promise|*}
*/
FunctionContext.prototype.chars = function(length) {
return new Promise(function(resolve, reject) {
try {
length = length || 8;
var chars = 'abcdefghkmnopqursuvwxz2456789ABCDEFHJKLMNPQURSTUVWXYZ';
var str = '';
var rnd;
for(var i = 0; i < length; i++) {
rnd = _.random(0, chars.length - 1);
str += chars.substring(rnd, rnd + 1);
}
resolve(str);
}
catch (err) {
reject(err);
}
});
};
/**
* @param {number} length
* @returns {Promise<string>}
*/
FunctionContext.prototype.password = function(length) {
return new Promise(function(resolve, reject) {
try {
length = length || 8;
var specialChars = '%=+-!$()#@[]?{}^|';
var chars = 'abcdefghkmnopqursuvwxz2456789ABCDEFHJKLMNPQURSTUVWXYZ';
var str = '';
var rnd = 0;
var specialCharIndex = _.random(0, length-1)
for(var i = 0; i < length; i++) {
if (i === specialCharIndex) {
rnd = _.random(0, specialChars.length - 1);
str += specialChars.substring(rnd, rnd + 1);
} else {
rnd = _.random(0, chars.length-1);
str += chars.substring(rnd, rnd + 1);
}
}
resolve('{clear}' + str);
}
catch (err) {
return reject(err);
}
});
};
/**
* @returns {Promise<any>}
*/
FunctionContext.prototype.user = async function() {
/**
* @type {import('./types').DataContext}
*/
var context = (this.model && this.model.context) || this.context;
if (context.interactiveUser) {
const interactiveUser = await context.getInteractiveUser();
return interactiveUser && interactiveUser.id ? interactiveUser.id : null;
} else if (context.user) {
const user = await context.getUser();
return user && user.id ? user.id : null;
}
return null;
};
/**
* @returns {Promise|*}
*/
FunctionContext.prototype.me = function() {
return this.user();
};
/**
* Creates a new instance of FunctionContext class
* @param {DataContext|*=} context
* @param {DataModel|*=} model
* @param {*=} target
* @returns FunctionContext
*/
function createContext(context, model, target) {
return new FunctionContext(context, model, target);
}
module.exports = {
createContext,
FunctionContext
};