1.0.3 • Published 6 months ago

filter-builder-js v1.0.3

Weekly downloads
-
License
ISC
Repository
github
Last release
6 months ago

This package supports the interaction between ORMs and Query Objects from the Client.

Installation

npm i filter-builder-js

Quick start

First, Using FilterBuilderConfig.config to define something information. Note, you must run config method in entry point file. In bellow example, server.js is entry point of server:

// server.js
    FilterBuilderConfig.config({
        type: ... ,
        hooks?: ... ,
        factoryAdapter?: ...
        dataSource?: ,
    )

    const filter = new FilterBuilder (....).in(...).gte(...);
    await filter.run();

In There:

KeyRequiredNote
typeYesString - Type of Orm in project, sequelize and typeorm
factoryAdapterNoFilterBuilderAdapterFactory - Used to register a custom FilterAdapter created by the user. This will be explained in a later section.
dataSourceNoDataSource -The Datasource object (in TypeORM). Note that this field is only used when the type is typeorm.
hooksNoObject - A list of hooks used to customize results, queries, etc., according to user needs. The list of hooks is presented below.

List of hooks:

   * beforeEachCondition: Array <( data: BeforeEachConditionDto ) => BeforeEachConditionDto>;
   
   * beforeOrder: (data: BeforeOrderHookDto) => BeforeOrderHookDto; 
   
   * beforeGroup: Array <(columnName: string) => string>;
   
   * beforeJoinHook: (joinData: JoinData) => JoinData;
   
   * getColumnName: ( data: GetColumnNameHookDto) => GetColumnNameHookDto; 

Example, To convert camelCase to snake_case before querying data from the database:

    
    function camelCase2snake_case (str) {
        return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
    }
    
    FilterBuilderConfig.config({
        type: "typeorm",
        hooks: {
            getColumnName: (data: GetColumnNameHookDto) => {
               data.columnName = camelCase2snake_case(data.columnName);
               return data;
            }
        }
    );

In FilterBuilder, each instance of FilterBuilder has its own configuration. Therefore, you can customize the configuration for each filter as follows:

   const filter = new FilterBuilder(...)
   .config(...) // Custom config in here
   ...

   await filter.run();

Filter data

Using FilterBuilder is as simple as the following:

  const filter = new FilterBuilder(mainTarget, queryData);

In FilterBuilder, Target is an abstraction that represents a table in your database. Depending on the type of ORM, the Target has different names. For example, in Sequelize, the Target is a Model, while in TypeORM, the Target is an Entity.

queryData is a Query-Object from client. Note, a queryData will be paginated if it contains two fields:

  • page: number of page in query
  • limit: number of item in page, if it undefined will get all records in database.

List of method in FilterBuilder:

  • Binary operator group:
   .equal() // "=" Operator   
   .gte() // ">=" Operator
   .lte() // "<=" Operator
   .like() // "Like" operator
   .in()  // "IN" operator
   .....
  • Ternary operation group:
   .range() // BETWEEN operato
  • Logical operator group:
   .and(Condition[]) // The AND operator displays a record if all the conditions are TRUE.   
   .or(Condition[]) // The OR operator displays a record if any of the conditions are TRUE.
   .....
  • Utils methods:
   .uuid() /** Check value is UUID ? and use "=" or "IN" operator */

   .makeArray() /** Parse string to array and use "BETWEEN" operator */
   
   .inConvertedArray() /** Parse string to array and use "IN" operator  */

   .run() /** Return list of Target is filted */

   .transform([async () => {}]) /** Get result and modifíe them */
  • Join methods:
   .leftJoin() /** Left join with other target */

   .rightJoin() /** Right join with other target */

NOTE:

  • The paths of the target must follow the correct order and should not be interrupted.
  // WRONG 
  filterBuilder.leftJoin("student.course", Course)
               .leftJoin("student",Student);  

  // RIGHT             
  filterBuilder.leftJoin("student",Student); 
               .leftJoin("student.course", Course)
               
  • When using targets in Conditions, remember to use the Join methods first.
  // WRONG 
  filterBuilder.or([new Condition("student).equal(),...])
               .leftJoin("student",Student);  

  // RIGHT             
  filterBuilder.leftJoin("student",Student)
               .or([new Condition("student).equal(),...])

Custom Filter Adapter

Each ORM (or query builder) is defined by an Adapter. Therefore, to attach a Filter to an ORM or customize a Filter according to the user's needs, we need to define a new Adapter class, which inherits from the FilterBuilderAdapter class:

    export class MyCustomAdapter<
      T extends object,
    > extends FilterBuilderAdapter<T> {

        ....
    }

Then, you need to register your new Adapter class with FilterBuilder:

    class CustomFactory extends FilterBuilderAdapterFactory {
        static create<T extends object>(opts: FilterBuilderAdapterFactoryOptions<T>): FilterBuilderAdapter<T> {
            return new MyCustomAdapter(....)
        }
    }

    FilterBuilderConfig.config({
        type: "custom",
        factoryAdapter: CustomFactory
    );

Example:

1.0.2

6 months ago

1.0.3

6 months ago

1.0.1

6 months ago

1.0.0

6 months ago