├── .babelrc ├── .bowerrc ├── .codeclimate.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .hound.yml ├── .npmignore ├── .nvmrc ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── build_tools └── upload-github-release.js ├── component.json ├── dependencyci.yml ├── dist ├── angular-vertxbus.js ├── angular-vertxbus.js.map ├── angular-vertxbus.min.js ├── angular-vertxbus.min.js.map ├── angular-vertxbus.withpolyfill.js └── angular-vertxbus.withpolyfill.min.js ├── docs └── github-badge.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── config.js ├── index.js ├── lib │ ├── VertxEventBusServiceProvider.js │ ├── VertxEventBusWrapperProvider.js │ ├── adapter │ │ ├── BaseAdapter.js │ │ ├── EventBusAdapter.js │ │ ├── NoopAdapter.js │ │ └── index.js │ ├── service │ │ ├── Delegator.js │ │ └── delegate │ │ │ ├── BaseDelegate.js │ │ │ ├── EventBusDelegate.js │ │ │ └── NoopDelegate.js │ └── support │ │ ├── ConnectionConfigHolder.js │ │ ├── Queue.js │ │ ├── SimpleMap.js │ │ └── index.js └── module.js ├── test ├── .eslintrc ├── e2e │ ├── server.js │ ├── vertx │ │ ├── app │ │ │ └── vertx3-config.js │ │ └── install-vertx.sh │ └── web │ │ ├── app.js │ │ └── index.html ├── index_all.js └── unit │ ├── binding │ ├── vertxEventBus.defaultHeaders.spec.js │ ├── vertxEventBus.spec.js │ └── vertxEventBusService.spec.js │ ├── lib │ └── support │ │ ├── Queue.spec.js │ │ └── SimpleMap.spec.js │ ├── mock │ └── sockjs.js │ ├── test_index.js │ └── util │ └── unhandledRejectionTracing.js ├── test_scopes ├── angular_1.2.x │ └── bower.json ├── angular_1.3.x │ └── bower.json ├── angular_1.4.x │ └── bower.json ├── angular_1.5.x │ └── bower.json ├── angular_1.6.x │ └── bower.json ├── sockjs-client_1.0.x │ └── bower.json ├── sockjs-client_1.1.x │ └── bower.json ├── vertx-bus_3.2.x │ └── bower.json ├── vertx-bus_3.3.x │ └── bower.json └── vertx-bus_3.4.x │ └── bower.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "debug": true, 7 | "modules": false, 8 | "targets": { 9 | "browsers": [ 10 | "> 1%", 11 | "last 3 versions", 12 | "Firefox ESR" 13 | ] 14 | } 15 | } 16 | ] 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "interactive": false 4 | } 5 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | eslint: 3 | enabled: true 4 | ratings: 5 | paths: 6 | - src/** 7 | exclude_paths: 8 | - build/**/* 9 | - dist/**/* 10 | - docs/**/* 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/** 2 | dist/** 3 | docs/** 4 | test/** 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": "eslint:recommended", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "rules": { 9 | "no-console": 1, 10 | "curly": 1, 11 | "eqeqeq": 1, 12 | "no-alert": 2, 13 | "no-eval": 2, 14 | "no-extra-semi": 1, 15 | "no-multi-spaces": 1, 16 | "no-unused-vars": 1, 17 | "no-unreachable": 1, 18 | "array-bracket-spacing": [1, "never"], 19 | "block-spacing": [1, "always"], 20 | "brace-style": [1, "1tbs", { "allowSingleLine": true }], 21 | "camelcase": [1, {"properties": "always"}], 22 | "comma-spacing": [1, {"before": false, "after": true}], 23 | "comma-style": [1, "last"], 24 | "eol-last": 1, 25 | "indent": [1, 2, {"SwitchCase": 1, "FunctionDeclaration": {"parameters": "first"}, "FunctionExpression": {"parameters": "first"}}], 26 | "keyword-spacing": 1, 27 | "semi": 2, 28 | "quotes": [1, "single"] 29 | }, 30 | "env": { 31 | "browser": true, 32 | "es6": true 33 | }, 34 | "globals": { 35 | "angular": false, 36 | "EventBus": false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Subject of the issue 2 | Describe your issue here. This is only a template useful as an advice. Delete everything you do not need. 3 | 4 | ### Your environment 5 | * version of angular-vertxbus 6 | * version of angular 7 | * which browser and its version 8 | 9 | ### Steps to reproduce 10 | Tell us how to reproduce this issue. Please provide a working demo if possible. 11 | 12 | ### Expected behaviour 13 | Tell us what should happen 14 | 15 | ### Actual behaviour 16 | Tell us what happens instead 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Your checklist for this pull request 2 | 🚨Please review the [guidelines for contributing](CONTRIBUTING.md) to this repository. 3 | 4 | - [ ] Make sure you are requesting to **pull a topic/feature/bugfix branch** (right side). Don't request your master! 5 | - [ ] Make sure you are making a pull request against the **canary branch** (left side). Also you should start *your branch* off *our canary*. 6 | - [ ] Check the commit's or even all commits' message styles matches our requested structure. 7 | - [ ] Check your code additions will fail neither code linting checks nor unit test. 8 | 9 | ### Description 10 | Please describe your pull request. 11 | 12 | 💔Thank you! 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | .DS_Store 4 | node_modules 5 | npm-debug.log 6 | components 7 | bower_components 8 | temp 9 | *.iml 10 | /build 11 | /dist/docs 12 | 13 | # Integration stuff 14 | /test/e2e/vertx/app/mods/io.vertx~mod-auth-mgr~2.0.0-final 15 | /test/e2e/vertx/app/mods/io.vertx~mod-web-server~2.0.0-final 16 | /test/e2e/vertx/vert.x-* 17 | /test/e2e/vertx/runtime 18 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | java_script: 2 | enabled: false 3 | eslint: 4 | enabled: true 5 | config_file: .eslintrc 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | components 4 | bower_components 5 | temp 6 | dist/docs 7 | 8 | .github 9 | .idea 10 | .vertx 11 | 12 | # Test Stuff 13 | /test/ 14 | /test_scopes/ 15 | /build 16 | /build_tools 17 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 8.9 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "8.9" 6 | 7 | addons: 8 | chrome: stable 9 | code_climate: 10 | repo_token: 94ea5ac76984c311dcbadb53a52dd219400775e20402587a0063d8b9d3a66bca 11 | 12 | before_install: 13 | - sudo chown root /opt/google/chrome/chrome-sandbox 14 | - sudo chmod 4755 /opt/google/chrome/chrome-sandbox 15 | 16 | before_script: 17 | - export DISPLAY=:99.0 18 | - sh -e /etc/init.d/xvfb start & 19 | - sleep 3 20 | 21 | after_script: 22 | - if [ "$TEST_SCOPE" == "" ]; then npm install -g codeclimate-test-reporter && codeclimate-test-reporter < build/coverage/lcov.info; fi 23 | 24 | env: 25 | matrix: 26 | - TEST_SCOPE= 27 | - TEST_SCOPE= SAUCE_ENABLED=$_SAUCE_ENABLED SAUCE_USERNAME=$_SAUCE_USERNAME SAUCE_ACCESS_KEY=$_SAUCE_ACCESS_KEY 28 | - TEST_SCOPE=angular_1.2.x 29 | - TEST_SCOPE=angular_1.3.x 30 | - TEST_SCOPE=angular_1.4.x 31 | - TEST_SCOPE=angular_1.5.x 32 | - TEST_SCOPE=angular_1.6.x 33 | - TEST_SCOPE=sockjs-client_1.0.x 34 | - TEST_SCOPE=sockjs-client_1.1.x 35 | - TEST_SCOPE=vertx-bus_3.2.x 36 | - TEST_SCOPE=vertx-bus_3.3.x 37 | - TEST_SCOPE=vertx-bus_3.4.x 38 | global: 39 | - CXX=g++-4.8 40 | - secure: "BQeu14UTGr7gWrEz9O2NSDb4g4F40dWw2QKgglkLX58VmJYZn6anQLIavotmNr9XEG7car8lWkxuDrcQEbUvp/nunhSd2EvDn3fZwI5lLAfuWwvGgAd37SRbD4xKykrzqmSNfH6jHAB+Zm5UcYPr127OzrEUY08ArEDj9lyhnkY=" 41 | - secure: "clpyd43PGosqt4eig31MMoDHOBoHRKHM+sx25GP8bWIw7ixp46z9yb00cOibHEwvbTW/reBiEmb3giDk0AHyduxDPJaK5uTKe/XjQNH+0fxilCvq9sY1bjhH95h7VV8TacASwTrhswgEMnALvTWxonNzsMgU5iTvrsGqXOVX4Z4=" 42 | - secure: "KnYZgICysNrYQFBavQ3IQU6oUGCHabawI6aDlAtSUvi6O5g6GOvbTcU7XFlFU8OVNaujgRPDSSuSsHcv4Dmz8hKKIQ94G54qL1ZaxmLOP/PluItnGRQI8+jAsL8qoBCXfw/0ce0DBKi2QEwSxkNsv3uxlAg57d/L3YDrGUiYSp8=" 43 | 44 | matrix: 45 | allow_failures: 46 | - env: TEST_SCOPE= SAUCE_ENABLED=$_SAUCE_ENABLED SAUCE_USERNAME=$_SAUCE_USERNAME SAUCE_ACCESS_KEY=$_SAUCE_ACCESS_KEY 47 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [6.4.1](https://github.com/knalli/angular-vertxbus/compare/6.4.0...6.4.1) (2018-02-23) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * **adapter:** fix missing conditional logging ([38681b4](https://github.com/knalli/angular-vertxbus/commit/38681b4)) 8 | 9 | 10 | 11 | 12 | # [6.4.0](https://github.com/knalli/angular-vertxbus/compare/6.3.0...6.4.0) (2018-02-23) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * **service:** ensure promise wrapped exceptions will be handled ([d4a65ea](https://github.com/knalli/angular-vertxbus/commit/d4a65ea)), closes [#283](https://github.com/knalli/angular-vertxbus/issues/283) 18 | 19 | 20 | ### Features 21 | 22 | * **adapter:** add diagnostic support for vertx-event internal reconnect ([229a29b](https://github.com/knalli/angular-vertxbus/commit/229a29b)) 23 | * **adapter:** add support for vertx EventBus.onreconnect ([07fdcd0](https://github.com/knalli/angular-vertxbus/commit/07fdcd0)) 24 | * **service:** add event reconnected ([e88b763](https://github.com/knalli/angular-vertxbus/commit/e88b763)) 25 | 26 | 27 | 28 | 29 | # [6.3.0](https://github.com/knalli/angular-vertxbus/compare/6.2.0...v6.3.0) (2017-06-06) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * **package:** change dependency version check ([b407d3b](https://github.com/knalli/angular-vertxbus/commit/b407d3b)) 35 | * **service:** fix missing promise rejection handlers ([59f43a5](https://github.com/knalli/angular-vertxbus/commit/59f43a5)) 36 | * **tests:** test_scopes should use scoped angular libs :bomb: ([ad7ab24](https://github.com/knalli/angular-vertxbus/commit/ad7ab24)) 37 | 38 | 39 | ### Features 40 | 41 | * add automatic tests at SauceLabs, for the latest browsers ([e440c6a](https://github.com/knalli/angular-vertxbus/commit/e440c6a)) 42 | * switch to babel-preset-env using browserlist (“last 3 versions”) ([88d590c](https://github.com/knalli/angular-vertxbus/commit/88d590c)) 43 | * **tests:** add sockjs-client 1.0 and 1.1 as target libraries ([170d5f7](https://github.com/knalli/angular-vertxbus/commit/170d5f7)) 44 | * **tests:** add vertx-bus 3.2, 3.3, and 3.4 as target libraries ([443b383](https://github.com/knalli/angular-vertxbus/commit/443b383)) 45 | * update preferred dependencies for SockJS and vertx-bus to latest ([e0cf3dd](https://github.com/knalli/angular-vertxbus/commit/e0cf3dd)) 46 | 47 | 48 | 49 | 50 | # [6.2.0](https://github.com/knalli/angular-vertxbus/compare/6.1.1...v6.2.0) (2017-02-16) 51 | 52 | 53 | ### Features 54 | 55 | * add AngularJS 1.6 support ([f383f29](https://github.com/knalli/angular-vertxbus/commit/f383f29)) 56 | * add AngularJS 1.6 support (fixup) ([180c494](https://github.com/knalli/angular-vertxbus/commit/180c494)) 57 | 58 | 59 | 60 | 61 | ## [6.1.1](https://github.com/knalli/angular-vertxbus/compare/6.1.0...v6.1.1) (2016-08-21) 62 | 63 | 64 | ### Bug Fixes 65 | 66 | * **service:** add missing hasOwnProperty check ([834f95f](https://github.com/knalli/angular-vertxbus/commit/834f95f)), closes [#212](https://github.com/knalli/angular-vertxbus/issues/212) 67 | 68 | 69 | 70 | 71 | # [6.1.0](https://github.com/knalli/angular-vertxbus/compare/6.0.0...v6.1.0) (2016-07-17) 72 | 73 | 74 | 75 | 76 | # [6.0.0](https://github.com/knalli/angular-vertxbus/compare/5.0.0...v6.0.0) (2016-04-01) 77 | 78 | 79 | ### Bug Fixes 80 | 81 | * **service:** ensure authHandler will be invoked on each request ([e692d36](https://github.com/knalli/angular-vertxbus/commit/e692d36)) 82 | * **service:** fix several serious invalid api signatures and docs #157 ([bf773fa](https://github.com/knalli/angular-vertxbus/commit/bf773fa)), closes [#157](https://github.com/knalli/angular-vertxbus/issues/157) 83 | 84 | ### Features 85 | 86 | * **adapter:** introduce `vertxEventBus.applyDefaultHeaders(headers)` ([ced8e74](https://github.com/knalli/angular-vertxbus/commit/ced8e74)) 87 | * **demo:** add demo demostrating using headers and authHandler ([5a9345e](https://github.com/knalli/angular-vertxbus/commit/5a9345e)) 88 | * **dependencies:** allow vertx3-eventbus patch updates by spec ([9b7d437](https://github.com/knalli/angular-vertxbus/commit/9b7d437)) 89 | * **service:** internal ensure*Connection handlers returning promises now ([551f5c3](https://github.com/knalli/angular-vertxbus/commit/551f5c3)) 90 | * **service:** introduce authHandler ([0e8e036](https://github.com/knalli/angular-vertxbus/commit/0e8e036)) 91 | 92 | 93 | ### BREAKING CHANGES 94 | 95 | * service: The return of `vertxEventBusService.publish()` has changed from boolean to Promise (just like `send()` already). 96 | * service: The argument `failureHandler` of `EventBus.send()` has been removed 97 | 98 | This callback has been obsolete since vertx-eventbus 3.1.0+. 99 | Solves #152 100 | * service: Remove fallback in signatures again. `headers` is not skipable anymore. 101 | 102 | 103 | 104 | 105 | # [5.0.0](https://github.com/knalli/angular-vertxbus/compare/4.0.0...v5.0.0) (2016-03-25) 106 | 107 | 108 | ### Features 109 | 110 | * **bundle:** migrate tooling to webpack ([74c6100](https://github.com/knalli/angular-vertxbus/commit/74c6100)) 111 | * **service:** add support for headers (supported since vertxbus v3.1) ([1881de1](https://github.com/knalli/angular-vertxbus/commit/1881de1)) 112 | 113 | 114 | ### BREAKING CHANGES 115 | 116 | * service: The signature of `vertxEventBus.send()` has been changed! 117 | 118 | Before, it was `address, message, replyHandler, failureHandler`. This has been changed to `address, message, headers, replyHandler, failureHandler`. Note the additional `headers`. 119 | 120 | Actually, all method signatures of `vertxEventBus` and `vertxEventBusService` for sending, publishing, and registering/unregistering handlers have been changed to match the optional `headers` introduced in EventBus 3.1. But only in case of `.send()` it has a broken signature. 121 | 122 | 123 | 124 | 125 | # [4.0.0](https://github.com/knalli/angular-vertxbus/compare/3.2.1...v4.0.0) (2016-02-13) 126 | 127 | 128 | ### Features 129 | 130 | * upgrade baseline to Vert.x 3.2 (breaking changes) ([e06515b](https://github.com/knalli/angular-vertxbus/commit/e06515b)) 131 | * **adapter:** add support for `EventBus.onerror` ([5e93cde](https://github.com/knalli/angular-vertxbus/commit/5e93cde)) 132 | * **service:** add support for `failureHandler` on send ([bbec54c](https://github.com/knalli/angular-vertxbus/commit/bbec54c)) 133 | * **service:** add support for new `type=err` messages ([54c4b2b](https://github.com/knalli/angular-vertxbus/commit/54c4b2b)) 134 | 135 | 136 | ### BREAKING CHANGES 137 | 138 | * Due insuffcient support and breaking things, the feature `login` has been removed completely. It will come back supporting login on connect providers as well (i.e. JWT over BasicAuth). 139 | * Due upgrading to Vert.x 3.2 (incl. 3.1), several things changed internally. Be aware of https://github.com/vert-x3/wiki/wiki/3.2.0-Breaking-changes 140 | * Since Vert.x 3.1, the dependency has changed `vertx3bus` => `vertx-eventbus`. Also the file name itself has changed. 141 | * Since Vert.x 3.1, the `EventBus` is a global now. No `vertx.` anymore. 142 | * Since Vert.x 3.1, the message payload of a receiving message has changed being closer to NodeJS apis. The `vertxEventBusService` will handle this correct without a change, but `vertxEventBus` has changed the signature being compliant: `register('address', callback({address, message}))` => `register(callback(err, {address, message}))` 143 | 144 | 145 | 146 | 147 | ## [3.2.1](https://github.com/knalli/angular-vertxbus/compare/3.2.0...v3.2.1) (2016-01-24) 148 | 149 | 150 | ### Bug Fixes 151 | 152 | * **adapter:** fix invalid delegating of SockJS.options ([43b93aa](https://github.com/knalli/angular-vertxbus/commit/43b93aa)), closes [#107](https://github.com/knalli/angular-vertxbus/issues/107) 153 | 154 | ### Features 155 | 156 | * **build:** update test scope "AJS 1.5" using rc0 ([10ef138](https://github.com/knalli/angular-vertxbus/commit/10ef138)) 157 | 158 | 159 | 160 | 161 | # [3.2.0](https://github.com/knalli/angular-vertxbus/compare/3.1.0...v3.2.0) (2015-10-31) 162 | 163 | 164 | ### Bug Fixes 165 | 166 | * **docs:** Fix invalid params descriptions ([1f85e52](https://github.com/knalli/angular-vertxbus/commit/1f85e52)) 167 | * **test:** fix incorrect redelcaration of a block scope variable ([6aa9572](https://github.com/knalli/angular-vertxbus/commit/6aa9572)) 168 | * **test:** fix internal babel-node scriptlets ([2acde13](https://github.com/knalli/angular-vertxbus/commit/2acde13)) 169 | 170 | ### Features 171 | 172 | * **adapter:** overload signature of EB.connect() returning promise ([df7cf0d](https://github.com/knalli/angular-vertxbus/commit/df7cf0d)), closes [#90](https://github.com/knalli/angular-vertxbus/issues/90) 173 | * **build:** add .babelrc ([ce49603](https://github.com/knalli/angular-vertxbus/commit/ce49603)) 174 | 175 | 176 | 177 | 178 | # [3.1.0](https://github.com/knalli/angular-vertxbus/compare/3.0.2...v3.1.0) (2015-10-25) 179 | 180 | 181 | ### Bug Fixes 182 | 183 | * **build:** fix invalid license header in artifacts' headers ([f0597fb](https://github.com/knalli/angular-vertxbus/commit/f0597fb)) 184 | 185 | ### Features 186 | 187 | * **wrapper:** introduce `.disableAutoConnect()` #71 ([ce3a0af](https://github.com/knalli/angular-vertxbus/commit/ce3a0af)) 188 | 189 | 190 | 191 | 192 | ## [3.0.2](https://github.com/knalli/angular-vertxbus/compare/3.0.1...v3.0.2) (2015-10-08) 193 | 194 | 195 | ### Features 196 | 197 | * **linting:** switch from JSHint to ESLint ([b70eea8](https://github.com/knalli/angular-vertxbus/commit/b70eea8)) 198 | 199 | 200 | 201 | 202 | ## [3.0.1](https://github.com/knalli/angular-vertxbus/compare/3.0.0...v3.0.1) (2015-10-01) 203 | 204 | ### No functional changes 205 | 206 | * This update changes only internals, structures and internal dependencies (patch only). 207 | 208 | 209 | 210 | # [3.0.0](https://github.com/knalli/angular-vertxbus/compare/2.0.4...v3.0.0) (2015-08-29) 211 | 212 | 213 | ### Bug Fixes 214 | 215 | * **package:** fix license attribute in package.json ([72dc32c](https://github.com/knalli/angular-vertxbus/commit/72dc32c)) 216 | 217 | ### Features 218 | 219 | * **compatiblity:** replace the dependencies sockjs/vertxbus to latest ([f56b4a6](https://github.com/knalli/angular-vertxbus/commit/f56b4a6)), closes [#42](https://github.com/knalli/angular-vertxbus/issues/42) [#61](https://github.com/knalli/angular-vertxbus/issues/61) 220 | * **dependencies:** update internal (dev) dependency AJS 1.2 -> 1.4 ([57d07f5](https://github.com/knalli/angular-vertxbus/commit/57d07f5)) 221 | * **e2e test:** fix installing/configuration of e2e vertx3 server ([c3413fe](https://github.com/knalli/angular-vertxbus/commit/c3413fe)) 222 | * **provider:** add support for custom auth/login interceptor ([bc5f814](https://github.com/knalli/angular-vertxbus/commit/bc5f814)) 223 | * **wrapper:** add support for `eventbus.send()` arg `failureHandler` ([2f418bd](https://github.com/knalli/angular-vertxbus/commit/2f418bd)) 224 | * **wrapper:** recognize missing vertx.EventBus.login(), improve usage ([7c3bd49](https://github.com/knalli/angular-vertxbus/commit/7c3bd49)) 225 | 226 | 227 | ### BREAKING CHANGES 228 | 229 | * Since Vert.x 3 there is a dedicated bower dependency called `vertx3-eventbus-client` [available](https://github.com/vert-x3/vertx-bus-bower). This one will replace the old legacy one. 230 | Additionally, this commit replaces the dependency for sockjs-client@0.3.4 in favor of the latest sockjs-client@1.0.3 231 | 232 | 233 | 234 | ## [2.0.4](https://github.com/knalli/angular-vertxbus/compare/2.0.3...2.0.4) (2015-06-22) 235 | 236 | 237 | ### Bug Fixes 238 | 239 | * **service:** remove invalid debug console ([333520b](https://github.com/knalli/angular-vertxbus/commit/333520b)) 240 | 241 | 242 | 243 | 244 | ## [2.0.3](https://github.com/knalli/angular-vertxbus/compare/2.0.2...2.0.3) (2015-06-22) 245 | 246 | 247 | ### Bug Fixes 248 | 249 | * **demo:** Replace CoffeeScript w/ BabelJS runner ([4dc71a0](https://github.com/knalli/angular-vertxbus/commit/4dc71a0)) 250 | * **service:** fix doubled handler registration in special circumstances ([f3311ca](https://github.com/knalli/angular-vertxbus/commit/f3311ca)) 251 | 252 | 253 | 254 | 255 | ## [2.0.2](https://github.com/knalli/angular-vertxbus/compare/2.0.1...2.0.2) (2015-06-15) 256 | 257 | 258 | ### Features 259 | 260 | * **artifact:** provide a variant with polyfill included ([98e17aa](https://github.com/knalli/angular-vertxbus/commit/98e17aa)) 261 | 262 | 263 | 264 | 265 | ## [2.0.1](https://github.com/knalli/angular-vertxbus/compare/2.0.0...2.0.1) (2015-06-10) 266 | 267 | 268 | ### Bug Fixes 269 | 270 | * **wrapper:** fix npe `Cannot read property 'CLOSED' of undefined` ([e369a7a](https://github.com/knalli/angular-vertxbus/commit/e369a7a)) 271 | 272 | 273 | 274 | 275 | # [2.0.0](https://github.com/knalli/angular-vertxbus/compare/1.1.4...2.0.0) (2015-06-02) 276 | 277 | 278 | ### Bug Fixes 279 | 280 | * **service:** fix possible internal npe on de-register ([53e5cfb](https://github.com/knalli/angular-vertxbus/commit/53e5cfb)) 281 | 282 | 283 | 284 | 285 | ## [1.1.4](https://github.com/knalli/angular-vertxbus/compare/2.0.0-beta.6...1.1.4) (2015-05-01) 286 | 287 | 288 | ### Bug Fixes 289 | 290 | * **service:** fix possible internal npe on de-register (also as 913ac74) ([6aa86bc](https://github.com/knalli/angular-vertxbus/commit/6aa86bc)) 291 | 292 | ### Features 293 | 294 | * **service:** change signature of .send() #51 ([7534034](https://github.com/knalli/angular-vertxbus/commit/7534034)) 295 | 296 | 297 | ### BREAKING CHANGES 298 | 299 | * The arguments of vertxEventBusService.send() have 300 | been restructured. 301 | Instead of `send(address, message, timeout, expectReply)` it is now 302 | `send(address, message, {timeout, expectReply})`. 303 | Reasons for this improvement of api: 304 | 1. Both `address` and `message` are required, but the other ones are only 305 | optional. 306 | 2. Long arguments are not a good api design 307 | 3. Using default timeout does not require an `undefined` argument or 308 | even a missplaced `null` or `0`. 309 | 310 | 311 | 312 | ## [1.1.3](https://github.com/knalli/angular-vertxbus/compare/1.1.2...1.1.3) (2015-04-14) 313 | 314 | 315 | ### Bug Fixes 316 | 317 | * **service:** after a reconnect the deconstructor does not work anymore ([5ebbfc4](https://github.com/knalli/angular-vertxbus/commit/5ebbfc4)) 318 | 319 | 320 | 321 | 322 | ## [1.1.2](https://github.com/knalli/angular-vertxbus/compare/1.1.1...1.1.2) (2015-04-13) 323 | 324 | 325 | ### Bug Fixes 326 | 327 | * **service:** fix edge case when deconstructor invoked multiple times ([7420087](https://github.com/knalli/angular-vertxbus/commit/7420087)) 328 | * **service:** fix possible internal npe on de-register ([913ac74](https://github.com/knalli/angular-vertxbus/commit/913ac74)) 329 | 330 | 331 | 332 | 333 | ## [1.1.1](https://github.com/knalli/angular-vertxbus/compare/1.1.0...1.1.1) (2015-04-09) 334 | 335 | 336 | ### Bug Fixes 337 | 338 | * **wrapper:** ensure eventbus is online when removing a handler ([a3dd555](https://github.com/knalli/angular-vertxbus/commit/a3dd555)), closes [#48](https://github.com/knalli/angular-vertxbus/issues/48) [#52](https://github.com/knalli/angular-vertxbus/issues/52) 339 | 340 | 341 | 342 | 343 | # [1.1.0](https://github.com/knalli/angular-vertxbus/compare/1.0.0...1.1.0) (2015-04-06) 344 | 345 | 346 | ### Features 347 | 348 | * **service:** add 4th arg `service.send()` for replyless sends ([849eb3a](https://github.com/knalli/angular-vertxbus/commit/849eb3a)) 349 | * **wrapper:** add `wrapper.reconnect(true)` allowing a reconnect asap ([bd0cc4a](https://github.com/knalli/angular-vertxbus/commit/bd0cc4a)) 350 | 351 | 352 | 353 | 354 | # [1.0.0](https://github.com/knalli/angular-vertxbus/compare/0.11.2...1.0.0) (2015-03-01) 355 | 356 | 357 | ### Bug Fixes 358 | 359 | * **protractor-$timeout:** use $interval service for reply timeouts so protractor tests can continue ([eed05bd](https://github.com/knalli/angular-vertxbus/commit/eed05bd)) 360 | * **service:** avoid duplicate broadcast events for (dis)connected ([0f56411](https://github.com/knalli/angular-vertxbus/commit/0f56411)), closes [#37](https://github.com/knalli/angular-vertxbus/issues/37) 361 | * **wrapper:** avoid invalid host+port combination (CORS) ([e29def5](https://github.com/knalli/angular-vertxbus/commit/e29def5)), closes [#39](https://github.com/knalli/angular-vertxbus/issues/39) 362 | 363 | 364 | 365 | 366 | ## [0.11.2](https://github.com/knalli/angular-vertxbus/compare/0.11.1...0.11.2) (2015-01-16) 367 | 368 | 369 | ### Bug Fixes 370 | 371 | * **service:** fix possible npe on re-registration of handlers after reconnect ([2225a8a](https://github.com/knalli/angular-vertxbus/commit/2225a8a)) 372 | 373 | 374 | 375 | 376 | ## [0.11.1](https://github.com/knalli/angular-vertxbus/compare/0.11.0...0.11.1) (2015-01-09) 377 | 378 | 379 | ### Bug Fixes 380 | 381 | * **service:** fix registering a callback again after disconnect ([483d2ee](https://github.com/knalli/angular-vertxbus/commit/483d2ee)) 382 | 383 | 384 | 385 | 386 | # [0.11.0](https://github.com/knalli/angular-vertxbus/compare/0.10.0...0.11.0) (2014-12-18) 387 | 388 | 389 | ### Features 390 | 391 | * **service:** improve memory usage, remove empty arrays of handlers ([4b68002](https://github.com/knalli/angular-vertxbus/commit/4b68002)) 392 | * replace console w/ $log ([3c9be73](https://github.com/knalli/angular-vertxbus/commit/3c9be73)) 393 | 394 | 395 | 396 | 397 | # [0.10.0](https://github.com/knalli/angular-vertxbus/compare/0.9.0...0.10.0) (2014-12-14) 398 | 399 | 400 | 401 | 402 | 403 | # [0.9.0](https://github.com/knalli/angular-vertxbus/compare/v0.8.1...0.9.0) (2014-11-23) 404 | 405 | 406 | ### Bug Fixes 407 | 408 | * **package:** use non minified artifact as 'main' ([72b5165](https://github.com/knalli/angular-vertxbus/commit/72b5165)), closes [#27](https://github.com/knalli/angular-vertxbus/issues/27) 409 | 410 | ### Features 411 | 412 | * **componentjs:** add support for componentjs and related builds ([9a763d6](https://github.com/knalli/angular-vertxbus/commit/9a763d6)) 413 | * **componentjs:** add support for componentjs and related builds ([d748944](https://github.com/knalli/angular-vertxbus/commit/d748944)) 414 | * **componentjs:** add support for componentjs and related builds ([2755038](https://github.com/knalli/angular-vertxbus/commit/2755038)) 415 | * improve debugger-readibility w/ fn.displayName ([8e5006e](https://github.com/knalli/angular-vertxbus/commit/8e5006e)) 416 | 417 | 418 | 419 | 420 | ## [0.8.1](https://github.com/knalli/angular-vertxbus/compare/v0.8.0...v0.8.1) (2014-10-30) 421 | 422 | 423 | ### Bug Fixes 424 | 425 | * **service:** fix npe if vertxEventBus is disabled (and null) ([7e4be4b](https://github.com/knalli/angular-vertxbus/commit/7e4be4b)) 426 | 427 | 428 | 429 | 430 | # [0.8.0](https://github.com/knalli/angular-vertxbus/compare/v0.7.1...v0.8.0) (2014-10-16) 431 | 432 | 433 | ### Features 434 | 435 | * **service:** use a simple map internally avoiding callbacks issues ([8a5bd54](https://github.com/knalli/angular-vertxbus/commit/8a5bd54)), closes [#23](https://github.com/knalli/angular-vertxbus/issues/23) 436 | 437 | 438 | 439 | 440 | ## [0.7.1](https://github.com/knalli/angular-vertxbus/compare/v0.7.0...v0.7.1) (2014-09-19) 441 | 442 | 443 | ### Features 444 | 445 | * **tests:** introduce automatic tests against latest AJS 1.2 & 1.3 ([89d6a3d](https://github.com/knalli/angular-vertxbus/commit/89d6a3d)) 446 | 447 | 448 | 449 | 450 | # [0.7.0](https://github.com/knalli/angular-vertxbus/compare/v0.6.0...v0.7.0) (2014-08-30) 451 | 452 | 453 | ### Bug Fixes 454 | 455 | * **artifact:** (requirejs) add `angular` as a missing dependency ([a566c53](https://github.com/knalli/angular-vertxbus/commit/a566c53)) 456 | * **service:** Fix issue with registerHandler/unregisterHandler #18 ([e723185](https://github.com/knalli/angular-vertxbus/commit/e723185)), closes [#18](https://github.com/knalli/angular-vertxbus/issues/18) 457 | * **service:** fix service.isValidSession() ([0cbfb10](https://github.com/knalli/angular-vertxbus/commit/0cbfb10)) 458 | * **service:** invalid promise on login (see also #17 & ca65a8d2) ([8e2cd8c](https://github.com/knalli/angular-vertxbus/commit/8e2cd8c)) 459 | * **wrapper:** fix typo in debug message ([0acd99b](https://github.com/knalli/angular-vertxbus/commit/0acd99b)) 460 | 461 | ### Features 462 | 463 | * **mock:** sockjs mock can emulate a login shake ([3618ede](https://github.com/knalli/angular-vertxbus/commit/3618ede)) 464 | * **service:** breaking change: service.send(addr, data, timeout) ([55716e4](https://github.com/knalli/angular-vertxbus/commit/55716e4)), closes [#19](https://github.com/knalli/angular-vertxbus/issues/19) 465 | * **service:** send/publish will additionally check login state ([e16083f](https://github.com/knalli/angular-vertxbus/commit/e16083f)) 466 | * **service:** the service handles a login if defined ([7727da7](https://github.com/knalli/angular-vertxbus/commit/7727da7)) 467 | 468 | 469 | 470 | 471 | # [0.6.0](https://github.com/knalli/angular-vertxbus/compare/v0.5.0...v0.6.0) (2014-05-19) 472 | 473 | 474 | ### Bug Fixes 475 | 476 | * **vertxEventBusProvider:** avoid default options object mutations ([031871c](https://github.com/knalli/angular-vertxbus/commit/031871c)) 477 | * **vertxEventBusProvider:** make config functions chainable ([7b02eab](https://github.com/knalli/angular-vertxbus/commit/7b02eab)) 478 | * **vertxEventBusService:** on registerHandler, return function to unregister this handler ([1f1b6bd](https://github.com/knalli/angular-vertxbus/commit/1f1b6bd)) 479 | * **vertxEventBusService:** on unregistering a handler, the callback was called accidently itself ([2dfcd11](https://github.com/knalli/angular-vertxbus/commit/2dfcd11)) 480 | 481 | ### Features 482 | 483 | * **vertxEventBusService:** add opt-in feature buffering messages ([de0e134](https://github.com/knalli/angular-vertxbus/commit/de0e134)) 484 | 485 | 486 | 487 | 488 | # [0.5.0](https://github.com/knalli/angular-vertxbus/compare/v0.4.5...v0.5.0) (2014-03-17) 489 | 490 | 491 | 492 | 493 | 494 | ## [0.4.5](https://github.com/knalli/angular-vertxbus/compare/2.0.0-beta.3...v0.4.5) (2013-12-24) 495 | 496 | 497 | 498 | 499 | 500 | ## [0.4.4](https://github.com/knalli/angular-vertxbus/compare/v0.4.3...v0.4.4) (2013-12-16) 501 | 502 | 503 | ### Bug Fixes 504 | 505 | * fix issue with $q / typo ([4c45587](https://github.com/knalli/angular-vertxbus/commit/4c45587)) 506 | 507 | 508 | 509 | 510 | ## [0.4.3](https://github.com/knalli/angular-vertxbus/compare/v0.4.2...v0.4.3) (2013-12-16) 511 | 512 | 513 | ### Bug Fixes 514 | 515 | * fix another npe ([b1cf79c](https://github.com/knalli/angular-vertxbus/commit/b1cf79c)) 516 | 517 | 518 | 519 | 520 | ## [0.4.2](https://github.com/knalli/angular-vertxbus/compare/v0.4.1...v0.4.2) (2013-12-16) 521 | 522 | 523 | ### Bug Fixes 524 | 525 | * fix possible npe if event bus is disabled (was not fixed in 0.4.1) ([15c5832](https://github.com/knalli/angular-vertxbus/commit/15c5832)) 526 | 527 | 528 | 529 | 530 | ## [0.4.1](https://github.com/knalli/angular-vertxbus/compare/v0.4.0...v0.4.1) (2013-12-16) 531 | 532 | 533 | ### Bug Fixes 534 | 535 | * fix possible npe if event bus is disabled ([600a090](https://github.com/knalli/angular-vertxbus/commit/600a090)) 536 | 537 | 538 | 539 | 540 | # [0.4.0](https://github.com/knalli/angular-vertxbus/compare/v0.3.0...v0.4.0) (2013-12-16) 541 | 542 | 543 | ### Features 544 | 545 | * fix use any angularjs 1.2.x ([35b4bc5](https://github.com/knalli/angular-vertxbus/commit/35b4bc5)) 546 | 547 | 548 | 549 | 550 | # [0.3.0](https://github.com/knalli/angular-vertxbus/compare/v0.2.0...v0.3.0) (2013-12-15) 551 | 552 | 553 | ### Bug Fixes 554 | 555 | * missing repository field in package.json ([1d4e888](https://github.com/knalli/angular-vertxbus/commit/1d4e888)) 556 | 557 | 558 | 559 | 560 | # [0.2.0](https://github.com/knalli/angular-vertxbus/compare/cf3dc75...v0.2.0) (2013-12-15) 561 | 562 | 563 | ### Bug Fixes 564 | 565 | * **grunt:** fix task order, missing coffee in chain ([cf3dc75](https://github.com/knalli/angular-vertxbus/commit/cf3dc75)) 566 | 567 | 568 | 569 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | Contributing to this repo is fairly easy. This document shows you how to 3 | get the project, run all provided tests and generate a production ready build. 4 | 5 | It also covers provided grunt tasks, that help you developing on this repo. 6 | 7 | ## Dependencies 8 | To make sure the following instructions work, please install the following dependencies 9 | on you machine: 10 | 11 | - Node.js 12 | - npm 13 | - Git 14 | 15 | If you install node through the binary installation file, **npm** will be already there. 16 | 17 | ## Installation 18 | To get the source of this project clone the git repository via: 19 | 20 | ```` 21 | $ git clone https://github.com/knalli/angular-vertxbus 22 | ```` 23 | 24 | This will clone the complete source to your local machine. Navigate to the project folder 25 | and install all needed dependencies via **npm** and **bower**: 26 | 27 | ```` 28 | $ npm install 29 | ```` 30 | 31 | (This will invoke a `bower install` automatically.) 32 | 33 | This commands installs everything which is required for building and testing the project. 34 | 35 | ## Testing 36 | Internally `angular-vertxbus` depends on **Grunt** and **Webpack**, however there have been been masked all steps behind 37 | simple tasks processed by **npm**. 38 | 39 | ### Source linting: `npm run lint` 40 | `npm run lint` performs a lint for all (also part of `test`). 41 | 42 | ### Unit testing: `npm run test` 43 | `npm run test` executes (as you might think) the unit tests, which are located 44 | in `test/unit`. The task uses **karma**, the spectacular test runner, to execute the tests with 45 | the **jasmine testing framework**. 46 | 47 | #### Testing of different scopes: `npm run test-scopes` 48 | Because `angular-vertxbus` supports multiple different versions of AngularJS 1.x, you should run the tests the code against these also. 49 | 50 | `npm run test-scopes` performs a `npm run test` against each registered scope which can be found at `/test_scopes/*`. 51 | 52 | #### Testing headless: `npm run test-headless` 53 | Just like `npm run test`, the command `npm run test-headless` performs the test against a headless PhantomJS. Maybe 54 | useful in case of automatic tests. 55 | 56 | ## Building 57 | ### Standard build 58 | You will probably being never required using the command `npm run build`, because it will create a production-ready 59 | build of `angular-vertxbus`. This task will also **lint**, **test** and **minify** the 60 | source. After running this task, you'll find the following files in a generated 61 | `/dist`folder: 62 | 63 | ```` 64 | dist/angular-vertxbus.js 65 | dist/angular-vertxbus.min.js 66 | dist/angular-vertxbus.withpolyfill.js 67 | dist/angular-vertxbus.withpolyfill.min.js 68 | ```` 69 | 70 | ### Compile only 71 | The command `npm run compile` creates production-ready files at `/dist`, also part of `npm run build`. 72 | 73 | ```` 74 | dist/angular-vertxbus.js 75 | dist/angular-vertxbus.min.js 76 | dist/angular-vertxbus.withpolyfill.js 77 | dist/angular-vertxbus.withpolyfill.min.js 78 | ```` 79 | 80 | ## Developing 81 | The *local test environment* starts and utilizes a full Vert.x node and a NodeJS based web server. 82 | 83 | **Easy:** Just run `npm run -s start-server` and open `http://localhost:3000/` in your preferred browser. 84 | 85 | If you have changed something, just invoke `npm run -s compile` in parallel and refresh the browser. 86 | 87 | Alternatively: 88 | 89 | 1. `npm run install-it-vertx-server` downloads and installs a Vert.x locally. This will store a cached download artifact at `test/e2e//vertx/`. 90 | 2. `npm run start-it-vertx-server` starts an Vert.x on port `8080`. 91 | 3. `npm run start-it-web-server` starts a web server on port `3000`. 92 | 4. Ensure at least `npm run -s compile` has been invoked so there is a `dist/angular-vertxbus.js`. 93 | 5. Open http://localhost:3000/ in your browser. 94 | 95 | ## Contributing/Submitting changes 96 | 97 | Note: In general, pull requests should be based on the `canary` branch. Most likely, `canary` will be most of time newer than the stable `master`. Therefor, you can make your changes based on `master` -- but you have to do it *always* based on `canary` in order to make a pull request. 98 | 99 | - Checkout a new branch based on canary and name it to what you intend to do: 100 | - Example: 101 | ```` 102 | $ git checkout -b BRANCH_NAME 103 | ```` 104 | - Use one branch per fix/feature 105 | - Make your changes 106 | - Make sure to provide a spec for unit tests. 107 | - Run your tests with either karma start karma.conf.js or simply grunt test. 108 | - In order to verify everything will work in the other test scopes (different AngularJS version), please run `npm run test-scopes`. If you are getting dependency resolution issue, run `npm run clean-test-scopes` and try again. 109 | - When all tests pass, everything's fine. 110 | - Commit your changes 111 | - Please provide a git message which explains what you've done. 112 | - This repo uses [Brian's conventional-changelog task](https://github.com/btford/grunt-conventional-changelog) so please make sure your commits follow the [conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit). 113 | - Commit to the forked repository. 114 | - Make a pull request 115 | - Make sure you send the PR to the canary branch. 116 | - Travis CI and a Hound are watching you! 117 | 118 | If you follow these instructions, your PR will land pretty safety in the main repo! 119 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*eslint-env node, commonjs */ 2 | /*eslint comma-dangle:0 */ 3 | 4 | const fs = require('fs'); 5 | 6 | module.exports = function (grunt) { 7 | 'use strict'; 8 | 9 | require('load-grunt-tasks')(grunt); 10 | 11 | // Returns configuration for bower-install plugin 12 | var loadTestScopeConfigurations = function () { 13 | var scopes = fs.readdirSync('./test_scopes').filter(function (filename) { 14 | return typeof filename === 'string' && filename[0] !== '.'; 15 | }); 16 | var config = { 17 | options : { 18 | color : false, 19 | interactive : false 20 | } 21 | }; 22 | // Create a sub config for each test scope 23 | for (var idx in scopes) { 24 | if (scopes.hasOwnProperty(idx)) { 25 | var scope = scopes[idx]; 26 | config['test_scopes_' + scope] = { 27 | options : { 28 | cwd : 'test_scopes/' + scope, 29 | production : false 30 | } 31 | }; 32 | } 33 | } 34 | return config; 35 | }; 36 | 37 | grunt.initConfig({ 38 | pkg : grunt.file.readJSON('package.json'), 39 | meta : { 40 | banner : '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + 41 | '<%= grunt.template.today("yyyy-mm-dd") %>\n' + 42 | '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + 43 | '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 44 | ' Licensed <%= pkg.license %> */' 45 | }, 46 | clean : { 47 | dist : 'dist/', 48 | temp : 'temp/' 49 | }, 50 | eslint : { 51 | chore: { 52 | src : ['Gruntfile.js'], 53 | options: { 54 | configFile: 'Gruntfile.eslint.json' 55 | } 56 | }, 57 | src: { 58 | src : ['src/**/*.js'] 59 | }, 60 | test: { 61 | src : ['test/unit/*.js'] 62 | } 63 | }, 64 | concat : { 65 | 'dist.polyfill' : { 66 | src : [ 67 | 'node_modules/babel-polyfill/dist/polyfill.js', 68 | 'dist/angular-vertxbus.js' 69 | ], 70 | dest : 'dist/angular-vertxbus.withpolyfill.js' 71 | }, 72 | 'dist.min.polyfill' : { 73 | src : [ 74 | 'node_modules/babel-polyfill/dist/polyfill.min.js', 75 | 'dist/angular-vertxbus.min.js' 76 | ], 77 | dest : 'dist/angular-vertxbus.withpolyfill.min.js' 78 | }, 79 | }, 80 | conventionalChangelog : { 81 | options : { 82 | changelogOpts : { 83 | // conventional-changelog options go here 84 | preset : 'angular' 85 | } 86 | }, 87 | release : { 88 | src : 'CHANGELOG.md' 89 | } 90 | }, 91 | ngdocs : { 92 | options : { 93 | dest : 'dist/docs', 94 | html5Mode : false, 95 | startPage : '/api/knalli.angular-vertxbus', 96 | scripts : [ 97 | 'angular.js', 98 | 'docs/github-badge.js' 99 | ] 100 | }, 101 | api : ['src/**/*.js'] 102 | }, 103 | 104 | 'bower-install-simple' : loadTestScopeConfigurations() 105 | 106 | }); 107 | 108 | // Compile and test (use "build" for dist/*) 109 | grunt.registerTask('default', [ 110 | 'clean', 111 | 'eslint', 112 | 'karma:unit' 113 | ]); 114 | 115 | // Linting 116 | grunt.registerTask('lint', [ 117 | 'eslint' 118 | ]); 119 | 120 | grunt.registerTask('install-test', [ 121 | 'bower-install-simple' 122 | ]); 123 | 124 | grunt.registerTask('docs', [ 125 | 'ngdocs:api' 126 | ]); 127 | 128 | // Building & releasing 129 | grunt.registerTask('build-post', [ 130 | 'concat:dist.polyfill', 131 | 'concat:dist.min.polyfill', 132 | ]); 133 | grunt.registerTask('release', [ 134 | 'conventionalChangelog', 135 | ]); 136 | }; 137 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-vertxbus 2 | 3 | ![Bower version](https://img.shields.io/bower/v/angular-vertxbus.svg) [![npm version](https://img.shields.io/npm/v/angular-vertxbus.svg)](https://www.npmjs.com/package/angular-vertxbus) [![cdnjs](https://img.shields.io/cdnjs/v/angular-vertxbus.svg)](https://cdnjs.com/libraries/angular-vertxbus) [![Build Status](https://img.shields.io/travis/knalli/angular-vertxbus.svg)](https://travis-ci.org/knalli/angular-vertxbus) [![Sauce Test Status](https://saucelabs.com/buildstatus/knalli-angular-vertxbus)](https://saucelabs.com/u/angular-vertxbus) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.svg)](http://gruntjs.com/) [![Greenkeeper badge](https://badges.greenkeeper.io/knalli/angular-vertxbus.svg)](https://greenkeeper.io/) 4 | 5 | Client side library using VertX Event Bus as an Angular Service module 6 | 7 | ## Status 8 | 9 | | Branch | Stability | Status | 10 | | --- | --- | --- | 11 | | Canary | unstable | [![Build Status](https://travis-ci.org/knalli/angular-vertxbus.svg?branch=canary)](https://travis-ci.org/knalli/angular-vertxbus) | 12 | | Master | stable | [![Build Status](https://travis-ci.org/knalli/angular-vertxbus.svg?branch=master)](https://travis-ci.org/knalli/angular-vertxbus) | 13 | 14 | Automatic tests running against the latest version of the major browsers: 15 | 16 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/angular-vertxbus.svg)](https://saucelabs.com/) 17 | 18 | 19 | ## How to get 20 | 21 | Either download it manually or install it automatically with Bower `bower install -D angular-vertxbus` or npm `npm install -D angular-vertxbus`. 22 | 23 | Then only import `dist/angular-vertxbus.js` or `dist/angular-vertxbus.min.js`. The file itself comes with a CJS header. 24 | 25 | Alternatively you can use the cdnjs: [cdnjs.com/libraries/angular-vertxbus](https://cdnjs.com/libraries/angular-vertxbus). 26 | 27 | ## Dependencies 28 | 29 | ### JavaScript (Polyfill) 30 | 31 | The source code is written using newer JavaScript ([ECMAScript 2015+](https://babeljs.io/learn-es2015/))and is using the JavaScript transpiler [BabelJS](https://babeljs.io). 32 | 33 | Depending on your target clients, you probably need to include a browser polyfill (for ES5 clients). BabelJS itself 34 | recommends the [requirement of its own polyfill](https://babeljs.io/docs/usage/polyfill/). Either you use the explained 35 | way using npm modules and/or browserify, or you can use the alternative artifact variant `dist/angular-vertxbus.withpolyfill.js`. 36 | 37 | ### AngularJS 1.x 38 | 39 | This library performs integration tests for *AngularJS 1.2 - 1.6*! 40 | 41 | ### Vert.x 42 | 43 | This library is being developed against the `eventbus.js` from Vert.x 3. 44 | 45 | ## How to use 46 | 47 | ### API 48 | 49 | An [Api Documentation](https://knalli.github.io/angular-vertxbus.docs/docs/#/api/knalli.angular-vertxbus) is available. 50 | 51 | ### Quick start 52 | 53 | You have to define the module dependency, this module is named `knalli.angular-vertxbus`. 54 | 55 | ```javascript 56 | angular.module('app', ['knalli.angular-vertxbus']) 57 | .controller('MyCtrl', function(vertxEventBus, vertxEventBusService) { 58 | 59 | // using the EventBus directly 60 | vertxEventBus.send('my.address', {data: 123}); 61 | 62 | // using the service 63 | vertxEventBusService.send('my.address', {data: 123}) 64 | 65 | }); 66 | ``` 67 | 68 | ### Consume messages 69 | 70 | ```javascript 71 | vertxEventBusService.on('myaddress', function(err, message) { 72 | console.log('Received a message: ', message); 73 | }); 74 | ``` 75 | 76 | ### Publish a message 77 | 78 | ```javascript 79 | vertxEventBusService.publish('myaddress', {data: 123}); 80 | ``` 81 | 82 | ### Send a message 83 | 84 | ```javascript 85 | vertxEventBusService.send('myaddress', {data: 123}) 86 | .then(function(reply) { 87 | console.log('A reply received: ', reply); 88 | }) 89 | .catch(function() { 90 | console.warn('No message'); 91 | }); 92 | 93 | // The "No reply message found" is controlled via a timeout (default 10000ms) 94 | vertxEventBusService.send('myaddress', {data: 123}, {timeout: 3000}) 95 | .then(function(reply) { 96 | console.log('A reply received: ', reply); 97 | }) 98 | .catch(function() { 99 | console.warn('No message within 3 seconds'); 100 | }); 101 | 102 | // If the reply is an error, this will be the payload 103 | vertxEventBusService.send('myaddress', {data: 123}) 104 | .then(function(reply) { 105 | console.log('A reply received: ', reply); 106 | }) 107 | .catch(function(err) { 108 | console.warn(err); 109 | }); 110 | ``` 111 | 112 | ## Advanced configuration 113 | 114 | The module has some advanced configuration options. Perhaps you do not have to change them, but at least you should know them! 115 | 116 | Each module configuration option must be defined in the `run` phase, i.e.: 117 | 118 | ```javascript 119 | angular.module('app', ['knalli.angular-vertxbus']) 120 | .config(function(vertxEventBusProvider) { 121 | vertxEventBusProvider 122 | .enable() 123 | .useReconnect() 124 | .useUrlServer('http://live.example.org:8888'); 125 | }); 126 | ``` 127 | 128 | Please have a look at the API documentation for [vertxEventBusProvider](https://knalli.github.io/angular-vertxbus.docs/docs/#/api/knalli.angular-vertxbus.vertxEventBusProvider) 129 | and [vertxEventBusServiceProvider](https://knalli.github.io/angular-vertxbus.docs/docs/#/api/knalli.angular-vertxbus.vertxEventBusServiceProvider) for further options. 130 | 131 | ## Architecture details 132 | 133 | The module contains two items: the stub holder `vertxEventBus` for the Vert.x EventBus and a more comfortbale high level service `vertxEventBusService`. 134 | 135 | *The stub* is required because the Vert.x Event Bus cannot handle a reconnect. The reason is the underlaying SockJS which cannot handle a reconnect, too. A reconnect means to create a new instance of `SockJS`, therefore a new instance of `EventBus`. The stub ensures only one single instance exists. Otherwise a global module was not possible. 136 | 137 | More or less the stub supports the same API calls like the original `EventBus`. 138 | 139 | Based on the stub, the *high level service* `vertxEventBusService` detects disconnects, handles reconnects and ensures re-registrations of subscriptions. Furthermore, the service provides some neat aliases for the usage of handlers. 140 | 141 | ```javascript 142 | // Same as EventBus.registerHandler() 143 | service.registerHandler('myaddress', callback); 144 | service.on('myaddress', callback); 145 | service.addListener('myaddress', callback); 146 | 147 | // Same as EventBus.unregisterHandler() 148 | service.unregisterHandler('myaddress', callback); 149 | service.un('myaddress', callback); 150 | service.removeListener('myaddress', callback); 151 | 152 | // Same as EventBus.send() 153 | service.send('myaddress', data) 154 | 155 | // Same as EventBus.publish 156 | service.publish('myaddress', data) 157 | service.emit('myaddress', data) 158 | 159 | // Same as EventBus.readyState() 160 | service.readyState() 161 | ``` 162 | 163 | In addition to this, when sending a message with an expected reply: 164 | 165 | ```javascript 166 | // Same as EventBus.send() but with a promise 167 | service.send('myaddress', data) 168 | .then(function(reply) {}) 169 | .catch(function(err) {}) 170 | ``` 171 | 172 | For each connect or disconnect, a global broadcast will be emitted (on `$rootScope` with `'vertx-eventbus.system.connected'`, `'vertx-eventbus.system.disconnected'`) 173 | 174 | ## Tests 175 | 176 | ### Unit tests 177 | 178 | Note: Check that dependencies are be installed (`npm install`). 179 | 180 | The *unit tests* are available with `npm test` which is actually a shortcut for `grunt test`. It performs tests under the current primary target version of AngularJS. Use `npm run test-scopes` for testing other scoped versions as well. 181 | 182 | ### Local test environment 183 | 184 | Note: Check that dependencies are be installed (`npm install`). 185 | 186 | The *local test environment* starts and utilizes a full Vert.x node and a NodeJS based web server. 187 | 188 | **Easy:** Just run `npm run -s start-server` and open `http://localhost:3000/` in your preferred browser. 189 | 190 | If you have changed something, just invoke `npm run -s compile` in parallel and refresh the browser. 191 | 192 | Alternatively: 193 | 194 | 1. `npm run install-it-vertx-server` downloads and installs a Vert.x locally. This will store a cached download artifact at `test/e2e//vertx/`. 195 | 2. `npm run start-it-vertx-server` starts an Vert.x on port `8080`. 196 | 3. `npm run start-it-web-server` starts a web server on port `3000`. 197 | 4. Ensure at least `npm run -s compile` has been invoked so there is a `dist/angular-vertxbus.js`. 198 | 5. Open http://localhost:3000/ in your browser. 199 | 200 | ## License 201 | 202 | Copyright 2017 by Jan Philipp. Licensed under MIT. 203 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "AngularJS facade and service acting as a Vert.x SockJS client", 5 | "version": "6.4.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "main": "./dist/angular-vertxbus.js", 8 | "keywords": [ 9 | "angular", 10 | "vertx", 11 | "facade", 12 | "websocket" 13 | ], 14 | "ignore": [ 15 | ".editorconfig", 16 | ".jshintrc", 17 | ".travis.yml", 18 | "karma.conf.js", 19 | "/temp/", 20 | "/test/", 21 | "/test_scopes/", 22 | "/build/", 23 | "/dist/docs/" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/knalli/angular-vertxbus" 28 | }, 29 | "dependencies": { 30 | "angular": ">=1.2 <1.7", 31 | "sockjs-client": "~1.1.0", 32 | "vertx3-eventbus-client": "~3.5.0" 33 | }, 34 | "devDependencies": { 35 | "angular": "~1.6.2", 36 | "angular-mocks": "~1.6.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /build_tools/upload-github-release.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const AdmZip = require('adm-zip'); 5 | const TarGz = require('tar.gz'); 6 | const publishRelease = require('publish-release'); 7 | const rimraf = require('rimraf'); 8 | 9 | // helper 10 | const mkdirSync = function (path) { 11 | try { 12 | fs.mkdirSync(path); 13 | } catch (e) { 14 | if (e.code != 'EEXIST') { 15 | throw e; 16 | } 17 | } 18 | }; 19 | 20 | // Find changelog for a specific version 21 | const getChangelog = (changelogFilePath, forVersion) => { 22 | const prefix = ' str.substr(0, prefix.length + forVersion.length) === `${prefix}${forVersion}`); 33 | if (bodyStartIndex > -1) { 34 | let bodyEndIndex = lines.findIndex((str, idx) => idx > bodyStartIndex && str.substr(0, prefix.length) === prefix); 35 | let header = forVersion; 36 | let body = lines.slice(bodyStartIndex + 1 + skipLines, bodyEndIndex).join('\n'); 37 | resolve({header, body}); 38 | } else { 39 | resolve({header : forVersion, body : ''}); 40 | } 41 | } 42 | }); 43 | }); 44 | }; 45 | 46 | // Build archive type .zip 47 | // FIXME: fix handling of sub directory 48 | const buildZipArchive = ({lookupDir, archiveFilePath}) => { 49 | return new Promise((resolve, reject) => { 50 | fs.readdir(lookupDir, (err, files) => { 51 | if (err) { 52 | reject(); 53 | } else { 54 | let archive = new AdmZip(); 55 | files.forEach(file => { 56 | let localFilename = path.join(lookupDir, file); 57 | archive.addLocalFile(localFilename); 58 | }); 59 | archive.writeZip(archiveFilePath); 60 | resolve(archiveFilePath); 61 | } 62 | }); 63 | }); 64 | }; 65 | 66 | // Build archive type .tar.gz 67 | const buildTarGzArchive = ({lookupDir, archiveFilePath}) => { 68 | let gzipOptions = { 69 | level : 9, 70 | memLevel : 9, 71 | }; 72 | let tarOptions = { 73 | fromBase : true 74 | }; 75 | return new TarGz(gzipOptions, tarOptions) 76 | .compress(lookupDir, archiveFilePath) 77 | .then(() => archiveFilePath); 78 | }; 79 | 80 | // Upload and apply release 81 | const publish = ({ghApiToken, projectVersion, projectVersionName, projectOwner, projectRepo, changelog, assets}) => { 82 | return new Promise((resolve, reject) => { 83 | publishRelease({ 84 | token : ghApiToken, 85 | owner : projectOwner, 86 | repo : projectRepo, 87 | tag : projectVersion, 88 | name : projectVersionName, 89 | notes : changelog.body, 90 | draft : false, 91 | prerelease : false, 92 | reuseRelease : true, 93 | reuseDraftOnly : true, 94 | assets : assets, 95 | }, function (err, release) { 96 | if (err) { 97 | reject(err); 98 | } else { 99 | resolve(release); 100 | } 101 | }) 102 | }); 103 | }; 104 | 105 | // Main 106 | // Load repo details 107 | const pkg = require('./../package.json'); 108 | 109 | if (!process.env.GH_TOKEN) { 110 | console.log('Missing env key GH_TOKEN'); 111 | process.exit(1); 112 | } 113 | //if (!process.env.PROJECT_OWNER) { 114 | // console.log('Missing env key PROJECT_OWNER'); 115 | // process.exit(1); 116 | //} 117 | 118 | console.log(`Get changelog for version ${pkg.version}...`); 119 | const changelogFilePath = path.normalize(path.join(__dirname, '../CHANGELOG.md')); 120 | const distDir = path.normalize(path.join(__dirname, '..', 'dist')); 121 | const tempDir = path.normalize(path.join(__dirname, '..', 'temp')); 122 | const tempAssetsDir = path.normalize(path.join(__dirname, '..', 'temp', 'assets')); 123 | 124 | // ensure temp structure 125 | const resetTempResources = () => { 126 | return new Promise((resolve) => { 127 | if (fs.existsSync(tempAssetsDir)) { 128 | // delete only 129 | rimraf(tempAssetsDir, () => { 130 | mkdirSync(tempAssetsDir); 131 | resolve(); 132 | }); 133 | } else { 134 | mkdirSync(tempDir); 135 | mkdirSync(tempAssetsDir); 136 | resolve(); 137 | } 138 | }); 139 | }; 140 | 141 | // get changelog and get fresh archives 142 | const bundle = () => { 143 | return Promise.all([ 144 | getChangelog(changelogFilePath, pkg.version), 145 | Promise.all([ 146 | buildZipArchive({lookupDir : distDir, archiveFilePath : `${tempAssetsDir}/${pkg.name}-${pkg.version}.zip`}), 147 | buildTarGzArchive({lookupDir : distDir, archiveFilePath : `${tempAssetsDir}/${pkg.name}-${pkg.version}.tar.gz`}), 148 | ]) 149 | ]); 150 | }; 151 | 152 | resetTempResources() 153 | .then(bundle) 154 | .then(([changelog, assets]) => { 155 | return publish({ 156 | ghApiToken : process.env.GH_TOKEN, 157 | projectOwner : 'knalli', 158 | projectRepo : process.env.PROJECT_REPO || pkg.name, 159 | projectVersion : pkg.version, 160 | projectVersionName : `${pkg.name} ${changelog.header || pkg.version}`, 161 | changelog : changelog, 162 | assets : assets, 163 | }); 164 | }) 165 | .then(() => { 166 | console.log('Release published successfully'); 167 | process.exit(0) 168 | }) 169 | .catch((err) => { 170 | console.log('Failed: ' + err); 171 | process.exit(1); 172 | }); 173 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-vertxbus", 3 | "description": "AngularJS facade and service acting as a Vert.x SockJS client", 4 | "version": "master", 5 | "main": "dist/angular-vertxbus.js", 6 | "keywords": ["angular", "vertx", "facade", "websocket"], 7 | "repository": "knalli/angular-vertxbus", 8 | "scripts": [ 9 | "dist/angular-vertxbus.js" 10 | ], 11 | "dependencies": { 12 | "components/angular.js": ">=1.2 <=1.6" 13 | }, 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /dependencyci.yml: -------------------------------------------------------------------------------- 1 | # don't run unlicensed test on any development dependencies 2 | tests: 3 | unlicensed: skip # broken due vertx-ventbus-client (https://dependencyci.com/github/knalli/angular-vertxbus/builds/6) 4 | -------------------------------------------------------------------------------- /docs/github-badge.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | "use strict"; 3 | window.setTimeout(function () { 4 | var img = document.createElement('img'); 5 | img.style.position = 'absolute'; 6 | img.style.top = '40px'; 7 | img.style.right = 0; 8 | img.style.border = 0; 9 | img.src = 'https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67'; 10 | img.alt = 'Fork me on GitHub'; 11 | img.dataCanonicalSrc = 'https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png'; 12 | var a = document.createElement('a'); 13 | a.href = 'https://github.com/knalli/angular-vertxbus'; 14 | a.appendChild(img); 15 | document.body.appendChild(a); 16 | }, 150); 17 | 18 | })(); 19 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /*eslint-env node, commonjs */ 2 | /*eslint comma-dangle:0,no-console:0 */ 3 | 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const webpack = require('webpack'); 7 | const browserslist = require('browserslist'); 8 | 9 | var AVAILABLE_SCOPES = [], isValidScope, injectByScope, getAffectiveScope, isDefaultScope; 10 | 11 | (function () { 12 | AVAILABLE_SCOPES = fs.readdirSync('./test_scopes').filter(function (filename) { 13 | return filename[0] !== '.'; 14 | }); 15 | isValidScope = function (scope) { 16 | return AVAILABLE_SCOPES.indexOf(scope) > -1; 17 | }; 18 | getAffectiveScope = function (scope) { 19 | if (isValidScope(scope)) { 20 | return scope; 21 | } else { 22 | return '(default)'; 23 | } 24 | }; 25 | injectByScope = function (scope, path) { 26 | var prefix = ''; 27 | // unless a scope is given, use the default resources 28 | if (scope && isValidScope(scope)) { 29 | prefix = 'test_scopes/' + scope + '/'; 30 | } 31 | return prefix + 'bower_components/' + path; 32 | }, 33 | isDefaultScope = function (scope) { 34 | return !isValidScope(scope); 35 | }; 36 | })(); 37 | 38 | /** 39 | * Configuration set for SauceLabs browser tests 40 | * @type {{enabled, launchers, buildOptions}} 41 | */ 42 | const sourcelabsConfig = ((browsers) => { 43 | 44 | const enabled = !!process.env.SAUCE_ENABLED; 45 | 46 | // parse list of browsers (by browserslist) and build a useful list 47 | const launchers = browsers 48 | .map((string) => { 49 | let [name, version] = string.split(' '); 50 | return { 51 | name, 52 | version, 53 | }; 54 | }) 55 | .filter(browser => { 56 | switch (browser.name) { 57 | case 'chrome': 58 | case 'edge': 59 | case 'firefox': 60 | case 'ie': 61 | case 'opera': 62 | case 'safari': 63 | return true; 64 | default: 65 | return false; 66 | } 67 | }) 68 | .map(browser => { 69 | switch (browser.name) { 70 | case 'chrome': 71 | return { 72 | id : `sl_${browser.name}_${browser.version}`, 73 | base : 'SauceLabs', 74 | browserName : browser.name, 75 | platform : 'Windows 7', 76 | version : browser.version 77 | }; 78 | case 'firefox': 79 | return { 80 | id : `sl_${browser.name}_${browser.version}`, 81 | base : 'SauceLabs', 82 | browserName : browser.name, 83 | platform : 'Windows 7', 84 | version : browser.version 85 | }; 86 | case 'ie': 87 | return { 88 | id : `sl_${browser.name}_${browser.version}`, 89 | base : 'SauceLabs', 90 | browserName : 'internet explorer', 91 | platform : 'Windows 7', 92 | version : browser.version 93 | }; 94 | case 'edge': 95 | return { 96 | id : `sl_${browser.name}_${browser.version}`, 97 | base : 'SauceLabs', 98 | browserName : 'microsoftedge', 99 | platform : 'Windows 10', 100 | version : browser.version 101 | }; 102 | case 'safari': 103 | // skip 9 104 | if (browser.version.substring(0, 1) === '9') { 105 | break; 106 | } 107 | return { 108 | id : `sl_${browser.name}_${browser.version}`, 109 | base : 'SauceLabs', 110 | browserName : browser.name, 111 | platform : 'macOS 10.12', 112 | version : browser.version 113 | }; 114 | } 115 | }) 116 | .filter(browser => browser); 117 | 118 | const buildOptions = (scope) => { 119 | return { 120 | testName : `angular-vertxbus Unit Tests, scope: ${scope}`, 121 | verbose : true, 122 | doctor : true, 123 | logger : console.log 124 | }; 125 | }; 126 | 127 | return { 128 | enabled, 129 | launchers, 130 | buildOptions, 131 | }; 132 | })(browserslist('last 2 versions, Firefox ESR')); 133 | 134 | module.exports = function (config) { 135 | 136 | const scope = process.env.TEST_SCOPE; 137 | const actualScope = getAffectiveScope(scope); 138 | console.log('Available test scopes: ', AVAILABLE_SCOPES); 139 | console.log('Currently selected scope: ', actualScope); 140 | 141 | var vertxEventBusFile = injectByScope(scope, 'vertx3-eventbus-client/vertx-eventbus.js'); 142 | 143 | config.set({ 144 | 145 | // list of files / patterns to load in the browser 146 | files : [ 147 | injectByScope(scope, 'angular/angular.js'), 148 | injectByScope(scope, 'angular-mocks/angular-mocks.js'), 149 | 'test/unit/util/unhandledRejectionTracing.js', 150 | 'node_modules/babel-polyfill/browser.js', 151 | 'test/unit/test_index.js', 152 | ], 153 | 154 | frameworks : ['expect', 'mocha', 'jasmine'], 155 | 156 | reporters : (() => { 157 | let reporters = ['progress']; 158 | if (isDefaultScope(scope)) { 159 | reporters.push('coverage-istanbul'); 160 | } 161 | if (sourcelabsConfig.enabled) { 162 | reporters.push('saucelabs'); 163 | } 164 | return reporters; 165 | })(), 166 | 167 | preprocessors : { 168 | 'test/unit/test_index.js' : ['webpack'], 169 | }, 170 | 171 | // SourceLabs 172 | // https://oligofren.wordpress.com/2014/05/27/running-karma-tests-on-browserstack/ 173 | // http://stackoverflow.com/questions/24093155/karma-sauce-launcher-disconnects-every-test-run-resulting-in-failed-runs-with-ie 174 | sauceLabs : ((scope) => { 175 | if (sourcelabsConfig.enabled) { 176 | return sourcelabsConfig.buildOptions(scope); 177 | } 178 | })(actualScope), 179 | customLaunchers : (() => { 180 | if (sourcelabsConfig.enabled) { 181 | return sourcelabsConfig.launchers; 182 | } 183 | })(), 184 | browserDisconnectTimeout : (() => { 185 | if (sourcelabsConfig.enabled) { 186 | return 10000; // default 2000 187 | } 188 | })(), 189 | browserDisconnectTolerance : (() => { 190 | if (sourcelabsConfig.enabled) { 191 | return 1; // default 0 192 | } 193 | })(), 194 | browserNoActivityTimeout : (() => { 195 | if (sourcelabsConfig.enabled) { 196 | return 5 * 60 * 1000; // default 10000 197 | } 198 | })(), 199 | 200 | webpack : { 201 | devtool : 'source-map', 202 | //entry: [], 203 | resolve : { 204 | modules : [ 205 | path.join(__dirname, ''), 206 | path.join(__dirname, 'src'), 207 | path.join(__dirname, 'test'), 208 | 'node_modules' 209 | ], 210 | alias : { 211 | 'sockjs-client' : 'test/unit/mock/sockjs.js', 212 | 'vertx-eventbus' : vertxEventBusFile 213 | } 214 | }, 215 | module : { 216 | rules : [ 217 | { 218 | enforce : 'pre', 219 | test : /\.js$/, 220 | exclude : [ 221 | /(node_modules|bower_components)/, 222 | ], 223 | loader : 'babel-loader', 224 | options : { 225 | presets : ['env'], 226 | plugins : ['transform-runtime'], 227 | }, 228 | }, 229 | { 230 | enforce : 'post', 231 | test : /\.js$/, 232 | use: { 233 | loader : 'istanbul-instrumenter-loader', 234 | options : { 235 | esModules : true, 236 | }, 237 | }, 238 | include : [ 239 | path.resolve('src/') 240 | ], 241 | exclude : [ 242 | /(node_modules|bower_components)/, 243 | ], 244 | }, 245 | { 246 | test : /vertx-eventbus\.js$/, 247 | loader : 'imports-loader', 248 | options : { 249 | 'SockJS' : 'sockjs-client', 250 | }, 251 | }, 252 | ] 253 | }, 254 | plugins : [ 255 | //new JasmineWebpackPlugin(), 256 | new webpack.ProvidePlugin({ 257 | 'EventBus' : 'vertx-eventbus', 258 | 'SockJS' : 'sockjs-client', 259 | 'window.EventBus' : 'vertx-eventbus', 260 | 'global.EventBus' : 'vertx-eventbus' 261 | }) 262 | ] 263 | }, 264 | 265 | webpackMiddleware : { 266 | noInfo : true 267 | }, 268 | 269 | coverageIstanbulReporter : (() => { 270 | if (isDefaultScope(scope)) { 271 | return { 272 | fixWebpackSourcePaths: true, 273 | reports: [ 274 | 'text-summary', 275 | 'lcovonly', 276 | ], 277 | dir : 'build/coverage', 278 | lcovonly: { 279 | subdir : 'report', 280 | type : 'lcov', 281 | }, 282 | }; 283 | } 284 | })(), 285 | 286 | // web server port 287 | port : 9876, 288 | 289 | // cli runner port 290 | runnerPort : 9100, 291 | 292 | // enable / disable colors in the output (reporters and logs) 293 | colors : true, 294 | 295 | // level of logging 296 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 297 | logLevel : config.LOG_INFO, 298 | 299 | // enable / disable watching file and executing tests whenever any file changes 300 | autoWatch : true, 301 | 302 | // Start these browsers, currently available: 303 | // - Chrome 304 | // - ChromeCanary 305 | // - Firefox 306 | // - Opera 307 | // - Safari (only Mac) 308 | // - PhantomJS 309 | // - IE (only Windows) 310 | browsers : (() => { 311 | if (process.env.WATCH) { 312 | return []; 313 | } 314 | 315 | let browsers = []; 316 | if (sourcelabsConfig.enabled) { 317 | browsers = [...browsers, ...Object.keys(sourcelabsConfig.launchers)]; 318 | } else if (process.env.TRAVIS) { 319 | browsers.push('ChromeHeadless'); 320 | } else { 321 | if (process.env.NO_HEADLESS) { 322 | browsers.push('Chrome'); 323 | } else { 324 | browsers.push('ChromeHeadless'); 325 | } 326 | } 327 | return browsers; 328 | })(), 329 | 330 | // If browser does not capture in given timeout [ms], kill it 331 | captureTimeout : (() => { 332 | if (sourcelabsConfig.enabled) { 333 | return 5 * 60 * 1000; // default 60000 334 | } else { 335 | return 1 * 60 * 1000; 336 | } 337 | })(), 338 | 339 | // Continuous Integration mode 340 | // if true, it capture browsers, run tests and exit 341 | singleRun : process.env.WATCH ? false : true 342 | }); 343 | }; 344 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-vertxbus", 3 | "version": "6.4.1", 4 | "description": "AngularJS facade and service acting as a Vert.x SockJS client", 5 | "main": "dist/angular-vertxbus.js", 6 | "keywords": [ 7 | "angular", 8 | "vertx", 9 | "facade", 10 | "websocket" 11 | ], 12 | "engines": { 13 | "node": ">*" 14 | }, 15 | "devEngines": { 16 | "node": ">=8.9", 17 | "npm": ">=5.3" 18 | }, 19 | "scripts": { 20 | "check-env": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json", 21 | "clean": "grunt clean", 22 | "clean-test-scopes": "for f in test_scopes/*; do (cd $f; rm -rf bower_components); done", 23 | "prepare": "bower install", 24 | "lint": "eslint --ignore-pattern node_modules/**,bower_components/** --ext .js src/** *.js", 25 | "test-headless": "karma start --browsers='PhantomJS' karma.conf.js", 26 | "test-karma": "karma start karma.conf.js", 27 | "test": "npm run -s check-env && npm run -s lint && grunt install-test && npm run -s test-karma", 28 | "test-scopes": "grunt install-test && for f in test_scopes/*; do TEST_SCOPE=\"`basename $f`\" npm run -s test; done", 29 | "start-it-web-server": "babel-node test/e2e/server.js", 30 | "install-it-vertx-server": "cd test/e2e/vertx && ./install-vertx.sh", 31 | "start-it-vertx-server": "cd test/e2e/vertx/app && ../runtime/vertx/bin/vertx run vertx3-config.js", 32 | "start-server": "npm-run-all --silent clean compile-dist install-it-vertx-server --parallel start-it-vertx-server start-it-web-server", 33 | "compile-dist": "webpack", 34 | "compile-distmin": "BUILD_MINIFIED=1 webpack", 35 | "compile": "grunt clean && npm run -s compile-dist && npm run -s compile-distmin && grunt build-post", 36 | "build": "npm run -s check-env && npm run -s test && npm run -s compile", 37 | "release": "npm run -s clean && npm run -s build && grunt release", 38 | "upload-github-release": "node build_tools/upload-github-release.js", 39 | "docs": "grunt docs" 40 | }, 41 | "author": { 42 | "name": "Jan Philipp", 43 | "email": "knallisworld@googlemail.com" 44 | }, 45 | "homepage": "https://github.com/knalli/angular-vertxbus", 46 | "repository": { 47 | "type": "git", 48 | "url": "git://github.com/knalli/angular-vertxbus" 49 | }, 50 | "license": "MIT", 51 | "devDependencies": { 52 | "adm-zip": "^0.4.7", 53 | "babel-cli": "^6.26.0", 54 | "babel-core": "^6.26.0", 55 | "babel-eslint": "^8.2.2", 56 | "babel-loader": "^7.1.2", 57 | "babel-plugin-transform-runtime": "^6.5.2", 58 | "babel-polyfill": "^6.26.0", 59 | "babel-preset-env": "^1.6.1", 60 | "bower": "1.8.2", 61 | "browserslist": "^3.1.1", 62 | "eslint": "^4.18.1", 63 | "eslint-loader": "^1.6.1", 64 | "eslint-plugin-angular": "^3.2.0", 65 | "estraverse": "^4.1.0", 66 | "express": "^4.16.2", 67 | "fbjs-scripts": "^0.8.0", 68 | "grunt": "^1.0.2", 69 | "grunt-babel": "^7.0.0", 70 | "grunt-bower-install-simple": "~1.2.3", 71 | "grunt-cli": "^1.2.0", 72 | "grunt-contrib-clean": "~1.1.0", 73 | "grunt-contrib-concat": "^1.0.0", 74 | "grunt-conventional-changelog": "^6.1.0", 75 | "grunt-ngdocs": "^0.2.11", 76 | "imports-loader": "^0.8.0", 77 | "istanbul": "^0.4.0", 78 | "istanbul-instrumenter-loader": "^3.0.0", 79 | "jasmine-core": "^2.99.1", 80 | "jasmine-webpack-plugin": "^0.1.1", 81 | "karma": "^2.0.0", 82 | "karma-babel-preprocessor": "^7.0.0", 83 | "karma-chrome-launcher": "^2.0.0", 84 | "karma-coverage": "^1.0.0", 85 | "karma-coverage-istanbul-reporter": "^1.4.1", 86 | "karma-expect": "~1.1.3", 87 | "karma-firefox-launcher": "~1.1.0", 88 | "karma-jasmine": "^1.1.1", 89 | "karma-mocha": "^1.0.1", 90 | "karma-phantomjs-launcher": "^1.0.0", 91 | "karma-sauce-launcher": "^1.2.0", 92 | "karma-sourcemap-loader": "^0.3.7", 93 | "karma-webpack": "^2.0.9", 94 | "load-grunt-tasks": "^3.3.0", 95 | "lodash": "^4.17.5", 96 | "mocha": "^5.0.1", 97 | "ng-annotate-webpack-plugin": "^0.2.0", 98 | "npm-run-all": "^4.1.2", 99 | "phantomjs-prebuilt": "^2.1.16", 100 | "publish-release": "^1.5.0", 101 | "rimraf": "^2.6.2", 102 | "tar.gz": "^1.0.7", 103 | "transform-loader": "^0.2.3", 104 | "webpack": "^3.11.0" 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const moduleName = 'knalli.angular-vertxbus'; 2 | 3 | export {moduleName}; 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import moduleName from './module'; 2 | 3 | export default moduleName; 4 | -------------------------------------------------------------------------------- /src/lib/VertxEventBusServiceProvider.js: -------------------------------------------------------------------------------- 1 | import EventBusDelegate from './service/delegate/EventBusDelegate'; 2 | import NoopDelegate from './service/delegate/NoopDelegate'; 3 | import Delegator from './service/Delegator'; 4 | 5 | /** 6 | * @ngdoc service 7 | * @module knalli.angular-vertxbus 8 | * @name knalli.angular-vertxbus.vertxEventBusServiceProvider 9 | * @description 10 | * This is the configuration provider for {@link knalli.angular-vertxbus.vertxEventBusService}. 11 | */ 12 | 13 | const DEFAULTS = { 14 | enabled : true, 15 | debugEnabled : false, 16 | authRequired : false, 17 | prefix : 'vertx-eventbus.', 18 | sockjsStateInterval : 10000, 19 | messageBuffer : 10000 20 | }; 21 | 22 | let VertxEventBusServiceProvider = function () { 23 | 24 | // options (globally, application-wide) 25 | var options = angular.extend({}, DEFAULTS); 26 | 27 | /** 28 | * @ngdoc method 29 | * @module knalli.angular-vertxbus 30 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 31 | * @name .#enable 32 | * 33 | * @description 34 | * Enables or disables the service. This setup is immutable. 35 | * 36 | * @param {boolean} [value=true] service is enabled on startup 37 | * @returns {object} this 38 | */ 39 | this.enable = (value = DEFAULTS.enabled) => { 40 | options.enabled = (value === true); 41 | return this; 42 | }; 43 | 44 | /** 45 | * @ngdoc method 46 | * @module knalli.angular-vertxbus 47 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 48 | * @name .#useDebug 49 | * 50 | * @description 51 | * Enables a verbose mode in which certain events will be logged to `$log`. 52 | * 53 | * @param {boolean} [value=false] verbose mode (using `$log`) 54 | * @returns {object} this 55 | */ 56 | this.useDebug = (value = DEFAULTS.debugEnabled) => { 57 | options.debugEnabled = (value === true); 58 | return this; 59 | }; 60 | 61 | /** 62 | * @ngdoc method 63 | * @module knalli.angular-vertxbus 64 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 65 | * @name .#usePrefix 66 | * 67 | * @description 68 | * Overrides the default prefix which will be used for emitted events. 69 | * 70 | * @param {string} [value='vertx-eventbus.'] prefix used in event names 71 | * @returns {object} this 72 | */ 73 | this.usePrefix = (value = DEFAULTS.prefix) => { 74 | options.prefix = value; 75 | return this; 76 | }; 77 | 78 | /** 79 | * @ngdoc method 80 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 81 | * @name .#useSockJsStateInterval 82 | * 83 | * 84 | * @description 85 | * Overrides the interval of checking the connection is still valid (required for reconnecting automatically). 86 | * 87 | * @param {boolean} [value=10000] interval of checking the underlying connection's state (in ms) 88 | * @returns {object} this 89 | */ 90 | this.useSockJsStateInterval = (value = DEFAULTS.sockjsStateInterval) => { 91 | options.sockjsStateInterval = value; 92 | return this; 93 | }; 94 | 95 | /** 96 | * @ngdoc method 97 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 98 | * @name .#useMessageBuffer 99 | * 100 | * @description 101 | * Enables buffering of (sending) messages. 102 | * 103 | * The setting defines the total amount of buffered messages (`0` no buffering). A message will be buffered if 104 | * connection is still in progress, the connection is stale or a login is required/pending. 105 | * 106 | * @param {boolean} [value=0] allowed total amount of messages in the buffer 107 | * @returns {object} this 108 | */ 109 | this.useMessageBuffer = (value = DEFAULTS.messageBuffer) => { 110 | options.messageBuffer = value; 111 | return this; 112 | }; 113 | 114 | /** 115 | * @ngdoc method 116 | * @module knalli.angular-vertxbus 117 | * @methodOf knalli.angular-vertxbus.vertxEventBusServiceProvider 118 | * @name .#authHandler 119 | * 120 | * @description 121 | * Function or service reference name for function checking the authorization state. 122 | * 123 | * The result of the function must be a boolean or promise. The handler can (but is not required) to create authorization on demand. 124 | * If it is resolved, the authorization is valid. 125 | * If it is rejected, the authorization is invalid. 126 | * 127 | * @param {string|function} value authorization handler (either a function or a service name) 128 | * @returns {object} promise 129 | */ 130 | this.authHandler = (value) => { 131 | options.authHandler = value; 132 | options.authRequired = !!value; 133 | return this; 134 | }; 135 | 136 | /** 137 | * @ngdoc service 138 | * @module knalli.angular-vertxbus 139 | * @name knalli.angular-vertxbus.vertxEventBusService 140 | * @description 141 | * A service utilizing an underlying Vert.x Event Bus 142 | * 143 | * The advanced features of this service are: 144 | * - broadcasting the connection changes (vertx-eventbus.system.connected, vertx-eventbus.system.disconnected) on $rootScope 145 | * - registering all handlers again when a reconnect had been required 146 | * - supporting a promise when using send() 147 | * - adding aliases on (registerHandler), un (unregisterHandler) and emit (publish) 148 | * 149 | * Basic usage: 150 | *
151 |    * module.controller('MyController', function('vertxEventService') {
152 |  *   vertxEventService.on('my.address', function(message) {
153 |  *     console.log("JSON Message received: ", message)
154 |  *   });
155 |  *   vertxEventService.publish('my.other.address', {type: 'foo', data: 'bar'});
156 |  * });
157 |    * 
158 | * 159 | * Note the additional {@link knalli.angular-vertxbus.vertxEventBusServiceProvider configuration} of the module itself. 160 | * 161 | * @requires knalli.angular-vertxbus.vertxEventBus 162 | * @requires $rootScope 163 | * @requires $q 164 | * @requires $interval 165 | * @requires $log 166 | * @requires $injector 167 | */ 168 | /* @ngInject */ 169 | this.$get = ($rootScope, $q, $interval, vertxEventBus, $log, $injector) => { 170 | // Current options (merged defaults with application-wide settings) 171 | let instanceOptions = angular.extend({}, vertxEventBus.getOptions(), options); 172 | if (instanceOptions.enabled) { 173 | return new Delegator( 174 | new EventBusDelegate($rootScope, $interval, $log, $q, $injector, vertxEventBus, instanceOptions), 175 | $log 176 | ); 177 | } else { 178 | return new Delegator(new NoopDelegate()); 179 | } 180 | }; 181 | 182 | }; 183 | 184 | export default VertxEventBusServiceProvider; 185 | -------------------------------------------------------------------------------- /src/lib/VertxEventBusWrapperProvider.js: -------------------------------------------------------------------------------- 1 | import EventBusAdapter from './adapter/EventBusAdapter'; 2 | import NoopAdapter from './adapter/NoopAdapter'; 3 | import ConnectionConfigHolder from './support/ConnectionConfigHolder'; 4 | 5 | import EventBus from 'vertx-eventbus'; 6 | 7 | /** 8 | * @ngdoc service 9 | * @module knalli.angular-vertxbus 10 | * @name knalli.angular-vertxbus.vertxEventBusProvider 11 | * @description 12 | * An AngularJS wrapper for projects using the VertX Event Bus 13 | */ 14 | 15 | const DEFAULTS = { 16 | enabled : true, 17 | debugEnabled : false, 18 | initialConnectEnabled : true, 19 | urlServer : `${location.protocol}//${location.hostname}` + ((() => { 20 | if (location.port) { 21 | return `:${location.port}`; 22 | } 23 | })() || ''), 24 | urlPath : '/eventbus', 25 | reconnectEnabled : true, 26 | sockjsReconnectInterval : 10000, 27 | sockjsOptions : {} 28 | }; 29 | 30 | let VertxEventBusWrapperProvider = function () { 31 | 32 | // options (globally, application-wide) 33 | var options = angular.extend({}, DEFAULTS); 34 | 35 | /** 36 | * @ngdoc method 37 | * @module knalli.angular-vertxbus 38 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 39 | * @name .#enable 40 | * 41 | * @description 42 | * Enables or disables the service. This setup is immutable. 43 | * 44 | * @param {boolean} [value=true] service is enabled on startup 45 | * @returns {object} this 46 | */ 47 | this.enable = (value = DEFAULTS.enabled) => { 48 | options.enabled = (value === true); 49 | return this; 50 | }; 51 | 52 | /** 53 | * @ngdoc method 54 | * @module knalli.angular-vertxbus 55 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 56 | * @name .#disableAutoConnect 57 | * 58 | * @description 59 | * Disables the auto connection feature. 60 | * 61 | * This feature will be only available if `enable == true`. 62 | * 63 | * @param {boolean} [value=true] auto connect on startup 64 | * @returns {object} this 65 | */ 66 | this.disableAutoConnect = () => { 67 | options.initialConnectEnabled = false; 68 | return this; 69 | }; 70 | 71 | /** 72 | * @ngdoc method 73 | * @module knalli.angular-vertxbus 74 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 75 | * @name .#useDebug 76 | * 77 | * @description 78 | * Enables a verbose mode in which certain events will be logged to `$log`. 79 | * 80 | * @param {boolean} [value=false] verbose mode (using `$log`) 81 | * @returns {object} this 82 | */ 83 | this.useDebug = (value = DEFAULTS.debugEnabled) => { 84 | options.debugEnabled = (value === true); 85 | return this; 86 | }; 87 | 88 | /** 89 | * @ngdoc method 90 | * @module knalli.angular-vertxbus 91 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 92 | * @name .#useUrlServer 93 | * 94 | * @description 95 | * Overrides the url part "server" for connecting. The default is based on 96 | * - `location.protocol` 97 | * - `location.hostname` 98 | * - `location.port` 99 | * 100 | * i.e. `http://domain.tld` or `http://domain.tld:port` 101 | * 102 | * @param {boolean} [value=$computed] server to connect (default based on `location.protocol`, `location.hostname` and `location.port`) 103 | * @returns {object} this 104 | */ 105 | this.useUrlServer = (value = DEFAULTS.urlServer) => { 106 | options.urlServer = value; 107 | return this; 108 | }; 109 | 110 | /** 111 | * @ngdoc method 112 | * @module knalli.angular-vertxbus 113 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 114 | * @name .#useUrlPath 115 | * 116 | * @description 117 | * Overrides the url part "path" for connection. 118 | * 119 | * @param {boolean} [value='/eventbus'] path to connect 120 | * @returns {object} this 121 | */ 122 | this.useUrlPath = (value = DEFAULTS.urlPath) => { 123 | options.urlPath = value; 124 | return this; 125 | }; 126 | 127 | /** 128 | * @ngdoc method 129 | * @module knalli.angular-vertxbus 130 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 131 | * @name .#useReconnect 132 | * 133 | * @description 134 | * Enables or disables the automatic reconnect handling. 135 | * 136 | * @param {boolean} [value=true] if a disconnect was being noted, a reconnect will be enforced automatically 137 | * @returns {object} this 138 | */ 139 | this.useReconnect = (value = DEFAULTS.reconnectEnabled) => { 140 | options.reconnectEnabled = value; 141 | return this; 142 | }; 143 | 144 | /** 145 | * @ngdoc method 146 | * @module knalli.angular-vertxbus 147 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 148 | * @name .#useSockJsReconnectInterval 149 | * 150 | * @description 151 | * Overrides the timeout for reconnecting after a disconnect was found. 152 | * 153 | * @param {boolean} [value=10000] time between a disconnect and the next try to reconnect (in ms) 154 | * @returns {object} this 155 | */ 156 | this.useSockJsReconnectInterval = (value = DEFAULTS.sockjsReconnectInterval) => { 157 | options.sockjsReconnectInterval = value; 158 | return this; 159 | }; 160 | 161 | /** 162 | * @ngdoc method 163 | * @module knalli.angular-vertxbus 164 | * @methodOf knalli.angular-vertxbus.vertxEventBusProvider 165 | * @name .#useSockJsOptions 166 | * 167 | * @description 168 | * Sets additional params for the `SockJS` instance. 169 | * 170 | * Internally, it will be applied (as `options`) like `new SockJS(url, undefined, options)`. 171 | * 172 | * @param {boolean} [value={}] optional params for raw SockJS options 173 | * @returns {object} this 174 | */ 175 | this.useSockJsOptions = (value = DEFAULTS.sockjsOptions) => { 176 | options.sockjsOptions = value; 177 | return this; 178 | }; 179 | 180 | /** 181 | * @ngdoc service 182 | * @module knalli.angular-vertxbus 183 | * @name knalli.angular-vertxbus.vertxEventBus 184 | * @description 185 | * A stub representing the Vert.x EventBus (core functionality) 186 | * 187 | * Because the Event Bus cannot handle a reconnect (because of the underlaying SockJS), a 188 | * new instance of the bus have to be created. 189 | * This stub ensures only one object holding the current active instance of the bus. 190 | * 191 | * The stub supports theses Vert.x Event Bus APIs: 192 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_close close()} 193 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_send send(address, message, handler)} 194 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_publish publish(address, message)} 195 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_registerHandler registerHandler(adress, handler)} 196 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_unregisterHandler unregisterHandler(address, handler)} 197 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_readyState readyState()} 198 | * 199 | * Furthermore, the stub supports theses extra APIs: 200 | * - {@link knalli.angular-vertxbus.vertxEventBus#methods_reconnect reconnect()} 201 | * 202 | * @requires $timeout 203 | * @requires $log 204 | */ 205 | /* @ngInject */ 206 | this.$get = ($timeout, $log, $q) => { 207 | // Current options (merged defaults with application-wide settings) 208 | let instanceOptions = angular.extend({}, DEFAULTS, options); 209 | if (instanceOptions.enabled && EventBus) { 210 | if (instanceOptions.debugEnabled) { 211 | $log.debug('[Vert.x EB Stub] Enabled'); 212 | } 213 | 214 | // aggregate server connection params 215 | instanceOptions.connectionConfig = new ConnectionConfigHolder({ 216 | urlServer : instanceOptions.urlServer, 217 | urlPath : instanceOptions.urlPath 218 | }); 219 | delete instanceOptions.urlServer; 220 | delete instanceOptions.urlPath; 221 | 222 | return new EventBusAdapter(EventBus, $timeout, $log, $q, instanceOptions); 223 | } else { 224 | if (instanceOptions.debugEnabled) { 225 | $log.debug('[Vert.x EB Stub] Disabled'); 226 | } 227 | return new NoopAdapter(EventBus, $q); 228 | } 229 | }; 230 | 231 | }; 232 | 233 | export default VertxEventBusWrapperProvider; 234 | -------------------------------------------------------------------------------- /src/lib/adapter/BaseAdapter.js: -------------------------------------------------------------------------------- 1 | export default class BaseAdapter { 2 | 3 | constructor($q) { 4 | this.$q = $q; 5 | } 6 | 7 | configureConnection() { 8 | } 9 | 10 | connect() { 11 | return this.$q.reject(); 12 | } 13 | 14 | reconnect() { 15 | } 16 | 17 | close() { 18 | } 19 | 20 | send() { 21 | } 22 | 23 | publish() { 24 | } 25 | 26 | registerHandler() { 27 | } 28 | 29 | unregisterHandler() { 30 | } 31 | 32 | readyState() { 33 | } 34 | 35 | getOptions() { 36 | return {}; 37 | } 38 | 39 | // empty: can be overriden by externals 40 | onopen() { 41 | } 42 | 43 | // empty: can be overriden by externals 44 | onclose() { 45 | } 46 | 47 | // private 48 | getDefaultHeaders() { 49 | return this.defaultHeaders; 50 | } 51 | 52 | /** 53 | * @ngdoc method 54 | * @module knalli.angular-vertxbus 55 | * @methodOf knalli.angular-vertxbus.vertxEventBus 56 | * @name .#applyDefaultHeaders 57 | * 58 | * @description 59 | * Stores the given default headers 60 | * 61 | * @param {object} headers additional standard headers 62 | */ 63 | applyDefaultHeaders(headers = {}) { 64 | this.defaultHeaders = angular.extend({}, headers); 65 | } 66 | 67 | // private 68 | getMergedHeaders(headers = {}) { 69 | return angular.extend({}, this.defaultHeaders, headers); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/lib/adapter/EventBusAdapter.js: -------------------------------------------------------------------------------- 1 | import {moduleName} from '../../config.js'; 2 | 3 | import BaseAdapter from './BaseAdapter'; 4 | import ConnectionConfigHolder from './../support/ConnectionConfigHolder'; 5 | 6 | /** 7 | * @ngdoc service 8 | * @module global 9 | * @name global.EventBus 10 | * 11 | * @description 12 | * This is the interface of `EventBus`. It is not included. 13 | */ 14 | 15 | /** 16 | * @ngdoc method 17 | * @module global 18 | * @methodOf global.EventBus 19 | * @name .#close 20 | */ 21 | 22 | /** 23 | * @ngdoc method 24 | * @module global 25 | * @methodOf global.EventBus 26 | * @name .#send 27 | * 28 | * @param {string} address target address 29 | * @param {object} message payload message 30 | * @param {object=} headers headers 31 | * @param {function=} replyHandler optional callback 32 | * @param {function=} failureHandler optional callback 33 | */ 34 | 35 | /** 36 | * @ngdoc method 37 | * @module global 38 | * @methodOf global.EventBus 39 | * @name .#publish 40 | * 41 | * @param {string} address target address 42 | * @param {object} message payload message 43 | * @param {object=} headers headers 44 | */ 45 | 46 | /** 47 | * @ngdoc method 48 | * @module global 49 | * @methodOf global.EventBus 50 | * @name .#registerHandler 51 | * 52 | * @param {string} address target address 53 | * @param {function} handler callback handler 54 | * @param {object=} headers headers 55 | */ 56 | 57 | /** 58 | * @ngdoc method 59 | * @module global 60 | * @methodOf global.EventBus 61 | * @name .#unregisterHandler 62 | * 63 | * @param {string} address target address 64 | * @param {function} handler callback handler to be removed 65 | * @param {object=} headers headers 66 | */ 67 | 68 | /** 69 | * @ngdoc property 70 | * @module global 71 | * @propertyOf global.EventBus 72 | * @name .#onopen 73 | * @description 74 | * Defines the callback called on opening the connection. 75 | */ 76 | 77 | /** 78 | * @ngdoc property 79 | * @module global 80 | * @propertyOf global.EventBus 81 | * @name .#onclose 82 | * @description 83 | * Defines the callback called on closing the connection. 84 | */ 85 | 86 | /** 87 | * @ngdoc property 88 | * @module global 89 | * @propertyOf global.EventBus 90 | * @name .#onerror 91 | * @description 92 | * Defines the callback called on any error. 93 | */ 94 | 95 | /** 96 | * @ngdoc property 97 | * @module global 98 | * @propertyOf global.EventBus 99 | * @name .#onreconnect 100 | * @description 101 | * Defines the callback called on reconnecting the connection (after onopen). 102 | */ 103 | 104 | export default class EventBusAdapter extends BaseAdapter { 105 | 106 | constructor(EventBus, 107 | $timeout, 108 | $log, 109 | $q, { 110 | enabled, 111 | debugEnabled, 112 | initialConnectEnabled, 113 | connectionConfig, 114 | reconnectEnabled, 115 | sockjsReconnectInterval, 116 | sockjsOptions 117 | }) { 118 | super($q); 119 | // actual EventBus type 120 | this.EventBus = EventBus; 121 | this.$timeout = $timeout; 122 | this.$log = $log; 123 | this.$q = $q; 124 | this.options = { 125 | enabled, 126 | debugEnabled, 127 | initialConnectEnabled, 128 | connectionConfig, 129 | reconnectEnabled, 130 | sockjsReconnectInterval, 131 | sockjsOptions 132 | }; 133 | this.nativeReconnectAvailable = false; 134 | this.disconnectTimeoutEnabled = true; 135 | this.applyDefaultHeaders(); 136 | if (initialConnectEnabled) { 137 | // asap create connection 138 | this.connect(); 139 | } 140 | } 141 | 142 | /** 143 | * @ngdoc method 144 | * @module knalli.angular-vertxbus 145 | * @methodOf knalli.angular-vertxbus.vertxEventBus 146 | * @name .#configureConnect 147 | * 148 | * @description 149 | * Reconfigure the connection details. 150 | * 151 | * @param {string} urlServer see {@link knalli.angular-vertxbus.vertxEventBusProvider#methods_useUrlServer vertxEventBusProvider.useUrlServer()} 152 | * @param {string} [urlPath=/eventbus] see {@link knalli.angular-vertxbus.vertxEventBusProvider#methods_useUrlPath vertxEventBusProvider.useUrlPath()} 153 | */ 154 | configureConnection(urlServer, urlPath = '/eventbus') { 155 | this.options.connectionConfig = new ConnectionConfigHolder({urlServer, urlPath}); 156 | return this; 157 | } 158 | 159 | connect() { 160 | // connect promise 161 | let deferred = this.$q.defer(); 162 | // currently valid url 163 | let url = `${this.options.connectionConfig.urlServer}${this.options.connectionConfig.urlPath}`; 164 | if (this.options.debugEnabled) { 165 | this.$log.debug(`[Vert.x EB Stub] Enabled: connecting '${url}'`); 166 | } 167 | // Because we have rebuild an EventBus object (because it have to rebuild a SockJS object) 168 | // we must wrap the object. Therefore, we have to mimic the behavior of onopen and onclose each time. 169 | this.instance = new this.EventBus(url, this.options.sockjsOptions); 170 | // Since vertx-eventbus 3.5.0 support for "native" reconnect is available 171 | this.nativeReconnectAvailable = typeof this.instance.enableReconnect === 'function'; 172 | if (this.nativeReconnectAvailable && this.options.reconnectEnabled) { 173 | this.instance.enableReconnect(true); 174 | } 175 | this.instance.onopen = () => { 176 | if (this.options.debugEnabled) { 177 | this.$log.debug('[Vert.x EB Stub] Connected'); 178 | } 179 | if (angular.isFunction(this.onopen)) { 180 | this.onopen(); 181 | } 182 | deferred.resolve(); 183 | }; 184 | // instance onClose handler 185 | this.instance.onclose = () => { 186 | // Since vertx-eventbus@3.5.0, the EventBus itself can handle reconnects 187 | if (this.nativeReconnectAvailable && this.instance.reconnectTimerID) { 188 | // 'reconnectTimerID' will be only set if reconnect is enabled 189 | if (this.options.debugEnabled) { 190 | this.$log.debug('[Vert.x EB Stub] Reconnect required, but seems to be handled by EventBus itself'); 191 | } 192 | return; 193 | } 194 | if (this.options.debugEnabled) { 195 | this.$log.debug(`[Vert.x EB Stub] Reconnect in ${this.options.sockjsReconnectInterval}ms`); 196 | } 197 | if (angular.isFunction(this.onclose)) { 198 | this.onclose(); 199 | } 200 | this.instance = undefined; 201 | 202 | if (!this.disconnectTimeoutEnabled) { 203 | // reconnect required asap 204 | if (this.options.debugEnabled) { 205 | this.$log.debug('[Vert.x EB Stub] Reconnect immediately'); 206 | } 207 | this.disconnectTimeoutEnabled = true; 208 | this.connect(); 209 | } else if (this.options.reconnectEnabled) { 210 | // automatic reconnect after timeout 211 | if (this.options.debugEnabled) { 212 | this.$log.debug(`[Vert.x EB Stub] Reconnect in ${this.options.sockjsReconnectInterval}ms`); 213 | } 214 | this.$timeout((() => this.connect()), this.options.sockjsReconnectInterval); 215 | } 216 | }; 217 | // instance onError handler 218 | this.instance.onerror = (message) => { 219 | if (angular.isFunction(this.onerror)) { 220 | this.onerror(message); 221 | } 222 | }; 223 | // instance onReconnect handler 224 | this.instance.onreconnect = (message) => { 225 | if (angular.isFunction(this.onreconnect)) { 226 | this.onreconnect(message); 227 | } 228 | }; 229 | return deferred.promise; 230 | } 231 | 232 | /** 233 | * @ngdoc method 234 | * @module knalli.angular-vertxbus 235 | * @methodOf knalli.angular-vertxbus.vertxEventBus 236 | * @name .#reconnect 237 | * 238 | * @description 239 | * Reconnects the underlying connection. 240 | * 241 | * Unless a connection is open, it will connect using a new one. 242 | * 243 | * If a connection is already open, it will close this one and opens a new one. If `immediately` is `true`, the 244 | * default timeout for reconnect will be skipped. 245 | * 246 | * @param {boolean} [immediately=false] optionally enforce a reconnect asap instead of using the timeout 247 | */ 248 | reconnect(immediately = false) { 249 | if (this.instance && this.instance.state === this.EventBus.OPEN) { 250 | if (immediately) { 251 | this.disconnectTimeoutEnabled = false; 252 | } 253 | this.instance.close(); 254 | } else { 255 | this.connect(); 256 | } 257 | } 258 | 259 | /** 260 | * @ngdoc method 261 | * @module knalli.angular-vertxbus 262 | * @methodOf knalli.angular-vertxbus.vertxEventBus 263 | * @name .#close 264 | * 265 | * @description 266 | * Closes the underlying connection. 267 | * 268 | * Note: If automatic reconnection is active, a new connection will be established after the {@link knalli.angular-vertxbus.vertxEventBusProvider#methods_useReconnect reconnect timeout}. 269 | * 270 | * See also: 271 | * - {@link EventBus#methods_close EventBus.close()} 272 | */ 273 | close() { 274 | if (this.instance) { 275 | this.instance.close(); 276 | } 277 | } 278 | 279 | /** 280 | * @ngdoc method 281 | * @module knalli.angular-vertxbus 282 | * @methodOf knalli.angular-vertxbus.vertxEventBus 283 | * @name .#send 284 | * 285 | * @description 286 | * Sends a message 287 | * 288 | * See also: 289 | * - {@link global.EventBus#methods_send EventBus.send()} 290 | * 291 | * @param {string} address target address 292 | * @param {object} message payload message 293 | * @param {object} headers optional headers 294 | * @param {function=} replyHandler optional callback 295 | */ 296 | send(address, message, headers, replyHandler) { 297 | if (this.instance) { 298 | const mergedHeaders = this.getMergedHeaders(headers); 299 | this.instance.send(address, message, mergedHeaders, replyHandler); 300 | } 301 | } 302 | 303 | /** 304 | * @ngdoc method 305 | * @module knalli.angular-vertxbus 306 | * @methodOf knalli.angular-vertxbus.vertxEventBus 307 | * @name .#publish 308 | * 309 | * @description 310 | * Publishes a message 311 | * 312 | * See also: 313 | * - {@link global.EventBus#methods_publish EventBus.publish()} 314 | * 315 | * @param {string} address target address 316 | * @param {object} message payload message 317 | * @param {object=} headers optional headers 318 | */ 319 | publish(address, message, headers) { 320 | if (this.instance) { 321 | const mergedHeaders = this.getMergedHeaders(headers); 322 | this.instance.publish(address, message, mergedHeaders); 323 | } 324 | } 325 | 326 | /** 327 | * @ngdoc method 328 | * @module knalli.angular-vertxbus 329 | * @methodOf knalli.angular-vertxbus.vertxEventBus 330 | * @name .#registerHandler 331 | * 332 | * @description 333 | * Registers a listener 334 | * 335 | * See also: 336 | * - {@link global.EventBus#methods_registerHandler EventBus.registerHandler()} 337 | * 338 | * @param {string} address target address 339 | * @param {object=} headers optional headers 340 | * @param {function} handler callback handler 341 | */ 342 | registerHandler(address, headers, handler) { 343 | if (this.instance) { 344 | if (angular.isFunction(headers) && !handler) { 345 | handler = headers; 346 | headers = undefined; 347 | } 348 | const mergedHeaders = this.getMergedHeaders(headers); 349 | this.instance.registerHandler(address, mergedHeaders, handler); 350 | // and return the deregister callback 351 | let deconstructor = () => { 352 | this.unregisterHandler(address, mergedHeaders, handler); 353 | }; 354 | deconstructor.displayName = `${moduleName}.wrapper.eventbus.registerHandler.deconstructor`; 355 | return deconstructor; 356 | } 357 | } 358 | 359 | /** 360 | * @ngdoc method 361 | * @module knalli.angular-vertxbus 362 | * @methodOf knalli.angular-vertxbus.vertxEventBus 363 | * @name .#unregisterHandler 364 | * 365 | * @description 366 | * Removes a registered a listener 367 | * 368 | * See also: 369 | * - {@link global.EventBus#methods_unregisterHandler EventBus.unregisterHandler()} 370 | * 371 | * @param {string} address target address 372 | * @param {object=} headers optional headers 373 | * @param {function} handler callback handler to be removed 374 | */ 375 | unregisterHandler(address, headers, handler) { 376 | if (this.instance && this.instance.state === this.EventBus.OPEN) { 377 | if (angular.isFunction(headers) && !handler) { 378 | handler = headers; 379 | headers = undefined; 380 | } 381 | const mergedHeaders = this.getMergedHeaders(headers); 382 | this.instance.unregisterHandler(address, mergedHeaders, handler); 383 | } 384 | } 385 | 386 | /** 387 | * @ngdoc method 388 | * @module knalli.angular-vertxbus 389 | * @methodOf knalli.angular-vertxbus.vertxEventBus 390 | * @name .#readyState 391 | * 392 | * @description 393 | * Returns the current connection state 394 | * 395 | * @returns {number} value of vertx-eventbus connection states 396 | */ 397 | readyState() { 398 | if (this.instance) { 399 | return this.instance.state; 400 | } else { 401 | return this.EventBus.CLOSED; 402 | } 403 | } 404 | 405 | get state() { 406 | return this.readyState(); 407 | } 408 | 409 | // private 410 | getOptions() { 411 | // clone options 412 | return angular.extend({}, this.options); 413 | } 414 | 415 | } 416 | -------------------------------------------------------------------------------- /src/lib/adapter/NoopAdapter.js: -------------------------------------------------------------------------------- 1 | import BaseAdapter from './BaseAdapter'; 2 | 3 | export default class NoopAdapter extends BaseAdapter { 4 | 5 | constructor(EventBus, $q) { 6 | super($q); 7 | // actual EventBus type 8 | this.EventBus = EventBus; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/lib/adapter/index.js: -------------------------------------------------------------------------------- 1 | import EventBusAdapter from './EventBusAdapter'; 2 | import NoopAdapter from './NoopAdapter'; 3 | 4 | export {EventBusAdapter, NoopAdapter}; 5 | -------------------------------------------------------------------------------- /src/lib/service/Delegator.js: -------------------------------------------------------------------------------- 1 | import {moduleName} from '../../config'; 2 | 3 | export default class Delegator { 4 | 5 | constructor(delegate, $log) { 6 | this.delegate = delegate; 7 | this.$log = $log; 8 | this.handlers = {}; 9 | this.delegate.observe({ 10 | afterEventbusConnected: () => this.afterEventbusConnected() 11 | }); 12 | } 13 | 14 | afterEventbusConnected() { 15 | for (let address in this.handlers) { 16 | if (Object.prototype.hasOwnProperty.call(this.handlers, address)) { 17 | let callbacks = this.handlers[address]; 18 | if (callbacks && callbacks.length) { 19 | for (let {headers, callback} of callbacks) { 20 | this.delegate.registerHandler(address, headers, callback); 21 | } 22 | } 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * @ngdoc method 29 | * @module knalli.angular-vertxbus 30 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 31 | * @name .#registerHandler 32 | * 33 | * @description 34 | * Registers a callback handler for the specified address match. 35 | * 36 | * @param {string} address target address 37 | * @param {object} headers optional headers 38 | * @param {function} callback handler with params `(message, replyTo)` 39 | * @returns {function} deconstructor 40 | */ 41 | registerHandler(address, headers, callback) { 42 | if (!this.handlers[address]) { 43 | this.handlers[address] = []; 44 | } 45 | var handler = {headers, callback}; 46 | this.handlers[address].push(handler); 47 | var unregisterFn = null; 48 | if (this.delegate.isConnectionOpen()) { 49 | this.delegate.registerHandler(address, headers, callback); 50 | unregisterFn = () => this.delegate.unregisterHandler(address, headers, callback); 51 | } 52 | // and return the deregister callback 53 | var deconstructor = () => { 54 | if (unregisterFn) { 55 | unregisterFn(); 56 | unregisterFn = undefined; 57 | } 58 | // Remove from internal map 59 | if (this.handlers[address]) { 60 | var index = this.handlers[address].indexOf(handler); 61 | if (index > -1) { 62 | this.handlers[address].splice(index, 1); 63 | } 64 | if (this.handlers[address].length < 1) { 65 | this.handlers[address] = undefined; 66 | } 67 | } 68 | }; 69 | deconstructor.displayName = `${moduleName}.service.registerHandler.deconstructor`; 70 | return deconstructor; 71 | } 72 | 73 | /** 74 | * @ngdoc method 75 | * @module knalli.angular-vertxbus 76 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 77 | * @name .#on 78 | * 79 | * @description 80 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_registerHandler registerHandler()}) 81 | */ 82 | on(address, headers, callback) { 83 | return this.registerHandler(address, headers, callback); 84 | } 85 | 86 | /** 87 | * @ngdoc method 88 | * @module knalli.angular-vertxbus 89 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 90 | * @name .#addListener 91 | * 92 | * @description 93 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_registerHandler registerHandler()}) 94 | */ 95 | addListener(address, headers, callback) { 96 | return this.registerHandler(address, headers, callback); 97 | } 98 | 99 | /** 100 | * @ngdoc method 101 | * @module knalli.angular-vertxbus 102 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 103 | * @name .#unregisterHandler 104 | * 105 | * @description 106 | * Removes a callback handler for the specified address match. 107 | * 108 | * @param {string} address target address 109 | * @param {object} headers optional headers 110 | * @param {function} callback handler with params `(message, replyTo)` 111 | */ 112 | unregisterHandler(address, headers, callback) { 113 | // Remove from internal map 114 | if (this.handlers[address]) { 115 | var index = this.handlers[address].indexOf({headers, callback}); 116 | if (index > -1) { 117 | this.handlers[address].splice(index, 1); 118 | } 119 | if (this.handlers[address].length < 1) { 120 | this.handlers[address] = undefined; 121 | } 122 | } 123 | // Remove from real instance 124 | if (this.delegate.isConnectionOpen()) { 125 | this.delegate.unregisterHandler(address, headers, callback); 126 | } 127 | } 128 | 129 | /** 130 | * @ngdoc method 131 | * @module knalli.angular-vertxbus 132 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 133 | * @name .#un 134 | * 135 | * @description 136 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_registerHandler unregisterHandler()}) 137 | */ 138 | un(address, headers, callback) { 139 | return this.unregisterHandler(address, headers, callback); 140 | } 141 | 142 | /** 143 | * @ngdoc method 144 | * @module knalli.angular-vertxbus 145 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 146 | * @name .#removeListener 147 | * 148 | * @description 149 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_registerHandler unregisterHandler()}) 150 | */ 151 | removeListener(address, headers, callback) { 152 | return this.unregisterHandler(address, headers, callback); 153 | } 154 | 155 | /** 156 | * @ngdoc method 157 | * @module knalli.angular-vertxbus 158 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 159 | * @name .#send 160 | * 161 | * @description 162 | * Sends a message to the specified address (using {@link knalli.angular-vertxbus.vertxEventBus#methods_send vertxEventBus.send()}). 163 | * 164 | * @param {string} address target address 165 | * @param {object} message payload message 166 | * @param {object} headers headers 167 | * @param {Object} options additional options 168 | * @param {number=} [options.timeout=10000] (in ms) after which the promise will be rejected 169 | * @param {boolean=} [options.expectReply=true] if false, the promise will be resolved directly and 170 | * no replyHandler will be created 171 | * @returns {object} promise 172 | */ 173 | send(address, message, headers = {}, options = {timeout: 10000, expectReply: true}) { 174 | return this.delegate.send(address, message, headers, options.timeout, options.expectReply); 175 | } 176 | 177 | /** 178 | * @ngdoc method 179 | * @module knalli.angular-vertxbus 180 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 181 | * @name .#publish 182 | * 183 | * @description 184 | * Publishes a message to the specified address (using {@link knalli.angular-vertxbus.vertxEventBus#methods_publish vertxEventBus.publish()}). 185 | * 186 | * @param {string} address target address 187 | * @param {object} message payload message 188 | * @param {object=} headers headers 189 | * @returns {object} promise (resolved on either performed or queued) 190 | */ 191 | publish(address, message, headers = {}) { 192 | return this.delegate.publish(address, message, headers); 193 | } 194 | 195 | /** 196 | * @ngdoc method 197 | * @module knalli.angular-vertxbus 198 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 199 | * @name .#emit 200 | * 201 | * @description 202 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_publish publish()}) 203 | */ 204 | emit(address, message, headers = {}) { 205 | return this.publish(address, message, headers); 206 | } 207 | 208 | /** 209 | * @ngdoc method 210 | * @module knalli.angular-vertxbus 211 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 212 | * @name .#getConnectionState 213 | * 214 | * @description 215 | * Returns the current connection state. The state is being cached internally. 216 | * 217 | * @returns {number} state type of vertx.EventBus 218 | */ 219 | getConnectionState() { 220 | return this.delegate.getConnectionState(); 221 | } 222 | 223 | /** 224 | * @ngdoc method 225 | * @module knalli.angular-vertxbus 226 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 227 | * @name .#readyState 228 | * 229 | * @description 230 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_getConnectionState getConnectionState()}) 231 | */ 232 | readyState() { 233 | return this.getConnectionState(); 234 | } 235 | 236 | 237 | 238 | /** 239 | * @ngdoc method 240 | * @module knalli.angular-vertxbus 241 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 242 | * @name .#isConnectionOpen 243 | * 244 | * @description 245 | * Returns true if the current connection state ({@link knalli.angular-vertxbus.vertxEventBusService#methods_getConnectionState getConnectionState()}) is `OPEN`. 246 | * 247 | * @returns {boolean} connection open state 248 | */ 249 | isConnectionOpen() { 250 | return this.isConnectionOpen(); 251 | } 252 | 253 | /** 254 | * @ngdoc method 255 | * @module knalli.angular-vertxbus 256 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 257 | * @name .#isEnabled 258 | * 259 | * @description 260 | * Returns true if service is being enabled. 261 | * 262 | * @returns {boolean} state 263 | */ 264 | isEnabled() { 265 | return this.delegate.isEnabled(); 266 | } 267 | 268 | /** 269 | * @ngdoc method 270 | * @module knalli.angular-vertxbus 271 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 272 | * @name .#isConnected 273 | * 274 | * @description 275 | * Returns true if service (and the eventbus) is being connected. 276 | * 277 | * @returns {boolean} state 278 | */ 279 | isConnected() { 280 | return this.delegate.isConnected(); 281 | } 282 | 283 | /** 284 | * @ngdoc method 285 | * @module knalli.angular-vertxbus 286 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 287 | * @name .#isAuthorized 288 | * 289 | * @description 290 | * Returns true if the authorization is valid 291 | * 292 | * @returns {boolean} state 293 | */ 294 | isAuthorized() { 295 | return this.delegate.isAuthorized(); 296 | } 297 | 298 | /** 299 | * @ngdoc method 300 | * @module knalli.angular-vertxbus 301 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 302 | * @name .#isValidSession 303 | * 304 | * See (using {@link knalli.angular-vertxbus.vertxEventBusService#methods_isAuthorized isAuthorized()}) 305 | */ 306 | isValidSession() { 307 | return this.delegate.isAuthorized(); 308 | } 309 | 310 | /** 311 | * @ngdoc method 312 | * @module knalli.angular-vertxbus 313 | * @methodOf knalli.angular-vertxbus.vertxEventBusService 314 | * @name .#getMessageQueueLength 315 | * 316 | * @description 317 | * Returns the current amount of messages in the internal buffer. 318 | * 319 | * @returns {number} amount 320 | */ 321 | getMessageQueueLength() { 322 | return this.delegate.getMessageQueueLength(); 323 | } 324 | 325 | } 326 | -------------------------------------------------------------------------------- /src/lib/service/delegate/BaseDelegate.js: -------------------------------------------------------------------------------- 1 | export default class BaseDelegate { 2 | 3 | observe() {} 4 | 5 | getConnectionState() { 6 | return 3; // CLOSED 7 | } 8 | 9 | isConnectionOpen() { 10 | return false; 11 | } 12 | 13 | isAuthorized() { 14 | return false; 15 | } 16 | 17 | isEnabled() { 18 | return false; 19 | } 20 | 21 | isConnected() { 22 | return false; 23 | } 24 | 25 | send() {} 26 | 27 | publish() {} 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/lib/service/delegate/EventBusDelegate.js: -------------------------------------------------------------------------------- 1 | import {moduleName} from '../../../config'; 2 | 3 | import Queue from './../../support/Queue'; 4 | import SimpleMap from './../../support/SimpleMap'; 5 | import BaseDelegate from './BaseDelegate'; 6 | 7 | /** 8 | * @ngdoc event 9 | * @module knalli.angular-vertxbus 10 | * @eventOf knalli.angular-vertxbus.vertxEventBusService 11 | * @eventType broadcast on $rootScope 12 | * @name disconnected 13 | * 14 | * @description 15 | * After a connection was being terminated. 16 | * 17 | * Event name is `prefix + 'system.disconnected'` (see {@link knalli.angular-vertxbus.vertxEventBusServiceProvider#methods_usePrefix prefix}) 18 | */ 19 | 20 | /** 21 | * @ngdoc event 22 | * @module knalli.angular-vertxbus 23 | * @eventOf knalli.angular-vertxbus.vertxEventBusService 24 | * @eventType broadcast on $rootScope 25 | * @name connected 26 | * 27 | * @description 28 | * After a connection was being established 29 | * 30 | * Event name is `prefix + 'system.connected'` (see {@link knalli.angular-vertxbus.vertxEventBusServiceProvider#methods_usePrefix prefix}) 31 | */ 32 | 33 | /** 34 | * @ngdoc event 35 | * @module knalli.angular-vertxbus 36 | * @eventOf knalli.angular-vertxbus.vertxEventBusService 37 | * @eventType broadcast on $rootScope 38 | * @name reconnected 39 | * 40 | * @description 41 | * After a connection was being re-established 42 | * 43 | * Event name is `prefix + 'system.reconnected'` (see {@link knalli.angular-vertxbus.vertxEventBusServiceProvider#methods_usePrefix prefix}) 44 | */ 45 | 46 | /** 47 | * @ngdoc event 48 | * @module knalli.angular-vertxbus 49 | * @eventOf knalli.angular-vertxbus.vertxEventBusService 50 | * @eventType broadcast on $rootScope 51 | * @name login-succeeded 52 | * 53 | * @description 54 | * After a login has been validated successfully 55 | * 56 | * Event name is `prefix + 'system.login.succeeded'` (see {@link knalli.angular-vertxbus.vertxEventBusServiceProvider#methods_usePrefix prefix}) 57 | * 58 | * @param {object} data data 59 | * @param {boolean} data.status must be `'ok'` 60 | */ 61 | 62 | /** 63 | * @ngdoc event 64 | * @module knalli.angular-vertxbus 65 | * @eventOf knalli.angular-vertxbus.vertxEventBusService 66 | * @eventType broadcast on $rootScope 67 | * @name login-failed 68 | * 69 | * @description 70 | * After a login has been destroyed or was invalidated 71 | * 72 | * Event name is `prefix + 'system.login.failed'` (see {@link knalli.angular-vertxbus.vertxEventBusServiceProvider#methods_usePrefix prefix}) 73 | * 74 | * @param {object} data data 75 | * @param {boolean} data.status must be not`'ok'` 76 | */ 77 | 78 | export default class EventBusDelegate extends BaseDelegate { 79 | 80 | constructor($rootScope, 81 | $interval, 82 | $log, 83 | $q, 84 | $injector, 85 | eventBus, 86 | { 87 | enabled, 88 | debugEnabled, 89 | prefix, 90 | sockjsStateInterval, 91 | messageBuffer, 92 | authRequired, 93 | authHandler 94 | }) { 95 | super(); 96 | this.$rootScope = $rootScope; 97 | this.$interval = $interval; 98 | this.$log = $log; 99 | this.$q = $q; 100 | this.eventBus = eventBus; 101 | this.options = { 102 | enabled, 103 | debugEnabled, 104 | prefix, 105 | sockjsStateInterval, 106 | messageBuffer, 107 | authRequired 108 | }; 109 | if (angular.isFunction(authHandler)) { 110 | this.authHandler = authHandler; 111 | } else if (angular.isString(authHandler)) { 112 | try { 113 | this.authHandler = $injector.get(authHandler); 114 | } catch (e) { 115 | if (this.options.debugEnabled) { 116 | this.$log.debug('[Vert.x EB Service] Failed to resolve authHandler: %s', e.message); 117 | } 118 | } 119 | } 120 | this.connectionState = this.eventBus.EventBus.CLOSED; 121 | this.states = { 122 | connected : false, 123 | authorized : false 124 | }; 125 | this.observers = []; 126 | // internal store of buffered messages 127 | this.messageQueue = new Queue(this.options.messageBuffer); 128 | // internal map of callbacks 129 | this.callbackMap = new SimpleMap(); 130 | // asap 131 | this.initialize(); 132 | } 133 | 134 | // internal 135 | initialize() { 136 | this.eventBus.onopen = () => this.onEventbusOpen(); 137 | this.eventBus.onclose = () => this.onEventbusClose(); 138 | this.eventBus.onreconnect = () => this.onEventbusReconnect(); 139 | 140 | // Update the current connection state periodically. 141 | let connectionIntervalCheck = () => this.getConnectionState(true); 142 | connectionIntervalCheck.displayName = 'connectionIntervalCheck'; 143 | this.$interval((() => connectionIntervalCheck()), this.options.sockjsStateInterval); 144 | } 145 | 146 | // internal 147 | onEventbusOpen() { 148 | let connectionStateFlipped = false; 149 | this.getConnectionState(true); 150 | if (!this.states.connected) { 151 | this.states.connected = true; 152 | connectionStateFlipped = true; 153 | } 154 | // Ensure all events will be re-attached 155 | this.afterEventbusConnected(); 156 | // Everything is online and registered again, let's notify everybody 157 | if (connectionStateFlipped) { 158 | this.$rootScope.$broadcast(`${this.options.prefix}system.connected`); 159 | } 160 | this.$rootScope.$digest(); // explicitly 161 | // consume message queue? 162 | if (this.options.messageBuffer && this.messageQueue.size()) { 163 | while (this.messageQueue.size()) { 164 | let fn = this.messageQueue.first(); 165 | if (angular.isFunction(fn)) { 166 | fn(); 167 | } 168 | } 169 | this.$rootScope.$digest(); 170 | } 171 | } 172 | 173 | // internal 174 | onEventbusClose() { 175 | this.getConnectionState(true); 176 | if (this.states.connected) { 177 | this.states.connected = false; 178 | this.$rootScope.$broadcast(`${this.options.prefix}system.disconnected`); 179 | } 180 | } 181 | 182 | // internal 183 | onEventbusReconnect() { 184 | // will be fired after a onEventbusOpen 185 | if (this.states.connected) { 186 | this.$rootScope.$broadcast(`${this.options.prefix}system.reconnected`); 187 | } 188 | } 189 | 190 | // internal 191 | observe(observer) { 192 | this.observers.push(observer); 193 | } 194 | 195 | // internal 196 | afterEventbusConnected() { 197 | for (let observer of this.observers) { 198 | if (angular.isFunction(observer.afterEventbusConnected)) { 199 | observer.afterEventbusConnected(); 200 | } 201 | } 202 | } 203 | 204 | registerHandler(address, headers, callback) { 205 | if (angular.isFunction(headers) && !callback) { 206 | callback = headers; 207 | headers = undefined; 208 | } 209 | if (!angular.isFunction(callback)) { 210 | return; 211 | } 212 | if (this.options.debugEnabled) { 213 | this.$log.debug(`[Vert.x EB Service] Register handler for ${address}`); 214 | } 215 | var callbackWrapper = (err, {body}, replyTo) => { 216 | callback(body, replyTo); 217 | this.$rootScope.$digest(); 218 | }; 219 | callbackWrapper.displayName = `${moduleName}.service.delegate.live.registerHandler.callbackWrapper`; 220 | this.callbackMap.put(callback, callbackWrapper); 221 | return this.eventBus.registerHandler(address, headers, callbackWrapper); 222 | } 223 | 224 | unregisterHandler(address, headers, callback) { 225 | if (angular.isFunction(headers) && !callback) { 226 | callback = headers; 227 | headers = undefined; 228 | } 229 | if (!angular.isFunction(callback)) { 230 | return; 231 | } 232 | if (this.options.debugEnabled) { 233 | this.$log.debug(`[Vert.x EB Service] Unregister handler for ${address}`); 234 | } 235 | this.eventBus.unregisterHandler(address, headers, this.callbackMap.get(callback)); 236 | this.callbackMap.remove(callback); 237 | } 238 | 239 | send(address, message, headers, timeout = 10000, expectReply = true) { 240 | let deferred = this.$q.defer(); 241 | let next = () => { 242 | if (expectReply) { 243 | // Register timeout for promise rejecting 244 | let timer = this.$interval((() => { 245 | if (this.options.debugEnabled) { 246 | this.$log.debug(`[Vert.x EB Service] send('${address}') timed out`); 247 | } 248 | deferred.reject(); 249 | }), timeout, 1); 250 | // Send message 251 | try { 252 | this.eventBus.send(address, message, headers, (err, reply) => { 253 | this.$interval.cancel(timer); // because it's resolved 254 | if (err) { 255 | deferred.reject(err); 256 | } else { 257 | deferred.resolve(reply); 258 | } 259 | }); 260 | } catch (e) { 261 | this.$interval.cancel(timer); // because it's resolved 262 | deferred.reject(e); 263 | } 264 | } else { 265 | try { 266 | this.eventBus.send(address, message, headers); 267 | deferred.resolve(); 268 | } catch (e) { 269 | deferred.reject(e); 270 | } 271 | } 272 | }; 273 | next.displayName = `${moduleName}.service.delegate.live.send.next`; 274 | this.ensureOpenAuthConnection(next).then(null, deferred.reject); 275 | return deferred.promise; 276 | } 277 | 278 | publish(address, message, headers) { 279 | return this.ensureOpenAuthConnection(() => this.eventBus.publish(address, message, headers)); 280 | } 281 | 282 | /** 283 | * Ensures the callback will be performed with an open connection. 284 | * 285 | * Unless an open connection was found, the callback will be queued in the message buffer (if available). 286 | * 287 | * @param {function} fn callback 288 | * @returns {object} promise (resolved on either performed or queued) 289 | */ 290 | ensureOpenConnection(fn) { 291 | const deferred = this.$q.defer(); 292 | if (this.isConnectionOpen()) { 293 | try { 294 | fn(); 295 | } catch (e) { 296 | deferred.reject(e); 297 | } 298 | deferred.resolve({ 299 | inQueue : false 300 | }); 301 | } else if (this.options.messageBuffer) { 302 | this.messageQueue.push(fn); 303 | deferred.resolve({ 304 | inQueue : true 305 | }); 306 | } else { 307 | deferred.reject(); 308 | } 309 | return deferred.promise; 310 | } 311 | 312 | /** 313 | * Ensures the callback will be performed with a valid session. 314 | * 315 | * Unless `authRequired` is enabled, this will be simple forward. 316 | * 317 | * Unless a valid session exist (but required), the callback will be not invoked. 318 | * 319 | * @param {function} fn callback 320 | * @returns {object} promise (resolved on either performed or queued) 321 | */ 322 | ensureOpenAuthConnection(fn) { 323 | if (!this.options.authRequired) { 324 | // easy: no login required 325 | return this.ensureOpenConnection(fn); 326 | } else { 327 | let fnWrapper = () => { 328 | if (this.authHandler) { 329 | const onValidAuth = () => { 330 | this.states.authorized = true; 331 | fn(); 332 | }; 333 | const onInvalidAuth = () => { 334 | this.states.authorized = false; 335 | if (this.options.debugEnabled) { 336 | this.$log.debug('[Vert.x EB Service] Message was not sent due authHandler rejected'); 337 | } 338 | }; 339 | const authResult = this.authHandler(this.eventBus); 340 | if (!(authResult && angular.isFunction(authResult.then))) { 341 | if (this.options.debugEnabled) { 342 | this.$log.debug('[Vert.x EB Service] Message was not sent because authHandler is returning not a promise'); 343 | } 344 | return false; 345 | } 346 | authResult.then(onValidAuth, onInvalidAuth); 347 | return true; 348 | } else { 349 | // ignore this message 350 | if (this.options.debugEnabled) { 351 | this.$log.debug('[Vert.x EB Service] Message was not sent because no authHandler is defined'); 352 | } 353 | return false; 354 | } 355 | }; 356 | fnWrapper.displayName = `${moduleName}.service.delegate.live.ensureOpenAuthConnection.fnWrapper`; 357 | return this.ensureOpenConnection(fnWrapper); 358 | } 359 | } 360 | 361 | /** 362 | * Returns the current connection state. The state is being cached internally. 363 | * 364 | * @param {boolean=} [immediate=false] if true, the connection state will be queried directly. 365 | * @returns {number} state type of vertx.EventBus 366 | */ 367 | getConnectionState(immediate) { 368 | if (this.options.enabled) { 369 | if (immediate) { 370 | this.connectionState = this.eventBus.state; 371 | } 372 | } else { 373 | this.connectionState = this.eventBus.EventBus.CLOSED; 374 | } 375 | return this.connectionState; 376 | } 377 | 378 | /** 379 | * Returns true if the current connection state ({@link knalli.angular-vertxbus.vertxEventBusService#methods_getConnectionState getConnectionState()}) is `OPEN`. 380 | * 381 | * @returns {boolean} connection open state 382 | */ 383 | isConnectionOpen() { 384 | return this.getConnectionState() === this.eventBus.EventBus.OPEN; 385 | } 386 | 387 | /** 388 | * Returns true if the session is valid 389 | * 390 | * @returns {boolean} state 391 | */ 392 | isAuthorized() { 393 | return this.states.authorized; 394 | } 395 | 396 | // internal 397 | isConnected() { 398 | return this.states.connected; 399 | } 400 | 401 | isEnabled() { 402 | return this.options.enabled; 403 | } 404 | 405 | /** 406 | * Returns the current amount of messages in the internal buffer. 407 | * 408 | * @returns {number} amount 409 | */ 410 | getMessageQueueLength() { 411 | return this.messageQueue.size(); 412 | } 413 | 414 | } 415 | -------------------------------------------------------------------------------- /src/lib/service/delegate/NoopDelegate.js: -------------------------------------------------------------------------------- 1 | import BaseDelegate from './BaseDelegate'; 2 | 3 | export default class NoopDelegate extends BaseDelegate {} 4 | -------------------------------------------------------------------------------- /src/lib/support/ConnectionConfigHolder.js: -------------------------------------------------------------------------------- 1 | export default class ConnectionConfigHolder { 2 | 3 | constructor({urlServer, urlPath}) { 4 | this._urlServer = urlServer; 5 | this._urlPath = urlPath; 6 | } 7 | 8 | get urlServer() { 9 | return this._urlServer; 10 | } 11 | 12 | get urlPath() { 13 | return this._urlPath; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/support/Queue.js: -------------------------------------------------------------------------------- 1 | /* 2 | Simple queue implementation 3 | 4 | FIFO: #push() + #first() 5 | LIFO: #push() + #last() 6 | */ 7 | export default class Queue { 8 | 9 | constructor(maxSize = 10) { 10 | this.maxSize = maxSize; 11 | this.items = []; 12 | } 13 | 14 | push(item) { 15 | this.items.push(item); 16 | return this.recalibrateBufferSize(); 17 | } 18 | 19 | recalibrateBufferSize() { 20 | while (this.items.length > this.maxSize) { 21 | this.first(); 22 | } 23 | return this; 24 | } 25 | 26 | last() { 27 | return this.items.pop(); 28 | } 29 | 30 | first() { 31 | return this.items.shift(0); 32 | } 33 | 34 | size() { 35 | return this.items.length; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/lib/support/SimpleMap.js: -------------------------------------------------------------------------------- 1 | /* 2 | Simple Map implementation 3 | 4 | This implementation allows usage of non serializable keys for values. 5 | */ 6 | export default class SimpleMap { 7 | 8 | constructor() { 9 | this.clear(); 10 | } 11 | 12 | // Stores the value under the key. 13 | // Chainable 14 | put(key, value) { 15 | var idx = this._indexForKey(key); 16 | if (idx > -1) { 17 | this.values[idx] = value; 18 | } else { 19 | this.keys.push(key); 20 | this.values.push(value); 21 | } 22 | return this; 23 | } 24 | 25 | // Returns value for key, otherwise undefined. 26 | get(key) { 27 | var idx = this._indexForKey(key); 28 | if (idx > -1) { 29 | return this.values[idx]; 30 | } 31 | } 32 | 33 | // Returns true if the key exists. 34 | containsKey(key) { 35 | let idx = this._indexForKey(key); 36 | return idx > -1; 37 | } 38 | 39 | // Returns true if the value exists. 40 | containsValue(value) { 41 | let idx = this._indexForValue(value); 42 | return idx > -1; 43 | } 44 | 45 | // Removes the key and its value. 46 | remove(key) { 47 | let idx = this._indexForKey(key); 48 | if (idx > -1) { 49 | this.keys[idx] = undefined; 50 | this.values[idx] = undefined; 51 | } 52 | 53 | } 54 | 55 | // Clears all keys and values. 56 | clear() { 57 | this.keys = []; 58 | this.values = []; 59 | return this; 60 | } 61 | 62 | // Returns index of key, otherwise -1. 63 | _indexForKey(key) { 64 | for (let i in this.keys) { 65 | if (key === this.keys[i]) { 66 | return i; 67 | } 68 | } 69 | return -1; 70 | } 71 | 72 | _indexForValue(value) { 73 | for (let i in this.values) { 74 | if (value === this.values[i]) { 75 | return i; 76 | } 77 | } 78 | return -1; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/lib/support/index.js: -------------------------------------------------------------------------------- 1 | import Queue from './Queue'; 2 | import SimpleMap from './SimpleMap'; 3 | 4 | export {Queue, SimpleMap}; 5 | -------------------------------------------------------------------------------- /src/module.js: -------------------------------------------------------------------------------- 1 | import {moduleName} from './config'; 2 | 3 | import VertxEventBusWrapperProvider from './lib/VertxEventBusWrapperProvider'; 4 | import VertxEventBusServiceProvider from './lib/VertxEventBusServiceProvider'; 5 | 6 | /** 7 | * @ngdoc overview 8 | * @module knalli.angular-vertxbus 9 | * @name knalli.angular-vertxbus 10 | * @description 11 | * 12 | * Client side library using VertX Event Bus as an Angular Service module 13 | * 14 | * You have to define the module dependency, this module is named `knalli.angular-vertxbus`. 15 | * 16 | *
17 |  *   angular.module('app', ['knalli.angular-vertxbus'])
18 |  *     .controller('MyCtrl', function(vertxEventBus, vertxEventBusService) {
19 |  *
20 |  *       // using the EventBus directly
21 |  *       vertxEventBus.send('my.address', {data: 123}, function (reply) {
22 |  *         // your reply comes here
23 |  *       });
24 |  *
25 |  *       // using the service
26 |  *       vertxEventBusService.send('my.address', {data: 123}, {timeout: 500})
27 |  *         .then(function (reply) {
28 |  *           // your reply comes here
29 |  *         })
30 |  *         .catch(function (err) {
31 |  *           // something went wrong, no connection, no login, timed out, or so
32 |  *         });
33 |  *     });
34 |  * 
35 | * 36 | * The module itself provides following components: 37 | * - {@link knalli.angular-vertxbus.vertxEventBus vertxEventBus}: a low level wrapper around `vertx.EventBus` 38 | * - {@link knalli.angular-vertxbus.vertxEventBusService vertxEventBusService}: a high level service around the wrapper 39 | * 40 | * While the wrapper only provides one single instance (even on reconnects), the service supports automatically 41 | * reconnect management, authorization and a clean promise based api. 42 | * 43 | * If you are looking for a low integration of `vertxbus.EventBus` as an AngularJS component, the wrapper will be your 44 | * choice. The only difference (and requirement for the wrapper actually) is how it will manage and replace the 45 | * underlying instance of the current `vertx.EventBus`. 46 | * 47 | * However, if you are looking for a simple, clean and promised based high api, the service is much better you. 48 | */ 49 | export default angular 50 | 51 | .module(moduleName, ['ng']) 52 | 53 | .provider('vertxEventBus', VertxEventBusWrapperProvider) 54 | .provider('vertxEventBusService', VertxEventBusServiceProvider) 55 | 56 | .name; 57 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jasmine": true, 4 | "node": true 5 | }, 6 | "plugins": [ 7 | "angular" 8 | ], 9 | "globals": { 10 | "inject": false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/e2e/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | app.use(express.static(__dirname + '/web')); 5 | app.use(express.static(__dirname + '/../../')); 6 | 7 | let server = app.listen(3000, () => console.log(`Listening on port ${server.address().port}`)); 8 | -------------------------------------------------------------------------------- /test/e2e/vertx/app/vertx3-config.js: -------------------------------------------------------------------------------- 1 | var Router = require("vertx-web-js/router"); 2 | var SockJSHandler = require("vertx-web-js/sock_js_handler"); 3 | 4 | var router = Router.router(vertx); 5 | 6 | var options = { 7 | 'inboundPermitteds' : [ 8 | { 9 | 'address' : 'commands' 10 | } 11 | ], 12 | 'outboundPermitteds' : [ 13 | { 14 | 'address' : 'what-time-is-it' 15 | } 16 | ] 17 | }; 18 | 19 | // We need cookies, sessions and request bodies 20 | //router.route().handler(CookieHandler.create().handle); 21 | //router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)).handle); 22 | 23 | router.route("/eventbus/*").handler(SockJSHandler.create(vertx).bridge(options).handle); 24 | 25 | vertx.createHttpServer().requestHandler(router.accept).listen(8080); 26 | 27 | // de-knallisworld-mock 28 | 29 | vertx.eventBus().consumer('commands', function (message) { 30 | var headers = message.headers(); 31 | var body = message.body(); 32 | var token = headers.get('token'); 33 | console.log('Intercepted token: ' + token); 34 | if (token && token.substring(0, 6) === 'VALID-') { 35 | if (body.type === 'PING') { 36 | message.reply({ 37 | type : 'PONG' 38 | }); 39 | } else { 40 | message.reply({ 41 | type : 'NON-PING' 42 | }); 43 | } 44 | } else { 45 | message.reply({ 46 | type : 'NO_AUTH' 47 | }); 48 | } 49 | }); 50 | 51 | vertx.setPeriodic(1000, function (timerId) { 52 | vertx.eventBus().publish('what-time-is-it', { 53 | time : new Date().getTime() 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /test/e2e/vertx/install-vertx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ARCHIVE="vert.x-3.5.1-full.tar.gz" 3 | DIRECTORY="runtime" 4 | [ -e ${ARCHIVE} ] || wget https://bintray.com/artifact/download/vertx/downloads/${ARCHIVE} 5 | if [ ! -e ${DIRECTORY} ]; then 6 | mkdir ${DIRECTORY}; (cd ${DIRECTORY} && tar -zxf ../${ARCHIVE}) 7 | fi 8 | -------------------------------------------------------------------------------- /test/e2e/web/app.js: -------------------------------------------------------------------------------- 1 | /* global angular:false,console:false */ 2 | (function () { 3 | 'use strict'; 4 | 5 | angular.module('app', ['ng', 'knalli.angular-vertxbus']) 6 | .config(function(vertxEventBusProvider, vertxEventBusServiceProvider) { 7 | vertxEventBusProvider 8 | .useDebug(true) 9 | .useUrlServer('http://localhost:8080'); 10 | vertxEventBusServiceProvider 11 | .useDebug(true) 12 | .authHandler('myCustomAuthHandler'); 13 | }) 14 | .run(function ($rootScope, vertxEventBus, vertxEventBusService, $interval) { 15 | $rootScope.sessionIsValid = false; 16 | 17 | $rootScope.moduleStats = { 18 | wrapper: {}, 19 | service: {} 20 | }; 21 | $interval(function () { 22 | try { 23 | $rootScope.moduleStats.wrapper.readyState = vertxEventBus.readyState(); 24 | $rootScope.moduleStats.service.readyState = vertxEventBusService.readyState(); 25 | $rootScope.moduleStats.service.getConnectionState = vertxEventBusService.getConnectionState(); 26 | $rootScope.moduleStats.service.isEnabled = vertxEventBusService.isEnabled(); 27 | $rootScope.moduleStats.service.isConnected = vertxEventBusService.isConnected(); 28 | $rootScope.moduleStats.service.isAuthorized = vertxEventBusService.isAuthorized(); 29 | } catch (e) {} 30 | }, 1000); 31 | }) 32 | .filter('eventBusState', function () { 33 | var states = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; 34 | return function (value) { 35 | return states[value] || value; 36 | }; 37 | }) 38 | .service('myCustomAuthHandler', function (vertxEventBus, $q) { 39 | var states = { 40 | enabled: false 41 | }; 42 | var service = function () { 43 | console.log('authHandler invoked', states); 44 | return $q(function (resolve, reject) { 45 | if (states.enabled) { 46 | vertxEventBus.applyDefaultHeaders({ 47 | token: 'VALID-123' 48 | }); 49 | resolve(); 50 | } else { 51 | reject(); 52 | } 53 | }); 54 | }; 55 | service.start = function () { 56 | states.enabled = true; 57 | }; 58 | service.stop = function () { 59 | states.enabled = false; 60 | vertxEventBus.applyDefaultHeaders({}); 61 | }; 62 | return service; 63 | }) 64 | .controller('MyController', function($scope, vertxEventBus, vertxEventBusService, myCustomAuthHandler) { 65 | var me = this; 66 | var holder = {}; 67 | me.timeServiceActive = false; 68 | me.registerTimeService = function () { 69 | holder.timeServiceDeconstructor = vertxEventBusService.on('what-time-is-it', function (data) { 70 | me.currentDateTime = new Date(data.time); 71 | }); 72 | me.timeServiceActive = true; 73 | }; 74 | me.deregisterTimeService = function () { 75 | holder.timeServiceDeconstructor(); 76 | holder.timeServiceDeconstructor = undefined; 77 | me.timeServiceActive = false; 78 | }; 79 | me.deregisterTimeService2x = function () { 80 | holder.timeServiceDeconstructor(); 81 | holder.timeServiceDeconstructor(); 82 | holder.timeServiceDeconstructor = undefined; 83 | me.timeServiceActive = false; 84 | }; 85 | 86 | me.timeServiceActive = false; 87 | me.registerTimeService = function () { 88 | holder.timeServiceDeconstructor = vertxEventBusService.on('what-time-is-it', function (data) { 89 | me.currentDateTime = new Date(data.time); 90 | }); 91 | me.timeServiceActive = true; 92 | }; 93 | me.deregisterTimeService = function () { 94 | holder.timeServiceDeconstructor(); 95 | holder.timeServiceDeconstructor = undefined; 96 | me.timeServiceActive = false; 97 | }; 98 | me.refreshDefaultHeaders = function(token) { 99 | vertxEventBus.applyDefaultHeaders({ 100 | token: token 101 | }); 102 | }; 103 | var sendCommand = function (type) { 104 | vertxEventBusService.send('commands', {type: type}) 105 | .then(function (message) { 106 | console.log('Command succeeded: ' + message.body.type) 107 | }, function () { 108 | console.log('Command failed') 109 | }); 110 | }; 111 | me.sendPing = function () { 112 | sendCommand('PING'); 113 | }; 114 | me.sendNonPing = function () { 115 | sendCommand('INVALID'); 116 | }; 117 | me.enableAuthHandler = function () { 118 | myCustomAuthHandler.start(); 119 | }; 120 | me.disableAuthHandler = function () { 121 | myCustomAuthHandler.stop(); 122 | }; 123 | }); 124 | }()); 125 | -------------------------------------------------------------------------------- /test/e2e/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | knalli.angular-vertxbus 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 |
15 | Custom headers: 16 | 17 |
The commands will be only successful if header named token and a valid value exist.
18 |
19 | Auth Handler: 20 | 21 | 22 |
If enabled, the authHandler will set such a token automatically on-the-fly.
23 |
24 | 25 | 26 |
27 |
28 | 29 |
30 | Statistics 31 |
32 |
vertxEventBus.readyState()
33 |
{{moduleStats.wrapper.readyState | eventBusState}}
34 |
vertxEventBusService.readyState()
35 |
{{moduleStats.service.readyState | eventBusState}}
36 |
vertxEventBusService.getConnectionState()
37 |
{{moduleStats.service.getConnectionState | eventBusState}}
38 |
vertxEventBusService.isEnabled()
39 |
{{moduleStats.service.isEnabled}}
40 |
vertxEventBusService.isConnected()
41 |
{{moduleStats.service.isConnected}}
42 |
vertxEventBusService.isAuthorized()
43 |
{{moduleStats.service.isAuthorized}}
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /test/index_all.js: -------------------------------------------------------------------------------- 1 | // require all modules ending in "_test" from the 2 | // current directory and all subdirectories 3 | var testsContext = require.context('.', true, /_spec\.js$/); 4 | testsContext.keys().forEach(testsContext); 5 | -------------------------------------------------------------------------------- /test/unit/binding/vertxEventBus.defaultHeaders.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint camelcase: false, undef: true, unused: true, browser: true */ 2 | /* global module: false, describe: false, it: false, expect: false, beforeEach: false, inject: false, SockJS: false */ 3 | 4 | const SockJS = require('sockjs-client'); 5 | const enableUnhandledRejectionTracing = require('../util/unhandledRejectionTracing.js'); 6 | require('../../../src/module.js'); 7 | 8 | describe('integration of module::vertxEventBus (defaultHeaders)', function () { 9 | 10 | beforeEach(angular.mock.module('knalli.angular-vertxbus')); 11 | 12 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function ($provide) { 13 | enableUnhandledRejectionTracing(angular, $provide); 14 | $provide.value('$log', { 15 | log : function () { 16 | }, 17 | debug : function () { 18 | }, 19 | info : function () { 20 | }, 21 | warn : function () { 22 | }, 23 | error : function () { 24 | } 25 | }); 26 | })); 27 | 28 | describe('without any defaultHeaders', function () { 29 | 30 | var vertxEventBus, $timeout, $rootScope, $log; 31 | 32 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function ($provide, vertxEventBusProvider) { 33 | // Override (improve test running time) 34 | vertxEventBusProvider.useDebug(true).useSockJsReconnectInterval(2000); 35 | })); 36 | 37 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _$timeout_, _$rootScope_, _$log_) { 38 | vertxEventBus = _vertxEventBus_; 39 | $timeout = _$timeout_; 40 | $rootScope = _$rootScope_; 41 | $log = _$log_; 42 | SockJS.currentMockInstance.$log = $log; 43 | 44 | // Mock bus is opened (said to be) 45 | _vertxEventBus_.readyState = function () { 46 | return _vertxEventBus_.EventBus.OPEN; 47 | }; 48 | })); 49 | 50 | describe('and no specific headers should be called with effective empty headers', function () { 51 | describe('on registerHandler()', function () { 52 | it('and implicit headers', function (done) { 53 | this.timeout(1000); 54 | const context = {}; 55 | vertxEventBus.instance.registerHandler = function (address, headers) { 56 | context.headers = headers; 57 | }; 58 | setTimeout(function () { 59 | vertxEventBus.registerHandler('address', function () { 60 | }); 61 | setTimeout(function () { 62 | expect(context.headers).to.eql({}); 63 | done(); 64 | }, 200); 65 | }, 200); 66 | }); 67 | it('and explicit headers (undefined)', function (done) { 68 | this.timeout(1000); 69 | const context = {}; 70 | vertxEventBus.instance.registerHandler = function (address, headers) { 71 | context.headers = headers; 72 | }; 73 | setTimeout(function () { 74 | vertxEventBus.registerHandler('address', undefined, function () { 75 | }); 76 | setTimeout(function () { 77 | expect(context.headers).to.eql({}); 78 | done(); 79 | }, 200); 80 | }, 200); 81 | }); 82 | it('and explicit headers (defined)', function (done) { 83 | this.timeout(1000); 84 | const context = {}; 85 | vertxEventBus.instance.registerHandler = function (address, headers) { 86 | context.headers = headers; 87 | }; 88 | setTimeout(function () { 89 | vertxEventBus.registerHandler('address', {}, function () { 90 | }); 91 | setTimeout(function () { 92 | expect(context.headers).to.eql({}); 93 | done(); 94 | }, 200); 95 | }, 200); 96 | }); 97 | }); 98 | it('on send()', function (done) { 99 | this.timeout(1000); 100 | const context = {}; 101 | vertxEventBus.instance.send = function (address, message, headers) { 102 | context.headers = headers; 103 | }; 104 | setTimeout(function () { 105 | vertxEventBus.send('address', {data : 1}); 106 | setTimeout(function () { 107 | expect(context.headers).to.eql({}); 108 | done(); 109 | }, 200); 110 | }, 200); 111 | }); 112 | it('on publish()', function (done) { 113 | this.timeout(1000); 114 | const context = {}; 115 | vertxEventBus.instance.publish = function (address, message, headers) { 116 | context.headers = headers; 117 | }; 118 | setTimeout(function () { 119 | vertxEventBus.publish('address', {data : 1}); 120 | setTimeout(function () { 121 | expect(context.headers).to.eql({}); 122 | done(); 123 | }, 200); 124 | }, 200); 125 | }); 126 | }); 127 | 128 | describe('and specified headers should be called with effective headers', function () { 129 | describe('on registerHandler()', function () { 130 | it('and explicit headers', function (done) { 131 | this.timeout(1000); 132 | const context = {}; 133 | vertxEventBus.instance.registerHandler = function (address, headers) { 134 | context.headers = headers; 135 | }; 136 | setTimeout(function () { 137 | vertxEventBus.registerHandler('address', {x : 1}, function () { 138 | }); 139 | setTimeout(function () { 140 | expect(context.headers).to.eql({x : 1}); 141 | done(); 142 | }, 200); 143 | }, 200); 144 | }); 145 | }); 146 | it('on send()', function (done) { 147 | this.timeout(1000); 148 | const context = {}; 149 | vertxEventBus.instance.send = function (address, message, headers) { 150 | context.headers = headers; 151 | }; 152 | setTimeout(function () { 153 | vertxEventBus.send('address', {data : 1}, {x : 1}); 154 | setTimeout(function () { 155 | expect(context.headers).to.eql({x : 1}); 156 | done(); 157 | }, 200); 158 | }, 200); 159 | }); 160 | it('on publish()', function (done) { 161 | this.timeout(1000); 162 | const context = {}; 163 | vertxEventBus.instance.publish = function (address, message, headers) { 164 | context.headers = headers; 165 | }; 166 | setTimeout(function () { 167 | vertxEventBus.publish('address', {data : 1}, {x : 1}); 168 | setTimeout(function () { 169 | expect(context.headers).to.eql({x : 1}); 170 | done(); 171 | }, 200); 172 | }, 200); 173 | }); 174 | }); 175 | 176 | }); 177 | 178 | describe('with defaultHeaders', function () { 179 | 180 | var vertxEventBus, $timeout, $rootScope, $log; 181 | 182 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function ($provide, vertxEventBusProvider) { 183 | enableUnhandledRejectionTracing(angular, $provide); 184 | // Override (improve test running time) 185 | vertxEventBusProvider.useDebug(true).useSockJsReconnectInterval(2000); 186 | })); 187 | 188 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _$timeout_, _$rootScope_, _$log_) { 189 | vertxEventBus = _vertxEventBus_; 190 | $timeout = _$timeout_; 191 | $rootScope = _$rootScope_; 192 | $log = _$log_; 193 | SockJS.currentMockInstance.$log = $log; 194 | 195 | // Mock bus is opened (said to be) 196 | vertxEventBus.readyState = function () { 197 | return vertxEventBus.EventBus.OPEN; 198 | }; 199 | vertxEventBus.applyDefaultHeaders({ 200 | x : 1, 201 | y : 2 202 | }); 203 | })); 204 | 205 | describe('and no specific headers should be called with headers', function () { 206 | describe('on registerHandler()', function () { 207 | it('and implicit headers', function (done) { 208 | this.timeout(1000); 209 | const context = {}; 210 | vertxEventBus.instance.registerHandler = function (address, headers) { 211 | context.headers = headers; 212 | }; 213 | setTimeout(function () { 214 | vertxEventBus.registerHandler('address', function () { 215 | }); 216 | setTimeout(function () { 217 | expect(context.headers).to.eql({x : 1, y : 2}); 218 | done(); 219 | }, 200); 220 | }, 200); 221 | }); 222 | it('and explicit headers (undefined)', function (done) { 223 | this.timeout(1000); 224 | const context = {}; 225 | vertxEventBus.instance.registerHandler = function (address, headers) { 226 | context.headers = headers; 227 | }; 228 | setTimeout(function () { 229 | vertxEventBus.registerHandler('address', undefined, function () { 230 | }); 231 | setTimeout(function () { 232 | expect(context.headers).to.eql({x : 1, y : 2}); 233 | done(); 234 | }, 200); 235 | }, 200); 236 | }); 237 | it('and explicit headers (defined)', function (done) { 238 | this.timeout(1000); 239 | const context = {}; 240 | vertxEventBus.instance.registerHandler = function (address, headers) { 241 | context.headers = headers; 242 | }; 243 | setTimeout(function () { 244 | vertxEventBus.registerHandler('address', {}, function () { 245 | }); 246 | setTimeout(function () { 247 | expect(context.headers).to.eql({x : 1, y : 2}); 248 | done(); 249 | }, 200); 250 | }, 200); 251 | }); 252 | }); 253 | it('on send()', function (done) { 254 | this.timeout(1000); 255 | const context = {}; 256 | vertxEventBus.instance.send = function (address, message, headers) { 257 | context.headers = headers; 258 | }; 259 | setTimeout(function () { 260 | vertxEventBus.send('address', {data : 1}); 261 | setTimeout(function () { 262 | expect(context.headers).to.eql({x : 1, y : 2}); 263 | done(); 264 | }, 200); 265 | }, 200); 266 | }); 267 | it('on publish()', function (done) { 268 | this.timeout(1000); 269 | const context = {}; 270 | vertxEventBus.instance.publish = function (address, message, headers) { 271 | context.headers = headers; 272 | }; 273 | setTimeout(function () { 274 | vertxEventBus.publish('address', {data : 1}); 275 | setTimeout(function () { 276 | expect(context.headers).to.eql({x : 1, y : 2}); 277 | done(); 278 | }, 200); 279 | }, 200); 280 | }); 281 | }); 282 | 283 | describe('and specified headers should be called with effective headers', function () { 284 | describe('on registerHandler()', function () { 285 | it('and explicit headers', function (done) { 286 | this.timeout(1000); 287 | const context = {}; 288 | vertxEventBus.instance.registerHandler = function (address, headers) { 289 | context.headers = headers; 290 | }; 291 | setTimeout(function () { 292 | vertxEventBus.registerHandler('address', {x : 3}, function () { 293 | }); 294 | setTimeout(function () { 295 | expect(context.headers).to.eql({x : 3, y : 2}); 296 | done(); 297 | }, 200); 298 | }, 200); 299 | }); 300 | }); 301 | it('on send()', function (done) { 302 | this.timeout(1000); 303 | const context = {}; 304 | vertxEventBus.instance.send = function (address, message, headers) { 305 | context.headers = headers; 306 | }; 307 | setTimeout(function () { 308 | vertxEventBus.send('address', {data : 1}, {x : 3}); 309 | setTimeout(function () { 310 | expect(context.headers).to.eql({x : 3, y : 2}); 311 | done(); 312 | }, 200); 313 | }, 200); 314 | }); 315 | it('on publish()', function (done) { 316 | this.timeout(1000); 317 | const context = {}; 318 | vertxEventBus.instance.publish = function (address, message, headers) { 319 | context.headers = headers; 320 | }; 321 | setTimeout(function () { 322 | vertxEventBus.publish('address', {data : 1}, {x : 3}); 323 | setTimeout(function () { 324 | expect(context.headers).to.eql({x : 3, y : 2}); 325 | done(); 326 | }, 200); 327 | }, 200); 328 | }); 329 | }); 330 | 331 | }); 332 | 333 | }); 334 | -------------------------------------------------------------------------------- /test/unit/binding/vertxEventBus.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint camelcase: false, undef: true, unused: true, browser: true */ 2 | /* global module: false, describe: false, it: false, expect: false, beforeEach: false, inject: false, SockJS: false */ 3 | 4 | const SockJS = require('sockjs-client'); 5 | const enableUnhandledRejectionTracing = require('../util/unhandledRejectionTracing.js'); 6 | require('../../../src/module.js'); 7 | 8 | describe('integration of module::vertxEventBus', function () { 9 | 10 | beforeEach(angular.mock.module('knalli.angular-vertxbus')); 11 | 12 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function ($provide) { 13 | enableUnhandledRejectionTracing(angular, $provide); 14 | $provide.value('$log', { 15 | log: function () {}, 16 | debug: function () {}, 17 | info: function () {}, 18 | warn: function () {}, 19 | error: function () {} 20 | }); 21 | })); 22 | 23 | it('should have vertxEventBus', angular.mock.inject(function (vertxEventBus) { 24 | expect(vertxEventBus).not.to.be(undefined); 25 | })); 26 | 27 | describe('vertxEventBus (w/ reconnect)', function () { 28 | 29 | var vertxEventBus, $timeout, $rootScope, $log; 30 | 31 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusProvider) { 32 | // Override (improve test running time) 33 | vertxEventBusProvider.useDebug(true).useSockJsReconnectInterval(2000); 34 | })); 35 | 36 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _$timeout_, _$rootScope_, _$log_) { 37 | vertxEventBus = _vertxEventBus_; 38 | $timeout = _$timeout_; 39 | $rootScope = _$rootScope_; 40 | $log = _$log_; 41 | SockJS.currentMockInstance.$log = $log; 42 | })); 43 | 44 | it('should be an object', function () { 45 | expect(typeof vertxEventBus).to.be('object'); 46 | }); 47 | 48 | it('should have a method close()', function () { 49 | expect(vertxEventBus.close).not.to.be(undefined); 50 | }); 51 | 52 | describe('constructor()', function () { 53 | // Delegating onopen transparently 54 | it('should call the onopen function', function (done) { 55 | var ok = false; 56 | vertxEventBus.onopen = function () { 57 | ok = true; 58 | }; 59 | setTimeout(function () { 60 | setTimeout(function () { 61 | expect(ok).to.be(true); 62 | done(); 63 | }, 1000); 64 | }, 200); 65 | }); 66 | }); 67 | 68 | describe('close()', function () { 69 | it('should be a function', function () { 70 | expect(typeof vertxEventBus.close).to.be('function'); 71 | }); 72 | // Delegating onclose transparently 73 | it('should call the onclose function', function (done) { 74 | var ok = false; 75 | vertxEventBus.onclose = function () { 76 | ok = true; 77 | }; 78 | setTimeout(function () { 79 | vertxEventBus.close(); 80 | setTimeout(function () { 81 | expect(ok).to.be(true); 82 | done(); 83 | }, 1000); 84 | }, 200); 85 | }); 86 | }); 87 | 88 | describe('reconnect()', function () { 89 | it('should be a function', function () { 90 | expect(typeof vertxEventBus.reconnect).to.be('function'); 91 | }); 92 | // Reconnect should be switch the connectivity, onopen() and onclose() 93 | // must be delegated transparently 94 | it('should call onclose and onopen functions', function (done) { 95 | this.timeout(20000); 96 | var okClose = false, okOpen = false; 97 | setTimeout(function () { 98 | vertxEventBus.onclose = function () { 99 | $log.debug('[TEST] onclose() called'); 100 | okClose = true; 101 | }; 102 | vertxEventBus.onopen = function () { 103 | $log.debug('[TEST] onopen() called'); 104 | okOpen = true; 105 | }; 106 | vertxEventBus.reconnect(); 107 | setTimeout(function () { 108 | expect(okClose).to.be(true); 109 | // Reconnect should be still false.. 110 | expect(okOpen).to.be(false); 111 | setTimeout(function () { 112 | expect(okOpen).to.be(true); 113 | done(); 114 | }, 2100); 115 | $timeout.flush(); 116 | }, 100); 117 | }, 100); 118 | }); 119 | }); 120 | 121 | describe('reconnect(true)', function () { 122 | it('should call the onclose and onopen function if previously connected', function (done) { 123 | this.timeout(20000); 124 | var onopenCount = 0; 125 | vertxEventBus.onopen = function () { 126 | onopenCount++; 127 | }; 128 | var oncloseCount = 0; 129 | vertxEventBus.onclose = function () { 130 | oncloseCount++; 131 | }; 132 | setTimeout(function () { 133 | expect(onopenCount, 'onopenCount').to.be(1); 134 | vertxEventBus.reconnect(true); 135 | setTimeout(function () { 136 | expect(oncloseCount).to.be(1); 137 | expect(onopenCount).to.be(2); 138 | done(); 139 | }, 1200); 140 | }, 200); 141 | }); 142 | }); 143 | 144 | describe('after adding a handler via "registerHandler"', function () { 145 | it('should be called', function (done) { 146 | var abcCalled, xyzCalled; 147 | setTimeout(function () { 148 | var abcHandler = function (err, message) { 149 | abcCalled = message.message.data; 150 | }, xyzHandler = function (err, message) { 151 | xyzCalled = message.message.data; 152 | }; 153 | vertxEventBus.registerHandler('abc', abcHandler); 154 | vertxEventBus.registerHandler('xyz', xyzHandler); 155 | SockJS.currentMockInstance.onmessage({ 156 | data : JSON.stringify({ 157 | address : 'xyz', 158 | message : { 159 | data : '1x' 160 | }, 161 | replyAddress : undefined 162 | }) 163 | }); 164 | expect(abcCalled).to.be(undefined); 165 | expect(xyzCalled).to.be('1x'); 166 | done(); 167 | }, 200); 168 | }); 169 | it('should be called as error', function (done) { 170 | var abcCalled, xyzCalled; 171 | setTimeout(function () { 172 | var abcHandler = function (err, message) { 173 | abcCalled = message.message.data; 174 | }, xyzHandler = function (err) { 175 | xyzCalled = err.message.data; 176 | }; 177 | vertxEventBus.registerHandler('abc', abcHandler); 178 | vertxEventBus.registerHandler('xyz', xyzHandler); 179 | SockJS.currentMockInstance.onmessage({ 180 | data : JSON.stringify({ 181 | address : 'xyz', 182 | type: 'err', 183 | failureCode: 4711, 184 | failureType: 'whatever', 185 | message : { 186 | data : '1x' 187 | } 188 | }) 189 | }); 190 | expect(abcCalled).to.be(undefined); 191 | expect(xyzCalled).to.be('1x'); 192 | done(); 193 | }, 200); 194 | }); 195 | }); 196 | 197 | describe('after adding and removing a handler via "registerHandler"', function () { 198 | it('should be not called', function (done) { 199 | var abcCalled, xyzCalled; 200 | setTimeout(function () { 201 | var abcHandler = function (err, message) { 202 | abcCalled = message.data; 203 | }, xyzHandler = function (err, message) { 204 | xyzCalled = message.data; 205 | }; 206 | var abcFunct = vertxEventBus.registerHandler('abc', abcHandler); 207 | var xyzFunct = vertxEventBus.registerHandler('xyz', xyzHandler); 208 | abcFunct(); 209 | xyzFunct(); 210 | SockJS.currentMockInstance.onmessage({ 211 | data : JSON.stringify({ 212 | address : 'xyz', 213 | message : { 214 | data : '1x' 215 | }, 216 | replyAddress : undefined 217 | }) 218 | }); 219 | expect(abcCalled).to.be(undefined); 220 | expect(xyzCalled).to.be(undefined); 221 | done(); 222 | }, 200); 223 | }); 224 | }); 225 | 226 | describe('after removing a registered handler via "unregisterHandler"', function () { 227 | it('should not be called', function (done) { 228 | var abcCalled, xyzCalled; 229 | setTimeout(function () { 230 | var abcHandler = function (err, message) { 231 | abcCalled = message.data; 232 | }, xyzHandler = function (err, message) { 233 | xyzCalled = message.data; 234 | }; 235 | vertxEventBus.registerHandler('abc', abcHandler); 236 | vertxEventBus.registerHandler('xyz', xyzHandler); 237 | // remove again! 238 | vertxEventBus.unregisterHandler('abc', abcHandler); 239 | vertxEventBus.unregisterHandler('xyz', xyzHandler); 240 | SockJS.currentMockInstance.onmessage({ 241 | data : JSON.stringify({ 242 | address : 'xyz', 243 | message : { 244 | data : '1x' 245 | }, 246 | replyAddress : undefined 247 | }) 248 | }); 249 | expect(abcCalled).to.be(undefined); 250 | expect(xyzCalled).to.be(undefined); 251 | done(); 252 | }, 200); 253 | }); 254 | }); 255 | 256 | }); 257 | 258 | describe('vertxEventBus (w/o reconnect)', function () { 259 | 260 | var vertxEventBus, $timeout, $rootScope, $log; 261 | 262 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusProvider) { 263 | // Override (improve test running time) 264 | vertxEventBusProvider.useDebug(true).useSockJsReconnectInterval(2000).useReconnect(false); 265 | })); 266 | 267 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _$timeout_, _$rootScope_, _$log_) { 268 | vertxEventBus = _vertxEventBus_; 269 | $timeout = _$timeout_; 270 | $rootScope = _$rootScope_; 271 | $log = _$log_; 272 | SockJS.currentMockInstance.$log = $log; 273 | })); 274 | 275 | it('should call the onopen function if not previously connected', function (done) { 276 | this.timeout(20000); 277 | var onopenCount = 0; 278 | vertxEventBus.onopen = function () { 279 | $log.debug('onopen'); 280 | onopenCount++; 281 | }; 282 | var oncloseCount = 0; 283 | vertxEventBus.onclose = function () { 284 | $log.debug('onclose'); 285 | oncloseCount++; 286 | }; 287 | setTimeout(function () { 288 | expect(onopenCount).to.be(1); 289 | $log.debug('reconnecting..'); 290 | vertxEventBus.close(); 291 | vertxEventBus.reconnect(true); 292 | setTimeout(function () { 293 | $log.debug('check..'); 294 | expect(oncloseCount).to.be(1); 295 | expect(onopenCount).to.be(2); 296 | done(); 297 | }, 1200); 298 | }, 200); 299 | }); 300 | 301 | }); 302 | 303 | describe('vertxEventBus (w/o autoconnect)', function () { 304 | 305 | var vertxEventBus, $timeout, $rootScope, $log; 306 | 307 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusProvider) { 308 | // Override (improve test running time) 309 | vertxEventBusProvider 310 | .useDebug(true) 311 | .useSockJsReconnectInterval(2000) 312 | .useReconnect(false) 313 | .disableAutoConnect(); 314 | })); 315 | 316 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _$timeout_, _$rootScope_, _$log_) { 317 | vertxEventBus = _vertxEventBus_; 318 | $timeout = _$timeout_; 319 | $rootScope = _$rootScope_; 320 | $log = _$log_; 321 | SockJS.currentMockInstance.$log = $log; 322 | })); 323 | 324 | it('should not fail calling close() on non existing connection', function (done) { 325 | this.timeout(20000); 326 | setTimeout(function () { 327 | vertxEventBus.close(); 328 | setTimeout(done, 1200); 329 | }, 200); 330 | }); 331 | 332 | it('should not fail calling reconnect() on non existing connection', function (done) { 333 | this.timeout(20000); 334 | setTimeout(function () { 335 | vertxEventBus.reconnect(true); 336 | setTimeout(done, 1200); 337 | }, 200); 338 | }); 339 | 340 | it('should not call the onopen function because no automatic connect', function (done) { 341 | this.timeout(20000); 342 | var onopenCount = 0; 343 | vertxEventBus.onopen = function () { 344 | $log.debug('onopen'); 345 | onopenCount++; 346 | }; 347 | var oncloseCount = 0; 348 | vertxEventBus.onclose = function () { 349 | $log.debug('onclose'); 350 | oncloseCount++; 351 | }; 352 | setTimeout(function () { 353 | expect(onopenCount).to.be(0); // should be not called! 354 | setTimeout(done, 1200); 355 | }, 200); 356 | }); 357 | 358 | it('should not call the onopen function because no automatic connect', function (done) { 359 | this.timeout(20000); 360 | var onopenCount = 0; 361 | vertxEventBus.onopen = function () { 362 | $log.debug('onopen'); 363 | onopenCount++; 364 | }; 365 | var oncloseCount = 0; 366 | vertxEventBus.onclose = function () { 367 | $log.debug('onclose'); 368 | oncloseCount++; 369 | }; 370 | setTimeout(function () { 371 | expect(onopenCount).to.be(0); // should be not called! 372 | $log.debug('apply connection config..'); 373 | vertxEventBus.configureConnection('http://localhost:1234', '/eventbus1'); 374 | var connectPromise = vertxEventBus.connect(); 375 | expect(connectPromise).not.to.be(undefined); 376 | var connectPromiseResult = false; 377 | connectPromise.then(() => { 378 | connectPromiseResult = true 379 | }); 380 | setTimeout(function () { 381 | $rootScope.$digest(); // for $q 382 | $log.debug('check..'); 383 | expect(SockJS.currentMockInstance.url).to.be('http://localhost:1234/eventbus1'); 384 | expect(onopenCount).to.be(1); 385 | expect(oncloseCount).to.be(0); 386 | expect(connectPromiseResult ).to.be(true); 387 | done(); 388 | }, 1200); 389 | }, 200); 390 | }); 391 | 392 | }); 393 | 394 | }); 395 | -------------------------------------------------------------------------------- /test/unit/binding/vertxEventBusService.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint camelcase: false, undef: true, unused: true, browser: true */ 2 | /* global module: false, describe: false, it: false, expect: false, beforeEach: false, inject: false, SockJS: false */ 3 | 4 | const SockJS = require('sockjs-client'); 5 | const enableUnhandledRejectionTracing = require('../util/unhandledRejectionTracing.js'); 6 | require('../../../src/module.js'); 7 | 8 | describe('integration of module::vertxEventBusService', function () { 9 | 10 | beforeEach(angular.mock.module('knalli.angular-vertxbus')); 11 | 12 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function ($provide) { 13 | enableUnhandledRejectionTracing(angular, $provide); 14 | $provide.value('$log', { 15 | log: function () {}, 16 | debug: function () {}, 17 | info: function () {}, 18 | warn: function () {}, 19 | error: function () {} 20 | }); 21 | })); 22 | 23 | it('should have vertxEventBusService', angular.mock.inject(function (vertxEventBusService) { 24 | expect(vertxEventBusService).not.to.be(undefined); 25 | })); 26 | 27 | describe('vertxEventBusService', function () { 28 | 29 | var vertxEventBusService; 30 | 31 | beforeEach(angular.mock.inject(function (_vertxEventBusService_) { 32 | vertxEventBusService = _vertxEventBusService_; 33 | })); 34 | 35 | it('should be an object', function () { 36 | expect(typeof vertxEventBusService).to.be('object'); 37 | }); 38 | 39 | it('should have a method readyState()', function () { 40 | expect(vertxEventBusService.readyState).not.to.be(undefined); 41 | }); 42 | 43 | describe('readyState()', function () { 44 | it('should be a function', function () { 45 | expect(typeof vertxEventBusService.readyState).to.be('function'); 46 | }); 47 | }); 48 | 49 | describe('adding two handlers with the same address, different callbacks.', function () { 50 | it('both handlers should be called - with same address', function (done) { 51 | var abcCalled, abcCalled2; 52 | setTimeout(function () { 53 | var abcHandler = function (message) { 54 | abcCalled = message; 55 | }, abcHandler2 = function (message) { 56 | // use a copy of the data so that we don't change 57 | // the message sent to other callbacks. 58 | var copy = angular.copy(message); 59 | copy = copy + "-2"; 60 | abcCalled2 = copy; 61 | }; 62 | vertxEventBusService.addListener('abc', abcHandler); 63 | vertxEventBusService.addListener('abc', abcHandler2); 64 | // remove again! 65 | SockJS.currentMockInstance.onmessage({ 66 | data : JSON.stringify({ 67 | address : 'abc', 68 | body : '1x', 69 | replyAddress : undefined 70 | }) 71 | }); 72 | expect(abcCalled).to.be('1x'); 73 | expect(abcCalled2).to.be('1x-2'); 74 | // remove handlers 75 | vertxEventBusService.removeListener('abc', abcHandler); 76 | vertxEventBusService.removeListener('abc', abcHandler2); 77 | done(); 78 | }, 200); 79 | }); 80 | }); 81 | 82 | describe('adding two handlers with the same callback, different addresses.', function () { 83 | it('handler should be called twice - with two different values - two different addresses', function (done) { 84 | var singleCallbackValue; 85 | 86 | function FunctionHolder() { 87 | "use strict"; 88 | return { 89 | handler : function (message) { 90 | singleCallbackValue = message; 91 | } 92 | }; 93 | } 94 | 95 | setTimeout(function () { 96 | var funcOne = new FunctionHolder(); 97 | var funcTwo = new FunctionHolder(); 98 | vertxEventBusService.addListener('abc', funcOne.handler); 99 | vertxEventBusService.addListener('xyz', funcTwo.handler); 100 | SockJS.currentMockInstance.onmessage({ 101 | data : JSON.stringify({ 102 | address : 'abc', 103 | body : 'abc', 104 | replyAddress : undefined 105 | }) 106 | }); 107 | expect(singleCallbackValue).to.be('abc'); 108 | SockJS.currentMockInstance.onmessage({ 109 | data : JSON.stringify({ 110 | address : 'xyz', 111 | body : 'xyz', 112 | replyAddress : undefined 113 | }) 114 | }); 115 | expect(singleCallbackValue).to.be('xyz'); 116 | // remove handlers 117 | vertxEventBusService.removeListener('abc', funcOne.handler); 118 | vertxEventBusService.removeListener('xyz', funcTwo.handler); 119 | done(); 120 | }, 200); 121 | }); 122 | }); 123 | }); 124 | 125 | describe('vertxEventBusService', function () { 126 | 127 | describe('with disabled message queue (default)', function () { 128 | var vertxEventBus, vertxEventBusService, result; 129 | 130 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 131 | vertxEventBusServiceProvider.useMessageBuffer(0); 132 | })); 133 | 134 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _vertxEventBusService_) { 135 | vertxEventBus = _vertxEventBus_; 136 | vertxEventBusService = _vertxEventBusService_; 137 | // Mock bus is closed 138 | _vertxEventBus_.readyState = function () { 139 | return _vertxEventBus_.EventBus.CLOSED; 140 | }; 141 | var sendCalls = 0; 142 | _vertxEventBus_.send = function (address, message, headers, replyHandler) { 143 | ++sendCalls; 144 | result = { 145 | reply : message 146 | }; 147 | if (replyHandler) { 148 | replyHandler(result); 149 | } 150 | }; 151 | // extend object 152 | vertxEventBus.getSendCalls = function () { 153 | return sendCalls; 154 | }; 155 | })); 156 | 157 | describe('should not dispatch send', function () { 158 | it('when eventbus is closed', function (done) { 159 | setTimeout(function () { 160 | vertxEventBusService.send('xyz', {data : 1}); 161 | setTimeout(function () { 162 | expect(result).to.be(undefined); 163 | expect(vertxEventBusService.delegate.getMessageQueueLength()).to.be(0); 164 | expect(vertxEventBus.getSendCalls()).to.be(0); 165 | done(); 166 | }, 1000); 167 | }, 200); 168 | }); 169 | }); 170 | }); 171 | 172 | describe('with enabled message queue (size 3)', function () { 173 | var vertxEventBus, vertxEventBusService, result; 174 | 175 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 176 | vertxEventBusServiceProvider.useMessageBuffer(3); 177 | })); 178 | 179 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _vertxEventBusService_) { 180 | vertxEventBus = _vertxEventBus_; 181 | vertxEventBusService = _vertxEventBusService_; 182 | // Mock bus is closed 183 | vertxEventBus.readyState = function () { 184 | return vertxEventBus.EventBus.CLOSED; 185 | }; 186 | var sendCalls = 0; 187 | vertxEventBus.send = function (address, message, headers, replyHandler) { 188 | ++sendCalls; 189 | result = { 190 | reply : message 191 | }; 192 | if (replyHandler) { 193 | replyHandler(result); 194 | } 195 | }; 196 | // extend object 197 | vertxEventBus.getSendCalls = function () { 198 | return sendCalls; 199 | }; 200 | })); 201 | 202 | describe('when eventbus is closed', function () { 203 | it('should dispatch send as queued', function (done) { 204 | setTimeout(function () { 205 | vertxEventBusService.send('xyz', {data : 123}); 206 | setTimeout(function () { 207 | expect(result).to.be(undefined); 208 | expect(vertxEventBusService.delegate.getMessageQueueLength()).to.be(1); 209 | expect(vertxEventBus.getSendCalls()).to.be(0); 210 | done(); 211 | }, 1000); 212 | }, 200); 213 | }); 214 | 215 | it('should queue max 3 items', function (done) { 216 | setTimeout(function () { 217 | vertxEventBusService.send('xyz', {data : 1}); 218 | vertxEventBusService.send('xyz', {data : 2}); 219 | vertxEventBusService.send('xyz', {data : 3}); 220 | vertxEventBusService.send('xyz', {data : 4}); 221 | setTimeout(function () { 222 | expect(result).to.be(undefined); 223 | expect(vertxEventBusService.delegate.getMessageQueueLength()).to.be(3); 224 | expect(vertxEventBus.getSendCalls()).to.be(0); 225 | done(); 226 | }, 1000); 227 | }, 200); 228 | }); 229 | }); 230 | 231 | describe('should replay queued items', function () { 232 | it('when eventbus is reopened', function (done) { 233 | setTimeout(function () { 234 | vertxEventBusService.send('xyz', {data : 0}).then(null, angular.noop); 235 | vertxEventBusService.send('xyz', {data : 1}).then(null, angular.noop); 236 | vertxEventBusService.send('xyz', {data : 2}).then(null, angular.noop); 237 | vertxEventBusService.send('xyz', {data : 3}).then(null, angular.noop); 238 | 239 | // fake connect 240 | vertxEventBus.readyState = function () { 241 | return vertxEventBus.EventBus.OPEN; 242 | }; 243 | vertxEventBus.onopen(); 244 | 245 | setTimeout(function () { 246 | expect(result).to.eql({reply : {data : 3}}); 247 | expect(vertxEventBusService.delegate.getMessageQueueLength()).to.be(0); 248 | expect(vertxEventBus.getSendCalls()).to.be(3); 249 | done(); 250 | }, 1000); 251 | }, 200); 252 | }); 253 | }); 254 | }); 255 | 256 | describe('when the service is not connected correctly (stalled connection)', function () { 257 | var $rootScope, vertxEventBus, vertxEventBusService, $timeout; 258 | 259 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 260 | vertxEventBusServiceProvider.useMessageBuffer(0).useDebug(true); 261 | })); 262 | 263 | beforeEach(angular.mock.inject(function (_$rootScope_, _vertxEventBus_, _vertxEventBusService_, _$timeout_) { 264 | $rootScope = _$rootScope_; 265 | $timeout = _$timeout_; 266 | vertxEventBus = _vertxEventBus_; 267 | vertxEventBusService = _vertxEventBusService_; 268 | // Mock bus is opened (said to be) 269 | _vertxEventBus_.readyState = function () { 270 | return _vertxEventBus_.EventBus.OPEN; 271 | }; 272 | _vertxEventBusService_.getConnectionState = function () { 273 | return true; 274 | }; 275 | var sendCalls = 0; 276 | _vertxEventBus_.send = function () { 277 | // do nothing, let it timeout 278 | }; 279 | // extend object 280 | vertxEventBus.getSendCalls = function () { 281 | return sendCalls; 282 | }; 283 | })); 284 | 285 | describe('send() should call the error callback', function () { 286 | 287 | var $interval; 288 | 289 | beforeEach(angular.mock.inject(function (_$interval_) { 290 | $interval = _$interval_; // angular.mock.$interval 291 | })); 292 | 293 | it('via promise.then()', function (done) { 294 | var successCalled, errorCalled; 295 | setTimeout(function () { 296 | // very short timeout: 10 297 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10}).then(function () { 298 | successCalled = true; 299 | }, function () { 300 | errorCalled = true; 301 | }); 302 | $rootScope.$apply(); 303 | setTimeout(function () { 304 | $interval.flush(20); // goto T+20 305 | expect(successCalled).to.be(undefined); 306 | expect(errorCalled).to.be(true); 307 | done(); 308 | }, 300); 309 | }, 200); 310 | }); 311 | 312 | it('via promise.then() without expecting reply', function (done) { 313 | var successCalled, errorCalled; 314 | setTimeout(function () { 315 | // very short timeout: 10 316 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10, expectReply : false}).then(function () { 317 | successCalled = true; 318 | }, function () { 319 | errorCalled = true; 320 | }); 321 | $rootScope.$apply(); 322 | setTimeout(function () { 323 | $interval.flush(20); // goto T+20 324 | expect(successCalled).to.be(true); 325 | expect(errorCalled).to.be(undefined); 326 | done(); 327 | }, 300); 328 | }, 200); 329 | }); 330 | 331 | it('via promise.catch()', function (done) { 332 | var successCalled, errorCalled; 333 | setTimeout(function () { 334 | // very short timeout: 10 335 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10}).then(function () { 336 | successCalled = true; 337 | })['catch'](function () { 338 | errorCalled = true; 339 | }); 340 | $rootScope.$apply(); 341 | setTimeout(function () { 342 | $interval.flush(20); // goto T+20 343 | expect(successCalled).to.be(undefined); 344 | expect(errorCalled).to.be(true); 345 | done(); 346 | }, 300); 347 | }, 200); 348 | }); 349 | 350 | }); 351 | 352 | }); 353 | 354 | describe('when the service is not connected correctly (send throws exception because not open)', function () { 355 | var $rootScope, vertxEventBus, vertxEventBusService, $timeout; 356 | 357 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 358 | vertxEventBusServiceProvider.useMessageBuffer(0).useDebug(true); 359 | })); 360 | 361 | beforeEach(angular.mock.inject(function (_$rootScope_, _vertxEventBus_, _vertxEventBusService_, _$timeout_) { 362 | $rootScope = _$rootScope_; 363 | $timeout = _$timeout_; 364 | vertxEventBus = _vertxEventBus_; 365 | vertxEventBusService = _vertxEventBusService_; 366 | // Mock bus is opened (said to be) 367 | _vertxEventBus_.readyState = function () { 368 | return _vertxEventBus_.EventBus.OPEN; 369 | }; 370 | _vertxEventBusService_.getConnectionState = function () { 371 | return true; 372 | }; 373 | var sendCalls = 0; 374 | _vertxEventBus_.send = function () { 375 | throw new Error('INVALID_STATE_ERR'); 376 | }; 377 | // extend object 378 | vertxEventBus.getSendCalls = function () { 379 | return sendCalls; 380 | }; 381 | })); 382 | 383 | describe('send() should call the error callback', function () { 384 | 385 | var $interval; 386 | 387 | beforeEach(angular.mock.inject(function (_$interval_) { 388 | $interval = _$interval_; // angular.mock.$interval 389 | })); 390 | 391 | it('via promise.then()', function (done) { 392 | var successCalled, errorCalled; 393 | setTimeout(function () { 394 | // very short timeout: 10 395 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10}).then(function () { 396 | successCalled = true; 397 | }, function () { 398 | errorCalled = true; 399 | }); 400 | $rootScope.$apply(); 401 | setTimeout(function () { 402 | $interval.flush(20); // goto T+20 403 | expect(successCalled).to.be(undefined); 404 | expect(errorCalled).to.be(true); 405 | done(); 406 | }, 300); 407 | }, 200); 408 | }); 409 | 410 | it('via promise.then() without expecting reply', function (done) { 411 | var successCalled, errorCalled; 412 | setTimeout(function () { 413 | // very short timeout: 10 414 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10, expectReply : false}).then(function () { 415 | successCalled = true; 416 | }, function () { 417 | errorCalled = true; 418 | }); 419 | $rootScope.$apply(); 420 | setTimeout(function () { 421 | $interval.flush(20); // goto T+20 422 | expect(successCalled).to.be(undefined); 423 | expect(errorCalled).to.be(true); 424 | done(); 425 | }, 300); 426 | }, 200); 427 | }); 428 | 429 | it('via promise.catch()', function (done) { 430 | var successCalled, errorCalled; 431 | setTimeout(function () { 432 | // very short timeout: 10 433 | vertxEventBusService.send('xyz', {data : 1}, {}, {timeout : 10}).then(function () { 434 | successCalled = true; 435 | })['catch'](function () { 436 | errorCalled = true; 437 | }); 438 | $rootScope.$apply(); 439 | setTimeout(function () { 440 | $interval.flush(20); // goto T+20 441 | expect(successCalled).to.be(undefined); 442 | expect(errorCalled).to.be(true); 443 | done(); 444 | }, 300); 445 | }, 200); 446 | }); 447 | 448 | }); 449 | 450 | }); 451 | 452 | describe('reconnect', function () { 453 | var $timeout, vertxEventBus, vertxEventBusService; 454 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _vertxEventBusService_, _$timeout_) { 455 | $timeout = _$timeout_; 456 | vertxEventBus = _vertxEventBus_; 457 | vertxEventBusService = _vertxEventBusService_; 458 | // Mock bus is closed 459 | _vertxEventBus_.readyState = function () { 460 | return _vertxEventBus_.EventBus.OPEN; 461 | }; 462 | var sendCalls = 0; 463 | _vertxEventBus_.send = function () { 464 | // do nothing, let it timeout 465 | }; 466 | // extend object 467 | vertxEventBus.getSendCalls = function () { 468 | return sendCalls; 469 | }; 470 | })); 471 | it('should be a function', function () { 472 | expect(typeof vertxEventBus.reconnect).to.be('function'); 473 | }); 474 | // Reconnect should be switch the connectivity, onopen() and onclose() 475 | // must be delegated transparently 476 | it('should re-add handler after a reconnect', function (done) { 477 | this.timeout(20000); 478 | var okHandler = false; 479 | var myHandler = function () { 480 | //$log.debug('[TEST] onhandle() called'); 481 | okHandler = true; 482 | }; 483 | 484 | setTimeout(function () { 485 | vertxEventBusService.addListener('lalelu', myHandler); 486 | vertxEventBus.reconnect(); 487 | setTimeout(function () { 488 | setTimeout(function () { 489 | SockJS.currentMockInstance.onmessage({ 490 | data : JSON.stringify({ 491 | address : 'lalelu', 492 | body : { 493 | data : '1x' 494 | }, 495 | replyAddress : undefined 496 | }) 497 | }); 498 | expect(okHandler).to.be(true); 499 | done(); 500 | }, 2100); 501 | $timeout.flush(); 502 | }, 100); 503 | }, 100); 504 | }); 505 | }); 506 | 507 | describe('after adding and removing a handler via "registerHandler"', function () { 508 | 509 | var vertxEventBusService; 510 | 511 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 512 | vertxEventBusServiceProvider.useMessageBuffer(0); 513 | })); 514 | 515 | beforeEach(angular.mock.inject(function (_vertxEventBusService_) { 516 | vertxEventBusService = _vertxEventBusService_; 517 | })); 518 | 519 | it('should not be called', function (done) { 520 | var abcCalled, xyzCalled; 521 | setTimeout(function () { 522 | var abcHandler = function (message) { 523 | abcCalled = message; 524 | }, xyzHandler = function (message) { 525 | xyzCalled = message; 526 | }; 527 | 528 | var abcFunct = vertxEventBusService.addListener('abc', abcHandler); 529 | var xyzFunct = vertxEventBusService.addListener('xyz', xyzHandler); 530 | // remove again! 531 | abcFunct(); 532 | xyzFunct(); 533 | SockJS.currentMockInstance.onmessage({ 534 | data : JSON.stringify({ 535 | address : 'xyz', 536 | body : { 537 | data : '1x' 538 | }, 539 | replyAddress : undefined 540 | }) 541 | }); 542 | expect(abcCalled).to.be(undefined); 543 | expect(xyzCalled).to.be(undefined); 544 | done(); 545 | }, 200); 546 | }); 547 | }); 548 | 549 | }); 550 | 551 | describe('after removing a registered handler via "unregisterHandler"', function () { 552 | 553 | var vertxEventBusService; 554 | 555 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 556 | vertxEventBusServiceProvider.useMessageBuffer(0); 557 | })); 558 | 559 | beforeEach(angular.mock.inject(function (_vertxEventBusService_) { 560 | vertxEventBusService = _vertxEventBusService_; 561 | })); 562 | 563 | it('should not be called', function (done) { 564 | var abcCalled, xyzCalled; 565 | setTimeout(function () { 566 | var abcHandler = function (message) { 567 | abcCalled = message; 568 | }, xyzHandler = function (message) { 569 | xyzCalled = message; 570 | }; 571 | vertxEventBusService.addListener('abc', abcHandler); 572 | vertxEventBusService.addListener('xyz', xyzHandler); 573 | // remove again! 574 | vertxEventBusService.removeListener('abc', abcHandler); 575 | vertxEventBusService.removeListener('xyz', xyzHandler); 576 | SockJS.currentMockInstance.onmessage({ 577 | data : JSON.stringify({ 578 | address : 'xyz', 579 | message : { 580 | data : '1x' 581 | } 582 | }) 583 | }); 584 | expect(abcCalled).to.be(undefined); 585 | expect(xyzCalled).to.be(undefined); 586 | done(); 587 | }, 200); 588 | }); 589 | 590 | }); 591 | 592 | describe('vertxEventBusService (bus online) send()', function () { 593 | 594 | var vertxEventBusService, vertxEventBus, $timeout, $rootScope, $log; 595 | 596 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 597 | vertxEventBusServiceProvider.useMessageBuffer(0).useDebug(true); 598 | })); 599 | 600 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _vertxEventBusService_, _$timeout_, _$rootScope_, _$log_) { 601 | vertxEventBus = _vertxEventBus_; 602 | vertxEventBusService = _vertxEventBusService_; 603 | $timeout = _$timeout_; 604 | $rootScope = _$rootScope_; 605 | $log = _$log_; 606 | SockJS.currentMockInstance.$log = $log; 607 | })); 608 | 609 | it('should return a promise which will be resolved (success)', function (done) { 610 | setTimeout(function () { 611 | var results = { 612 | 'then' : 0, 613 | 'catch' : 0, 614 | 'finally' : 0 615 | }; 616 | var promise = vertxEventBusService.send('xyz', {data : 123}); 617 | expect(promise).to.not.be(undefined); 618 | // looks like a promise? 619 | expect(typeof promise).to.be('object'); 620 | expect(typeof promise.then).to.be('function'); 621 | expect(typeof promise.catch).to.be('function'); 622 | expect(typeof promise.finally).to.be('function'); 623 | promise.then(function () { 624 | results.then++; 625 | }); 626 | promise.catch(function () { 627 | results.catch++; 628 | }); 629 | promise.finally(function () { 630 | results.finally++; 631 | }); 632 | $rootScope.$apply(); 633 | setTimeout(function () { 634 | expect(results.then).to.be(1); 635 | expect(results.catch).to.be(0); 636 | expect(results.finally).to.be(1); 637 | done(); 638 | }, 500); 639 | }, 200); 640 | }); 641 | 642 | it('should return a promise which will be rejected (failure in message)', function (done) { 643 | setTimeout(function () { 644 | var results = { 645 | 'then' : 0, 646 | 'catch' : 0, 647 | 'finally' : 0 648 | }; 649 | var promise = vertxEventBusService.send('xyz', { 650 | data : 123, 651 | mockReply: { 652 | type: 'err', 653 | failureCode: 4711, 654 | failureType: 'whatever' 655 | } 656 | }); 657 | expect(promise).to.not.be(undefined); 658 | // looks like a promise? 659 | expect(typeof promise).to.be('object'); 660 | expect(typeof promise.then).to.be('function'); 661 | expect(typeof promise.catch).to.be('function'); 662 | expect(typeof promise.finally).to.be('function'); 663 | promise.then(function () { 664 | results.then++; 665 | }, angular.noop); // ignore error (because error is expected) 666 | promise.catch(function () { 667 | results.catch++; 668 | }); 669 | promise.finally(function () { 670 | results.finally++; 671 | }).then(null, angular.noop); // ignore error (because error is expected) 672 | $rootScope.$apply(); 673 | setTimeout(function () { 674 | expect(results.then).to.be(0); 675 | expect(results.catch).to.be(1); 676 | expect(results.finally).to.be(1); 677 | done(); 678 | }, 500); 679 | }, 200); 680 | }); 681 | 682 | }); 683 | 684 | describe('vertxEventBusService (bus offline) send()', function () { 685 | 686 | var vertxEventBusService, vertxEventBus, $timeout, $rootScope, $log; 687 | 688 | beforeEach(angular.mock.module('knalli.angular-vertxbus', function (vertxEventBusServiceProvider) { 689 | vertxEventBusServiceProvider.useMessageBuffer(0).useDebug(true); 690 | })); 691 | 692 | beforeEach(angular.mock.inject(function (_vertxEventBus_, _vertxEventBusService_, _$timeout_, _$rootScope_, _$log_) { 693 | vertxEventBus = _vertxEventBus_; 694 | vertxEventBusService = _vertxEventBusService_; 695 | $timeout = _$timeout_; 696 | $rootScope = _$rootScope_; 697 | $log = _$log_; 698 | SockJS.currentMockInstance.$log = $log; 699 | 700 | vertxEventBus.readyState = function () { 701 | return 3; 702 | }; 703 | })); 704 | 705 | it('should return a promise which will be rejected (fail)', function (done) { 706 | setTimeout(function () { 707 | var results = { 708 | 'then' : 0, 709 | 'catch' : 0, 710 | 'finally' : 0 711 | }; 712 | var promise = vertxEventBusService.send('xyz', {data : 123}); 713 | expect(promise).to.not.be(undefined); 714 | // looks like a promise? 715 | expect(typeof promise).to.be('object'); 716 | expect(typeof promise.then).to.be('function'); 717 | expect(typeof promise.catch).to.be('function'); 718 | expect(typeof promise.finally).to.be('function'); 719 | promise.then(function () { 720 | results.then++; 721 | }, angular.noop); // ignore error (because error is expected) 722 | promise.catch(function () { 723 | results.catch++; 724 | }); 725 | promise.finally(function () { 726 | results.finally++; 727 | }).then(null, angular.noop); // ignore error (because error is expected) 728 | $rootScope.$apply(); 729 | setTimeout(function () { 730 | window.console.warn(results); 731 | expect(results.then).to.be(0); 732 | expect(results.catch).to.be(1); 733 | expect(results.finally).to.be(1); 734 | done(); 735 | }, 500); 736 | }, 200); 737 | }); 738 | 739 | }); 740 | 741 | }); 742 | -------------------------------------------------------------------------------- /test/unit/lib/support/Queue.spec.js: -------------------------------------------------------------------------------- 1 | import Queue from '../../../../src/lib/support/Queue'; 2 | 3 | describe('lib.helpers.Queue', () => { 4 | 5 | describe('after creation', () => { 6 | 7 | it('queue should be empty (size is 0)', () => { 8 | let queue = new Queue; 9 | expect(queue.size()).to.be(0); 10 | }); 11 | 12 | it('queue should be empty (no first item)', () => { 13 | let queue = new Queue; 14 | expect(queue.first()).to.be(undefined); 15 | }); 16 | 17 | it('queue should be empty (no last item)', () => { 18 | let queue = new Queue; 19 | expect(queue.last()).to.be(undefined); 20 | }); 21 | 22 | }); 23 | 24 | describe('after adding one item', () => { 25 | 26 | it('queue should be not empty (size is 1)', () => { 27 | let queue = new Queue; 28 | queue.push('an item'); 29 | expect(queue.size()).to.be(1); 30 | }); 31 | 32 | it('queue should be not empty (first item is the added one)', () => { 33 | let queue = new Queue; 34 | queue.push('an item'); 35 | expect(queue.first()).to.be('an item'); 36 | }); 37 | 38 | it('queue should be not empty (last item is the added one)', () => { 39 | let queue = new Queue; 40 | queue.push('an item'); 41 | expect(queue.last()).to.be('an item'); 42 | }); 43 | 44 | describe('and removing it again', () => { 45 | it('queue should be empty (size is 0)', () => { 46 | let queue = new Queue; 47 | queue.push('an item'); 48 | queue.first(); 49 | expect(queue.size()).to.be(0); 50 | }); 51 | 52 | it('queue should be empty (no first item)', () => { 53 | let queue = new Queue; 54 | queue.push('an item'); 55 | queue.first(); 56 | expect(queue.first()).to.be(undefined); 57 | }); 58 | 59 | it('queue should be empty (no last item)', () => { 60 | let queue = new Queue; 61 | queue.push('an item'); 62 | queue.last(); 63 | expect(queue.last()).to.be(undefined); 64 | }); 65 | }); 66 | 67 | }); 68 | 69 | describe('after adding multiple items', () => { 70 | 71 | it('queue should be not empty (size is 5)', () => { 72 | let queue = new Queue; 73 | queue.push('an item 1'); 74 | queue.push('an item 2'); 75 | queue.push('an item 3'); 76 | queue.push('an item 4'); 77 | queue.push('an item 5'); 78 | expect(queue.size()).to.be(5); 79 | }); 80 | 81 | it('queue should be not empty (first item is the added one)', () => { 82 | let queue = new Queue; 83 | queue.push('an item 1'); 84 | queue.push('an item 2'); 85 | queue.push('an item 3'); 86 | queue.push('an item 4'); 87 | queue.push('an item 5'); 88 | expect(queue.first()).to.be('an item 1'); 89 | }); 90 | 91 | it('queue should be not empty (last item is the added one)', () => { 92 | let queue = new Queue; 93 | queue.push('an item 1'); 94 | queue.push('an item 2'); 95 | queue.push('an item 3'); 96 | queue.push('an item 4'); 97 | queue.push('an item 5'); 98 | expect(queue.last()).to.be('an item 5'); 99 | }); 100 | 101 | describe('and removing it again', () => { 102 | it('queue should be still not empty (size is 4)', () => { 103 | let queue = new Queue; 104 | queue.push('an item 1'); 105 | queue.push('an item 2'); 106 | queue.push('an item 3'); 107 | queue.push('an item 4'); 108 | queue.push('an item 5'); 109 | queue.first(); 110 | expect(queue.size()).to.be(4); 111 | }); 112 | 113 | it('queue should be not empty (previous first(), now first item is the 2nd added one)', () => { 114 | let queue = new Queue; 115 | queue.push('an item 1'); 116 | queue.push('an item 2'); 117 | queue.push('an item 3'); 118 | queue.push('an item 4'); 119 | queue.push('an item 5'); 120 | queue.first(); 121 | expect(queue.first()).to.be('an item 2'); 122 | }); 123 | 124 | it('queue should be not empty (previous last(), now last item is the 4th added one)', () => { 125 | let queue = new Queue; 126 | queue.push('an item 1'); 127 | queue.push('an item 2'); 128 | queue.push('an item 3'); 129 | queue.push('an item 4'); 130 | queue.push('an item 5'); 131 | queue.last(); 132 | expect(queue.last()).to.be('an item 4'); 133 | }); 134 | 135 | it('queue should be not empty (previous last(), now first item is the 1st added one)', () => { 136 | let queue = new Queue; 137 | queue.push('an item 1'); 138 | queue.push('an item 2'); 139 | queue.push('an item 3'); 140 | queue.push('an item 4'); 141 | queue.push('an item 5'); 142 | queue.last(); 143 | expect(queue.first()).to.be('an item 1'); 144 | }); 145 | 146 | it('queue should be not empty (previous first(), now last item is the 5th added one)', () => { 147 | let queue = new Queue; 148 | queue.push('an item 1'); 149 | queue.push('an item 2'); 150 | queue.push('an item 3'); 151 | queue.push('an item 4'); 152 | queue.push('an item 5'); 153 | queue.first(); 154 | expect(queue.last()).to.be('an item 5'); 155 | }); 156 | }); 157 | 158 | }); 159 | 160 | }); 161 | 162 | -------------------------------------------------------------------------------- /test/unit/lib/support/SimpleMap.spec.js: -------------------------------------------------------------------------------- 1 | import SimpleMap from '../../../../src/lib/support/SimpleMap'; 2 | 3 | describe('lib.helpers.SimpleMap', () => { 4 | 5 | describe('get()', () => { 6 | 7 | it('should return undefined for unknown keys (empty map)', () => { 8 | let map = new SimpleMap; 9 | expect(map.get('key1')).to.be(undefined); 10 | }); 11 | 12 | it('should return undefined for unknown keys (not empty map)', () => { 13 | let map = new SimpleMap; 14 | map.put('key2', 'A'); 15 | expect(map.get('key1')).to.be(undefined); 16 | }); 17 | 18 | it('should return undefined for well known key with value undefined', () => { 19 | let map = new SimpleMap; 20 | map.put('key1', undefined); 21 | expect(map.get('key1')).to.be(undefined); 22 | }); 23 | 24 | describe('should return value for key type ', () => { 25 | 26 | it('int', () => { 27 | let map = new SimpleMap; 28 | map.put(1, 'A'); 29 | expect(map.get(1)).to.be('A'); 30 | }); 31 | 32 | it('string', () => { 33 | let map = new SimpleMap; 34 | map.put('1', 'A'); 35 | expect(map.get('1')).to.be('A'); 36 | }); 37 | 38 | it('object', () => { 39 | let map = new SimpleMap; 40 | let obj = {a : 1}; 41 | map.put(obj, 'A'); 42 | expect(map.get(obj)).to.be('A'); 43 | }); 44 | 45 | it('function', () => { 46 | let map = new SimpleMap; 47 | let fn = () => { 48 | }; 49 | map.put(fn, 'A'); 50 | expect(map.get(fn)).to.be('A'); 51 | }); 52 | 53 | }); 54 | 55 | describe('should return value for value type ', () => { 56 | 57 | it('int', () => { 58 | let map = new SimpleMap; 59 | map.put('key1', 1); 60 | expect(map.get('key1')).to.be(1); 61 | }); 62 | 63 | it('string', () => { 64 | let map = new SimpleMap; 65 | map.put('key1', '1'); 66 | expect(map.get('key1')).to.be('1'); 67 | }); 68 | 69 | it('object', () => { 70 | let map = new SimpleMap; 71 | let obj = {a : 1}; 72 | map.put('key1', obj); 73 | expect(map.get('key1')).to.be(obj); 74 | }); 75 | 76 | it('function', () => { 77 | let map = new SimpleMap; 78 | let fn = () => { 79 | }; 80 | map.put('key1', fn); 81 | expect(map.get('key1')).to.be(fn); 82 | }); 83 | 84 | }); 85 | 86 | }); 87 | 88 | describe('store multiple', () => { 89 | 90 | it('should return the correct value for a key', () => { 91 | let map = new SimpleMap; 92 | map.put('key1', 'A'); 93 | map.put('key2', 'B'); 94 | expect(map.get('key1')).to.be('A'); 95 | }); 96 | 97 | }); 98 | 99 | describe('ensure toString() is not being used', () => { 100 | 101 | it('using functions as keys', ()=> { 102 | let map = new SimpleMap; 103 | let fn1 = () => { 104 | }; 105 | let fn2 = () => { 106 | }; 107 | map.put(fn1, 'A'); 108 | map.put(fn2, 'B'); 109 | expect(map.get(fn1)).to.be('A'); 110 | expect(map.get(fn2)).to.be('B'); 111 | 112 | }); 113 | 114 | }); 115 | 116 | }); 117 | -------------------------------------------------------------------------------- /test/unit/mock/sockjs.js: -------------------------------------------------------------------------------- 1 | class SockJS { 2 | 3 | constructor(url, whitelist, options, mockOptions) { 4 | this.nextLoginState = true; 5 | this.url = url; 6 | this.whitelist = whitelist; 7 | this.options = options; 8 | SockJS.mockInstances.push(this); 9 | SockJS.currentMockInstance = this; 10 | let fn = () => { 11 | if (typeof this.onopen === 'function') { 12 | this.onopen(); 13 | } 14 | }; 15 | if (mockOptions != null && mockOptions.timeout) { 16 | window.setTimeout(fn, mockOptions.timeout); 17 | } else { 18 | window.setTimeout(fn, 1); 19 | } 20 | } 21 | 22 | log(...args) { 23 | var log = window.console; 24 | if (SockJS.currentMockInstance && SockJS.currentMockInstance.$log) { 25 | log = SockJS.currentMockInstance.$log; 26 | } 27 | log.debug(...args); 28 | } 29 | 30 | close(mockOptions) { 31 | this.log("[MOCK] SockJS.close()"); 32 | let fn = () => { 33 | if (typeof this.onclose === 'function') { 34 | this.onclose(); 35 | } 36 | }; 37 | if (mockOptions && mockOptions.timeout) { 38 | window.setTimeout(fn, mockOptions.timeout); 39 | } else { 40 | fn(); 41 | } 42 | } 43 | 44 | send(event) { 45 | let message = this._unwrapFromEvent(event); 46 | if (message.type !== 'send') { 47 | return; 48 | } 49 | this.log(`[MOCK] SockJS.send(${event})`); 50 | if (message.replyAddress) { 51 | this.log(`[MOCK] Sending reply to ${message.replyAddress}`); 52 | var mockReply = message.body.mockReply || {data: 'reply'}; 53 | var reply = this._wrapToEvent(message.replyAddress, mockReply, undefined, mockReply.type); 54 | this.onmessage(reply); 55 | } 56 | } 57 | 58 | _unwrapFromEvent(event) { 59 | return JSON.parse(event); 60 | } 61 | 62 | _wrapToEvent(address, body, replyAddress, type) { 63 | return { 64 | data : JSON.stringify({ 65 | type: type, 66 | address : address, 67 | message : body, 68 | replyAddress : replyAddress 69 | }) 70 | }; 71 | } 72 | 73 | _buildLoginReplyAsSuccess(username, password) { 74 | this.sessionId = "SESSION" + (Math.round(1000000 * Math.random())); 75 | return { 76 | status : 'ok', 77 | sessionID : this.sessionId 78 | }; 79 | } 80 | 81 | _buildLoginReplyAsFail(username, password) { 82 | return { 83 | status : 'fail' 84 | }; 85 | } 86 | 87 | onmessage() { 88 | console.warn('No SockJS.onmessage() defined!'); 89 | } 90 | 91 | } 92 | 93 | SockJS.mockInstances = []; 94 | SockJS.currentMockInstance = null; 95 | 96 | module.exports = SockJS; 97 | -------------------------------------------------------------------------------- /test/unit/test_index.js: -------------------------------------------------------------------------------- 1 | // load all specs into one bundle 2 | var testsContext = require.context('.', true, /spec\.js$/); 3 | testsContext.keys().forEach(testsContext); 4 | -------------------------------------------------------------------------------- /test/unit/util/unhandledRejectionTracing.js: -------------------------------------------------------------------------------- 1 | // https://github.com/angular-ui/ui-router/issues/2889#issuecomment-273944742 2 | module.exports = function (angular, module) { 3 | 4 | if (angular.version.minor < 3) { 5 | // will work w/ AngularJS 1.3+ 6 | return; 7 | } 8 | 9 | /* jshint ignore:start */ 10 | // Decorate the $q service when app starts 11 | module.decorator('$q', ['$delegate', function ($delegate) { 12 | // Create a new promise object 13 | var promise = $delegate.when(); 14 | 15 | // Access the `Promise` prototype (nonstandard, but works in Chrome) 16 | var proto = promise.__proto__; 17 | 18 | // Define a setter for `$$state` that creates a stacktrace 19 | // (string) and assigns it as a property of the internal `$$state` object. 20 | Object.defineProperty(proto, '$$state', { 21 | configurable : true, 22 | enumerable : true, 23 | set : function (val) { 24 | val.stack = new Error().stack; 25 | this._$$state = val; 26 | }, 27 | get : function () { 28 | return this._$$state; 29 | } 30 | }); 31 | 32 | return $delegate; 33 | }]); 34 | /* jshint ignore:end */ 35 | }; 36 | -------------------------------------------------------------------------------- /test_scopes/angular_1.2.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.2.0", 13 | "angular-mocks": "~1.2.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/angular_1.3.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.3.0", 13 | "angular-mocks": "~1.3.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/angular_1.4.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.4.0", 13 | "angular-mocks": "~1.4.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/angular_1.5.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.5.0", 13 | "angular-mocks": "~1.5.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/angular_1.6.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/sockjs-client_1.0.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "~1.0.3", 15 | "vertx3-eventbus-client": "~3.2.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/sockjs-client_1.1.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "~1.1.0", 15 | "vertx3-eventbus-client": "~3.2.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/vertx-bus_3.2.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.2.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/vertx-bus_3.3.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.3.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test_scopes/vertx-bus_3.4.x/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jan Philipp", 3 | "name": "angular-vertxbus", 4 | "description": "", 5 | "version": "0.0.0", 6 | "homepage": "http://github.com/knalli/angular-vertxbus", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/knalli/angular-vertxbus" 10 | }, 11 | "devDependencies": { 12 | "angular": "~1.6.0", 13 | "angular-mocks": "~1.6.0", 14 | "sockjs-client": "1.0.3", 15 | "vertx3-eventbus-client": "~3.4.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /*eslint-env node, commonjs */ 2 | /*eslint comma-dangle:0 */ 3 | 4 | const webpack = require('webpack'); 5 | const NgAnnotatePlugin = require('ng-annotate-webpack-plugin'); 6 | 7 | const pkg = require('./package.json'); 8 | const banner = '' + 9 | '/*! ' + (pkg.title || pkg.name) + ' - v' + (pkg.version) + ' - ' + (new Date().toISOString().substring(0, 10)) + '\n' + 10 | ' * ' + (pkg.homepage) + '\n' + 11 | ' * Copyright (c) ' + (new Date().toISOString().substring(0, 4)) + ' ' + (pkg.author.name) + '\n' + 12 | ' * @license ' + (pkg.license) + ' */' + 13 | ''; 14 | 15 | const factory = function (options) { 16 | var minified = options.minified || false; 17 | var result = { 18 | entry : { 19 | 'angular-vertxbus' : './src/index.js', 20 | }, 21 | output : { 22 | filename : minified ? 'dist/[name].min.js' : 'dist/[name].js', 23 | libraryTarget : 'umd', 24 | }, 25 | externals : [ 26 | { 27 | 'vertx-eventbus' : { 28 | root : 'EventBus', 29 | commonjs2 : 'vertx-eventbus', 30 | commonjs : 'vertx-eventbus', 31 | amd : 'vertx-eventbus', 32 | } 33 | } 34 | ], 35 | module : { 36 | loaders : [ 37 | { 38 | enforce : 'pre', 39 | test : /\.js$/, 40 | exclude : /(node_modules|bower_components)/, 41 | loader : 'eslint-loader', 42 | }, 43 | { 44 | test : /\.js$/, 45 | exclude : /(node_modules|bower_components)/, 46 | loader : 'babel-loader', 47 | options : { 48 | presets : ['env'], 49 | plugins : ['transform-runtime'] 50 | }, 51 | }, 52 | ] 53 | }, 54 | plugins : [], 55 | devtool : 'source-map', 56 | }; 57 | 58 | result.plugins.push(new webpack.BannerPlugin({ 59 | banner : banner, 60 | raw : true, 61 | entryOnly : true, 62 | })); 63 | result.plugins.push(new NgAnnotatePlugin({ 64 | add : true, 65 | })); 66 | if (minified) { 67 | result.plugins.push(new webpack.optimize.UglifyJsPlugin({ 68 | sourceMap : true, 69 | })); 70 | } 71 | 72 | return result; 73 | }; 74 | 75 | module.exports = factory({ 76 | minified : process.env.BUILD_MINIFIED ? true : false 77 | }); 78 | --------------------------------------------------------------------------------