Skip to content

Commit c3f2206

Browse files
authored
use an instance of a class as event listener (#259)
1 parent d15b796 commit c3f2206

4 files changed

Lines changed: 69 additions & 6 deletions

File tree

data-model.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,9 @@ function unregisterContextListeners() {
610610
* @private
611611
*/
612612
function registerContextListeners() {
613-
614-
//description: change default max listeners (10) to 64 in order to avoid node.js message
615-
// for reaching the maximum number of listeners
616-
//author: k.barbounakis@gmail.com
613+
// unregister listeners
614+
unregisterContextListeners.call(this);
615+
// set max listeners
617616
if (typeof this.setMaxListeners === 'function') {
618617
this.setMaxListeners(64);
619618
}
@@ -652,7 +651,7 @@ function unregisterContextListeners() {
652651
this.on('before.save', OnJsonAttribute.prototype.beforeSave);
653652
//get module loader
654653
/**
655-
* @type {ModuleLoader|*}
654+
* @type {ModuleLoaderStrategy}
656655
*/
657656
var moduleLoader = this.context.getConfiguration().getStrategy(ModuleLoaderStrategy);
658657
//register configuration listeners
@@ -662,10 +661,25 @@ function unregisterContextListeners() {
662661
//get listener type (e.g. type: require('./custom-listener.js'))
663662
if (listener.type && !listener.disabled)
664663
{
664+
const [listenerModule, listenerClassOrObject] = listener.type.split('#');
665665
/**
666666
* @type {{beforeSave?:function,afterSave?:function,beforeRemove?:function,afterRemove?:function,beforeExecute?:function,afterExecute?:function,beforeUpgrade?:function,afterUpgrade?:function}}
667667
*/
668-
var dataEventListener = moduleLoader.require(listener.type);
668+
let dataEventListener;
669+
if (listenerClassOrObject) {
670+
const module = moduleLoader.require(listenerModule);
671+
if (Object.prototype.hasOwnProperty.call(module, listenerClassOrObject) === false) {
672+
throw new DataError('ERR_TYPE_NOENT'`The event listener type "${listenerClassOrObject}" cannot be found in target module`, null, this.name);
673+
}
674+
if (isObjectDeep(module[listenerClassOrObject])) {
675+
dataEventListener = module[listenerClassOrObject];
676+
} else {
677+
const ListenerClass = module[listenerClassOrObject];
678+
dataEventListener = new ListenerClass();
679+
}
680+
} else {
681+
dataEventListener = moduleLoader.require(listener.type);
682+
}
669683
if (typeof dataEventListener.beforeUpgrade === 'function')
670684
this.on('before.upgrade', dataEventListener.beforeUpgrade);
671685
if (typeof dataEventListener.beforeSave === 'function')

spec/DataModel.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { TestApplication } from './TestApplication';
33
import { resolve } from 'path';
44
import {SqliteAdapter} from '@themost/sqlite';
55
import * as listener from './test1/listeners/Employee.beforeUpgrade';
6+
import { OnUpdateProduct, onRemoveProduct } from './test1/listeners/OnUpdateProduct';
67

78
class Employee {
89
public EmployeeID?: number;
@@ -108,6 +109,7 @@ describe('DataModel', () => {
108109
});
109110

110111
it('should use beforeUpgrade', async () => {
112+
// @ts-ignore
111113
const schema: SchemaLoaderStrategy = context.getConfiguration().getStrategy(SchemaLoaderStrategy);
112114
const modelDefinition = schema.getModelDefinition('Employee')
113115
modelDefinition.eventListeners = modelDefinition.eventListeners || [];
@@ -124,5 +126,25 @@ describe('DataModel', () => {
124126
expect(beforeUpgradeListener).toBe(listener.beforeUpgrade);
125127
});
126128

129+
it('should use class event listener', async () => {
130+
const model = context.model('Product');
131+
expect(model).toBeTruthy();
132+
const listeners = model.listeners('before.save');
133+
expect(listeners).toBeTruthy();
134+
expect(listeners.length).toBeGreaterThan(0);
135+
const found = listeners.find((f) => f === OnUpdateProduct.prototype.beforeSave);
136+
expect(found).toBeTruthy();
137+
});
138+
139+
it('should use object event listener', async () => {
140+
const model = context.model('Product');
141+
expect(model).toBeTruthy();
142+
const listeners = model.listeners('before.remove');
143+
expect(listeners).toBeTruthy();
144+
expect(listeners.length).toBeGreaterThan(0);
145+
const found = listeners.find((f) => f === onRemoveProduct.beforeRemove);
146+
expect(found).toBeTruthy();
147+
});
148+
127149
});
128150

spec/test1/config/models/Product.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@
4141
"nullable": false
4242
}
4343
],
44+
"eventListeners": [
45+
{
46+
"type": "./listeners/OnUpdateProduct#OnUpdateProduct"
47+
},
48+
{
49+
"type": "./listeners/OnUpdateProduct#onRemoveProduct"
50+
}
51+
],
4452
"seed": [
4553
{
4654
"ProductID": 1,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {BeforeSaveEventListener, DataEventArgs} from '@themost/data';
2+
3+
class OnUpdateProduct implements BeforeSaveEventListener {
4+
beforeSave(_event: DataEventArgs, callback: (err?: Error) => void): void {
5+
return callback();
6+
}
7+
}
8+
9+
// use a native object to export a listener
10+
const onRemoveProduct = {
11+
beforeRemove: (_event: DataEventArgs, callback: (err?: Error) => void) => {
12+
return callback();
13+
}
14+
}
15+
16+
export {
17+
OnUpdateProduct,
18+
onRemoveProduct
19+
}

0 commit comments

Comments
 (0)