nodejs vm+ babel ast 实现类似cube.js schema 的处理能力
2021-03-02 05:27
标签:log 替换 图片 === span str efault ace 原理 很简单主要是学习下cube.js 关于schema 的特殊处理了解下原理 简单说明,对于info 我们认为应该一个函数,同时app 也是我们一个全局变量,类似cube.js 的cube https://babeljs.io/docs/en/ nodejs vm+ babel ast 实现类似cube.js schema 的处理能力 标签:log 替换 图片 === span str efault ace 原理 原文地址:https://www.cnblogs.com/rongfengliang/p/14375123.html
以下部分代码参考了cube.js compiler 部分参考项目
{
"name": "vm-scripts",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@babel/core": "^7.12.10",
"@babel/generator": "^7.12.11",
"@babel/parser": "^7.12.11",
"@babel/preset-env": "^7.12.11",
"@babel/traverse": "^7.12.12",
"@babel/types": "^7.12.12"
}
}
app("dalong2",{
"name":{
age:333,
version:"v1",
name:"v1 rongfengliang",
full_name: `${JSON.stringify(COMPILE_CONTEXT)}---demoapp`
},
"info":`${COMPILE_CONTEXT.name}`
})
同时我们也提供了一个全局变量COMPILE_CONTEXT,类似cube.js 编译时的schema 处理,当然其他的也是可以扩展的
主要是将info 属性变为info: COMPILE_CONTEXT=>
${COMPILE_CONTEXT.name},这样就和cube.js sql 是一个函数类似了
参考代码const vm = require("vm")
const fs = require("fs")
const { parse } = require("@babel/parser")
const generate = require("@babel/generator")
const traverse = require("@babel/traverse")
const t = require("@babel/types")
// 进行数据的中间存储
const cubes = [];
const field = /^.*(info|sql|conf)$/
?
// 包装的基于babel ast+ vm 的处理函数
function call_vm(context) {
const code = fs.readFileSync("./cube.js", {
encoding: "utf8"
}).toString();
const ast1 = parse(
code,
{
sourceFilename: "cube.js",
sourceType: ‘module‘,
plugins: [‘objectRestSpread‘]
},
);
traverse.default(ast1, {
ObjectProperty(path) {
console.log("path info:",JSON.stringify(path.node))
// 进行ast类型判断处理,同时进行as的替换处理,将info 的包含为一个箭头函数
if (path.node.key.type === ‘StringLiteral‘ && path.node.key.value.match(field)) {
path.get(‘value‘).replaceWith(
t.arrowFunctionExpression([t.identifier("COMPILE_CONTEXT")], path.node.value, false)
);
}
}
})
const output = generate.default(
ast1,
{},
code
);
console.log(output)
// 使用vm 沙箱提供数据隔离的环境
vm.runInNewContext(output.code, {
// 提供上下文的函数
app: (name, conf) => {
cubes.push({
name:name,
conf:conf
})
},
COMPILE_CONTEXT: context
})
}
?
context = {
name: "rongfengliangdemoapp",
appid: "app001",
auth: {
name: "dalong",
age: 22
}
}
call_vm(context)
cubes.forEach(cube => {
console.log(cube)
let result = cube.conf.info(cube.conf.name)
console.log("=======",result,"=======")
});
参考资料
https://astexplorer.net/
https://cube.dev/docs/schema/dynamic-schema-creation
https://nodejs.org/api/vm.html
文章标题:nodejs vm+ babel ast 实现类似cube.js schema 的处理能力
文章链接:http://soscw.com/index.php/essay/58892.html