Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

feathers-knex

A service plugin for KnexJS a query builder for PostgreSQL, MySQL and SQLite3

feathers, feathers-plugin

readme

feathers-knex

CI Dependency Status Download Status

A database adapter for KnexJS, an SQL query builder for Postgres, MSSQL, MySQL, MariaDB, SQLite3, and Oracle.

npm install --save mysql knex feathers-knex

Important: feathers-knex implements the Feathers Common database adapter API and querying syntax.

Note: You also need to install the database driver for the DB you want to use.

API

service(options)

Returns a new service instance initialized with the given options.

const knex = require('knex');
const service = require('feathers-knex');

const db = knex({
  client: 'sqlite3',
  connection: {
    filename: './db.sqlite'
  }
});

// Create the schema
db.schema.createTable('messages', table => {
  table.increments('id');
  table.string('text');
});

app.use('/messages', service({
  Model: db,
  name: 'messages'
}));
app.use('/messages', service({ Model, name, id, events, paginate }));

Options:

  • Model (required) - The KnexJS database instance
  • name (required) - The name of the table
  • schema (optional) - The name of the schema table prefix (example: schema.table)
  • id (optional, default: 'id') - The name of the id field property.
  • events (optional) - A list of custom service events sent by this service
  • paginate (optional) - A pagination object containing a default and max page size
  • multi (optional) - Allow create with arrays and update and remove with id null to change multiple items. Can be true for all methods or an array of allowed methods (e.g. [ 'remove', 'create' ])
  • whitelist (optional) - A list of additional query parameters to allow (e..g [ '$regex', '$geoNear' ]). Default is the supported operators

adapter.createQuery(query)

Returns a KnexJS query with the common filter criteria (without pagination) applied.

params.knex

When making a service method call, params can contain an knex property which allows to modify the options used to run the KnexJS query. See customizing the query for an example.

Example

Here's a complete example of a Feathers server with a messages SQLite service. We are using the Knex schema builder and SQLite as the database.

$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio feathers-knex knex sqlite3

In app.js:

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

const service = require('feathers-knex');
const knex = require('knex');

const db = knex({
  client: 'sqlite3',
  connection: {
    filename: './db.sqlite'
  }
});

// Create a feathers instance.
const app = express(feathers());
// Turn on JSON parser for REST services
app.use(express.json());
// Turn on URL-encoded parser for REST services
app.use(express.urlencoded({ extended: true }));
// Enable REST services
app.configure(express.rest());
// Enable Socket.io services
app.configure(socketio());
// Create Knex Feathers service with a default page size of 2 items
// and a maximum size of 4
app.use('/messages', service({
  Model: db,
  name: 'messages',
  paginate: {
    default: 2,
    max: 4
  }
}))
app.use(express.errorHandler());

// Clean up our data. This is optional and is here
// because of our integration tests
db.schema.dropTableIfExists('messages').then(() => {
  console.log('Dropped messages table');

  // Initialize your table
  return db.schema.createTable('messages', table => {
    console.log('Creating messages table');
    table.increments('id');
    table.string('text');
  });
}).then(() => {
  // Create a dummy Message
  app.service('messages').create({
    text: 'Message created on server'
  }).then(message => console.log('Created message', message));
});

// Start the server.
const port = 3030;

app.listen(port, () => {
  console.log(`Feathers server listening on port ${port}`);
});

Run the example with node app and go to localhost:3030/messages.

Querying

In addition to the common querying mechanism, this adapter also supports:

$and

Find all records that match all of the given criteria. The following query retrieves all messages that have foo and bar attributes as true.

app.service('messages').find({
  query: {
    $and: [
      {foo: true},
      {bar: true}
    ]
  }
});

Through the REST API:

/messages?$and[][foo]=true&$and[][bar]=true

$like

Find all records where the value matches the given string pattern. The following query retrieves all messages that start with Hello:

app.service('messages').find({
  query: {
    text: {
      $like: 'Hello%'
    }
  }
});

Through the REST API:

/messages?text[$like]=Hello%

$notlike

The opposite of $like; resulting in an SQL condition similar to this: WHERE some_field NOT LIKE 'X'

app.service('messages').find({
  query: {
    text: {
      $notlike: '%bar'
    }
  }
});

Through the REST API:

/messages?text[$notlike]=%bar

$ilike

For PostgreSQL only, the keywork $ilike can be used instead of $like to make the match case insensitive. The following query retrieves all messages that start with hello (case insensitive):

app.service('messages').find({
  query: {
    text: {
      $ilike: 'hello%'
    }
  }
});

Through the REST API:

/messages?text[$ilike]=hello%

Transaction Support

The Knex adapter comes with three hooks that allows to run service method calls in a transaction. They can be used as application wide (app.hooks.js) hooks or per service like this:

// A common hooks file
const { hooks } = require('feathers-knex');

const { transaction } = hooks;

module.exports = {
  before: {
    all: [ transaction.start() ],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  after: {
    all: [ transaction.end() ],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  error: {
    all: [ transaction.rollback() ],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
};

To use the transactions feature, you must ensure that the three hooks (start, end and rollback) are being used.

At the start of any request, a new transaction will be started. All the changes made during the request to the services that are using the feathers-knex will use the transaction. At the end of the request, if sucessful, the changes will be commited. If an error occurs, the changes will be forfeit, all the creates, patches, updates and deletes are not going to be commited.

The object that contains transaction is stored in the params.transaction of each request.

Important: If you call another Knex service within a hook and want to share the transaction you will have to pass context.params.transaction in the parameters of the service call.

Customizing the query

In a find call, params.knex can be passed a KnexJS query (without pagination) to customize the find results.

Combined with .createQuery({ query: {...} }), which returns a new KnexJS query with the common filter criteria applied, this can be used to create more complex queries. The best way to customize the query is in a before hook for find.

app.service('messages').hooks({
  before: {
    find(context) {
      const query = context.service.createQuery(context.params);

      // do something with query here
      query.orderBy('name', 'desc');

      context.params.knex = query;
      return context;
    }
  }
});

Configuring migrations

For using knex's migration CLI, we need to make the configuration available by the CLI. We can do that by providing a knexfile.js (OR knexfile.ts when using TypeScript) in the root folder with the following contents:

knexfile.js

const app = require('./src/app')
module.exports = app.get('postgres')

OR

knexfile.ts

import app from './src/app';
module.exports = app.get('postgres');

You will need to replace the postgres part with the adapter you are using. You will also need to add a migrations key to your feathersjs config under your database adapter. Optionally, add a seeds key if you will be using seeds.

// src/config/default.json
...
  "postgres": {
    "client": "pg",
    "connection": "postgres://user:password@localhost:5432/database",
    "migrations": {
      "tableName": "knex_migrations"
    },
    "seeds": {
      "directory": "../src/seeds"
    }
  }

Then, by running: knex migrate:make create-users, a migrations directory will be created, with the new migration.

Error handling

As of version 4.0.0 feathers-knex only throws Feathers Errors with the message. On the server, the original error can be retrieved through a secure symbol via error[require('feathers-knex').ERROR]

const { ERROR } = require('feathers-knex');

try {
  await knexService.doSomething();
} catch(error) {
  // error is a FeathersError with just the message
  // Safely retrieve the Knex error
  const knexError = error[ERROR];
}

Waiting for transactions to complete

Sometimes it can be important to know when the transaction has been completed (committed or rolled back). For example, we might want to wait for transaction to complete before we send out any realtime events. This can be done by awaiting on the transaction.committed promise which will always resolve to either true in case the transaction has been committed, or false in case the transaction has been rejected.

app.service('messages').publish((data, context) => {
  const { transaction } = context.params

  if (transaction) {
    const success = await transaction.committed
    if (!success) {
      return []
    }
  }

  return app.channel(`rooms/${data.roomId}`)
})

This also works with nested service calls and nested transactions. For example, if a service calls transaction.start() and passes the transaction param to a nested service call, which also calls transaction.start() in it's own hooks, they will share the top most committed promise that will resolve once all of the transactions have succesfully committed.

License

Copyright (c) 2021

Licensed under the MIT license.

changelog

Changelog

Unreleased

Full Changelog

Merged pull requests:

v8.0.0 (2021-07-13)

Full Changelog

Closed issues:

  • Fix types to work with knex > 0.95 #261
  • Cannot use namespace 'Knex' as a type #259

v7.1.1 (2020-07-05)

Full Changelog

Closed issues:

  • No release #252
  • SQL Server "Cannot read property '0' of undefined" when create #247
  • Closing the database connection / cleanup ? #246
  • An in-range update of knex is breaking the build 🚨 #245
  • Create method with knex plugged with mssql database returns no id. Gets General Error in feathers api #243
  • An in-range update of @feathersjs/adapter-commons is breaking the build 🚨 #238
  • An in-range update of knex is breaking the build 🚨 #231
  • An in-range update of @feathersjs/adapter-commons is breaking the build 🚨 #228

Merged pull requests:

v7.1.0 (2019-10-07)

Full Changelog

Merged pull requests:

v7.0.0 (2019-09-29)

Full Changelog

Implemented enhancements:

  • Why is there an init method in this service? #183
  • Getting affected rows after a patch? #164

Merged pull requests:

v6.1.0 (2019-09-04)

Full Changelog

Closed issues:

  • Nested transactions stepping on each other #217

Merged pull requests:

v6.0.2 (2019-08-14)

Full Changelog

Closed issues:

  • Issue with whitelist #215

Merged pull requests:

  • Fix whitelist initialization #218 (daffl)
  • fix: postgres should also returning [id] #216 (ucokfm)

v6.0.1 (2019-08-09)

Full Changelog

Closed issues:

  • .returning() is not supported by mysql and will not have any effect. #209

Merged pull requests:

v6.0.0 (2019-07-06)

Full Changelog

Fixed bugs:

  • transaction rollback not executed #197

Closed issues:

  • Overriding knex-adapter default post-create behaviour #207

Merged pull requests:

v5.1.0 (2019-06-10)

Full Changelog

Closed issues:

  • An in-range update of knex is breaking the build 🚨 #203
  • An in-range update of sqlite3 is breaking the build 🚨 #202
  • An in-range update of body-parser is breaking the build 🚨 #200

Merged pull requests:

v5.0.7 (2019-04-16)

Full Changelog

Merged pull requests:

v5.0.6 (2019-03-30)

Full Changelog

Merged pull requests:

v5.0.5 (2019-02-18)

Full Changelog

Merged pull requests:

v5.0.4 (2019-01-26)

Full Changelog

Closed issues:

  • Patch has broke for MSSQL adapter: selecting the same field twice returns an array #188

Merged pull requests:

v5.0.3 (2019-01-16)

Full Changelog

Closed issues:

  • Oracle Proxy User #186
  • No record found for id '${id}' #184

Merged pull requests:

  • Fix patch with pagination enabled #187 (daffl)

v5.0.2 (2019-01-13)

Full Changelog

Merged pull requests:

v5.0.1 (2018-12-29)

Full Changelog

Merged pull requests:

  • Add default parameters to hook-less service methods #182 (daffl)

v5.0.0 (2018-12-28)

Full Changelog

Closed issues:

  • An in-range update of debug is breaking the build 🚨 #180
  • An in-range update of @feathersjs/feathers is breaking the build 🚨 #179
  • An in-range update of @feathersjs/express is breaking the build 🚨 #178
  • An in-range update of @feathersjs/errors is breaking the build 🚨 #177

Merged pull requests:

  • Upgrade to @feathersjs/adapter-commons and latest common service features #181 (daffl)
  • Update knex to the latest version 🚀 #176 (greenkeeper[bot])

v4.0.0 (2018-10-15)

Full Changelog

Closed issues:

  • An in-range update of debug is breaking the build 🚨 #171

Merged pull requests:

v3.3.0 (2018-06-29)

Full Changelog

Merged pull requests:

v3.2.0 (2018-06-26)

Full Changelog

Merged pull requests:

  • Add explicit peer dependency on latest Knex version #162 (daffl)
  • Do clearOrder() for countQuery #161 (ik9999)

v3.1.1 (2018-06-03)

Full Changelog

Closed issues:

  • Version 10 of node.js has been released #156
  • Can't find relation if table name != service name? #150

Merged pull requests:

v3.1.0 (2018-04-20)

Full Changelog

Closed issues:

  • How to properly extend knex service #155
  • Support Database Schemas #153

Merged pull requests:

v3.0.6 (2018-03-27)

Full Changelog

Closed issues:

  • createQuery on empty table throws an error #147

Merged pull requests:

v3.0.5 (2018-03-26)

Full Changelog

Closed issues:

  • Support querying null value #149

Merged pull requests:

v3.0.4 (2018-03-06)

Full Changelog

Closed issues:

  • Error handling question. #133

Merged pull requests:

  • call update directly on knex instead of where. #146 (omeid)

v3.0.3 (2018-02-24)

Full Changelog

Closed issues:

  • nested tables on join #144
  • How to implement soft deletes? #143
  • Pagination broken in SQL-Server #141
  • Wrong total if params.knex is set #121

Merged pull requests:

  • Fix count query when using params.knex #145 (omeid)

v3.0.2 (2018-02-05)

Full Changelog

Closed issues:

  • Properties not passed to Feathers are getting set to null #140

Merged pull requests:

v3.0.1 (2017-12-14)

Full Changelog

Closed issues:

  • Warning message output from hook.js #136

Merged pull requests:

v3.0.0 (2017-12-03)

Full Changelog

Closed issues:

  • Nested service usage with transaction hooks at both of them? #118

Merged pull requests:

v2.9.0 (2017-10-25)

Full Changelog

Merged pull requests:

v2.8.2 (2017-10-19)

Full Changelog

Closed issues:

  • $or bug #120
  • knexfile.js for migrations #116

Merged pull requests:

v2.8.1 (2017-09-04)

Full Changelog

Merged pull requests:

  • Add this.Model reference for the Knex client #115 (daffl)

v2.8.0 (2017-09-03)

Full Changelog

Closed issues:

  • Service methods are not executed in transaction #91

Merged pull requests:

v2.7.2 (2017-07-24)

Full Changelog

Merged pull requests:

v2.7.1 (2017-07-22)

Full Changelog

Closed issues:

  • result.total type is string in postgres #108
  • ER_DUP_KEYNAME: Duplicate key name #103

Merged pull requests:

v2.7.0 (2017-06-22)

Full Changelog

Closed issues:

  • Primary key is not "id" #101
  • An in-range update of mocha is breaking the build 🚨 #100
  • Datetype for mysql #98

Merged pull requests:

v2.6.3 (2017-03-01)

Full Changelog

Closed issues:

  • Update selected fields error #94

Merged pull requests:

  • Scoping select to current table to prevent "ambiguous" join queries #90 (shadowRR)

v2.6.2 (2017-02-14)

Full Changelog

Merged pull requests:

v2.6.1 (2017-02-13)

Full Changelog

Merged pull requests:

  • Add error handling for mysql and mysql2 server errors #92 (lvivier)
  • Update README Example #89 (arlair)

v2.6.0 (2016-11-30)

Full Changelog

Closed issues:

  • Exposing the query builder #87

Merged pull requests:

  • Add createQuery and remove error handler for now #88 (daffl)

v2.5.0 (2016-11-12)

Full Changelog

Closed issues:

  • Social Authentication SQL parse error with Knex #68

Merged pull requests:

v2.4.0 (2016-10-19)

Full Changelog

Closed issues:

  • $or filter doesn't group together conditions #71
  • Patch many doesn't return patched items when the query includes patched fields #52

Merged pull requests:

v2.3.0 (2016-09-22)

Full Changelog

Fixed bugs:

  • We shouldn't remove properties from original objects #55

Closed issues:

  • Need a way to exclude automatically generated columns from the update method. #61
  • How to setup relations between tables ? #60
  • Ability to return value from original insert object #58

Merged pull requests:

v2.2.0 (2016-06-17)

Full Changelog

Merged pull requests:

v2.1.3 (2016-06-01)

Full Changelog

Closed issues:

  • Support $search #30
  • Support for deeply nested/complex queries #10
  • Support population one level deep #3

Merged pull requests:

v2.1.2 (2016-04-01)

Full Changelog

Closed issues:

  • Review patch and remove many for consistency #26
  • Feature: ability to CRUD without needing to bind as a feathers service #19

Merged pull requests:

v2.1.1 (2016-02-24)

Full Changelog

Merged pull requests:

v2.1.0 (2016-01-31)

Full Changelog

Merged pull requests:

  • Use internal methods instead of service methods directly #29 (daffl)

v2.0.2 (2016-01-25)

Full Changelog

Merged pull requests:

v2.0.1 (2016-01-24)

Full Changelog

Closed issues:

  • Initialization should conform with other adapters #24

Merged pull requests:

v2.0.0 (2016-01-06)

Full Changelog

Closed issues:

  • Expose Knex lib #23

v1.3.0 (2015-12-21)

Full Changelog

Closed issues:

  • Example code problems #20
  • README example does not work #18

Merged pull requests:

v1.2.2 (2015-11-24)

Full Changelog

Closed issues:

  • Example in README does not work #16

Merged pull requests:

  • Use CommonJS export Babel plugin #17 (daffl)

v1.2.1 (2015-11-23)

Full Changelog

Closed issues:

  • Should other adapters rely on this or Sequelize? #14
  • Object.assign not available in older Node versions #13

Merged pull requests:

  • Upgrading to Babel 6 and adding Object.assign polyfill #15 (daffl)

v1.2.0 (2015-11-11)

Full Changelog

Merged pull requests:

  • Upgrade to latest service tests #12 (daffl)

v1.1.0 (2015-11-04)

Full Changelog

Merged pull requests:

  • Move to using feathers-service-tests for unified test suite #11 (daffl)

v1.0.0 (2015-10-26)

Full Changelog

Closed issues:

  • Support remove #9
  • Support patch #8
  • Support update #7
  • Support special query filters #6
  • Support basic find queries #5
  • Support get queries #4
  • Support comparators, like $gte, $gt, etc. #2
  • Support conditional queries #1

* This Changelog was automatically generated by github_changelog_generator