mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
refactored connection options, how they are loaded and how connection manager works; implemented loading from multiple configuration sources; implemented including in cli (now can load from env)
This commit is contained in:
parent
34bbd9a3ad
commit
31c3b70eb2
@ -33,6 +33,9 @@ Now naming strategy should be registered by passing naming strategy instance dir
|
||||
* removed `usePool` option from the connection options
|
||||
* connection options interface has changed and now each platform has its own set of connection options
|
||||
* `storage` in sqlite options has been renamed to `database`
|
||||
* env variable names for connection were changed (`TYPEORM_DRIVER_TYPE` has been renamed to `TYPEORM_CONNECTION`, some other renaming).
|
||||
More env variable names you can find in `ConnectionOptionsEnvReader` class.
|
||||
* some api changes in `ConnectionManager` and `createConnection` / `createConnections` methods of typeorm main entrypoint
|
||||
|
||||
### OTHER API CHANGES
|
||||
|
||||
@ -44,6 +47,10 @@ Now naming strategy should be registered by passing naming strategy instance dir
|
||||
* added `mongodb` support
|
||||
* entity now can be saved partially within `update` method
|
||||
* added prefix support to embeddeds
|
||||
* now embeddeds inside other embeddeds are supported
|
||||
* now relations are supported inside embeds
|
||||
* now relations for multiple primary keys are generated properly
|
||||
* now ormconfig is read from `.env`, `.js`, `.json`, `.yml`, `.xml` formats
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import * as fs from "fs";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Generates a new entity.
|
||||
@ -26,7 +26,7 @@ export class EntityCreateCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -39,15 +39,9 @@ export class EntityCreateCommand {
|
||||
// if directory is not set then try to open tsconfig and find default path there
|
||||
if (!directory) {
|
||||
try {
|
||||
const connections: ConnectionOptions[] = require(process.cwd() + "/" + argv.config);
|
||||
if (connections) {
|
||||
const connection = connections.find(connection => { // todo: need to implement "environment" support in the ormconfig too
|
||||
return connection.name === argv.connection || ((argv.connection === "default" || !argv.connection) && !connection.name);
|
||||
});
|
||||
if (connection && connection.cli) {
|
||||
directory = connection.cli.entitiesDir;
|
||||
}
|
||||
}
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
directory = connectionOptions.cli ? connectionOptions.cli.entitiesDir : undefined;
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import * as fs from "fs";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Creates a new migration file.
|
||||
@ -27,7 +28,7 @@ export class MigrationCreateCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -41,15 +42,9 @@ export class MigrationCreateCommand {
|
||||
// if directory is not set then try to open tsconfig and find default path there
|
||||
if (!directory) {
|
||||
try {
|
||||
const connections: ConnectionOptions[] = require(process.cwd() + "/" + argv.config);
|
||||
if (connections) {
|
||||
const connection = connections.find(connection => { // todo: need to implement "environment" support in the ormconfig too
|
||||
return connection.name === argv.connection || ((argv.connection === "default" || !argv.connection) && !connection.name);
|
||||
});
|
||||
if (connection && connection.cli) {
|
||||
directory = connection.cli.migrationsDir;
|
||||
}
|
||||
}
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
directory = connectionOptions.cli ? connectionOptions.cli.migrationsDir : undefined;
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {createConnection} from "../index";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Reverts last migration command.
|
||||
@ -17,7 +18,7 @@ export class MigrationRevertCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -25,9 +26,11 @@ export class MigrationRevertCommand {
|
||||
async handler(argv: any) {
|
||||
|
||||
try {
|
||||
process.env.SKIP_SCHEMA_CREATION = true;
|
||||
process.env.SKIP_SUBSCRIBERS_LOADING = true;
|
||||
const connection = await createConnection(argv.connection, process.cwd() + "/" + argv.config);
|
||||
process.env.SKIP_SCHEMA_CREATION = true; // todo: maybe simply re-assign connection options?
|
||||
process.env.SKIP_SUBSCRIBERS_LOADING = true; // todo: maybe simply re-assign connection options?
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
const connection = await createConnection(connectionOptions);
|
||||
|
||||
try {
|
||||
await connection.undoLastMigration();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {createConnection} from "../index";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Runs migration command.
|
||||
@ -17,7 +18,7 @@ export class MigrationRunCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -27,7 +28,10 @@ export class MigrationRunCommand {
|
||||
try {
|
||||
process.env.SKIP_SCHEMA_CREATION = true;
|
||||
process.env.SKIP_SUBSCRIBERS_LOADING = true;
|
||||
const connection = await createConnection(argv.connection, process.cwd() + "/" + argv.config);
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
const connection = await createConnection(connectionOptions);
|
||||
|
||||
try {
|
||||
await connection.runMigrations();
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {createConnection} from "../index";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Executes an sql query on the given connection.
|
||||
@ -17,14 +18,17 @@ export class QueryCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
|
||||
async handler(argv: any) {
|
||||
process.env.SKIP_SCHEMA_CREATION = true;
|
||||
const connection = await createConnection(argv.connection, process.cwd() + "/" + argv.config);
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
const connection = await createConnection(connectionOptions);
|
||||
|
||||
let queryRunner: QueryRunner|undefined = undefined;
|
||||
try {
|
||||
queryRunner = await connection.driver.createQueryRunner();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {createConnections, createConnection} from "../index";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Drops all tables of the database from the given connection.
|
||||
@ -18,7 +19,7 @@ export class SchemaDropCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -29,12 +30,16 @@ export class SchemaDropCommand {
|
||||
try {
|
||||
process.env.LOGGER_CLI_SCHEMA_SYNC = true;
|
||||
process.env.SKIP_SCHEMA_CREATION = true;
|
||||
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
if (argv.connection) {
|
||||
connection = await createConnection(argv.connection, process.cwd() + "/" + argv.config);
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
connection = await createConnection(connectionOptions);
|
||||
await connection.dropDatabase();
|
||||
|
||||
} else {
|
||||
connections = await createConnections();
|
||||
const connectionOptions = await connectionOptionsReader.all();
|
||||
connections = await createConnections(connectionOptions);
|
||||
await Promise.all(connections.map(connection => connection.dropDatabase()));
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {createConnections, createConnection} from "../index";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Synchronizes database schema with entities.
|
||||
@ -18,7 +19,7 @@ export class SchemaSyncCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -29,12 +30,16 @@ export class SchemaSyncCommand {
|
||||
try {
|
||||
process.env.LOGGER_CLI_SCHEMA_SYNC = true;
|
||||
process.env.SKIP_SCHEMA_CREATION = true;
|
||||
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
if (argv.connection) {
|
||||
connection = await createConnection(argv.connection, process.cwd() + "/" + argv.config);
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
connection = await createConnection(connectionOptions); // process.cwd()
|
||||
await connection.syncSchema(false);
|
||||
|
||||
} else {
|
||||
connections = await createConnections();
|
||||
const connectionOptions = await connectionOptionsReader.all();
|
||||
connections = await createConnections(connectionOptions);
|
||||
await Promise.all(connections.map(connection => connection.syncSchema(false)));
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import * as fs from "fs";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader";
|
||||
|
||||
/**
|
||||
* Generates a new subscriber.
|
||||
@ -26,7 +27,7 @@ export class SubscriberCreateCommand {
|
||||
})
|
||||
.option("cf", {
|
||||
alias: "config",
|
||||
default: "ormconfig.json",
|
||||
default: "ormconfig",
|
||||
describe: "Name of the file with connection configuration."
|
||||
});
|
||||
}
|
||||
@ -39,15 +40,9 @@ export class SubscriberCreateCommand {
|
||||
// if directory is not set then try to open tsconfig and find default path there
|
||||
if (!directory) {
|
||||
try {
|
||||
const connections: ConnectionOptions[] = require(process.cwd() + "/" + argv.config);
|
||||
if (connections) {
|
||||
const connection = connections.find(connection => { // todo: need to implement "environment" support in the ormconfig too
|
||||
return connection.name === argv.connection || ((argv.connection === "default" || !argv.connection) && !connection.name);
|
||||
});
|
||||
if (connection && connection.cli) {
|
||||
directory = connection.cli.subscribersDir;
|
||||
}
|
||||
}
|
||||
const connectionOptionsReader = new ConnectionOptionsReader({ root: process.cwd(), configName: argv.config });
|
||||
const connectionOptions = await connectionOptionsReader.get(argv.connection);
|
||||
directory = connectionOptions.cli ? connectionOptions.cli.subscribersDir : undefined;
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
|
||||
@ -142,10 +142,23 @@ export class Connection {
|
||||
// set connected status for the current connection
|
||||
Object.assign(this, { isConnected: true });
|
||||
|
||||
// build all metadatas registered in the current connection
|
||||
try {
|
||||
|
||||
// build all metadatas registered in the current connection
|
||||
this.buildMetadatas();
|
||||
|
||||
// if option is set - drop schema once connection is done
|
||||
if (this.options.dropSchemaOnConnection && !PlatformTools.getEnvVariable("SKIP_SCHEMA_CREATION"))
|
||||
await this.dropDatabase();
|
||||
|
||||
// if option is set - automatically synchronize a schema
|
||||
if (this.options.autoSchemaSync && !PlatformTools.getEnvVariable("SKIP_SCHEMA_CREATION"))
|
||||
await this.syncSchema();
|
||||
|
||||
// if option is set - automatically synchronize a schema
|
||||
if (this.options.autoMigrationsRun && !PlatformTools.getEnvVariable("SKIP_MIGRATIONS_RUN"))
|
||||
await this.runMigrations();
|
||||
|
||||
} catch (error) {
|
||||
|
||||
// if for some reason build metadata fail (for example validation error during entity metadata check)
|
||||
@ -300,7 +313,7 @@ export class Connection {
|
||||
|
||||
const usedQueryRunnerProvider = queryRunnerProvider || new QueryRunnerProvider(this.driver, true);
|
||||
const queryRunner = await usedQueryRunnerProvider.provide();
|
||||
const transactionEntityManager = new EntityManager(this, usedQueryRunnerProvider);
|
||||
const transactionEntityManager = new EntityManagerFactory().create(this, usedQueryRunnerProvider);
|
||||
|
||||
try {
|
||||
await queryRunner.beginTransaction();
|
||||
@ -371,7 +384,7 @@ export class Connection {
|
||||
/**
|
||||
* Creates a new entity manager with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
* After finishing with entity manager, don't forget to release it (to release database connection back to pool).
|
||||
*/
|
||||
createIsolatedManager(queryRunnerProvider?: QueryRunnerProvider): EntityManager {
|
||||
if (!queryRunnerProvider)
|
||||
@ -383,7 +396,7 @@ export class Connection {
|
||||
/**
|
||||
* Creates a new repository with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
* After finishing with entity manager, don't forget to release it (to release database connection back to pool).
|
||||
*/
|
||||
createIsolatedRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, queryRunnerProvider?: QueryRunnerProvider): Repository<Entity> {
|
||||
if (!queryRunnerProvider)
|
||||
@ -395,7 +408,7 @@ export class Connection {
|
||||
/**
|
||||
* Creates a new specific repository with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
* After finishing with entity manager, don't forget to release it (to release database connection back to pool).
|
||||
*/
|
||||
createIsolatedSpecificRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, queryRunnerProvider?: QueryRunnerProvider): SpecificRepository<Entity> {
|
||||
if (!queryRunnerProvider)
|
||||
@ -435,7 +448,7 @@ export class Connection {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds entity metadata exist for the given entity class, target name or table name.
|
||||
* Finds exist entity metadata by the given entity class, target name or table name.
|
||||
*/
|
||||
protected findMetadata(target: Function|string): EntityMetadata|undefined {
|
||||
return this.entityMetadatas.find(metadata => {
|
||||
@ -449,7 +462,7 @@ export class Connection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds all registered metadatas.
|
||||
* Builds metadatas for all registered classes inside this connection.
|
||||
*/
|
||||
protected buildMetadatas(): void {
|
||||
|
||||
@ -457,7 +470,7 @@ export class Connection {
|
||||
const repositoryFactory = new RepositoryFactory();
|
||||
const entityMetadataValidator = new EntityMetadataValidator();
|
||||
|
||||
// build subscribers if they are not disallowed from high-level (for example they can disallowed from migrations run process)
|
||||
// create subscribers instances if they are not disallowed from high-level (for example they can disallowed from migrations run process)
|
||||
if (!PlatformTools.getEnvVariable("SKIP_SUBSCRIBERS_LOADING")) {
|
||||
const subscribers = connectionMetadataBuilder.buildSubscribers(this.options.subscribers || []);
|
||||
Object.assign(this, { subscribers: subscribers });
|
||||
|
||||
@ -2,12 +2,9 @@ import {Connection} from "./Connection";
|
||||
import {ConnectionNotFoundError} from "./error/ConnectionNotFoundError";
|
||||
import {ConnectionOptions} from "./ConnectionOptions";
|
||||
import {AlreadyHasActiveConnectionError} from "./error/AlreadyHasActiveConnectionError";
|
||||
import {OrmUtils} from "../util/OrmUtils";
|
||||
import {CannotDetermineConnectionOptionsError} from "./error/CannotDetermineConnectionOptionsError";
|
||||
import {PlatformTools} from "../platform/PlatformTools";
|
||||
|
||||
/**
|
||||
* ConnectionManager is used to store and manage all these different connections.
|
||||
* ConnectionManager is used to store and manage multiple orm connections.
|
||||
* It also provides useful factory methods to simplify connection creation.
|
||||
*/
|
||||
export class ConnectionManager {
|
||||
@ -19,7 +16,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* List of connections registered in this connection manager.
|
||||
*/
|
||||
protected connections: Connection[] = [];
|
||||
protected readonly connections: Connection[] = [];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
@ -35,7 +32,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* 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.
|
||||
* Throws error if connection with the given name was not found.
|
||||
*/
|
||||
get(name: string = "default"): Connection {
|
||||
const connection = this.connections.find(connection => connection.name === name);
|
||||
@ -47,9 +44,7 @@ export class ConnectionManager {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Connection won't be established, you'll need to manually call connect method to establish connection.
|
||||
*/
|
||||
create(options: ConnectionOptions): Connection {
|
||||
|
||||
@ -57,343 +52,22 @@ export class ConnectionManager {
|
||||
if (options.driver)
|
||||
Object.assign(options, options.driver);
|
||||
|
||||
// check if such connection is already registered
|
||||
const existConnection = this.connections.find(connection => connection.name === (options.name || "default"));
|
||||
if (existConnection) {
|
||||
|
||||
// if connection is registered and its not closed then throw an error
|
||||
if (existConnection.isConnected)
|
||||
throw new AlreadyHasActiveConnectionError(options.name || "default");
|
||||
|
||||
// if its registered but closed then simply remove it from the manager
|
||||
this.connections.splice(this.connections.indexOf(existConnection), 1);
|
||||
}
|
||||
|
||||
// create a new connection
|
||||
const connection = new Connection(options);
|
||||
this.connections.push(connection);
|
||||
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", "postgres", "mariadb", "sqlite", "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 sqlite 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.
|
||||
*/
|
||||
async createAndConnect(options: ConnectionOptions): Promise<Connection>;
|
||||
|
||||
/**
|
||||
* Creates connection with the given connection name from the ormconfig.json file and registers it in the manager.
|
||||
* Optionally you can specify a path to custom ormconfig.json file.
|
||||
*/
|
||||
async createAndConnect(connectionNameFromConfig: string, ormConfigPath?: string): Promise<Connection>;
|
||||
|
||||
/**
|
||||
* Creates connection and and registers it in the manager.
|
||||
*/
|
||||
async createAndConnect(optionsOrConnectionNameFromConfig?: ConnectionOptions|string, ormConfigPath?: string): Promise<Connection> {
|
||||
|
||||
// if connection options are given, then create connection from them
|
||||
if (optionsOrConnectionNameFromConfig && optionsOrConnectionNameFromConfig instanceof Object)
|
||||
return this.createAndConnectByConnectionOptions(optionsOrConnectionNameFromConfig as 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 nothing is specified then try to silently load config from ormconfig.json
|
||||
if (this.hasDefaultConfigurationInConfigurationFile())
|
||||
return this.createFromConfigAndConnect("default");
|
||||
|
||||
// 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 new connections and registers them in the manager.
|
||||
*
|
||||
* If array of connection options were not specified, then it will try to create them automatically
|
||||
* from ormconfig.json. You can also specify path to your 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", "postgres", "mariadb", "sqlite", "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 sqlite 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 createAndConnectToAll(): Promise<Connection[]>;
|
||||
|
||||
/**
|
||||
* Creates connections from the given connection options and registers them in the manager.
|
||||
*/
|
||||
async createAndConnectToAll(options?: ConnectionOptions[]): Promise<Connection[]>;
|
||||
|
||||
/**
|
||||
* Creates connections from the ormconfig.json file.
|
||||
* Optionally you can specify a path to custom ormconfig.json file.
|
||||
*/
|
||||
async createAndConnectToAll(ormConfigPath?: string): Promise<Connection[]>;
|
||||
|
||||
/**
|
||||
* Creates connections and and registers them in the manager.
|
||||
*/
|
||||
async createAndConnectToAll(optionsOrOrmConfigFilePath?: ConnectionOptions[]|string): Promise<Connection[]> {
|
||||
|
||||
// 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 as ConnectionOptions);
|
||||
}));
|
||||
|
||||
// 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 nothing is specified then try to silently load config from ormconfig.json
|
||||
if (this.hasOrmConfigurationFile())
|
||||
return this.createFromConfigAndConnectToAll();
|
||||
|
||||
// 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 ormconfig.json exists.
|
||||
*/
|
||||
protected hasOrmConfigurationFile(): boolean {
|
||||
const path = PlatformTools.load("app-root-path").path + "/ormconfig.json";
|
||||
if (!PlatformTools.fileExist(path))
|
||||
return false;
|
||||
|
||||
const configuration: ConnectionOptions[]|ConnectionOptions = PlatformTools.load(path);
|
||||
if (configuration instanceof Array) {
|
||||
return configuration
|
||||
.filter(options => !options.environment || options.environment === PlatformTools.getEnvVariable("NODE_ENV"))
|
||||
.length > 0;
|
||||
|
||||
} else if (configuration instanceof Object) {
|
||||
if (configuration.environment && configuration.environment !== PlatformTools.getEnvVariable("NODE_ENV"))
|
||||
return false;
|
||||
|
||||
return Object.keys(configuration).length > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a default connection in the ormconfig.json file.
|
||||
*/
|
||||
protected hasDefaultConfigurationInConfigurationFile(): boolean {
|
||||
const path = PlatformTools.load("app-root-path").path + "/ormconfig.json";
|
||||
if (!PlatformTools.fileExist(path))
|
||||
return false;
|
||||
|
||||
const configuration: ConnectionOptions[]|ConnectionOptions = PlatformTools.load(path);
|
||||
if (configuration instanceof Array) {
|
||||
return !!configuration
|
||||
.filter(options => !options.environment || options.environment === PlatformTools.getEnvVariable("NODE_ENV"))
|
||||
.find(config => !!config.name || config.name === "default");
|
||||
|
||||
} else if (configuration instanceof Object) {
|
||||
if (!configuration.name ||
|
||||
configuration.name !== "default")
|
||||
return false;
|
||||
|
||||
if (configuration.environment && configuration.environment !== PlatformTools.getEnvVariable("NODE_ENV"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if environment variables contains connection options.
|
||||
*/
|
||||
protected hasDefaultConfigurationInEnvironmentVariables(): boolean {
|
||||
return !!PlatformTools.getEnvVariable("TYPEORM_DRIVER_TYPE");
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to quickly create a connection based on the environment variable values.
|
||||
*/
|
||||
protected async createFromEnvAndConnect(): Promise<Connection> {
|
||||
return this.createAndConnectByConnectionOptions({
|
||||
type: PlatformTools.getEnvVariable("TYPEORM_DRIVER_TYPE"),
|
||||
url: PlatformTools.getEnvVariable("TYPEORM_URL"),
|
||||
host: PlatformTools.getEnvVariable("TYPEORM_HOST"),
|
||||
port: PlatformTools.getEnvVariable("TYPEORM_PORT"),
|
||||
username: PlatformTools.getEnvVariable("TYPEORM_USERNAME"),
|
||||
password: PlatformTools.getEnvVariable("TYPEORM_PASSWORD"),
|
||||
database: PlatformTools.getEnvVariable("TYPEORM_DATABASE"),
|
||||
sid: PlatformTools.getEnvVariable("TYPEORM_SID"),
|
||||
extra: PlatformTools.getEnvVariable("TYPEORM_DRIVER_EXTRA") ? JSON.parse(PlatformTools.getEnvVariable("TYPEORM_DRIVER_EXTRA")) : undefined,
|
||||
autoSchemaSync: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_AUTO_SCHEMA_SYNC")),
|
||||
entities: PlatformTools.getEnvVariable("TYPEORM_ENTITIES") ? PlatformTools.getEnvVariable("TYPEORM_ENTITIES").split(",") : [],
|
||||
subscribers: PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS") ? PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS").split(",") : [],
|
||||
entitySchemas: PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS") ? PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS").split(",") : [],
|
||||
logging: {
|
||||
logQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_QUERIES")),
|
||||
logFailedQueryError: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_FAILED_QUERIES")),
|
||||
logOnlyFailedQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("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[]> {
|
||||
let optionsArray: ConnectionOptions[] = PlatformTools.load(path || (PlatformTools.load("app-root-path").path + "/ormconfig.json"));
|
||||
if (!(optionsArray instanceof Array)) optionsArray = [optionsArray]; // cast options to array if ormconfig contains a single connection options object
|
||||
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 === PlatformTools.getEnvVariable("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> {
|
||||
let optionsArray: ConnectionOptions[] = PlatformTools.load(path || (PlatformTools.load("app-root-path").path + "/ormconfig.json"));
|
||||
if (!(optionsArray instanceof Array)) optionsArray = [optionsArray]; // cast options to array if ormconfig contains a single connection options object
|
||||
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.find(options => !options.environment || options.environment === PlatformTools.getEnvVariable("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)
|
||||
throw new Error(`Connection "${connectionName}" ${PlatformTools.getEnvVariable("NODE_ENV") ? "for the environment " + PlatformTools.getEnvVariable("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(", ")}.` : ""));
|
||||
|
||||
let connectionOptions: ConnectionOptions = Object.assign({}, options);
|
||||
// normalize directory paths
|
||||
if (options.entities) {
|
||||
const entities = (options.entities as any[]).map(entity => {
|
||||
if (typeof entity === "string" || entity.substr(0, 1) !== "/")
|
||||
return PlatformTools.load("app-root-path").path + "/" + entity;
|
||||
|
||||
return entity;
|
||||
});
|
||||
Object.assign(connectionOptions, { entities: entities });
|
||||
}
|
||||
if (options.subscribers) {
|
||||
const subscribers = (options.subscribers as any[]).map(subscriber => {
|
||||
if (typeof subscriber === "string" || subscriber.substr(0, 1) !== "/")
|
||||
return PlatformTools.load("app-root-path").path + "/" + subscriber;
|
||||
|
||||
return subscriber;
|
||||
});
|
||||
Object.assign(connectionOptions, { subscribers: subscribers });
|
||||
}
|
||||
if (options.migrations) {
|
||||
const migrations = (options.migrations as any[]).map(migration => {
|
||||
if (typeof migration === "string" || migration.substr(0, 1) !== "/")
|
||||
return PlatformTools.load("app-root-path").path + "/" + migration;
|
||||
|
||||
return migration;
|
||||
});
|
||||
Object.assign(connectionOptions, { migrations: migrations });
|
||||
}
|
||||
|
||||
return this.createAndConnectByConnectionOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection based on the given connection options and registers a new connection in the manager.
|
||||
*/
|
||||
protected async createAndConnectByConnectionOptions(options: ConnectionOptions): Promise<Connection> {
|
||||
const connection = this.create(options);
|
||||
|
||||
// connect to the database
|
||||
await connection.connect();
|
||||
|
||||
// if option is set - drop schema once connection is done
|
||||
if (options.dropSchemaOnConnection && !PlatformTools.getEnvVariable("SKIP_SCHEMA_CREATION"))
|
||||
await connection.dropDatabase();
|
||||
|
||||
// if option is set - automatically synchronize a schema
|
||||
if (options.autoSchemaSync && !PlatformTools.getEnvVariable("SKIP_SCHEMA_CREATION"))
|
||||
await connection.syncSchema();
|
||||
|
||||
// if option is set - automatically synchronize a schema
|
||||
if (options.autoMigrationsRun && !PlatformTools.getEnvVariable("SKIP_MIGRATIONS_RUN"))
|
||||
await connection.runMigrations();
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,9 @@ import {EntitySchema} from "../entity-schema/EntitySchema";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {EntitySubscriberInterface} from "../subscriber/EntitySubscriberInterface";
|
||||
|
||||
/**
|
||||
* Builds migration instances, subscriber instances and entity metadatas for the given classes.
|
||||
*/
|
||||
export class ConnectionMetadataBuilder {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -23,12 +26,18 @@ export class ConnectionMetadataBuilder {
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds migration instances for the given classes or directories.
|
||||
*/
|
||||
buildMigrations(migrations: Function[]|string[]): MigrationInterface[] {
|
||||
const [migrationClasses, migrationDirectories] = OrmUtils.splitClassesAndStrings(migrations);
|
||||
const allMigrationClasses = [...migrationClasses, ...importClassesFromDirectories(migrationDirectories)];
|
||||
return allMigrationClasses.map(migrationClass => getFromContainer<MigrationInterface>(migrationClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds subscriber instances for the given classes or directories.
|
||||
*/
|
||||
buildSubscribers(subscribers: Function[]|string[]): EntitySubscriberInterface<any>[] {
|
||||
const [subscriberClasses, subscriberDirectories] = OrmUtils.splitClassesAndStrings(subscribers || []);
|
||||
const allSubscriberClasses = [...subscriberClasses, ...importClassesFromDirectories(subscriberDirectories)];
|
||||
@ -37,6 +46,9 @@ export class ConnectionMetadataBuilder {
|
||||
.map(metadata => getFromContainer<EntitySubscriberInterface<any>>(metadata.target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds entity metadatas for the given classes or directories.
|
||||
*/
|
||||
buildEntityMetadatas(entities: Function[]|string[], schemas: EntitySchema[]|string[]): EntityMetadata[] {
|
||||
const [entityClasses, entityDirectories] = OrmUtils.splitClassesAndStrings(entities || []);
|
||||
const allEntityClasses = [...entityClasses, ...importClassesFromDirectories(entityDirectories)];
|
||||
|
||||
@ -11,7 +11,8 @@ import {MongoConnectionOptions} from "../driver/mongodb/MongoConnectionOptions";
|
||||
* Options contain database and other connection-related settings.
|
||||
* Consumer must provide connection options for each of your connections.
|
||||
*/
|
||||
export type ConnectionOptions = MysqlConnectionOptions|
|
||||
export type ConnectionOptions =
|
||||
MysqlConnectionOptions|
|
||||
PostgresConnectionOptions|
|
||||
SqliteConnectionOptions|
|
||||
SqlServerConnectionOptions|
|
||||
|
||||
173
src/connection/ConnectionOptionsReader.ts
Normal file
173
src/connection/ConnectionOptionsReader.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import {ConnectionOptions} from "./ConnectionOptions";
|
||||
import {PlatformTools} from "../platform/PlatformTools";
|
||||
import {ConnectionOptionsEnvReader} from "./options-reader/ConnectionOptionsEnvReader";
|
||||
import {ConnectionOptionsYmlReader} from "./options-reader/ConnectionOptionsYmlReader";
|
||||
import {ConnectionOptionsXmlReader} from "./options-reader/ConnectionOptionsXmlReader";
|
||||
|
||||
/**
|
||||
* Reads connection options from the ormconfig.
|
||||
* Can read from multiple file extensions including env, json, js, xml and yml.
|
||||
*/
|
||||
export class ConnectionOptionsReader {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected options?: {
|
||||
/**
|
||||
* Directory where ormconfig should be read from.
|
||||
* By default its your application root (where your app package.json is located).
|
||||
*/
|
||||
root?: string,
|
||||
|
||||
/**
|
||||
* Filename of the ormconfig configuration. By default its equal to "ormconfig".
|
||||
*/
|
||||
configName?: string
|
||||
}) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns all connection options read from the ormconfig.
|
||||
*/
|
||||
async all(): Promise<ConnectionOptions[]> {
|
||||
return this.load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a connection with a given name read from ormconfig.
|
||||
* If connection with such name would not be found then it throw error.
|
||||
*/
|
||||
async get(name: string): Promise<ConnectionOptions> {
|
||||
const allOptions = await this.all();
|
||||
const targetOptions = allOptions.find(options => options.name === name || (name === "default" && !options.name));
|
||||
if (!targetOptions)
|
||||
throw new Error(`Cannot find connection ${name} because its not defined in any orm configuration files.`);
|
||||
|
||||
return targetOptions;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Loads all connection options from a configuration file.
|
||||
*
|
||||
* todo: get in count NODE_ENV somehow
|
||||
*/
|
||||
protected async load(): Promise<ConnectionOptions[]> {
|
||||
|
||||
// try to find any of following configuration formats
|
||||
const foundFileFormat = ["env", "js", "json", "yml", "yaml", "xml"].find(format => {
|
||||
return PlatformTools.fileExist(this.baseFilePath + "." + format);
|
||||
});
|
||||
|
||||
// if .env file found then load all its variables into process.env using dotenv package
|
||||
if (foundFileFormat === "env") {
|
||||
const dotenv = PlatformTools.load("dotenv");
|
||||
dotenv.config({ path: this.baseFilePath + ".env" });
|
||||
}
|
||||
|
||||
// try to find connection options from any of available sources of configuration
|
||||
let connectionOptions: ConnectionOptions|ConnectionOptions[];
|
||||
if (PlatformTools.getEnvVariable("TYPEORM_CONNECTION")) {
|
||||
connectionOptions = new ConnectionOptionsEnvReader().read();
|
||||
|
||||
} else if (foundFileFormat === "js") {
|
||||
connectionOptions = PlatformTools.load(this.baseFilePath + ".js");
|
||||
|
||||
} else if (foundFileFormat === "json") {
|
||||
connectionOptions = PlatformTools.load(this.baseFilePath + ".json");
|
||||
|
||||
} else if (foundFileFormat === "yml") {
|
||||
connectionOptions = new ConnectionOptionsYmlReader().read(this.baseFilePath + ".yml");
|
||||
|
||||
} else if (foundFileFormat === "yaml") {
|
||||
connectionOptions = new ConnectionOptionsYmlReader().read(this.baseFilePath + ".yaml");
|
||||
|
||||
} else if (foundFileFormat === "xml") {
|
||||
connectionOptions = await new ConnectionOptionsXmlReader().read(this.baseFilePath + ".xml");
|
||||
|
||||
} else {
|
||||
throw new Error(`No connection options were found in any of configurations file.`);
|
||||
}
|
||||
|
||||
// normalize and return connection options
|
||||
return this.normalizeConnectionOptions(connectionOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize connection options.
|
||||
*/
|
||||
protected normalizeConnectionOptions(connectionOptions: ConnectionOptions|ConnectionOptions[]): ConnectionOptions[] {
|
||||
if (!(connectionOptions instanceof Array))
|
||||
connectionOptions = [connectionOptions];
|
||||
|
||||
connectionOptions.forEach(options => {
|
||||
|
||||
if (options.entities) {
|
||||
const entities = (options.entities as any[]).map(entity => {
|
||||
if (typeof entity === "string" || entity.substr(0, 1) !== "/")
|
||||
return this.baseFilePath + "/" + entity;
|
||||
|
||||
return entity;
|
||||
});
|
||||
Object.assign(connectionOptions, { entities: entities });
|
||||
}
|
||||
if (options.subscribers) {
|
||||
const subscribers = (options.subscribers as any[]).map(subscriber => {
|
||||
if (typeof subscriber === "string" || subscriber.substr(0, 1) !== "/")
|
||||
return this.baseFilePath + "/" + subscriber;
|
||||
|
||||
return subscriber;
|
||||
});
|
||||
Object.assign(connectionOptions, { subscribers: subscribers });
|
||||
}
|
||||
if (options.migrations) {
|
||||
const migrations = (options.migrations as any[]).map(migration => {
|
||||
if (typeof migration === "string" || migration.substr(0, 1) !== "/")
|
||||
return this.baseFilePath + "/" + migration;
|
||||
|
||||
return migration;
|
||||
});
|
||||
Object.assign(connectionOptions, { migrations: migrations });
|
||||
}
|
||||
});
|
||||
|
||||
return connectionOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets directory where configuration file should be located and configuration file name without extension.
|
||||
*/
|
||||
protected get baseFilePath(): string {
|
||||
return this.baseDirectory + "/" + this.baseConfigName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets directory where configuration file should be located.
|
||||
*/
|
||||
protected get baseDirectory(): string {
|
||||
if (this.options && this.options.root)
|
||||
return this.options.root;
|
||||
|
||||
return PlatformTools.load("app-root-path").path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets configuration file name.
|
||||
*/
|
||||
protected get baseConfigName(): string {
|
||||
if (this.options && this.options.configName)
|
||||
return this.options.configName;
|
||||
|
||||
return "ormconfig";
|
||||
}
|
||||
|
||||
}
|
||||
42
src/connection/options-reader/ConnectionOptionsEnvReader.ts
Normal file
42
src/connection/options-reader/ConnectionOptionsEnvReader.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import {ConnectionOptions} from "../ConnectionOptions";
|
||||
import {PlatformTools} from "../../platform/PlatformTools";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
|
||||
/**
|
||||
* Reads connection options from environment variables.
|
||||
* Environment variables can have only a single connection.
|
||||
* Its strongly required to define TYPEORM_CONNECTION env variable.
|
||||
*/
|
||||
export class ConnectionOptionsEnvReader {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reads connection options from environment variables.
|
||||
*/
|
||||
read(): ConnectionOptions {
|
||||
return {
|
||||
type: PlatformTools.getEnvVariable("TYPEORM_CONNECTION"),
|
||||
url: PlatformTools.getEnvVariable("TYPEORM_URL"),
|
||||
host: PlatformTools.getEnvVariable("TYPEORM_HOST"),
|
||||
port: PlatformTools.getEnvVariable("TYPEORM_PORT"),
|
||||
username: PlatformTools.getEnvVariable("TYPEORM_USERNAME"),
|
||||
password: PlatformTools.getEnvVariable("TYPEORM_PASSWORD"),
|
||||
database: PlatformTools.getEnvVariable("TYPEORM_DATABASE"),
|
||||
sid: PlatformTools.getEnvVariable("TYPEORM_SID"),
|
||||
extra: PlatformTools.getEnvVariable("TYPEORM_DRIVER_EXTRA") ? JSON.parse(PlatformTools.getEnvVariable("TYPEORM_DRIVER_EXTRA")) : undefined,
|
||||
autoSchemaSync: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_AUTO_SCHEMA_SYNC")),
|
||||
entities: PlatformTools.getEnvVariable("TYPEORM_ENTITIES") ? PlatformTools.getEnvVariable("TYPEORM_ENTITIES").split(",") : [],
|
||||
subscribers: PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS") ? PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS").split(",") : [],
|
||||
entitySchemas: PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS") ? PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS").split(",") : [],
|
||||
logging: {
|
||||
logQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_QUERIES")),
|
||||
logFailedQueryError: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_FAILED_QUERIES")),
|
||||
logOnlyFailedQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_ONLY_FAILED_QUERIES")),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
59
src/connection/options-reader/ConnectionOptionsXmlReader.ts
Normal file
59
src/connection/options-reader/ConnectionOptionsXmlReader.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import * as fs from "fs";
|
||||
import {PlatformTools} from "../../platform/PlatformTools";
|
||||
import {ConnectionOptions} from "../ConnectionOptions";
|
||||
|
||||
/**
|
||||
* Reads connection options defined in the xml file.
|
||||
*/
|
||||
export class ConnectionOptionsXmlReader {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reads connection options from given xml file.
|
||||
*/
|
||||
async read(path: string): Promise<ConnectionOptions[]> {
|
||||
const xml = await this.readXml(path);
|
||||
return (xml.connection as any[]).map(connection => {
|
||||
return {
|
||||
name: connection.$.name,
|
||||
type: connection.$.type,
|
||||
url: connection.url ? connection.url[0] : undefined,
|
||||
host: connection.host ? connection.host[0] : undefined,
|
||||
port: connection.port && connection.port[0] ? parseInt(connection.port[0]) : undefined,
|
||||
username: connection.username ? connection.username[0] : undefined,
|
||||
password: connection.password ? connection.password[0] : undefined,
|
||||
database: connection.database ? connection.database[0] : undefined,
|
||||
sid: connection.sid ? connection.sid[0] : undefined,
|
||||
extra: connection.extra ? connection.extra[0] : undefined,
|
||||
autoSchemaSync: connection.autoSchemaSync ? connection.autoSchemaSync[0] : undefined,
|
||||
entities: connection.entities ? connection.entities[0].entity : [],
|
||||
subscribers: connection.subscribers ? connection.subscribers[0].entity : [],
|
||||
entitySchemas: connection.entitySchemas ? connection.entitySchemas[0].entity : [],
|
||||
logging: {
|
||||
logQueries: connection.logging && connection.logging[0].logQueries ? connection.logging[0].logQueries[0] : undefined,
|
||||
logFailedQueryError: connection.logging && connection.logging[0].logFailedQueryError ? connection.logging[0].logFailedQueryError[0] : undefined,
|
||||
logOnlyFailedQueries: connection.logging && connection.logging[0].logOnlyFailedQueries ? connection.logging[0].logOnlyFailedQueries[0] : undefined,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reads xml file contents and returns them in a promise.
|
||||
*/
|
||||
protected readXml(path: string): Promise<any> {
|
||||
const xmlParser = PlatformTools.load("xml2js").parseString;
|
||||
const xmlOptions = { trim: true, explicitRoot: false };
|
||||
return new Promise((ok, fail) => {
|
||||
xmlParser(fs.readFileSync(path), xmlOptions, (err: any, result: any) => err ? fail(err) : ok(result));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
25
src/connection/options-reader/ConnectionOptionsYmlReader.ts
Normal file
25
src/connection/options-reader/ConnectionOptionsYmlReader.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import * as fs from "fs";
|
||||
import {PlatformTools} from "../../platform/PlatformTools";
|
||||
import {ConnectionOptions} from "../ConnectionOptions";
|
||||
|
||||
/**
|
||||
* Reads connection options defined in the yml file.
|
||||
*/
|
||||
export class ConnectionOptionsYmlReader {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reads connection options from given yml file.
|
||||
*/
|
||||
read(path: string): ConnectionOptions[] {
|
||||
const ymlParser = PlatformTools.load("js-yaml");
|
||||
const config = ymlParser.safeLoad(fs.readFileSync(path));
|
||||
return Object.keys(config).map(connectionName => {
|
||||
return Object.assign({ name: connectionName }, config[connectionName]);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
148
src/index.ts
148
src/index.ts
@ -12,6 +12,7 @@ import {EntityManager} from "./entity-manager/EntityManager";
|
||||
import {PlatformTools} from "./platform/PlatformTools";
|
||||
import {TreeRepository} from "./repository/TreeRepository";
|
||||
import {MongoRepository} from "./repository/MongoRepository";
|
||||
import {ConnectionOptionsReader} from "./connection/ConnectionOptionsReader";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Commonly Used exports
|
||||
@ -135,106 +136,29 @@ export function getConnectionManager(): ConnectionManager {
|
||||
/**
|
||||
* 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 your custom ormconfig.json.
|
||||
*
|
||||
* 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", "postgres", "mariadb", "sqlite", "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 sqlite 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.
|
||||
* If connection options were not specified, then it will try to create connection automatically,
|
||||
* based on content of ormconfig (json/js/yml/xml/env) file or environment variables.
|
||||
* Only one connection from ormconfig will be created (name "default" or connection without name).
|
||||
*/
|
||||
export function createConnection(): Promise<Connection>;
|
||||
export async function createConnection(options?: ConnectionOptions): Promise<Connection> {
|
||||
if (!options)
|
||||
options = await new ConnectionOptionsReader().get("default");
|
||||
|
||||
/**
|
||||
* Creates connection from the given connection options and registers it in the manager.
|
||||
*/
|
||||
export function createConnection(options?: ConnectionOptions): Promise<Connection>;
|
||||
|
||||
/**
|
||||
* Creates connection with the given connection name from the ormconfig.json file and registers it in the manager.
|
||||
* Optionally you can specify a path to custom ormconfig.json file.
|
||||
*/
|
||||
export function createConnection(connectionNameFromConfig: string, ormConfigPath?: string): Promise<Connection>;
|
||||
|
||||
/**
|
||||
* Creates connection and and registers it in the manager.
|
||||
*/
|
||||
export function createConnection(optionsOrConnectionNameFromConfig?: ConnectionOptions|string, ormConfigPath?: string): Promise<Connection> {
|
||||
return getConnectionManager().createAndConnect(optionsOrConnectionNameFromConfig as any, ormConfigPath);
|
||||
return getConnectionManager().create(options).connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new connections and registers them in the manager.
|
||||
*
|
||||
* If array of connection options were not specified, then it will try to create them automatically
|
||||
* from ormconfig.json. You can also specify path to your custom ormconfig.json.
|
||||
*
|
||||
* 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", "postgres", "mariadb", "sqlite", "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 sqlite 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.
|
||||
* If connection options were not specified, then it will try to create connection automatically,
|
||||
* based on content of ormconfig (json/js/yml/xml/env) file or environment variables.
|
||||
* All connections from the ormconfig will be created.
|
||||
*/
|
||||
export function createConnections(): Promise<Connection[]>;
|
||||
export async function createConnections(options?: ConnectionOptions[]): Promise<Connection[]> {
|
||||
if (!options)
|
||||
options = await new ConnectionOptionsReader().all();
|
||||
|
||||
/**
|
||||
* Creates connections from the given connection options and registers them in the manager.
|
||||
*/
|
||||
export function createConnections(options?: ConnectionOptions[]): Promise<Connection[]>;
|
||||
|
||||
/**
|
||||
* Creates connection with the given connection name from the ormconfig.json file and registers it in the manager.
|
||||
* Optionally you can specify a path to custom ormconfig.json file.
|
||||
*/
|
||||
export function createConnections(ormConfigPath?: string): Promise<Connection[]>;
|
||||
|
||||
/**
|
||||
* Creates connections and and registers them in the manager.
|
||||
*/
|
||||
export function createConnections(optionsOrOrmConfigFilePath?: ConnectionOptions[]|string): Promise<Connection[]> {
|
||||
return getConnectionManager().createAndConnectToAll(optionsOrOrmConfigFilePath as any);
|
||||
return Promise.all(options.map(options => getConnectionManager().create(options).connect()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,50 +180,20 @@ export function getEntityManager(connectionName: string = "default"): EntityMana
|
||||
/**
|
||||
* Gets repository for the given entity class.
|
||||
*/
|
||||
export function getRepository<Entity>(entityClass: ObjectType<Entity>, connectionName?: string): Repository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets repository for the given entity name.
|
||||
*/
|
||||
export function getRepository<Entity>(entityName: string, connectionName?: string): Repository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets repository for the given entity class or name.
|
||||
*/
|
||||
export function getRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, connectionName: string = "default"): Repository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getRepository<Entity>(entityClassOrName as any);
|
||||
export function getRepository<Entity>(entityClass: ObjectType<Entity>|string, connectionName: string = "default"): Repository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getRepository<Entity>(entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class.
|
||||
*/
|
||||
export function getTreeRepository<Entity>(entityClass: ObjectType<Entity>, connectionName?: string): TreeRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity name.
|
||||
*/
|
||||
export function getTreeRepository<Entity>(entityName: string, connectionName?: string): TreeRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class or name.
|
||||
*/
|
||||
export function getTreeRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, connectionName: string = "default"): TreeRepository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getTreeRepository<Entity>(entityClassOrName as any);
|
||||
export function getTreeRepository<Entity>(entityClass: ObjectType<Entity>|string, connectionName: string = "default"): TreeRepository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getTreeRepository<Entity>(entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets mongodb repository for the given entity class.
|
||||
*/
|
||||
export function getMongoRepository<Entity>(entityClass: ObjectType<Entity>, connectionName?: string): MongoRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets mongodb repository for the given entity name.
|
||||
*/
|
||||
export function getMongoRepository<Entity>(entityName: string, connectionName?: string): MongoRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets mongodb repository for the given entity class or name.
|
||||
*/
|
||||
export function getMongoRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, connectionName: string = "default"): MongoRepository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getMongoRepository<Entity>(entityClassOrName as any);
|
||||
export function getMongoRepository<Entity>(entityClass: ObjectType<Entity>|string, connectionName: string = "default"): MongoRepository<Entity> {
|
||||
return getConnectionManager().get(connectionName).getMongoRepository<Entity>(entityClass);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ describe("ConnectionManager", () => {
|
||||
|
||||
});
|
||||
|
||||
describe("createAndConnect", function() {
|
||||
/*describe("createAndConnect", function() {
|
||||
|
||||
it("should create a mysql connection when mysql driver is specified AND connect to it", async () => {
|
||||
const options: ConnectionOptions = setupSingleTestingConnection("mysql", {
|
||||
@ -69,7 +69,7 @@ describe("ConnectionManager", () => {
|
||||
await connection.close();
|
||||
});
|
||||
|
||||
/* it("should create a postgres connection when postgres driver is specified AND connect to it", async () => {
|
||||
/!* it("should create a postgres connection when postgres driver is specified AND connect to it", async () => {
|
||||
const options: ConnectionOptions = {
|
||||
name: "myPostgresConnection",
|
||||
driver: createTestingConnectionOptions("postgres")
|
||||
@ -80,9 +80,9 @@ describe("ConnectionManager", () => {
|
||||
connection.driver.should.be.instanceOf(PostgresDriver);
|
||||
connection.isConnected.should.be.true;
|
||||
await connection.close();
|
||||
});*/
|
||||
});*!/
|
||||
|
||||
});
|
||||
});*/
|
||||
|
||||
describe("get", function() {
|
||||
|
||||
@ -121,13 +121,13 @@ describe("ConnectionManager", () => {
|
||||
const connectionManager = new ConnectionManager();
|
||||
|
||||
// create connection, save post and close connection
|
||||
let connection = await connectionManager.createAndConnect(options);
|
||||
let connection = await connectionManager.create(options).connect();
|
||||
const post = new Post(1, "Hello post");
|
||||
await connection.manager.save(post);
|
||||
await connection.close();
|
||||
|
||||
// recreate connection and find previously saved post
|
||||
connection = await connectionManager.createAndConnect(options);
|
||||
connection = await connectionManager.create(options).connect();
|
||||
const loadedPost = (await connection.manager.findOneById(Post, 1))!;
|
||||
loadedPost.should.be.instanceof(Post);
|
||||
loadedPost.should.be.eql({ id: 1, title: "Hello post" });
|
||||
@ -144,13 +144,13 @@ describe("ConnectionManager", () => {
|
||||
const connectionManager = new ConnectionManager();
|
||||
|
||||
// create connection, save post and close connection
|
||||
let connection = await connectionManager.createAndConnect(options);
|
||||
let connection = await connectionManager.create(options).connect();
|
||||
const post = new Post(1, "Hello post");
|
||||
await connection.manager.save(post);
|
||||
await connection.close();
|
||||
|
||||
// recreate connection and find previously saved post
|
||||
connection = await connectionManager.createAndConnect(options);
|
||||
connection = await connectionManager.create(options).connect();
|
||||
const loadedPost = await connection.manager.findOneById(Post, 1);
|
||||
expect(loadedPost).to.be.undefined;
|
||||
await connection.close();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user