Skip to content

Commit

Permalink
Merge pull request #3 from Come2Daddy/refactor/changed_config_droped_…
Browse files Browse the repository at this point in the history
…dotenv

refactor: changed config means without dotenv
  • Loading branch information
Come2Daddy authored Oct 4, 2020
2 parents ca71076 + 6fa6f78 commit 2f033a5
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.env
src/.env
.nvmrc
node_modules
yarn-error.log
yarn.lock
coverage
*migrations
.upmigrc.js
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ or
```bash
yarn add pg-upmig
```

## Configuration
Either use environment variables
```bash
UPMIG_PATH=./migrations
UPMIG_TABLE=pg_upmig
```
or use `.upmigrc.js` to set global options:
```javascript
module.exports = {
migrations: "./migrations", // Where to store migrations files
table: "pg_upmig", // Table name where migrations history is stored
};
```
## Migrations folder tree view
```
.
Expand Down Expand Up @@ -54,7 +68,6 @@ Usage: pg-upmig [options] [command]
Options:
-V, --version output the version number
-h, --help display help for command
-e, --env <path> specify environment file path
-m, --migrations <path> specify migrations path (default: "./migrations")
-p, --pgtable <table> specify migration table name (default: "pg_upmig")

Expand Down Expand Up @@ -141,7 +154,6 @@ migration.up({
|options|[Global options](#global-options)|
|connection|[Connection parameters](#connection-parameters) for default `node-postgres` client|
|client|[Custom postgres client](#custom-postgres-client) instance|
|enfFile|Environment file path (.env)|

##### Global options
|Key|Type|Description|Default|
Expand Down Expand Up @@ -244,7 +256,6 @@ function customFunction () {
*Promise*

Creates timestamped migration files (sql file creation is avoided when `nosql` is `true`) using `template.stub` as a template. Filename collision is handled even if this case should not happen.
`name` is

Returns the full name of created file :
`1600775947530_create-table`
Expand Down Expand Up @@ -282,3 +293,4 @@ Returns an array of objects representing migration file:
|name|string|Migration name excluding timestamp.|
## Todo
- [ ] Custom logger implementation
- [ ] Remove dispensable dependencies
15 changes: 13 additions & 2 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
require("dotenv").config({path: "src/.env"});
const fs = require("fs");

module.exports = () => {};
module.exports = async () => {
try {
(await fs.promises.readFile(".env")) // read config file
.toString("utf8") // buffer to string
.split(/\n|\r|\r/) // break by new line
.filter(item => /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/.test(item)) // keep key / val
.map(item => {
const match = item.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/);
if (!Object.prototype.hasOwnProperty.call(process.env, match[1])) process.env[match[1]] = match[2].replace(/^("|')(.*)\1$/, "$2"); // set env
});
} catch (error) {}
};
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pg-upmig",
"version": "0.0.25",
"version": "0.0.26",
"description": "Postgresql migration tool",
"keywords": [
"database",
Expand All @@ -25,7 +25,6 @@
"dependencies": {
"chalk": "^4.1.0",
"commander": "^6.1.0",
"dotenv": "^8.2.0",
"pg": "^8.3.3"
},
"devDependencies": {
Expand Down
27 changes: 13 additions & 14 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ const migration = require("./index.js");
const pkg = require("../package.json");
const chalk = require("chalk");
const { program } = require("commander");
const path = require("path");

let migrationsPath = process.env.UPMIG_PATH||"./migrations";
let pgTable = process.env.UPMIG_TABLE||"pg_upmig";

try {
const dotConfig = require(path.join(process.cwd(), ".upmigrc.js"));
migrationsPath = dotConfig.migrations?dotConfig.migrations:migrationsPath;
pgTable = dotConfig.table?dotConfig.table:pgTable;
} catch (error) {}

function steps (s) {
const parsed = parseInt(s.replace(/[^0-9]+/g, ""));
Expand All @@ -26,16 +35,9 @@ function migTable (name) {

exports.migTable = migTable;

let envFile = ".env";
let migrationsPath = "./migrations";
let pgTable = "pg_upmig";

function setOpt (namespace) {
return (option) => {
switch (namespace) {
case "env":
envFile = option ? option:envFile;
break;
case "migrations":
migrationsPath = option ? option:migrationsPath;
break;
Expand All @@ -49,25 +51,22 @@ exports.setOpt = setOpt;

exports._env = () => {
return {
envFile,
migrationsPath,
pgTable
};
}

program.on("option:env", setOpt("env"));
program.on("option:migrations", setOpt("migrations"));
program.on("option:pgtable", setOpt("pgtable"));

program.version(pkg.version)
.arguments("<cmd> [opt]")
.usage("<command> [options]")
.option("-e, --env <path>", "specify environment file path")
.option("-m, --migrations <path>", "specify migrations path", "./migrations")
.option("-p, --pgtable <table>", "specify migration table name", "pg-upmig", migTable);

async function up (cmd) {
const mig = new migration({envFile});
const mig = new migration();
await mig.init({
table: pgTable,
migrations: migrationsPath,
Expand Down Expand Up @@ -98,9 +97,9 @@ program
});

async function create (cmd, name){
const mig = new migration({envFile});
const mig = new migration();
await mig.init({migrations: migrationsPath, table: pgTable});
const file = await mig.create(name.join("-"), cmd.nosql);
const file = await mig.create(name?name.join("-"):"", cmd.nosql);
mig.release();
return file;
}
Expand All @@ -119,7 +118,7 @@ program
});

async function pending (cmd) {
const mig = new migration({envFile});
const mig = new migration();
await mig.init({migrations: migrationsPath, table: pgTable, history: cmd.history});
const list = await mig.pending();
mig.release();
Expand Down
29 changes: 11 additions & 18 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/** @module pg-upmig */

const { Client, types } = require("pg");
const dotenv = require("dotenv");
const path = require("path");
const fs = require("fs");

Expand All @@ -12,7 +11,6 @@ const fs = require("fs");
* @param {Object} params Constructor arguments
* @param {Object} params.client Custom database client
* @param {Object} params.connection PG connection params
* @param {String} params.envFile Environment file path
* @param {Object} params.options Global options
* @param {String} params.options.table Migrations table
* @param {String} params.options.migrations Migrations path
Expand Down Expand Up @@ -44,8 +42,8 @@ class migration {
this.isConnected = false;

this.options = {
table: "pg_upmig",
migrations: "./migrations",
table: process.env.UPMIG_TABLE||"pg_upmig",
migrations: process.env.UPMIG_PATH||"./migrations",
transactionnal: true,
queryMethod: "query",
connectMethod: "connect",
Expand All @@ -56,29 +54,24 @@ class migration {
debug: false
};

if (params.options) {
Object.assign(this.options, params.options);
}

// finds environment file path first if defined
try {
const cfg = dotenv.config({path: params.envFile});
if (cfg.error) {
throw new Error("Check for standard environment file (.env)");
}
} catch (error) {
this._debug(error, 1);
dotenv.config();
const dotConfig = require(path.join(process.cwd(),".upmigrc.js"));
this.options.migrations = dotConfig.migrations?dotConfig.migrations:this.options.migrations;
this.options.table = dotConfig.table?dotConfig.table:this.options.table;
} catch (error) { }

if ((params||{}).options) {
Object.assign(this.options, params.options);
}

// Sets custom database client
if (params.client) {
if ((params||{}).client) {
this.client = params.client;
}

// Sets default database client
if (!this.client) {
if (params.connection) {
if ((params||{}).connection) {
// Uses connection params
this.client = new Client(params.connection);
} else {
Expand Down
42 changes: 19 additions & 23 deletions tests/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,12 @@ describe("Core helpers logic", () => {
});

test("setOpt function", () => {
cli.setOpt("env")("");
expect(cli._env().envFile).toBe(".env");
cli.setOpt("env")("null");
expect(cli._env().envFile).toBe("null");
cli.setOpt("migrations")("");
expect(cli._env().migrationsPath).toBe("./migrations");
expect(cli._env().migrationsPath).toBe(fixtures.migrations);
cli.setOpt("migrations")("null");
expect(cli._env().migrationsPath).toBe("null");
cli.setOpt("pgtable")("");
expect(cli._env().pgTable).toBe("pg_upmig");
expect(cli._env().pgTable).toBe(fixtures.pgTable);
cli.setOpt("pgtable")("null");
expect(cli._env().pgTable).toBe("null");
});
Expand Down Expand Up @@ -251,7 +247,7 @@ describe("Create migration file", () => {
});

test("Init and create new migration file", async () => {
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const line = response.trim();
expect(line).toEqual(expect.stringMatching(/Migration file created:\s+[0-9]+_.+$/i));
const filename = line.replace(/^.+\s([0-9]+_[0-9a-z_\-]+)$/i, "$1");
Expand All @@ -260,7 +256,7 @@ describe("Create migration file", () => {
});

test("Create new migration file without sql placeholder file", async () => {
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile, "-n"], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile, "-n"], [], {env});
const line = response.trim();
expect(line).toEqual(expect.stringMatching(/Migration file created:\s+[0-9]+_.+$/i));
const filename = line.replace(/^.+\s([0-9]+_[0-9a-z_\-]+)$/i, "$1");
Expand All @@ -283,7 +279,7 @@ describe("List pending migrations", () => {
test("List pending migratons without history", async () => {
const details = [];
for (let i = 0; i <= Math.round(Math.random() * 5); i++) {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
details.push(created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i));
}
const containing = [];
Expand All @@ -293,17 +289,17 @@ describe("List pending migrations", () => {
}
containing.push(expect.stringMatching(new RegExp(`Pending migrations:\\s+${details.length}$`, "i")));

const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.list], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.list], [], {env});
expect(response.trim().split(EOL)).toEqual(containing);

// Perform left pending migrations
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform], [], {env});
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform], [], {env});
});

test("List pending migratons with history", async () => {
const details = [];
for (let i = 0; i <= Math.round(Math.random() * 5); i++) {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
details.push(created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i));
}
const containing = [];
Expand All @@ -313,7 +309,7 @@ describe("List pending migrations", () => {
}
containing.push(expect.stringMatching(new RegExp(`Pending migrations:\\s+${details.length}/\[0\-9\]\+\\s\\(\[0\-9\]\+\\sdone\\)$`, "i")));

const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.list, "-H"], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.list, "-H"], [], {env});
expect(response.trim().split(EOL)).toEqual(containing);
});
});
Expand All @@ -330,9 +326,9 @@ describe("Perform pending migrations", () => {
});

test("Perform all pending migrations", async () => {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const details = created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i);
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform], [], {env});
expect(response.trim().split(EOL)).toEqual(expect.arrayContaining([
expect.stringMatching(new RegExp(`${details[2]}\\s+${details[1]}$`, "i")),
expect.stringMatching(/Migrations completed:\s+1$/i)
Expand All @@ -342,42 +338,42 @@ describe("Perform pending migrations", () => {
test("Perform specific number of pending migrations", async () => {
const details = [];
for (let i = 0; i < 3; i++) {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
details.push(created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i));
}
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform, "-s", "2"], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform, "-s", "2"], [], {env});
expect(response.trim().split(EOL)).toEqual(expect.arrayContaining([
expect.stringMatching(new RegExp(`${details[0][2]}\\s+${details[0][1]}$`, "i")),
expect.stringMatching(new RegExp(`${details[1][2]}\\s+${details[1][1]}$`, "i")),
expect.stringMatching(/Migrations completed:\s+2$/i)
]));

// Perform left pending migrations
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform], [], {env});
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform], [], {env});
});

test("Perform pending migrations till specific timestamp", async () => {
const details = [];
for (let i = 0; i < 3; i++) {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
details.push(created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i));
}
const ts = parseInt(details[1][1], 10) + 1;
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform, "-t", ts], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform, "-t", ts], [], {env});
expect(response.trim().split(EOL)).toEqual(expect.arrayContaining([
expect.stringMatching(new RegExp(`${details[0][2]}\\s+${details[0][1]}$`, "i")),
expect.stringMatching(new RegExp(`${details[1][2]}\\s+${details[1][1]}$`, "i")),
expect.stringMatching(/Migrations completed:\s+2$/i)
]));

// Perform left pending migrations
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform], [], {env});
await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform], [], {env});
});

test("Perform pending migrations first condition reached (steps & timestamp)", async () => {
const details = [];
for (let i = 0; i <= 4; i++) {
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
const created = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.new, fixtures.migrationFile], [], {env});
details.push(created.trim().match(/\s([0-9]+)_([0-9a-z_\-]+)$/i));
}
const byTs = Math.round(Math.random() * 3);
Expand All @@ -391,7 +387,7 @@ describe("Perform pending migrations", () => {
}
containing.push(expect.stringMatching(new RegExp(`Migrations completed:\\s+${min+1}$`, "i")));

const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, "-e", fixtures.envFile, fixtures.cli._cmds.perform, "-t", ts, "-s", bySt+1], [], {env});
const response = await proc.execute(["-m", fixtures.migrations, "-p", fixtures.pgTable, fixtures.cli._cmds.perform, "-t", ts, "-s", bySt+1], [], {env});
expect(response.trim().split(EOL)).toEqual(expect.arrayContaining(containing));
});
});
Loading

0 comments on commit 2f033a5

Please sign in to comment.