Skip to content

Use Unit Of Wrok pattern to wrap sequelize up and make sequelize easy to use.

Notifications You must be signed in to change notification settings

BibbyChung/sequelize-adapter

Repository files navigation

sequelize-adapter Build Status npm Coverage Status

Use Unit Of Wrok pattern to wrap sequelize up and make sequelize easy to use.

Requirement

Install

Install the components

npm install sequelize-adapter sequelize --save

Features

  • use the singleton pattern to design
  • use the unit of work pattern to wrap sequelize
  • use trasation feature to create, update, delete by default
  • support retrying feature
  • support ES2015 module

Quick Start

You can use TypeScirpt or JavaScript. Up to you.

TypeScript

create your classes what you need.

// myUnitOfWork.ts
import { Sequelize } from 'sequelize';
import { IChangeObject } from '../src/IChangeObject';
import { UnitOfWorkBase } from '../src/unitOfWorkBase';
import { UserRepository } from './userRepository';

export class MyUnitOfWork extends UnitOfWorkBase {

  private static _instance: Sequelize;
  static async getInstance() {
    if (!MyUnitOfWork._instance) {

      // setup db => test in memory
      const setting = {
        host: 'localhost',
        dbName: 'test_db',
        username: 'root',
        password: '1234',
        type: 'sqlite', // 'mysql'
      };
      const s = new Sequelize(setting.dbName, setting.username, setting.password, {
        dialect: 'sqlite',
        pool: {
          max: 5,
          min: 0,
          acquire: 30000,
          idle: 10000,
        },
        logging: false,
      });

      try {
        await s.authenticate();
        console.log('connect db successfully.');
      } catch (err) {
        throw err;
      }

      MyUnitOfWork._instance = s;
    }
    return new this(MyUnitOfWork._instance);
  }

  private constructor(public db: Sequelize) {
    super();
    this.init();
  }

  reps = {
    user: new UserRepository(this),
  };

  beforeSaveChange(addedEntities: IChangeObject[], updatedEntities: IChangeObject[], deletedEntities: IChangeObject[]) {
    // do something...
  }
  afterSaveChange() {
    // do something...
  }

  async close() {
    MyUnitOfWork._instance = null;
    await this.db.close();
  }

  private init() {
    // setup retrying setting
    this.retryingOption = {
      count: 3,
      watingMillisecond: 1000
    };

    // setup repositories
    this.__reps = this.reps;
  }

}

// userRepository.ts
import { DataTypes, ModelAttributes } from 'sequelize';
import { RepositoryBase } from '../src/repositoryBase';
import { UnitOfWorkBase } from '../src/unitOfWorkBase';
import { IUserEntity } from './IUserEntity';

export class UserRepository extends RepositoryBase<IUserEntity> {

  get tableName(): string {
    return 'users';
  }

  constructor(unitOfWork: UnitOfWorkBase) {
    super(unitOfWork);
  }

  get schema(): ModelAttributes {
    return {
      id: {
        type: DataTypes.UUID,
        primaryKey: true,
      },
      name: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      age: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      birthday: {
        type: DataTypes.DATE,
        allowNull: false,
      },
    };
  }

}

// IUserEntity.ts
export interface IUserEntity {
  id: string;
  name: string;
  age: number;
  birthday: Date;
}

CRUD Examples

// ==== create data =====
const mydb = await MyUnitOfWork.getInstance();
mydb.reps.user.add({
  id: uuid4(),
  name: `Bibby`,
  age: 21,
  birthday: new Date(),
});
await mydb.saveChange();

// ==== update data ====
const mydb = await MyUnitOfWork.getInstance();
const uOne = await mydb.reps.user.getFirstOrDefault<IUserEntity, IUserEntity>({ where: {id: 'xxxxx'} });
uOne.name = 'Bibby_0';
uOne.age = 28;
uOne.brithday = new Date('2011-10-10');
mydb.reps.user.update(uOne);
await mydb.saveChange();

// ==== delete data ====
const mydb = await MyUnitOfWork.getInstance();
const data = await mydb.reps.user.getAll<IUserEntity, IUserEntity>({ where: {id: 'xxxxx'} });
for (const item of data) {
  mydb.reps.user.delete(item);
}
await mydb.saveChange();


// ==== get data ====
const mydb = await MyUnitOfWork.getInstance();
const data = await mydb.reps.user.getAll<IUserEntity, IUserEntity>({ where: {id: 'xxxxx'} });
const data1 = await mydb.reps.user.getFirstOrDefault<IUserEntity, IUserEntity>({ where: {id: 'xxxxx'} });

// ==== get data by sql statement ====
const mydb = await MyUnitOfWork.getInstance();
const q = `
  select *
  from users u
  where u.age = :age
`;
const data: IUserEntity = await mydb.query(q, {
  replacements: {
    age: 22
  },
  type: QueryTypes.SELECT
});

Project Up

docker run -it --rm -v $(PWD):/app -w /app node:12.18-alpine sh

or

make workspace-up

References