src/lib/core/md-seed-runner.js
import { Subject } from 'rxjs';
import {
getObjectWithSelectedKeys,
normalizeSeederName,
} from '../utils/helpers';
import MdSeedRunnerError from './md-seed-runner-error';
/**
* mongoose-data-seed runner
*/
export default class MdSeedRunner {
/**
* MdSeedRunner operations constants
* @type {Object}
* @property {string} START MdSeedRunner starts.
* @property {string} SUCCESS MdSeedRunner succeed.
* @property {string} ERROR MdSeedRunner finished with an error.
*/
static operations = {
START: 'START',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
MONGOOSE_CONNECT_START: 'MONGOOSE_CONNECT_START',
MONGOOSE_CONNECT_SUCCESS: 'MONGOOSE_CONNECT_SUCCESS',
MONGOOSE_CONNECT_ERROR: 'MONGOOSE_CONNECT_ERROR',
MONGOOSE_DROP_START: 'MONGOOSE_DROP_START',
MONGOOSE_DROP_SUCCESS: 'MONGOOSE_DROP_SUCCESS',
MONGOOSE_DROP_ERROR: 'MONGOOSE_DROP_ERROR',
ALL_SEEDERS_START: 'ALL_SEEDERS_START',
ALL_SEEDERS_FINISH: 'ALL_SEEDERS_FINISH',
SEEDER_START: 'SEEDER_START',
SEEDER_SUCCESS: 'SEEDER_SUCCESS',
SEEDER_ERROR: 'SEEDER_ERROR',
};
/**
* Creates MdSeedRunner
* @param {Function<Promise>} connect Connect to mongodb implementation
* @param {Function<Promise>} dropdb Drop/Clear the database implementation
* @param {Map<string, Function>} seedersList key=Seeder name | value=Seeder implementation
*/
constructor({ connect, dropdb, seedersList }) {
this.connect = connect;
this.dropdb = dropdb;
this.seedersList = seedersList;
this._subject = new Subject();
}
run({ selectedSeeders = [], dropDatabase = false } = {}) {
this._run({ selectedSeeders, dropDatabase });
return this._subject.asObservable();
}
/*
Private methods
*/
async _run({ selectedSeeders, dropDatabase }) {
const { START, SUCCESS, ERROR } = MdSeedRunner.operations;
try {
this._subject.next({
type: START,
payload: { selectedSeeders, dropDatabase },
});
await this._connectToMongodb();
if (dropDatabase) {
await this._dropDatabase();
}
await this._runSeeders(selectedSeeders);
this._subject.next({
type: SUCCESS,
payload: { selectedSeeders, dropDatabase },
});
this._subject.complete();
} catch (error) {
const { type = ERROR, payload = { error } } = error;
this._subject.error({ type, payload });
}
}
async _connectToMongodb() {
const {
MONGOOSE_CONNECT_START,
MONGOOSE_CONNECT_SUCCESS,
MONGOOSE_CONNECT_ERROR,
} = MdSeedRunner.operations;
try {
this._subject.next({ type: MONGOOSE_CONNECT_START });
await this.connect();
this._subject.next({ type: MONGOOSE_CONNECT_SUCCESS });
} catch (error) {
throw new MdSeedRunnerError({ type: MONGOOSE_CONNECT_ERROR, error });
}
}
async _dropDatabase() {
const {
MONGOOSE_DROP_START,
MONGOOSE_DROP_SUCCESS,
MONGOOSE_DROP_ERROR,
} = MdSeedRunner.operations;
try {
this._subject.next({ type: MONGOOSE_DROP_START });
await this.dropdb();
this._subject.next({ type: MONGOOSE_DROP_SUCCESS });
} catch (error) {
throw new MdSeedRunnerError({ type: MONGOOSE_DROP_ERROR, error });
}
}
async _runSeeders(selectedSeeders) {
const { ALL_SEEDERS_START, ALL_SEEDERS_FINISH } = MdSeedRunner.operations;
const seeders = this._loadSelectedSeeders(selectedSeeders);
this._subject.next({
type: ALL_SEEDERS_START,
payload: { seeders: Object.keys(seeders) },
});
for (const [name, Seeder] of Object.entries(seeders)) {
await this._runSeeder({ name, Seeder });
}
this._subject.next({
type: ALL_SEEDERS_FINISH,
payload: { seeders: Object.keys(seeders) },
});
}
async _runSeeder({ Seeder, name }) {
const {
SEEDER_START,
SEEDER_SUCCESS,
SEEDER_ERROR,
} = MdSeedRunner.operations;
try {
this._subject.next({
type: SEEDER_START,
payload: { name },
});
const seeder = new Seeder();
const results = await seeder.seed();
this._subject.next({ type: SEEDER_SUCCESS, payload: { name, results } });
} catch (error) {
throw new MdSeedRunnerError({
type: SEEDER_ERROR,
payload: { name },
error,
});
}
}
_loadSelectedSeeders(selectedSeeders) {
if (selectedSeeders && selectedSeeders.length > 0) {
return getObjectWithSelectedKeys(
this.seedersList,
selectedSeeders.map(name => normalizeSeederName(name))
);
}
return this.seedersList;
}
}