All files / src index.ts

100% Statements 26/26
100% Branches 4/4
100% Functions 8/8
100% Lines 23/23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87        1x 1x   1x 1x 1x   1x 1x           258x 257x             62x             17x             7x             7x                       5x 5x   5x 5x 5x   5x           52x           52x             1x 1x
import { Database as sqliteDatabase } from "sqlite3";
import { DatabaseEngine } from "./database-engine";
import * as pg from "pg";
import * as mysql from "mysql2/promise";
import Sqlite3Engine from "./engines/sqlite3-engine";
import PostgresEngine from "./engines/postgres-engine";
import BaseModel, { DatabaseType, Wrapped } from "./base-model";
import { getTableName } from "./util";
import QueryBuilder from "./query/builder";
import MySQLEngine from "./engines/mysql-engine";
 
export class BasieStatic {
    private engine: DatabaseEngine | null = null;
 
    /**
     * Returns the engine currently in use, or throws if there is no engine configured.
     */
    public getEngine(): DatabaseEngine {
        if (!this.engine) throw new Error("No database engine has been configured. Ensure that you use Basie.use(engine) before attempting any queries.");
        return this.engine;
    }
 
    /**
     * Changes the current database engine to the specified engine.
     */
    public use(engine: DatabaseEngine) {
        this.engine = engine;
    }
 
    /**
     * Configures basie to be used with the specified sqlite database.
     */
    public sqlite(db: sqliteDatabase) {
        this.use(new Sqlite3Engine(db));
    }
 
    /**
     * Configures basie to be used with the specified postgres connection pool.
     */
    public postgres(db: pg.Pool) {
        this.use(new PostgresEngine(db));
    }
 
    /**
     * Configures basie to be used with the specified mysql connection.
     */
    public mysql(connection: mysql.Connection) {
        this.use(new MySQLEngine(connection));
    }
 
    /**
     * Wraps the specified model with basie-specific methods that give it static
     * querying methods. This does not create a table within the database, and
     * instead expects the table to already be present. This function is called
     * a bit weirdly (`Basie.wrap<_Model>()(_Model)`) to overcome some typescript
     * type system limits and statically typecheck that you're only using valid
     * members.
     */
    public wrap<InstanceType extends BaseModel, Fields extends string = keyof InstanceType>() {
        return <ConstructorFN extends { new(...args: any[]): InstanceType2 }, InstanceType2 extends Record<Fields, DatabaseType | Function>>(arg: ConstructorFN, tableName?: string) => {
            if (!tableName) tableName = getTableName(arg.name);
 
            const local = <Wrapped<ConstructorFN, InstanceType2>>arg;
            (<any>local).tableName = tableName;
            (<any>local).prototype.tableName = tableName;
 
            return <Wrapped<ConstructorFN, InstanceType>>new Proxy(local, {
                get(target: any, name) {
                    // If the property exists on the object itself (static method), return that.
                    /* istanbul ignore next This incorrectly reports as uncovered, even though it runs. */
                    if (typeof target[name] !== "undefined") return target[name];
 
                    const builder = <any>QueryBuilder.model(local);
                    // If it is not a function, act like it doesn't exist (which is probably the thruth).
                    /* istanbul ignore next This incorrectly reports as uncovered, even though it runs. */
                    if (typeof builder[name] !== "function") return undefined;
 
                    // Return that method of the QueryBuilder and bind it to the builder.
                    return builder[name].bind(builder);
                }
            });
        };
    }
}
 
export default new BasieStatic();
export { default as BaseModel, R, A } from "./base-model";