Skip to content

Commit

Permalink
feat: read migrations and previous schema from history
Browse files Browse the repository at this point in the history
Refs: #23
  • Loading branch information
tshemsedinov committed Sep 12, 2020
1 parent 5ec31f3 commit 925ed65
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
10 changes: 8 additions & 2 deletions lib/ddl.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const PG_TYPES = {
money: 'numeric(12, 2)',
date: 'date',
time: 'time',
datetime: 'timestamp',
datetime: 'timestamp with time zone',
uuid: 'uuid',
url: 'varchar',
inet: 'inet',
Expand Down Expand Up @@ -101,10 +101,16 @@ class PgSchema extends DatabaseSchema {
const generate = async (schemaPath, outputPath) => {
const schema = await new PgSchema(schemaPath);
await schema.preprocess();
await schema.validate();
await schema.generate(outputPath);
};

const migrate = async schemaPath => {
const schema = await new PgSchema(schemaPath);
await schema.preprocess();
await schema.migrate();
};

module.exports = {
generate,
migrate,
};
44 changes: 44 additions & 0 deletions lib/schema-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ class DatabaseSchema {
this.path = schemaPath;
this.entities = new Map();
this.order = new Set();
this.database = null;
return this.load();
}

async load() {
const files = await fs.readdir(this.path, { withFileTypes: true });
const dbPath = path.join(this.path, '.database.js');
this.database = await new Schema(dbPath);
for (const file of files) {
if (file.isDirectory()) continue;
if (!file.name.endsWith('.js')) continue;
if (file.name.startsWith('.')) continue;
const absPath = path.join(this.path, file.name);
const schema = await new Schema(absPath);
if (!schema) continue;
Expand Down Expand Up @@ -81,6 +85,46 @@ class DatabaseSchema {
const args = `${name}, ${JSON.stringify(entity)}`;
throw new Error(`Method is not implemented: generateEntity(${args})`);
}

async getPreviousSchema() {
const historyPath = path.join(this.path, '.history');
const folders = await fs.readdir(historyPath, { withFileTypes: true });
let version = 0;
let previousName = '';
for (const folder of folders) {
if (!folder.isDirectory()) continue;
const { name } = folder;
const v = parseInt(name.substring(name.indexOf('v') + 1), 10);
if (v > version) {
version = v;
previousName = folder.name;
}
}
if (version === 0) return null;
const previousPath = path.join(historyPath, previousName);
return new DatabaseSchema(previousPath);
}

async migrate() {
const { name, driver, version } = this.database;
const now = new Date().toISOString().substring(0, 10);
console.log(`Migration ${driver} database: ${name} v${version} (${now})`);
const ps = await this.getPreviousSchema();
if (!ps) {
console.log('Previous schema is not found in ../.history');
return;
}
const folder = path.basename(ps.path);
const date = folder.substring(0, folder.lastIndexOf('v') - 1);
console.log(`Previous schema: v${ps.database.version} (${date})`);
const newFolder = path.join(this.path, `.history/${date}-v${version}`);
const mig = path.join(this.path, `.migration/${date}-v${version}`);
const migUp = mig + '-up.sql';
const migDn = mig + '-dn.sql';
console.log(`Save history: ${newFolder}`);
console.log(`Migration up: ${migUp}`);
console.log(`Migration down: ${migDn}`);
}
}

module.exports = { DatabaseSchema };
3 changes: 2 additions & 1 deletion test/ddl.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use strict';

const path = require('path');
const { generate } = require('../lib/ddl.js');
const { generate, migrate } = require('../lib/ddl.js');

const cwd = process.cwd();
const schemaPath = path.join(cwd, 'test/schema');
const outputPath = path.join(cwd, 'test/sql');

generate(schemaPath, outputPath);
migrate(schemaPath);

0 comments on commit 925ed65

Please sign in to comment.