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) {
|
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));
|
||||||
|
|
||||||
|
@ -574,9 +630,9 @@ export class GBVMService extends GBService {
|
||||||
tables.push({
|
tables.push({
|
||||||
name: table, fields: fields
|
name: table, fields: fields
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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}.`);
|
GBLog.info(`Expired Token for ${url}.`);
|
||||||
await DialogKeywords.setOption({ pid, name: `${proc.executable}-continuationToken`, value: null });
|
await DialogKeywords.setOption({ pid, name: `${proc.executable}-continuationToken`, value: null });
|
||||||
|
|
||||||
return 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 }) {
|
||||||
|
@ -2101,21 +2109,21 @@ export class SystemKeywords {
|
||||||
maxLines = Number.parseInt(params.maxLines).valueOf();
|
maxLines = Number.parseInt(params.maxLines).valueOf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose data sources based on file type (HTML Table, data variable or sheet file)
|
// Choose data sources based on file type (HTML Table, data variable or sheet file)
|
||||||
|
|
||||||
let storage = file.indexOf('.xlsx') !== -1;
|
let storage = file.indexOf('.xlsx') !== -1;
|
||||||
let results;
|
let results;
|
||||||
let header = [], rows = [];
|
let header = [], rows = [];
|
||||||
const minBoot = GBServer.globals.minBoot;
|
const minBoot = GBServer.globals.minBoot;
|
||||||
let t;
|
let t;
|
||||||
|
|
||||||
if (storage) {
|
if (storage) {
|
||||||
t = minBoot.core.sequelize.models[file];
|
t = minBoot.core.sequelize.models[file];
|
||||||
rows = await t.findAll({});
|
rows = await t.findAll({});
|
||||||
header = rows['dataNames'];
|
header = rows['dataNames'];
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const botId = min.instance.botId;
|
const botId = min.instance.botId;
|
||||||
const path = DialogKeywords.getGBAIPath(botId, 'gbdata');
|
const path = DialogKeywords.getGBAIPath(botId, 'gbdata');
|
||||||
|
|
||||||
|
@ -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' });
|
||||||
|
@ -2212,7 +2220,7 @@ export class SystemKeywords {
|
||||||
const address = `${cell}:${cell}`;
|
const address = `${cell}:${cell}`;
|
||||||
|
|
||||||
if (value !== found[columnName]) {
|
if (value !== found[columnName]) {
|
||||||
|
|
||||||
await this.set({ pid, handle: null, file, address, value });
|
await this.set({ pid, handle: null, file, address, value });
|
||||||
merges++;
|
merges++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue