diff --git a/packages/tools/src/ScriptWriter.ts b/packages/tools/src/ScriptWriter.ts index 93d143212..3bf0e84d5 100644 --- a/packages/tools/src/ScriptWriter.ts +++ b/packages/tools/src/ScriptWriter.ts @@ -1,7 +1,21 @@ import _uniq from 'lodash/uniq'; -import { extractShellApiFunctionName, extractShellApiPlugins } from './packageTools'; +import { evalShellApiFunctionName, extractShellApiFunctionName, extractShellApiPlugins } from './packageTools'; -export class ScriptWriterJavaScript { +export interface ScriptWriterGeneric { + allocVariable(prefix?: string); + endLine(); + assign(variableName: string, functionName: string, props: any); + assignValue(variableName: string, jsonValue: any); + requirePackage(packageName: string); + copyStream(sourceVar: string, targetVar: string, colmapVar?: string, progressName?: string); + importDatabase(options: any); + dataReplicator(options: any); + comment(s: string); + zipDirectory(inputDirectory: string, outputFile: string); + getScript(schedule?: any): any; +} + +export class ScriptWriterJavaScript implements ScriptWriterGeneric { s = ''; packageNames: string[] = []; varCount = 0; @@ -78,7 +92,7 @@ export class ScriptWriterJavaScript { } } -export class ScriptWriterJson { +export class ScriptWriterJson implements ScriptWriterGeneric { s = ''; packageNames: string[] = []; varCount = 0; @@ -110,6 +124,10 @@ export class ScriptWriterJson { this.packageNames.push(...extractShellApiPlugins(functionName, props)); } + requirePackage(packageName) { + this.packageNames.push(packageName); + } + assignValue(variableName, jsonValue) { this.commands.push({ type: 'assignValue', @@ -167,17 +185,66 @@ export class ScriptWriterJson { } } -export function jsonScriptToJavascript(json) { - const { schedule, commands, packageNames } = json; - const script = new ScriptWriterJavaScript(); - for (const packageName of packageNames) { - if (!/^dbgate-plugin-.*$/.test(packageName)) { - throw new Error('Unallowed package name:' + packageName); - } - script.packageNames.push(packageName); +export class ScriptWriterEval implements ScriptWriterGeneric { + s = ''; + varCount = 0; + commands = []; + dbgateApi: any; + requirePlugin: (name: string) => any; + variables: { [name: string]: any } = {}; + + constructor(dbgateApi, requirePlugin, varCount = '0') { + this.varCount = parseInt(varCount) || 0; + this.dbgateApi = dbgateApi; + this.requirePlugin = requirePlugin; } - for (const cmd of commands) { + allocVariable(prefix = 'var') { + this.varCount += 1; + return `${prefix}${this.varCount}`; + } + + endLine() {} + + requirePackage(packageName) {} + + async assign(variableName, functionName, props) { + const func = evalShellApiFunctionName(functionName, this.dbgateApi, this.requirePlugin); + this.variables[variableName] = await func(props); + } + + assignValue(variableName, jsonValue) { + this.variables[variableName] = jsonValue; + } + + async copyStream(sourceVar, targetVar, colmapVar = null, progressName?: string) { + await this.dbgateApi.copyStream(this.variables[sourceVar], this.variables[targetVar], { + progressName, + columns: colmapVar ? this.variables[colmapVar] : null, + }); + } + + comment(text) {} + + async importDatabase(options) { + await this.dbgateApi.importDatabase(options); + } + + async dataReplicator(options) { + await this.dbgateApi.dataReplicator(options); + } + + async zipDirectory(inputDirectory, outputFile) { + await this.dbgateApi.zipDirectory(inputDirectory, outputFile); + } + + getScript(schedule?: any) { + throw new Error('Not implemented'); + } +} + +export function playJsonScriptWriter(json, script) { + for (const cmd of json.commands) { switch (cmd.type) { case 'assign': script.assignCore(cmd.variableName, cmd.functionName, cmd.props); @@ -205,6 +272,19 @@ export function jsonScriptToJavascript(json) { break; } } +} + +export function jsonScriptToJavascript(json) { + const { schedule, packageNames } = json; + const script = new ScriptWriterJavaScript(); + for (const packageName of packageNames) { + if (!/^dbgate-plugin-.*$/.test(packageName)) { + throw new Error('Unallowed package name:' + packageName); + } + script.packageNames.push(packageName); + } + + playJsonScriptWriter(json, script); return script.getScript(schedule); } diff --git a/packages/tools/src/packageTools.ts b/packages/tools/src/packageTools.ts index b0c506261..9a0735142 100644 --- a/packages/tools/src/packageTools.ts +++ b/packages/tools/src/packageTools.ts @@ -35,6 +35,14 @@ export function extractShellApiFunctionName(functionName) { return `dbgateApi.${functionName}`; } +export function evalShellApiFunctionName(functionName, dbgateApi, requirePlugin) { + const nsMatch = functionName.match(/^([^@]+)@([^@]+)/); + if (nsMatch) { + return requirePlugin(nsMatch[2]).shellApi[nsMatch[1]]; + } + return dbgateApi[functionName]; +} + export function findEngineDriver(connection, extensions: ExtensionsDirectory): EngineDriver { if (!extensions) { return null; diff --git a/packages/web/src/impexp/createImpExpScript.ts b/packages/web/src/impexp/createImpExpScript.ts index e280586bb..195117528 100644 --- a/packages/web/src/impexp/createImpExpScript.ts +++ b/packages/web/src/impexp/createImpExpScript.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import moment from 'moment'; -import { ScriptWriterJavaScript, ScriptWriterJson } from 'dbgate-tools'; +import { ScriptWriterGeneric, ScriptWriterJavaScript, ScriptWriterJson } from 'dbgate-tools'; import getAsArray from '../utility/getAsArray'; import { getConnectionInfo } from '../utility/metadataLoaders'; import { findEngineDriver, findObjectLike } from 'dbgate-tools'; @@ -203,12 +203,12 @@ export function normalizeExportColumnMap(colmap) { return null; } -export default async function createImpExpScript(extensions, values, forceScript = false) { +export default async function createImpExpScript(extensions, values, format = undefined) { const config = getCurrentConfig(); - const script = - config.allowShellScripting || forceScript - ? new ScriptWriterJavaScript(values.startVariableIndex || 0) - : new ScriptWriterJson(values.startVariableIndex || 0); + let script: ScriptWriterGeneric = new ScriptWriterJson(values.startVariableIndex || 0); + if (format == 'script' && config.allowShellScripting) { + script = new ScriptWriterJavaScript(values.startVariableIndex || 0); + } const [sourceConnection, sourceDriver] = await getConnection( extensions, diff --git a/packages/web/src/tabs/ImportExportTab.svelte b/packages/web/src/tabs/ImportExportTab.svelte index 04935cd8b..cfe8a9849 100644 --- a/packages/web/src/tabs/ImportExportTab.svelte +++ b/packages/web/src/tabs/ImportExportTab.svelte @@ -167,7 +167,7 @@ const handleGenerateScript = async e => { const values = $formValues as any; - const code = await createImpExpScript($extensions, values, true); + const code = await createImpExpScript($extensions, values, 'script'); openNewTab( { title: 'Shell #', @@ -183,7 +183,7 @@ progressHolder = {}; const values = $formValues as any; busy = true; - const script = await createImpExpScript($extensions, values); + const script = await createImpExpScript($extensions, values, 'json'); executeNumber += 1; let runid = runnerId; const resp = await apiCall('runners/start', { script });