Skip to content

Commit

Permalink
Restructuring and a massive amount of extra documentation for TypeDoc
Browse files Browse the repository at this point in the history
  • Loading branch information
notheotherben committed Aug 30, 2015
1 parent d92fce4 commit 5d05863
Show file tree
Hide file tree
Showing 21 changed files with 552 additions and 56 deletions.
7 changes: 7 additions & 0 deletions lib/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ import {Cache} from './Cache';
import {NoOpCache} from './caches/NoOpCache';
import {MemoryCache} from './caches/MemoryCache';

/**
* The Iridium Core, responsible for managing the connection to the database as well
* as any plugins you are making use of.
*
* Generally you will subclass this to provide your own custom core with the models you
* make use of within your application.
*/
export class Core {
/**
* Creates a new Iridium Core instance connected to the specified MongoDB instance
Expand Down
9 changes: 8 additions & 1 deletion lib/Cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import MongoDB = require('mongodb');
import Bluebird = require('bluebird');
import * as Index from './Index';

export default class Cursor<TDocument extends { _id?: any }, TInstance> {
/**
* An Iridium collection cursor which allows the itteration through documents
* in the collection, automatically wrapping them in the correct instance type.
*
* @param TDocument The interface representing the collection's documents
* @param TInstance The interface or class used to represent the wrapped documents.
*/
export class Cursor<TDocument extends { _id?: any }, TInstance> {
/**
* Creates a new Iridium cursor which wraps a MongoDB cursor object
* @param {Model} model The Iridium model that this cursor belongs to
Expand Down
63 changes: 63 additions & 0 deletions lib/Decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,69 @@ import {Index, IndexSpecification} from './Index';
import {Schema} from './Schema';
import {InstanceImplementation} from './InstanceInterface';

/**
* Specifies the name of the collection to which this instance's documents should be sent.
* @param name The name of the MongoDB collection to store the documents in.
*
* This decorator replaces the use of the static collection property on instance implementation
* classes. If your transpiler does not support decorators then you are free to make use of the
* property instead.
*/
export function Collection(name: string) {
return function(target: InstanceImplementation<any, any>) {
target.collection = name;
};
}

/**
* Specifies a MongoDB collection level index to be managed by Iridium for this instance type.
* More than one instance of this decorator may be used if you wish to specify multiple indexes.
* @param spec The formal index specification which defines the properties and ordering used in the index.
* @param options The options dictating the way in which the index behaves.
*
* This decorator replaces the use of the static indexes property on instance implementation
* classes. If your transpiler does not support decorators then you are free to make use of the
* property instead.
*/
export function Index(spec: IndexSpecification, options?: MongoDB.IndexOptions) {
return function(target: InstanceImplementation<any,any>) {
target.indexes = (target.indexes || []).concat(<Index>{ spec: spec, options: options || {} });
}
}

/**
* Specifies a custom validator to be made available for this collection's schema.
* More than one instance of this decorator may be used if you wish to specify multiple validators.
* @param forType The value in the schema which will be delegated to this function for validation.
* @param validate A function which calls this.assert(condition) to determine whether a schema node is valid or not.
*
* This decorator replaces the use of the static validators property on instance implementation
* classes. If your transpiler does not support decorators then you are free to make use of the
* property instead.
*/
export function Validate(forType: any, validate: (schema: any, data: any, path: string) => Skmatc.Result) {
return function(target: InstanceImplementation<any,any>) {
target.validators = (target.validators || []).concat(skmatc.create(schema => schema === forType, validate));
}
}

/**
* Specifies the schema type for the property this decorator is applied to. This can be used to replace the
* static schema property on your instance. Multiple instances of this decorator can be applied, but no more
* than one per property.
*
* @param asType The schema validation type to make use of for this property
* @param required Whether this property is required to have a value or not, defaults to true.
*/
export function Property(asType: any, required?: boolean): (target: { constructor: Function }, name: string) => void;
/**
* Specifies the schema type for a property with the given name on the class this decorator is applied to. This
* can either compliment or replace the static schema property on your instance class.
*
* @param name The name of the property that is being targetted
* @param asType The schema validation type to make use of for this property
* @param required Whether this property is required to have a value or not, defaults to true.
*/
export function Property(name: string, asType: any, required?: boolean): (target: Function) => void;
export function Property(...args: any[]): (target: any, name?: string) => void {
let name = null,
Expand All @@ -49,6 +93,17 @@ export function Property(...args: any[]): (target: any, name?: string) => void {
}
}

/**
* Specifies a custom transform to be applied to the property this decorator is applied to.
*
* @param fromDB The function used to convert values from the database for the application.
* @param toDB The function used to convert values from the application to the form used in the database.
*
* This decorator can either compliment or replace the static transforms property on your instance
* class, however only one transform can be applied to any property at a time.
* If your transpiler does not support decorators then you are free to make use of the
* property instead.
*/
export function Transform(fromDB: (value: any) => any, toDB: (value: any) => any) {
return function(target: any, property: string) {
target.constructor.transforms = _.clone(target.constructor.transforms || {})
Expand All @@ -59,6 +114,14 @@ export function Transform(fromDB: (value: any) => any, toDB: (value: any) => any
};
}


/**
* Specifies that this property should be treated as an ObjectID, with the requisite validator and transforms.
*
* This decorator applies an ObjectID validator to the property, which ensures that values sent to the database
* are instances of the MongoDB ObjectID type, as well as applying a transform operation which converts ObjectIDs
* to strings for your application, and then converts strings back to ObjectIDs for the database.
*/
export function ObjectID(target: { constructor: typeof Instance }, name: string) {
Property(MongoDB.ObjectID)(target, name);
Transform(
Expand Down
45 changes: 45 additions & 0 deletions lib/General.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,66 @@
/// <reference path="../_references.d.ts" />

/**
* A method which is called once an asynchronous operation has completed, an alternative
* to using Promises.
* @param T The type of object returned by the asynchronous operation.
*/
export interface Callback<T> {
/**
* @param err The error object, if one occurred, otherwise null if the operation completed successfully.
* @param object The result of the asynchronous operation if it completed successfully. If err is defined, the presence of this value is unknown.
*/
(err: Error, object?: T): void;
}

/**
* A method which is used to determine whether a value within a collection meets a set of criteria.
* @param T The type of item in the collection.
*/
export interface Predicate<T> {
/**
* @param object The value of the item in the collection
* @param key The key, if one is available, under which the item appeared within the collection
* @returns A true-y value if the item met the predicate conditions, false-y values if it did not.
*/
(object: T, key?: string): boolean;
}

/**
* A method which is called to retrieve a value of the given type.
* @param T The type of value to be retrieved.
*/
export interface PropertyGetter<T> {
/**
* Gets the current value of the property
* @returns The current value
*/
(): T;
}

/**
* A method which is called to set a value of the given type.
* @param T The type of value to set
*/
export interface PropertySetter<T> {
/**
* Sets the value to the provided one
* @param value The new value to set
*/
(value: T): void;
}

/**
* A compound property which provides either a getter, setter or both.
* @param T The type of objects stored in the property
*/
export interface Property<T> {
/**
* An optional getter which can be used to retrieve the property's value
*/
get?: PropertyGetter<T>;
/**
* An optional setter which can be used to set the property's value
*/
set?: PropertySetter<T>;
}
103 changes: 76 additions & 27 deletions lib/Instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,35 @@ import * as General from './General';
import * as ModelInterfaces from './ModelInterfaces';
import * as Index from './Index';
import {Schema} from './Schema';
import {Transforms} from './Transforms';

import _ = require('lodash');
import MongoDB = require('mongodb');
import Bluebird = require('bluebird');
import skmatc = require('skmatc');

/**
* The default Iridium Instance implementation which provides methods for saving, refreshing and
* removing the wrapped document from the collection, as well as integrating with Omnom, our
* built in document diff processor which allows clean, atomic, document updates to be performed
* without needing to write the update queries yourself.
*
* @param TDocument The interface representing the structure of the documents in the collection.
* @param TInstance The type of instance which wraps the documents, generally the subclass of this class.
*
* This class will be subclassed automatically by Iridium to create a model specific instance
* which takes advantage of some of v8's optimizations to boost performance significantly.
* The instance returned by the model, and all of this instance's methods, will be of type
* TInstance - which should represent the merger of TSchema and IInstance for best results.
*/
export class Instance<TDocument extends { _id?: any }, TInstance> {
/**
* Creates a new instance which represents the given document as a type of model
* @param {model.Model} model The model that the document represents
* @param {TSchema} document The document which should be wrapped by this instance
* @param {Boolean} isNew Whether the document is new (doesn't exist in the database) or not
* @param {Boolean} isPartial Whether the document has only a subset of its fields populated
* @description
* This class will be subclassed automatically by Iridium to create a model specific instance
* which takes advantage of some of v8's optimizations to boost performance significantly.
* The instance returned by the model, and all of this instance's methods, will be of type
* TInstance - which should represent the merger of TSchema and IInstance for best results.
* @param model The model that dictates the collection the document originated from as well as how validations are performed.
* @param document The document which should be wrapped by this instance
* @param isNew Whether the document is new (doesn't exist in the database) or not
* @param isPartial Whether the document has only a subset of its fields populated
*
*/
constructor(model: Model<TDocument, TInstance>, document: TDocument, isNew: boolean = true, isPartial: boolean = false) {
this._model = model;
Expand Down Expand Up @@ -54,34 +65,72 @@ export class Instance<TDocument extends { _id?: any }, TInstance> {

[name: string]: any;

/**
* A function which is called whenever a new document is in the process of being inserted into the database.
* @param document The document which will be inserted into the database.
*/
static onCreating: (document: { _id?: any }) => void;

/**
* A function which is called whenever a document of this type is received from the database, prior to it being
* wrapped by an Instance object.
* @param document The document that was retrieved from the database.
*/
static onRetrieved: (document: { _id?: any }) => void;

/**
* A function which is called whenever a new instance has been created to wrap a document.
* @param instance The instance which has been created.
*/
static onReady: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>) => void;

/**
* A function which is called whenever an instance's save() method is called to allow you to interrogate and/or manipulate
* the changes which are being made.
*
* @param instance The instance to which the changes are being made
* @param changes The MongoDB change object describing the changes being made to the document.
*/
static onSaving: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>, changes: any) => void;

/**
* The name of the collection into which documents of this type are stored.
*/
static collection: string;

/**
* The schema used to validate documents of this type before being stored in the database.
*/
static schema: Schema = {
_id: false
};

/**
* Additional which should be made available for use in the schema definition for this instance.
*/
static validators: Skmatc.Validator[] = [
skmatc.create(schema => schema === MongoDB.ObjectID, function(schema, data) {
return this.assert(!data || data instanceof MongoDB.ObjectID || (data._bsontype === 'ObjectID' && data.id));
}, { name: 'ObjectID validation' })
];

static transforms: { [property: string]: { fromDB: (value: any) => any; toDB: (value: any) => any; } } = {
/**
* The transformations which should be applied to properties of documents of this type.
*/
static transforms: Transforms = {

};

/**
* The cache director used to derive unique cache keys for documents of this type.
*/
static cache: CacheDirector;

/**
* The indexes which should be managed by Iridium for the collection used by this type.
*/
static indexes: (Index.Index | Index.IndexSpecification)[] = [];
static identifier: {
apply(fromSource: any): any;
reverse(toSource: any): any;
};


/**
* Saves any changes to this instance, using the built in diff algorithm to write the update query.
* @param {function(Error, IInstance)} callback A callback which is triggered when the save operation completes
Expand Down Expand Up @@ -269,16 +318,16 @@ export class Instance<TDocument extends { _id?: any }, TInstance> {

/**
* Retrieves the first element in an enumerable collection which matches the predicate
* @param {any[]} collection The collection from which to retrieve the element
* @param {function(any, Number): Boolean} predicate The function which determines whether to select an element
* @returns {any}
* @param collection The collection from which to retrieve the element
* @param predicate The function which determines whether to select an element
* @returns The first element in the array which matched the predicate.
*/
first<T>(collection: T[], predicate: General.Predicate<T>): T;
/**
* Retrieves the first element in an enumerable collection which matches the predicate
* @param {Object} collection The collection from which to retrieve the element
* @param {function(any, String): Boolean} predicate The function which determines whether to select an element
* @returns {any}
* @param collection The collection from which to retrieve the element
* @param predicate The function which determines whether to select an element
* @returns The first element in the object which matched the predicate.
*/
first<T>(collection: { [key: string]: T }, predicate: General.Predicate<T>): T;
first<T>(collection: T[]| { [key: string]: T }, predicate: General.Predicate<T>): T {
Expand All @@ -296,16 +345,16 @@ export class Instance<TDocument extends { _id?: any }, TInstance> {

/**
* Retrieves a number of elements from an enumerable collection which match the predicate
* @param {any[]} collection The collection from which elements will be plucked
* @param {function(any, Number): Boolean} predicate The function which determines the elements to be plucked
* @returns {any[]}
* @param collection The collection from which elements will be plucked
* @param predicate The function which determines the elements to be plucked
* @returns A new array containing the elements in the array which matched the predicate.
*/
select<T>(collection: T[], predicate: General.Predicate<T>): T[];
/**
* Retrieves a number of elements from an enumerable collection which match the predicate
* @param {Object} collection The collection from which elements will be plucked
* @param {function(any, String): Boolean} predicate The function which determines the elements to be plucked
* @returns {Object}
* @param collection The collection from which elements will be plucked
* @param predicate The function which determines the elements to be plucked
* @returns An object with the properties from the collection which matched the predicate.
*/
select<T>(collection: { [key: string]: T }, predicate: General.Predicate<T>): { [key: string]: T };
select<T>(collection: T[]| { [key: string]: T }, predicate: General.Predicate<T>): any {
Expand Down
Loading

0 comments on commit 5d05863

Please sign in to comment.