knex 的自定义函数

Custom functions for knex

我一直在做一些操作,我希望有一种方法可以让 "extend" knex 能够完成这些操作。

我想要这样的东西:

oneExists
    result = knex.count(id).from('table').where({'code': 25})
    if (result.length === 0) return false
    if (result.length === 1) return true
    throw an error

我希望能够做类似

的事情
knex.oneExists.count('id').from('table').where({'code': 25}).

目前我正在编写这样的代码:

KnexUtil.oneExists(knex.select('id').from('table').where({code: 25})) 

哪个returns一个承诺

我查看了 knex 代码库,但不确定:

  1. 如何链接这个(以及我是否会在 /lib/query/compiler.js 中这样做)
  2. 如何只对 knex 进行扩展,这样我就不需要修改原始代码库

当然可以。我建议只创建自己的插件,如下所示:

// my-plugin.js
'use strict';

module.exports = function (Bookshelf) {
    Bookshelf.Model = Bookshelf.Model.extend({
        foo: function ( bar ) {
            if( bar )
                console.log('Method foo was called on a model with the arguments:', arguments.join(', '));
        }
    });

    Bookshelf.Collection = Bookshelf.Collection.extend({
        foo: function ( bar ) {
            if( bar )
                console.log('Method foo was called on a collection with the arguments:', arguments.join(', '));
        }
    });
};

然后在您的主应用程序文件中,添加:

Bookshelf.plugin( require( './my-plugin' ) );

BookshelfJS 插件基本上允许您扩展模型和集合(以及更多),这允许您添加自己的方法或覆盖现有方法(同时仍然能够从您的插件中调用原始方法)

为了更好地理解,您最好查看 plugins directory 中一些现有的 BookshelfJS 插件,其中一些已经随书架一起提供。

另一个可能有助于更好地理解插件工作原理的插件是 Soft Delete Plugin. In that plugin, you can see how some BookshelfJS methods are overridden in both the models and the collections objects, with methods that execute the original version of the method, then return the parsed/modified result (Lines #37-#59 and Lines #37-#57), as well as adding completely new methods (Lines #61-#72)

编辑:显然这比 KnexJS 更多 BookshelfJS,但我没有看到任何为 KnexJS 创建插件的方法,因为它只是一个查询构造函数,所有真正的魔法在 ORM

从 v0.19.1 开始,knex 可以build-in扩展 QueryBuilder

import Knex from 'knex'
Knex.QueryBuilder.extend('someFn', function (arg) {
  console.log('Do Smth', arg)
  return this
})
const knex = Knex({ client: 'pg' })
knex.select().from('table').someFn(0).toString()

如果使用 TypeScript:

import { knex, Knex as KnexOriginal } from "knex";

declare module "knex" {
  namespace Knex {
    interface QueryBuilder {
      customFunction<TRecord, TResult>(
        value: number
      ): KnexOriginal.QueryBuilder<TRecord, TResult>;
    }
  }
}

knex.QueryBuilder.extend("customFunction", function (value: number) {
  console.log("Custom Function:", value);
  return this;
});

const pg = knex({ client: "pg" });
pg("table").select("*").customFunction(10).toString()

查看 documentation 关于如何延长 knex