mekanika-query

Isomorphic fluent interface for building query objects

npm install mekanika-query
4 downloads in the last week
6 downloads in the last month

query

query is an isomorphic interface for building Query Objects.

Alpha release version

Code Climate

query()                  // Create query
  .from( 'user' )        // Resource to execute on
  .where( 'name' )       // Constraint field
    .in( ['Tom','Bob'] ) //  - operator and conditions
  .and( 'age' )          // AND constraint (also supports `.or()`)
    .gt( 25 )            //  - operator and conditions
  .limit( 20 )           // Number of results
  .offset( 5 )           // Result offset (used for paging)
  .done( callback );     // Execute and return `callback( err, res )`

Installation

  npm install --production

Queries

Initiate a query:

  query()
  // -> new Query

Queries require setting:

  • .{action}(...) - {action} to execute (find, save, etc)

Execute a query with .done( cb ). Calls can be chained to this query# instance and executed by calling:

  query()
    .from( 'users' )
    .find()
    .done( cb );
    // `cb` is required callback, passed `cb( err, res, query )`

Query actions (Query#action)

The available actions supported by query are:

  • create
  • save
  • update
  • remove
  • find

Setting match constraints

Constraints are set using the .where( field ).<operator>( condition ) pattern.

The field is the named target to apply an operator (the criteria) and condition to. Operators include:

  • .eq( value ) - Equality (exact) match. Alias: .is().
  • .neq( value ) - Not equal to. Alias not().
  • .in( array ) - Where field value is in the array.
  • .nin( array ) - Where field value is not in the array.
  • .all( array ) - everything in the list
  • .lt( number ) - Less than number.
  • .gt( number ) - More (greater) than than number.
  • .lte( number ) - Less than or equal to number.
  • .gte( number ) - More (greater) than or equal to number.

Examples:

query().where( 'name' ).is( 'Mordecai' );
// Match any record with `{name: 'Mordecai'}`

query().where( 'age' ).gte( 21 );
// Match records where `age` is 21 or higher

Middleware

query supports pre and post processing middleware, and:

  • is only executed if an adapter is set
  • can add multiple methods to pre and post
  • executes in the order it is added

Pre

Pre-processing middleware is executed before the query is handed to its adapter, and are passed fn( query ) with this query as their only parameter.

This enables you to modify the query prior to adapter execution.

There are no special requirements for pre-middleware functions.

  function preHandler( qry ) {
    qry.resource += ':magic_suffix';
    // Example modification of the query passed to the adapter
  }

  query().pre( preHandler );
  // Adds `preHandler` to the pre-processing queue

Also supports adding multiple middleware methods

  query().pre( fn1 ).pre( fn2 ); // etc

Post

Post-processing middleware is run after the adapter execution is complete, and are passed fn( err, res, query ), where err and res are responses from the adapter, and query is this query.

This enables you to modify the results from the server.

Post middleware functions must return an [error, results] array, which will presumably include your modifications.

  function postHandler( err, res, qry ) {
    // MUST return [err, res] array
    err = 'My modified error';
    res = 'Custom results!';
    return [err, res];
  }

  query().post( postHandler );
  // Adds `postHandler` to post-processing queue

Also supports adding multiple middleware methods:

  query().post( fn1 ).post( fn2 ); // etc

Adapter

query can optionally delegate execution to an adapter.

This means that calling .done( cb ) on a query will delegate to:

  query#adapter.exec( query, cb );

Setting an adapter

Pass an adapter directly to each query:

  var myadapter = require('my-adapter');
  query( myadapter );

This is syntactic sugar for the identical call:

  query().useAdapter( myadapter );

See https://github.com/mekanika/adapter for more details on adapters.

Advanced: Custom adapter classes

You may also specify a custom adapter class handler on the query class itself (note the lack of query() parentheses):

  query.adapterClass( adapter.Adapter );

This exposes the adapter cache via adapter( 'adapterName' ).

Adapter references may then be passed as strings, and are retrieved from the adapter cache:

  query( 'adapterName' );

Which is syntactic sugar for:

  query().use( 'adapterName' );

Tests

Ensure you have installed the development dependencies:

  make install

To run the tests:

  make test

Test Coverage

To generate a coverage.html report, run:

make coverage

Bugs

If you find a bug, report it.

License

GNU Lesser General Public License, either version 3 of the License, or (at your option) any later version (LGPL3+). See the License. files for full details.

npm loves you