UNPKG

@riao/dbal

Version:
319 lines 10.8 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Database = void 0; const fs_1 = require("fs"); const path_1 = require("path"); const config_1 = require("../config"); const get_database_path_1 = require("./get-database-path"); const ddl_1 = require("../ddl"); const dml_1 = require("../dml"); const schema_query_repository_1 = require("../schema/schema-query-repository"); /** * Represents a single database instance, including a driver, * configuration, connection, etc. */ class Database { constructor() { /** * Reconstructors will be used to re-initialize repositories * after the database has been initialized. * * This allows repositories to be created in global scope * before the database is init()'d */ this.queryRepoInitQueue = []; this.ddlRepoInitQueue = []; this.schemaRepoInitQueue = []; this.isLoaded = false; /** * Migrations directory, relative to this database * e.g. If the migrations are in `database/main/migrations`, * set this to `migrations` */ this.migrations = 'migrations'; /** * Seeds directory, relative to this database * e.g. If the seeds are in `database/main/seeds`, * set this to `seeds` */ this.seeds = 'seeds'; /** * Schema storage directory, relative to this database * e.g. If the schema is in `database/main/.schema`, * set this to `.schema` */ this.schemaDirectory = '.schema'; /** * Query builder class type used to create new query builders */ this.queryBuilderType = dml_1.DatabaseQueryBuilder; /** * Query repository class type used to create new repos */ this.queryRepositoryType = dml_1.QueryRepository; /** * DDL builder class type used to create new builders */ this.ddlBuilderType = ddl_1.DataDefinitionBuilder; /** * DDL repository class type used to create new repos */ this.ddlRepositoryType = ddl_1.DataDefinitionRepository; /** * Schema Query repository class type used to create new repos */ this.schemaQueryRepositoryType = schema_query_repository_1.SchemaQueryRepository; } /** * Initialize the database * * @param options Database options */ init(options) { return __awaiter(this, void 0, void 0, function* () { options = options !== null && options !== void 0 ? options : {}; if (!this.name) { throw new Error('Cannot load database without a name'); } if (!this.databasePath) { this.databasePath = (0, get_database_path_1.getDatabasePath)(); } if (!this.driver) { this.driver = new this.driverType(); } if (options.connectionOptions) { this.env = options.connectionOptions; } else { this.configureFromEnv(); } yield this.connect(); this.isLoaded = true; // Load schema query repos this.schemaQuery = this.getSchemaQueryRepository(); for (const repo of this.schemaRepoInitQueue) { repo.init({ database: this.env.database, driver: this.driver, }); } yield this.loadSchema(); // Load DDL repositories this.ddl = this.getDataDefinitionRepository(); for (const repo of this.ddlRepoInitQueue) { repo.init({ driver: this.driver, }); } // Load query repositories this.query = this.getQueryRepository(); for (const repo of this.queryRepoInitQueue) { repo.init({ driver: this.driver, schema: this.schema, }); } }); } /** * Load the configuration .env */ configureFromEnv() { this.env = (0, config_1.configureDb)(this.envType, this.databasePath, this.name); } /** * Connect to the database */ connect() { return __awaiter(this, void 0, void 0, function* () { if (!this.env) { throw new Error(`Cannot connect() database "${this.name}" before init()`); } yield this.driver.connect(this.env); }); } /** * Disconnect from the database */ disconnect() { return __awaiter(this, void 0, void 0, function* () { yield this.driver.disconnect(); }); } /** * Get the full relative path to this database's migrations folder * * @returns Returns the relative file path */ getMigrationsDirectory() { return (0, path_1.join)(this.databasePath, this.name, this.migrations); } /** * Get the full relative path to this database's seeds folder * * @returns Returns the relative file path */ getSeedsDirectory() { return (0, path_1.join)(this.databasePath, this.name, this.seeds); } /** * Get the full relative path to this database's schema folder * * @returns Returns the relative file path */ getSchemaDirectory() { return (0, path_1.join)(this.databasePath, this.name, this.schemaDirectory); } /** * Get a new DDL builder * * @returns DDL builder */ getDataDefinitionBuilder() { return new this.ddlBuilderType(); } /** * Get a new DDL repository * * @param options Repository options * @returns Returns the DDL repository */ getDataDefinitionRepository() { const repo = new this.ddlRepositoryType({ ddlBuilderType: this.ddlBuilderType, }); if (this.isLoaded) { repo.init({ driver: this.driver }); } else { this.ddlRepoInitQueue.push(repo); } return repo; } /** * Get a new query builder * * @returns Query builder */ getQueryBuilder() { return new this.queryBuilderType(); } /** * Get a new query repository * * @param options Repository options * @returns Returns the query repository */ getQueryRepository(options) { const repo = new this.queryRepositoryType(Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { queryBuilderType: this.queryBuilderType })); if (this.isLoaded) { repo.init({ driver: this.driver, schema: this.schema, }); } else { this.queryRepoInitQueue.push(repo); } return repo; } /** * Get a new schema query repository * * @returns Schema Query Repository */ getSchemaQueryRepository() { const repo = new this.schemaQueryRepositoryType({ queryBuilderType: this.queryBuilderType, }); if (this.isLoaded) { repo.init({ database: this.env.database, driver: this.driver, }); } else { this.schemaRepoInitQueue.push(repo); } return repo; } /** * Build & save the database schema */ buildSchema() { return __awaiter(this, void 0, void 0, function* () { this.schema = yield this.schemaQuery.getSchema(); yield this.saveSchema(); }); } /** * Save the database schema */ saveSchema() { return __awaiter(this, void 0, void 0, function* () { (0, fs_1.mkdirSync)(this.getSchemaDirectory(), { recursive: true }); const filepath = (0, path_1.join)(this.getSchemaDirectory(), 'schema.json'); const data = JSON.stringify(this.schema); (0, fs_1.writeFileSync)(filepath, data); }); } /** * Load the database schema */ loadSchema() { return __awaiter(this, void 0, void 0, function* () { const filepath = (0, path_1.join)(this.getSchemaDirectory(), 'schema.json'); if ((0, fs_1.existsSync)(filepath)) { const data = (0, fs_1.readFileSync)(filepath).toString(); this.schema = JSON.parse(data); } else { yield this.buildSchema(); } }); } /** * Get schema metadata * * @returns Schema */ getSchema() { return __awaiter(this, void 0, void 0, function* () { if (!this.schema) { yield this.loadSchema(); } return this.schema; }); } /** * Run a transaction * * @param fn Transaction callback * @returns Passes the return from the transaction callback */ transaction(fn) { return __awaiter(this, void 0, void 0, function* () { const connectionDriver = new this.driverType(); const ddl = this.getDataDefinitionRepository(); ddl.init({ driver: connectionDriver }); const query = this.getQueryRepository(); query.init({ driver: connectionDriver, schema: this.schema }); return yield this.driver.transaction(fn, { driver: connectionDriver, ddl, query, }); }); } } exports.Database = Database; //# sourceMappingURL=database.js.map