@ones-op/node-host
Version:
ONES Open Platform Node.js plugin host
78 lines (77 loc) • 3.06 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginVM = void 0;
const node_fs_1 = __importDefault(require("node:fs"));
const node_vm_1 = __importDefault(require("node:vm"));
class MethodNotFoundError extends Error {
}
// 部分插件因为错误安装了与内置模块同名的社区模块
// 又因为 vm2 做了兼容处理 导致插件可以正常启动
// 实际上与内置模块同名的社区模块没有参与实际业务代码
// vm 的 require 调整了优先策略
// 先查询第三方的社区模块 如存在会返回第三方的社区模块
// 该策略也可以提前暴露非法安装模块的问题
// 目前先保留一个白名单列表
// 如果是内置模块的白名单 则不查询第三方的社区模块
const NODE_PACKAGE_WHITE_LIST = ['https'];
class PluginVM {
run(pluginInfo) {
const { code, packagePath = '', env } = pluginInfo;
const proxy = {
global: {},
exports: {},
require: (packageName) => {
if (NODE_PACKAGE_WHITE_LIST.includes(packageName)) {
// 白名单模块为 node 内置模块
}
else {
// 拼接相对路径为绝对路径
const path = `${packagePath}/${packageName}`;
// 检查一下该模块是否存在
if (node_fs_1.default.existsSync(path)) {
// 若存在则认为是 node_modules 模块
// 尝试引用
// 原则上插件打包后的代码不存在 require 引用
// 当前仅为防御性代码
return require(path);
}
}
// 默认为 node 内置模块
return require(packageName);
},
console,
process,
TextEncoder,
TextDecoder,
Buffer,
onesEnv: env,
setTimeout,
setInterval,
setImmediate,
clearTimeout,
clearInterval,
clearImmediate,
version: parseInt(process.versions.node.split('.')[0]),
};
proxy.global = proxy;
const context = node_vm_1.default.createContext(proxy);
const script = new node_vm_1.default.Script(code, 'index.js');
script.runInContext(context);
this.context = context.exports;
}
async runMethod(method, ...args) {
if (!this.context)
throw new Error('VM not initialized');
if (!this.context[method]) {
throw new MethodNotFoundError('Method not found' + method);
}
return await this.context[method](...args);
}
isMethodNotFoundError(err) {
return err instanceof MethodNotFoundError;
}
}
exports.PluginVM = PluginVM;