fix(basic.gblib): Allow TABLE keyword multiple times per file #383.

This commit is contained in:
Rodrigo Rodriguez 2023-10-20 13:39:34 -03:00
parent cb311832a4
commit 6e1c01e6fe
4 changed files with 127 additions and 62 deletions

View file

@ -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) { public async loadDialog(filename: string, folder: string, min: GBMinInstance) {
const wordFile = filename; const wordFile = filename;
const vbsFile = filename.substr(0, filename.indexOf('docx')) + 'vbs'; 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". // Syncronizes Database Objects with the ones returned from "Word".
const tablesFile = urlJoin(folder, `${filename}.tables.json`); const tablesFile = urlJoin(folder, `${filename}.tables.json`);
let sync = false;
if (Fs.existsSync(tablesFile)) { if (Fs.existsSync(tablesFile)) {
const minBoot = GBServer.globals.minBoot; 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; const tableDef = JSON.parse(Fs.readFileSync(tablesFile, 'utf8')) as any;
@ -204,18 +227,45 @@ export class GBVMService extends GBService {
const associations = []; const associations = [];
Object.keys(tableDef.tables).forEach(tableName => { tableDef.forEach(t => {
const t = tableDef[tableName];
Object.keys(t.fields).forEach(key => { Object.keys(t.fields).forEach(key => {
let obj = t.fields[key]; let obj = t.fields[key];
obj.type = getTypeBasedOnCondition(obj.type); obj.type = getTypeBasedOnCondition(obj.type);
if (obj.type.key === "TABLE") { if (obj.type.key === "TABLE") {
obj.type.key = "INTEGER"
associations.push({ from: t.name, to: obj.type.name }); associations.push({ from: t.name, to: obj.type.name });
} }
if (key.toLowerCase() === 'id') { if (key.toLowerCase() === 'id') {
obj['primaryKey'] = true; 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); 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({ await minBoot.core.sequelize.sync({
alter: true, alter: true,
force: false // Keep it false due to data loss danger. 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'); const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
return filename; return filename;
} }
public async translateBASIC(mainName, filename: any, min: GBMinInstance) { 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. // Creates an empty object that will receive Sequelize fields.
const path = DialogKeywords.getGBAIPath(min.botId, `gbdialog`);
const tablesFile = `${task.file}.tables.json`; const tablesFile = `${task.file}.tables.json`;
Fs.writeFileSync(tablesFile, JSON.stringify(task.tables)); Fs.writeFileSync(tablesFile, JSON.stringify(task.tables));
@ -576,7 +632,7 @@ export class GBVMService extends GBService {
}); });
fields = []; fields = {};
table = null; table = null;
emmit = false; emmit = false;
} }
@ -604,7 +660,7 @@ export class GBVMService extends GBService {
lines[i - 1] = emmit ? line : ''; lines[i - 1] = emmit ? line : '';
} }
if (tables){ if (tables) {
tasks.push({ tasks.push({
kind: 'writeTableDefinition', file: filename, tables kind: 'writeTableDefinition', file: filename, tables
}); });

View file

@ -30,7 +30,7 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
'use strict'; 'use strict';
import { GBLog, GBMinInstance } from 'botlib'; import { GBError, GBLog, GBMinInstance } from 'botlib';
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
import { CollectionUtil } from 'pragmatismo-io-framework'; import { CollectionUtil } from 'pragmatismo-io-framework';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
@ -1795,38 +1795,33 @@ export class SystemKeywords {
const result = await fetch(url, options); 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}.`); return null;
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;
} }
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 }) { public async postByHttp({ pid, url, data, headers }) {
const options = { const options = {
json: data, headers: headers,
headers: headers method: 'POST'
}; };
let result = await fetch(url, options); if (typeof (data) === 'object') {
GBLog.info(`[POST]: ${url} (${data}): ${result}`); 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 }) { public async numberOnly({ pid, text }) {
@ -2131,15 +2139,15 @@ export class SystemKeywords {
results = await client results = await client
.api( .api(
`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:CZ${maxLines}')` `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:CZ${maxLines}')`
) )
.get(); .get();
header = results.text[0]; header = results.text[0];
rows = results.text; rows = results.text;
} }
// As BASIC uses arrays starting with 1 (one) as index, // As BASIC uses arrays starting with 1 (one) as index,
// a ghost element is added at 0 (zero) position. // a ghost element is added at 0 (zero) position.
let table = []; let table = [];
table.push({ gbarray: '0' }); table.push({ gbarray: '0' });

View file

@ -696,7 +696,7 @@ export class GBMinService {
const manager = new NlpManager({ languages: ['pt'], forceNER: true }); const manager = new NlpManager({ languages: ['pt'], forceNER: true });
min['nerEngine'] = manager; min['nerEngine'] = manager;
if (GBServer.globals.minBoot === undefined) { if (!GBServer.globals.minBoot.botId) {
GBServer.globals.minBoot = min; GBServer.globals.minBoot = min;
} }

View file

@ -43,7 +43,7 @@ import http from 'http';
import mkdirp from 'mkdirp'; import mkdirp from 'mkdirp';
import Path from 'path'; import Path from 'path';
import * as Fs from 'fs'; 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 { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js';
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js'; import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js';
import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js'; import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js';
@ -97,6 +97,7 @@ export class GBServer {
GBServer.globals.appPackages = []; GBServer.globals.appPackages = [];
GBServer.globals.sysPackages = []; GBServer.globals.sysPackages = [];
GBServer.globals.minInstances = []; GBServer.globals.minInstances = [];
GBServer.globals.minBoot = new GBMinInstance();
GBServer.globals.wwwroot = null; GBServer.globals.wwwroot = null;
GBServer.globals.entryPointDialog = null; GBServer.globals.entryPointDialog = null;
GBServer.globals.debuggers = []; GBServer.globals.debuggers = [];
@ -217,7 +218,7 @@ export class GBServer {
); );
instances.push(instance); instances.push(instance);
GBServer.globals.minBoot GBServer.globals.minBoot.instance = instances[0];
GBServer.globals.bootInstance = instances[0]; GBServer.globals.bootInstance = instances[0];
await deployer.deployBotFull(instance, GBServer.globals.publicAddress); await deployer.deployBotFull(instance, GBServer.globals.publicAddress);