npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

postgres-migrator

v1.1.0

Published

Simple database migrations for PostgreSQL.

Downloads

100

Readme

postgres-migrator

Simple database migrations for PostgreSQL.

Getting started

Install

$ npm install postgres postgres-migrator

Example

const postgres = require("postgres");
const postgresMigrator = require("postgres-migrator");

const sql = postgres();
const migrator = postgresMigrator(sql);

const migrated = await migrator.apply();

Behavior

Migration is one-way. There is no ability to reverse a migration, as this is rarely used, and is better handled with a new migration that reverts a previous one.

Directories being migrated are expected to contain zero or more migration files. Any unrecognized file types will be ignored.

Migration files are sorted before being applied, so you can be certain that 001.sql will be applied before 002.sql.

As you would expect, only unapplied migrations will be applied.

Each migration is run in a database transaction. Any errors encountered are left uncaught and migration ceases at that point. Migrations completed previously are left applied, and once the error is corrected, migrator.apply can be run again and migration will continue from the last migration that was successfully applied.

Each migrator instance represents a directory of migration files. If you need to support multiple directories, you can create a migrator instance for each directory with a different table name.

Only the filename of the migration file is recorded, so relocating or renaming the directory will not affect the tracking.

Migrations are tracked using a database table named migrations (configurable).

Migrations are assumed to be in the directory ./migrations (configurable).

Migration files

SQL migration files

SQL migration files are just plain sql, as you would expect. The only restriction is that they have the extension ".sql" (lower case).

An example sql migration file might be 010-users-table-add-email.sql:

alter table users add column email text not null unique;

JavaScript migration files

JavaScript migration files are javascript modules that export a default function (can be async) that takes as its only argument an instance of a postgres client (typically named sql).

See the postgres documentation for its capabilities.

If a promise is returned, it will be awaited.

The file must be in CommonJS (module.exports) syntax.

An example javascript migration file might be 010-users-table-add-email.js:

module.exports = (sql) => {
	return sql`alter table users add column email text not null unique`;
};

API

Creating a migrator object

const migrator = postgresMigrator(sql, { ...options });

The first argument must be a postgres client object.

The second argument is an optional options object with the following default properties:

const migrator = postgresMigrator(sql, {
	table: "migrations",
	directory: "./migrations",
});

Applying migrations

const migrated = await migrator.apply();

If needed, the return value is an array of migration files that were applied during that function call.

Testing if a file has been migrated

const exists = await migrator.has(filename);

Getting all migrated files

const migrated = await migrator.all();

Events

Emits apply after a migration file is applied

migrator.on("apply", (file) => {
	console.log("applied migration file:", file);
});

await migrator.apply();

Recommendations

Creating migration files

To reduce confusion, new migration files should be sorted after old ones. You can ensure this by using a shell function like the following to generate new migrations that are sorted by the timestamp when they were created:

function mkmigration() {
	local name=$1
	local ext=${2:-sql}
	local ts=$(date +%Y%m%d%H%M%S)
	touch "${PWD}/migrations/${ts}.${ext}"
}

This will allow you to do the following:

$ mkmigration users-table
$ ls migrations
20201225103045-users-table.sql

Obviously this could be easily tailored to your project, such as using a template for new migrations or a different way to establish proper sorting.

Command-line interface

I originally planned to include a command-line interface, but could not decide how to make it flexible enough. I'll leave it to you to decide how best to implement that for your project, but the following should be sufficient for most:

#!/usr/bin/env node

const postgres = require("postgres");
const postgresMigrator = require("postgres-migrator");

const sql = postgres(process.env.POSTGRES_URL);
const migrator = createMigrator(sql);

migrator.on("apply", (file) => {
	console.log("applied migration file:", file);
});

migrator
	.apply()
	.catch((error) => {
		console.error(error);
		process.exit(1);
	})
	.finally(sql.end);

Obviously this could be easily tailored to your project, such as using a command-line parser to allow options to be configurable, or migrating multiple directories.

Contributing

Testing

Test files expect the environment variable POSTGRES_URL to point to your database. No existing tables will be affected, including migrations, as unique table names are used and dropped after the test finishes.

A docker compose file is included which provisions a database that's configured as expected:

$ docker-compose up

To run tests:

$ npm test