daemonraco/dfdb

View on GitHub
src/includes/manager.dfdb.ts

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @file manager.dfdb.ts
 * @author Alejandro D. Simi
 */

import { Promise } from 'es6-promise';
import * as fs from 'fs';
import * as path from 'path';

import { BasicConstants } from './constants.dfdb';
import { Connection, ConnectionDBValidationResult } from './connection/connection.dfdb';
import { Rejection } from './rejection.dfdb';
import { RejectionCodes } from './rejection-codes.dfdb';

/**
 * Central manager for all connection.
 *
 * @class DocsOnFileDB
 */
export class DocsOnFileDB {
    //
    // Class private properties.
    private static _instance: DocsOnFileDB;
    //
    // Protected properties.
    protected _connections: { [name: string]: Connection } = {};
    //
    // Constructor.
    /**
     * @constructor
     */
    protected constructor() {
    }
    //
    // Public methods.
    /**
     * Provides access to a database connection. In case the requested database
     * is already connected, it returns the same connection.
     *
     * @method connect
     * @param {string} dbname Name of the database to connect.
     * @param {string} dbpath Directory where the requested database is stored.
     * @param {any} options List of extra options to use when connecting.
     * @returns {Promise<Connection>} Returns a connection as a promise.
     */
    public connect(dbname: string, dbpath: string, options: any = null): Promise<Connection> {
        //
        // Checking and fixing options.
        if (options === null || typeof options !== 'object' || Array.isArray(options)) {
            options = {};
        }
        //
        // Building promise to return.
        return new Promise<Connection>((resolve: (conn: Connection) => void, reject: (err: Rejection) => void) => {
            //
            // Getting a key to identify the requested connection.
            const key = DocsOnFileDB.BuildKey(dbpath, dbname);
            //
            // Is it a known connection?
            if (typeof this._connections[key] === 'undefined') {
                //
                // Creating a proper connection object.
                this._connections[key] = new Connection(dbname, dbpath, options);
                //
                // Starting connection.
                this._connections[key].connect()
                    .then(() => {
                        resolve(this._connections[key]);
                    })
                    .catch(reject);
            } else {
                //
                // Resolving with a previously loaded connection.
                resolve(this._connections[key]);
            }
        });
    }
    /**
     * Provides a way to dispose of an existing database
     *
     * @method dropDatabase
     * @param {string} dbname Name of the database to delete.
     * @param {string} dbpath Directory where the requested database is stored.
     * @returns {Promise<void>} Returns a promise to indicate when the operation
     * finishes.
     */
    public dropDatabase(dbname: string, dbpath: string): Promise<void> {
        //
        // Building promise to return.
        return new Promise<void>((resolve: () => void, reject: (err: Rejection) => void) => {
            let validation: any = null;
            let errors: string = null;
            //
            // Getting a key to identify the requested connection.
            const key = DocsOnFileDB.BuildKey(dbpath, dbname);
            //
            // Guessing the full path of the requested database.
            const dbFullPath = DocsOnFileDB.GuessDatabasePath(dbname, dbpath);
            //
            // Checking if given parameters point to a valid and existing
            // database.
            Connection.IsValidDatabase(dbname, dbpath)
                .then((results: ConnectionDBValidationResult) => {
                    //
                    // Should it be removed?
                    if (results.exists && results.valid) {
                        //
                        // Cleaning known connections if any.
                        if (typeof this._connections[key] !== 'undefined') {
                            delete this._connections[key];
                        }
                        //
                        // Removing file.
                        fs.unlinkSync(dbFullPath);
                        //
                        // Resolving promise.
                        resolve();
                    } else {
                        reject(new Rejection(results.errorCode, results));
                    }
                })
                .catch(reject);
        });
    }
    /**
     * Ask this manager to forget a tracked connection.
     *
     * @method forgetConnection
     * @param {string} dbname Name of the database.
     * @param {string} dbpath Directory where the requested database is stored.
     * @returns {boolean} Returns TRUE when it was forgotten.
     */
    public forgetConnection(dbname: string, dbpath: string): boolean {
        //
        // Default values.
        let forgotten = false;
        //
        // Getting a key to identify the requested connection.
        const key = DocsOnFileDB.BuildKey(dbpath, dbname);
        //
        // Is it known?
        if (typeof this._connections[key] !== 'undefined') {
            //
            // Is it disconnected?
            if (!this._connections[key].connected()) {
                //
                // Forguetting.
                delete this._connections[key];
                forgotten = true;
            }
        } else {
            //
            // If it's not known, it's considered as forgotten.
            forgotten = true;
        }

        return forgotten;
    }
    /**
     * This methods provides a proper value for string auto-castings.
     *
     * @method toString
     * @returns {string} Returns a simple string identifying this manager.
     */
    public toString = (): string => {
        return `DocsOnFileDB[manager]`;
    }
    //
    // Public class methods.
    /**
     * This class method provides access to this manager's single instance.
     *
     * @static
     * @method Instance
     * @returns {DocsOnFileDB} Singleton's instance.
     */
    public static Instance(): DocsOnFileDB {
        //
        // Is this the first invocation?
        if (!this._instance) {
            //
            // Creating the sole instance.
            this._instance = new DocsOnFileDB();
        }

        return this._instance;
    }
    //
    // Protected class methods.
    /**
     * Takes basic identifiers of a database and builds a key for indexation.
     *
     * @static
     * @method BuildKey
     * @param {string} dbname Name of the database.
     * @param {string} dbpath Directory where the requested database is stored.
     * @returns {string}
     */
    protected static BuildKey(dbname: string, dbpath: string): string {
        return `${dbpath}[${dbname}]`;
    }
    /**
     * Takes basic identifiers of a database and guesses its full path.
     *
     * @static
     * @method GuessDatabasePath
     * @param {string} dbname Name of the database.
     * @param {string} dbpath Directory where the requested database is stored.
     * @returns {string}
     */
    public static GuessDatabasePath(dbname: string, dbpath: string): string {
        return path.join(dbpath, `${dbname}${BasicConstants.DBExtension}`);
    }
}