Tool-Kid / express-query-adapter

:mag_right: :dizzy: Transfrom automatically Express.js req.query into your favourite query tool
MIT License
72 stars 29 forks source link

Express Query Adapter logo

Express Query Adapter

Easily transform an Express req.query into your favourite query tool






Contributing · License

Installation

npm install @tool-kid/express-query-adapter

How it works?

Usage

Use getQueryBuilder exported from package and pass your req.query as an argument:

import { getQueryBuilder } from '@tool-kid/express-query-adapter';

const builder = await getQueryBuilder({ adapter: 'typeorm' });
const builtQuery = builder.build(req.query);
// Now your query is built, pass it to your favourite tool
const results = await fooRepository.find(builtQuery);

Adapters

Given the following url query string:

foo/?name__contains=foo&role__in=admin,common&age__gte=18&page=3&limit=10

It will be transformed into:

{
  where: {
    foo: Like('%foo%'),
    role: In(['admin', 'common']),
    age: MoreThanOrEqual(18)
  },
  skip: 20,
  take: 10
}

Different ways of retrieve data

GET, POST method by url query string

GET foo/?name__contains=foo&role__in=admin,common&age__gte=18&page=3&limit=10

POST foo/?name__contains=foo&role__in=admin,common&age__gte=18&page=3&limit=10

app.get('/foo', (req, res) => {
  const qb = await getQueryBuilder({ adapter: 'typeorm' });
  const built = qb.build(req.query); // => Parsed into req.query
});

POST method by body

POST foo/, body: {
  "name__contains": "foo",
  "role__in": "admin,common",
  "age__gte": 18,
  "page": 3,
  "limit": 10
}
app.post('/foo', (req, res) => {
  const qb = await getQueryBuilder({ adapter: 'typeorm' });
  const built = qb.build(req.query); // => Parsed into req.body
});

Available Lookups

Lookup Behaviour Example
(none) Return entries that match with value foo=raul
contains Return entries that contains value foo__contains=lopez
startswith Return entries that starts with value foo__startswith=r
endswith Return entries that ends with value foo__endswith=dev
icontains Return entries that contains value and ignoring case foo__icontains=Lopez
istartswith Return entries that starts with value and ignoring case foo__istartswith=R
iendswith Return entries that ends with value and ignoring case foo__iendswith=Dev
isnull Return entries with null value foo__isnull
lt Return entries with value less than or equal to provided foo__lt=18
lte Return entries with value less than provided foo__lte=18
gt Returns entries with value greater than provided foo__gt=18
gte Return entries with value greater than or equal to provided foo__gte=18
in Return entries that match with values in list foo__in=admin,common
between Return entries in range (numeric, dates) foo__between=1,27

Notice: you can use negative logic prefixing lookup with __not.

Example: foo__not__contains=value

Options

Pagination

Option Default Behaviour Example
pagination true If true, paginate results. If false, disable pagination pagination=false
page 1 Return entries for page page page=2
limit 25 Return entries for page page paginated by size limit limit=15

Ordering

Option Default Behaviour Example
order - Order for fields:
+: Ascendant
-: Descendant
order=+foo,-name,+surname

Selection

Option Default Behaviour Example
select - Fields to select as response. If no provided, it select all fields. select=name,surname,foo.nested
with - Entity relations to attach to query with=posts,comments

Profile

If you need to disable some capabilities, you can do using shortcuts to enable|disable by default or provide a custom Profile.

A Profile describe capabilities that can be used by clients & its behaviour.

const qb = getQueryBuilder({ adapter: 'typeorm', profile: 'enabled' | 'disabled' | ConfigProgile });
const builtQuery = builder.build(req.query);

ConfigProfile

ConfigProfile object looks like:

const customProfile: ConfigProfile = {
  options: {
    pagination: {
      status: 'enabled',
      paginate: true,
      itemsPerPage: 25,
    },
    ordering: {
      status: 'enabled',
    },
    relations: {
      status: 'enabled',
    },
    select: {
      status: 'enabled',
    },
  },
  policy: 'skip',
};
Field Default Behaviour Type
options 'enabled' Profile options ProfileOptions
policy 'skip' Policy to apply in cases client try use disabled options FindPolicyType