xpress-mongo
Advanced tools
Comparing version 0.8.0 to 0.9.0
@@ -33,2 +33,3 @@ import { FunctionReturnsBoolean, SchemaPropertiesType, StringToAnyObject, ValidatorType } from "../src/CustomTypes"; | ||
export declare function runAndValidation(value: any, validators: ValidatorType[] | FunctionReturnsBoolean[]): boolean; | ||
export declare function RunInBackground<T = any>(fn: () => void): Promise<void>; | ||
export declare function RunOnEvent(event: string, modelInstance: XMongoModel, changes?: StringToAnyObject): Promise<any>; |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RunOnEvent = exports.runAndValidation = exports.runOrValidation = exports.defaultValue = void 0; | ||
exports.RunOnEvent = exports.RunInBackground = exports.runAndValidation = exports.runOrValidation = exports.defaultValue = void 0; | ||
const Lodash_1 = __importDefault(require("../src/Lodash")); | ||
@@ -69,25 +69,60 @@ /** | ||
exports.runAndValidation = runAndValidation; | ||
function RunInBackground(fn) { | ||
/** | ||
* The `then` of promises are always asynchronous. | ||
* This above with setTimout & setImmediate, we are sure this will run in background. | ||
* without interfering the current process. | ||
*/ | ||
return (new Promise((resolve) => setImmediate(resolve)) | ||
// Run function in setImmediate | ||
.then(fn) | ||
// catch Errors | ||
.catch(console.log)); | ||
} | ||
exports.RunInBackground = RunInBackground; | ||
async function RunOnEvent(event, modelInstance, changes) { | ||
// Get Model | ||
const Model = modelInstance.constructor; | ||
// if model does not have events defined, return false. | ||
if (!Model.events) | ||
return false; | ||
// Get events from Model | ||
let events = Model.events; | ||
// Check if events has defined 'event' | ||
if (!events[event]) | ||
return false; | ||
events = events[event]; | ||
// Get Event | ||
let thisEvent = events[event]; | ||
/** | ||
* if event is watch and no fields in 'changes' object, return false. | ||
*/ | ||
if (event === "watch" && changes && !Object.keys(changes).length) | ||
return false; | ||
if (typeof events === "function") { | ||
await events(modelInstance); | ||
/** | ||
* if type of event === function | ||
* | ||
* Function: All | ||
* Object: events that targets fields | ||
*/ | ||
if (typeof thisEvent === "function") { | ||
if (["watch", "created", "deleted"].includes(event)) { | ||
// noinspection ES6MissingAwait | ||
RunInBackground(() => thisEvent(modelInstance)); | ||
} | ||
else { | ||
await thisEvent(modelInstance); | ||
} | ||
} | ||
else if (typeof events === "object") { | ||
const fields = Object.keys(events); | ||
else if (typeof thisEvent === "object") { | ||
const fields = Object.keys(thisEvent); | ||
for (const field of fields) { | ||
if (event === "watch") { | ||
if (Lodash_1.default.has(changes, field)) { | ||
Promise.all([events[field](modelInstance)]).catch(console.error); | ||
// noinspection ES6MissingAwait | ||
RunInBackground(() => thisEvent[field](modelInstance)); | ||
} | ||
} | ||
else { | ||
const newFieldValue = await events[field](modelInstance); | ||
// else it is `update` or `create` | ||
const newFieldValue = await thisEvent[field](modelInstance); | ||
if (newFieldValue !== undefined) { | ||
@@ -94,0 +129,0 @@ modelInstance.set(field, newFieldValue); |
{ | ||
"name": "xpress-mongo", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "Light Weight ODM for mongoDb", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -401,3 +401,3 @@ import ObjectCollection = require("object-collection"); | ||
*/ | ||
static on<T extends typeof XMongoModel>(this: T, event: "create" | "update" | "delete" | "create.fieldName" | "update.fieldName" | "watch.fieldName" | string, functionOrFunctions: ((modelInstance: InstanceType<T>) => void | any) | Record<string, (modelInstance: InstanceType<T>) => void | any>): void; | ||
static on<T extends typeof XMongoModel>(this: T, event: "create" | "update" | "deleted" | "create.fieldName" | "update.fieldName" | "watch.fieldName" | string, functionOrFunctions: ((modelInstance: InstanceType<T>) => void | any) | Record<string, (modelInstance: InstanceType<T>) => void | any>): void; | ||
/** | ||
@@ -404,0 +404,0 @@ * Replace Current Model Instance Data |
@@ -487,2 +487,3 @@ "use strict"; | ||
this.$setOriginal(this.data); | ||
inbuilt_1.RunOnEvent("created", this); | ||
return resolve(res); | ||
@@ -662,9 +663,9 @@ }); | ||
*/ | ||
delete() { | ||
async delete() { | ||
const _id = this.id(); | ||
if (_id) { | ||
// Run on delete Events on background | ||
inbuilt_1.RunOnEvent("delete", this).catch(console.error); | ||
// Delete Document | ||
return this.constructor.native().deleteOne({ _id }); | ||
const result = await this.constructor.native().deleteOne({ _id }); | ||
inbuilt_1.RunOnEvent("deleted", this).finally(() => { }); | ||
return result; | ||
} | ||
@@ -1096,24 +1097,38 @@ else { | ||
static on(event, functionOrFunctions) { | ||
if (!this.events) | ||
this.events = {}; | ||
if (event === "delete" && typeof functionOrFunctions !== "function") { | ||
throw Error("on('delete') event must be type of Function."); | ||
// Get Current Model Name | ||
const modelName = this.name || "Model"; | ||
// Throw error if deprecated `delete` command is used. | ||
if (event === "delete") | ||
throw Error(`${modelName}.on("${event}") is deprecated. Use "deleted" instead.`); | ||
// Validate events that must be a function | ||
if (["deleted", "created"].includes(event) && typeof functionOrFunctions !== "function") { | ||
throw Error(`${modelName}.on("${event}") event must be type of Function.`); | ||
} | ||
// watch when not using dot notation must be an object | ||
if (event === "watch" && typeof functionOrFunctions !== "object") { | ||
throw Error("on('watch') event must be type of Object."); | ||
throw Error(`${modelName}.on("watch") event must be type of Object.`); | ||
} | ||
const dots = event.split("."); | ||
if (dots.length > 2) { | ||
let [main, ...others] = dots; | ||
others = others.join("."); | ||
if (this.events[main]) { | ||
this.events[main][others] = functionOrFunctions; | ||
/** | ||
* Parse Dot Notation "event.field" | ||
*/ | ||
if (event.includes(".")) { | ||
// Split . | ||
const dots = event.split("."); | ||
// Throw error if more than dots | ||
if (dots.length > 2) { | ||
throw Error(`Model events supports only first level Field names when using dot notation. {event:"${event}"}`); | ||
} | ||
else { | ||
this.events[main] = { [others]: functionOrFunctions }; | ||
else if (dots.length === 2) { | ||
// Check if event supports the dot notation | ||
let [main] = dots; | ||
if (!["create", "update", "watch"].includes(main)) { | ||
throw Error(`${modelName}.on("${main}") does not support dot notation. {event:"${event}"}`); | ||
} | ||
} | ||
} | ||
else { | ||
_.set(this.events, event, functionOrFunctions); | ||
} | ||
// Set to default if not. | ||
if (!this.events) | ||
this.events = {}; | ||
// Merge to events | ||
_.merge(this.events, _.set({}, event, functionOrFunctions)); | ||
} | ||
@@ -1120,0 +1135,0 @@ /** |
82969
2590