Use bson only for mongo
This commit is contained in:
parent
716e642d08
commit
599860b558
2 changed files with 53 additions and 27 deletions
|
@ -14,7 +14,7 @@ import { context, cache, auth } from "@budibase/backend-core"
|
||||||
import { getGlobalIDFromUserMetadataID } from "../db/utils"
|
import { getGlobalIDFromUserMetadataID } from "../db/utils"
|
||||||
import sdk from "../sdk"
|
import sdk from "../sdk"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { Datasource, Query } from "@budibase/types"
|
import { Datasource, Query, SourceName } from "@budibase/types"
|
||||||
|
|
||||||
import { isSQL } from "../integrations/utils"
|
import { isSQL } from "../integrations/utils"
|
||||||
import { interpolateSQL } from "../integrations/queries/sql"
|
import { interpolateSQL } from "../integrations/queries/sql"
|
||||||
|
@ -127,10 +127,16 @@ class QueryRunner {
|
||||||
|
|
||||||
// transform as required
|
// transform as required
|
||||||
if (transformer) {
|
if (transformer) {
|
||||||
const runner = new ScriptRunner(transformer, {
|
const runner = new ScriptRunner(
|
||||||
|
transformer,
|
||||||
|
{
|
||||||
data: rows,
|
data: rows,
|
||||||
params: enrichedParameters,
|
params: enrichedParameters,
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
parseBson: datasource.source === SourceName.MONGODB,
|
||||||
|
}
|
||||||
|
)
|
||||||
rows = runner.execute()
|
rows = runner.execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,15 +9,24 @@ const JS_TIMEOUT_MS = 1000
|
||||||
class ScriptRunner {
|
class ScriptRunner {
|
||||||
vm: IsolatedVM
|
vm: IsolatedVM
|
||||||
|
|
||||||
constructor(script: string, context: any) {
|
constructor(script: string, context: any, { parseBson = false } = {}) {
|
||||||
this.vm = new IsolatedVM({ memoryLimit: env.JS_RUNNER_MEMORY_LIMIT })
|
this.vm = new IsolatedVM({
|
||||||
|
memoryLimit: env.JS_RUNNER_MEMORY_LIMIT,
|
||||||
|
parseBson,
|
||||||
|
})
|
||||||
this.vm.context = {
|
this.vm.context = {
|
||||||
...context,
|
...context,
|
||||||
data: bson.BSON.serialize({ data: context.data }),
|
data: parseBson
|
||||||
|
? bson.BSON.serialize({ data: context.data })
|
||||||
|
: context.data,
|
||||||
results: { out: "" },
|
results: { out: "" },
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `let fn = () => {data=deserialize(data).data;\n${script}\n}; cb(JSON.parse(JSON.stringify(fn())));`
|
if (parseBson) {
|
||||||
|
script = `return JSON.parse(JSON.stringify((function(){data=deserialize(data).data;${script}})()));`
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = `const fn=function(){${script}};cb(fn());`
|
||||||
this.vm.code = code
|
this.vm.code = code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,13 +41,28 @@ class IsolatedVM {
|
||||||
vm: ivm.Context
|
vm: ivm.Context
|
||||||
#jail: ivm.Reference
|
#jail: ivm.Reference
|
||||||
script: ivm.Module = undefined!
|
script: ivm.Module = undefined!
|
||||||
#bsonModule: ivm.Module = undefined!
|
#bsonModule?: ivm.Module
|
||||||
|
|
||||||
constructor({ memoryLimit }: { memoryLimit: number }) {
|
constructor({
|
||||||
|
memoryLimit,
|
||||||
|
parseBson,
|
||||||
|
}: {
|
||||||
|
memoryLimit: number
|
||||||
|
parseBson: boolean
|
||||||
|
}) {
|
||||||
this.isolate = new ivm.Isolate({ memoryLimit })
|
this.isolate = new ivm.Isolate({ memoryLimit })
|
||||||
this.vm = this.isolate.createContextSync()
|
this.vm = this.isolate.createContextSync()
|
||||||
this.#jail = this.vm.global
|
this.#jail = this.vm.global
|
||||||
this.#jail.setSync("global", this.#jail.derefInto())
|
this.#jail.setSync("global", this.#jail.derefInto())
|
||||||
|
// this.#parseBson = parseBson
|
||||||
|
|
||||||
|
if (parseBson) {
|
||||||
|
const bsonSource = loadBundle(BundleType.BSON)
|
||||||
|
this.#bsonModule = this.isolate.compileModuleSync(bsonSource)
|
||||||
|
this.#bsonModule.instantiateSync(this.vm, specifier => {
|
||||||
|
throw new Error(`No imports allowed. Required: ${specifier}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue(key: string) {
|
getValue(key: string) {
|
||||||
|
@ -55,26 +79,22 @@ class IsolatedVM {
|
||||||
}
|
}
|
||||||
|
|
||||||
set code(code: string) {
|
set code(code: string) {
|
||||||
const bsonSource = loadBundle(BundleType.BSON)
|
if (this.#bsonModule) {
|
||||||
|
code = `import {deserialize} from "compiled_module";${code}`
|
||||||
this.#bsonModule = this.isolate.compileModuleSync(bsonSource)
|
}
|
||||||
this.#bsonModule.instantiateSync(this.vm, specifier => {
|
this.script = this.isolate.compileModuleSync(code)
|
||||||
throw new Error(`No imports allowed. Required: ${specifier}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.script = this.isolate.compileModuleSync(
|
|
||||||
`import {deserialize} from "compiled_module";${code}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runScript() {
|
runScript() {
|
||||||
|
if (this.#bsonModule) {
|
||||||
this.script.instantiateSync(this.vm, specifier => {
|
this.script.instantiateSync(this.vm, specifier => {
|
||||||
if (specifier === "compiled_module") {
|
if (specifier === "compiled_module") {
|
||||||
return this.#bsonModule
|
return this.#bsonModule!
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`"${specifier}" import not allowed`)
|
throw new Error(`"${specifier}" import not allowed`)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let result
|
let result
|
||||||
this.vm.global.setSync(
|
this.vm.global.setSync(
|
||||||
|
|
Loading…
Reference in a new issue