import * as async from "async" ; import { Collection , MongoClient , Db } from "mongodb" ; import { NamingStrategy , NamingStrategies } from "./namingStrategies" ; import { ResultCallback } from "../core/callback" ; import { MappingRegistry } from "../mapping/mappingRegistry" ; import { ChangeTrackingType } from "../mapping/mappingModel" ; import { Table } from "../core/table" ; import { MappingModel , PropertyConverter } from "../mapping/mappingModel" ; import { SessionFactory , SessionFactoryImpl } from "../sessionFactory" ; import { EntityMapping } from "../mapping/entityMapping" ; import { ObjectIdGenerator } from "./objectIdGenerator" ; import { ClassMapping } from "../mapping/classMapping" ; import { PersistenceError } from "../persistenceError" ; /**
 * Specifies default settings used to create the [[SessionFactory]].
 */ export class Configuration { /**
     * The default database name to use.
     */ databaseName : string ; /**
     * Default identity generator to use.
     */ identityGenerator : IdentityGenerator = new ObjectIdGenerator ( ) ; /**
     * True if entities are versioned by default; otherwise, false.
     */ versioned = true ; /**
     * True if null values should be saved for properties by default; otherwise, false.
     */ nullable = false ; /**
     * Default field name to use for optimistic locking.
     */ versionField = "__v" ; /**
     * Default field name to use for the class discriminator.
     */ discriminatorField = "__t" ; /**
     * Default change tracking strategy to use.
     */ changeTracking = ChangeTrackingType . DeferredImplicit ; /**
     * If specified, prefix to add to all collection names.
     */ collectionPrefix : string ; /**
     * Naming strategy to use for collection names.
     */ collectionNamingStrategy : NamingStrategy = NamingStrategies . CamelCase ; /**
     * Naming strategy to use for field names.
     */ fieldNamingStrategy : NamingStrategy = NamingStrategies . CamelCase ; /**
     * Naming strategy to use for the discriminator value of a class.
     */ discriminatorNamingStrategy : NamingStrategy = NamingStrategies . None ; /**
     * Named property converters.
     */ propertyConverters : { [ name ] : PropertyConverter ; } = { } ; /**
     * A logger that conforms for the [bunyan](https://www.npmjs.com/package/bunyan) logger interface. If specified, all executed queries
     * and other debug information will be logged using the TRACE logging level.
     */ logger : Logger ; /**
     * Indicates if any missing indexes should be created when the [[SessionFactory]] is created. This is turned off by default.
     */ createIndexes : boolean ; hidden private _mappings : MappingProvider [ ] = [ ] ; param mapping addMapping ( mapping ) { this . _mappings . push ( mapping ) ; } param connection param callback createSessionFactory ( connection , callback ) ; param connection param databaseName param callback createSessionFactory ( connection , databaseName , callback ) ; createSessionFactory ( connection , callbackOrDatabaseName , callback ? ) { var registry = new MappingRegistry ( ) , databaseName ; if ( typeof callbackOrDatabaseName === "function" ) { callback = callbackOrDatabaseName ; } else { databaseName = callbackOrDatabaseName ; } if ( ! this . _mappings || this . _mappings . length == 0 ) { return callback ( new PersistenceError ( "No mappings were added to the configuration." ) ) ; } async . each ( this . _mappings , ( provider , done ) => { provider . getMapping ( this , ( err , r ) => { if ( err ) return done ( err ) ; registry . addMappings ( < ClassMapping [ ] > r ) ; done ( ) ; } ) ; } , ( err ) => { if ( err ) return callback ( err ) ; this . _buildCollections ( connection , databaseName , registry , ( err , collections ) => { if ( err ) return callback ( err ) ; let factory = new SessionFactoryImpl ( connection , collections , registry ) ; factory . logger = this . logger ; if ( ! this . createIndexes ) { callback ( null , factory ) ; } else { factory . createIndexes ( ( err ) => { if ( err ) return callback ( err ) ; callback ( null , factory ) ; } ) ; } } ) ; } ) ; } hidden private _buildCollections ( connection , databaseName , registry , callback ) { var collections = [ ] ; var namesSeen = new Map < string , boolean > ( ) ; async . each ( registry . getEntityMappings ( ) , ( mapping , done ) => { if ( ! ( mapping . flags & MappingModel . MappingFlags . InheritanceRoot ) ) { process . nextTick ( done ) ; return ; } if ( ! mapping . collectionName ) { return done ( new PersistenceError ( "Missing collection name on mapping for type '" + mapping . name + "'." ) ) ; } var dbName = mapping . databaseName || databaseName || this . databaseName ; if ( ! dbName ) { return done ( new Error ( `Could not determine database name for '${ mapping . collectionName }'. Please make sure to specify ` + "the database name in either the Configuration, the call to createSessionFactory, or the @Collection decorator." ) ) ; } var key = dbName + "/" + mapping . collectionName ; if ( namesSeen . has ( key ) ) { return done ( new PersistenceError ( "Duplicate collection name '" + key + "' on type '" + mapping . name + "' ." ) ) ; } namesSeen . set ( key , true ) ; var db = connection . db ( dbName ) ; db . listCollections ( { name : mapping . collectionName } ) . toArray ( ( err , names ) : void => { if ( err ) return done ( err ) ; if ( names . length == 0 ) { db . createCollection ( mapping . collectionName , mapping . collectionOptions || { } , ( err , collection ) => { if ( err ) return done ( err ) ; collections [ mapping . id ] = collection ; process . nextTick ( done ) ; } ) ; } else { db . collection ( mapping . collectionName , { strict : true } , ( err , collection ) => { if ( err ) return done ( err ) ; collections [ mapping . id ] = collection ; process . nextTick ( done ) ; } ) ; } } ) ; } , ( err ) => { if ( err ) return callback ( err ) ; callback ( null , collections ) ; } ) ; } } export interface IdentityGenerator { generate ( ) : any ; fromString ( text ) : any ; validate ( value ) : boolean ; areEqual ( first , second ) : boolean ; } /**
 * Describes a type that is able to convert an entity or embeddable property value to a MongoDB document field and back.
 *
 * ### Example
 *
 * The example below defines a PropertyConverter that converts an instance of a Point class to a string.
 * ```typescript
 *  class PointConverter implements PropertyConverter {
 *
 *      convertToDocumentField(property: any): any {
 *          if(property instanceof Point) {
 *              return [property.x, property.y].join(",");
 *          }
 *      }
 *
 *      convertToObjectProperty(field: any): any {
 *          if(typeof field === "string") {
 *              var parts = field.split(",");
 *              return new Point(parts[0], parts[1]);
 *         }
 *      }
 *  }
 *  ```
 */ export interface PropertyConverter { param property convertToDocumentField ( property ) : any ; param field convertToObjectProperty ( field ) : any ; param field1 param field2 areEqual ( field1 , field2 ) : boolean ; } /**
 * Provides data mappings to the Configuration.
 */ export interface MappingProvider { param config param callback getMapping ( config , callback ) : void ; } /**
 * A logger that conforms for the [bunyan](https://www.npmjs.com/package/bunyan) logger interface.
 */ export interface Logger { param options child ( options ) : Logger ; param error param msg trace ( error , msg ? , ... args ) : void ; param fields param msg trace ( fields , msg ? , ... args ) : void ; param msg trace ( msg , ... params ) : void ; param error param msg debug ( error , msg ? , ... args ) : void ; param fields param msg debug ( fields , msg ? , ... args ) : void ; param msg debug ( msg , ... args ) : void ; param error param msg info ( error , msg ? , ... args ) : void ; param fields param msg info ( fields , msg ? , ... args ) : void ; param msg info ( msg , ... args ) : void ; param error param msg warn ( error , msg ? , ... args ) : void ; param fields param msg warn ( fields , msg ? , ... args ) : void ; param msg warn ( msg , ... args ) : void ; param error param msg error ( error , msg ? , ... args ) : void ; param fields param msg error ( fields , msg ? , ... args ) : void ; param msg error ( msg , ... args ) : void ; param error param msg fatal ( error , msg ? , ... args ) : void ; param fields param msg fatal ( fields , msg ? , ... args ) : void ; param msg fatal ( msg , ... args ) : void ; } /**
 * Logger options.
 */ export interface LoggerOptions { /**
     * Dictionary of custom serializers. The key is the name of the property that is serialized and the the value
     * is a function that takes an object and returns a JSON serializable value.
     */ serializers ? : { [ key ] : ( input : any ) => any ; } ; }