fix(basic.gblib): DELETE keyword in storage #400. @othonlima

This commit is contained in:
Rodrigo Rodriguez 2024-01-13 14:23:04 -03:00
parent d23524b7b8
commit 86313b7684
7 changed files with 184 additions and 90 deletions

View file

@ -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()
});

View file

@ -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",

View file

@ -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 () {

View file

@ -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 });

View file

@ -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++] = [

View file

@ -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}'.`);

View file

@ -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);