274 lines
8.9 KiB
JavaScript
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();
|
|
},
|
|
|
|
}; |