@rxstack/sequelize-service
v0.7.0
Published
RxStack Sequelize Service
Downloads
14
Maintainers
Readme
The RxStack Sequelize Service
Sequelize service that implements @rxstack/platform adapter API and querying syntax.
Table of content
Installation
npm install @rxstack/sequelize-service --save
// peer depencencies
npm install --no-save @rxstack/core@^0.7 @rxstack/platform@^0.7 @rxstack/exceptions@^0.6 @rxstack/query-filter@^0.6 @rxstack/security@^0.7 @rxstack/async-event-dispatcher@^0.6 @rxstack/service-registry@^0.6 winston@^3.3.3
and add one of the following:
npm install --save pg pg-hstore
npm install --save mysql2 // For both mysql and mariadb dialects
npm install --save sqlite3
npm install --save tedious // MSSQL
Setup
SequelizeServiceModule
needs to be registered in the application
. Let's create the application:
In the example we are using
mysql
.
import {Application, ApplicationOptions} from '@rxstack/core';
import {SequelizeServiceModule} from '@rxstack/sequilize-service';
export const APP_OPTIONS: ApplicationOptions = {
imports: [
SequelizeServiceModule.configure({
connection: {
host: process.env.MYSQL_HOST,
database: process.env.MYSQL_DATABASE,
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
dialect: 'mysql',
define: {
timestamps: false
}
},
logger: {
enabled: true
}
})
],
providers: [
// ...
]
};
new Application(APP_OPTIONS).start();
Module Options
connection
: sequelize optionslogger.enabled
: enable query logging (defaults to false)logger.level
: logging level
Service Options
In addition to service base options we need to set the following options:
model
: sequelize model
Usage
Create interfaces
First we need to create model interface
and InjectionToken
:
import {InjectionToken} from 'injection-js';
import {SequelizeService} from '@rxstack/sequelize-service';
export interface Product {
id: string;
name: string;
}
export const PRODUCT_SERVICE = new InjectionToken<SequelizeService<Product>>('PRODUCT_SERVICE');
Create sequelize models
import {DataTypes, Sequelize} from 'sequelize';
import {ModelStatic} from '@rxstack/sequelize-service';
export const defineProduct = (connection: Sequelize): ModelStatic => {
return <ModelStatic>connection.define('product', {
_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING, allowNull: false, unique: true,
validate: {
notEmpty: true
}
}
});
};
define all models in a singe function (useful to set associations) :
import {DataTypes, Sequelize} from 'sequelize';
import {ModelStatic} from '@rxstack/sequelize-service';
import {defineProduct} from './product.schema';
export const defineModels = (connection: Sequelize): {[key: string]: ModelStatic} => {
const product = defineProduct(connection);
// define other models here
// ...
// define associations here
return {
product
// ...
};
};
then register the service and models in the application provides:
import {InjectionToken} from 'injection-js';
import {ApplicationOptions} from '@rxstack/core';
import {SequelizeService} from '@rxstack/sequelize-service';
import {SEQUELIZE_CONNECTION_TOKEN} from '@rxstack/sequelize-service'
import {ModelStatic} from '@rxstack/sequelize-service';
import {Sequelize} from 'sequelize';
export const SEQUELIZE_MODELS = new InjectionToken<{[key: string]: ModelStatic}>('SEQUELIZE_MODELS');
export const APP_OPTIONS: ApplicationOptions = {
// ...
providers: [
{
provide: SEQUELIZE_MODELS,
useFactory: (conn: Sequelize) => defineModels(conn),
deps: [SEQUELIZE_CONNECTION_TOKEN],
},
{
provide: PRODUCT_SERVICE,
useFactory: (conn: Sequelize, models: {[key: string]: ModelStatic}) => {
return new SequelizeService<Product>({
idField: '_id', defaultLimit: 25, model: models['product']
});
},
deps: [SEQUELIZE_CONNECTION_TOKEN, SEQUELIZE_MODELS],
},
]
};
How to use in controller
import {Injectable} from 'injection-js';
import {Http, Request, Response, WebSocket, InjectorAwareInterface} from '@rxstack/core';
@Injectable()
export class ProductController implements InjectorAwareInterface {
@Http('POST', '/product', 'app_product_create')
@WebSocket('app_product_create')
async createAction(request: Request): Promise<Response> {
// getting connection
const conn = this.injector.get(SEQUELIZE_CONNECTION_TOKEN);
const service = this.injector.get(PRODUCT_SERVICE);
// standard use
await service.insertOne(request.body);
// with transaction and sequelize model options
await conn.transaction(async (t: any) => {
await service.insertOne(request.body, {transaction: t});
await anotherService.insertOne(request.body, {transaction: t});
});
}
}
How to build queries with query-filter
If you use @rxstack/query-filter to build db queries then you need to replace default operators with sequelize specific ones:
import {QueryFilterSchema} from '@rxstack/query-filter';
import {Op} from 'sequelize';
export const myQueryFilterSchema: QueryFilterSchema = {
'properties': {
'product_name': {
'property_path': 'name',
'operators': ['$ne', '$eq'],
'replace_operators': [['$eq', Op.eq], ['$ne', Op.ne]],
'sort': true
}
},
'allowOrOperator': true,
'replaceOrOperatorWith': Op.or,
'defaultLimit': 10
};
Commands
Helpful commands managing your sequelize database
Sync
Sync all defined models to the DB. More info
npm run cli sequelize:sync
with "force" option, defaults to false
npm run cli sequelize:sync -- -f
Drop
Drop all tables. More info
npm run cli sequelize:drop
Validation Observer
ValidationObserver
converts sequelize errors to BadRequestException
.
In order to return proper validation errors and status code 400
we catch the exception and throw BadRequestException
.
The error messages can be accessed exception.data['errors']
and implement ValidationError[]
.
License
Licensed under the MIT license.