├── .gitignore ├── .npmignore ├── .prettierrc ├── LICENSE ├── README.md ├── package.json ├── src ├── configs │ ├── index.ts │ ├── mongoconf.ts │ └── mysqlconf.ts ├── index.ts └── lib │ ├── datatypes.ts │ └── migrate.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | json-data-files 3 | generated-schema-models 4 | package-lock.json 5 | lib 6 | configs 7 | *.js 8 | yarn.lock -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | data-files 2 | 3 | json-data-files 4 | generated-schema-models 5 | package-lock.json 6 | 7 | *.log 8 | npm-debug.log* 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | .nyc_output 13 | 14 | # Dependency directories 15 | node_modules 16 | 17 | # npm package lock 18 | package-lock.json 19 | yarn.lock 20 | 21 | # project files 22 | src 23 | test 24 | examples 25 | CHANGELOG.md 26 | .travis.yml 27 | .editorconfig 28 | .eslintignore 29 | .eslintrc 30 | .babelrc 31 | .gitignore -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 320, 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "trailingComma": "es5", 6 | "jsxSingleQuote": true 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Danny Sofftie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MySQL to MongoDB data migration tool 2 | 3 | A Node.js script to migrate MySQL data to MongoDB, mapping MySQL tables to MongoDB collections. 4 | 5 | Supports migrations over network, use cases: 6 | 1. MySQL database hosted in GCP, to MongoDB hosted in Digital Ocean, 7 | 2. MySQL local database, to MongoDB Atlas, 8 | 3. MySQL database hosted in Linode, to local MongoDB instance, 9 | 4. And so much more ... 10 | 11 | Will allow migrations from and to remote sites. 12 | 13 | ![mysql-mongo-etl](https://user-images.githubusercontent.com/17042186/50631158-694f8780-0f54-11e9-89b4-465fc98eb2dd.gif) 14 | 15 | ## Migrate your existing MySQL data into MongoDB 16 | 17 | Open terminal/command promt and follow any of below methods. 18 | 19 | Before you continue, ensure you have [Node.js](https://nodejs.org/download) installed in your system. See [here](https://nodejs.org/download) for more instructions. If you have it installed, you can continue below. 20 | 21 | **Method I (For developers)** 22 | 23 | 1. Clone project 24 | > git clone https://github.com/dannysofftie/mysql-mongo-etl.git 25 | 2. Change working directory 26 | > cd mysql-mongo-etl 27 | 3. Install dependencies 28 | > npm install 29 | 4. Make it happen :wink: 30 | > npm run migrate 31 | 32 | **Method II (This is for non-developers/non technical guys)** 33 | 34 | 1. Install package globally 35 | > npm install -g mysql-mongo-etl 36 | 2. Run command 37 | > mysql-mongo-etl 38 | 39 | --- 40 | 41 | For both methods, you will be prompted to enter authentication credentials for your MySQL and MongoDB databases. Ensure you have access credentials that have read/write roles enabled, or else you will encounter errors. 42 | 43 | --- 44 | 45 | Issues might occur if you don't have authentication set up in your MongoDB database, as read and write roles are required when inserting bulk data into MongoDB. 46 | 47 | Follow below steps to enable authentication in your server: 48 | 49 | > This set up is for Linux distros only. Check online for your operating system if not a linux distro. 50 | 51 | 52 | - Login to your server and create a user for your database. 53 | > $ mongo 54 | ```bash 55 | mongo~$ use databaseName 56 | mongo~$ db.createUser({user: "username", pwd: "password", role: [{roles: "readWrite", db: "databaseName"}]}) 57 | ``` 58 | 59 | _Replace with your preferred credentials. You will use them to do migration in the other steps_ 60 | 61 | - Exit the mongo shell and restart mongod service. 62 | 63 | - Uncomment the following code block at the bottom of `/etc/mongo.conf`, or add if not available. 64 | 65 | > sudo vi /etc/mongo.conf 66 | 67 | ```sh 68 | # security: 69 | # authorization: enabled 70 | ``` 71 | 72 | - After enabling authentication and create a user with appropriate credentials, restart your mongo instance for this to take effect 73 | > sudo service restart mongo 74 | 75 | --- 76 | 77 | You should be ready to migrate your data now. Follow **Method I** or **Method II** as above. 78 | 79 | --- 80 | 81 | ### Roadmap 82 | 83 | - [x] Retrieve MySQL database models and data 84 | - [x] Generate Mongoose schemas in Typescript 85 | - [x] Dump MySQL data to MongoDB 86 | - [x] Support migrations over the network 87 | - [ ] Prevent duplicates in subsequent migrations 88 | 89 | ## LICENSE 90 | 91 | MIT License 92 | 93 | Copyright (c) 2018 - 2020 Danny Sofftie 94 | 95 | Permission is hereby granted, free of charge, to any person obtaining a copy 96 | of this software and associated documentation files (the "Software"), to deal 97 | in the Software without restriction, including without limitation the rights 98 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 99 | copies of the Software, and to permit persons to whom the Software is 100 | furnished to do so, subject to the following conditions: 101 | 102 | The above copyright notice and this permission notice shall be included in all 103 | copies or substantial portions of the Software. 104 | 105 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 106 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 107 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 108 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 109 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 110 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 111 | SOFTWARE. 112 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysql-mongo-etl", 3 | "version": "1.4.0", 4 | "description": "An ETL Node.js script to migrate MySQL data to MongoDB, mapping MySQL tables to MongoDB collections.", 5 | "bin": { 6 | "mysql-mongo-etl": "index.js" 7 | }, 8 | "main": "index.js", 9 | "scripts": { 10 | "start": "ts-node-dev --respawn --transpileOnly --no-notify src/index.ts", 11 | "prepublish": "tsc .", 12 | "migrate": "node ." 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/dannysofftie/mysql-mongo-etl.git" 17 | }, 18 | "keywords": [ 19 | "mysql", 20 | "mongodb", 21 | "mysql-migrate" 22 | ], 23 | "author": "Danny Sofftie", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/dannysofftie/mysql-mongo-etl/issues" 27 | }, 28 | "homepage": "https://github.com/dannysofftie/mysql-mongo-etl#readme", 29 | "dependencies": { 30 | "mongoose": "^5.8.9", 31 | "mysql": "^2.18.1", 32 | "ora": "^4.0.3", 33 | "prompts": "^2.3.0" 34 | }, 35 | "devDependencies": { 36 | "@types/mongoose": "^5.5.43", 37 | "@types/mysql": "^2.15.8", 38 | "@types/ora": "^3.2.0", 39 | "@types/prompts": "^2.0.3", 40 | "ts-node-dev": "^1.0.0-pre.44", 41 | "typescript": "^3.7.5" 42 | } 43 | } -------------------------------------------------------------------------------- /src/configs/index.ts: -------------------------------------------------------------------------------- 1 | export interface IMysqlConfig { 2 | mysqlusername: string; 3 | mysqlhost: string; 4 | mysqlpassword: string; 5 | mysqldatabase: string; 6 | } 7 | 8 | export interface IMongoConfig { 9 | mongousername: string; 10 | mongohost: string; 11 | mongopassword: string; 12 | mongodatabase: string; 13 | } 14 | 15 | export function mysqlConfig(options?: IMysqlConfig): string { 16 | try { 17 | return `mysql://${options.mysqlusername.trim()}:${options.mysqlpassword.trim()}@${options.mysqlhost.trim()}:3306/${options.mysqldatabase.trim()}?connectionLimit=10&dateStrings=true`; 18 | } catch (e) { 19 | return process.exit(); 20 | } 21 | } 22 | 23 | export function mongoConfig(options?: IMongoConfig): string { 24 | try { 25 | return new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(?!$)|$)){4}$/).test(options.mongohost) 26 | ? `mongodb://${options.mongousername.trim()}:${options.mongopassword.trim()}@${options.mongohost.trim()}/${options.mongodatabase.trim()}?authSource=admin&readPreference=primary&retryWrites=true&w=majority&ssl=false` 27 | : `mongodb+srv://${options.mongousername.trim()}:${options.mongopassword.trim()}@${options.mongohost.trim()}/${options.mongodatabase.trim()}?authSource=admin&readPreference=primary&retryWrites=true&w=majority&ssl=false`; 28 | } catch (e) { 29 | return process.exit(); 30 | } 31 | } 32 | 33 | export * from './mysqlconf'; 34 | -------------------------------------------------------------------------------- /src/configs/mongoconf.ts: -------------------------------------------------------------------------------- 1 | import { IMongoConfig, mongoConfig } from '.'; 2 | import * as ora from 'ora'; 3 | import { MongoClient, Db } from 'mongodb'; 4 | 5 | export class MongoConnection { 6 | public database: Db; 7 | 8 | public connection: MongoClient; 9 | 10 | private options: IMongoConfig; 11 | 12 | constructor(options: IMongoConfig) { 13 | this.options = options; 14 | } 15 | 16 | public connect(): Promise { 17 | const spinner = ora('Establishing MongoDB connection').start(); 18 | return new Promise((resolve) => { 19 | MongoClient.connect( 20 | mongoConfig(this.options), 21 | { useUnifiedTopology: true, useNewUrlParser: true }, 22 | (err, client) => { 23 | if (err) { 24 | spinner.fail(`MongoDB connection error ${err.message}`).stop(); 25 | process.exit(); 26 | } 27 | spinner.succeed('MongoDB connection established. Press any key to continue. \n').stop(); 28 | this.connection = client; 29 | this.database = this.connection.db(this.options.mongodatabase); 30 | resolve(client); 31 | }, 32 | ); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/configs/mysqlconf.ts: -------------------------------------------------------------------------------- 1 | import { Connection, createConnection, escape } from 'mysql'; 2 | import * as ora from 'ora'; 3 | 4 | /** 5 | * Database class to handle database queries 6 | * 7 | * @class Database 8 | */ 9 | export class Database { 10 | /** 11 | * Database connection object 12 | * 13 | * @private 14 | * @type {Pool} 15 | * @memberof Database 16 | */ 17 | private conn: Connection; 18 | 19 | constructor(conf: string) { 20 | this.conn = createConnection(conf); 21 | const spinner = ora('Establishing MySQL connection ').start(); 22 | this.conn.connect((err) => { 23 | if (err) { 24 | spinner.fail(`Connection error ,${err.message}`); 25 | process.exit(); 26 | } 27 | spinner.succeed('MySQL connection established. Press tab key to continue. \n').stop(); 28 | }); 29 | } 30 | 31 | /** 32 | * Execute passed sql into database 33 | * 34 | * @param {string} sql - sql query to execute 35 | * @param {(Array | any)} [params] - data to insert if any 36 | * @returns {Promise} 37 | * @memberof Database 38 | */ 39 | public query(sql: string, params?: Array | any): Promise { 40 | return new Promise((resolve, reject) => { 41 | typeof params === 'undefined' 42 | ? this.conn.query(sql, (err, results) => (err ? reject(err) : resolve(results))) 43 | : this.conn.query(sql, params, (err, results) => (err ? reject(err) : resolve(results))); 44 | }); 45 | } 46 | 47 | /** 48 | * Escape passed value 49 | * 50 | * @param {string} param 51 | * @returns {string} 52 | * @memberof Database 53 | */ 54 | public escape(param: string): string { 55 | return escape(param); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import * as prompts from 'prompts'; 3 | import { Database, mysqlConfig } from './configs'; 4 | import { MongoConnection } from './configs/mongoconf'; 5 | import { Migrate } from './lib/migrate'; 6 | 7 | const mysqlPrompts = [ 8 | { 9 | type: 'text', 10 | name: 'mysqlhost', 11 | message: 'MySQL database host address?', 12 | initial: '127.0.0.1', 13 | }, 14 | { 15 | type: 'text', 16 | name: 'mysqlusername', 17 | message: 'MySQL database authentication username?', 18 | initial: 'root', 19 | }, 20 | { 21 | type: 'password', 22 | name: 'mysqlpassword', 23 | message: 'MySQL database authentication password?', 24 | }, 25 | { 26 | type: 'text', 27 | name: 'mysqldatabase', 28 | message: 'MySQL database name?', 29 | }, 30 | ]; 31 | 32 | const mongoPrompts = [ 33 | { 34 | type: 'text', 35 | name: 'mongohost', 36 | message: 'MongoDB database host address?', 37 | initial: '127.0.0.1', 38 | }, 39 | { 40 | type: 'text', 41 | name: 'mongousername', 42 | message: 'MongoDB authentication username?', 43 | }, 44 | { 45 | type: 'password', 46 | name: 'mongopassword', 47 | message: 'MongoDB authentication password?', 48 | }, 49 | { 50 | type: 'text', 51 | name: 'mongodatabase', 52 | message: 'MongoDB database name?', 53 | }, 54 | ]; 55 | 56 | (async () => { 57 | // @ts-ignore 58 | const mongoConn = new MongoConnection(await prompts(mongoPrompts)); 59 | await mongoConn.connect().catch(e => process.exit()); 60 | // @ts-ignore 61 | const mysqlConn = new Database(mysqlConfig(await prompts(mysqlPrompts))); 62 | 63 | const migrate = new Migrate({ mysqlconn: mysqlConn, mongodb: mongoConn.database }); 64 | await migrate.retrieveModels(); 65 | await migrate.retrieveMysqlData(); 66 | // @ts-ignore 67 | // const schema = await prompts(schemaPrompts); 68 | 69 | // if (schema.generateschemas === 'y' || schema.generateschemas === 'yes') { 70 | await migrate.generateMongoSchemas(); 71 | // } 72 | 73 | await migrate.populateMongo().catch(e => process.exit()); 74 | })(); 75 | -------------------------------------------------------------------------------- /src/lib/datatypes.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | nvarchar: 'String', 3 | int: 'Number', 4 | mediumint: 'Number', 5 | bigint: 'String', // save bigints as strings to maintain fidelity 6 | decimal: 'Number', 7 | year: 'Number', 8 | json: 'Array', 9 | text: 'String', 10 | tinyint: 'Number', 11 | tinyblob: 'String', 12 | mediumtext: 'String', 13 | mediumblob: 'String', 14 | longblob: 'String', 15 | varchar: 'String', 16 | timestamp: 'Date', 17 | datetime: 'Date', 18 | time: 'Date', 19 | enum: 'Enum', 20 | date: 'Date', 21 | double: 'Number', 22 | longtext: 'String', 23 | binary: 'String', 24 | float: 'Number', 25 | varbinary: 'String', 26 | char: 'String', 27 | blob: 'String', // MongoDB limits blobs to below 16MB in size, so just be careful 28 | set: 'Array', 29 | }; 30 | -------------------------------------------------------------------------------- /src/lib/migrate.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as mongo from 'mongodb'; 3 | import * as ora from 'ora'; 4 | import * as path from 'path'; 5 | import { Database } from '../configs'; 6 | import datatypes from './datatypes'; 7 | 8 | /** 9 | * Database migration utility. WIll migrate data from MySQL to MongoDb, 10 | * MySQL this.mysqldb name will be retained. All MySQL table names will be mapped to MongoDb collections, 11 | * MySQL model relationships will not be reinforced since MongoDB does not support schema relationships 12 | * 13 | * @export 14 | * @class Migrate 15 | */ 16 | export class Migrate { 17 | /** 18 | * Hold name of the models to be generated 19 | * 20 | * @private 21 | * @type {(string | any[])} 22 | * @memberof Migrate 23 | */ 24 | private models: string | any[]; 25 | 26 | /** 27 | * Directory where data is saved in json format. File names correspond to MySQL table names 28 | * 29 | * @private 30 | * @type {string} 31 | * @memberof Migrate 32 | */ 33 | private datafilesdir: string; 34 | 35 | /** 36 | * Directory where generated models will be stored 37 | * 38 | * @private 39 | * @type {string} 40 | * @memberof Migrate 41 | */ 42 | private modelsdirectory: string; 43 | 44 | /** 45 | * Store collection model names and their corresonding data files 46 | * 47 | * @private 48 | * @type {Map} 49 | * @memberof Migrate 50 | */ 51 | private modelschemas: Map; 52 | 53 | private mysqldb: Database; 54 | 55 | private mongodb: mongo.Db; 56 | 57 | constructor(options: { mysqlconn: Database; mongodb: mongo.Db }) { 58 | this.datafilesdir = path.join(process.cwd(), `/generated-json-data-files/`); 59 | this.modelsdirectory = path.join(process.cwd(), `/generated-schema-model-definitions/`); 60 | this.modelschemas = new Map(); 61 | this.mysqldb = options.mysqlconn; 62 | this.mongodb = options.mongodb; 63 | } 64 | 65 | /** 66 | * Get table names from the selected / provided this.mysqldb. 67 | * 68 | * Will populate `this.models` property. 69 | * 70 | * @memberof Migrate 71 | */ 72 | public async retrieveModels(): Promise { 73 | const modelInfo = await this.mysqldb.query(`show full tables where Table_Type = 'BASE TABLE'`); 74 | this.models = modelInfo.map((res: { [x: string]: any }) => { 75 | return res[Object.keys(res)[0]]; 76 | }); 77 | } 78 | 79 | /** 80 | * Retrieve data for each model from MySQL, and generate corresponding data file in json. 81 | * 82 | * @memberof Migrate 83 | */ 84 | public async retrieveMysqlData(): Promise { 85 | if (this.models === undefined) { 86 | throw new Error(`Call retrieveModels to get MySQL models!`); 87 | } 88 | try { 89 | const files = fs.readdirSync(this.datafilesdir); 90 | if (files.length) { 91 | for await (const file of files) { 92 | fs.unlinkSync(this.datafilesdir + file); 93 | } 94 | } 95 | } catch { 96 | fs.mkdirSync(this.datafilesdir); 97 | } 98 | 99 | for await (const model of this.models) { 100 | const modelData = await this.mysqldb.query(`select * from ${model}`); 101 | fs.writeFileSync(`${this.datafilesdir + model}.json`, JSON.stringify(modelData)); 102 | } 103 | console.log(`Found ${this.models.length} models and wrote into json files in ${Math.floor(process.uptime())} s and `); 104 | } 105 | 106 | /** 107 | * Generate MongoDB Schemas with corresponding data types as from MySQL. These schemas will used to populate data into MongoDB. 108 | * 109 | * Can be used later for another project, or deleted if not needed elsewhere anyways. Most common use case will be when taking over 110 | * a Node.js project using TypeScript. 111 | * 112 | * @memberof Migrate 113 | */ 114 | public async generateMongoSchemas(): Promise { 115 | const schemafiles: string[] = fs.readdirSync(this.datafilesdir); 116 | if (!schemafiles.length) { 117 | throw new Error('Empty directory!'); 118 | } 119 | 120 | try { 121 | // delete previously generated models if any 122 | const models = fs.readdirSync(this.modelsdirectory); 123 | models.forEach(model => { 124 | fs.unlinkSync(this.modelsdirectory + model); 125 | }); 126 | // tslint:disable-next-line:no-empty 127 | } catch {} 128 | 129 | for await (const schemafile of schemafiles) { 130 | let modelname: string = schemafile.split('.')[0]; 131 | const definition: any[] = await this.mysqldb.query(`describe ${modelname}`); 132 | if (modelname.indexOf('_') !== -1) { 133 | modelname = modelname.split('_').join(''); 134 | } 135 | modelname = modelname.slice(0, 1).toUpperCase() + modelname.slice(1); 136 | // add key value pairs to modelschemas, to map data-files to their corresponding mongo-model files 137 | this.modelschemas.set(schemafile, modelname); 138 | try { 139 | fs.mkdirSync(this.modelsdirectory); 140 | } catch { 141 | // do nothing if `models` directory exists 142 | } finally { 143 | const model = fs.createWriteStream(`${this.modelsdirectory + modelname}.ts`); 144 | model.write(`import { Schema, model } from 'mongoose';\n\n`); 145 | 146 | let modeldefinition: string = ''; 147 | 148 | for await (const field of definition) { 149 | const datatype = field.Type.indexOf('(') !== -1 ? field.Type.split('(')[0] : field.Type; 150 | modeldefinition += `${field.Field}: { 151 | type: ${datatypes[datatype]}, 152 | required: ${field.Null === 'YES' ? false : true}, 153 | default: ${field.Default === 'CURRENT_TIMESTAMP' ? 'Date.now' : field.Default}, 154 | },\n`; 155 | } 156 | 157 | model.write(`const ${modelname} = new Schema({${modeldefinition}});`); 158 | model.write(`\n\n\n\nexport default model('${modelname}', ${modelname});\n`); 159 | } 160 | } 161 | } 162 | 163 | /** 164 | * Write / populate retrieved data into MongoDB, using previously generated Schemas and json data files. 165 | * 166 | * @returns {Promise} 167 | * @memberof Migrate 168 | */ 169 | public async populateMongo(): Promise { 170 | if (this.modelschemas.size) { 171 | let counter = 0; 172 | const spinner = ora('Started data migration').start(); 173 | spinner.color = 'blue'; 174 | for await (const datafile of this.modelschemas) { 175 | const modeldata = fs.readFileSync(this.datafilesdir + datafile[0], 'utf-8'); 176 | const data = Array.from(JSON.parse(modeldata)); 177 | const collectionName = datafile[1].toLowerCase(); 178 | 179 | if (data.length) { 180 | const collection = this.mongodb.collection(collectionName); 181 | await collection.insertMany(data, { ordered: true }); 182 | spinner.succeed('Inserted ' + data.length + ' documents into the ' + collectionName + ' collection.'); 183 | } 184 | counter += 1; 185 | } 186 | 187 | if (counter === this.modelschemas.size) { 188 | console.log('\n'); 189 | spinner.succeed('Complete! Dumped into MongoDB. Empty MySQL schemas were ignored.'); 190 | try { 191 | const files = fs.readdirSync(this.datafilesdir); 192 | if (files.length) { 193 | for await (const file of files) { 194 | fs.unlinkSync(this.datafilesdir + file); 195 | } 196 | fs.rmdirSync(this.datafilesdir); 197 | } 198 | } catch (e) { 199 | // 200 | } 201 | process.exit(); 202 | } 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "es2018", 5 | "lib": ["es2018", "es2015", "es2017"], 6 | "module": "commonjs", 7 | "outDir": "./", 8 | "rootDir": "./src", 9 | "removeComments": false, 10 | "downlevelIteration": true, 11 | "strict": true, 12 | "noImplicitAny": false, 13 | "strictNullChecks": false, 14 | "noImplicitThis": false, 15 | "alwaysStrict": true, 16 | "noUnusedParameters": false, 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | "moduleResolution": "node", 20 | "experimentalDecorators": true 21 | }, 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "warning", 3 | "extends": ["tslint:recommended"], 4 | "linterOptions": { 5 | "exclude": ["node_modules/**"] 6 | }, 7 | "rules": { 8 | "quotemark": [true, "single"], 9 | "interface-name": false, 10 | "ordered-imports": false, 11 | "object-literal-sort-keys": false, 12 | "no-consecutive-blank-lines": false, 13 | "no-console": false, 14 | "radix": false, 15 | "max-line-length": false, 16 | "no-var-requires": false, 17 | "semicolon": true 18 | } 19 | } 20 | --------------------------------------------------------------------------------