This tutorial is assuming:
- You have a working NestJS project
- You are using MongoDB and mongoose
In the recent past, I had an urge to do a bit of refactoring on my discord game. Still a work in progress, but I couldn't stand anymore the fact that houses were named homes... I already can hear you, 'just change labels displayed no one care!'.
I do care about the consistency of naming in my codebases. If homes are houses then the next thing you know is: Canons will become wooden swords and wolves are dogs...
I spent some time online looking for solutions and I finally built something I like. Let me present to you the result of my work.
I chose to use the migrate
library since it is database agnostic, offers an easy up/down logic, and can store the migration status in any form.
Enough speaking about me, let me guide you through this journey.
Install migrate
Go on install the bad guy!
npm i --save migrate
You will new two folders:
mkdir src/migrations
mkdir src/migrations-utils
The first one will store the update scripts and the seconds will store some utilities. Let's look into the seconds.
In the introduction, I told you that migrate is database agnostic. Therefore you need to write a little mongodb connector:
import { MongoClient } from 'mongodb';
import { configs } from '../config/configuration';
const MONGO_URL = configs.mongoUrl;
export const getDb = async () => {
const client: any = await MongoClient.connect(MONGO_URL, { useUnifiedTopology: true });
return client.db();
};
Nice! let's keep going.
Migrate is a tool made in javascript. And we use typescript, the best thing to do is have a little template with the database already connected.
import { getDb } from '../migrations-utils/db';
export const up = async () => {
const db = await getDb();
/*
Code your update script here!
*/
};
export const down = async () => {
const db = await getDb();
/*
Code you downgrade script here!
*/
};
I had some trouble with ts-node/register
in migrate command line.
This little helper solved my transpilation errors!
Do the same! now! do it!
// eslint-disable-next-line @typescript-eslint/no-var-requires
const tsNode = require('ts-node');
module.exports = tsNode.register;
it's time for you to update the package.json
of your project in order to have easy to use scripts for the future!
Add this sweet line in the package.json
, in the script section!
"migrate:create": "migrate create --template-file ./src/migrations-utils/template.ts --migrations-dir=\"./src/migrations\" --compiler=\"ts:./src/migrations-utils/ts-compiler.js\"",
--template-file ./src/migrations-utils/template.ts
provide a template file, it's a necessary thing since we are in a typescript repo.
It also provides you an easy way to bootstrap migration just the way you like it!
--migrations-dir=\"./src/migrations\"
Tell migrate where your migration scripts are stored.
By default, it's at the project root.
--compiler=\"ts:./src/migrations-utils/ts-compiler.js\"
Explain to migrate how to handle typescript files.
Now, you just need to run this command to create an empty typescript migration file in the correct folder!
npm run migrate:create -- <migration name>
AAAAAAnd two more lines in the package.json
, again in the scripts section!
"migrate:up": "migrate --migrations-dir=\"./src/migrations\" --compiler=\"ts:./src/migrations-utils/ts-compiler.js\" up",
"migrate:down": "migrate --migrations-dir=\"./src/migrations\" --compiler=\"ts:./src/migrations-utils/ts-compiler.js\" down"
No new options here, I already explained them but refreshing is nice.
--migrations-dir=\"./src/migrations\"
Tells migrate where to find your migrations!
--compiler=\"ts:./src/migrations-utils/ts-compiler.js\"
Tells migrate how to handle typescript...
You can now run update script: npm run migrate:up
or downgrade script npm run migrate:down
Migrate will store your migration state in a file at the project root.
This file is called migrate.json
.
It looks like this:
{
"lastRun": "1605197159478-test.ts",
"migrations": [
{
"title": "1605197159478-test.ts",
"timestamp": 1605197181474
}
]
}
DO NOT COMMIT migrate.json
I'll be glad to answers questions in the comments.
If you liked my discord consider joining my coding lair! :phone:Webeleon coding lair on discord
You can also email me and offer me a contract 💰 ✉️Email me!
And since I'm a nice guy, here, take this sample repo containing a working codebase! :gift:Get the code of the tuto from github