UNPKG

ionic-orm-2

Version:

Data-mapper ORM for Ionic WebSQL and SQLite

300 lines (295 loc) 17.1 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Connection } from "./Connection"; import { ConnectionNotFoundError } from "./error/ConnectionNotFoundError"; import { MissingDriverError } from "./error/MissingDriverError"; import { AlreadyHasActiveConnectionError } from "./error/AlreadyHasActiveConnectionError"; import { Logger } from "../logger/Logger"; import { CannotDetermineConnectionOptionsError } from "./error/CannotDetermineConnectionOptionsError"; import { WebSqlDriver } from "../driver/websql/WebSqlDriver"; import { IonicSQLiteDriver } from "../driver/ionic-sqlite/IonicSQLiteDriver"; /** * ConnectionManager is used to store and manage all these different connections. * It also provides useful factory methods to simplify connection creation. */ export class ConnectionManager { constructor() { // ------------------------------------------------------------------------- // Protected Properties // ------------------------------------------------------------------------- /** * List of connections registered in this connection manager. */ this.connections = []; } // ------------------------------------------------------------------------- // Public Methods // ------------------------------------------------------------------------- /** * Checks if connection with the given name exist in the manager. */ has(name) { return !!this.connections.find(connection => connection.name === name); } /** * Gets registered connection with the given name. * If connection name is not given then it will get a default connection. * Throws exception if connection with the given name was not found. */ get(name = "default") { const connection = this.connections.find(connection => connection.name === name); if (!connection) throw new ConnectionNotFoundError(name); return connection; } /** * Creates a new connection based on the given connection options and registers it in the manager. * You need to manually call #connect method to establish connection. * Note that dropSchemaOnConnection and autoSchemaSync options of a ConnectionOptions will not work there - use * createAndConnect method to use them. */ create(options) { const logger = new Logger(options.logging || {}); const driver = this.createDriver(options.driver, logger); const connection = this.createConnection(options.name || "default", driver, logger); // import entity schemas if (options.entitySchemas) { const [directories, classes] = this.splitStringsAndClasses(options.entitySchemas); connection .importEntitySchemas(classes); // .importEntitySchemaFromDirectories(directories); } // import entities if (options.entities) { const [directories, classes] = this.splitStringsAndClasses(options.entities); connection .importEntities(classes); // .importEntitiesFromDirectories(directories); } // import subscriber if (options.subscribers) { const [directories, classes] = this.splitStringsAndClasses(options.subscribers); connection .importSubscribers(classes); // .importSubscribersFromDirectories(directories); } // import naming strategies if (options.namingStrategies) { const [directories, classes] = this.splitStringsAndClasses(options.namingStrategies); connection .importNamingStrategies(classes); // .importNamingStrategiesFromDirectories(directories); } // set naming strategy to be used for this connection if (options.usedNamingStrategy) connection.useNamingStrategy(options.usedNamingStrategy); return connection; } /** * Creates a new connection and registers it in the manager. * * If connection options were not specified, then it will try to create connection automatically. * * First, it will try to find a "default" configuration from ormconfig.json. * You can also specify a connection name to use from ormconfig.json, * and you even can specify a path to custom ormconfig.json file. * * In the case if options were not specified, and ormconfig.json file also wasn't found, * it will try to create connection from environment variables. * There are several environment variables you can set: * * - TYPEORM_DRIVER_TYPE - driver type. Can be "mysql", "mysql2", "postgres", "mariadb", "websql", "oracle" or "mssql". * - TYPEORM_URL - database connection url. Should be a string. * - TYPEORM_HOST - database host. Should be a string. * - TYPEORM_PORT - database access port. Should be a number. * - TYPEORM_USERNAME - database username. Should be a string. * - TYPEORM_PASSWORD - database user's password. Should be a string. * - TYPEORM_SID - database's SID. Used only for oracle databases. Should be a string. * - TYPEORM_STORAGE - database's storage url. Used only for websql databases. Should be a string. * - TYPEORM_USE_POOL - indicates if connection pooling should be enabled. By default its enabled. Should be boolean-like value. * - TYPEORM_DRIVER_EXTRA - extra options to be passed to the driver. Should be a serialized json string of options. * - TYPEORM_AUTO_SCHEMA_SYNC - indicates if automatic schema synchronization will be performed on each application run. Should be boolean-like value. * - TYPEORM_ENTITIES - list of directories containing entities to load. Should be string - directory names (can be patterns) split by a comma. * - TYPEORM_SUBSCRIBERS - list of directories containing subscribers to load. Should be string - directory names (can be patterns) split by a comma. * - TYPEORM_ENTITY_SCHEMAS - list of directories containing entity schemas to load. Should be string - directory names (can be patterns) split by a comma. * - TYPEORM_NAMING_STRATEGIES - list of directories containing custom naming strategies to load. Should be string - directory names (can be patterns) split by a comma. * - TYPEORM_LOGGING_QUERIES - indicates if each executed query must be logged. Should be boolean-like value. * - TYPEORM_LOGGING_FAILED_QUERIES - indicates if logger should log failed query's error. Should be boolean-like value. * - TYPEORM_LOGGING_ONLY_FAILED_QUERIES - indicates if only failed queries must be logged. Should be boolean-like value. * * TYPEORM_DRIVER_TYPE variable is required. Depend on the driver type some other variables may be required too. */ // async createAndConnect(): Promise<Connection>; /** * Creates connection from the given connection options and registers it in the manager. */ /** * Creates connection and and registers it in the manager. */ createAndConnect(connectionOptions) { return __awaiter(this, void 0, void 0, function* () { // if connection options are given, then create connection from them if (connectionOptions && connectionOptions instanceof Object) { return this.createAndConnectByConnectionOptions(connectionOptions); } // if connection name is specified then explicitly try to load connection options from it // if (typeof optionsOrConnectionNameFromConfig === "string") // return this.createFromConfigAndConnect(optionsOrConnectionNameFromConfig || "default", ormConfigPath); // if driver type is set in environment variables then try to create connection from env variables // if (this.hasDefaultConfigurationInEnvironmentVariables()) // return this.createFromEnvAndConnect(); throw new CannotDetermineConnectionOptionsError(); }); } /** * Creates connections and and registers them in the manager. */ createAndConnectToAll(optionsOrOrmConfigFilePath) { return __awaiter(this, void 0, void 0, function* () { // if connection options are given, then create connection from them if (optionsOrOrmConfigFilePath && optionsOrOrmConfigFilePath instanceof Array) return Promise.all(optionsOrOrmConfigFilePath.map(options => { return this.createAndConnectByConnectionOptions(options); })); // if connection name is specified then explicitly try to load connection options from it // if (typeof optionsOrOrmConfigFilePath === "string") // return this.createFromConfigAndConnectToAll(optionsOrOrmConfigFilePath as string); // if driver type is set in environment variables then try to create connection from env variables // if (this.hasDefaultConfigurationInEnvironmentVariables()) // return [await this.createFromEnvAndConnect()]; throw new CannotDetermineConnectionOptionsError(); }); } // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- /** * Checks if environment variables contains connection options. */ /*protected hasDefaultConfigurationInEnvironmentVariables(): boolean { return !!process.env.TYPEORM_DRIVER_TYPE; }*/ /** * Allows to quickly create a connection based on the environment variable values. */ /*protected async createFromEnvAndConnect(): Promise<Connection> { return this.createAndConnectByConnectionOptions({ driver: { type: process.env.TYPEORM_DRIVER_TYPE, url: process.env.TYPEORM_URL, host: process.env.TYPEORM_HOST, port: process.env.TYPEORM_PORT, username: process.env.TYPEORM_USERNAME, password: process.env.TYPEORM_PASSWORD, database: process.env.TYPEORM_DATABASE, sid: process.env.TYPEORM_SID, storage: process.env.TYPEORM_STORAGE, usePool: process.env.TYPEORM_USE_POOL !== undefined ? OrmUtils.toBoolean(process.env.TYPEORM_USE_POOL) : undefined, // special check for defined is required here extra: process.env.TYPEORM_DRIVER_EXTRA ? JSON.parse(process.env.TYPEORM_DRIVER_EXTRA) : undefined }, autoSchemaSync: OrmUtils.toBoolean(process.env.TYPEORM_AUTO_SCHEMA_SYNC), entities: process.env.TYPEORM_ENTITIES ? process.env.TYPEORM_ENTITIES.split(",") : [], subscribers: process.env.TYPEORM_SUBSCRIBERS ? process.env.TYPEORM_SUBSCRIBERS.split(",") : [], entitySchemas: process.env.TYPEORM_ENTITY_SCHEMAS ? process.env.TYPEORM_ENTITY_SCHEMAS.split(",") : [], namingStrategies: process.env.TYPEORM_NAMING_STRATEGIES ? process.env.TYPEORM_NAMING_STRATEGIES.split(",") : [], usedNamingStrategy: process.env.TYPEORM_USED_NAMING_STRATEGY, logging: { logQueries: OrmUtils.toBoolean(process.env.TYPEORM_LOGGING_QUERIES), logFailedQueryError: OrmUtils.toBoolean(process.env.TYPEORM_LOGGING_FAILED_QUERIES), logOnlyFailedQueries: OrmUtils.toBoolean(process.env.TYPEORM_LOGGING_ONLY_FAILED_QUERIES), } }); }*/ /** * Creates a new connection based on the connection options from "ormconfig.json" * and registers a new connection in the manager. * Optionally you can specify a path to the json configuration. * If path is not given, then ormconfig.json file will be searched near node_modules directory. */ /* protected async createFromConfigAndConnectToAll(path?: string): Promise<Connection[]> { const optionsArray: ConnectionOptions[] = require(path || (require("app-root-path").path + "/ormconfig.json")); if (!optionsArray) throw new Error(`Configuration ${path || "ormconfig.json"} was not found. Add connection configuration inside ormconfig.json file.`); const promises = optionsArray .filter(options => !options.environment || options.environment === process.env.NODE_ENV) // skip connection creation if environment is set in the options, and its not equal to the value in the NODE_ENV variable .map(options => this.createAndConnectByConnectionOptions(options)); return Promise.all(promises); }*/ /** * Creates a new connection based on the connection options from "ormconfig.json" * and registers a new connection in the manager. * Optionally you can specify a path to the json configuration. * If path is not given, then ormconfig.json file will be searched near node_modules directory. */ /*protected async createFromConfigAndConnect(connectionName: string, path?: string): Promise<Connection> { const optionsArray: ConnectionOptions[] = require(path || (require("app-root-path").path + "/ormconfig.json")); if (!optionsArray) throw new Error(`Configuration ${path || "ormconfig.json"} was not found. Add connection configuration inside ormconfig.json file.`); const environmentLessOptions = optionsArray.filter(options => (options.name || "default") === connectionName); const options = environmentLessOptions.filter(options => !options.environment || options.environment === process.env.NODE_ENV); // skip connection creation if environment is set in the options, and its not equal to the value in the NODE_ENV variable if (!options.length) throw new Error(`Connection "${connectionName}" ${process.env.NODE_ENV ? "for the environment " + process.env.NODE_ENV + " " : ""}was not found in the json configuration file.` + (environmentLessOptions.length ? ` However there are such configurations for other environments: ${environmentLessOptions.map(options => options.environment).join(", ")}.` : "")); return this.createAndConnectByConnectionOptions(options[0]); }*/ /** * Creates a new connection based on the given connection options and registers a new connection in the manager. */ createAndConnectByConnectionOptions(options) { return __awaiter(this, void 0, void 0, function* () { const connection = this.create(options); // connect to the database yield connection.connect(); // if option is set - drop schema once connection is done if (options.dropSchemaOnConnection /* && !process.env.SKIP_SCHEMA_CREATION*/) yield connection.dropDatabase(); // if option is set - automatically synchronize a schema if (options.autoSchemaSync /* && !process.env.SKIP_SCHEMA_CREATION*/) yield connection.syncSchema(); return connection; }); } /** * Splits given array of mixed strings and / or functions into two separate array of string and array of functions. */ splitStringsAndClasses(strAndClses) { return [ strAndClses.filter(str => typeof str === "string"), strAndClses.filter(cls => typeof cls !== "string"), ]; } /** * Creates a new driver based on the given driver type and options. */ createDriver(options, logger) { switch (options.type) { case "ionic-sqlite": return new IonicSQLiteDriver(options, logger); case "websql": return new WebSqlDriver(options, logger); default: throw new MissingDriverError(options.type); } } /** * Creates a new connection and registers it in the connection manager. */ createConnection(name, driver, logger) { const existConnection = this.connections.find(connection => connection.name === name); if (existConnection) { if (existConnection.isConnected) throw new AlreadyHasActiveConnectionError(name); this.connections.splice(this.connections.indexOf(existConnection), 1); } const connection = new Connection(name, driver, logger); this.connections.push(connection); return connection; } } //# sourceMappingURL=ConnectionManager.js.map