如何使用函数扩展 pg-promise 接口

How to extend pg-promise interface with function

我有一个 node.js 模块 pg-promise 实例化如下。

const pgp = require('pg-promise')();

// Database connection details;
const cn = {
    host: 'localhost', // 'localhost' is the default;
    ...
}


// Create db connection and verify it
var db = pgp(process.env.DATABASE_URL || cn);
db.one('Select version()')
    .then(data => {
        log.info('Connected: ', data);
    })
    .catch(error => {
        log.error("Error connecting to db", error);
    })

// extension methods
db.findById = function (table, id) {
    log.debug('read ', table, id);
    return db.one('Select * from ' + table + ' where id = ', id);
}

module.exports = db;

db对象是接口类型的一个实例pgPromise.IDatabase<{}, pg.Iclient>

我希望能够调用这个库提供的函数以及我自己的函数。:

const db = require('../db');

db.any('Select query..')
  .then(data => { res.send(data); })
  .catch(err => { log.error(err); });

db.findById('users',1)
  .then(data => { res.send(data); })
  .catch(err => { log.error(err); });

但是当我 运行 它时,我得到了错误

TypeError: db.findById is not a function

我也试过了,效果一样。

module.exports = db;
module.exports.findById = function()...;

我能想到的唯一解决方案是:

module.exports = {
  db: db,
  findById: function(){
    ...
  }
}

但是现在很难在其他模块中使用它,因为我总是需要专门询问 db 属性.

pg-promise 似乎使用了一种烦人的模式,他们冻结每个对象并使每个 属性 只读,所以你将无法像你一样简单地手动添加属性尝试。该库支持 initOptions extend 属性 中的扩展,如下所示:

const initOptions = {
  extend(obj, dc) {
    obj.findById = function() {
      ...
    }
    //add other extension methods or properties here
  }
};
const pgp = require('pg-promise')(initOptions);

//now any databases created with pgp will contain those extension methods

或者,您可以在您的导出对象上定义一个代理,它遵从数据库或您自己的自定义函数:

const extension = {
  findById: function() {
    ...
  },
  //other functions
};

module.exports = new Proxy(extension, { get(target, name) {
  if(db[name] !== undefined) return db[name];
  return target[name];
});

但是您应该更喜欢使用 initOptions.

本机支持的方式来执行此操作

来自 pg-promise 的作者。


pg-promise 中的数据库协议是可扩展的,支持事件 extend,可让您在所有级别上扩展协议。您需要这种级别的自动化,因为当涉及到基本的 TasksTransactions 时,它们封装了分配的连接,协议变得动态,并且所以你需要一个特殊的规定来使协议扩展自动工作,这正是事件 extend 所做的。

为了更好地理解它,我写了 pg-promise-demo 来展示如何正确地做到这一点,以及一些其他大多数时候有用的高级内容。