-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
db91d84
commit d038220
Showing
7 changed files
with
159 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// Copyright IBM Corp. 2018. All Rights Reserved. | ||
// Node module: @loopback/events | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
export * from './listen'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright IBM Corp. 2018. All Rights Reserved. | ||
// Node module: @loopback/events | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import {MethodDecoratorFactory} from '@loopback/metadata'; | ||
|
||
/** | ||
* Decorate a method to listen to certain events. | ||
* For example, | ||
* ```ts | ||
* @listen('start') | ||
* async function onStart() { | ||
* } | ||
* ``` | ||
* @param messageTypes | ||
*/ | ||
export function listen(...messageTypes: (string | RegExp)[]) { | ||
return MethodDecoratorFactory.createDecorator('events:listen', messageTypes); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright IBM Corp. 2018. All Rights Reserved. | ||
// Node module: @loopback/events | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import {ListenerFunction} from './types'; | ||
import {MetadataInspector} from '@loopback/metadata'; | ||
|
||
/** | ||
* Create a listener function for an object that has methods for corresponding | ||
* events. For example: | ||
* ```ts | ||
* export class MyListener { | ||
* async start() {} | ||
* async stop() {} | ||
* } | ||
* ``` | ||
* @param obj | ||
*/ | ||
export function asListener<T>(obj: { | ||
[method: string]: unknown; | ||
}): ListenerFunction<T> { | ||
return async (event, eventName) => { | ||
const name = eventName.toString(); | ||
for (const m of findListenMethods(obj, name)) { | ||
if (m === 'listen') { | ||
await (obj.listen as Function)(event, eventName); | ||
} else { | ||
await (obj[m] as Function)(event, eventName); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
function findListenMethods( | ||
obj: { | ||
[method: string]: unknown; | ||
}, | ||
eventName: string, | ||
): string[] { | ||
const listenMethods = | ||
MetadataInspector.getAllMethodMetadata<(string | RegExp)[]>( | ||
'events:listen', | ||
obj, | ||
) || {}; | ||
const methods = []; | ||
for (const m in listenMethods) { | ||
if ( | ||
listenMethods[m].some(e => { | ||
return !!eventName.match(e); | ||
}) | ||
) { | ||
methods.push(m); | ||
} | ||
} | ||
if (methods.length === 0) { | ||
if (typeof obj[eventName] === 'function') { | ||
methods.push(eventName); | ||
} | ||
if (typeof obj['listen'] === 'function') { | ||
methods.push('listen'); | ||
} | ||
} | ||
return methods; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright IBM Corp. 2018. All Rights Reserved. | ||
// Node module: @loopback/events | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import {expect} from '@loopback/testlab'; | ||
import {asListener} from '../..'; | ||
import {ListenerObject, listen} from '../..'; | ||
|
||
describe('listener adapter', () => { | ||
it('adapts an object with matching methods', async () => { | ||
const events: string[] = []; | ||
class MyListener { | ||
start() { | ||
events.push('start'); | ||
} | ||
|
||
stop() { | ||
events.push('stop'); | ||
} | ||
} | ||
const inst = new MyListener(); | ||
await asListener(inst)('', 'start'); | ||
expect(events).to.eql(['start']); | ||
await asListener(inst)('', 'stop'); | ||
expect(events).to.eql(['start', 'stop']); | ||
}); | ||
|
||
it('adapts an object with listen()', async () => { | ||
const events: string[] = []; | ||
class MyListener implements ListenerObject<string> { | ||
async listen(event: string, eventName: string) { | ||
events.push(eventName); | ||
} | ||
} | ||
const inst = new MyListener(); | ||
await asListener(inst)('', 'start'); | ||
expect(events).to.eql(['start']); | ||
await asListener(inst)('', 'stop'); | ||
expect(events).to.eql(['start', 'stop']); | ||
}); | ||
|
||
it('adapts an object with @listen()', async () => { | ||
const events: string[] = []; | ||
class MyListener { | ||
@listen('start') | ||
_start() { | ||
events.push('start'); | ||
} | ||
|
||
@listen(/stop/) | ||
_stop() { | ||
events.push('stop'); | ||
} | ||
} | ||
const inst = new MyListener(); | ||
await asListener(inst)('', 'start'); | ||
expect(events).to.eql(['start']); | ||
await asListener(inst)('', 'stop'); | ||
expect(events).to.eql(['start', 'stop']); | ||
}); | ||
}); |