Advertisement
aldikhan13

Custom Builder Sequelize

Mar 8th, 2025 (edited)
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { Injectable } from '@nestjs/common'
  2. import sequelize, {
  3.   FindOptions,
  4.   Transaction,
  5.   TransactionOptions,
  6.   Optional,
  7.   WhereOptions,
  8.   Includeable,
  9.   Op,
  10.   IncludeOptions,
  11.   CreateOptions,
  12.   UpdateOptions,
  13.   DestroyOptions,
  14.   FindAttributeOptions,
  15. } from 'sequelize'
  16. import { Repository, Sequelize, Model } from 'sequelize-typescript'
  17. import { MakeNullishOptional, NullishPropertiesOf } from 'sequelize/lib/utils'
  18. import { EPGRelationAction } from '~/domain/enums/common.enum'
  19. export { InjectModel as InjectRepository } from '@nestjs/sequelize'
  20. export { Repository } from 'sequelize-typescript'
  21.  
  22. import { response } from '~/infrastructure/common/helpers/response.helper'
  23.  
  24. @Injectable()
  25. export class SequelizeService {
  26.   constructor(private sequelize: Sequelize) {}
  27.  
  28.   async transaction<T = any>(operation: (transaction: Transaction) => Promise<T>, options?: TransactionOptions): Promise<T> {
  29.     try {
  30.       const transaction = await this.sequelize.transaction({ autocommit: false, ...options })
  31.       try {
  32.         const responseTransaction: T = await operation(transaction)
  33.         await transaction.commit()
  34.         return responseTransaction
  35.       } catch (e: any) {
  36.         await transaction.rollback()
  37.         throw response(e)
  38.       }
  39.     } catch (e: any) {
  40.       response(e)
  41.       return null
  42.     }
  43.   }
  44.  
  45.   async findOneAndUpdate<T = any>(repository: Repository<Model<T, T>>, data: Optional<T, NullishPropertiesOf<T>>, options: FindOptions<T>): Promise<T> {
  46.     try {
  47.       let repositoryModel: Model<T, T> = await repository.findOne(options)
  48.       if (!repositoryModel) return null
  49.  
  50.       repositoryModel = Object.assign(repositoryModel, { ...data })
  51.       return (await repositoryModel.save(options))?.dataValues
  52.     } catch (e: any) {
  53.       response(e)
  54.       return null
  55.     }
  56.   }
  57. }
  58.  
  59. export class SequelizeQueryBuilder<M extends Model> {
  60.   private model: Repository<M>
  61.   private options: FindOptions<M>
  62.  
  63.   constructor(model: Repository<M>) {
  64.     this.model = model
  65.     this.options = { where: {}, attributes: { include: [], exclude: [] } }
  66.   }
  67.  
  68.   select(columns: FindAttributeOptions): this {
  69.     this.options.attributes = columns
  70.     return this
  71.   }
  72.  
  73.   where(condition: WhereOptions<M>): this {
  74.     this.options.where = condition
  75.     return this
  76.   }
  77.  
  78.   andWhere(condition: WhereOptions<M>): this {
  79.     if (!this.options.where) {
  80.       this.options.where = {}
  81.     }
  82.     Object.assign(this.options.where, condition)
  83.     return this
  84.   }
  85.  
  86.   orWhere(condition: WhereOptions<M>): this {
  87.     if (!this.options.where[Op.or]) {
  88.       this.options.where[Op.or] = []
  89.     }
  90.     this.options.where[Op.or].push(condition)
  91.     return this
  92.   }
  93.  
  94.   orWhereIn<T = any>(field: keyof M, values: T[]): this {
  95.     if (!this.options.where[Op.or]) {
  96.       this.options.where[Op.or] = []
  97.     }
  98.     this.options.where[Op.or].push({ [field]: { [Op.in]: values } })
  99.     return this
  100.   }
  101.  
  102.   andWhereIn<T = any>(field: keyof M, values: T[]): this {
  103.     this.options.where[String(field)] = { [Op.in]: values }
  104.     return this
  105.   }
  106.  
  107.   whereNot(condition: WhereOptions<M>): this {
  108.     this.options.where[Op.not] = condition
  109.     return this
  110.   }
  111.  
  112.   whereNotIn<T = any>(field: keyof M, values: T[]): this {
  113.     this.options.where[String(field)] = { [Op.notIn]: values }
  114.     return this
  115.   }
  116.  
  117.   whereIn<T = any>(field: keyof M, values: T[]): this {
  118.     this.options.where[String(field)] = { [Op.in]: values }
  119.     return this
  120.   }
  121.  
  122.   orderBy(field: keyof M, direction: 'ASC' | 'DESC' = 'ASC'): this {
  123.     this.options.order = [[String(field), direction]]
  124.     return this
  125.   }
  126.  
  127.   limit(limit: number): this {
  128.     this.options.limit = limit
  129.     return this
  130.   }
  131.  
  132.   offset(offset: number): this {
  133.     this.options.offset = offset
  134.     return this
  135.   }
  136.  
  137.   include(include: Includeable | Includeable[]): this {
  138.     this.options.include = Array.isArray(include) ? include : [include]
  139.     return this
  140.   }
  141.  
  142.   join(options: IncludeOptions | IncludeOptions[], action: EPGRelationAction, alias?: string): this {
  143.     if (Array.isArray(options)) {
  144.       options = options.map((option: IncludeOptions) => {
  145.         if (alias) {
  146.           option.as = alias
  147.         }
  148.  
  149.         if (action === EPGRelationAction.INNER) {
  150.           option.required = true
  151.         } else if (action === EPGRelationAction.LEFT) {
  152.           option.required = false
  153.         } else if (action === EPGRelationAction.RIGH) {
  154.           option.required = true
  155.           option.right = true
  156.         }
  157.  
  158.         return option
  159.       })
  160.     } else {
  161.       if (alias) {
  162.         options.as = alias
  163.       }
  164.  
  165.       if (action === EPGRelationAction.INNER) {
  166.         options.required = true
  167.       } else if (action === EPGRelationAction.LEFT) {
  168.         options.required = false
  169.       } else if (action === EPGRelationAction.RIGH) {
  170.         options.required = true
  171.         options.right = true
  172.       }
  173.     }
  174.  
  175.     this.include(options)
  176.  
  177.     return this
  178.   }
  179.  
  180.   insert(values: MakeNullishOptional<M>, options?: CreateOptions): Promise<M> {
  181.     return this.model.create(values, options)
  182.   }
  183.  
  184.   update(values: Partial<M>, options?: UpdateOptions & { returning?: boolean | Array<keyof M> }): Promise<[number, M[]]> {
  185.     return this.model.update(values, { ...options, where: this.options.where, returning: options?.returning || true })
  186.   }
  187.  
  188.   delete(options?: DestroyOptions & { returning?: boolean | Array<keyof M> }): Promise<number> {
  189.     return this.model.destroy({ ...options, where: this.options.where })
  190.   }
  191.  
  192.   like(field: keyof M, value: string): this {
  193.     this.options.where = sequelize.where(sequelize.literal(`${String(field)}::text`), {
  194.       [Op.iLike]: `%${value}%`,
  195.     })
  196.     return this
  197.   }
  198.  
  199.   orLike(field: keyof M, value: string): this {
  200.     if (!this.options.where[Op.or]) {
  201.       this.options.where[Op.or] = []
  202.     }
  203.     this.options.where[Op.or].push(
  204.       sequelize.where(sequelize.literal(`${String(field)}::text`), {
  205.         [Op.iLike]: `%${value}%`,
  206.       }),
  207.     )
  208.     return this
  209.   }
  210.  
  211.   andLike(field: keyof M, value: string): this {
  212.     if (!this.options.where) {
  213.       this.options.where = {}
  214.     }
  215.     this.options.where = sequelize.where(sequelize.literal(`${String(field)}::text`), {
  216.       [Op.iLike]: `%${value}%`,
  217.     })
  218.     return this
  219.   }
  220.  
  221.   getOne(): Promise<M | null> {
  222.     return this.model.findOne({ ...this.options, raw: false })
  223.   }
  224.  
  225.   getMany(): Promise<M[]> {
  226.     return this.model.findAll({ ...this.options, raw: false })
  227.   }
  228.  
  229.   getOneRaw(): Promise<M | null> {
  230.     return this.model.findOne({ ...this.options, raw: true })
  231.   }
  232.  
  233.   getManyRaw(): Promise<M[]> {
  234.     return this.model.findAll({ ...this.options, raw: true })
  235.   }
  236.  
  237.   getCount(): Promise<number> {
  238.     delete this.options.attributes
  239.     return this.model.count(this.options)
  240.   }
  241. }
  242.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement