fix(basic.gblib): DELETE keyword in storage #400. @othonlima
This commit is contained in:
parent
d23524b7b8
commit
86313b7684
7 changed files with 184 additions and 90 deletions
21
boot.mjs
21
boot.mjs
|
@ -1,27 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import chalkAnimation from 'chalk-animation';
|
||||
import Fs from 'fs';
|
||||
import Path from 'path';
|
||||
import { exec } from 'child_process';
|
||||
import pjson from './package.json' assert { type: 'json' };
|
||||
import { GBUtil } from './dist/src/util.js';
|
||||
|
||||
// Displays version of Node JS being used at runtime and others attributes.
|
||||
|
||||
console.log(``);
|
||||
console.log(``);
|
||||
console.log(``);
|
||||
console.log(``);
|
||||
console.log(``);
|
||||
console.log(`General Bots Open-core Server 3.1 is initializing...`);
|
||||
console.log(`Visit: https://github.com/generalbots.`);
|
||||
console.log(``);
|
||||
process.stdout.write(`Enviroment: botserver@${pjson.version}, botlib@${pjson.dependencies.botlib}, botbuilder@${pjson.dependencies.botbuilder}, node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||
console.log(``);
|
||||
console.log(``);
|
||||
chalkAnimation.karaoke(`
|
||||
█████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ®
|
||||
██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █
|
||||
██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██
|
||||
██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █
|
||||
█████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███
|
||||
`,1000);
|
||||
await GBUtil.sleep(80);
|
||||
var __dirname = process.env.PWD || process.cwd();
|
||||
try {
|
||||
var run = () => {
|
||||
|
||||
import('./dist/src/app.js').then((gb)=> {
|
||||
console.log(`\n`);
|
||||
process.stdout.write(`${pjson.version}, botlib@${pjson.dependencies.botlib}, botbuilder@${pjson.dependencies.botbuilder}, node@${process.version.replace('v', '')}, ${process.platform} ${process.arch} `);
|
||||
console.log(`\n`);
|
||||
gb.GBServer.run()
|
||||
});
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
"botlib": "3.0.11",
|
||||
"c3-chart-maker": "0.2.8",
|
||||
"cd": "0.3.3",
|
||||
"chalk-animation": "^2.0.3",
|
||||
"chatgpt": "2.4.2",
|
||||
"chrome-remote-interface": "0.31.3",
|
||||
"cli-progress": "3.11.2",
|
||||
|
|
|
@ -317,23 +317,34 @@ export class DialogKeywords {
|
|||
}
|
||||
|
||||
// https://weblog.west-wind.com/posts/2008/Mar/18/A-simple-formatDate-function-for-JavaScript
|
||||
public async format(value, format) {
|
||||
public async format({pid, value, format}) {
|
||||
|
||||
var date = value;
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
const contentLocale = min.core.getParam(
|
||||
min.instance,
|
||||
'Default Content Language',
|
||||
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
||||
);
|
||||
|
||||
if (!(value instanceof Date)) {
|
||||
value = SystemKeywords.getDateFromLocaleString(pid,value, contentLocale);
|
||||
}
|
||||
var date:any = new Date(value); //don't change original date
|
||||
|
||||
if (!format)
|
||||
format = "MM/dd/yyyy";
|
||||
|
||||
var month = date.getMonth() + 1;
|
||||
var year = date.getFullYear();
|
||||
|
||||
format = format.replace("MM", month.toString().padL(2, "0"));
|
||||
format = format.replace("MM", GBUtil.padL(month.toString(), 2, "0"));
|
||||
|
||||
if (format.indexOf("yyyy") > -1)
|
||||
format = format.replace("yyyy", year.toString());
|
||||
else if (format.indexOf("yy") > -1)
|
||||
format = format.replace("yy", year.toString().substr(2, 2));
|
||||
|
||||
format = format.replace("dd", date.getDate().toString().padL(2, "0"));
|
||||
format = format.replace("dd", GBUtil.padL(date.getDate().toString(), 2, "0"));
|
||||
|
||||
var hours = date.getHours();
|
||||
if (format.indexOf("t") > -1) {
|
||||
|
@ -343,16 +354,17 @@ export class DialogKeywords {
|
|||
format = format.replace("t", "am")
|
||||
}
|
||||
if (format.indexOf("HH") > -1)
|
||||
format = format.replace("HH", hours.toString().padL(2, "0"));
|
||||
format = format.replace("HH", GBUtil.padL(hours.toString(), 2, "0"));
|
||||
if (format.indexOf("hh") > -1) {
|
||||
if (hours > 12) hours - 12;
|
||||
if (hours == 0) hours = 12;
|
||||
format = format.replace("hh", hours.toString().padL(2, "0"));
|
||||
}
|
||||
if (format.indexOf("mm") > -1)
|
||||
format = format.replace("mm", date.getMinutes().toString().padL(2, "0"));
|
||||
format = format.replace("mm", GBUtil.padL(date.getMinutes().toString(), 2, "0"));
|
||||
if (format.indexOf("ss") > -1)
|
||||
format = format.replace("ss", date.getSeconds().toString().padL(2, "0"));
|
||||
format = format.replace("ss", GBUtil.padL(date.getSeconds().toString(), 2, "0"));
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
@ -363,10 +375,18 @@ export class DialogKeywords {
|
|||
*
|
||||
* https://stackoverflow.com/a/1214753/18511
|
||||
*/
|
||||
public dateAdd(date, mode, units) {
|
||||
public async dateAdd({pid, date, mode, units}) {
|
||||
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
const contentLocale = min.core.getParam(
|
||||
min.instance,
|
||||
'Default Content Language',
|
||||
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
||||
);
|
||||
|
||||
let dateCopy = date;
|
||||
if (!(dateCopy instanceof Date)) {
|
||||
dateCopy = new Date(dateCopy);
|
||||
dateCopy = SystemKeywords.getDateFromLocaleString(pid,dateCopy, contentLocale);
|
||||
}
|
||||
var ret = new Date(dateCopy); //don't change original date
|
||||
var checkRollover = function () {
|
||||
|
|
|
@ -592,7 +592,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
// Setups interprocess communication from .gbdialog run-time to the BotServer API.
|
||||
|
||||
const optsRPC = {callTimeout: this.callTimeout};
|
||||
const optsRPC = {callTimeout: this.callTimeout, messageParser: data => {return JSON.parse(data)}};
|
||||
let url;
|
||||
const agent = http.Agent({ keepAlive: true });
|
||||
|
||||
|
|
|
@ -40,28 +40,31 @@ import Path from 'path';
|
|||
* Image processing services of conversation to be called by BASIC.
|
||||
*/
|
||||
export class KeywordsExpressions {
|
||||
private static getParams = (text: string, names) => {
|
||||
const splitParamsButIgnoreCommasInDoublequotes = (str: string) => {
|
||||
return str.split(',').reduce(
|
||||
(accum, curr) => {
|
||||
if (accum.isConcatting) {
|
||||
accum.soFar[accum.soFar.length - 1] += ',' + curr;
|
||||
} else {
|
||||
if (curr === '') {
|
||||
curr = null;
|
||||
}
|
||||
accum.soFar.push(curr);
|
||||
}
|
||||
if (curr.split('"').length % 2 == 0) {
|
||||
accum.isConcatting = !accum.isConcatting;
|
||||
}
|
||||
return accum;
|
||||
},
|
||||
{ soFar: [], isConcatting: false }
|
||||
).soFar;
|
||||
};
|
||||
|
||||
const items = splitParamsButIgnoreCommasInDoublequotes(text);
|
||||
public static splitParamsButIgnoreCommasInDoublequotes = (str: string) => {
|
||||
return str.split(',').reduce(
|
||||
(accum, curr) => {
|
||||
if (accum.isConcatting) {
|
||||
accum.soFar[accum.soFar.length - 1] += ',' + curr;
|
||||
} else {
|
||||
if (curr === '') {
|
||||
curr = null;
|
||||
}
|
||||
accum.soFar.push(curr);
|
||||
}
|
||||
if (curr.split('"').length % 2 == 0) {
|
||||
accum.isConcatting = !accum.isConcatting;
|
||||
}
|
||||
return accum;
|
||||
},
|
||||
{ soFar: [], isConcatting: false }
|
||||
).soFar;
|
||||
};
|
||||
|
||||
|
||||
private static getParams = (text: string, names) => {
|
||||
|
||||
const items = KeywordsExpressions.splitParamsButIgnoreCommasInDoublequotes(text);
|
||||
|
||||
let i = 0;
|
||||
let json = '';
|
||||
|
@ -440,8 +443,14 @@ export class KeywordsExpressions {
|
|||
keywords[i++] = [
|
||||
/^\s*(DELETE)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['file']);
|
||||
return `await sys.deleteFile ({pid: pid, ${params}})`;
|
||||
const params = this.getParams($3, ['table', 'criteria']);
|
||||
|
||||
if (params[1]){
|
||||
return `await sys.deleteFromStorage ({pid: pid, ${params}})`;
|
||||
}
|
||||
else {
|
||||
return `await sys.deleteFile ({pid: pid, ${params}})`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -796,7 +805,7 @@ export class KeywordsExpressions {
|
|||
/^\s*(.*)\=\s*(dateadd)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3, $4) => {
|
||||
const params = this.getParams($4, ['date', 'mode', 'units']);
|
||||
return `await dk.dateAdd ({pid: pid, ${params}})`;
|
||||
return `${$1} = await dk.dateAdd ({pid: pid, ${params}})`;
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -974,10 +983,10 @@ export class KeywordsExpressions {
|
|||
];
|
||||
|
||||
keywords[i++] = [
|
||||
/^\s*(FORMAT)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3) => {
|
||||
const params = this.getParams($3, ['value', 'format']);
|
||||
return `await dk.format({pid: pid, ${params}})`;
|
||||
/^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*(FORMAT)(\s*)(.*)/gim,
|
||||
($0, $1, $2, $3, $4) => {
|
||||
const params = this.getParams($4, ['value', 'format']);
|
||||
return `${$1} = await dk.format({pid: pid, ${params}})`;
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -1161,27 +1170,34 @@ export class KeywordsExpressions {
|
|||
$3 = $3.replace(/\"/g, '');
|
||||
let fields = $3.split(',');
|
||||
const table = fields[0].trim();
|
||||
|
||||
fields.shift();
|
||||
|
||||
const fieldsAsText = fields.join(',');
|
||||
|
||||
let fieldsNamesOnly = [];
|
||||
let index = 0;
|
||||
|
||||
|
||||
fields.forEach(field => {
|
||||
|
||||
// Extracts only the last part of the variable like 'column'
|
||||
// from 'row.column'.
|
||||
|
||||
const fieldRegExp = /(?:.*\.)(.*)/gim;
|
||||
let name = fieldRegExp.exec(field)[1]
|
||||
const fieldRegExp = /(?:.*\.)*(.*)/gim;
|
||||
let name = fieldRegExp.exec(field.trim())[1]
|
||||
|
||||
fieldsNamesOnly.push(`'${name}'`);
|
||||
});
|
||||
let fieldsNames = fieldsNamesOnly.join(',');
|
||||
|
||||
return `await sys.saveToStorage({pid: pid, table: "${table}", fieldsValues: [${fieldsAsText}], fieldsNames: [${fieldsNames}] })`;
|
||||
// Checks if it is a collection or series of params.
|
||||
return `
|
||||
|
||||
if (${fields[0]}[0]){
|
||||
await sys.saveToStorageBatch({pid: pid, table: ${table}, rows:${fields[0]} })
|
||||
}else{
|
||||
await sys.saveToStorage({pid: pid, table: ${table}, fieldsValues: [${fieldsAsText}], fieldsNames: [${fieldsNames}] })
|
||||
}
|
||||
`;
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -1189,7 +1205,8 @@ export class KeywordsExpressions {
|
|||
/^\s*set\s*(.*)/gim,
|
||||
($0, $1, $2) => {
|
||||
const params = this.getParams($1, ['file', 'address', 'value']);
|
||||
return `await sys.set ({pid: pid, handle: page, ${params}})`;
|
||||
const items = KeywordsExpressions.splitParamsButIgnoreCommasInDoublequotes($1);
|
||||
return `${items[0]} = await sys.set ({pid: pid, handle: page, ${params}})`;
|
||||
}
|
||||
];
|
||||
keywords[i++] = [
|
||||
|
|
|
@ -513,7 +513,7 @@ export class SystemKeywords {
|
|||
* @example SET "file.xlsx", "A2", 4500
|
||||
*
|
||||
* @example SET page, "elementHTMLSelector", "text"
|
||||
*
|
||||
|
||||
*/
|
||||
public async set({ pid, handle, file, address, value, name = null }): Promise<any> {
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
|
@ -973,6 +973,38 @@ export class SystemKeywords {
|
|||
return /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/.test(value);
|
||||
}
|
||||
|
||||
public static async getFilter(text) {
|
||||
let filter;
|
||||
const operators = [/\<\=/, /\<\>/, /\>\=/, /\</, /\>/, /\bnot in\b/, /\bin\b/, /\=/];
|
||||
let done = false;
|
||||
await CollectionUtil.asyncForEach(operators, async op => {
|
||||
var re = new RegExp(op, 'gi');
|
||||
const parts = text.split(re);
|
||||
|
||||
if (parts.length === 2 && !done) {
|
||||
filter = {
|
||||
columnName: parts[0].trim(),
|
||||
operator: op.toString().replace(/\\b/g, '').replace(/\//g, '').replace(/\\/g, '').replace(/\b/g, ''),
|
||||
value: parts[1].trim()
|
||||
};
|
||||
|
||||
// Swaps values and names in case of IN operators.
|
||||
|
||||
if (filter.operator === 'not in' || filter.operator === 'in') {
|
||||
const columnName = filter.columnName;
|
||||
filter.columnName = filter.value;
|
||||
filter.value = columnName;
|
||||
}
|
||||
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
|
||||
return filter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds a value or multi-value results in a tabular file.
|
||||
*
|
||||
|
@ -1093,35 +1125,6 @@ export class SystemKeywords {
|
|||
rows = results.text;
|
||||
}
|
||||
|
||||
let getFilter = async text => {
|
||||
let filter;
|
||||
const operators = [/\<\=/, /\<\>/, /\>\=/, /\</, /\>/, /\bnot in\b/, /\bin\b/, /\=/];
|
||||
let done = false;
|
||||
await CollectionUtil.asyncForEach(operators, async op => {
|
||||
var re = new RegExp(op, 'gi');
|
||||
const parts = text.split(re);
|
||||
|
||||
if (parts.length === 2 && !done) {
|
||||
filter = {
|
||||
columnName: parts[0].trim(),
|
||||
operator: op.toString().replace(/\\b/g, '').replace(/\//g, '').replace(/\\/g, '').replace(/\b/g, ''),
|
||||
value: parts[1].trim()
|
||||
};
|
||||
|
||||
// Swaps values and names in case of IN operators.
|
||||
|
||||
if (filter.operator === 'not in' || filter.operator === 'in') {
|
||||
const columnName = filter.columnName;
|
||||
filter.columnName = filter.value;
|
||||
filter.value = columnName;
|
||||
}
|
||||
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
|
||||
return filter;
|
||||
};
|
||||
|
||||
const contentLocale = min.core.getParam(
|
||||
min.instance,
|
||||
|
@ -1139,7 +1142,7 @@ export class SystemKeywords {
|
|||
|
||||
let filterIndex = 0;
|
||||
await CollectionUtil.asyncForEach(args, async arg => {
|
||||
const filter = await getFilter(arg);
|
||||
const filter = await SystemKeywords.getFilter(arg);
|
||||
if (!filter) {
|
||||
throw new Error(`BASIC: FIND filter has an error: ${arg} check this and publish .gbdialog again.`);
|
||||
}
|
||||
|
@ -2322,7 +2325,7 @@ export class SystemKeywords {
|
|||
}
|
||||
});
|
||||
|
||||
const equals =
|
||||
const equals =
|
||||
typeof (value) === 'string' && typeof (valueFound) === 'string' ?
|
||||
value?.toLowerCase() != valueFound?.toLowerCase() :
|
||||
value != valueFound;
|
||||
|
@ -2335,16 +2338,12 @@ export class SystemKeywords {
|
|||
obj[columnName] = value;
|
||||
let criteria = {};
|
||||
criteria[key1Original] = key1Value;
|
||||
let item;
|
||||
|
||||
await retry(
|
||||
async (bail) => {
|
||||
await t.update(obj, { where: criteria });
|
||||
},
|
||||
{
|
||||
retries: 5,
|
||||
}
|
||||
}, { retries: 5 }
|
||||
);
|
||||
return item;
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -2565,6 +2564,30 @@ export class SystemKeywords {
|
|||
return { contentType, ext, kind, category: kind['category'] };
|
||||
}
|
||||
|
||||
public async deleteFromStorage({ pid, table, criteria }) {
|
||||
const { min } = await DialogKeywords.getProcessInfo(pid);
|
||||
GBLog.info(`BASIC: DELETE (storage) '${table}' where ${criteria}.`);
|
||||
|
||||
const definition = this.getTableFromName(table, min);
|
||||
const filter = await SystemKeywords.getFilter(criteria);
|
||||
|
||||
await retry(
|
||||
async (bail) => {
|
||||
const options = { where: {} };
|
||||
options.where = {};
|
||||
|
||||
options.where[filter['columnName']] = filter['value'];
|
||||
await definition.destroy(options);
|
||||
|
||||
},
|
||||
{
|
||||
retries: 5,
|
||||
onRetry: (err) => { GBLog.error(`Retrying SaveToStorageBatch due to: ${err.message}.`); }
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public async deleteFile({ pid, file }) {
|
||||
const { min } = await DialogKeywords.getProcessInfo(pid);
|
||||
GBLog.info(`BASIC: DELETE '${file.name}'.`);
|
||||
|
|
28
src/util.ts
28
src/util.ts
|
@ -36,6 +36,34 @@
|
|||
|
||||
export class GBUtil {
|
||||
|
||||
public static repeat = function (chr, count) {
|
||||
var str = "";
|
||||
for (var x = 0; x < count; x++) { str += chr };
|
||||
return str;
|
||||
}
|
||||
|
||||
public static padL = function (value, width, pad) {
|
||||
if (!width || width < 1)
|
||||
return value;
|
||||
|
||||
if (!pad) pad = " ";
|
||||
var length = width - value.length
|
||||
if (length < 1) return value.substr(0, width);
|
||||
|
||||
return (GBUtil.repeat(pad, length) + value).substr(0, width);
|
||||
}
|
||||
public static padR = function (value, width, pad) {
|
||||
if (!width || width < 1)
|
||||
return value;
|
||||
|
||||
if (!pad) pad = " ";
|
||||
var length = width - value.length
|
||||
if (length < 1) value.substr(0, width);
|
||||
|
||||
return (value + GBUtil.repeat(pad, length)).substr(0, width);
|
||||
}
|
||||
|
||||
|
||||
public static sleep(ms) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
|
|
Loading…
Add table
Reference in a new issue