Skip to content

Commit

Permalink
Promises support in hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
louy authored and notheotherben committed Nov 17, 2015
1 parent 0a8ee18 commit 2dabf54
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 19 deletions.
9 changes: 5 additions & 4 deletions lib/Hooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import instance = require('./Instance');
import Bluebird = require('bluebird');

export interface Hooks<TDocument, TInstance> {
onCreating? (document: TDocument): void;
onRetrieved? (document: TDocument): void;
onReady? (instance: TInstance): void;
onSaving? (instance: TInstance, changes: any): void;
onCreating? (document: TDocument): Promise.Thenable<void> | void;
onRetrieved? (document: TDocument): Promise.Thenable<void> | void;
onReady? (instance: TInstance): Promise.Thenable<void> | void;
onSaving? (instance: TInstance, changes: any): Promise.Thenable<void> | void;
}
8 changes: 4 additions & 4 deletions lib/Instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@ export class Instance<TDocument extends { _id?: any }, TInstance> {
* 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;
static onCreating: (document: { _id?: any }) => Promise.Thenable<void> | 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;
static onRetrieved: (document: { _id?: any }) => Promise.Thenable<void> | 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;
static onReady: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>) => Promise.Thenable<void> | void;

/**
* A function which is called whenever an instance's save() method is called to allow you to interrogate and/or manipulate
Expand All @@ -90,7 +90,7 @@ export class Instance<TDocument extends { _id?: any }, TInstance> {
* @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;
static onSaving: (instance: Instance<{ _id?: any }, Instance<{ _id?: any }, any>>, changes: any) => Promise.Thenable<void> | void;

/**
* The name of the collection into which documents of this type are stored.
Expand Down
8 changes: 4 additions & 4 deletions lib/InstanceInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,26 @@ export interface InstanceImplementation<TDocument extends { _id ?: any }, TInsta
* An optional method which will be called whenever a document is about to be inserted into the database,
* allowing you to set default values and do any preprocessing you wish prior to the document being inserted.
*/
onCreating? (document: TDocument): void;
onCreating? (document: TDocument): Promise.Thenable<void> | void;

/**
* An optional method which is called whenever a new document is received from the model's collection and
* prior to the document being wrapped, can be used to perform preprocessing if necessary - however we recommend
* you rather make use of transforms for that task.
*/
onRetrieved? (document: TDocument): void;
onRetrieved? (document: TDocument): Promise.Thenable<void> | void;

/**
* An optional method which is called whenever a new document for this model has been wrapped in an instance.
*/
onReady? (instance: TInstance): void;
onReady? (instance: TInstance): Promise.Thenable<void> | void;

/**
* An optional method which is called prior to saving an instance, it is provided with the instance itself as
* well as the proposed changes to the instance. This allows you to make additional changes, such as updating
* a lastChanged property on the document, or abort changes by throwing an error.
*/
onSaving? (instance: TInstance, changes: any): void;
onSaving? (instance: TInstance, changes: any): Promise.Thenable<void> | void;

/**
* The cache controller used to determine whether a document may be cached, as well as deriving a unique cache
Expand Down
17 changes: 10 additions & 7 deletions lib/ModelHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,22 @@ export class ModelHandlers<TDocument extends { _id?: any }, TInstance> {
partial: false
});

let wrapped: TResult;
return Bluebird.resolve(result).then((target: any) => {
return <Bluebird<TResult>>Bluebird.resolve().then(() => {

// Cache the document if caching is enabled
if (this.model.core.cache && options.cache && !options.fields) {
this.model.cache.set(target); // Does not block execution pipeline - fire and forget
}

// Trigger the received hook
if (this.model.hooks.onRetrieved) this.model.hooks.onRetrieved(target);

if (this.model.hooks.onRetrieved) return this.model.hooks.onRetrieved(target);
}).then(() => {
// Wrap the document and trigger the ready hook
let wrapped: TResult = wrapper(target, false, !!options.fields);
wrapped = wrapper(target, false, !!options.fields);

if (this.model.hooks.onReady && wrapped instanceof this.model.Instance) this.model.hooks.onReady(<TInstance><any>wrapped);
if (this.model.hooks.onReady && wrapped instanceof this.model.Instance) return this.model.hooks.onReady(<TInstance><any>wrapped);
}).then(() => {
return wrapped;
});
});
Expand All @@ -54,7 +55,8 @@ export class ModelHandlers<TDocument extends { _id?: any }, TInstance> {
creatingDocuments(documents: TDocument[]): Bluebird<any[]> {
return Bluebird.all(documents.map((document: any) => {
return Bluebird.resolve().then(() => {
if (this.model.hooks.onCreating) this.model.hooks.onCreating(document);
if (this.model.hooks.onCreating) return this.model.hooks.onCreating(document);
}).then(() => {
document = this.model.helpers.convertToDB(document);
let validation: Skmatc.Result = this.model.helpers.validate(document);
if (validation.failed) return Bluebird.reject(validation.error);
Expand All @@ -66,7 +68,8 @@ export class ModelHandlers<TDocument extends { _id?: any }, TInstance> {

savingDocument(instance: TInstance, changes: any): Bluebird<TInstance> {
return Bluebird.resolve().then(() => {
if (this.model.hooks.onSaving) this.model.hooks.onSaving(instance, changes);
if (this.model.hooks.onSaving) return this.model.hooks.onSaving(instance, changes);
}).then(() => {
return instance;
});
}
Expand Down

0 comments on commit 2dabf54

Please sign in to comment.