Skip to content

Instantly share code, notes, and snippets.

@jyotendra
Last active February 22, 2018 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jyotendra/57039b29d5a5dd375ff631c3227f80dd to your computer and use it in GitHub Desktop.
Save jyotendra/57039b29d5a5dd375ff631c3227f80dd to your computer and use it in GitHub Desktop.
'sequelize-model-importer.ts' is used to connect all models with main model, in sequelize.
import * as fs from 'fs'
import * as path from 'path'
import * as Sequelize from 'sequelize'
// configuration to connect to db are getted
const config = require('../config/config.json')
// Import model specification from its own definition file.
import { LanguageInstance, LanguageAttributes } from './language'
import { AppUserInstance, AppUserAttributes } from './appuser'
interface DbConnection {
Language: Sequelize.Model<LanguageInstance, LanguageAttributes>,
AppUser: Sequelize.Model<AppUserInstance, AppUserAttributes>
}
/**
* Object that will be used to hold all imported models and sequelize instance
*/
let db = {}
// db-config based on current node environment is getted and used.
const dbConfig = config[process.env.NODE_ENV]
const sequelize = new Sequelize(
dbConfig['database'],
dbConfig['username'],
dbConfig['password'],
dbConfig
)
/**
* basename of file is getted, in our case it is "sequelize-model-importer.ts"
*/
const basename = path.basename(module.filename)
/**
* readdirSync returns file (files only, not folder) from directory yielded by __dirname
* __dirname returns the directory path of the script currently invoked.
* the files being emitted by readdirSync are transferred to a filter that tests for the following conditions:
* - file.indexOf('.') !== 0) : checks if the file don't have '.' at first place. Ex: '.gitignore', '.vscode' etc
* - (file !== basename): ignores the current file thats currently executing.
* - (file.slice(-3) === '.js'): only file with js extension are included (as typescript will be compiled to js at some point)
*/
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
})
.forEach(function(file) {
/**
* The file that successfully pass the filter is imported by sequelize.
*/
const model = sequelize['import'](path.join(__dirname, file))
// NOTE: you have to change from the original property notation to
// index notation or tsc will complain about undefined property.
db[model['name']] = model
})
Object.keys(db).forEach(function(modelName) {
/**
* If the model do have 'associate' method declared then call it.
* associate is a user defined method that's included by user in extended model
* upto sequelize v3, class extension methods were to be defined inside 'classMethods' object.
* from sequelize v4, classes are extended as Model.associate = function (models){}
* see http://docs.sequelizejs.com/manual/tutorial/upgrade-to-v4.html for more details
*/
if (db[modelName].associate) {
// entire db object is passed, so that required model can be getted and associated.
db[modelName].associate(db)
}
})
/**
* Sequelize is the entire 'sequelize' node module
* sequelize is instance of sequelize orm which is connected with db
*/
db['sequelize'] = sequelize
db['Sequelize'] = Sequelize
// The exported
export default <DbConnection>db
import * as Sequelize from 'sequelize'
export interface AppUserAttributes {
id?: string
active?: boolean,
avatar?: string,
email?: string,
firstName?: string,
lastName?: string,
notification?: boolean,
phone?: string,
pwd?: string,
languageId?: string
}
export interface AppUserInstance extends Sequelize.Instance<AppUserAttributes> {
id: string
createdAt: Date
updatedAt: Date
email: string,
pwd: string,
languageId: string
}
export default function defineUser(sequelize: Sequelize.Sequelize, DataTypes) {
const AppUser = sequelize.define('AppUser', {
email: DataTypes.STRING,
pwd: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
AppUser.belongsTo(models.Language, {
foreignKey: 'languageId',
onDelete: 'CASCADE',
})
}
}
});
return AppUser
}
{
"development": {
"username": "postgres",
"password": "postgres",
"database": "app-dev",
"host": "127.0.0.1",
"port": 5432,
"dialect": "postgres",
"logging": true,
"force": true,
"timezone": "+00:00"
},
"test": {
"username": "postgres",
"password": "postgres",
"database": "app-test",
"host": "127.0.0.1",
"port": 5432,
"dialect": "postgres",
"logging": true,
"force": true,
"timezone": "+00:00"
},
"production": {
"username": "postgres",
"password": "postgres",
"database": "app",
"host": "127.0.0.1",
"port": 5432,
"dialect": "postgres",
"logging": true,
"force": true,
"timezone": "+00:00"
}
}
import * as Sequelize from 'sequelize'
export interface LanguageAttributes {
id?: string
label?: string
name?: string
}
export interface LanguageInstance extends Sequelize.Instance<LanguageAttributes> {
id: string
createdAt: Date
updatedAt: Date
label: string
name: string
}
export default function defineUser(sequelize: Sequelize.Sequelize, DataTypes) {
const Language = sequelize.define('Language', {
label: DataTypes.STRING(255),
name: DataTypes.STRING(50)
}, {
classMethods: {
associate: function(models) {
Language.hasMany(models.AppUser, {
foreignKey: 'languageId',
as: 'appUsers'
})
}
}
})
return Language
}
@jyotendra
Copy link
Author

These files are from this repo: https://github.com/maximegris/typescript-express-sequelize
I have just commented and arranged the files to suit my understanding. Thanks to repo author for putting up the project.

"language.ts" and "appuser.ts" are models file, which defines table structure.

"config.json" is used to store connection object for database.

"_index.ts" invokes sequelize instance using configurations defined in config.json and exports a 'db' object which can be used by "data-access objects" to interact with DB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment