fix(basic.gblib): Allow TABLE keyword multiple times per file #383.
This commit is contained in:
parent
cb311832a4
commit
6e1c01e6fe
4 changed files with 127 additions and 62 deletions
|
@ -84,6 +84,28 @@ export class GBVMService extends GBService {
|
|||
});
|
||||
}
|
||||
|
||||
public static compare(obj1, obj2) {
|
||||
//check for obj2 overlapping props
|
||||
if (!Object.keys(obj2).every(key => obj1.hasOwnProperty(key))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check every key for being same
|
||||
return Object.keys(obj1).every(function (key) {
|
||||
|
||||
//if object
|
||||
if ((typeof obj1[key] == "object") && (typeof obj2[key] == "object")) {
|
||||
|
||||
//recursively check
|
||||
return GBVMService.compare(obj1[key], obj2[key]);
|
||||
} else {
|
||||
|
||||
//do the normal compare
|
||||
return obj1[key] === obj2[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async loadDialog(filename: string, folder: string, min: GBMinInstance) {
|
||||
const wordFile = filename;
|
||||
const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs';
|
||||
|
@ -175,9 +197,10 @@ export class GBVMService extends GBService {
|
|||
// Syncronizes Database Objects with the ones returned from "Word".
|
||||
|
||||
const tablesFile = urlJoin(folder, `${filename}.tables.json`);
|
||||
let sync = false;
|
||||
|
||||
if (Fs.existsSync(tablesFile)) {
|
||||
const minBoot = GBServer.globals.minBoot;
|
||||
GBLogEx.info(min, `BASIC: Sync TABLE keywords storage for ${min.botId}...`);
|
||||
|
||||
const tableDef = JSON.parse(Fs.readFileSync(tablesFile, 'utf8')) as any;
|
||||
|
||||
|
@ -204,18 +227,45 @@ export class GBVMService extends GBService {
|
|||
|
||||
const associations = [];
|
||||
|
||||
Object.keys(tableDef.tables).forEach(tableName => {
|
||||
const t = tableDef[tableName];
|
||||
tableDef.forEach(t => {
|
||||
Object.keys(t.fields).forEach(key => {
|
||||
let obj = t.fields[key];
|
||||
obj.type = getTypeBasedOnCondition(obj.type);
|
||||
if (obj.type.key === "TABLE") {
|
||||
obj.type.key = "INTEGER"
|
||||
associations.push({ from: t.name, to: obj.type.name });
|
||||
}
|
||||
if (key.toLowerCase() === 'id') {
|
||||
obj['primaryKey'] = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Only syncs if there is any difference.
|
||||
|
||||
const model = minBoot.core.sequelize.models[t.name];
|
||||
if (model) {
|
||||
|
||||
// Except Id, checks if has same number of fields.
|
||||
|
||||
let equals = 0;
|
||||
Object.keys(t.fields).forEach(key => {
|
||||
let obj1 = t.fields[key];
|
||||
let obj2 = model['fieldRawAttributesMap'][key];
|
||||
|
||||
if (key !== "id"){
|
||||
if (obj1 && obj2)
|
||||
{
|
||||
equals++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (equals != Object.keys(t.fields).length) {
|
||||
sync = true;
|
||||
}
|
||||
}
|
||||
|
||||
minBoot.core.sequelize.define(t.name, t.fields);
|
||||
});
|
||||
|
||||
|
@ -228,17 +278,24 @@ export class GBVMService extends GBService {
|
|||
|
||||
});
|
||||
|
||||
if (sync) {
|
||||
GBLogEx.info(min, `BASIC: Syncing changes for TABLE keywords (${min.botId})...`);
|
||||
|
||||
await minBoot.core.sequelize.sync({
|
||||
alter: true,
|
||||
force: false // Keep it false due to data loss danger.
|
||||
});
|
||||
await minBoot.core.sequelize.sync({
|
||||
alter: true,
|
||||
force: false // Keep it false due to data loss danger.
|
||||
});
|
||||
GBLogEx.info(min, `BASIC: Done sync for ${min.botId} storage tables...`);
|
||||
}
|
||||
else
|
||||
{
|
||||
GBLogEx.verbose(min, `BASIC: TABLE keywords already up to date (${min.botId})...`);
|
||||
}
|
||||
}
|
||||
|
||||
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
|
||||
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
||||
return filename;
|
||||
|
||||
}
|
||||
|
||||
public async translateBASIC(mainName, filename: any, min: GBMinInstance) {
|
||||
|
@ -404,7 +461,6 @@ export class GBVMService extends GBService {
|
|||
|
||||
// Creates an empty object that will receive Sequelize fields.
|
||||
|
||||
const path = DialogKeywords.getGBAIPath(min.botId, `gbdialog`);
|
||||
const tablesFile = `${task.file}.tables.json`;
|
||||
Fs.writeFileSync(tablesFile, JSON.stringify(task.tables));
|
||||
|
||||
|
@ -574,9 +630,9 @@ export class GBVMService extends GBService {
|
|||
tables.push({
|
||||
name: table, fields: fields
|
||||
});
|
||||
|
||||
|
||||
fields = [];
|
||||
|
||||
fields = {};
|
||||
table = null;
|
||||
emmit = false;
|
||||
}
|
||||
|
@ -604,7 +660,7 @@ export class GBVMService extends GBService {
|
|||
lines[i - 1] = emmit ? line : '';
|
||||
}
|
||||
|
||||
if (tables){
|
||||
if (tables) {
|
||||
tasks.push({
|
||||
kind: 'writeTableDefinition', file: filename, tables
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
'use strict';
|
||||
import { GBLog, GBMinInstance } from 'botlib';
|
||||
import { GBError, GBLog, GBMinInstance } from 'botlib';
|
||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||
|
@ -1795,38 +1795,33 @@ export class SystemKeywords {
|
|||
|
||||
const result = await fetch(url, options);
|
||||
|
||||
try {
|
||||
if (result.status === 2000) {
|
||||
|
||||
if (result.status === 2000) {
|
||||
|
||||
// Token expired.
|
||||
// Token expired.
|
||||
|
||||
GBLog.info(`Expired Token for ${url}.`);
|
||||
await DialogKeywords.setOption({ pid, name: `${proc.executable}-continuationToken`, value: null });
|
||||
GBLog.info(`Expired Token for ${url}.`);
|
||||
await DialogKeywords.setOption({ pid, name: `${proc.executable}-continuationToken`, value: null });
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
let res = JSON.parse(await result.text());
|
||||
|
||||
if (pageMode === "auto") {
|
||||
|
||||
continuationToken = res.next?.headers['MS-ContinuationToken'];
|
||||
|
||||
if (continuationToken) {
|
||||
GBLog.info(`Updating continuationToken for ${url}.`);
|
||||
await DialogKeywords.setOption({ pid, name: 'continuationToken', value: continuationToken });
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
// This is not JSON.
|
||||
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
if (result.status != 200) {
|
||||
throw new Error(`BASIC: GET ${result.status}: ${result.statusText}.`)
|
||||
}
|
||||
|
||||
let res = JSON.parse(await result.text());
|
||||
|
||||
if (pageMode === "auto") {
|
||||
|
||||
continuationToken = res.next?.headers['MS-ContinuationToken'];
|
||||
|
||||
if (continuationToken) {
|
||||
GBLog.info(`Updating continuationToken for ${url}.`);
|
||||
await DialogKeywords.setOption({ pid, name: 'continuationToken', value: continuationToken });
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1860,14 +1855,27 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async postByHttp({ pid, url, data, headers }) {
|
||||
const options = {
|
||||
json: data,
|
||||
headers: headers
|
||||
headers: headers,
|
||||
method: 'POST'
|
||||
};
|
||||
|
||||
let result = await fetch(url, options);
|
||||
GBLog.info(`[POST]: ${url} (${data}): ${result}`);
|
||||
if (typeof (data) === 'object') {
|
||||
options['json'] = data;
|
||||
}
|
||||
else {
|
||||
options['body'] = data;
|
||||
}
|
||||
|
||||
return result ? (typeof result === 'object' ? result : JSON.parse(result)) : true;
|
||||
let result = await fetch(url, options);
|
||||
const text = await result.text();
|
||||
GBLog.info(`BASIC: POST ${url} (${data}): ${text}`);
|
||||
|
||||
if (result.status != 200) {
|
||||
throw new Error(`BASIC: POST ${result.status}: ${result.statusText}.`)
|
||||
}
|
||||
|
||||
let res = JSON.parse(text);
|
||||
return res;
|
||||
}
|
||||
|
||||
public async numberOnly({ pid, text }) {
|
||||
|
@ -2101,21 +2109,21 @@ export class SystemKeywords {
|
|||
maxLines = Number.parseInt(params.maxLines).valueOf();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Choose data sources based on file type (HTML Table, data variable or sheet file)
|
||||
|
||||
|
||||
let storage = file.indexOf('.xlsx') !== -1;
|
||||
let results;
|
||||
let header = [], rows = [];
|
||||
const minBoot = GBServer.globals.minBoot;
|
||||
let t;
|
||||
|
||||
|
||||
if (storage) {
|
||||
t = minBoot.core.sequelize.models[file];
|
||||
rows = await t.findAll({});
|
||||
header = rows['dataNames'];
|
||||
} else {
|
||||
|
||||
|
||||
const botId = min.instance.botId;
|
||||
const path = DialogKeywords.getGBAIPath(botId, 'gbdata');
|
||||
|
||||
|
@ -2131,15 +2139,15 @@ export class SystemKeywords {
|
|||
results = await client
|
||||
.api(
|
||||
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:CZ${maxLines}')`
|
||||
)
|
||||
)
|
||||
.get();
|
||||
|
||||
header = results.text[0];
|
||||
rows = results.text;
|
||||
}
|
||||
|
||||
// As BASIC uses arrays starting with 1 (one) as index,
|
||||
// a ghost element is added at 0 (zero) position.
|
||||
|
||||
header = results.text[0];
|
||||
rows = results.text;
|
||||
}
|
||||
|
||||
// As BASIC uses arrays starting with 1 (one) as index,
|
||||
// a ghost element is added at 0 (zero) position.
|
||||
|
||||
let table = [];
|
||||
table.push({ gbarray: '0' });
|
||||
|
@ -2212,7 +2220,7 @@ export class SystemKeywords {
|
|||
const address = `${cell}:${cell}`;
|
||||
|
||||
if (value !== found[columnName]) {
|
||||
|
||||
|
||||
await this.set({ pid, handle: null, file, address, value });
|
||||
merges++;
|
||||
}
|
||||
|
|
|
@ -696,7 +696,7 @@ export class GBMinService {
|
|||
const manager = new NlpManager({ languages: ['pt'], forceNER: true });
|
||||
min['nerEngine'] = manager;
|
||||
|
||||
if (GBServer.globals.minBoot === undefined) {
|
||||
if (!GBServer.globals.minBoot.botId) {
|
||||
GBServer.globals.minBoot = min;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ import http from 'http';
|
|||
import mkdirp from 'mkdirp';
|
||||
import Path from 'path';
|
||||
import * as Fs from 'fs';
|
||||
import { GBLog, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js';
|
||||
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||
import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js';
|
||||
|
@ -97,6 +97,7 @@ export class GBServer {
|
|||
GBServer.globals.appPackages = [];
|
||||
GBServer.globals.sysPackages = [];
|
||||
GBServer.globals.minInstances = [];
|
||||
GBServer.globals.minBoot = new GBMinInstance();
|
||||
GBServer.globals.wwwroot = null;
|
||||
GBServer.globals.entryPointDialog = null;
|
||||
GBServer.globals.debuggers = [];
|
||||
|
@ -217,7 +218,7 @@ export class GBServer {
|
|||
);
|
||||
|
||||
instances.push(instance);
|
||||
GBServer.globals.minBoot
|
||||
GBServer.globals.minBoot.instance = instances[0];
|
||||
GBServer.globals.bootInstance = instances[0];
|
||||
await deployer.deployBotFull(instance, GBServer.globals.publicAddress);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue