Skip to content

Instantly share code, notes, and snippets.

@IagoPFerreira
Last active April 25, 2024 11:20
Show Gist options
  • Save IagoPFerreira/ae0d2846eb395be44ead1a991303bedf to your computer and use it in GitHub Desktop.
Save IagoPFerreira/ae0d2846eb395be44ead1a991303bedf to your computer and use it in GitHub Desktop.

Criando o Sequelize com TypeScript

Partindo do pressuposto que o projeto já tem uma configuração base para usar TypeScript em conjunto com Express, é possível encontrar exemplos de configurações básicas neste gist de Express com TypeScript.

Pacotes iniciais

  1. Instalar o dotenv
npm i dotenv
  1. Instalar o Sequelize
npm i sequelize
  1. Instalar o @types/sequelize
npm i @types/sequelize
  • Atalho
npm i dotenv sequelize @types/sequelize
  1. Instalar o mysql2
npm i -D @types/sequelize
  1. Instalar o sequelize-cli
npm i -D @types/sequelize
  • Atalho
npm i -D mysql2 sequelize-cli

Configuração inicial

  1. Gere um arquivo ./.sequelizerc
  touch .sequelizerc
  1. Garanta as seguintes configurações
const path = require('path');

module.exports = {
  'config': path.resolve(__dirname,'dist','database','config', 'config.js'),
  'models-path': path.resolve(__dirname,'dist','database','models'),
  'seeders-path': path.resolve(__dirname,'src','database', 'seeders'),
  'migrations-path': path.resolve(__dirname,'src','database', 'migrations'),
};
  1. Inicie o sequelize
npx sequelize-cli init
  1. Crie as pastas faltantes ./src/database/config/, ./src/database/models/
mkdir ./src/database/config/ ./src/database/models/
  1. Crie o arquivo config.ts em ./src/database/config/
touch ./src/database/config/config.ts
  1. Garanta as seguintes configurações
import 'dotenv/config';
import { Options } from 'sequelize';

const config: Options = {
  username: process.env.DB_USER || 'root',
  password: process.env.DB_PASS || '',
  database: process.env.DB_NAME || 'books_api',
  host: process.env.DB_HOST || 'localhost',
  port: Number(process.env.DB_PORT) || 3306,
  dialect: 'mysql',
}

export default config;
  1. Crie um script de transpilação do arquivo de configuração e criação do banco
//...
"scripts": {
  //...
    "db:reset": "npx -y tsc && npx sequelize-cli db:drop && npx sequelize-cli db:create",
  //...
 },
//...
  1. Verifique se está tudo certo, executando o script
npm run db:reset

Inicializando o Sequelize

  1. Crie um arquivo index.ts no diretório ./src/database/models/
touch ./src/database/models/index.ts
  1. Instancie o Sequelize dentro deste arquivo
import { Sequelize } from 'sequelize';
import * as config from '../config/config';

export default new Sequelize(config);
  1. Crie as migrations
npx sequelize migration:generate --name create-users
npx sequelize migration:generate --name create-vets
npx sequelize migration:generate --name create-pets
npx sequelize migration:generate --name create-attendances
  1. Altere as migrations
'use strict';
module.exports = {
  async up (queryInterface, Sequelize) {
    await queryInterface.createTable('users', {
      id: { 
        type: Sequelize.INTEGER,
        allowNull: false, 
        primaryKey: true,
        autoIncrement: true,
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false, 
      },
      passowordHash: {
        type: Sequelize.STRING,
        allowNull: false, 
        field: 'password_hash'
      },
      name: {
        type: Sequelize.STRING,
        allowNull: false, 
      },
      phone: {
        type: Sequelize.STRING,
        allowNull: false, 
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
        field: 'created_at',
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
        field: 'updated_at'
      }
    })
  },

  async down (queryInterface, Sequelize) {
    await queryInterface.dropTable('users');
  }
};
  1. Executar a migration
npx sequelize db:migrate

Caso queira reverter:

npx sequelize db:migrate:undo

Ou:

npx sequelize db:migrate:undo:all
  1. Criar um novo seed
npx sequelize seed:generate --name users
npx sequelize seed:generate --name vets
npx sequelize seed:generate --name pets
npx sequelize seed:generate --name attendances
  1. Adicionar as informações que serão colocadas no banco
// seeders/XXXXXXXXXXXXX-users.js

'use strict';
module.exports = {
  async up (queryInterface, Sequelize) {
    console.log('here!')
    await queryInterface.bulkInsert('users',
    [
      {
        name: 'Yarpen Zigrin',
        email: 'yarpen.zigrin@commerce.com',
        'password_hash': 'c2f28289d2ed874df63306dc0305e642',
        phone: '999999999',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Ford Perfect',
        email: 'ford.perfect@yahoo.com',
        'password_hash': 'b4df15c4d4cc344b161638d78aad20f8',
        phone: '888888888',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Arthur Dent',
        email: 'dent.arthur@gmail.com',
        'password_hash': '5b0cedd4fc9cda69752f9adb7d75833f',
        phone: '777777777',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Hurley Reyes',
        email: 'hurley.reyes@commerce.com',
        'password_hash': 'f7b16af5588f9654862e4aefcec8b0de',
        phone: '666666666',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Franklin Clinton',
        email: 'clinton_gs.franklin@yahoo.com',
        'password_hash': '0f5d023227880c7629468b0b0ab3d650',
        phone: '555555555',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Trevor Phillips',
        email: 'phillips.trevor@tpindustries.com',
        'password_hash': '40bc4b7c2b114dc11c98b4c3fdf0679f',
        phone: '444444444',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Carol Denvers',
        email: 'denvers.carol@commerce.com',
        'password_hash': '64c9ac2bb5fe46c3ac32844bb97be6bc',
        phone: '333333333',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      {
        name: 'Vovo Juju',
        email: 'vovo.juju@hotmail.com',
        'password_hash': '62608e08adc29a8d6dbc9754e659f125',
        phone: '222222222',
        'created_at': Sequelize.literal('CURRENT_TIMESTAMP'),
        'updated_at': Sequelize.literal('CURRENT_TIMESTAMP'),
      },
    ], { });
  },
  
  async down (queryInterface) { queryInterface.bulkDelete('users', null, {}) }
};
  1. Executar o seed
npx sequelize db:seed:all

E para reverter:

npx sequelize db:seed:undo:all
  1. Criar o Model

Neste passo um ponto temos um ponto de atenção, se executarmos o comando npx sequelize model:generate --name users --attributes name:string, em conjunto com o nosso model será criado um novo arquivo de migration para a tabela users, porém nós já temos essa migration, sendo assim, apague a nova migration gerada.

Aqui iremos usar o terminal para criar a model, mas não usaremos a cli do sequelize, usaremos o bash mesmo

touch ./src/database/models/users.ts
  1. Adicione as informações referentes ao Model
// models/user.ts

import { DATE, INTEGER, Model, STRING } from 'sequelize';
import db from '.';

class User extends Model {
  id!: number;
  email!: string;
  passwordHash!: string;
  name!: string;
  phone!: string;
  createdAt!: Date;
  updatedAt!: Date;
}

User.init({
  id: {
    type: INTEGER,
    allowNull: false,
    primaryKey: true,
    autoIncrement: true,
  },
  email: {
    type: STRING,
    allowNull: false,
  },
  passwordHash: {
    type: STRING,
    allowNull: false,
  },
  name: {
    type: STRING,
    allowNull: false,
  },
  phone: {
    type: STRING,
    allowNull: false,
  },
  createdAt: {
    type: DATE,
    allowNull: false,
  },
  updatedAt: {
    type: DATE,
    allowNull: false,
  },
}, {
  sequelize: db,
  modelName: 'users',
  underscored: true,
});

export default User;
  1. Crie a associação entre os Models
// models/pet.ts

import { Model, STRING, INTEGER, DATE} from 'sequelize';
import db from '.';
import User from './user';

class Pet extends Model {
  id!: number;
  name!: string;
  createdAt!: Date;
  updatedAt!: Date;
}

Pet.init({
  id: {
    type: INTEGER,
    allowNull: false,
    primaryKey: true,
    autoIncrement: true,
  },
  name: {
    type: STRING,
    allowNull: false,
  },
  userId: {
    type: INTEGER,
    allowNull: false,
    
  },
  createdAt: {
    type: DATE,
    allowNull: false,
  },
  updatedAt: {
    type: DATE,
    allowNull: false,
  }
}, {
  sequelize: db,
  modelName: 'pets',
  underscored: true
});

Pet.belongsTo(User, { foreignKey: 'userId', as: 'user' })

export default Pet;
  1. Chame uma função do Sequelize passando uma associação
// src/testModel.ts

import Pet from "./database/models/pet";

(async () => {
    const books = await Pet.findAll({
      raw: true,
      include: [ Pet.associations.user ]
    });
    console.log(books);
    process.exit(0)
  })();
  1. Execute o arquivo com o ts-node
npx ts-node src/testModel.ts

@isaacbatst
Copy link

No passo 9 tem um export = config; não seria export default config ou export config apenas?

@renatosousafilho
Copy link

No tópico 21 faz mais sentido começar implementando o model User pois ele vai ser referenciado no model Pet.

@IagoPFerreira
Copy link
Author

@isaacbatst corrigido

@renatosousafilho corrigido

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