Как расширить интерфейс pg-обещания с помощью функции - PullRequest
1 голос
/ 07 февраля 2020

У меня есть 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 = $1', 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 свойство.

Ответы [ 2 ]

1 голос
/ 07 февраля 2020

От автора pg-обещание .


Протокол базы данных в pg-обещание является расширяемым, поддерживая событие extend это позволяет расширить протокол на всех уровнях. Вы нуждаетесь в этом уровне автоматизации, потому что когда дело доходит до необходимых Задач и Транзакций , которые инкапсулируют выделенное соединение, протокол становится динамическим c, и поэтому вам нужен специальный положение, при котором расширение протокола работает автоматически, и это именно то, что делает extension .

Чтобы лучше понять его, я написал pg-promise-demo для покажите, как это сделать правильно, а также другие высокоуровневые материалы, которые полезны в большинстве случаев.

0 голосов
/ 07 февраля 2020

pg-promise, кажется, использует раздражающий шаблон, в котором они замораживают каждый объект и делают каждое свойство доступным только для чтения, поэтому вы не сможете просто добавить свойства к нему вручную, как пытаетесь. Библиотека поддерживает расширения в свойстве extend, равном initOptions, например:

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.

...