-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathModelHandlers.ts
81 lines (71 loc) · 3.48 KB
/
ModelHandlers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import {Core} from "./Core";
import {Schema} from "./Schema";
import {Model} from "./Model";
import {ModelCache} from "./ModelCache";
import * as ModelOptions from "./ModelOptions";
import * as Skmatc from "skmatc";
import * as _ from "lodash";
import * as MongoDB from "mongodb";
import * as Bluebird from "bluebird";
/**
* Provides a number of methods which are used to handle events that occur within
* the Iridium workflow - such as what happens when a document is received from
* the database, or how to handle the creation of new documents and saving of instances.
*
* Mostly this is for cache support, wrapping and hook triggering.
* @internal
*/
export class ModelHandlers<TDocument extends { _id?: any }, TInstance> {
constructor(public model: Model<TDocument, TInstance>) {
}
documentReceived<TResult>(conditions: any,
result: TDocument,
wrapper: (document: TDocument, isNew?: boolean, isPartial?: boolean) => TResult,
options: ModelOptions.QueryOptions = {}): Bluebird<TResult> {
_.defaults(options, {
cache: true,
partial: false
});
let wrapped: TResult;
return Bluebird.resolve(this.model.helpers.transformFromDB(result, { document: true })).then((target: any) => {
return <Bluebird<TResult>>Bluebird
// If onRetrieved returns a Bluebird promise then there is no significant performance overhead here
.resolve(this.model.hooks.onRetrieved && this.model.hooks.onRetrieved(target))
.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
}
// Wrap the document and trigger the ready hook
let wrapped: TResult = wrapper(target, false, !!options.fields);
// Only incur the additional promise's performance penalty if this hook is being used
if (this.model.hooks.onReady)
return Bluebird
.resolve(this.model.hooks.onReady(<TInstance><any>wrapped))
.then(() => wrapped);
return wrapped;
});
});
}
creatingDocuments(documents: TDocument[]): Bluebird<any[]> {
return Bluebird.all(documents.map((document: any) => {
return Bluebird
// If onCreating returns a Bluebird promise then there is no significant performance overhead here
.resolve(this.model.hooks.onCreating && this.model.hooks.onCreating(document))
.then(() => {
document = this.model.helpers.convertToDB(document, { document: true, properties: true });
let validation: Skmatc.Result = this.model.helpers.validate(document);
if (validation.failed) return Bluebird.reject(validation.error);
return document;
});
}));
}
savingDocument(instance: TInstance, changes: any): Bluebird<TInstance> {
return Bluebird
// If onSaving returns a Bluebird promise then there is no significant performance overhead here
.resolve(this.model.hooks.onSaving && this.model.hooks.onSaving(instance, changes))
.then(() => {
return instance;
});
}
}