1.9.4 • Published 5 years ago

wander-cli v1.9.4

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

Wander

Database Migrations for Modern Apps

Introduction

Wander is a command-line tool that enables programmable database changes. Through Migrations, you can version control your database and easily commit or revert changes between versions.

Supported Databases

Currently, only mysql is supported. Adapters for other databases are still under development.

  • MySQL
  • PostgreSQL
  • SQL Server
  • Oracle DB

Getting Started

To get started, globally install wander-cli

> npm install -g wander-cli

Initializing Wander

To initialize a new wander project, run wander init inside your project folder

> mkdir MyDatabase
> cd MyDatabase
> wander init

This will ask you for the name of your migrations folder (default: ./migrations) and your database URI. Once completed, you can now start using wander.

Changing environments

wander supports migrations for different environments. To change your current wander environment, run wander env inside your project folder

> wander env

Creating a new Migration

To create a new migration, run wander new <name>.

> wander new create_post

This will create a new file inside your migrations folder

+ migrations
  - v1_0_0__create_post.js
+ wrconfig.json
+ .gitignore

Note that you can change the type of version that your new migration will use, using the -t or --version-type option.

{major}.{minor}.{patch}

Version Commands:

  • major: wander new create_post -t major (e.g. 2.0.0)
  • minor: wander new crete_post -t minor (e.g. 1.1.0)
  • patch: wander new create_posrt -t patch (e.g. 1.0.1)

Once created, the file would look similar to the following.

v1_0_0__create_post.js

module.exports = {
    version() {
        return '1.0.0';
    },
    description() {
        return `Create post`;
    },
    async up({}) {
    },
    async down({}) {
    }
};

Description

  • The version method returns the version name of your migration.
  • The description method returns the a brief description of your database changes. You can expand this as you wish.
  • The up method runs whenever the migration is committed
  • The down method runs whenever the migration is reverted

For the up and down methods, an object is passed to them for your usage, which includes serveral useful functions. Check the API section for more information.

Example

module.exports = {
    version() {
        return '1.0.0';
    },
    description() {
        return `Create post`;
    },
    async up({ create, seed }) {
        create('post', table => {
            table.id();
            table.string('caption');
            table.timestamps();
        });

        seed('post', [
            { caption: 'New post!' },
            { caption: 'Another post!' }
        ]);
    },
    async down({ drop, truncate }) {
        truncate('post');
        drop('post');
    }
};

API

create

Parameters

ParamterData type
tableNamestring
definition(table: Table) => void

Description

  • Accepts a tableName that you want to create, and a definition function.
  • The definition function has a Table parameter that allows you to define the structure of your table.

Example

create('post', table => {
    table.id();
    table.string('caption');
    table.timestamps();
});

alter

Parameters

ParamterData type
tableNamestring
definition(table: Table) => void

Description

  • Accepts a tableName that you want to alter, and a definition function.
  • The definition function has a Table parameter that allows you to define the structure of your table.

Example

alter('comment', table => {
    table.integer('comment_count').add();
});

drop

Parameters

ParamterData type
tableNamestring

Description

  • Accepts a tableName that you want to drop.

Example

drop('comment');

seed

Parameters

ParamterData type
tableNamestring
seedsobject[]

Description

  • Accepts a tableName that you want to seed with data.
  • Accepts a seeds array of objects defining the data you want to insert.

NOTE: Only the columns of the first item in the list will define the columns that will be populated for all of the items.

Example

seed('post', [
    { caption: 'A new post!' },
    { capton: 'Another post' }
]);

truncate

Parameters

ParamterData type
tableNamestring

Description

  • Accepts a tableName that you want to truncate.

Example

truncate('comment');

execute

Parameters

ParamterData type
querystring

Description

  • Ideal for running scripts that are too complex or are too specific to the database you are running.
  • Accepts a query that you want to execute.

WARNING: Running execute is very dangerous especially if the keys and values you are trying to use are not properly escaped.

Example

execute(`
    SET sql_safe_updates = 0;
    UPDATE post SET updated_at = now() WHERE id > 5;
`);

Table class

Description

  • Allows you to define the structue of your table via different methods

Methods

  • id(columnName?: string)
    • Adds a primary auto_increment key (default: id)
  • string(columnName: string, length?: number)
    • Adds a string column (e.g. on MySQL this is equivalent to varchar)
  • text(columnName: string)
    • Adds a text column (unlike string, there is no limit to the length)
  • integer(columnName: string, length?: number)
    • Adds an integer column
  • float(columnName: string, length?: number, precision?: number)
    • Adds a float column
  • decimal(columnName: string, length?: number, precision?: number)
    • Adds a decimal column
  • double(columnName: string, length?: number, precision?: number)
    • Adds a double column
  • date(columnName: string)
    • Adds a date column
  • datetime(columnName: string)
    • Adds a datetime column
  • boolean(columnName: string)
    • Adds a boolean column (e.g. on MySQL this is equivalent to bit)
  • json(columnName: string)
    • Supported in MySQL 5.7+
  • char(columnName: string, length?: number)
    • Adds a char data type column
  • timestamps()
    • Creates created_at, updated_at and deleted_at datetime columns
  • index(columnName: string, alias?: string)
    • Create an index on the table
  • unique(columnName: string, alias?: string)
    • Create a unique index on the table

You can also specify specific options for creation.

  • nullable(isNullable?: boolean)
    • Determine whether the field should be nullable or not nullable
  • increments()
    • State that the field should auto-increment

Key Actions

In addition, when using the alter option, the above methods have specific actions that need to be defined in order to let wander know how the columns are going to be changed.

  • add()
    • Add the column/index/unique key
  • modify()
    • Modify the column
  • drop()
    • Drop the column/index/unique key

You can also specify specific options for the alteration.

  • nullable(isNullable?: boolean)
    • Determine whether the field should be nullable or not nullable
  • increments()
    • State that the field should auto-increment
  • first(column?: string)
    • Determine the position of the column
  • after(column?: string)
    • Determine the position of the column

Example

alter('comment', table => {
    table.integer('comment_count').add();
    table.index('IDENT').drop();
});

Sample migration

module.exports = {
    version() {
        return '1.0.0';
    },
    description() {
        return `
            Created the post table.
            Changed the comment table.
            Populated the post table.
        `;
    },
    async up({ create, alter, seed, execute }) {
        create('post', table => {
            table.id();
            table.string('caption', 500);
            table.pointer('user');
            table.json('info');
            table.string('identifier');
            table.index('identifier', 'IDENT');
            table.timestamps();
        });

        // Equivalent to the following
        `
        CREATE TABLE post (
        id int AUTO_INCREMENT,
        caption varchar(500),
        user_id int(11),
        info json,
        identifier varchar(30),
        PRIMARY KEY (id),
        INDEX IDENT (identifier));
        `

        alter('comment', table => {
            table.integer('like_count').add();
            table.string('message', 250).modify();
            table.pointer('post').drop();
            table.index('IDENT').drop();
        });

        // Equivalent to the following
        `
        ALTER TABLE comment 
        ADD COLUMN like_count int,
        MODIFY COLUMN message varchar(250),
        DROP COLUMN post_id;
        `

        seed('post', [
            { caption: 'New caption!' },
            { caption: 'New caption!' },
            { caption: 'New caption!' }
        ]);

        // Equivalent to the following
        `
        INSERT INTO post
        (caption)
        VALUES
        ('New caption!'),
        ('New caption!'),
        ('New caption!');
        `

        execute(`
            SET sql_safe_updates = 0;
            UPDATE post SET privacy = 'public' WHERE role IS NULL;
        `);
    },
    async down({ alter, drop, truncate }) {

        truncate('post');
        drop('post');

        alter('comment', () => {
            this.integer('like_count').drop();
            this.string('message', 500).modify();
            this.pointer('post').add();
            this.index('identifier', 'IDENT').add();
        });

        execute(`UPDATE post SET privacy = 'private' WHERE role IS NULL`);
    }
};

Committing Pending Migrations

After you've set up your migrations, you can now commit them. To commit pending migrations, run the command below.

> wander commit

You can apply the --verbose or -v flag to see the actual scripts being run. Note that wander runs the migrations in the order of their version number.

Reverting Commited Migrations

To revert migrations you've already committed, run the following command.

> wander revert

Like commit, you can apply the --verbose or -v flag to see the actual scripts being run. Also, you can specify the --count or -c parameter in order to tell wander how many migrations are going to be reverted, starting from the latest version.

Resetting All Migrations

To reset all migrations, run the command below.

> wander reset

Like the previous commands, you can apply the --verbose or -v flag to see the actual scripts being run. The commands are reset from latest to oldest version.

Up versus Down

In terms of the Migrations standard for databases, the convention is to always have up and down methods.

The purpose of the up method is to commit the changes you want to apply to the database. Conversely, it is required that you undo everything that you performed, inside the down method.

The reason why this practice is observed is that it allows you, to some extent, to recover from a breaking change that was executed accidentally. Also, it allows you to ensure consistency when changing between database versions.

Do note, however, that unless a seed option is defined inside the methods, any data that was truncated or dropped will be lost forever.

Transactions

For wander, all migrations are executed as a single transaction. That means the MigrationOptions you used will not be fired until the processor has gone through all of them.

That also means that if anything goes wrong, the scripts will be rolled back (except for cases where database auto-commits occur). See the corresponding manuals of your databases for more information.

1.9.4

5 years ago

1.9.3

5 years ago

1.9.2

5 years ago

1.9.1

5 years ago

1.9.0

5 years ago

1.8.0

5 years ago

1.7.0

5 years ago

1.6.0

5 years ago

1.5.1

5 years ago

1.5.0

5 years ago

1.4.1

6 years ago

1.4.0

6 years ago

1.3.3

6 years ago

1.3.2

6 years ago

1.3.1

6 years ago

1.3.0

6 years ago

1.2.2

6 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.5

6 years ago

1.1.4

6 years ago

1.1.3

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago