├── .circleci └── config.yml ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── bower.json ├── build ├── args.js ├── babel-options.js ├── paths.js ├── tasks │ ├── build.js │ ├── clean.js │ ├── dev.js │ ├── doc.js │ ├── lint.js │ ├── prepare-release.js │ └── test.js └── typescript-options.js ├── config.js ├── dist ├── amd │ ├── aurelia-event-aggregator.js │ └── index.js ├── aurelia-event-aggregator.d.ts ├── aurelia-event-aggregator.js ├── commonjs │ ├── aurelia-event-aggregator.js │ └── index.js ├── es2015 │ ├── aurelia-event-aggregator.js │ └── index.js ├── index.d.ts ├── native-modules │ ├── aurelia-event-aggregator.js │ └── index.js └── system │ ├── aurelia-event-aggregator.js │ └── index.js ├── doc ├── CHANGELOG.md └── api.json ├── gulpfile.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── src └── index.js ├── test └── event-aggregator.spec.js ├── tsconfig.json └── typings.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | map-1: &filter_only_develop 4 | filters: 5 | branches: 6 | only: develop 7 | 8 | map-2: &filter_only_tag 9 | filters: 10 | branches: 11 | ignore: /.*/ 12 | tags: 13 | only: /^v?[0-9]+(\.[0-9]+)*$/ 14 | 15 | orbs: 16 | v1: aurelia/v1@volatile 17 | 18 | workflows: 19 | main: 20 | jobs: 21 | - v1/build_test 22 | - v1/build_merge: 23 | <<: *filter_only_develop 24 | requires: 25 | - v1/build_test 26 | - v1/npm_publish: 27 | <<: *filter_only_tag 28 | name: npm_publish_dry 29 | args: "--dry-run" 30 | - request_publish_latest: 31 | <<: *filter_only_tag 32 | type: approval 33 | requires: 34 | - npm_publish_dry 35 | - v1/npm_publish: 36 | <<: *filter_only_tag 37 | name: npm_publish 38 | context: Aurelia 39 | requires: 40 | - request_publish_latest 41 | - v1/merge_back: 42 | <<: *filter_only_tag 43 | requires: 44 | - npm_publish 45 | 46 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 2 space indentation 12 | [**.*] 13 | indent_style = space 14 | indent_size = 2 -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/aurelia-tools/.eslintrc.json" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | jspm_packages 3 | bower_components 4 | .idea 5 | .DS_STORE 6 | build/reports 7 | dist 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | jspm_packages 2 | bower_components 3 | .idea 4 | build/reports 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We'd love for you to contribute and to make this project even better than it is today! If this interests you, please begin by reading [our contributing guidelines](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md). The contributing document will provide you with all the information you need to get started. Once you have read that, you will need to also [sign our CLA](http://goo.gl/forms/dI8QDDSyKR) before we can accept a Pull Request from you. More information on the process is included in the [contributor's guide](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md). 4 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 19 | **I'm submitting a bug report** 20 | **I'm submitting a feature request** 21 | 22 | * **Library Version:** 23 | major.minor.patch-pre 24 | 25 | 26 | **Please tell us about your environment:** 27 | * **Operating System:** 28 | OSX 10.x|Linux (distro)|Windows [7|8|8.1|10] 29 | 30 | * **Node Version:** 31 | 6.2.0 32 | 36 | 37 | * **NPM Version:** 38 | 3.8.9 39 | 43 | 44 | * **JSPM OR Webpack AND Version** 45 | JSPM 0.16.32 | webpack 2.1.0-beta.17 46 | 52 | 53 | * **Browser:** 54 | all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView 55 | 56 | * **Language:** 57 | all | TypeScript X.X | ESNext 58 | 59 | 60 | **Current behavior:** 61 | 62 | 63 | **Expected/desired behavior:** 64 | 71 | 72 | 73 | * **What is the expected behavior?** 74 | 75 | 76 | * **What is the motivation / use case for changing the behavior?** 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2010 - 2018 Blue Spire Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aurelia-event-aggregator 2 | 3 | [![npm Version](https://img.shields.io/npm/v/aurelia-event-aggregator.svg)](https://www.npmjs.com/package/aurelia-event-aggregator) 4 | [![ZenHub](https://raw.githubusercontent.com/ZenHubIO/support/master/zenhub-badge.png)](https://zenhub.io) 5 | [![Join the chat at https://gitter.im/aurelia/discuss](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/aurelia/discuss?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | [![CircleCI](https://circleci.com/gh/aurelia/event-aggregator.svg?style=shield)](https://circleci.com/gh/aurelia/event-aggregator) 7 | 8 | This library is part of the [Aurelia](http://www.aurelia.io/) platform and contains a lightweight pub/sub messaging system for app-wide or per-object loosely coupled events. 9 | 10 | > To keep up to date on [Aurelia](http://www.aurelia.io/), please visit and subscribe to [the official blog](http://blog.aurelia.io/) and [our email list](http://eepurl.com/ces50j). We also invite you to [follow us on twitter](https://twitter.com/aureliaeffect). If you have questions, please [join our community on Gitter](https://gitter.im/aurelia/discuss) or use [stack overflow](http://stackoverflow.com/search?q=aurelia). Documentation can be found [in our developer hub](http://aurelia.io/hub.html). If you would like to have deeper insight into our development process, please install the [ZenHub](https://zenhub.io) Chrome or Firefox Extension and visit any of our repository's boards. 11 | 12 | ## Platform Support 13 | 14 | This library can be used in the **browser** as well as on the **server**. 15 | 16 | ## Building The Code 17 | 18 | To build the code, follow these steps. 19 | 20 | 1. Ensure that [NodeJS](http://nodejs.org/) is installed. This provides the platform on which the build tooling runs. 21 | 2. From the project folder, execute the following command: 22 | 23 | ```shell 24 | npm install 25 | ``` 26 | 3. Ensure that [Gulp](http://gulpjs.com/) is installed. If you need to install it, use the following command: 27 | 28 | ```shell 29 | npm install -g gulp 30 | ``` 31 | 4. To build the code, you can now run: 32 | 33 | ```shell 34 | gulp build 35 | ``` 36 | 5. You will find the compiled code in the `dist` folder, available in three module formats: AMD, CommonJS and ES6. 37 | 38 | 6. See `gulpfile.js` for other tasks related to generating the docs and linting. 39 | 40 | ## Running The Tests 41 | 42 | To run the unit tests, first ensure that you have followed the steps above in order to install all dependencies and successfully build the library. Once you have done that, proceed with these additional steps: 43 | 44 | 1. Ensure that the [Karma](http://karma-runner.github.io/) CLI is installed. If you need to install it, use the following command: 45 | 46 | ```shell 47 | npm install -g karma-cli 48 | ``` 49 | 2. Ensure that [jspm](http://jspm.io/) is installed. If you need to install it, use the following commnand: 50 | 51 | ```shell 52 | npm install -g jspm 53 | ``` 54 | 3. Download the [SystemJS](https://github.com/systemjs/systemjs) module loader: 55 | 56 | ```shell 57 | jspm dl-loader 58 | ``` 59 | 60 | 4. You can now run the tests with this command: 61 | 62 | ```shell 63 | karma start 64 | ``` 65 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-event-aggregator", 3 | "version": "1.0.4", 4 | "description": "A lightweight pub/sub messaging system for app-wide or per-object loosely coupled events.", 5 | "keywords": [ 6 | "aurelia", 7 | "event aggregator", 8 | "events", 9 | "pub/sub" 10 | ], 11 | "homepage": "http://aurelia.io", 12 | "main": "dist/commonjs/aurelia-event-aggregator.js", 13 | "moduleType": "node", 14 | "license": "MIT", 15 | "authors": [ 16 | "Rob Eisenberg (http://robeisenberg.com/)" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "http://github.com/aurelia/event-aggregator" 21 | }, 22 | "dependencies": { 23 | "aurelia-logging": "^1.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /build/args.js: -------------------------------------------------------------------------------- 1 | var yargs = require('yargs'); 2 | 3 | var argv = yargs.argv, 4 | validBumpTypes = "major|minor|patch|prerelease".split("|"), 5 | bump = (argv.bump || 'patch').toLowerCase(); 6 | 7 | if(validBumpTypes.indexOf(bump) === -1) { 8 | throw new Error('Unrecognized bump "' + bump + '".'); 9 | } 10 | 11 | module.exports = { 12 | bump: bump 13 | }; 14 | -------------------------------------------------------------------------------- /build/babel-options.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var paths = require('./paths'); 3 | 4 | exports.base = function() { 5 | var config = { 6 | filename: '', 7 | filenameRelative: '', 8 | sourceMap: true, 9 | sourceRoot: '', 10 | moduleRoot: path.resolve('src').replace(/\\/g, '/'), 11 | moduleIds: false, 12 | comments: false, 13 | compact: false, 14 | code: true, 15 | presets: [ 'es2015-loose', 'stage-1' ], 16 | plugins: [ 17 | 'syntax-flow', 18 | 'transform-decorators-legacy', 19 | ] 20 | }; 21 | if (!paths.useTypeScriptForDTS) { 22 | config.plugins.push( 23 | ['babel-dts-generator', { 24 | packageName: paths.packageName, 25 | typings: '', 26 | suppressModulePath: true, 27 | suppressComments: false, 28 | memberOutputFilter: /^_.*/, 29 | suppressAmbientDeclaration: true 30 | }] 31 | ); 32 | }; 33 | config.plugins.push('transform-flow-strip-types'); 34 | return config; 35 | } 36 | 37 | exports.commonjs = function() { 38 | var options = exports.base(); 39 | options.plugins.push('transform-es2015-modules-commonjs'); 40 | return options; 41 | }; 42 | 43 | exports.amd = function() { 44 | var options = exports.base(); 45 | options.plugins.push('transform-es2015-modules-amd'); 46 | return options; 47 | }; 48 | 49 | exports.system = function() { 50 | var options = exports.base(); 51 | options.plugins.push('transform-es2015-modules-systemjs'); 52 | return options; 53 | }; 54 | 55 | exports.es2015 = function() { 56 | var options = exports.base(); 57 | options.presets = ['stage-1'] 58 | return options; 59 | }; 60 | 61 | exports['native-modules'] = function() { 62 | var options = exports.base(); 63 | options.presets[0] = 'es2015-loose-native-modules'; 64 | return options; 65 | } 66 | -------------------------------------------------------------------------------- /build/paths.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | 4 | // hide warning // 5 | var emitter = require('events'); 6 | emitter.defaultMaxListeners = 20; 7 | 8 | var appRoot = 'src/'; 9 | var pkg = JSON.parse(fs.readFileSync('./package.json', 'utf-8')); 10 | 11 | var paths = { 12 | root: appRoot, 13 | source: appRoot + '**/*.js', 14 | html: appRoot + '**/*.html', 15 | style: 'styles/**/*.css', 16 | output: 'dist/', 17 | doc:'./doc', 18 | e2eSpecsSrc: 'test/e2e/src/*.js', 19 | e2eSpecsDist: 'test/e2e/dist/', 20 | packageName: pkg.name, 21 | ignore: [], 22 | useTypeScriptForDTS: false, 23 | importsToAdd: [], 24 | sort: false 25 | }; 26 | 27 | paths.files = [ 28 | 'index.js' 29 | ].map(function(file){ 30 | return paths.root + file; 31 | }); 32 | 33 | module.exports = paths; 34 | -------------------------------------------------------------------------------- /build/tasks/build.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var runSequence = require('run-sequence'); 3 | var to5 = require('gulp-babel'); 4 | var paths = require('../paths'); 5 | var compilerOptions = require('../babel-options'); 6 | var compilerTsOptions = require('../typescript-options'); 7 | var assign = Object.assign || require('object.assign'); 8 | var through2 = require('through2'); 9 | var concat = require('gulp-concat'); 10 | var insert = require('gulp-insert'); 11 | var rename = require('gulp-rename'); 12 | var tools = require('aurelia-tools'); 13 | var ts = require('gulp-typescript'); 14 | var gutil = require('gulp-util'); 15 | var gulpIgnore = require('gulp-ignore'); 16 | var merge = require('merge2'); 17 | var jsName = paths.packageName + '.js'; 18 | var compileToModules = ['es2015', 'commonjs', 'amd', 'system', 'native-modules']; 19 | 20 | function cleanGeneratedCode() { 21 | return through2.obj(function(file, enc, callback) { 22 | file.contents = new Buffer(tools.cleanGeneratedCode(file.contents.toString('utf8'))); 23 | this.push(file); 24 | return callback(); 25 | }); 26 | } 27 | 28 | gulp.task('build-index', function() { 29 | var importsToAdd = paths.importsToAdd.slice(); 30 | 31 | var src = gulp.src(paths.files); 32 | 33 | if (paths.sort) { 34 | src = src.pipe(tools.sortFiles()); 35 | } 36 | 37 | if (paths.ignore) { 38 | paths.ignore.forEach(function(filename){ 39 | src = src.pipe(gulpIgnore.exclude(filename)); 40 | }); 41 | } 42 | 43 | return src.pipe(through2.obj(function(file, enc, callback) { 44 | file.contents = new Buffer(tools.extractImports(file.contents.toString('utf8'), importsToAdd)); 45 | this.push(file); 46 | return callback(); 47 | })) 48 | .pipe(concat(jsName)) 49 | .pipe(insert.transform(function(contents) { 50 | return tools.createImportBlock(importsToAdd) + contents; 51 | })) 52 | .pipe(gulp.dest(paths.output)); 53 | }); 54 | 55 | function gulpFileFromString(filename, string) { 56 | var src = require('stream').Readable({ objectMode: true }); 57 | src._read = function() { 58 | this.push(new gutil.File({ cwd: paths.appRoot, base: paths.output, path: filename, contents: new Buffer(string) })) 59 | this.push(null) 60 | } 61 | return src; 62 | } 63 | 64 | function srcForBabel() { 65 | return merge( 66 | gulp.src(paths.output + jsName), 67 | gulpFileFromString(paths.output + 'index.js', "export * from './" + paths.packageName + "';") 68 | ); 69 | } 70 | 71 | function srcForTypeScript() { 72 | return gulp 73 | .src(paths.output + paths.packageName + '.js') 74 | .pipe(rename(function (path) { 75 | if (path.extname == '.js') { 76 | path.extname = '.ts'; 77 | } 78 | })); 79 | } 80 | 81 | compileToModules.forEach(function(moduleType){ 82 | gulp.task('build-babel-' + moduleType, function () { 83 | return srcForBabel() 84 | .pipe(to5(assign({}, compilerOptions[moduleType]()))) 85 | .pipe(cleanGeneratedCode()) 86 | .pipe(gulp.dest(paths.output + moduleType)); 87 | }); 88 | 89 | if (moduleType === 'native-modules') return; // typescript doesn't support the combination of: es5 + native modules 90 | 91 | gulp.task('build-ts-' + moduleType, function () { 92 | var tsProject = ts.createProject( 93 | compilerTsOptions({ module: moduleType, target: moduleType == 'es2015' ? 'es2015' : 'es5' }), ts.reporter.defaultReporter()); 94 | var tsResult = srcForTypeScript().pipe(ts(tsProject)); 95 | return tsResult.js 96 | .pipe(gulp.dest(paths.output + moduleType)); 97 | }); 98 | }); 99 | 100 | gulp.task('build-dts', function() { 101 | var tsProject = ts.createProject( 102 | compilerTsOptions({ removeComments: false, target: "es2015", module: "es2015" }), ts.reporter.defaultReporter()); 103 | var tsResult = srcForTypeScript().pipe(ts(tsProject)); 104 | return tsResult.dts 105 | .pipe(gulp.dest(paths.output)); 106 | }); 107 | 108 | gulp.task('build', function(callback) { 109 | return runSequence( 110 | 'clean', 111 | 'build-index', 112 | compileToModules 113 | .map(function(moduleType) { return 'build-babel-' + moduleType }) 114 | .concat(paths.useTypeScriptForDTS ? ['build-dts'] : []), 115 | callback 116 | ); 117 | }); 118 | 119 | gulp.task('build-ts', function(callback) { 120 | return runSequence( 121 | 'clean', 122 | 'build-index', 123 | 'build-babel-native-modules', 124 | compileToModules 125 | .filter(function(moduleType) { return moduleType !== 'native-modules' }) 126 | .map(function(moduleType) { return 'build-ts-' + moduleType }) 127 | .concat(paths.useTypeScriptForDTS ? ['build-dts'] : []), 128 | callback 129 | ); 130 | }); 131 | -------------------------------------------------------------------------------- /build/tasks/clean.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var paths = require('../paths'); 3 | var del = require('del'); 4 | var vinylPaths = require('vinyl-paths'); 5 | 6 | gulp.task('clean', function() { 7 | return gulp.src([paths.output]) 8 | .pipe(vinylPaths(del)); 9 | }); 10 | -------------------------------------------------------------------------------- /build/tasks/dev.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var tools = require('aurelia-tools'); 3 | 4 | gulp.task('update-own-deps', function(){ 5 | tools.updateOwnDependenciesFromLocalRepositories(); 6 | }); 7 | 8 | gulp.task('build-dev-env', function () { 9 | tools.buildDevEnv(); 10 | }); 11 | -------------------------------------------------------------------------------- /build/tasks/doc.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var paths = require('../paths'); 3 | var typedoc = require('gulp-typedoc'); 4 | var runSequence = require('run-sequence'); 5 | var through2 = require('through2'); 6 | 7 | gulp.task('doc-generate', function(){ 8 | return gulp.src([paths.output + paths.packageName + '.d.ts']) 9 | .pipe(typedoc({ 10 | target: 'es6', 11 | includeDeclarations: true, 12 | moduleResolution: 'node', 13 | json: paths.doc + '/api.json', 14 | name: paths.packageName + '-docs',  15 | mode: 'modules', 16 | excludeExternals: true, 17 | ignoreCompilerErrors: false, 18 | version: true 19 | })); 20 | }); 21 | 22 | gulp.task('doc-shape', function(){ 23 | return gulp.src([paths.doc + '/api.json']) 24 | .pipe(through2.obj(function(file, enc, callback) { 25 | var json = JSON.parse(file.contents.toString('utf8')).children[0]; 26 | 27 | json = { 28 | name: paths.packageName, 29 | children: json.children, 30 | groups: json.groups 31 | }; 32 | 33 | file.contents = new Buffer(JSON.stringify(json)); 34 | this.push(file); 35 | return callback(); 36 | })) 37 | .pipe(gulp.dest(paths.doc)); 38 | }); 39 | 40 | gulp.task('doc', function(callback){ 41 | return runSequence( 42 | 'doc-generate', 43 | 'doc-shape', 44 | callback 45 | ); 46 | }); 47 | -------------------------------------------------------------------------------- /build/tasks/lint.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var paths = require('../paths'); 3 | var eslint = require('gulp-eslint'); 4 | 5 | gulp.task('lint', function() { 6 | return gulp.src(paths.source) 7 | .pipe(eslint()) 8 | .pipe(eslint.format()) 9 | .pipe(eslint.failOnError()); 10 | }); 11 | -------------------------------------------------------------------------------- /build/tasks/prepare-release.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var runSequence = require('run-sequence'); 3 | var paths = require('../paths'); 4 | var fs = require('fs'); 5 | var bump = require('gulp-bump'); 6 | var args = require('../args'); 7 | var conventionalChangelog = require('gulp-conventional-changelog'); 8 | 9 | gulp.task('changelog', function () { 10 | return gulp.src(paths.doc + '/CHANGELOG.md', { 11 | buffer: false 12 | }).pipe(conventionalChangelog({ 13 | preset: 'angular' 14 | })) 15 | .pipe(gulp.dest(paths.doc)); 16 | }); 17 | 18 | gulp.task('bump-version', function(){ 19 | return gulp.src(['./package.json', './bower.json']) 20 | .pipe(bump({type:args.bump })) //major|minor|patch|prerelease 21 | .pipe(gulp.dest('./')); 22 | }); 23 | 24 | gulp.task('prepare-release', function(callback){ 25 | return runSequence( 26 | 'build', 27 | 'lint', 28 | 'bump-version', 29 | 'doc', 30 | 'changelog', 31 | callback 32 | ); 33 | }); 34 | -------------------------------------------------------------------------------- /build/tasks/test.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var Karma = require('karma').Server; 3 | 4 | /** 5 | * Run test once and exit 6 | */ 7 | gulp.task('test', function (done) { 8 | new Karma({ 9 | configFile: __dirname + '/../../karma.conf.js', 10 | singleRun: true 11 | }, done).start(); 12 | }); 13 | 14 | /** 15 | * Watch for file changes and re-run tests on each change 16 | */ 17 | gulp.task('tdd', function (done) { 18 | new Karma({ 19 | configFile: __dirname + '/../../karma.conf.js' 20 | }, done).start(); 21 | }); 22 | 23 | /** 24 | * Run test once with code coverage and exit 25 | */ 26 | gulp.task('cover', function (done) { 27 | new Karma({ 28 | configFile: __dirname + '/../../karma.conf.js', 29 | singleRun: true, 30 | reporters: ['coverage'], 31 | preprocessors: { 32 | 'test/**/*.js': ['babel'], 33 | 'src/**/*.js': ['babel', 'coverage'] 34 | }, 35 | coverageReporter: { 36 | type: 'html', 37 | dir: 'build/reports/coverage' 38 | } 39 | }, done).start(); 40 | }); 41 | -------------------------------------------------------------------------------- /build/typescript-options.js: -------------------------------------------------------------------------------- 1 | var tsconfig = require('../tsconfig.json'); 2 | var assign = Object.assign || require('object.assign'); 3 | 4 | module.exports = function(override) { 5 | return assign(tsconfig.compilerOptions, { 6 | "target": override && override.target || "es5", 7 | "typescript": require('typescript') 8 | }, override || {}); 9 | } 10 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | defaultJSExtensions: true, 3 | transpiler: "babel", 4 | babelOptions: { 5 | "optional": [ 6 | "runtime", 7 | "optimisation.modules.system" 8 | ] 9 | }, 10 | paths: { 11 | "github:*": "jspm_packages/github/*", 12 | "npm:*": "jspm_packages/npm/*" 13 | }, 14 | 15 | map: { 16 | "aurelia-logging": "npm:aurelia-logging@1.0.0", 17 | "babel": "npm:babel-core@5.8.38", 18 | "babel-runtime": "npm:babel-runtime@5.8.38", 19 | "core-js": "npm:core-js@2.4.1", 20 | "github:jspm/nodelibs-assert@0.1.0": { 21 | "assert": "npm:assert@1.4.1" 22 | }, 23 | "github:jspm/nodelibs-buffer@0.1.0": { 24 | "buffer": "npm:buffer@3.6.0" 25 | }, 26 | "github:jspm/nodelibs-path@0.1.0": { 27 | "path-browserify": "npm:path-browserify@0.0.0" 28 | }, 29 | "github:jspm/nodelibs-process@0.1.2": { 30 | "process": "npm:process@0.11.6" 31 | }, 32 | "github:jspm/nodelibs-util@0.1.0": { 33 | "util": "npm:util@0.10.3" 34 | }, 35 | "github:jspm/nodelibs-vm@0.1.0": { 36 | "vm-browserify": "npm:vm-browserify@0.0.4" 37 | }, 38 | "npm:assert@1.4.1": { 39 | "assert": "github:jspm/nodelibs-assert@0.1.0", 40 | "buffer": "github:jspm/nodelibs-buffer@0.1.0", 41 | "process": "github:jspm/nodelibs-process@0.1.2", 42 | "util": "npm:util@0.10.3" 43 | }, 44 | "npm:babel-runtime@5.8.38": { 45 | "process": "github:jspm/nodelibs-process@0.1.2" 46 | }, 47 | "npm:buffer@3.6.0": { 48 | "base64-js": "npm:base64-js@0.0.8", 49 | "child_process": "github:jspm/nodelibs-child_process@0.1.0", 50 | "fs": "github:jspm/nodelibs-fs@0.1.2", 51 | "ieee754": "npm:ieee754@1.1.6", 52 | "isarray": "npm:isarray@1.0.0", 53 | "process": "github:jspm/nodelibs-process@0.1.2" 54 | }, 55 | "npm:core-js@2.4.1": { 56 | "fs": "github:jspm/nodelibs-fs@0.1.2", 57 | "path": "github:jspm/nodelibs-path@0.1.0", 58 | "process": "github:jspm/nodelibs-process@0.1.2", 59 | "systemjs-json": "github:systemjs/plugin-json@0.1.2" 60 | }, 61 | "npm:inherits@2.0.1": { 62 | "util": "github:jspm/nodelibs-util@0.1.0" 63 | }, 64 | "npm:path-browserify@0.0.0": { 65 | "process": "github:jspm/nodelibs-process@0.1.2" 66 | }, 67 | "npm:process@0.11.6": { 68 | "assert": "github:jspm/nodelibs-assert@0.1.0", 69 | "fs": "github:jspm/nodelibs-fs@0.1.2", 70 | "vm": "github:jspm/nodelibs-vm@0.1.0" 71 | }, 72 | "npm:util@0.10.3": { 73 | "inherits": "npm:inherits@2.0.1", 74 | "process": "github:jspm/nodelibs-process@0.1.2" 75 | }, 76 | "npm:vm-browserify@0.0.4": { 77 | "indexof": "npm:indexof@0.0.1" 78 | } 79 | } 80 | }); 81 | -------------------------------------------------------------------------------- /dist/amd/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | define(['exports', 'aurelia-logging'], function (exports, _aureliaLogging) { 2 | 'use strict'; 3 | 4 | Object.defineProperty(exports, "__esModule", { 5 | value: true 6 | }); 7 | exports.EventAggregator = undefined; 8 | exports.includeEventsIn = includeEventsIn; 9 | exports.configure = configure; 10 | 11 | var LogManager = _interopRequireWildcard(_aureliaLogging); 12 | 13 | function _interopRequireWildcard(obj) { 14 | if (obj && obj.__esModule) { 15 | return obj; 16 | } else { 17 | var newObj = {}; 18 | 19 | if (obj != null) { 20 | for (var key in obj) { 21 | if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; 22 | } 23 | } 24 | 25 | newObj.default = obj; 26 | return newObj; 27 | } 28 | } 29 | 30 | 31 | 32 | var logger = LogManager.getLogger('event-aggregator'); 33 | 34 | var Handler = function () { 35 | function Handler(messageType, callback) { 36 | 37 | 38 | this.messageType = messageType; 39 | this.callback = callback; 40 | } 41 | 42 | Handler.prototype.handle = function handle(message) { 43 | if (message instanceof this.messageType) { 44 | this.callback.call(null, message); 45 | } 46 | }; 47 | 48 | return Handler; 49 | }(); 50 | 51 | function invokeCallback(callback, data, event) { 52 | try { 53 | callback(data, event); 54 | } catch (e) { 55 | logger.error(e); 56 | } 57 | } 58 | 59 | function invokeHandler(handler, data) { 60 | try { 61 | handler.handle(data); 62 | } catch (e) { 63 | logger.error(e); 64 | } 65 | } 66 | 67 | var EventAggregator = exports.EventAggregator = function () { 68 | function EventAggregator() { 69 | 70 | 71 | this.eventLookup = {}; 72 | this.messageHandlers = []; 73 | } 74 | 75 | EventAggregator.prototype.publish = function publish(event, data) { 76 | var subscribers = void 0; 77 | var i = void 0; 78 | 79 | if (!event) { 80 | throw new Error('Event was invalid.'); 81 | } 82 | 83 | if (typeof event === 'string') { 84 | subscribers = this.eventLookup[event]; 85 | if (subscribers) { 86 | subscribers = subscribers.slice(); 87 | i = subscribers.length; 88 | 89 | while (i--) { 90 | invokeCallback(subscribers[i], data, event); 91 | } 92 | } 93 | } else { 94 | subscribers = this.messageHandlers.slice(); 95 | i = subscribers.length; 96 | 97 | while (i--) { 98 | invokeHandler(subscribers[i], event); 99 | } 100 | } 101 | }; 102 | 103 | EventAggregator.prototype.subscribe = function subscribe(event, callback) { 104 | var handler = void 0; 105 | var subscribers = void 0; 106 | 107 | if (!event) { 108 | throw new Error('Event channel/type was invalid.'); 109 | } 110 | 111 | if (typeof event === 'string') { 112 | handler = callback; 113 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 114 | } else { 115 | handler = new Handler(event, callback); 116 | subscribers = this.messageHandlers; 117 | } 118 | 119 | subscribers.push(handler); 120 | 121 | return { 122 | dispose: function dispose() { 123 | var idx = subscribers.indexOf(handler); 124 | if (idx !== -1) { 125 | subscribers.splice(idx, 1); 126 | } 127 | } 128 | }; 129 | }; 130 | 131 | EventAggregator.prototype.subscribeOnce = function subscribeOnce(event, callback) { 132 | var sub = this.subscribe(event, function (a, b) { 133 | sub.dispose(); 134 | return callback(a, b); 135 | }); 136 | 137 | return sub; 138 | }; 139 | 140 | return EventAggregator; 141 | }(); 142 | 143 | function includeEventsIn(obj) { 144 | var ea = new EventAggregator(); 145 | 146 | obj.subscribeOnce = function (event, callback) { 147 | return ea.subscribeOnce(event, callback); 148 | }; 149 | 150 | obj.subscribe = function (event, callback) { 151 | return ea.subscribe(event, callback); 152 | }; 153 | 154 | obj.publish = function (event, data) { 155 | ea.publish(event, data); 156 | }; 157 | 158 | return ea; 159 | } 160 | 161 | function configure(config) { 162 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 163 | } 164 | }); -------------------------------------------------------------------------------- /dist/amd/index.js: -------------------------------------------------------------------------------- 1 | define(['exports', './aurelia-event-aggregator'], function (exports, _aureliaEventAggregator) { 2 | 'use strict'; 3 | 4 | Object.defineProperty(exports, "__esModule", { 5 | value: true 6 | }); 7 | Object.keys(_aureliaEventAggregator).forEach(function (key) { 8 | if (key === "default" || key === "__esModule") return; 9 | Object.defineProperty(exports, key, { 10 | enumerable: true, 11 | get: function () { 12 | return _aureliaEventAggregator[key]; 13 | } 14 | }); 15 | }); 16 | }); -------------------------------------------------------------------------------- /dist/aurelia-event-aggregator.d.ts: -------------------------------------------------------------------------------- 1 | import * as LogManager from 'aurelia-logging'; 2 | 3 | /** 4 | * Represents a disposable subsciption to an EventAggregator event. 5 | */ 6 | export declare interface Subscription { 7 | 8 | /** 9 | * Disposes the subscription. 10 | */ 11 | dispose(): void; 12 | } 13 | 14 | /** 15 | * Enables loosely coupled publish/subscribe messaging. 16 | */ 17 | /** 18 | * Enables loosely coupled publish/subscribe messaging. 19 | */ 20 | export declare class EventAggregator { 21 | 22 | /** 23 | * Creates an instance of the EventAggregator class. 24 | */ 25 | constructor(); 26 | 27 | /** 28 | * Publishes a message. 29 | * @param event The event or channel to publish to. 30 | * @param data The data to publish on the channel. 31 | */ 32 | publish(event: string | any, data?: any): void; 33 | 34 | /** 35 | * Subscribes to a message channel or message type. 36 | * @param event The event channel or event data type. 37 | * @param callback The callback to be invoked when the specified message is published. 38 | */ 39 | subscribe(event: string | Function, callback: Function): Subscription; 40 | 41 | /** 42 | * Subscribes to a message channel or message type, then disposes the subscription automatically after the first message is received. 43 | * @param event The event channel or event data type. 44 | * @param callback The callback to be invoked when the specified message is published. 45 | */ 46 | subscribeOnce(event: string | Function, callback: Function): Subscription; 47 | } 48 | 49 | /** 50 | * Includes EA functionality into an object instance. 51 | * @param obj The object to mix Event Aggregator functionality into. 52 | */ 53 | export declare function includeEventsIn(obj: Object): EventAggregator; 54 | 55 | /** 56 | * Configures a global EA by merging functionality into the Aurelia instance. 57 | * @param config The Aurelia Framework configuration object used to configure the plugin. 58 | */ 59 | export declare function configure(config: Object): void; -------------------------------------------------------------------------------- /dist/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | import * as LogManager from 'aurelia-logging'; 2 | 3 | const logger = LogManager.getLogger('event-aggregator'); 4 | 5 | class Handler { 6 | constructor(messageType, callback) { 7 | this.messageType = messageType; 8 | this.callback = callback; 9 | } 10 | 11 | handle(message) { 12 | if (message instanceof this.messageType) { 13 | this.callback.call(null, message); 14 | } 15 | } 16 | } 17 | 18 | function invokeCallback(callback, data, event) { 19 | try { 20 | callback(data, event); 21 | } catch (e) { 22 | logger.error(e); 23 | } 24 | } 25 | 26 | function invokeHandler(handler, data) { 27 | try { 28 | handler.handle(data); 29 | } catch (e) { 30 | logger.error(e); 31 | } 32 | } 33 | 34 | /** 35 | * Represents a disposable subsciption to an EventAggregator event. 36 | */ 37 | interface Subscription { 38 | /** 39 | * Disposes the subscription. 40 | */ 41 | dispose(): void; 42 | } 43 | 44 | /** 45 | * Enables loosely coupled publish/subscribe messaging. 46 | */ 47 | export class EventAggregator { 48 | /** 49 | * Creates an instance of the EventAggregator class. 50 | */ 51 | constructor() { 52 | this.eventLookup = {}; 53 | this.messageHandlers = []; 54 | } 55 | 56 | /** 57 | * Publishes a message. 58 | * @param event The event or channel to publish to. 59 | * @param data The data to publish on the channel. 60 | */ 61 | publish(event: string | any, data?: any): void { 62 | let subscribers; 63 | let i; 64 | 65 | if (!event) { 66 | throw new Error('Event was invalid.'); 67 | } 68 | 69 | if (typeof event === 'string') { 70 | subscribers = this.eventLookup[event]; 71 | if (subscribers) { 72 | subscribers = subscribers.slice(); 73 | i = subscribers.length; 74 | 75 | while (i--) { 76 | invokeCallback(subscribers[i], data, event); 77 | } 78 | } 79 | } else { 80 | subscribers = this.messageHandlers.slice(); 81 | i = subscribers.length; 82 | 83 | while (i--) { 84 | invokeHandler(subscribers[i], event); 85 | } 86 | } 87 | } 88 | 89 | /** 90 | * Subscribes to a message channel or message type. 91 | * @param event The event channel or event data type. 92 | * @param callback The callback to be invoked when the specified message is published. 93 | */ 94 | subscribe(event: string | Function, callback: Function): Subscription { 95 | let handler; 96 | let subscribers; 97 | 98 | if (!event) { 99 | throw new Error('Event channel/type was invalid.'); 100 | } 101 | 102 | if (typeof event === 'string') { 103 | handler = callback; 104 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 105 | } else { 106 | handler = new Handler(event, callback); 107 | subscribers = this.messageHandlers; 108 | } 109 | 110 | subscribers.push(handler); 111 | 112 | return { 113 | dispose() { 114 | let idx = subscribers.indexOf(handler); 115 | if (idx !== -1) { 116 | subscribers.splice(idx, 1); 117 | } 118 | } 119 | }; 120 | } 121 | 122 | /** 123 | * Subscribes to a message channel or message type, then disposes the subscription automatically after the first message is received. 124 | * @param event The event channel or event data type. 125 | * @param callback The callback to be invoked when the specified message is published. 126 | */ 127 | subscribeOnce(event: string | Function, callback: Function): Subscription { 128 | let sub = this.subscribe(event, (a, b) => { 129 | sub.dispose(); 130 | return callback(a, b); 131 | }); 132 | 133 | return sub; 134 | } 135 | } 136 | 137 | /** 138 | * Includes EA functionality into an object instance. 139 | * @param obj The object to mix Event Aggregator functionality into. 140 | */ 141 | export function includeEventsIn(obj: Object): EventAggregator { 142 | let ea = new EventAggregator(); 143 | 144 | obj.subscribeOnce = function(event, callback) { 145 | return ea.subscribeOnce(event, callback); 146 | }; 147 | 148 | obj.subscribe = function(event, callback) { 149 | return ea.subscribe(event, callback); 150 | }; 151 | 152 | obj.publish = function(event, data) { 153 | ea.publish(event, data); 154 | }; 155 | 156 | return ea; 157 | } 158 | 159 | /** 160 | * Configures a global EA by merging functionality into the Aurelia instance. 161 | * @param config The Aurelia Framework configuration object used to configure the plugin. 162 | */ 163 | export function configure(config: Object): void { 164 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 165 | } 166 | -------------------------------------------------------------------------------- /dist/commonjs/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.EventAggregator = undefined; 7 | exports.includeEventsIn = includeEventsIn; 8 | exports.configure = configure; 9 | 10 | var _aureliaLogging = require('aurelia-logging'); 11 | 12 | var LogManager = _interopRequireWildcard(_aureliaLogging); 13 | 14 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 15 | 16 | 17 | 18 | var logger = LogManager.getLogger('event-aggregator'); 19 | 20 | var Handler = function () { 21 | function Handler(messageType, callback) { 22 | 23 | 24 | this.messageType = messageType; 25 | this.callback = callback; 26 | } 27 | 28 | Handler.prototype.handle = function handle(message) { 29 | if (message instanceof this.messageType) { 30 | this.callback.call(null, message); 31 | } 32 | }; 33 | 34 | return Handler; 35 | }(); 36 | 37 | function invokeCallback(callback, data, event) { 38 | try { 39 | callback(data, event); 40 | } catch (e) { 41 | logger.error(e); 42 | } 43 | } 44 | 45 | function invokeHandler(handler, data) { 46 | try { 47 | handler.handle(data); 48 | } catch (e) { 49 | logger.error(e); 50 | } 51 | } 52 | 53 | var EventAggregator = exports.EventAggregator = function () { 54 | function EventAggregator() { 55 | 56 | 57 | this.eventLookup = {}; 58 | this.messageHandlers = []; 59 | } 60 | 61 | EventAggregator.prototype.publish = function publish(event, data) { 62 | var subscribers = void 0; 63 | var i = void 0; 64 | 65 | if (!event) { 66 | throw new Error('Event was invalid.'); 67 | } 68 | 69 | if (typeof event === 'string') { 70 | subscribers = this.eventLookup[event]; 71 | if (subscribers) { 72 | subscribers = subscribers.slice(); 73 | i = subscribers.length; 74 | 75 | while (i--) { 76 | invokeCallback(subscribers[i], data, event); 77 | } 78 | } 79 | } else { 80 | subscribers = this.messageHandlers.slice(); 81 | i = subscribers.length; 82 | 83 | while (i--) { 84 | invokeHandler(subscribers[i], event); 85 | } 86 | } 87 | }; 88 | 89 | EventAggregator.prototype.subscribe = function subscribe(event, callback) { 90 | var handler = void 0; 91 | var subscribers = void 0; 92 | 93 | if (!event) { 94 | throw new Error('Event channel/type was invalid.'); 95 | } 96 | 97 | if (typeof event === 'string') { 98 | handler = callback; 99 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 100 | } else { 101 | handler = new Handler(event, callback); 102 | subscribers = this.messageHandlers; 103 | } 104 | 105 | subscribers.push(handler); 106 | 107 | return { 108 | dispose: function dispose() { 109 | var idx = subscribers.indexOf(handler); 110 | if (idx !== -1) { 111 | subscribers.splice(idx, 1); 112 | } 113 | } 114 | }; 115 | }; 116 | 117 | EventAggregator.prototype.subscribeOnce = function subscribeOnce(event, callback) { 118 | var sub = this.subscribe(event, function (a, b) { 119 | sub.dispose(); 120 | return callback(a, b); 121 | }); 122 | 123 | return sub; 124 | }; 125 | 126 | return EventAggregator; 127 | }(); 128 | 129 | function includeEventsIn(obj) { 130 | var ea = new EventAggregator(); 131 | 132 | obj.subscribeOnce = function (event, callback) { 133 | return ea.subscribeOnce(event, callback); 134 | }; 135 | 136 | obj.subscribe = function (event, callback) { 137 | return ea.subscribe(event, callback); 138 | }; 139 | 140 | obj.publish = function (event, data) { 141 | ea.publish(event, data); 142 | }; 143 | 144 | return ea; 145 | } 146 | 147 | function configure(config) { 148 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 149 | } -------------------------------------------------------------------------------- /dist/commonjs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _aureliaEventAggregator = require('./aurelia-event-aggregator'); 8 | 9 | Object.keys(_aureliaEventAggregator).forEach(function (key) { 10 | if (key === "default" || key === "__esModule") return; 11 | Object.defineProperty(exports, key, { 12 | enumerable: true, 13 | get: function get() { 14 | return _aureliaEventAggregator[key]; 15 | } 16 | }); 17 | }); -------------------------------------------------------------------------------- /dist/es2015/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | import * as LogManager from 'aurelia-logging'; 2 | 3 | const logger = LogManager.getLogger('event-aggregator'); 4 | 5 | let Handler = class Handler { 6 | constructor(messageType, callback) { 7 | this.messageType = messageType; 8 | this.callback = callback; 9 | } 10 | 11 | handle(message) { 12 | if (message instanceof this.messageType) { 13 | this.callback.call(null, message); 14 | } 15 | } 16 | }; 17 | 18 | 19 | function invokeCallback(callback, data, event) { 20 | try { 21 | callback(data, event); 22 | } catch (e) { 23 | logger.error(e); 24 | } 25 | } 26 | 27 | function invokeHandler(handler, data) { 28 | try { 29 | handler.handle(data); 30 | } catch (e) { 31 | logger.error(e); 32 | } 33 | } 34 | 35 | export let EventAggregator = class EventAggregator { 36 | constructor() { 37 | this.eventLookup = {}; 38 | this.messageHandlers = []; 39 | } 40 | 41 | publish(event, data) { 42 | let subscribers; 43 | let i; 44 | 45 | if (!event) { 46 | throw new Error('Event was invalid.'); 47 | } 48 | 49 | if (typeof event === 'string') { 50 | subscribers = this.eventLookup[event]; 51 | if (subscribers) { 52 | subscribers = subscribers.slice(); 53 | i = subscribers.length; 54 | 55 | while (i--) { 56 | invokeCallback(subscribers[i], data, event); 57 | } 58 | } 59 | } else { 60 | subscribers = this.messageHandlers.slice(); 61 | i = subscribers.length; 62 | 63 | while (i--) { 64 | invokeHandler(subscribers[i], event); 65 | } 66 | } 67 | } 68 | 69 | subscribe(event, callback) { 70 | let handler; 71 | let subscribers; 72 | 73 | if (!event) { 74 | throw new Error('Event channel/type was invalid.'); 75 | } 76 | 77 | if (typeof event === 'string') { 78 | handler = callback; 79 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 80 | } else { 81 | handler = new Handler(event, callback); 82 | subscribers = this.messageHandlers; 83 | } 84 | 85 | subscribers.push(handler); 86 | 87 | return { 88 | dispose() { 89 | let idx = subscribers.indexOf(handler); 90 | if (idx !== -1) { 91 | subscribers.splice(idx, 1); 92 | } 93 | } 94 | }; 95 | } 96 | 97 | subscribeOnce(event, callback) { 98 | let sub = this.subscribe(event, (a, b) => { 99 | sub.dispose(); 100 | return callback(a, b); 101 | }); 102 | 103 | return sub; 104 | } 105 | }; 106 | 107 | export function includeEventsIn(obj) { 108 | let ea = new EventAggregator(); 109 | 110 | obj.subscribeOnce = function (event, callback) { 111 | return ea.subscribeOnce(event, callback); 112 | }; 113 | 114 | obj.subscribe = function (event, callback) { 115 | return ea.subscribe(event, callback); 116 | }; 117 | 118 | obj.publish = function (event, data) { 119 | ea.publish(event, data); 120 | }; 121 | 122 | return ea; 123 | } 124 | 125 | export function configure(config) { 126 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 127 | } -------------------------------------------------------------------------------- /dist/es2015/index.js: -------------------------------------------------------------------------------- 1 | export * from './aurelia-event-aggregator'; -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from 'aurelia-event-aggregator/aurelia-event-aggregator'; -------------------------------------------------------------------------------- /dist/native-modules/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | import * as LogManager from 'aurelia-logging'; 4 | 5 | var logger = LogManager.getLogger('event-aggregator'); 6 | 7 | var Handler = function () { 8 | function Handler(messageType, callback) { 9 | 10 | 11 | this.messageType = messageType; 12 | this.callback = callback; 13 | } 14 | 15 | Handler.prototype.handle = function handle(message) { 16 | if (message instanceof this.messageType) { 17 | this.callback.call(null, message); 18 | } 19 | }; 20 | 21 | return Handler; 22 | }(); 23 | 24 | function invokeCallback(callback, data, event) { 25 | try { 26 | callback(data, event); 27 | } catch (e) { 28 | logger.error(e); 29 | } 30 | } 31 | 32 | function invokeHandler(handler, data) { 33 | try { 34 | handler.handle(data); 35 | } catch (e) { 36 | logger.error(e); 37 | } 38 | } 39 | 40 | export var EventAggregator = function () { 41 | function EventAggregator() { 42 | 43 | 44 | this.eventLookup = {}; 45 | this.messageHandlers = []; 46 | } 47 | 48 | EventAggregator.prototype.publish = function publish(event, data) { 49 | var subscribers = void 0; 50 | var i = void 0; 51 | 52 | if (!event) { 53 | throw new Error('Event was invalid.'); 54 | } 55 | 56 | if (typeof event === 'string') { 57 | subscribers = this.eventLookup[event]; 58 | if (subscribers) { 59 | subscribers = subscribers.slice(); 60 | i = subscribers.length; 61 | 62 | while (i--) { 63 | invokeCallback(subscribers[i], data, event); 64 | } 65 | } 66 | } else { 67 | subscribers = this.messageHandlers.slice(); 68 | i = subscribers.length; 69 | 70 | while (i--) { 71 | invokeHandler(subscribers[i], event); 72 | } 73 | } 74 | }; 75 | 76 | EventAggregator.prototype.subscribe = function subscribe(event, callback) { 77 | var handler = void 0; 78 | var subscribers = void 0; 79 | 80 | if (!event) { 81 | throw new Error('Event channel/type was invalid.'); 82 | } 83 | 84 | if (typeof event === 'string') { 85 | handler = callback; 86 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 87 | } else { 88 | handler = new Handler(event, callback); 89 | subscribers = this.messageHandlers; 90 | } 91 | 92 | subscribers.push(handler); 93 | 94 | return { 95 | dispose: function dispose() { 96 | var idx = subscribers.indexOf(handler); 97 | if (idx !== -1) { 98 | subscribers.splice(idx, 1); 99 | } 100 | } 101 | }; 102 | }; 103 | 104 | EventAggregator.prototype.subscribeOnce = function subscribeOnce(event, callback) { 105 | var sub = this.subscribe(event, function (a, b) { 106 | sub.dispose(); 107 | return callback(a, b); 108 | }); 109 | 110 | return sub; 111 | }; 112 | 113 | return EventAggregator; 114 | }(); 115 | 116 | export function includeEventsIn(obj) { 117 | var ea = new EventAggregator(); 118 | 119 | obj.subscribeOnce = function (event, callback) { 120 | return ea.subscribeOnce(event, callback); 121 | }; 122 | 123 | obj.subscribe = function (event, callback) { 124 | return ea.subscribe(event, callback); 125 | }; 126 | 127 | obj.publish = function (event, data) { 128 | ea.publish(event, data); 129 | }; 130 | 131 | return ea; 132 | } 133 | 134 | export function configure(config) { 135 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 136 | } -------------------------------------------------------------------------------- /dist/native-modules/index.js: -------------------------------------------------------------------------------- 1 | export * from './aurelia-event-aggregator'; -------------------------------------------------------------------------------- /dist/system/aurelia-event-aggregator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | System.register(['aurelia-logging'], function (_export, _context) { 4 | "use strict"; 5 | 6 | var LogManager, logger, Handler, EventAggregator; 7 | 8 | 9 | 10 | function invokeCallback(callback, data, event) { 11 | try { 12 | callback(data, event); 13 | } catch (e) { 14 | logger.error(e); 15 | } 16 | } 17 | 18 | function invokeHandler(handler, data) { 19 | try { 20 | handler.handle(data); 21 | } catch (e) { 22 | logger.error(e); 23 | } 24 | } 25 | 26 | function includeEventsIn(obj) { 27 | var ea = new EventAggregator(); 28 | 29 | obj.subscribeOnce = function (event, callback) { 30 | return ea.subscribeOnce(event, callback); 31 | }; 32 | 33 | obj.subscribe = function (event, callback) { 34 | return ea.subscribe(event, callback); 35 | }; 36 | 37 | obj.publish = function (event, data) { 38 | ea.publish(event, data); 39 | }; 40 | 41 | return ea; 42 | } 43 | 44 | _export('includeEventsIn', includeEventsIn); 45 | 46 | function configure(config) { 47 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 48 | } 49 | 50 | _export('configure', configure); 51 | 52 | return { 53 | setters: [function (_aureliaLogging) { 54 | LogManager = _aureliaLogging; 55 | }], 56 | execute: function () { 57 | logger = LogManager.getLogger('event-aggregator'); 58 | 59 | Handler = function () { 60 | function Handler(messageType, callback) { 61 | 62 | 63 | this.messageType = messageType; 64 | this.callback = callback; 65 | } 66 | 67 | Handler.prototype.handle = function handle(message) { 68 | if (message instanceof this.messageType) { 69 | this.callback.call(null, message); 70 | } 71 | }; 72 | 73 | return Handler; 74 | }(); 75 | 76 | _export('EventAggregator', EventAggregator = function () { 77 | function EventAggregator() { 78 | 79 | 80 | this.eventLookup = {}; 81 | this.messageHandlers = []; 82 | } 83 | 84 | EventAggregator.prototype.publish = function publish(event, data) { 85 | var subscribers = void 0; 86 | var i = void 0; 87 | 88 | if (!event) { 89 | throw new Error('Event was invalid.'); 90 | } 91 | 92 | if (typeof event === 'string') { 93 | subscribers = this.eventLookup[event]; 94 | if (subscribers) { 95 | subscribers = subscribers.slice(); 96 | i = subscribers.length; 97 | 98 | while (i--) { 99 | invokeCallback(subscribers[i], data, event); 100 | } 101 | } 102 | } else { 103 | subscribers = this.messageHandlers.slice(); 104 | i = subscribers.length; 105 | 106 | while (i--) { 107 | invokeHandler(subscribers[i], event); 108 | } 109 | } 110 | }; 111 | 112 | EventAggregator.prototype.subscribe = function subscribe(event, callback) { 113 | var handler = void 0; 114 | var subscribers = void 0; 115 | 116 | if (!event) { 117 | throw new Error('Event channel/type was invalid.'); 118 | } 119 | 120 | if (typeof event === 'string') { 121 | handler = callback; 122 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 123 | } else { 124 | handler = new Handler(event, callback); 125 | subscribers = this.messageHandlers; 126 | } 127 | 128 | subscribers.push(handler); 129 | 130 | return { 131 | dispose: function dispose() { 132 | var idx = subscribers.indexOf(handler); 133 | if (idx !== -1) { 134 | subscribers.splice(idx, 1); 135 | } 136 | } 137 | }; 138 | }; 139 | 140 | EventAggregator.prototype.subscribeOnce = function subscribeOnce(event, callback) { 141 | var sub = this.subscribe(event, function (a, b) { 142 | sub.dispose(); 143 | return callback(a, b); 144 | }); 145 | 146 | return sub; 147 | }; 148 | 149 | return EventAggregator; 150 | }()); 151 | 152 | _export('EventAggregator', EventAggregator); 153 | } 154 | }; 155 | }); -------------------------------------------------------------------------------- /dist/system/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | System.register(['./aurelia-event-aggregator'], function (_export, _context) { 4 | "use strict"; 5 | 6 | return { 7 | setters: [function (_aureliaEventAggregator) { 8 | var _exportObj = {}; 9 | 10 | for (var _key in _aureliaEventAggregator) { 11 | if (_key !== "default" && _key !== "__esModule") _exportObj[_key] = _aureliaEventAggregator[_key]; 12 | } 13 | 14 | _export(_exportObj); 15 | }], 16 | execute: function () {} 17 | }; 18 | }); -------------------------------------------------------------------------------- /doc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [1.0.4](https://github.com/aurelia/event-aggregator/compare/1.0.2...1.0.4) (2019-03-27) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * **all:** change es2015 back to native-modules ([38c3b31](https://github.com/aurelia/event-aggregator/commit/38c3b31)) 8 | 9 | 10 | 11 | 12 | ## [1.0.3](https://github.com/aurelia/event-aggregator/compare/1.0.2...1.0.3) (2019-02-04) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * **all:** change es2015 back to native-modules ([38c3b31](https://github.com/aurelia/event-aggregator/commit/38c3b31)) 18 | 19 | 20 | 21 | 22 | ## [1.0.2](https://github.com/aurelia/event-aggregator/compare/1.0.1...1.0.2) (2019-01-18) 23 | 24 | * Add module field to package.json 25 | 26 | 27 | ## [1.0.1](https://github.com/aurelia/event-aggregator/compare/1.0.0...v1.0.1) (2016-12-03) 28 | 29 | 30 | ### Bug Fixes 31 | 32 | * **index:** handle errors per callback invocation ([dc7819f](https://github.com/aurelia/event-aggregator/commit/dc7819f)) 33 | 34 | 35 | 36 | 37 | # [1.0.0](https://github.com/aurelia/event-aggregator/compare/1.0.0-rc.1.0.0...v1.0.0) (2016-07-27) 38 | 39 | 40 | 41 | 42 | # [1.0.0-rc.1.0.0](https://github.com/aurelia/event-aggregator/compare/1.0.0-beta.2.0.1...v1.0.0-rc.1.0.0) (2016-06-22) 43 | 44 | 45 | 46 | ### 1.0.0-beta.1.2.1 (2016-05-10) 47 | 48 | 49 | ### 1.0.0-beta.1.2.0 (2016-03-22) 50 | 51 | * Update to Babel 6 52 | 53 | ### 1.0.0-beta.1.1.1 (2016-02-08) 54 | 55 | 56 | #### Bug Fixes 57 | 58 | * **index:** add some error checking to guard args ([e1661a00](http://github.com/aurelia/event-aggregator/commit/e1661a00ff9894891a59cd8dfd3f5d83964de158), closes [#15](http://github.com/aurelia/event-aggregator/issues/15)) 59 | 60 | 61 | ### 1.0.0-beta.1.1.0 (2016-01-29) 62 | 63 | 64 | #### Features 65 | 66 | * **all:** update jspm meta; core-js; aurelia deps ([05e6674d](http://github.com/aurelia/event-aggregator/commit/05e6674d13d393e6813dda656a8e79ba75b85aa8)) 67 | 68 | 69 | ### 1.0.0-beta.1 (2015-11-16) 70 | 71 | 72 | ## 0.10.0 (2015-11-10) 73 | 74 | 75 | ## 0.9.0 (2015-10-13) 76 | 77 | 78 | #### Bug Fixes 79 | 80 | * **all:** 81 | * update to latest plugin api ([2a17472d](http://github.com/aurelia/event-aggregator/commit/2a17472dba61e6d6f364207d2ba438e65a97ed87)) 82 | * upgrade to latest compiler ([ae84b313](http://github.com/aurelia/event-aggregator/commit/ae84b3139c1cc906614a904d78935e06a7959fde)) 83 | * **build:** 84 | * update linting, testing and tools ([172366a4](http://github.com/aurelia/event-aggregator/commit/172366a4e3ce6b97c16fc0f6af96e2e32114ba2e)) 85 | * add missing bower bump ([31130469](http://github.com/aurelia/event-aggregator/commit/31130469776c1518355122d8d61577d4fefd6c8b)) 86 | * **event-aggregator:** removing another callback when called twice ([50e01cd7](http://github.com/aurelia/event-aggregator/commit/50e01cd7d882aaef49b7ff892b324ed4088e0b15)) 87 | * **index:** 88 | * update to latest framework configuration api ([87083a44](http://github.com/aurelia/event-aggregator/commit/87083a44abaf411f694460ff7308c17c43b682b3)) 89 | * remove invalid character ([96642658](http://github.com/aurelia/event-aggregator/commit/96642658caf7d90733a0e103980841ccbbc43eb8)) 90 | * **package:** change jspm directories ([84c67fbc](http://github.com/aurelia/event-aggregator/commit/84c67fbc43971830255d20a08d726de9565b6dbd)) 91 | * **publish:** catch errors thrown in subscribers ([9dafe002](http://github.com/aurelia/event-aggregator/commit/9dafe002f1b2d8fbda5211495bb1de06c0b58c90)) 92 | 93 | 94 | #### Features 95 | 96 | * **all:** 97 | * subscribe methods now return subscription object with dispose method ([862cb83f](http://github.com/aurelia/event-aggregator/commit/862cb83f2f1a3979fc39a90dbdbff4b1369dd252), closes [#10](http://github.com/aurelia/event-aggregator/issues/10)) 98 | * add more type info ([7b08cae1](http://github.com/aurelia/event-aggregator/commit/7b08cae11ecc11c6e6130cfdfa9ded657c565ff4)) 99 | * **build:** update compiler and switch to register module format ([302c2870](http://github.com/aurelia/event-aggregator/commit/302c287092d9812a3d2c7e5fca2c1bb20618fffc)) 100 | * **docs:** generate api.json from .d.ts file ([36ac335d](http://github.com/aurelia/event-aggregator/commit/36ac335d10d43b02fb0c4402dcfceb8946a89222)) 101 | * **event-aggregator:** 102 | * subscribeOnce function ([076264e7](http://github.com/aurelia/event-aggregator/commit/076264e7ffc2bcec090b4c4339671262ffb8238d)) 103 | * enable plugin usage ([2c597329](http://github.com/aurelia/event-aggregator/commit/2c5973292dbd5087325226298ae966b1dcb7ac17)) 104 | 105 | 106 | ## 0.8.0 (2015-09-04) 107 | 108 | 109 | #### Bug Fixes 110 | 111 | * **build:** update linting, testing and tools ([172366a4](http://github.com/aurelia/event-aggregator/commit/172366a4e3ce6b97c16fc0f6af96e2e32114ba2e)) 112 | 113 | 114 | #### Features 115 | 116 | * **docs:** generate api.json from .d.ts file ([36ac335d](http://github.com/aurelia/event-aggregator/commit/36ac335d10d43b02fb0c4402dcfceb8946a89222)) 117 | 118 | 119 | ## 0.7.0 (2015-08-14) 120 | 121 | 122 | #### Bug Fixes 123 | 124 | * **index:** update to latest framework configuration api ([87083a44](http://github.com/aurelia/event-aggregator/commit/87083a44abaf411f694460ff7308c17c43b682b3)) 125 | 126 | 127 | #### Features 128 | 129 | * **all:** add more type info ([7b08cae1](http://github.com/aurelia/event-aggregator/commit/7b08cae11ecc11c6e6130cfdfa9ded657c565ff4)) 130 | 131 | 132 | ### 0.6.2 (2015-07-29) 133 | 134 | * improve output file name 135 | 136 | ### 0.6.1 (2015-07-07) 137 | 138 | 139 | ## 0.6.0 (2015-07-02) 140 | 141 | 142 | ## 0.5.0 (2015-06-08) 143 | 144 | 145 | #### Bug Fixes 146 | 147 | * **publish:** catch errors thrown in subscribers ([9dafe002](http://github.com/aurelia/event-aggregator/commit/9dafe002f1b2d8fbda5211495bb1de06c0b58c90)) 148 | 149 | 150 | ## 0.4.0 (2015-04-30) 151 | 152 | 153 | #### Bug Fixes 154 | 155 | * **all:** update to latest plugin api ([2a17472d](http://github.com/aurelia/event-aggregator/commit/2a17472dba61e6d6f364207d2ba438e65a97ed87)) 156 | * **event-aggregator:** removing another callback when called twice ([50e01cd7](http://github.com/aurelia/event-aggregator/commit/50e01cd7d882aaef49b7ff892b324ed4088e0b15)) 157 | 158 | 159 | ## 0.3.0 (2015-04-09) 160 | 161 | 162 | #### Bug Fixes 163 | 164 | * **all:** upgrade to latest compiler ([ae84b313](http://github.com/aurelia/event-aggregator/commit/ae84b3139c1cc906614a904d78935e06a7959fde)) 165 | 166 | 167 | #### Features 168 | 169 | * **event-aggregator:** subscribeOnce function ([076264e7](http://github.com/aurelia/event-aggregator/commit/076264e7ffc2bcec090b4c4339671262ffb8238d)) 170 | 171 | 172 | ### 0.2.4 (2015-02-28) 173 | 174 | 175 | #### Bug Fixes 176 | 177 | * **package:** change jspm directories ([84c67fbc](http://github.com/aurelia/event-aggregator/commit/84c67fbc43971830255d20a08d726de9565b6dbd)) 178 | 179 | 180 | ### 0.2.3 (2015-02-28) 181 | 182 | 183 | #### Bug Fixes 184 | 185 | * **build:** add missing bower bump ([31130469](http://github.com/aurelia/event-aggregator/commit/31130469776c1518355122d8d61577d4fefd6c8b)) 186 | 187 | 188 | ### 0.2.2 (2015-01-22) 189 | 190 | * Update compiler. 191 | 192 | ### 0.2.1 (2015-01-12) 193 | 194 | * Updated compiled output. 195 | 196 | ## 0.2.0 (2015-01-06) 197 | 198 | 199 | #### Bug Fixes 200 | 201 | * **index:** remove invalid character ([96642658](http://github.com/aurelia/event-aggregator/commit/96642658caf7d90733a0e103980841ccbbc43eb8)) 202 | 203 | 204 | #### Features 205 | 206 | * **build:** update compiler and switch to register module format ([302c2870](http://github.com/aurelia/event-aggregator/commit/302c287092d9812a3d2c7e5fca2c1bb20618fffc)) 207 | * **event-aggregator:** enable plugin usage ([2c597329](http://github.com/aurelia/event-aggregator/commit/2c5973292dbd5087325226298ae966b1dcb7ac17)) 208 | -------------------------------------------------------------------------------- /doc/api.json: -------------------------------------------------------------------------------- 1 | {"name":"aurelia-event-aggregator","children":[{"id":5,"name":"EventAggregator","kind":128,"kindString":"Class","flags":{"isExported":true},"comment":{"shortText":"Enables loosely coupled publish/subscribe messaging."},"children":[{"id":6,"name":"constructor","kind":512,"kindString":"Constructor","flags":{"isExported":true},"comment":{"shortText":"Creates an instance of the EventAggregator class."},"signatures":[{"id":7,"name":"new EventAggregator","kind":16384,"kindString":"Constructor signature","flags":{},"comment":{"shortText":"Creates an instance of the EventAggregator class."},"type":{"type":"reference","name":"EventAggregator","id":5}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":20,"character":38}]},{"id":8,"name":"publish","kind":2048,"kindString":"Method","flags":{"isExported":true},"signatures":[{"id":9,"name":"publish","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Publishes a message."},"parameters":[{"id":10,"name":"event","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The event or channel to publish to."},"type":{"type":"union","types":[{"type":"instrinct","name":"string"},{"type":"instrinct","name":"any"}]}},{"id":11,"name":"data","kind":32768,"kindString":"Parameter","flags":{"isOptional":true},"comment":{"text":"The data to publish on the channel.\n"},"type":{"type":"instrinct","name":"any"}}],"type":{"type":"instrinct","name":"void"}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":32,"character":9}]},{"id":12,"name":"subscribe","kind":2048,"kindString":"Method","flags":{"isExported":true},"signatures":[{"id":13,"name":"subscribe","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Subscribes to a message channel or message type."},"parameters":[{"id":14,"name":"event","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The event channel or event data type."},"type":{"type":"union","types":[{"type":"instrinct","name":"string"},{"type":"reference","name":"Function"}]}},{"id":15,"name":"callback","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The callback to be invoked when the specified message is published.\n"},"type":{"type":"reference","name":"Function"}}],"type":{"type":"reference","name":"Subscription","id":2}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":39,"character":11}]},{"id":16,"name":"subscribeOnce","kind":2048,"kindString":"Method","flags":{"isExported":true},"signatures":[{"id":17,"name":"subscribeOnce","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Subscribes to a message channel or message type, then disposes the subscription automatically after the first message is received."},"parameters":[{"id":18,"name":"event","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The event channel or event data type."},"type":{"type":"union","types":[{"type":"instrinct","name":"string"},{"type":"reference","name":"Function"}]}},{"id":19,"name":"callback","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The callback to be invoked when the specified message is published.\n"},"type":{"type":"reference","name":"Function"}}],"type":{"type":"reference","name":"Subscription","id":2}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":46,"character":15}]}],"groups":[{"title":"Constructors","kind":512,"children":[6]},{"title":"Methods","kind":2048,"children":[8,12,16]}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":20,"character":36}]},{"id":2,"name":"Subscription","kind":256,"kindString":"Interface","flags":{"isExported":true},"comment":{"shortText":"Represents a disposable subsciption to an EventAggregator event."},"children":[{"id":3,"name":"dispose","kind":2048,"kindString":"Method","flags":{"isExported":true},"signatures":[{"id":4,"name":"dispose","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Disposes the subscription."},"type":{"type":"instrinct","name":"void"}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":11,"character":9}]}],"groups":[{"title":"Methods","kind":2048,"children":[3]}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":6,"character":37}]},{"id":23,"name":"configure","kind":64,"kindString":"Function","flags":{"isExported":true},"signatures":[{"id":24,"name":"configure","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Configures a global EA by merging functionality into the Aurelia instance."},"parameters":[{"id":25,"name":"config","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The Aurelia Framework configuration object used to configure the plugin.\n"},"type":{"type":"reference","name":"Object"}}],"type":{"type":"instrinct","name":"void"}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":59,"character":33}]},{"id":20,"name":"includeEventsIn","kind":64,"kindString":"Function","flags":{"isExported":true},"signatures":[{"id":21,"name":"includeEventsIn","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Includes EA functionality into an object instance."},"parameters":[{"id":22,"name":"obj","kind":32768,"kindString":"Parameter","flags":{},"comment":{"text":"The object to mix Event Aggregator functionality into.\n"},"type":{"type":"reference","name":"Object"}}],"type":{"type":"reference","name":"EventAggregator","id":5}}],"sources":[{"fileName":"aurelia-event-aggregator.d.ts","line":53,"character":39}]}],"groups":[{"title":"Classes","kind":128,"children":[5]},{"title":"Interfaces","kind":256,"children":[2]},{"title":"Functions","kind":64,"children":[23,20]}]} -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | require('require-dir')('build/tasks'); 2 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Dec 05 2014 16:49:29 GMT-0500 (EST) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jspm', 'jasmine'], 14 | 15 | jspm: { 16 | // Edit this to your needs 17 | loadFiles: ['src/**/*.js', 'test/**/*.js'] 18 | }, 19 | 20 | 21 | // list of files / patterns to load in the browser 22 | files: [], 23 | 24 | 25 | // list of files to exclude 26 | exclude: [ 27 | ], 28 | 29 | 30 | // preprocess matching files before serving them to the browser 31 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 32 | preprocessors: { 33 | 'test/**/*.js': ['babel'], 34 | 'src/**/*.js': ['babel'] 35 | }, 36 | 'babelPreprocessor': { 37 | options: { 38 | sourceMap: 'inline', 39 | presets: [ 'es2015-loose', 'stage-1'], 40 | plugins: [ 41 | 'syntax-flow', 42 | 'transform-decorators-legacy', 43 | 'transform-flow-strip-types' 44 | ] 45 | } 46 | }, 47 | 48 | // test results reporter to use 49 | // possible values: 'dots', 'progress' 50 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 51 | reporters: ['progress'], 52 | 53 | 54 | // web server port 55 | port: 9876, 56 | 57 | 58 | // enable / disable colors in the output (reporters and logs) 59 | colors: true, 60 | 61 | 62 | // level of logging 63 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 64 | logLevel: config.LOG_INFO, 65 | 66 | 67 | // enable / disable watching file and executing tests whenever any file changes 68 | autoWatch: true, 69 | 70 | 71 | // start these browsers 72 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 73 | browsers: ['Chrome'], 74 | 75 | 76 | // Continuous Integration mode 77 | // if true, Karma captures browsers, runs the tests and exits 78 | singleRun: false 79 | }); 80 | }; 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-event-aggregator", 3 | "version": "1.0.4", 4 | "description": "A lightweight pub/sub messaging system for app-wide or per-object loosely coupled events.", 5 | "keywords": [ 6 | "aurelia", 7 | "event aggregator", 8 | "events", 9 | "pub/sub" 10 | ], 11 | "scripts": { 12 | "test": "karma start --single-run", 13 | "build": "gulp build", 14 | "cut-release": "gulp prepare-release" 15 | }, 16 | "homepage": "http://aurelia.io", 17 | "bugs": { 18 | "url": "https://github.com/aurelia/event-aggregator/issues" 19 | }, 20 | "license": "MIT", 21 | "author": "Rob Eisenberg (http://robeisenberg.com/)", 22 | "main": "dist/commonjs/aurelia-event-aggregator.js", 23 | "module": "dist/native-modules/aurelia-event-aggregator.js", 24 | "typings": "dist/aurelia-event-aggregator.d.ts", 25 | "repository": { 26 | "type": "git", 27 | "url": "http://github.com/aurelia/event-aggregator" 28 | }, 29 | "files": [ 30 | "dist", 31 | "doc", 32 | "src", 33 | "typings.json", 34 | "README.md", 35 | "LICENSE" 36 | ], 37 | "jspm": { 38 | "registry": "npm", 39 | "main": "aurelia-event-aggregator", 40 | "format": "amd", 41 | "directories": { 42 | "dist": "dist/amd" 43 | }, 44 | "dependencies": { 45 | "aurelia-logging": "^1.0.0" 46 | }, 47 | "devDependencies": { 48 | "babel": "babel-core@^5.1.13", 49 | "babel-runtime": "^5.1.13", 50 | "core-js": "^2.0.3" 51 | } 52 | }, 53 | "dependencies": { 54 | "aurelia-logging": "^1.0.0" 55 | }, 56 | "devDependencies": { 57 | "aurelia-tools": "^0.2.4", 58 | "babel-dts-generator": "^0.6.1", 59 | "babel-eslint": "^6.1.2", 60 | "babel-plugin-syntax-flow": "^6.8.0", 61 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 62 | "babel-plugin-transform-es2015-modules-amd": "^6.8.0", 63 | "babel-plugin-transform-es2015-modules-commonjs": "^6.11.5", 64 | "babel-plugin-transform-es2015-modules-systemjs": "^6.11.6", 65 | "babel-plugin-transform-flow-strip-types": "^6.8.0", 66 | "babel-preset-es2015": "^6.9.0", 67 | "babel-preset-es2015-loose": "^7.0.0", 68 | "babel-preset-es2015-loose-native-modules": "^1.0.0", 69 | "babel-preset-stage-1": "^6.5.0", 70 | "del": "^2.2.1", 71 | "gulp": "^3.9.1", 72 | "gulp-babel": "^6.1.2", 73 | "gulp-bump": "^2.2.0", 74 | "gulp-concat": "^2.6.0", 75 | "gulp-conventional-changelog": "^1.1.0", 76 | "gulp-eslint": "^3.0.1", 77 | "gulp-ignore": "^2.0.1", 78 | "gulp-insert": "^0.5.0", 79 | "gulp-rename": "^1.2.2", 80 | "gulp-typedoc": "^2.0.0", 81 | "gulp-typedoc-extractor": "^0.0.8", 82 | "gulp-typescript": "^2.13.6", 83 | "gulp-util": "^3.0.7", 84 | "jasmine-core": "^2.4.1", 85 | "jspm": "^0.16.53", 86 | "karma": "^1.1.2", 87 | "karma-babel-preprocessor": "^6.0.1", 88 | "karma-chrome-launcher": "^1.0.1", 89 | "karma-coverage": "^1.1.1", 90 | "karma-jasmine": "^1.0.2", 91 | "karma-jspm": "^2.2.0", 92 | "merge2": "^1.0.2", 93 | "object.assign": "^4.0.4", 94 | "require-dir": "^0.3.0", 95 | "run-sequence": "^1.2.2", 96 | "through2": "^2.0.1", 97 | "typedoc": "^0.4.4", 98 | "typescript": "^1.9.0-dev.20160622-1.0", 99 | "vinyl": "^1.1.1", 100 | "vinyl-paths": "^2.1.0", 101 | "yargs": "^4.8.1" 102 | }, 103 | "aurelia": { 104 | "documentation": { 105 | "articles": [] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import * as LogManager from 'aurelia-logging'; 2 | 3 | const logger = LogManager.getLogger('event-aggregator'); 4 | 5 | class Handler { 6 | constructor(messageType, callback) { 7 | this.messageType = messageType; 8 | this.callback = callback; 9 | } 10 | 11 | handle(message) { 12 | if (message instanceof this.messageType) { 13 | this.callback.call(null, message); 14 | } 15 | } 16 | } 17 | 18 | function invokeCallback(callback, data, event) { 19 | try { 20 | callback(data, event); 21 | } catch (e) { 22 | logger.error(e); 23 | } 24 | } 25 | 26 | function invokeHandler(handler, data) { 27 | try { 28 | handler.handle(data); 29 | } catch (e) { 30 | logger.error(e); 31 | } 32 | } 33 | 34 | /** 35 | * Represents a disposable subsciption to an EventAggregator event. 36 | */ 37 | interface Subscription { 38 | /** 39 | * Disposes the subscription. 40 | */ 41 | dispose(): void; 42 | } 43 | 44 | /** 45 | * Enables loosely coupled publish/subscribe messaging. 46 | */ 47 | export class EventAggregator { 48 | /** 49 | * Creates an instance of the EventAggregator class. 50 | */ 51 | constructor() { 52 | this.eventLookup = {}; 53 | this.messageHandlers = []; 54 | } 55 | 56 | /** 57 | * Publishes a message. 58 | * @param event The event or channel to publish to. 59 | * @param data The data to publish on the channel. 60 | */ 61 | publish(event: string | any, data?: any): void { 62 | let subscribers; 63 | let i; 64 | 65 | if (!event) { 66 | throw new Error('Event was invalid.'); 67 | } 68 | 69 | if (typeof event === 'string') { 70 | subscribers = this.eventLookup[event]; 71 | if (subscribers) { 72 | subscribers = subscribers.slice(); 73 | i = subscribers.length; 74 | 75 | while (i--) { 76 | invokeCallback(subscribers[i], data, event); 77 | } 78 | } 79 | } else { 80 | subscribers = this.messageHandlers.slice(); 81 | i = subscribers.length; 82 | 83 | while (i--) { 84 | invokeHandler(subscribers[i], event); 85 | } 86 | } 87 | } 88 | 89 | /** 90 | * Subscribes to a message channel or message type. 91 | * @param event The event channel or event data type. 92 | * @param callback The callback to be invoked when the specified message is published. 93 | */ 94 | subscribe(event: string | Function, callback: Function): Subscription { 95 | let handler; 96 | let subscribers; 97 | 98 | if (!event) { 99 | throw new Error('Event channel/type was invalid.'); 100 | } 101 | 102 | if (typeof event === 'string') { 103 | handler = callback; 104 | subscribers = this.eventLookup[event] || (this.eventLookup[event] = []); 105 | } else { 106 | handler = new Handler(event, callback); 107 | subscribers = this.messageHandlers; 108 | } 109 | 110 | subscribers.push(handler); 111 | 112 | return { 113 | dispose() { 114 | let idx = subscribers.indexOf(handler); 115 | if (idx !== -1) { 116 | subscribers.splice(idx, 1); 117 | } 118 | } 119 | }; 120 | } 121 | 122 | /** 123 | * Subscribes to a message channel or message type, then disposes the subscription automatically after the first message is received. 124 | * @param event The event channel or event data type. 125 | * @param callback The callback to be invoked when the specified message is published. 126 | */ 127 | subscribeOnce(event: string | Function, callback: Function): Subscription { 128 | let sub = this.subscribe(event, (a, b) => { 129 | sub.dispose(); 130 | return callback(a, b); 131 | }); 132 | 133 | return sub; 134 | } 135 | } 136 | 137 | /** 138 | * Includes EA functionality into an object instance. 139 | * @param obj The object to mix Event Aggregator functionality into. 140 | */ 141 | export function includeEventsIn(obj: Object): EventAggregator { 142 | let ea = new EventAggregator(); 143 | 144 | obj.subscribeOnce = function(event, callback) { 145 | return ea.subscribeOnce(event, callback); 146 | }; 147 | 148 | obj.subscribe = function(event, callback) { 149 | return ea.subscribe(event, callback); 150 | }; 151 | 152 | obj.publish = function(event, data) { 153 | ea.publish(event, data); 154 | }; 155 | 156 | return ea; 157 | } 158 | 159 | /** 160 | * Configures a global EA by merging functionality into the Aurelia instance. 161 | * @param config The Aurelia Framework configuration object used to configure the plugin. 162 | */ 163 | export function configure(config: Object): void { 164 | config.instance(EventAggregator, includeEventsIn(config.aurelia)); 165 | } 166 | -------------------------------------------------------------------------------- /test/event-aggregator.spec.js: -------------------------------------------------------------------------------- 1 | import {EventAggregator} from '../src/index'; 2 | 3 | describe('event aggregator', () => { 4 | 5 | describe('subscribe', () => { 6 | 7 | describe('string events', () => { 8 | 9 | it('should not remove another callback when execute called twice', ()=>{ 10 | let ea = new EventAggregator(); 11 | let data = 0; 12 | 13 | let subscription = ea.subscribe('dinner', function() {}); 14 | ea.subscribe('dinner', function() { data = 1; }); 15 | 16 | subscription.dispose(); 17 | subscription.dispose(); 18 | 19 | ea.publish('dinner'); 20 | 21 | expect(data).toBe(1); 22 | }); 23 | 24 | it('adds event with callback to the eventLookup object', () =>{ 25 | let ea = new EventAggregator(); 26 | let callback = function(){}; 27 | ea.subscribe('dinner', callback); 28 | 29 | expect(ea.eventLookup.dinner.length).toBe(1); 30 | expect(ea.eventLookup.dinner[0]).toBe(callback); 31 | }); 32 | 33 | it('adds multiple callbacks the same event', () =>{ 34 | let ea = new EventAggregator(); 35 | let callback = function(){}; 36 | ea.subscribe('dinner', callback); 37 | 38 | let callback2 = function(){}; 39 | ea.subscribe('dinner', callback2); 40 | 41 | expect(ea.eventLookup.dinner.length).toBe(2); 42 | expect(ea.eventLookup.dinner[0]).toBe(callback); 43 | expect(ea.eventLookup.dinner[1]).toBe(callback2); 44 | }); 45 | 46 | it('removes the callback after execution', ()=>{ 47 | let ea = new EventAggregator(); 48 | 49 | let callback = function(){}; 50 | let subscription = ea.subscribe('dinner', callback); 51 | 52 | let callback2 = function(){}; 53 | let subscription2 = ea.subscribe('dinner', callback2); 54 | 55 | expect(ea.eventLookup.dinner.length).toBe(2); 56 | expect(ea.eventLookup.dinner[0]).toBe(callback); 57 | expect(ea.eventLookup.dinner[1]).toBe(callback2); 58 | 59 | subscription.dispose(); 60 | 61 | expect(ea.eventLookup.dinner.length).toBe(1); 62 | expect(ea.eventLookup.dinner[0]).toBe(callback2); 63 | 64 | subscription2.dispose(); 65 | expect(ea.eventLookup.dinner.length).toBe(0); 66 | }); 67 | 68 | it('will respond to an event any time it is published', ()=>{ 69 | let ea = new EventAggregator(); 70 | let callback = function(){}; 71 | ea.subscribe('dinner', callback); 72 | 73 | expect(ea.eventLookup.dinner.length).toBe(1); 74 | expect(ea.eventLookup.dinner[0]).toBe(callback); 75 | 76 | ea.publish('dinner'); 77 | ea.publish('dinner'); 78 | ea.publish('dinner'); 79 | 80 | expect(ea.eventLookup.dinner.length).toBe(1); 81 | expect(ea.eventLookup.dinner[0]).toBe(callback); 82 | }); 83 | 84 | it('will pass published data to the callback function', ()=>{ 85 | let ea = new EventAggregator(); 86 | let data = null; 87 | let callback = function(d){ data = d;}; 88 | ea.subscribe('dinner', callback); 89 | 90 | expect(ea.eventLookup.dinner.length).toBe(1); 91 | expect(ea.eventLookup.dinner[0]).toBe(callback); 92 | 93 | ea.publish('dinner',{foo:"bar"}); 94 | expect(data.foo).toBe("bar"); 95 | }); 96 | 97 | }); 98 | 99 | describe('handler events', () =>{ 100 | 101 | it('should not remove another handler when execute called twice', ()=>{ 102 | let ea = new EventAggregator(); 103 | let data = 0; 104 | 105 | let subscription = ea.subscribe(DinnerEvent, function() {}); 106 | ea.subscribe(AnotherDinnerEvent, function() { data = 1; }); 107 | 108 | subscription.dispose(); 109 | subscription.dispose(); 110 | 111 | ea.publish(new AnotherDinnerEvent("")); 112 | 113 | expect(data).toBe(1); 114 | }); 115 | 116 | it('adds handler with messageType and callback to the messageHandlers array', ()=>{ 117 | let ea = new EventAggregator(); 118 | let callback = function(){}; 119 | ea.subscribe(DinnerEvent, callback); 120 | 121 | expect(ea.messageHandlers.length).toBe(1); 122 | expect(ea.messageHandlers[0].messageType).toBe(DinnerEvent); 123 | expect(ea.messageHandlers[0].callback).toBe(callback); 124 | }); 125 | 126 | it('removes the handler after execution', () =>{ 127 | let ea = new EventAggregator(); 128 | let callback = function(){}; 129 | let subscription = ea.subscribe(DinnerEvent, callback); 130 | 131 | expect(ea.messageHandlers.length).toBe(1); 132 | subscription.dispose(); 133 | expect(ea.messageHandlers.length).toBe(0); 134 | }); 135 | 136 | }); 137 | 138 | }); 139 | 140 | describe('subscribeOnce', () =>{ 141 | 142 | describe('string events', () =>{ 143 | 144 | it('adds event with an anynomous function that will execute the callback to the eventLookup object', ()=>{ 145 | let ea = new EventAggregator(); 146 | let callback = function(){}; 147 | ea.subscribeOnce('dinner', callback); 148 | 149 | expect(ea.eventLookup.dinner.length).toBe(1); 150 | expect(ea.eventLookup.dinner[0] === callback).toBe(false); 151 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 152 | }); 153 | 154 | it('adds multiple callbacks the same event', () =>{ 155 | let ea = new EventAggregator(); 156 | let callback = function(){}; 157 | ea.subscribeOnce('dinner', callback); 158 | 159 | let callback2 = function(){}; 160 | ea.subscribeOnce('dinner', callback2); 161 | 162 | expect(ea.eventLookup.dinner.length).toBe(2); 163 | expect(ea.eventLookup.dinner[0] === callback).toBe(false); 164 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 165 | expect(ea.eventLookup.dinner[1] === callback).toBe(false); 166 | expect(typeof ea.eventLookup.dinner[1] === "function").toBe(true); 167 | }); 168 | 169 | it('removes the callback after execution', ()=>{ 170 | let ea = new EventAggregator(); 171 | let callback = function(){}; 172 | let subscription = ea.subscribeOnce('dinner', callback); 173 | 174 | let callback2 = function(){}; 175 | let subscription2 = ea.subscribeOnce('dinner', callback2); 176 | 177 | expect(ea.eventLookup.dinner.length).toBe(2); 178 | expect(ea.eventLookup.dinner[0] === callback).toBe(false); 179 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 180 | expect(ea.eventLookup.dinner[1] === callback2).toBe(false); 181 | expect(typeof ea.eventLookup.dinner[1] === "function").toBe(true); 182 | 183 | subscription.dispose(); 184 | 185 | expect(ea.eventLookup.dinner.length).toBe(1); 186 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 187 | 188 | subscription2.dispose(); 189 | expect(ea.eventLookup.dinner.length).toBe(0); 190 | }); 191 | 192 | it('will respond to an event only once', ()=>{ 193 | let ea = new EventAggregator(); 194 | let data = null; 195 | 196 | let callback = function(){data = "something";}; 197 | ea.subscribeOnce('dinner', callback); 198 | 199 | expect(ea.eventLookup.dinner.length).toBe(1); 200 | expect(ea.eventLookup.dinner[0] === callback).toBe(false); 201 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 202 | 203 | ea.publish('dinner'); 204 | expect(data).toBe("something"); 205 | 206 | expect(ea.eventLookup.dinner.length).toBe(0); 207 | 208 | data = null; 209 | ea.publish('dinner'); 210 | expect(data).toBe(null); 211 | }); 212 | 213 | it('will pass published data to the callback function', ()=>{ 214 | let ea = new EventAggregator(); 215 | 216 | let data = null; 217 | let callback = function(d){data = d;}; 218 | ea.subscribeOnce('dinner', callback); 219 | 220 | expect(ea.eventLookup.dinner.length).toBe(1); 221 | expect(ea.eventLookup.dinner[0] === callback).toBe(false); 222 | expect(typeof ea.eventLookup.dinner[0] === "function").toBe(true); 223 | 224 | ea.publish('dinner',{foo:"bar"}); 225 | expect(data.foo).toBe("bar"); 226 | 227 | data = null; 228 | ea.publish('dinner'); 229 | expect(data).toBe(null); 230 | }); 231 | }); 232 | 233 | describe('handler events', () =>{ 234 | 235 | it('adds handler with messageType and callback to the messageHandlers array', ()=>{ 236 | let ea = new EventAggregator(); 237 | 238 | let callback = function(){}; 239 | ea.subscribeOnce(DinnerEvent, callback); 240 | 241 | expect(ea.messageHandlers.length).toBe(1); 242 | expect(ea.messageHandlers[0].messageType).toBe(DinnerEvent); 243 | expect(ea.messageHandlers[0].callback === callback).toBe(false); 244 | expect(typeof ea.messageHandlers[0].callback === "function").toBe(true); 245 | 246 | }); 247 | 248 | it('removes the handler after execution', () =>{ 249 | let ea = new EventAggregator(); 250 | let callback = function(){}; 251 | let subscription = ea.subscribeOnce(DinnerEvent, callback); 252 | 253 | expect(ea.messageHandlers.length).toBe(1); 254 | subscription.dispose(); 255 | expect(ea.messageHandlers.length).toBe(0); 256 | }); 257 | 258 | }); 259 | 260 | }); 261 | 262 | describe('publish', () =>{ 263 | 264 | describe('string events', () =>{ 265 | 266 | it('calls the callback functions for the event', () =>{ 267 | let ea = new EventAggregator(); 268 | 269 | let someData, someData2; 270 | 271 | let callback = function(data){ 272 | someData = data; 273 | }; 274 | ea.subscribe('dinner', callback); 275 | 276 | let callback2 = function(data){ 277 | someData2 = data; 278 | }; 279 | ea.subscribe('dinner', callback2); 280 | 281 | let data = {foo: 'bar'}; 282 | ea.publish('dinner', data); 283 | 284 | expect(someData).toBe(data); 285 | expect(someData2).toBe(data); 286 | }); 287 | 288 | it('does not call the callback functions if subscriber does not exist', () =>{ 289 | let ea = new EventAggregator(); 290 | 291 | let someData; 292 | 293 | let callback = function(data){ 294 | someData = data; 295 | }; 296 | ea.subscribe('dinner', callback); 297 | 298 | ea.publish('garbage', {}); 299 | 300 | expect(someData).toBeUndefined(); 301 | }); 302 | 303 | it('handles errors in subscriber callbacks', () => { 304 | let ea = new EventAggregator(); 305 | 306 | let someMessage; 307 | 308 | let crash = function() { 309 | throw new Error('oops'); 310 | } 311 | 312 | let callback = function(message){ 313 | someMessage = message; 314 | }; 315 | 316 | let data = {foo: 'bar'}; 317 | 318 | ea.subscribe('dinner', crash); 319 | ea.subscribe('dinner', callback); 320 | ea.subscribe('dinner', crash); 321 | 322 | ea.publish('dinner', data); 323 | 324 | expect(someMessage).toBe(data); 325 | }); 326 | 327 | }); 328 | 329 | describe('handler events', () =>{ 330 | 331 | it('calls the callback functions for the event', () =>{ 332 | let ea = new EventAggregator(); 333 | 334 | let someMessage; 335 | 336 | let callback = function(message){ 337 | someMessage = message; 338 | }; 339 | ea.subscribe(DinnerEvent, callback); 340 | 341 | let americanDinner = new DinnerEvent('Cajun chicken'); 342 | ea.publish(americanDinner); 343 | 344 | expect(someMessage.message).toBe('Cajun chicken'); 345 | 346 | let swedishDinner = new DinnerEvent('Meatballs'); 347 | ea.publish(swedishDinner); 348 | 349 | expect(someMessage.message).toBe('Meatballs'); 350 | }); 351 | 352 | it('does not call the callback funtions if message is not an instance of the messageType', ()=>{ 353 | let ea = new EventAggregator(); 354 | 355 | let someMessage; 356 | 357 | let callback = function(message){ 358 | someMessage = message; 359 | }; 360 | ea.subscribe(DinnerEvent, callback); 361 | 362 | ea.publish(new DrinkingEvent()); 363 | 364 | expect(someMessage).toBeUndefined(); 365 | }); 366 | 367 | 368 | it('handles errors in subscriber callbacks', () => { 369 | let ea = new EventAggregator(); 370 | 371 | let someMessage; 372 | 373 | let crash = function() { 374 | throw new Error('oops'); 375 | } 376 | 377 | let callback = function(message){ 378 | someMessage = message; 379 | }; 380 | 381 | var data = {foo: 'bar'}; 382 | 383 | ea.subscribe(DinnerEvent, crash); 384 | ea.subscribe(DinnerEvent, callback); 385 | 386 | ea.publish(new DinnerEvent(data)); 387 | 388 | expect(someMessage.message).toBe(data); 389 | }); 390 | 391 | }); 392 | 393 | }); 394 | 395 | }); 396 | 397 | class DinnerEvent { 398 | constructor(message){ 399 | this._message = message; 400 | } 401 | 402 | get message(){ 403 | return this._message; 404 | } 405 | } 406 | 407 | class AnotherDinnerEvent { 408 | constructor(message){ 409 | this._message = message; 410 | } 411 | 412 | get message(){ 413 | return this._message; 414 | } 415 | } 416 | 417 | class DrinkingEvent {} 418 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "es2015", 5 | "experimentalDecorators": true, 6 | "emitDecoratorMetadata": false, 7 | "moduleResolution": "node", 8 | "stripInternal": true, 9 | "preserveConstEnums": true, 10 | "listFiles": true, 11 | "declaration": true, 12 | "removeComments": true, 13 | "lib": ["es2015", "dom"] 14 | }, 15 | "exclude": [ 16 | "node_modules", 17 | "dist", 18 | "build", 19 | "doc", 20 | "test", 21 | "config.js", 22 | "gulpfile.js", 23 | "karma.conf.js" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-event-aggregator", 3 | "main": "dist/aurelia-event-aggregator.d.ts" 4 | } 5 | --------------------------------------------------------------------------------