mysql-migration 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2023-present 𝐒𝐡𝐞𝐫𝐊𝐚𝐧
2
+
3
+ This software is protected by copyright and is provided under this license.
4
+
5
+ You are allowed to use this software only for non-commercial purposes and only in the form in which it is distributed by the author. You are not allowed to modify the source code, redistribute this software in any form, or use it for commercial purposes.
6
+
7
+ This software is provided "as is," without any warranty of any kind. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the use or distribution of this software.
package/README.md CHANGED
@@ -4,44 +4,63 @@ A simple command-line tool for generating and running database migrations for My
4
4
 
5
5
  ## Installation
6
6
 
7
- You can install `mysql-migration` using npm:
8
- npm install -g mysql-migration
7
+ You can install `mysql-migration` using npm: `npm install mysql-migration`
9
8
 
9
+ ### Initialize the migrations table
10
10
 
11
- ## Usage
11
+ If you have not yet run any migrations, you need to initialize the migrations table by running the following command: `npx mysql-migration init`
12
12
 
13
- ### Create a new migration
13
+ <br>
14
14
 
15
- To create a new migration, run the following command:
16
- npx mysql-migration migration-name database-name
15
+ ## Configuration
17
16
 
18
- This will create a new migration file in the `migrations` directory with a timestamp and the name `migration-name`.
17
+ The configuration file `mysql-migration.config.json` should export an object with the following properties:
19
18
 
19
+ - `host`: the MySQL server host
20
+ - `database`: the name of the database to migrate
21
+ - `user`: the MySQL user name
22
+ - `password`: the MySQL user password
20
23
 
21
- ### Running migrations
24
+ ```json
25
+ {
26
+ "databases": {
27
+ "db_name": {
28
+ "host": "db_host",
29
+ "user": "db_user",
30
+ "password": "db_password",
31
+ "database": "db_name"
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ <br>
22
38
 
23
- To run pending migrations, run the following command:
24
- npx mysql-migration run database-name (optional)
39
+ ## Usage
25
40
 
41
+ ### Create a new migration
26
42
 
27
- This will run all migrations that have not yet been run.
43
+ To create a new migration, run the following command:\
44
+ &emsp;`npx mysql-migration migration-name database-name`
28
45
 
29
- ### Initialize the migrations table
46
+ This will create a new migration file in the `migrations` directory with a timestamp and the name `migration-name`.
47
+
48
+ ### Running migrations
30
49
 
31
- If you have not yet run any migrations, you need to initialize the migrations table by running the following command:
32
- npx mysql-migration init
50
+ To run pending migrations, run the following command:\
51
+ &emsp;`npx mysql-migration run database-name(optional)`
33
52
 
53
+ This will run all migrations that have not yet been run.
34
54
 
35
- ### Configuration
55
+ ### Rolling back migrations
36
56
 
37
- The configuration file should export an object with the following properties:
57
+ To roll back the last migration, run the following command:\
58
+ &emsp;`npx mysql-migration rollback database-name batch`
38
59
 
39
- - `host`: the MySQL server host
40
- - `database`: the name of the database to migrate
41
- - `user`: the MySQL user name
42
- - `password`: the MySQL user password
60
+ This will roll back migrations to the given batch number.
43
61
 
62
+ <br>
44
63
 
45
- ### License
64
+ > **Copyright (c) 2023-present [𝐒𝐡𝐞𝐫𝐊𝐚𝐧](https://github.com/SherKan-n). All Rights Reserved.**
46
65
 
47
- This package is licensed under the MIT License.
66
+ <br>
package/index.js CHANGED
@@ -1,10 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  const program = require('commander');
3
3
  //---------------------------------------
4
- program
5
- .version('1.0.0')
6
- .description('Migration for mysql database');
7
- //---------------------------------------
8
4
  program
9
5
  .command('init')
10
6
  .description('Initialize migration')
@@ -15,6 +11,11 @@ program
15
11
  .description('Run migration')
16
12
  .action((dbName) => require('./src/commands/run')(dbName));
17
13
  //---------------------------------------
14
+ program
15
+ .command('rollback <dbName> <batch>')
16
+ .description('Run migration backward')
17
+ .action((dbName, batch) => require('./src/commands/back')(dbName, batch));
18
+ //---------------------------------------
18
19
  program
19
20
  .command('create <migrationName> <dbName>')
20
21
  .description('Create a new migration')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql-migration",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Migration for mysql database",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -21,5 +21,5 @@
21
21
  "commander": "^2.20.0"
22
22
  },
23
23
  "author": "SherKan",
24
- "license": "MIT"
24
+ "license": "SEE LICENSE IN LICENSE.md"
25
25
  }
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+ //==============================================================================
3
+ const fs = require('fs');
4
+ const mysql = require('mysql');
5
+ //---------------------------------------
6
+ const currentPath = process.cwd();
7
+ const config = require(`${currentPath}/migrations/mysql-migration.config.json`);
8
+ const { checkTableMigrations, createTableMigrations, getAllMigrations, getCurrentBatch, deleteMigration } = require("../utils/functions");
9
+ //==============================================================================
10
+ async function back_migration(dbName, batch) {
11
+ const connection = {};
12
+ const databases = config.databases;
13
+ //---------------------------------------
14
+ if (dbName) {
15
+ const batchNumber = parseInt(batch);
16
+ if (isNaN(batchNumber)) {
17
+ console.error('\x1b[31m%s\x1b[0m', `Error: Invalid batch number.`);
18
+ process.exit(1);
19
+ }
20
+ //---------------------------------------
21
+ if (!databases[dbName]) {
22
+ console.error('\x1b[31m%s\x1b[0m', `Error: Invalid database name "${dbName}".`);
23
+ process.exit(1);
24
+ }
25
+ //---------------------------------------
26
+ connection[dbName] = mysql.createConnection(databases[dbName]);
27
+ connection[dbName].connect((err) => {
28
+ if (err) {
29
+ console.error('\x1b[31m%s\x1b[0m', `Error: Unable to connect to database "${dbName}".\n${err}`);
30
+ process.exit(1);
31
+ }
32
+ });
33
+ //---------------------------------------
34
+ const tableMigrations = await checkTableMigrations(connection[dbName]);
35
+ if (!tableMigrations) await createTableMigrations(connection[dbName]);
36
+ //---------------------------------------
37
+ const currentBatch = await getCurrentBatch(connection[dbName]);
38
+ if (batchNumber >= currentBatch) {
39
+ console.error('\x1b[31m%s\x1b[0m', `Error: Invalid batch number, the current batch is "${currentBatch}".`);
40
+ process.exit(1);
41
+ }
42
+ const migrations = await getAllMigrations(connection[dbName], batchNumber);
43
+ //---------------------------------------
44
+ for (let file of migrations) {
45
+ if (!fs.existsSync(`${currentPath}/migrations/${dbName}_db/${file.migration}.js`)) {
46
+ console.warn('\x1b[33m%s\x1b[0m', `Warning: Migration "${file.migration}" not found.`);
47
+ }
48
+ else {
49
+ const migration = require(`${currentPath}/migrations/${dbName}_db/${file.migration}`);
50
+ try {
51
+ await migration.down(connection[dbName]);
52
+ await deleteMigration(connection[dbName], file.migration, batchNumber);
53
+ console.log('\x1b[32m%s\x1b[0m', `Migration "${file.migration}" has been successfully rolled back.`);
54
+ }
55
+ catch (err) {
56
+ console.warn('\x1b[33m%s\x1b[0m', `Warning: "${err}" in migration "${file.migration}".`);
57
+ }
58
+ }
59
+ }
60
+ connection[dbName].end();
61
+ }
62
+ else console.error('\x1b[31m%s\x1b[0m', `Error: Database name is empty !`);
63
+ }
64
+ //==============================================================================
65
+ module.exports = back_migration;
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const moment = require('moment');
5
5
  //---------------------------------------
6
6
  const currentPath = process.cwd();
7
- const config = require(`${currentPath}/migrations/config.json`);
7
+ const config = require(`${currentPath}/migrations/mysql-migration.config.json`);
8
8
  //---------------------------------------
9
9
  function create_migration(migrationName, dbName) {
10
10
  if (!migrationName) {
@@ -5,7 +5,7 @@ const fs = require('fs');
5
5
  const currentPath = process.cwd();
6
6
  //---------------------------------------
7
7
  if (!fs.existsSync(`${currentPath}/migrations`)) fs.mkdirSync(`${currentPath}/migrations`);
8
- if (!fs.existsSync(`${currentPath}/migrations/config.json`)) fs.writeFileSync(`${currentPath}/migrations/config.json`, JSON.stringify({
8
+ if (!fs.existsSync(`${currentPath}/migrations/mysql-migration.config.json`)) fs.writeFileSync(`${currentPath}/migrations/mysql-migration.config.json`, JSON.stringify({
9
9
  "databases": {
10
10
  "db_name": {
11
11
  "host": "db_host",
@@ -15,4 +15,4 @@ if (!fs.existsSync(`${currentPath}/migrations/config.json`)) fs.writeFileSync(`$
15
15
  }
16
16
  }
17
17
  }, null, 3));
18
- console.log('\x1b[32m%s\x1b[0m', `Created migration config file: "config.json" in the "migrations" directory.`);
18
+ console.log('\x1b[32m%s\x1b[0m', `Created migration config file: "mysql-migration.config.json" in the "migrations" directory.`);
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const mysql = require('mysql');
5
5
  //---------------------------------------
6
6
  const currentPath = process.cwd();
7
- const config = require(`${currentPath}/migrations/config.json`);
7
+ const config = require(`${currentPath}/migrations/mysql-migration.config.json`);
8
8
  const { checkTableMigrations, createTableMigrations, getAllMigrations, getCurrentBatch, insertMigration } = require("../utils/functions");
9
9
  //==============================================================================
10
10
  async function run_migration(dbName) {
@@ -22,9 +22,11 @@ function createTableMigrations(connection) {
22
22
  });
23
23
  }
24
24
  //---------------------------------------
25
- function getAllMigrations(connection) {
25
+ function getAllMigrations(connection, batch = null) {
26
26
  return new Promise((resolve) => {
27
- connection.query("SELECT `migration` FROM `migrations`;", (error, results) => {
27
+ let query = "SELECT `migration` FROM `migrations`";
28
+ if (batch) query += " WHERE `batch` > ?;";
29
+ connection.query(query, [batch], (error, results) => {
28
30
  if (error) throw error;
29
31
  if (results?.length > 0) resolve(results);
30
32
  else resolve([]);
@@ -52,6 +54,16 @@ function insertMigration(connection, migration, batch) {
52
54
  });
53
55
  }
54
56
  //---------------------------------------
57
+ function deleteMigration(connection, migration, batch) {
58
+ return new Promise((resolve) => {
59
+ const query = `DELETE FROM \`migrations\` WHERE \`migration\` = '${migration}' AND \`batch\` > '${batch}';`
60
+ connection.query(query, (error) => {
61
+ if (error) throw error;
62
+ resolve(true);
63
+ });
64
+ });
65
+ }
66
+ //---------------------------------------
55
67
  module.exports = {
56
- checkTableMigrations, createTableMigrations, getAllMigrations, getCurrentBatch, insertMigration
68
+ checkTableMigrations, createTableMigrations, getAllMigrations, getCurrentBatch, insertMigration, deleteMigration
57
69
  }