diff --git a/README.md b/README.md index 2e565f1..e88d6ee 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ It's great for: There are many tools for MongoDB data import out there, including the official one - `mongoimport`. Why should you choose Mongo Seeding? ### Problem #1: JSON used for import data definition + Every tool I found before creating Mongo Seeding support only JSON files. In my opinion, that is not the most convenient way of data definition. The biggest problems are data redundancy and lack of ability to write logic. Imagine that you want to import 10 very similar documents into `authors` collection. Every document is identical - except the name: @@ -195,6 +196,7 @@ The Mongo Seeding CLI and Mongo Seeding Docker Image have TypeScript runtime bui You can use Mongo Seeding library in your projects with TypeScript runtime and enable importing TS files as well. ### Problem #3: No ultimate solution + Tools like this should be as flexible as possible. Some developers need just CLI tool, and some want to import data programmatically. Before writing Mongo Seeding, I needed a ready-to-use Docker image and found none. Dockerizing an application is easy, but it takes time. That's why Mongo Seeding consists of: diff --git a/cli/README.md b/cli/README.md index cb825e7..13b9f57 100644 --- a/cli/README.md +++ b/cli/README.md @@ -4,7 +4,9 @@ [![npm version](https://badge.fury.io/js/mongo-seeding-cli.svg)](https://npmjs.org/package/mongo-seeding-cli) [![David](https://img.shields.io/david/pkosiec/mongo-seeding.svg?path=cli)]() [![David](https://img.shields.io/david/dev/pkosiec/mongo-seeding.svg?path=cli)]() -The ultimate solution for populating your MongoDB database. Define the data in JSON or JavaScript. Import collections and documents using command line interface! +The ultimate CLI tool for populating your MongoDB database :rocket: + +Define MongoDB documents in JSON, JavaScript or even TypeScript file(s). Import them with command line interface. ## Installation @@ -24,29 +26,56 @@ In order to seed your database with data from current directory using default co seed ``` -You can specify custom settings with parameters. The following example imports data from `./example/data` directory using MongoDB connection URI `mongodb://127.0.0.1:27017/mydb`. +You can specify custom settings with command line parameters. The following example imports data from `./example/data` directory using MongoDB connection URI `mongodb://127.0.0.1:27017/mydb`: ```bash seed -u 'mongodb://127.0.0.1:27017/mydb' -d ./example/data ``` -Full configuration options are described in [Command line parameters](#command-line-parameters) section. +You can also use environmental variables to configure the CLI. For example: + +```bash +DB_URI='mongodb://127.0.0.1:27017/mydb' seed -d ./example/data +``` + +Full configuration options are described in [Configuration](#configuration) section. + +## Configuration +You can configure data import with command line parameters or environmental variables. + +> **Note:** Command line parameters have always a higher priority over environmental variables. ## Command line parameters -You can use the following parameters while using `seed` binary: +You can use the following parameters while using `seed` tool: | Name | Default Value | Description | |-------------|----------------|---------------------| -| `--data $PATH` or `-d $PATH` | current directory | Path to directory containing import data | -| `--db-uri $URI` or `-u $URI` | *`undefined`* | If defined, the URI will be used for establishing connection to database, ignoring values defined via other `db-*` parameters (e.g. `db-name`, `db-host`, etc.) -| `--db-protocol $DB_PROTOCOL` | `mongodb` | MongoDB database protocol | -| `--db-host $DB_HOST` | `127.0.0.1` | MongoDB database host | -| `--db-port $DB_PORT` | `27017` | MongoDB database port | -| `--db-name $DB_NAME` | `database` | Name of the database | -| `--db-username $DB_USERNAME` | database | Username for connecting with database that requires authentication | -| `--db-password $DB_PASSWORD` | database | Password for connecting with database that requires authentication | +| `--data {PATH}` or `-d {PATH}` | current directory | Path to directory containing import data | +| `--db-uri {URI}` or `-u {URI}` | *`undefined`* | If defined, the URI will be used for establishing connection to database, ignoring values defined via other `db-*` parameters (e.g. `db-name`, `db-host`, etc.) +| `--db-protocol {DB_PROTOCOL}` | `mongodb` | MongoDB database protocol | +| `--db-host {DB_HOST}` | `127.0.0.1` | MongoDB database host | +| `--db-port {DB_PORT}` | `27017` | MongoDB database port | +| `--db-name {DB_NAME}` | `database` | Name of the database | +| `--db-username {DB_USERNAME}` | *`undefined`* | Username for connecting with database that requires authentication | +| `--db-password {DB_PASSWORD}` | *`undefined`* | Password for connecting with database that requires authentication | | `--drop-database` | `false` | Dropping entire database before data import | | `--drop-collection` | `false` | Dropping every collection that is being imported | | `--replace-id` | `false` | Replacing `id` property with `_id` for every document during data import | | `--reconnect-timeout` | `10` (seconds) | Maximum time of waiting for successful MongoDB connection| | `--help` or `-h` | n/a | Help + +## Environmental variables +You can use the following environmental variables while using `seed` tool: + +| Name | Default Value | Description | +|-------------|----------------|---------------------| +| DB_URI | *`undefined`* | If defined, the URI is used for establishing connection to database, ignoring values given in `DB_*` environmental variables (e.g. `DB_HOST`, `DB_PORT`, etc.). +| DB_HOST | `127.0.0.1` | MongoDB database host | +| DB_PORT | `27017` | MongoDB database port | +| DB_NAME | `database` | Name of the database | +| DB_USERNAME | *`undefined`* | Username for connecting with database that requires authentication | +| DB_PASSWORD | *`undefined`* | Password for connecting with database that requires authentication | +| DROP_DATABASE | `false` | Dropping entire database before data import | +| DROP_COLLECTION | `false` | Dropping every collection that is being imported | +| REPLACE_ID | `false` | Replacing `id` property with `_id` for every document during import; useful for ORMs | +| RECONNECT_TIMEOUT | `10` | Maximum time, in which app should keep trying connecting to database | diff --git a/cli/package-lock.json b/cli/package-lock.json index 945dac6..d0416c6 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -23,6 +23,12 @@ "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" }, + "@types/extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/extend/-/extend-3.0.0.tgz", + "integrity": "sha512-Eo8NQCbgjlMPQarlFAE3vpyCvFda4dg1Ob5ZJb6BJI9x4NAZVWowyMNB8GJJDgDI4lr2oqiQvXlPB0Fn1NoXnQ==", + "dev": true + }, "@types/mongodb": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.1.7.tgz", diff --git a/cli/package.json b/cli/package.json index 59807ea..55a2757 100755 --- a/cli/package.json +++ b/cli/package.json @@ -59,11 +59,13 @@ "@types/node": "^10.9.0", "command-line-args": "^5.0.0", "command-line-usage": "^5.0.0", + "extend": "^3.0.2", "mongo-seeding": "^2.2.0", "ts-node": "^7.0.1", "typescript": "^3.0.0" }, "devDependencies": { - "@types/command-line-args": "^5.0.0" + "@types/command-line-args": "^5.0.0", + "@types/extend": "^3.0.0" } } diff --git a/cli/src/index.ts b/cli/src/index.ts index 5891245..70b41ce 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -1,30 +1,35 @@ // Enable debug output for Mongo Seeding process.env.DEBUG = 'mongo-seeding'; +import * as commandLineArgs from 'command-line-args'; +import * as extend from 'extend'; import { seedDatabase } from 'mongo-seeding'; import { - populateOptions, + populateCommandLineOptions, optionsDefinition, shouldShowHelp, CommandLineOptions, validateOptions, + populateEnvOptions, } from './options'; import { showHelp } from './help'; - -import * as commandLineArgs from "command-line-args"; +import { AppConfig, DeepPartial } from 'mongo-seeding/dist/common'; export const run = async () => { - const options: CommandLineOptions = commandLineArgs(optionsDefinition) as CommandLineOptions; + const options: CommandLineOptions = commandLineArgs( + optionsDefinition, + ) as CommandLineOptions; if (shouldShowHelp(options)) { showHelp(); return; } - const partialConfig = populateOptions(options); + const config = getConfig(options); + try { validateOptions(options); - await seedDatabase(partialConfig); + await seedDatabase(config); } catch (err) { printError(err); } @@ -32,6 +37,13 @@ export const run = async () => { process.exit(0); }; +const getConfig = (options: CommandLineOptions): DeepPartial => { + const commandLineConfig = populateCommandLineOptions(options); + const envConfig = populateEnvOptions(); + const config = {}; + return extend(true, config, envConfig, commandLineConfig); +}; + const printError = (err: Error) => { console.error(`Error ${err.name}: ${err.message}`); }; diff --git a/cli/src/options.ts b/cli/src/options.ts index 8726c9f..b49d0ee 100644 --- a/cli/src/options.ts +++ b/cli/src/options.ts @@ -120,7 +120,7 @@ const validatePositiveNumber = (variable: number | undefined, name: string) => { } }; -export const populateOptions = ( +export const populateCommandLineOptions = ( options: CommandLineOptions, ): DeepPartial => ({ database: { @@ -137,5 +137,28 @@ export const populateOptions = ( dropCollection: options['drop-collection'], replaceIdWithUnderscoreId: options['replace-id'], reconnectTimeoutInSeconds: options['reconnect-timeout'], - supportedExtensions: ["js", "json", "ts"] }); + +export const populateEnvOptions = (): DeepPartial => { + const env = process.env; + const envOptions: DeepPartial = { + database: { + protocol: env.DB_PROTOCOL ? String(env.DB_PROTOCOL) : undefined, + host: env.DB_HOST ? String(env.DB_HOST) : undefined, + port: env.DB_PORT ? Number(env.DB_PORT) : undefined, + name: env.DB_NAME ? String(env.DB_NAME) : undefined, + username: env.DB_USERNAME ? String(env.DB_USERNAME) : undefined, + password: env.DB_PASSWORD ? String(env.DB_PASSWORD) : undefined, + }, + databaseConnectionUri: env.DB_URI ? String(env.DB_URI) : undefined, + dropDatabase: env.DROP_DATABASE === 'true', + dropCollection: env.DROP_COLLECTION === 'true', + replaceIdWithUnderscoreId: env.REPLACE_ID === 'true', + supportedExtensions: ['ts', 'js', 'json'], + reconnectTimeoutInSeconds: env.RECONNECT_TIMEOUT + ? Number(env.RECONNECT_TIMEOUT) + : undefined, + }; + + return envOptions; +};