0.2.0 • Published 1 year ago

@yadah/objection-scope v0.2.0

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

Objection scope mixin

A mixin for Objection.js which extends the QueryBuilder to have a scope() method. It allows a model to define common query building functions based on a criteria object with a well-defined shape.

Usage

The Model.scopes object maps criteria keys to functions that work in a similar way to Model.modifiers. Scope modifiers accept the query object and the criteria object that was passed to the QueryBuilder.scope() function (this object will have a property with key that matches the Model.scopes key).

import ScopeMixin from "@yadah/objection-scope"
import { mixin, Model } from "objection"

class MyModel extends mixin(Model, [ScopeMixin]) {
  static get scopes() {
    return {
      ...super.scopes,
      keyword: (query, { keyword }) {
        return query.where("title", "like", `%${keyword}`)
      }
    }
  }
}

MyModel.query().scope({ keyword: "abc" })
// select * from "tableName" where "tableName"."title" like ?
// bindings: ["%abc"]

Matcher

The ScopeBuilder class can be used to help write common modifier patterns.

class MyModel extends mixin(Model, [ScopeMixin]) {
  static get scopes() {
    const matcher = new this.ScopeBuilder();
    return {
      ...super.scopes,
      field1: matcher,
      field2: matcher,
    };
  }
}
MyModel.query().scope({ field1: "foo", field2: "bar" });
// select * from "tableName" where "tableName"."field1" = ? and "tableName"."field2" = ?
// bindings: ["foo", "bar"]

The matcher object can be chained to produce various common types of query modifier.

const matcher = new this.ScopeBuilder();
const scopes = {
  field1: matcher,
  minField2: matcher.min,
  maxField3: matcher.max,
  field4: matcher.related("related"),
  field5: matcher.notNull,
};
ExpressionResultNotes
matcher.where(fieldName, value)if value is not an array
matcher.whereIn(fieldName, value)if value is an array
matcher.min.where(fieldName, ">=", value)
matcher.max.where(fieldname, "<=", value)
matcher.related(relationName).joinRelated(relationName).where(`\${relationName}.\${fieldName}`, value)if value is not an array
matcher.related(relationName).joinRelated(relationName).whereIn(`\${relationName}.\${fieldName}`, value)if value is an array
matcher.exists.whereExists(Model.relatedQuery(fieldName).scope(value))
matcher.notNull.whereNotNull(fieldname)if value is true
matcher.notNull.whereNull(fieldName)if value is false
matcher.name(name)changes fieldName to name