0.3.3 • Published 5 years ago

douze-sequelize v0.3.3

Weekly downloads
1
License
MIT
Repository
github
Last release
5 years ago

douze-sequelize

MIT License Travis CI Build Average issue resolution time Number of open issues

Use Sequelize in Douze to connect to SQL databases.

Features

Installation

Install douze-sequelize along with your desired database driver:

  • pg pg-hstore for PostgreSQL
  • mysql2 for MySQL
  • mariadb for MariaDB
  • sqlite3 for SQLite
  • tedious for Microsoft SQL Server (MSSQL)

Example for Postgres:

$ yarn add douze-sequelize pg pg-hstore
# or
$ npm i douze-sequelize pg pg-hstore

Usage

Import it into your app and extend Douze with it:

import Douze from 'douze'
import douzeSequelize from 'douze-sequelize'

const douze = new Douze()

douze.extend(douzeSequelize())

async function main() {
  const app = douze.createApp()
  await douze.start(app)
}

if (require.main === module) {
  main()
}

Configuration

You can configure the name of the environment variable used for the connection URI, along with the paths where to load models and migrations:

douze.extend(
  douzeSequelize({
    envNames: {
      // uri will be read from process.env.SERVICES_POSTGRES_URI
      uri: 'SERVICES_POSTGRES_URI'
    },
    paths: {
      models: [path.join(__dirname, './db/models')]
    },
    options: {
      // Pass more options to the Sequelize constructor here
      ...
    }
  })
)

Models definition

You can follow the documentation of sequelize-typescript, with one catch: as noted in this issue, models have to use the same package as the one with which the Sequelize instance is created (ie: the one used in douze-sequelize).

To solve that and minimize the amount of dependency-juggling, douze-sequelize re-exports all definitions from sequelize-typescript, so you can do:

- import { Model, Table, Column } from 'sequelize-typescript'
+ import { Model, Table, Column } from 'douze-sequelize'

Accessing the Sequelize instance

The Sequelize instance can be found in your app, at app.locals.sequelize:

import Douze from 'douze'
import douzeSequelize from 'douze-sequelize'

const douze = new Douze()

douze.extend(douzeSequelize())

export default async function main() {
  const app = douze.createApp()

  // Access the sequelize instance
  await app.locals.sequelize.authenticate()

  // Note: douze.start will do the `authenticate` part for you
  // and handle / log errors.
  await douze.start(app)
}

Multiple databases

If you want to connect to multiple databases, you can call extend as many times as you want with different configurations.

However, to differenciate the sequelize instances, you'll have to give them unique names:

import path from 'path'
import Douze from 'douze'
import douzeSequelize from 'douze-sequelize'

const douze = new Douze()

douze.extend(
  douzeSequelize({
    name: 'pg',
    envNames: {
      uri: 'SERVICES_POSTGRES_URI'
    },
    paths: {
      models: [path.join(__dirname, './db/pg/models')]
    }
  })
)

douze.extend(
  douzeSequelize({
    name: 'sqlite',
    type: 'sqlite', // only needed for SQLite
    envNames: {
      // URI to a file path is optional on SQLite,
      // if unset at runtime it will use :memory:
      uri: 'SERVICES_SQLITE_FILE_PATH'
    },
    paths: {
      models: [path.join(__dirname, './db/sqlite/models')]
    }
  })
)

export default async function main() {
  const app = douze.createApp()

  // Access the sequelize instances by their names:
  await app.locals.pg.authenticate()
  await app.locals.sqlite.authenticate()

  await douze.start(app)
}

Migrations

Migrations are a way to run modifications to the database structure in production.

douze-sequelize uses umzug for migration definitions, and stores the migration state in the database itself.

  1. Declare the path of the directory where you will store your migration files:
douze.extend(douzeSequelize(
  paths: {
    migrationsDirectory: path.join(__dirname, './db/migrations')
  }
))
  1. Write a migration definition file:
// db/migrations/0001-name-of-migration.ts
import { MigrationArgs } from 'douze-sequelize'

export const up = async ({ douze, app, sequelize }: MigrationArgs) => {
  // Place your 'forward' modifications here
}

export const down = async ({ douze, app, sequelize }: MigrationArgs) => {
  // Place your 'rollback' modifications here
}

Extra configuration

You can pass additional configuration to umzug as shown:

douze.extend(douzeSequelize(
  paths: {
    migrationsDirectory: path.join(__dirname, './db/migrations')
  },
  umzug: { // Umzug configuration object
    migrations: {
      // Eg: add extra arguments to the up/down migration functions:
      wrap: f => (args: MigrationArgs) => f({ ...args, foo: 'bar' }),
    }
  }
))
  1. Run your migrations with the {name}:migrate task:
import Douze from 'douze'
import douzeSequelize from 'douze-sequelize'

const douze = new Douze()

douze.extend(
  douzeSequelize({
    name: 'mysql'
  })
)

const app = douze.createApp()

douze.invokeTask('mysql:migrate', app)

Tasks

This plugin exposes the following tasks, where {name} is the value of the name field in the options, or sequelize by default:

  • {name}:init - Initialize the database, force-syncing models and dropping all data.
  • {name}:seed - Run seeding functions (not implemented yet)
  • {name}:migrate - Execute all pending migrations
  • {name}:rollback - Rollback the latest migration (if any)

Environment variables

This plugin exposes the following environment variables for runtime configuration:

  • DOUZE_SEQUELIZE_CONNECTION_RETRIES: optional, defines the number of retries allowed to establish the connection to the database. Note that up to N+1 attempts will be performed (the initial attempt + N retries). Defaults to 7 retries (8 attempts) if unset.

  • DOUZE_SEQUELIZE_CONNECTION_RETRY_DELAY_MS: optional, defines the delay in milliseconds before the first retry. Exponential backout strategy is used, so this delay is doubled for each retry. Defaults to 150ms if unset.

  • DOUZE_SEQUELIZE_FORCE_SYNC: optional, set to true to drop all data and recreate the database structure on application startup. Has an effect only in development.

  • DOUZE_DATABASE_NO_MIGRATIONS: optional, set to true to skip running migrations on application startup. Has an effect only in production.

Roadmap

Features and stories required to reach 1.0.0:

  • Retry logic for initial connection
  • Migrations in production
  • Seeding