DockerERTFF/lib/modules/core.js

274 lines
8.9 KiB
JavaScript

const fs = require('fs-extra');
const { clone } = require('../core/util');
module.exports = {
wait: function(options) {
let delay = this.parseOptional(options.delay, 'number', 1000);
return new Promise(resolve => setTimeout(resolve, delay))
},
log: function(options) {
let message = this.parse(options.message);
console.log(message);
return message;
},
repeat: async function(options) {
let repeater = this.parseRequired(options.repeat, '*', 'core.repeater: repeat is required.');
let outputFilter = this.parseOptional(options.outputFilter, 'string', 'include'); // include/exclude
let outputFields = this.parseOptional(options.outputFields, 'object'/*array[string]*/, []);
let index = 0, data = [], parentData = this.data;
switch (typeof repeater) {
case 'boolean':
repeater = repeater ? [0] : [];
break;
case 'string':
repeater = repeater.split(',');
break;
case 'number':
repeater = (n => {
let a = [], i = 0;
while (i < n) a.push(i++);
return a;
})(repeater);
break;
}
if (!(Array.isArray(repeater) || repeater instanceof Object)) {
throw new Error('Repeater data is not an array or object');
}
for (let key in repeater) {
if (Object.hasOwn(repeater, key)) {
let scope = {};
this.data = {};
if (repeater[key] instanceof Object) {
for (var prop in repeater[key]) {
if (Object.hasOwn(repeater[key], prop)) {
scope[prop] = repeater[key][prop];
if (outputFilter == 'exclude') {
if (!outputFields.includes(prop)) {
this.data[prop] = repeater[key][prop];
}
} else {
if (outputFields.includes(prop)) {
this.data[prop] = repeater[key][prop];
}
}
}
}
}
scope.$key = key;
scope.$name = key;
scope.$value = clone(repeater[key]);
scope.$index = index;
scope.$number = index + 1;
scope.$oddeven = index % 2;
if (repeater[key] == null) {
repeater[key] = {};
}
this.scope = this.scope.create(scope, clone(repeater[key]));
await this.exec(options.exec, true);
this.scope = this.scope.parent;
data.push({ ...this.data });
index++;
}
}
this.data = parentData;
return data;
},
while: async function(options) {
let max = this.parseOptional(options.max, 'number', Number.MAX_SAFE_INTEGER);
let i = 0;
while (this.parse(options.while)) {
await this.exec(options.exec, true);
if (++i == max) break;
}
},
condition: async function(options) {
let condition = this.parse(options.if);
if (!!condition) {
if (options.then) {
await this.exec(options.then, true);
}
} else if (options.else) {
await this.exec(options.else, true);
}
},
conditions: async function(options) {
if (Array.isArray(options.conditions)) {
for (let condition of options.conditions) {
let when = this.parse(condition.when);
if (!!when) {
return this.exec(condition.then, true);
}
}
}
},
select: async function(options) {
let expression = this.parse(options.expression);
if (Array.isArray(options.cases)) {
for (let item of options.cases) {
let value = this.parse(item.value);
if (expression === value) {
return this.exec(item.exec, true);
}
}
}
},
setvalue: function(options) {
let key = this.parseOptional(options.key, 'string', '');
let value = this.parse(options.value);
if (key) this.set(key, value);
return value;
},
setsession: function(options, name) {
let value = this.parse(options.value);
this.req.session[name] = value;
return value;
},
removesession: function(options, name) {
delete this.req.session[name];
},
setcookie: function(options, name) {
options = this.parse(options);
let cookieOptions = {
domain: options.domain || undefined,
httpOnly: !!options.httpOnly,
maxAge: options.expires === 0 ? undefined : (options.expires || 30) * 24 * 60 * 60 * 1000, // from days to ms
path: options.path || '/',
secure: !!options.secure,
sameSite: options.sameSite || false
};
this.setCookie(name, options.value, cookieOptions);
},
removecookie: function(options, name) {
options = this.parse(options);
let cookieOptions = {
domain: options.domain || undefined,
httpOnly: !!options.httpOnly,
maxAge: options.expires === 0 ? undefined : (options.expires || 30) * 24 * 60 * 60 * 1000, // from days to ms
path: options.path || '/',
secure: !!options.secure,
sameSite: !!options.sameSite
};
this.removeCookie(name, cookieOptions);
},
response: function(options) {
let data = this.parseOptional(options.data, '*', null);
let status = this.parseOptional(options.status, 'number', 200);
let contentType = this.parseOptional(options.contentType, 'string', 'application/json');
if (contentType != 'application/json') {
this.res.set('Content-Type', contentType);
this.res.status(status).send(data);
} else {
this.res.status(status).json(data);
}
},
end: function(options) {
this.res.json(this.data);
},
error: function(options) {
let message = this.parseRequired(options.message, 'string', 'core.error: message is required.');
throw new Error(message);
},
redirect: function(options) {
let url = this.parseRequired(options.url, 'string', 'core.redirect: url is required.');
let status = this.parseOptional(options.status, 'number', 302);
this.res.redirect(status, url);
},
trycatch: async function(options) {
try {
await this.exec(options.try, true);
} catch (error) {
this.scope.set('$_ERROR', error.message || error);
this.scope.set('$_EXCEPTION', error);
this.error = false;
if (options.catch) {
await this.exec(options.catch, true);
}
}
},
exec: async function(options) {
var data = {};
if (options.exec && fs.existsSync(`app/modules/lib/${options.exec}.json`)) {
let parentData = this.data;
this.data = {};
this.scope = this.scope.create({ $_PARAM: this.parse(options.params) });
await this.exec(await fs.readJSON(`app/modules/lib/${options.exec}.json`), true);
data = this.data;
this.scope = this.scope.parent;
this.data = parentData;
} else {
throw new Error(`There is no action called '${options.exec}' found in the library.`);
}
return data;
},
group: async function(options, name) {
if (name) {
return this.sub(options.exec);
} else {
return this.exec(options.exec, true);
}
},
parallel: async function(options, name) {
let actions = options.exec.steps || options.exec;
if (!Array.isArray(actions)) actions = [actions];
return await Promise.all(actions.map(exec => {
if (name) {
return this.sub(exec);
} else {
return this.exec(exec, true);
}
}));
},
randomUUID: function(options) {
const { randomUUID } = require('crypto');
const { v4: uuidv4 } = require('uuid');
return randomUUID ? randomUUID() : uuidv4();
},
};