plv8 是postgres 的一个比较强大的插件,社区有人基于babel,browserify 实现了一个方便的require 模块加载
实际上官方也有介绍过了类似的基于数据库存储js,然后通过eval 动态加载代码,以下是一个简单的试用

环境准备

  • docker-compose 文件
 
  1. version: '3.6'
  1. services:
  1.  postgres:
  1.    image: dalongrong/plv8:2.3.12
  1.    ports:
  1.    - "5432:5432"
  1.    environment:
  1.    - "POSTGRES_PASSWORD=dalong"
  1.  graphql-engine:
  1.    image: hasura/graphql-engine:v1.0.0-beta.9
  1.    ports:
  1.    - "8080:8080"
  1.    depends_on:
  1.    - "postgres"
  1.    environment:
  1.      HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:dalong@postgres:5432/postgres
  1.      HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
  1.      HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
  • node-plv8 项目
    package.json
 
  1. {
  1.  "name": "node-plv8",
  1.  "version": "1.0.0",
  1.  "main": "app.js",
  1.  "bin": "app.js",
  1.  "license": "MIT",
  1.  "dependencies": {
  1.    "cuid": "^2.1.6",
  1.    "knex": "^0.20.1",
  1.    "lodash": "^4.17.15",
  1.    "pg": "^7.12.1",
  1.    "plv8": "^2.1.4",
  1.    "uuid": "^3.3.3"
  1. },
  1.  "scripts": {
  1.    "init:app": "node app"
  1. }
  1. }

app.js
进行模块的注册,目前包含了lodash以及一个自己的

 
  1. // setup plv8 connection
  1. const PLV8 = require('plv8')
  1. const knex = require('knex')
  1. const knexHandle = knex({
  1.    client: 'pg',
  1.    connection: {
  1.      host: "127.0.0.1",
  1.      user: "postgres",
  1.      password: "dalong",
  1.      database: "postgres"
  1.   }
  1. })
  1. const plv8 = new PLV8(knexHandle)
  1. // setup a log listener
  1. plv8.on('log:error', msg => {
  1.  console.error(msg)
  1. })
  1. // install the lodash module so that it can be loaded (via require()) later
  1. plv8.install({modulePath:require.resolve('lodash'),moduleName:"lodash"})
  1. .then(() => {
  1.    // eval some code
  1.    return plv8.eval(() => {
  1.      const _ = require('lodash')
  1.      return _.map([ 1, 2, 3 ], e => e + 1)
  1.   })
  1. })
  1. .then(result => {
  1.   console.log(result)
  1. }).catch(err=>{
  1.      console.log(err)
  1. })
  1.    plv8.install({modulePath:require.resolve("./login"),moduleName:"login"})
  1. .then(() => {
  1.    // eval some code
  1.    return plv8.eval(() => {
  1.      const login = require('login')
  1.      return login
  1.   })
  1. })
  1. .then(result => {
  1.   console.log(result)
  1. }).catch(err=>{
  1.      console.log(err)
  1. })

login.js 模块

  1. module.exports = {
  1.    name:"dalong",
  1.    age:333
  1. }

运行&&测试

  • 启动docker 服务
  1. docker-compose up -d
  • 运行nodejs demo 服务
  1. yarn init:app
  • 效果
    目前有关于pg 通信的一些异常log,可能是和代码很就已经没维护,包版本兼容pg 的问题,后边
    调试研究下
 
  1. yarn run v1.17.3
  1. $ node app
  1. (node:56198) UnhandledPromiseRejectionWarning: error: syntax error at or near ":"
  1.    at Connection.parseE (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:604:11)
  1.    at Connection.parseMessage (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:401:19)
  1.    at Socket.<anonymous> (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:121:22)
  1.    at Socket.emit (events.js:182:13)
  1.    at addChunk (_stream_readable.js:283:12)
  1.    at readableAddChunk (_stream_readable.js:264:11)
  1.    at Socket.Readable.push (_stream_readable.js:219:10)
  1.    at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
  1. (node:56198) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
  1. (node:56198) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  1. Use async .hasTable to check if table exists and then use plain .createTable. Since .createTableIfNotExists actually just generates plain "CREATE TABLE IF NOT EXIST..." query it will not work correctly if there are any alter table queries generated for columns afterwards. To not break old migrations this function is left untouched for now, but it should not be used when writing new code and it is removed from documentation.
  1. Use async .hasTable to check if table exists and then use plain .createTable. Since .createTableIfNotExists actually just generates plain "CREATE TABLE IF NOT EXIST..." query it will not work correctly if there are any alter table queries generated for columns afterwards. To not break old migrations this function is left untouched for now, but it should not be used when writing new code and it is removed from documentation.
  1. { name: 'dalong', age: 333 }
  1. [ 2, 3, 4 ]
 

sql 方式调用

  • 函数定义
  1. CREATE or replace FUNCTION dalong2() RETURNS json AS
  1. $$
  1.    const login = require('login')
  1.    return JSON.stringify(login);
  1. $$
  1. LANGUAGE plv8;
  • 查询
  1. SET plv8.start_proc = 'v8.plv8_init';
  1. select * from dalong2();
 
  • 效果
  1. {"name":"dalong","age":333}

简单原理说明

node plv8 将生成的js 通过browserify 以及babel 转换,存储在v8 schema 中的modules 表中
同时注册了SET plv8.start_proc = 'v8.plv8_init'; 需要的plv8.init 函数,同时也注册了几个依赖的
函数,代码的执行通过的是eval 函数,整体上还是比较简单的,但是实现的功能确实很方便的

参考资料

https://pgxn.org/dist/plv8/doc/plv8.html
https://github.com/plv8/plv8
https://plv8.github.io/
https://github.com/rongfengliang/plv8-require-learning

plv8 require 模块试用的更多相关文章

  1. <5>Lua多返回值和require模块

    1.多返回值 --1: 一个lua函数可以返回多个返回值: --2: 定义多个变量来接受多返回值 --3: lua的unpack函数,解开表里的单个的值; 结果 2.require模块 --1: 第一 ...

  2. Node.js require 模块加载原理 All In One

    Node.js require 模块加载原理 All In One require 加载模块,搜索路径 "use strict"; /** * * @author xgqfrms ...

  3. nodejs的require模块及路径

    在nodejs中,模块大概可以分为核心模块和文件模块. 核心模块是被编译成二进制代码,引用的时候只需require表示符即可,如(require('net')). 文件模块,则是指js文件.json文 ...

  4. webToImage (网页转图片)模块试用分享

    模块介绍: 本模块封装了把 webview 转换成图片的功能.调用本模块的transImage接口,可把当前 webview显示的内容转换成一张图片.注意,本模块只能把当前的webview页面转换为图 ...

  5. nginx unit nodejs 模块试用(续)

      最新(应该是18 年了)nginx unit 发布了新的版本,对于nodejs 的支持有很大的改进,上次测试过,问题还是 比较多,这次使用新版本在测试下对于nodejs 的支持,以及以前block ...

  6. nginx unit nodejs 模块试用

      unit 对于nodejs 的支持是在10.25 发布的,基本能用,但是依然有好多问题,当前在测试的时候就发现,请求之后会block , 相关的issue 已经有人反馈了,最好使用源码编译,方便测 ...

  7. angular的require模块的使用($requireProvider的作用)

      今天我们学习一下angular的另一个几乎被忽略的模块angular-require 先给出链接地址(git:)   https://github.com/Treri/angular-requir ...

  8. require模块开发(一)

    1.require下载和加载 1.1 下载 工欲善其事必先利其器,先下载require.js下载地址, 然后添加 require.js 到 scripts 目录 1.2 加载 然后加载require ...

  9. sublime 打开import require 模块文件的url 或路径的插件

    结果一番周折,终于发现sublime提供的一个插件(open url)可以实现打开import file 路径的文件,比如import demo from “../path” 的文件在新窗口或者新标签 ...

随机推荐

  1. Windows 配置Apache+CGI

    首先还是先在官网下载Apache,版本为Apache 2.4.26 x64,下载64位的地址为:http://www.apachehaus.com/cgi-bin/download.plx 下载完成后 ...

  2. 第十一次作业 LL(1)文法的判断,递归下降分析程序

    1. 文法 G(S): (1)S -> AB (2)A ->Da|ε (3)B -> cC (4)C -> aADC |ε (5)D -> b|ε 验证文法 G(S)是不 ...

  3. 阿里云服务器ECS安全组设置 允许ping

    另外也需要服务器的设置允许ping

  4. GNU Makefile中的条件控制结构

    在常见的编程语言中,使用条件控制结构诸如if ... else if ... else...是很寻常的事情,那么在GNU Makefile中如何使用呢? ifeq ifneq 例如:foo.sh #! ...

  5. Linux常用命令:fdisk mkfs mount umount fstab实现自动挂载

    写在前 记录点常用命令,fdisk mkfs mount和umount,以及fstab实现自动挂载 fdisk fdisk主要用于操作硬盘的分区表.分区,下面简单记一点最常用的部分 查看当前系统识别到 ...

  6. 《 .NET并发编程实战》阅读指南 - 第2章

    先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.

  7. C# Moq

    Moq 1 My Cases 1.1 简单入门 2 Reference 2.1 Methods 2.2 Matching Arguments 2.3 Properties 2.4 Events 2.5 ...

  8. BAT: 获取时间有空格问题

    最近在项目上需要把文件定时备份,用BAT文件来自动生成文件夹名,精确到秒: bat脚本时间设定如下: pushd E:\Test set T=%date:~0,10%-%time:~0,2%%time ...

  9. 设计模式之(九)桥接模式(Bridge)

    桥接模式是怎么诞生的呢?来看一个场景. 一个软件企业开发一套系统,要兼容所有的不同类型硬件和和各种操作系统.不同种类硬件主要是 电脑.平板电脑.手机.各种操作系统是苹果系统.windows 系统.Li ...

  10. vue-cli随机生成port源码

    const portfinder = require('portfinder'): const port = await portfinder.getPortPromise(): 两行代码 端口搜索范 ...