npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@baethon/kex

v1.1.0

Published

Extend knex with query models

Downloads

2

Readme

Node.js CI npm version

@baethon/kex

Kex is a query extension for Knex. It uses the concept of "model" from ORMs like Lucid, or Laravel Eloquent restricted only to make queries. It has support for scopes, plugins, relations, and many more.

Installation

Install the package:

npm i @baethon/kex

Set up Kex instance:

const knex = require('knex')({ /* ... */ })
const { Kex } = require('@baethon/kex')

const kex = new Kex({ knex })

Create first model:

const User = kex.createModel('User')

Making queries

Kex models uses the Knex query builder. To start the query, use query() method:

const usersList = await User.query()

The query object is chainable:

const activeUsers = await User.query()
  .where({ active: true })

In some cases, you can omit the query() method and start chaining using following methods:

  • where()
  • whereIn()
  • insert()
  • returning()
const activeUsers = await User.where({ active: true })

Unlike Knex, the models don't create a query when using other methods (e.g. andWhere()).

Creating new records

await User.insert({ name: 'Jon' })

As in Knex, you should use returning() when you want to receive the returning fields:

const [id] = await User.returning('id')
  .insert({ name: 'Jon' })

Updating records

User.where({ active: true })
  .update({ active: false })
  
// to make an update of a single item you can use
// following query
User.find(userId)
  .update({ active: true })

Scopes

Scope is a function that alters the query. You can chain them as other query methods.

Scopes are declared when creating a model:

const User = kex.createModel('User', {
  scopes: {
    active (qb) {
      qb.where('active', true)
    }
  }
})

const activeUsers = await User.query()
  .active()

Scopes can be used in the callbacks of where():

const usersList = await User.where(qb => {
  qb.active()
    .orWhere('role', 'admin')
})

Global scopes

Global scope is very similar to the regular scope. The main difference is that it's applied automatically to every query.

const User = kex.createModel('User', {
  globalScopes: {
    active (qb) {
      qb.where('active', true)
    }
  }
})

const activeUsers = await User.query()

It's possible to ignore the scope using withoutGlobalScope(), or withoutGlobalScopes() method:

const usersList = await User.query()
  .withoutGlobalScope('active')
  // alternative syntax:
  // .withoutGlobalScopes(['active'])

Other

Kex supports many other things:

Conventions

Kex uses naming conventions taken from Lucid, or Eloquent:

  • the table name is a snake_case version of the pluralized model name (e.g. users)
  • the primary key is always id
  • foreign keys (used in relations) are snake_case version of a table name (in singular form) postfixed with _id (e.g. user_id)
  • the pivot table is a snake_case version of related table names (in singular form) joined in alphabetical order (e.g. tag_user)

The naming is fully customizable.

Motivation

Full-blown ORMs offer fantastic features. Yet sometimes, it might be overkill for your application. What I needed is a customizable DBAL which wouldn't make too much magic behind the scenes. I wanted something like Knex, yet a little more robust.

Kex gives you the feeling of an ORM. However, it makes sure not to interfere with your work. Build a query and fetch the results. That's all. Don't worry about hydrated objects, results collections, or anything like that.

Testing

The test suite is a combination of unit tests and integration tests. The latter use by default an SQLite database, however, you can (and sometimes must) choose a different database backend.

To run tests:

yarn test

Running a single test suite with:

yarn test tests/path/to/test-file.test.js

Using different database backend

You need to install client dependency:

  • mysql for MySQL database
  • pg for PostgreSQL database

Then, start the database and set env variables. The test suite supports two env variables:

  • DB_CLIENT (either mysql or pg)
  • DB_URL (e.g. mysql://user:passwd@host:3306/db_name)
DB_CLIENT=mysql DB_URL=mysql://user:passwd@host:3306/db_name yarn test