├── .gitignore
├── .jshintrc
├── .travis.yml
├── CONTRIBUTING.md
├── Gruntfile.js
├── README.md
├── custom_build_help.txt
├── external
├── crypto
│ ├── LICENSE
│ └── sjcl.js
└── uuid
│ ├── license.md
│ └── uuid.js
├── package.json
├── src
├── aerogear.core.js
├── crypto
│ └── aerogear.crypto.js
├── data-manager
│ ├── adapters
│ │ ├── base.js
│ │ ├── indexeddb.js
│ │ ├── memory.js
│ │ ├── session-local.js
│ │ └── websql.js
│ └── aerogear.datamanager.js
├── diff-sync
│ ├── aerogear.diff-sync-client.js
│ ├── aerogear.diff-sync-engine.js
│ └── engine-adapters
│ │ ├── diff-match-patch.js
│ │ └── json-patch.js
├── notifier
│ ├── adapters
│ │ ├── base.js
│ │ ├── mqttws.js
│ │ ├── simplePush.js
│ │ ├── stompws.js
│ │ └── vertx.js
│ └── aerogear.notifier.js
├── simplepush
│ └── aerogear.simplepush.js
└── unifiedpush
│ └── aerogear.unifiedpush.js
└── tests
├── .jshintrc
├── polyfill
└── bind-polyfill.js
├── unit
├── all.html
├── crypto
│ ├── aerogear.crypto.html
│ └── aerogear.crypto.js
├── data-manager-indexeddb
│ ├── data-manager-indexeddb-encrypted.html
│ ├── data-manager-indexeddb-encrypted.js
│ ├── data-manager-indexeddb.html
│ └── data-manager-indexeddb.js
├── data-manager-websql
│ ├── data-manager-websql-encrypted.html
│ ├── data-manager-websql-encrypted.js
│ ├── data-manager-websql.html
│ └── data-manager-websql.js
├── data-manager
│ ├── data-manager-fallback-feature-detect.html
│ ├── data-manager-fallback-feature-detect.js
│ ├── data-manager-fallback.html
│ ├── data-manager-fallback.js
│ ├── data-manager-memory-async.html
│ ├── data-manager-memory-async.js
│ ├── data-manager-sessionLocal-async-encrypted.html
│ ├── data-manager-sessionLocal-async-encrypted.js
│ ├── data-manager-sessionLocal-async.html
│ └── data-manager-sessionLocal-async.js
├── index.html
├── notifier
│ ├── mqttws.js
│ ├── notifier.html
│ ├── simplepush.js
│ ├── stompws.js
│ └── vertx.js
├── simplepush
│ ├── simplepush.html
│ └── simplepush.js
├── sync
│ ├── diff-sync-client.html
│ ├── diff-sync-client.js
│ ├── diff-sync-engine-dmp.html
│ ├── diff-sync-engine-dmp.js
│ ├── diff-sync-engine-json-patch.html
│ └── diff-sync-engine-json-patch.js
└── unifiedpush
│ ├── unifiedpush.html
│ └── unifiedpush.js
└── vendor
├── diff_match_patch_uncompressed.js
├── jquery-2.0.3.min.js
├── json-patch-duplex.min.js
├── mqttws31.js
├── promise-0.1.1.js
├── qunit-composite.css
├── qunit-composite.js
├── qunit.css
├── qunit.js
├── sinon-1.9.0.js
├── sockjs.js
├── stomp.js
└── vertxbus.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.yaml
2 | dist/
3 | docs/
4 | node_modules/
5 | aerogear-js-integration/
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "browser": true,
3 | "curly": true,
4 | "eqeqeq": true,
5 | "latedef": true,
6 | "loopfunc": true,
7 | "noarg": true,
8 | "noempty": true,
9 | "undef": true,
10 | "trailing": true,
11 | "globals": {
12 | "jQuery": true,
13 | "AeroGear": true,
14 | "Promise": true,
15 | "require": true,
16 | "uuid": true,
17 | "vertx": true,
18 | "SockJS": true,
19 | "Stomp": true,
20 | "Paho": true,
21 | "File": true,
22 | "sjcl": true,
23 | "crypto": true,
24 | "diff_match_patch": true,
25 | "jsonpatch": true
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.10'
4 | before_script:
5 | - git clone https://github.com/aerogear/aerogear-js-integration.git
6 | - npm install -g grunt-cli
7 | - pushd aerogear-js-integration; npm install; popd
8 | script:
9 | - grunt travis --verbose
10 | notifications:
11 | irc: "irc.freenode.org#aerogear"
12 | branches:
13 | only:
14 | - master
15 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to AeroGear
2 |
3 | As an open source project we are always on the lookout for community members that want to step up and help with the project. There are lots of ways to help, and this article will help you get started!
4 |
5 | ## Help Others
6 |
7 | Have experience with mobile or HTML5 based technologies? Interested in sharing your knowledge?
8 |
9 | If you've got ideas for the project, or want to discuss ways to improve AeroGear, join the [aerogear-dev](https://lists.jboss.org/mailman/listinfo/aerogear-dev) mailing list and share what your working on, or struggling with. For more immediate gratification join the IRC channel (#aerogear). There are are usually a good bunch of people hanging out there. Ask your questions, share your experience, or just make jokes :-)
10 |
11 | ## Found An Issue?
12 | Have you run into an issue with one of our examples, sites, or have a suggestion? The best place to start is probably talking about it in the forums or IRC. If you've already done that, or just want to create the issue please do at [https://issues.jboss.org/browse/AGJS](https://issues.jboss.org/browse/AGJS).
13 |
14 | We only ask that you review our [AeroGear Jira Usage and Guidelines](http://aerogear.org/docs/guides/JIRAUsage) and use your noodle! Help the community help you :-)
15 |
16 | ## Fix an Issue!
17 |
18 | Your ready to start taking action, dig into an issue, and update some code! Excellent!!
19 |
20 | ### Communicate
21 |
22 | The first recommended step is to communicate with the project team. This way you can get any advice, or feedback on your plans.
23 |
24 | The best ways to do this are through:
25 |
26 | * IRC: #aerogear @ irc.freenode.net
27 | * Developer mailing list: [aerogear-dev](https://lists.jboss.org/mailman/listinfo/aerogear-dev)
28 | * Project meetings: [AeroGear Community Calendar](https://www.jboss.org/aerogear/AeroGearCalendar)
29 |
30 | ### Pick your poison
31 |
32 | If what you want to work on is already in jira, then ask to have it assigned to you (see communicate section above). If there is no jira, go ahead and make one as described above, and in the [AeroGear Jira Usage and Guidelines](http://aerogear.org/docs/guides/JIRAUsage).
33 |
34 | ### Sign the JBoss community license agreement
35 |
36 | This is pretty standard stuff for open source. Just use your JBoss user, and pick AeroGear for the project here:
37 |
38 | [https://cla.jboss.org](https://cla.jboss.org)
39 |
40 | ### Follow AeroGear.js's coding conventions and style
41 |
42 | Our coding style comes from jQuery's style. Here is a link to their [style guide](http://contribute.jquery.org/style-guide/js/)
43 |
44 | Our grunt build will run JSHint to let you know if most things are in line.
45 |
46 | Most editors will have support for the provided `.jshintrc` file. This will help during development.
47 |
48 | In addition, we have added a grunt watch task which executes the corresponding unit tests whenever a file is added, changed or deleted.
49 |
50 | ### Follow AeroGear's github workflow*
51 |
52 | Follow our document that will walk you through how to work with GitHub, and the AeroGear repositories: [AeroGear GitHub Workflow & Instructions](http://aerogear.org/docs/guides/GitHubWorkflow).
53 |
54 | ### Get Fame and Applause from Everyone!!
55 |
56 | Talk about your work, create a blog, or tweet about it using the #AeroGear hashtag!
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # aerogear-js [](https://travis-ci.org/aerogear/aerogear-js) [](https://david-dm.org/aerogear/aerogear-js#info=devDependencies) #
2 |
3 | JavaScript client library implementation for AeroGear. Eventually, this will include API's for persistence, security, data synchronization and more. For more information and downloads, visit [AeroGear.org](http://aerogear.org/javascript).
4 |
5 | | | Project Info |
6 | | --------------- | ------------- |
7 | | License: | Apache License, Version 2.0 |
8 | | Build: | NPM, Grunt |
9 | | Documentation: | https://aerogear.org/docs/specs/aerogear-js/ |
10 | | Issue tracker: | https://issues.jboss.org/browse/AGJS |
11 | | Mailing lists: | [aerogear-users](http://aerogear-users.1116366.n5.nabble.com/) ([subscribe](https://lists.jboss.org/mailman/listinfo/aerogear-users)) |
12 | | | [aerogear-dev](http://aerogear-dev.1069024.n5.nabble.com/) ([subscribe](https://lists.jboss.org/mailman/listinfo/aerogear-dev)) |
13 |
14 | ## Authorization
15 | - - -
16 |
17 | _This api has been deprecated and removed as of 2.1.0. To use it you will need the latest 1.x release, which can be [found here](https://github.com/aerogear/aerogear-js/tree/1.x))_
18 |
19 | ## Auth
20 | - - -
21 |
22 | _This api has been deprecated. To use it you will need the latest 1.x release, which can be [found here](https://github.com/aerogear/aerogear-js/tree/1.x))_
23 |
24 | ## Crypto
25 | - - -
26 |
27 | The AeroGear.Crypto namespace provides a straightforward API to provide an easy to use cryptography interface for data encryption and decryption.
28 |
29 | See the [Crypto API Docs](http://aerogear.org/docs/specs/aerogear-js/AeroGear.Crypto.html) for more info.
30 |
31 | ## DataManager
32 | - - -
33 |
34 | A collection of data connections (stores) and their corresponding data models. This object provides a standard way to interact with client side data no matter the data format or storage mechanism used.
35 |
36 | See the [DataManager API docs](http://aerogear.org/docs/specs/aerogear-js/AeroGear.DataManager.html) for more info.
37 |
38 | ## Notifier
39 | - - -
40 |
41 | _This api has been deprecated as of 2.1.0 and will be removed in a future version_
42 |
43 | Notifier is a collection of adapters which provide a unified or similar API for interacting with different messaging services and protocols.
44 |
45 | See the [Notifier API docs](http://aerogear.org/docs/specs/aerogear-js/AeroGear.Notifier.html) for more info.
46 |
47 | ## Pipeline
48 | - - -
49 |
50 | _This api has been deprecated. To use it you will need the latest 1.x release, which can be [found here](https://github.com/aerogear/aerogear-js/tree/1.x))_
51 |
52 | ## SimplePushClient
53 | - - -
54 |
55 | SimplePushClient is a client implementation and polyfill for the Mozilla SimplePush specification. SimplePush allows for simple push notification support in web, as well as Firefox OS, applications. This implementation does differ slightly from the specification in that it only works in applications that are "online" and active in the browser. This implementation also supports connecting to both Mozilla's SimplePush server as well as the AeroGear project's server.
56 |
57 | See the [SimplePushClient API docs](http://aerogear.org/docs/specs/aerogear-js/AeroGear.SimplePushClient.html) for more info. Also, please see the [Mozilla SimplePush specification](https://wiki.mozilla.org/WebAPI/SimplePush) for more info on SimplePush.
58 |
59 | ## Diff Sync
60 | - - -
61 |
62 | The Diff Sync client and server are based on an implementation of Google's [Differential Synchonrization](http://research.google.com/pubs/pub35605.html) by Neil Fraser.
63 |
64 | The [DiffSyncClient](http://aerogear.org/docs/specs/aerogear-js/AeroGear.DiffSyncClient.html) connects to the [AeroGear Sync Server](https://github.com/aerogear/aerogear-sync-server)
65 |
66 | The [DiffSyncEngine](http://aerogear.org/docs/specs/aerogear-js/AeroGear.DiffSyncEngine.html) is responsible for the algorithm logic - there are two adapters available: [JSON Patch](http://aerogear.org/docs/specs/aerogear-js/AeroGear.DiffSyncEngine.adapters.jsonPatch.html) and [DiffMatchPatch](http://aerogear.org/docs/specs/aerogear-js/AeroGear.DiffSyncEngine.adapters.diffMatchPatch.html).
67 |
68 |
69 | ## UnifiedPushClient
70 | - - -
71 |
72 | UnifiedPushClient is used in conjunction with AeroGear's UnifiedPush server to register web applications for push notifications. Using the SimplePushClient, a web application can register for push notifications from a SimplePush network and then inform the UnifiedPush server as to where it should send those push notifications.
73 |
74 | See the [UnifiedPushClient API docs](http://aerogear.org/docs/specs/aerogear-js/AeroGear.UnifiedPushClient.html) for more info.
75 |
76 | ## Feature Stability
77 | - - -
78 |
79 | All features of the library are given a stability rating which is noted in the documentation for that feature. The stability ratings are as follows:
80 |
81 | * Experimental - This feature is new and has not been thoroughly tested outside of development. This feature could be changed or removed at any time. Use of these features in a production environment is at your own risk.
82 | * Stable - This feature has existed for a full release cycle and has been thoroughly tested. These features are considered safe for use in production environments.
83 | * Deprecated - This feature is being removed or replaced. As with experimental features, these features could be removed at any time and their use in production environments is at your own risk. For features being replaced, it is recommended to update to the next version and begin using the new feature.
84 |
85 | ## Library Dependencies
86 | - - -
87 |
88 | Some parts of AeroGear.js depend on external libraries which are not bundled in the same file. Below is a list of each plugin and their adapters along with external dependencies, if they have any. It is recommended to use the latest stable version of each dependency unless otherwise noted.
89 |
90 | ### Crypto
91 | * [SJCL](https://github.com/bitwiseshiftleft/sjcl) - bundled w/ AeroGear.js
92 |
93 | ### DataManager
94 |
95 | * **Memory**
96 | * [ES6 Promise polyfill](https://github.com/jakearchibald/es6-promise)
97 | * **SessionLocal**
98 | * [ES6 Promise polyfill](https://github.com/jakearchibald/es6-promise)
99 | * **IndexedDB**
100 | * [ES6 Promise polyfill](https://github.com/jakearchibald/es6-promise)
101 | * **WebSQL**
102 | * [ES6 Promise polyfill](https://github.com/jakearchibald/es6-promise)
103 |
104 | ### Notifier
105 |
106 | * **STOMP-WS**
107 | * [STOMP Over WebSocket](https://github.com/jmesnil/stomp-websocket/)
108 | * **vert.x**
109 | * [vert.x Event Bus](http://vertx.io/downloads.html)
110 | * [SockJS](http://cdn.sockjs.org/)
111 | * **MQTT-WS**
112 | * [Eclipse Paho MQTT JavaScript Client](http://download.eclipse.org/paho/1.0/paho.javascript-1.0.0.zip)
113 | * **SimplePush**
114 | * See SimplePush Plugin
115 |
116 | ### SimplePush
117 | * [jQuery](http://jquery.com/download/)
118 | * [SockJS](http://cdn.sockjs.org/)
119 |
120 | ### UnifiedPush
121 | * [ES6 Promise polyfill](https://github.com/jakearchibald/es6-promise)
122 |
123 | ### Diff Sync
124 | * **Diff Match Patch**
125 | * [Google Diff Match Patch](https://code.google.com/p/google-diff-match-patch/)
126 |
127 | * **JSON Patch**
128 | * [JSON Patch](https://github.com/Starcounter-Jack/JSON-Patch)
129 |
130 | ## Building
131 | - - -
132 |
133 | ### Grunt
134 |
135 | [Grunt](http://gruntjs.com/) is used as the build tool which requires [Node.js](http://nodejs.org/) version >= 0.10.
136 | Please refer to [nodejs.org](http://nodejs.org) for details regarding installing Node.js.
137 | Please refer to Grunt's [getting started](http://gruntjs.com/getting-started) guide for details regarding installing Grunt.
138 |
139 | ### Installing Build Dependencies
140 | To install the dependencies of the project run the following command:
141 |
142 | $ npm install
143 |
144 | This will install the versions of the dependencies declared in package.json. This is only required to be done once before
145 | building the first time, or if the dependencies in package.json have been updated.
146 |
147 | ### Building the project
148 |
149 | $ grunt
150 |
151 | The produced JavaScript will be in the __dist__ directory.
152 |
153 | ### Custom Build
154 |
155 | There is a special grunt task called, `custom` to help create custom builds of the library.
156 |
157 | The custom task takes a comma delimited list of "modules".
158 |
159 | For example, if you wanted a build with Authorization/OAuth2 and the SimplePushClient, you would do
160 |
161 | $ grunt custom:oauth2,simplePush
162 |
163 | The produced JavaScript will be in the __dist__ directory as __aerogear.custom.js__.
164 |
165 | For usage and a list of available "modules" run,
166 |
167 | $ grunt custom:help
168 |
169 | ### Generating the documentation
170 | To generate the API docs, run the following command:
171 |
172 | $ jsdoc-aerogear src/ -r -d docs README.md
173 |
174 | or by running the grunt `docs` task
175 |
176 | $ grunt docs
177 |
178 | _The docs use a slightly modified version of jsdoc_
179 |
180 | ## Documentation
181 |
182 | For more details about the current release, please consult [our documentation](https://aerogear.org/docs/specs/aerogear-js/).
183 |
184 | ## Development
185 |
186 | If you would like to help develop AeroGear you can join our [developer's mailing list](https://lists.jboss.org/mailman/listinfo/aerogear-dev), join #aerogear on Freenode, or shout at us on Twitter @aerogears.
187 |
188 | Also takes some time and skim the [contributor guide](http://aerogear.org/docs/guides/Contributing/)
189 |
190 | ## Questions?
191 |
192 | Join our [user mailing list](https://lists.jboss.org/mailman/listinfo/aerogear-users) for any questions or help! We really hope you enjoy app development with AeroGear!
193 |
194 | ## Found a bug?
195 |
196 | If you found a bug please create a ticket for us on [Jira](https://issues.jboss.org/browse/AGJS) with some steps to reproduce it.
197 |
--------------------------------------------------------------------------------
/custom_build_help.txt:
--------------------------------------------------------------------------------
1 | A task to create custom builds of the library based on the 'concat' task
2 |
3 | Usage:
4 | grunt custom:[ task[,task...] ] - create a custom build
5 |
6 | grunt custom:help - Show this help
7 |
8 |
9 | Example: A custom build containing IndexedDB Adapter
10 |
11 | grunt custom:dataManagerIndexedDB
12 |
13 | ----------------------------------------------------------------------------
14 |
15 | Below is a listing of the available modules:
16 |
--------------------------------------------------------------------------------
/external/crypto/LICENSE:
--------------------------------------------------------------------------------
1 | SJCL is open. You can use, modify and redistribute it under a BSD license or under the GNU GPL, version 2.0 or higher.
2 | http://bitwiseshiftleft.github.io/sjcl/
3 |
--------------------------------------------------------------------------------
/external/uuid/license.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2012 Robert Kieffer
2 | MIT License - http://opensource.org/licenses/mit-license.php
--------------------------------------------------------------------------------
/external/uuid/uuid.js:
--------------------------------------------------------------------------------
1 | // node-uuid/uuid.js
2 | //
3 | // Copyright (c) 2010 Robert Kieffer
4 | // Dual licensed under the MIT and GPL licenses.
5 | // Documentation and details at https://github.com/broofa/node-uuid
6 | (function() {
7 | var _global = this;
8 |
9 | // Unique ID creation requires a high quality random # generator, but
10 | // Math.random() does not guarantee "cryptographic quality". So we feature
11 | // detect for more robust APIs, normalizing each method to return 128-bits
12 | // (16 bytes) of random data.
13 | var mathRNG, nodeRNG, whatwgRNG;
14 |
15 | // Math.random()-based RNG. All platforms, very fast, unknown quality
16 | var _rndBytes = new Array(16);
17 | mathRNG = function() {
18 | var r, b = _rndBytes, i = 0;
19 |
20 | for (var i = 0, r; i < 16; i++) {
21 | if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
22 | b[i] = r >>> ((i & 0x03) << 3) & 0xff;
23 | }
24 |
25 | return b;
26 | }
27 |
28 | // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
29 | // WebKit only (currently), moderately fast, high quality
30 | if (_global.crypto && crypto.getRandomValues) {
31 | var _rnds = new Uint32Array(4);
32 | whatwgRNG = function() {
33 | crypto.getRandomValues(_rnds);
34 |
35 | for (var c = 0 ; c < 16; c++) {
36 | _rndBytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff;
37 | }
38 | return _rndBytes;
39 | }
40 | }
41 |
42 | // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
43 | // Node.js only, moderately fast, high quality
44 | try {
45 | var _rb = require('crypto').randomBytes;
46 | nodeRNG = _rb && function() {
47 | return _rb(16);
48 | };
49 | } catch (e) {}
50 |
51 | // Select RNG with best quality
52 | var _rng = nodeRNG || whatwgRNG || mathRNG;
53 |
54 | // Buffer class to use
55 | var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
56 |
57 | // Maps for number <-> hex string conversion
58 | var _byteToHex = [];
59 | var _hexToByte = {};
60 | for (var i = 0; i < 256; i++) {
61 | _byteToHex[i] = (i + 0x100).toString(16).substr(1);
62 | _hexToByte[_byteToHex[i]] = i;
63 | }
64 |
65 | // **`parse()` - Parse a UUID into it's component bytes**
66 | function parse(s, buf, offset) {
67 | var i = (buf && offset) || 0, ii = 0;
68 |
69 | buf = buf || [];
70 | s.toLowerCase().replace(/[0-9a-f]{2}/g, function(byte) {
71 | if (ii < 16) { // Don't overflow!
72 | buf[i + ii++] = _hexToByte[byte];
73 | }
74 | });
75 |
76 | // Zero out remaining bytes if string was short
77 | while (ii < 16) {
78 | buf[i + ii++] = 0;
79 | }
80 |
81 | return buf;
82 | }
83 |
84 | // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
85 | function unparse(buf, offset) {
86 | var i = offset || 0, bth = _byteToHex;
87 | return bth[buf[i++]] + bth[buf[i++]] +
88 | bth[buf[i++]] + bth[buf[i++]] + '-' +
89 | bth[buf[i++]] + bth[buf[i++]] + '-' +
90 | bth[buf[i++]] + bth[buf[i++]] + '-' +
91 | bth[buf[i++]] + bth[buf[i++]] + '-' +
92 | bth[buf[i++]] + bth[buf[i++]] +
93 | bth[buf[i++]] + bth[buf[i++]] +
94 | bth[buf[i++]] + bth[buf[i++]];
95 | }
96 |
97 | // **`v1()` - Generate time-based UUID**
98 | //
99 | // Inspired by https://github.com/LiosK/UUID.js
100 | // and http://docs.python.org/library/uuid.html
101 |
102 | // random #'s we need to init node and clockseq
103 | var _seedBytes = _rng();
104 |
105 | // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
106 | var _nodeId = [
107 | _seedBytes[0] | 0x01,
108 | _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
109 | ];
110 |
111 | // Per 4.2.2, randomize (14 bit) clockseq
112 | var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
113 |
114 | // Previous uuid creation time
115 | var _lastMSecs = 0, _lastNSecs = 0;
116 |
117 | // See https://github.com/broofa/node-uuid for API details
118 | function v1(options, buf, offset) {
119 | var i = buf && offset || 0;
120 | var b = buf || [];
121 |
122 | options = options || {};
123 |
124 | var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
125 |
126 | // UUID timestamps are 100 nano-second units since the Gregorian epoch,
127 | // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
128 | // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
129 | // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
130 | var msecs = options.msecs != null ? options.msecs : new Date().getTime();
131 |
132 | // Per 4.2.1.2, use count of uuid's generated during the current clock
133 | // cycle to simulate higher resolution clock
134 | var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
135 |
136 | // Time since last uuid creation (in msecs)
137 | var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
138 |
139 | // Per 4.2.1.2, Bump clockseq on clock regression
140 | if (dt < 0 && options.clockseq == null) {
141 | clockseq = clockseq + 1 & 0x3fff;
142 | }
143 |
144 | // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
145 | // time interval
146 | if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
147 | nsecs = 0;
148 | }
149 |
150 | // Per 4.2.1.2 Throw error if too many uuids are requested
151 | if (nsecs >= 10000) {
152 | throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
153 | }
154 |
155 | _lastMSecs = msecs;
156 | _lastNSecs = nsecs;
157 | _clockseq = clockseq;
158 |
159 | // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
160 | msecs += 12219292800000;
161 |
162 | // `time_low`
163 | var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
164 | b[i++] = tl >>> 24 & 0xff;
165 | b[i++] = tl >>> 16 & 0xff;
166 | b[i++] = tl >>> 8 & 0xff;
167 | b[i++] = tl & 0xff;
168 |
169 | // `time_mid`
170 | var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
171 | b[i++] = tmh >>> 8 & 0xff;
172 | b[i++] = tmh & 0xff;
173 |
174 | // `time_high_and_version`
175 | b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
176 | b[i++] = tmh >>> 16 & 0xff;
177 |
178 | // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
179 | b[i++] = clockseq >>> 8 | 0x80;
180 |
181 | // `clock_seq_low`
182 | b[i++] = clockseq & 0xff;
183 |
184 | // `node`
185 | var node = options.node || _nodeId;
186 | for (var n = 0; n < 6; n++) {
187 | b[i + n] = node[n];
188 | }
189 |
190 | return buf ? buf : unparse(b);
191 | }
192 |
193 | // **`v4()` - Generate random UUID**
194 |
195 | // See https://github.com/broofa/node-uuid for API details
196 | function v4(options, buf, offset) {
197 | // Deprecated - 'format' argument, as supported in v1.2
198 | var i = buf && offset || 0;
199 |
200 | if (typeof(options) == 'string') {
201 | buf = options == 'binary' ? new BufferClass(16) : null;
202 | options = null;
203 | }
204 | options = options || {};
205 |
206 | var rnds = options.random || (options.rng || _rng)();
207 |
208 | // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
209 | rnds[6] = (rnds[6] & 0x0f) | 0x40;
210 | rnds[8] = (rnds[8] & 0x3f) | 0x80;
211 |
212 | // Copy bytes to buffer, if provided
213 | if (buf) {
214 | for (var ii = 0; ii < 16; ii++) {
215 | buf[i + ii] = rnds[ii];
216 | }
217 | }
218 |
219 | return buf || unparse(rnds);
220 | }
221 |
222 | // Export public API
223 | var uuid = v4;
224 | uuid.v1 = v1;
225 | uuid.v4 = v4;
226 | uuid.parse = parse;
227 | uuid.unparse = unparse;
228 | uuid.BufferClass = BufferClass;
229 |
230 | // Export RNG options
231 | uuid.mathRNG = mathRNG;
232 | uuid.nodeRNG = nodeRNG;
233 | uuid.whatwgRNG = whatwgRNG;
234 |
235 | // Play nice with browsers
236 | var _previousRoot = _global.uuid;
237 |
238 | // **`noConflict()` - (browser only) to reset global 'uuid' var**
239 | uuid.noConflict = function() {
240 | _global.uuid = _previousRoot;
241 | return uuid;
242 | }
243 | _global.uuid = uuid;
244 | }());
245 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aerogear",
3 | "title": "AeroGear JavaScript Library",
4 | "description": "Provides a lightweight set of utilities for communication, security, storage and more.",
5 | "version": "2.2.0-dev",
6 | "homepage": "https://github.com/aerogear/aerogear-js",
7 | "author": {
8 | "name": "Red Hat, Inc.",
9 | "url": "http://aerogear.org"
10 | },
11 | "maintainers": {
12 | "name": "Lucas Holmquist",
13 | "email": "lholmqui@redhat.com"
14 | },
15 | "contributors": [
16 | {
17 | "name": "Kris Borchers",
18 | "url": "http://twitter.com/kborchers"
19 | },
20 | {
21 | "name": "Lucas Holmquist",
22 | "url": "http://twitter.com/sienaluke"
23 | },
24 | {
25 | "name": "Bruno Oliveira",
26 | "url": "http://twitter.com/abstractj"
27 | },
28 | {
29 | "name": "Matthias Wessendorf",
30 | "url": "http://twitter.com/mwessendorf"
31 | },
32 | {
33 | "name": "Daniel Bevenius",
34 | "url": "http://twitter.com/dbevenius"
35 | },
36 | {
37 | "name": "Douglas Campos",
38 | "url": "http://twitter.com/qmx"
39 | },
40 | {
41 | "name": "Sebastien Blanc",
42 | "url": "http://twitter.com/sebi2706"
43 | },
44 | {
45 | "name": "Jay Balunas",
46 | "url": "http://twitter.com/tech4j"
47 | },
48 | {
49 | "name": "Christos Vasilakis",
50 | "url": "http://twitter.com/cvasilak"
51 | },
52 | {
53 | "name": "Yavuz Yilmaz",
54 | "url": "https://github.com/yavuzsel"
55 | },
56 | {
57 | "name": "Tolis Emmanouilidis",
58 | "url": "https://twitter.com/tolis_e"
59 | },
60 | {
61 | "name": "Lukáš Fryč",
62 | "url": "https://twitter.com/lfryc"
63 | }
64 | ],
65 | "repository": {
66 | "type": "git",
67 | "url": "aerogear/aerogear-js.git"
68 | },
69 | "bugs": {
70 | "url": "https://issues.jboss.org/browse/AGJS"
71 | },
72 | "licenses": [
73 | {
74 | "type": "Apache-2.0",
75 | "url": "http://www.apache.org/licenses/LICENSE-2.0"
76 | }
77 | ],
78 | "keywords": [],
79 | "devDependencies": {
80 | "grunt": "~0.4.1",
81 | "grunt-cli": "~0.1.13",
82 | "grunt-contrib-concat": "~0.1.2",
83 | "grunt-contrib-jshint": "~0.10.0",
84 | "grunt-contrib-qunit": "~0.5.2",
85 | "grunt-contrib-uglify": "~0.6.0",
86 | "grunt-contrib-watch": "~0.6.1",
87 | "grunt-shell": "0.3.1",
88 | "jsdoc-aerogear": "~3.2.0-dev",
89 | "lodash": "~2.4.1",
90 | "request": "~2.27.0",
91 | "shelljs": "^0.3.0"
92 | },
93 | "scripts": {
94 | "test": "grunt travis --verbose"
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/aerogear.core.js:
--------------------------------------------------------------------------------
1 | /* AeroGear JavaScript Library
2 | * https://github.com/aerogear/aerogear-js
3 | * JBoss, Home of Professional Open Source
4 | * Copyright Red Hat, Inc., and individual contributors
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | The AeroGear namespace provides a way to encapsulate the library's properties and methods away from the global namespace
18 | @namespace
19 | */
20 | this.AeroGear = {};
21 |
22 | /**
23 | AeroGear.Core is a base for all of the library modules to extend. It is not to be instantiated and will throw an error when attempted
24 | @class
25 | @private
26 | */
27 | AeroGear.Core = function() {
28 | // Prevent instantiation of this base class
29 | if ( this instanceof AeroGear.Core ) {
30 | throw "Invalid instantiation of base class AeroGear.Core";
31 | }
32 |
33 | /**
34 | This function is used by the different parts of AeroGear to add a new Object to its respective collection.
35 | @name AeroGear.add
36 | @method
37 | @param {String|Array|Object} config - This can be a variety of types specifying how to create the object. See the particular constructor for the object calling .add for more info.
38 | @returns {Object} The object containing the collection that was updated
39 | */
40 | this.add = function( config ) {
41 | var i,
42 | current,
43 | collection = this[ this.collectionName ] || {};
44 | this[ this.collectionName ] = collection;
45 |
46 | if ( !config ) {
47 | return this;
48 | } else if ( typeof config === "string" ) {
49 | // config is a string so use default adapter type
50 | collection[ config ] = AeroGear[ this.lib ].adapters[ this.type ]( config, this.config );
51 | } else if ( Array.isArray( config ) ) {
52 | // config is an array so loop through each item in the array
53 | for ( i = 0; i < config.length; i++ ) {
54 | current = config[ i ];
55 |
56 | if ( typeof current === "string" ) {
57 | collection[ current ] = AeroGear[ this.lib ].adapters[ this.type ]( current, this.config );
58 | } else {
59 | if( current.name ) {
60 |
61 | // Merge the Module( authz, datamanger, ... )config with the adapters settings
62 | current.settings = AeroGear.extend( current.settings || {}, this.config );
63 |
64 | collection[ current.name ] = AeroGear[ this.lib ].adapters[ current.type || this.type ]( current.name, current.settings );
65 | }
66 | }
67 | }
68 | } else {
69 | if( !config.name ) {
70 | return this;
71 | }
72 |
73 | // Merge the Module( authz, datamanger, ... )config with the adapters settings
74 | // config is an object so use that signature
75 | config.settings = AeroGear.extend( config.settings || {}, this.config );
76 |
77 | collection[ config.name ] = AeroGear[ this.lib ].adapters[ config.type || this.type ]( config.name, config.settings );
78 | }
79 |
80 | // reset the collection instance
81 | this[ this.collectionName ] = collection;
82 |
83 | return this;
84 | };
85 | /**
86 | This function is used internally by datamanager, etc. to remove an Object (store, etc.) from the respective collection.
87 | @name AeroGear.remove
88 | @method
89 | @param {String|String[]|Object[]|Object} config - This can be a variety of types specifying how to remove the object. See the particular constructor for the object calling .remove for more info.
90 | @returns {Object} The object containing the collection that was updated
91 | */
92 | this.remove = function( config ) {
93 | var i,
94 | current,
95 | collection = this[ this.collectionName ] || {};
96 |
97 | if ( typeof config === "string" ) {
98 | // config is a string so delete that item by name
99 | delete collection[ config ];
100 | } else if ( Array.isArray( config ) ) {
101 | // config is an array so loop through each item in the array
102 | for ( i = 0; i < config.length; i++ ) {
103 | current = config[ i ];
104 |
105 | if ( typeof current === "string" ) {
106 | delete collection[ current ];
107 | } else {
108 | delete collection[ current.name ];
109 | }
110 | }
111 | } else if ( config ) {
112 | // config is an object so use that signature
113 | delete collection[ config.name ];
114 | }
115 |
116 | // reset the collection instance
117 | this[ this.collectionName ] = collection;
118 |
119 | return this;
120 | };
121 | };
122 |
123 | /**
124 | Utility function to merge many Objects in one target Object which is the first object in arguments list.
125 | @private
126 | @method
127 | */
128 | AeroGear.extend = function() {
129 | var name, i, source,
130 | target = arguments[ 0 ];
131 | for( i=1; i 0 ) {
81 | patchMsg.edits = pendingEdits.concat( patchMsg.edits );
82 | }
83 |
84 | return patchMsg;
85 | };
86 |
87 | /**
88 | * Performs the client side patch process.
89 | *
90 | * @param patchMsg the patch message that is sent from the server
91 | *
92 | * @example:
93 | * {
94 | * "msgType":"patch",
95 | * "id":"12345",
96 | * "clientId":"3346dff7-aada-4d5f-a3da-c93ff0ffc472",
97 | * "edits":[{
98 | * "clientVersion":0,
99 | * "serverVersion":0,
100 | * "checksum":"5f9844b21c298ea1f3ed7bf37f96e42df03395b",
101 | * "diffs":[
102 | * {"operation":"UNCHANGED","text":"I'm a Je"},
103 | * {"operation":"DELETE","text":"di"}]
104 | * }]
105 | * }
106 | */
107 | this.patch = function( patchMsg ) {
108 | // Flow is based on the server side
109 | // patch the shadow
110 | var patchedShadow = this.patchShadow( patchMsg );
111 | // Then patch the document
112 | this.patchDocument( patchedShadow );
113 | // then save backup shadow
114 | this._saveShadowBackup( patchedShadow, patchedShadow.clientVersion );
115 |
116 | };
117 |
118 | this.patchShadow = function( patchMsg ) {
119 | // First get the shadow document for this doc.id and clientId
120 | var i, patched, edit,
121 | shadow = this.getShadow( patchMsg.id ),
122 | edits = patchMsg.edits;
123 | //Iterate over the edits of the doc
124 | for ( i = 0; i < edits.length; i++ ) {
125 | edit = edits[i];
126 |
127 | //Check for dropped packets?
128 | // edit.clientVersion < shadow.ClientVersion
129 | if( edit.clientVersion < shadow.clientVersion && !this._isSeeded( edit ) ) {
130 | // Dropped packet? // restore from back
131 | shadow = this._restoreBackup( shadow, edit );
132 | continue;
133 | }
134 |
135 | //check if we already have this one
136 | // IF SO discard the edit
137 | // edit.serverVersion < shadow.ServerVesion
138 | if( edit.serverVersion < shadow.serverVersion ) {
139 | // discard edit
140 | this._removeEdit( patchMsg.id, edit );
141 | continue;
142 | }
143 |
144 | //make sure the versions match
145 | if( (edit.serverVersion === shadow.serverVersion && edit.clientVersion === shadow.clientVersion) || this._isSeeded( edit )) {
146 | // Good , Patch the shadow
147 | this.applyEditsToShadow( edit, shadow );
148 | if ( this._isSeeded( edit ) ) {
149 | shadow.clientVersion = 0;
150 | } else if ( edit.clientVersion >= 0 ) {
151 | shadow.serverVersion++;
152 | }
153 | this._saveShadow( shadow );
154 | this._removeEdit( patchMsg.id, edit );
155 | }
156 | }
157 |
158 | return shadow;
159 | };
160 |
161 | // A seeded patch is when all clients start with a base document. They all send this base version as
162 | // part of the addDocument call. The server will respond with a patchMsg enabling the client to
163 | // patch it's local version to get the latest updates. Such an edit is identified by a clientVersion
164 | // set to '-1'.
165 | this._isSeeded = function( edit ) {
166 | return edit.clientVersion === -1;
167 | };
168 |
169 | this.applyEditsToShadow = function ( edits, shadow ) {
170 | var patchResult;
171 | // returns true or false, should probably do something with it?
172 | patchResult = jsonpatch.apply( shadow.content, edits.diffs );
173 | return shadow;
174 | };
175 |
176 | this.patchDocument = function( shadow ) {
177 | var doc, diffs, patch;
178 |
179 | // first get the document based on the shadowdocs ID
180 | doc = this.getDocument( shadow.id );
181 |
182 | diffs = jsonpatch.compare( doc.content, shadow.content );
183 |
184 | patch = jsonpatch.apply( doc.content, diffs );
185 |
186 | //save the newly patched document, do we save if the apply failed?
187 | this._saveDocument( doc );
188 |
189 | return patch;
190 | };
191 |
192 | this._saveData = function( data, type ) {
193 | data = Array.isArray( data ) ? data : [ data ];
194 |
195 | stores[ type ] = data;
196 | };
197 |
198 | this._readData = function( id, type ) {
199 | return stores[ type ].filter( function( doc ) {
200 | return doc.id === id;
201 | });
202 | };
203 |
204 | this._saveDocument = function( doc ) {
205 | this._saveData( doc, "docs" );
206 | return doc;
207 | };
208 |
209 | this._saveShadow = function( doc ) {
210 | var shadow = {
211 | id: doc.id,
212 | serverVersion: doc.serverVersion || 0,
213 | clientId: doc.clientId,
214 | clientVersion: doc.clientVersion || 0,
215 | content: doc.content
216 | };
217 |
218 | this._saveData( shadow, "shadows" );
219 | return shadow;
220 | };
221 |
222 | this._saveShadowBackup = function( shadow, clientVersion ) {
223 | var backup = { id: shadow.id, clientVersion: clientVersion, content: shadow.content };
224 | this._saveData( backup, "backups" );
225 | return backup;
226 | };
227 |
228 | this.getDocument = function( id ) {
229 | return this._readData( id, "docs" )[ 0 ];
230 | };
231 |
232 | this.getShadow = function( id ) {
233 | return this._readData( id, "shadows" )[ 0 ];
234 | };
235 |
236 | this.getBackup = function( id ) {
237 | return this._readData( id, "backups" )[ 0 ];
238 | };
239 |
240 | this._saveEdits = function( patchMsg ) {
241 | var record = { id: patchMsg.id, clientId: patchMsg.clientId, edits: patchMsg.edits};
242 | this._saveData( record, "edits" );
243 | return record;
244 | };
245 |
246 | this._getEdits = function( id ) {
247 | var patchMessages = this._readData( id, "edits" );
248 |
249 | return patchMessages.length ? patchMessages.edits : [];
250 | };
251 |
252 | this._removeEdit = function( documentId, edit ) {
253 | var pendingEdits = this._readData( documentId, "edits" ), i, j, pendingEdit;
254 | for ( i = 0; i < pendingEdits.length; i++ ) {
255 | pendingEdit = pendingEdits[i];
256 | for ( j = 0; j < pendingEdit.edits.length; j++) {
257 | if ( pendingEdit.edits[j].clientVersion <= edit.clientVersion) {
258 | pendingEdit.edits.splice(i, 1);
259 | break;
260 | }
261 | }
262 | }
263 | };
264 |
265 | this._removeEdits = function( documentId ) {
266 | var edits = this._readData( documentId, "edits" ), i;
267 | edits.splice(0, edits.length);
268 | };
269 |
270 | this._restoreBackup = function( shadow, edit) {
271 | var patchedShadow, restoredBackup,
272 | backup = this.getBackup( shadow.id );
273 |
274 | if ( edit.clientVersion === backup.clientVersion ) {
275 |
276 | restoredBackup = {
277 | id: backup.id,
278 | clientVersion: backup.clientVersion,
279 | content: backup.content
280 | };
281 |
282 | patchedShadow = this.applyEditsToShadow( edit, restoredBackup );
283 | restoredBackup.serverVersion++;
284 | this._removeEdits( shadow.id );
285 |
286 | return this._saveShadow( patchedShadow );
287 | } else {
288 | throw "Edit's clientVersion '" + edit.clientVersion + "' does not match the backups clientVersion '" + backup.clientVersion + "'";
289 | }
290 | };
291 | };
292 |
--------------------------------------------------------------------------------
/src/notifier/adapters/base.js:
--------------------------------------------------------------------------------
1 | /* AeroGear JavaScript Library
2 | * https://github.com/aerogear/aerogear-js
3 | * JBoss, Home of Professional Open Source
4 | * Copyright Red Hat, Inc., and individual contributors
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | The Base Notifier adapter that all other Notifier adapters( except SimplePush ) will extend from.
18 | Not to be Instantiated directly
19 | */
20 |
21 | AeroGear.Notifier.adapters.base = function( clientName, settings ) {
22 | if ( this instanceof AeroGear.Notifier.adapters.base ) {
23 | throw "Invalid instantiation of base class AeroGear.Notifier.adapters.base";
24 | }
25 |
26 | settings = settings || {};
27 |
28 | var connectURL = settings.connectURL || "",
29 | channels = settings.channels || [],
30 | autoConnect = !!settings.autoConnect || channels.length,
31 | state = AeroGear.Notifier.CONNECTING,
32 | name = clientName,
33 | client = null;
34 |
35 | // Privileged methods
36 | /**
37 | Returns the value of the private connectURL var
38 | @private
39 | @augments AeroGear.Notifier.adapters.base
40 | */
41 | this.getConnectURL = function() {
42 | return connectURL;
43 | };
44 |
45 | /**
46 | Set the value of the private connectURL var
47 | @private
48 | @augments AeroGear.Notifier.adapters.base
49 | @param {String} url - New connectURL for this client
50 | */
51 | this.setConnectURL = function( url ) {
52 | connectURL = url;
53 | };
54 |
55 | /**
56 | Returns the value of the private channels var
57 | @private
58 | @augments AeroGear.Notifier.adapters.base
59 | */
60 | this.getChannels = function() {
61 | return channels;
62 | };
63 |
64 | /**
65 | Adds a channel to the set
66 | @param {Object} channel - The channel object to add to the set
67 | @private
68 | @augments AeroGear.Notifier.adapters.base
69 | */
70 | this.addChannel = function( channel ) {
71 | channels.push( channel );
72 | };
73 |
74 | /**
75 | Check if subscribed to a channel
76 | @param {String} address - The address of the channel object to search for in the set
77 | @private
78 | @augments AeroGear.Notifier.adapters.base
79 | */
80 | this.getChannelIndex = function( address ) {
81 | for ( var i = 0; i < channels.length; i++ ) {
82 | if ( channels[ i ].address === address ) {
83 | return i;
84 | }
85 | }
86 | return -1;
87 | };
88 |
89 | /**
90 | Removes a channel from the set
91 | @param {Object} channel - The channel object to remove from the set
92 | @private
93 | @augments AeroGear.Notifier.adapters.base
94 | */
95 | this.removeChannel = function( channel ) {
96 | var index = this.getChannelIndex( channel.address );
97 | if ( index >= 0 ) {
98 | channels.splice( index, 1 );
99 | }
100 | };
101 |
102 | /**
103 | Returns the value of the private state var
104 | @private
105 | @augments AeroGear.Notifier.adapters.base
106 | */
107 | this.getState = function() {
108 | return state;
109 | };
110 |
111 | /**
112 | Sets the value of the private state var
113 | @private
114 | @augments AeroGear.Notifier.adapters.base
115 | */
116 | this.setState = function( newState ) {
117 | state = newState;
118 | };
119 |
120 | /**
121 | Returns the value of the private client var
122 | @private
123 | @augments AeroGear.Notifier.adapters.base
124 | */
125 | this.getClient = function() {
126 | return client;
127 | };
128 |
129 | /**
130 | Sets the value of the private client var
131 | @private
132 | @augments AeroGear.Notifier.adapters.base
133 | */
134 | this.setClient = function( newClient ) {
135 | client = newClient;
136 | };
137 |
138 | // Handle auto-connect.
139 | // for stompws ONLY - If Login or Password are needed, autoConnect won't happen
140 | if ( ( autoConnect || channels.length ) && ( !settings.login && !settings.password ) ) {
141 | this.connect({
142 | url: connectURL,
143 | onConnect: settings.onConnect,
144 | onDisconnect: settings.onDisconnect, // for Vertx
145 | onConnectError: settings.onConnectError,
146 | onMessage: settings.onMessage // for mqttws
147 | });
148 | }
149 | };
150 |
--------------------------------------------------------------------------------
/src/notifier/aerogear.notifier.js:
--------------------------------------------------------------------------------
1 | /* AeroGear JavaScript Library
2 | * https://github.com/aerogear/aerogear-js
3 | * JBoss, Home of Professional Open Source
4 | * Copyright Red Hat, Inc., and individual contributors
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | The AeroGear.Notifier namespace provides a messaging API. Through the use of adapters, this library provides common methods like connect, disconnect, subscribe, unsubscribe and publish.
18 | @deprecated since 2.1.0 and will be removed in a future release.
19 | @status Deprecated
20 | @class
21 | @augments AeroGear.Core
22 | @param {String|Array|Object} [config] - A configuration for the client(s) being created along with the notifier. If an object or array containing objects is used, the objects can have the following properties:
23 | @param {String} config.name - the name that the client will later be referenced by
24 | @param {String} [config.type="vertx"] - the type of client as determined by the adapter used
25 | @param {Object} [config.settings={}] - the settings to be passed to the adapter
26 | @returns {Object} The created notifier containing any messaging clients that may have been created
27 | @example
28 | // Create an empty notifier
29 | var notifier = AeroGear.Notifier();
30 |
31 | // Create a single client using the default adapter
32 | var notifier2 = AeroGear.Notifier( "myNotifier" );
33 |
34 | // Create multiple clients using the default adapter
35 | var notifier3 = AeroGear.Notifier( [ "someNotifier", "anotherNotifier" ] );
36 |
37 | // Create a default adapter with settings
38 | var notifier4 = AeroGear.Notifier({
39 | name: "vertxNotifier",
40 | type: "vertx",
41 | settings: { ... }
42 | });
43 |
44 | // Create a stompws adapter with settings
45 | var notifier5 = AeroGear.Notifier({
46 | name: "STOMPNotifier",
47 | type: "stompws",
48 | settings: { ... }
49 | });
50 |
51 | // Create a vertx and stompws adapter with settings
52 | var notifier6 = AeroGear.Notifier([
53 | {
54 | name: "vertxNotifier",
55 | type: "vertx",
56 | settings: { ... }
57 | },
58 | {
59 | name: "STOMPNotifier",
60 | type: "stompws",
61 | settings: { ... }
62 | }
63 | ]);
64 | */
65 | AeroGear.Notifier = function( config ) {
66 | // Allow instantiation without using new
67 | if ( !( this instanceof AeroGear.Notifier ) ) {
68 | return new AeroGear.Notifier( config );
69 | }
70 | // Super Constructor
71 | AeroGear.Core.call( this );
72 |
73 | this.lib = "Notifier";
74 | this.type = config ? config.type || "vertx" : "vertx";
75 |
76 | /**
77 | The name used to reference the collection of notifier client instances created from the adapters
78 | @memberOf AeroGear.Notifier
79 | @type Object
80 | @default modules
81 | */
82 | this.collectionName = "clients";
83 |
84 | this.add( config );
85 | };
86 |
87 | AeroGear.Notifier.prototype = AeroGear.Core;
88 | AeroGear.Notifier.constructor = AeroGear.Notifier;
89 |
90 | /**
91 | The adapters object is provided so that adapters can be added to the AeroGear.Notifier namespace dynamically and still be accessible to the add method
92 | @augments AeroGear.Notifier
93 | */
94 | AeroGear.Notifier.adapters = {};
95 |
96 | /**
97 | A set of constants used to track the state of a client connection.
98 | */
99 | AeroGear.Notifier.CONNECTING = 0;
100 | AeroGear.Notifier.CONNECTED = 1;
101 | AeroGear.Notifier.DISCONNECTING = 2;
102 | AeroGear.Notifier.DISCONNECTED = 3;
103 |
--------------------------------------------------------------------------------
/src/simplepush/aerogear.simplepush.js:
--------------------------------------------------------------------------------
1 | /* AeroGear JavaScript Library
2 | * https://github.com/aerogear/aerogear-js
3 | * JBoss, Home of Professional Open Source
4 | * Copyright Red Hat, Inc., and individual contributors
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | (function( AeroGear, $, undefined ) {
17 | /**
18 | The SimplePushClient object is used as a sort of polyfill/implementation of the SimplePush spec implemented in Firefox OS and the Firefox browser and provides a mechanism for subscribing to and acting on push notifications in a web application. See https://wiki.mozilla.org/WebAPI/SimplePush
19 | @status Experimental
20 | @constructs AeroGear.SimplePushClient
21 | @param {Object} options - an object used to initialize the connection to the SimplePush server
22 | @param {Boolean} [options.useNative=false] - if true, the connection will first try to use the Mozilla push network (still in development and not ready for production) before falling back to the SimplePush server specified
23 | @param {String} [options.simplePushServerURL] - the URL of the SimplePush server. This option is optional but only if you don't want to support browsers that are missing websocket support and you trust the not yet production ready Mozilla push server.
24 | @param {Function} options.onConnect - a callback to fire when a connection is established with the SimplePush server. This is a deviation from the SimplePush spec as it is not necessary when you using the in browser functionality since the browser establishes the connection before the application is started.
25 | @param {Function} options.onClose - a callback to fire when a connection to the SimplePush server is closed or lost.
26 | @returns {Object} The created unified push server client
27 | @example
28 | // Create the SimplePushClient object:
29 | var client = AeroGear.SimplePushClient({
30 | simplePushServerURL: "https://localhost:7777/simplepush",
31 | onConnect: myConnectCallback,
32 | onClose: myCloseCallback
33 | });
34 | */
35 | AeroGear.SimplePushClient = function( options ) {
36 | // Allow instantiation without using new
37 | if ( !( this instanceof AeroGear.SimplePushClient ) ) {
38 | return new AeroGear.SimplePushClient( options );
39 | }
40 |
41 | this.options = options || {};
42 |
43 | // Check for native push support
44 | if ( !!navigator.push && this.options.useNative ) {
45 | // Browser supports push so let it handle it
46 | if ( options.onConnect ) {
47 | options.onConnect();
48 | }
49 | return;
50 | }
51 |
52 | if ( this.options.useNative ) {
53 | if ("WebSocket" in window ) {
54 | // No native push support but want to use Mozilla servers
55 | this.options.simplePushServerURL = "wss://push.services.mozilla.com";
56 | } else if ( !this.options.simplePushServerURL ) {
57 | // No native push support and no websocket support so can't talk to Mozilla server
58 | throw "SimplePushConfigurationError";
59 | } else {
60 | // No websocket, no native support but SimplePush server specified so try SockJS connection
61 | this.options.useNative = false;
62 | }
63 | }
64 |
65 | var spClient = this,
66 | connectOptions = {
67 | onConnect: function() {
68 | /**
69 | The window.navigator object
70 | @namespace navigator
71 | */
72 |
73 | /**
74 | Add the push object to the global navigator object
75 | @status Experimental
76 | @constructs navigator.push
77 | */
78 | navigator.push = (function() {
79 | return {
80 | /**
81 | Register a push notification channel with the SimplePush server
82 | @function
83 | @memberof navigator.push
84 | @returns {Object} - The request object where a connection success callback can be registered
85 | @example
86 | var mailRequest = navigator.push.register();
87 | */
88 | register: function() {
89 | var request = {
90 | onsuccess: function( event ) {}
91 | };
92 |
93 | if ( !spClient.simpleNotifier ) {
94 | throw "SimplePushConnectionError";
95 | }
96 |
97 | spClient.simpleNotifier.subscribe({
98 | requestObject: request
99 | });
100 |
101 | return request;
102 | },
103 |
104 | /**
105 | Unregister a push notification channel from the SimplePush server
106 | @function
107 | @memberof navigator.push
108 | @example
109 | navigator.push.unregister( mailEndpoint );
110 | */
111 | unregister: function( endpoint ) {
112 | spClient.simpleNotifier.unsubscribe( endpoint );
113 | },
114 |
115 | /**
116 | Reestablish the connection with the SimplePush server when closed or lost. This is an addition and not part of the SimplePush spec
117 | @function
118 | @memberof navigator.push
119 | @param {Object} options - an object used to initialize the connection to the SimplePush server
120 | @param {String} options.simplePushServerURL - the URL of the SimplePush server
121 | @param {Function} options.onConnect - a callback to fire when a connection is established with the SimplePush server. This is a deviation from the SimplePush spec as it is not necessary when you using the in browser functionality since the browser establishes the connection before the application is started.
122 | @param {Function} options.onClose - a callback to fire when a connection to the SimplePush server is closed or lost.
123 | @example
124 | navigator.push.reconnect({
125 | simplePushServerURL: "https://localhost:7777/simplepush",
126 | onConnect: myConnectCallback,
127 | onClose: myCloseCallback
128 | });
129 | */
130 | reconnect: function() {
131 | spClient.simpleNotifier.connect( connectOptions );
132 | }
133 | };
134 | })();
135 |
136 | /**
137 | Add the setMessageHandler/mozSetMessageHandler function to the global navigator object
138 | @status Experimental
139 | @constructs navigator.setMessageHandler/navigator.mozSetMessageHandler
140 | @param {String} messageType - a name or category to give the messages being received and in this implementation, likely 'push'
141 | @param {Function} callback - the function to be called when a message of this type is received
142 | @example
143 | navigator.setMessageHandler( "push", function( message ) {
144 | if ( message.channelID === mailEndpoint.channelID ) {
145 | console.log("Mail Message Received");
146 | }
147 | });
148 |
149 | or
150 | // Mozilla's spec currently has the 'moz' prefix
151 | navigator.mozSetMessageHandler( "push", function( message ) {
152 | if ( message.channelID === mailEndpoint.channelID ) {
153 | console.log("Mail Message Received");
154 | }
155 | });
156 | */
157 | navigator.setMessageHandler = navigator.mozSetMessageHandler = function( messageType, callback ) {
158 | $( navigator.push ).on( messageType, function( event ) {
159 | var message = event.message;
160 | callback.call( this, message );
161 | });
162 | };
163 |
164 | if ( spClient.options.onConnect ) {
165 | spClient.options.onConnect();
166 | }
167 | },
168 | onClose: function() {
169 | spClient.simpleNotifier.disconnect( spClient.options.onClose );
170 | }
171 | };
172 |
173 | // Create a Notifier connection to the Push Network
174 | spClient.simpleNotifier = AeroGear.Notifier({
175 | name: "agPushNetwork",
176 | type: "SimplePush",
177 | settings: {
178 | connectURL: spClient.options.simplePushServerURL,
179 | useNative: spClient.options.useNative
180 | }
181 | }).clients.agPushNetwork;
182 |
183 | spClient.simpleNotifier.connect( connectOptions );
184 | };
185 | })( AeroGear, jQuery );
186 |
--------------------------------------------------------------------------------
/src/unifiedpush/aerogear.unifiedpush.js:
--------------------------------------------------------------------------------
1 | /* AeroGear JavaScript Library
2 | * https://github.com/aerogear/aerogear-js
3 | * JBoss, Home of Professional Open Source
4 | * Copyright Red Hat, Inc., and individual contributors
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | (function( AeroGear, undefined ) {
17 | /**
18 | The UnifiedPushClient object is used to perfom register and unregister operations against the AeroGear UnifiedPush server.
19 | @status Experimental
20 | @constructs AeroGear.UnifiedPushClient
21 | @param {String} variantID - the id representing the mobile application variant
22 | @param {String} variantSecret - the secret for the mobile application variant
23 | @param {String} pushServerURL - the location of the UnifiedPush server e.g. http(s)//host:port/context
24 | @returns {Object} The created unified push server client
25 | @example
26 | // Create the UnifiedPush client object:
27 | var client = AeroGear.UnifiedPushClient(
28 | "myVariantID",
29 | "myVariantSecret",
30 | "http://SERVER:PORT/CONTEXT"
31 | );
32 |
33 | // assemble the metadata for the registration:
34 | var metadata = {
35 | deviceToken: "http://server.com/simplePushEndpoint",
36 | alias: "some_username",
37 | categories: [ "email" ]
38 | };
39 |
40 | var settings = {};
41 |
42 | settings.metadata = metadata;
43 |
44 | // perform the registration against the UnifiedPush server:
45 | client.registerWithPushServer( settings );
46 |
47 | */
48 | AeroGear.UnifiedPushClient = function( variantID, variantSecret, pushServerURL ) {
49 |
50 | // we require all arguments to be present, otherwise it does not work
51 | if ( !variantID || !variantSecret || !pushServerURL ) {
52 | throw "UnifiedPushClientException";
53 | }
54 |
55 | // Allow instantiation without using new
56 | if ( !( this instanceof AeroGear.UnifiedPushClient ) ) {
57 | return new AeroGear.UnifiedPushClient( variantID, variantSecret, pushServerURL );
58 | }
59 |
60 | pushServerURL = pushServerURL.substr(-1) === '/' ? pushServerURL : pushServerURL + '/';
61 |
62 | this._ajax = function( settings ) {
63 | return new Promise( function( resolve, reject ) {
64 | var header,
65 | that = this,
66 | request = new XMLHttpRequest();
67 |
68 |
69 | request.open( settings.type || "GET", settings.url, true, settings.username, settings.password );
70 |
71 | request.setRequestHeader( "Content-Type", "application/json" );
72 | request.setRequestHeader( "Accept", "application/json" );
73 |
74 | if( settings.headers ) {
75 | for ( header in settings.headers ) {
76 | request.setRequestHeader( header, settings.headers[ header ] );
77 | }
78 | }
79 |
80 | // Success and 400's
81 | request.onload = function() {
82 | var status = ( request.status < 400 ) ? "success" : "error",
83 | promiseValue = that._createPromiseValue( request, status );
84 |
85 | if( status === "success" ) {
86 | return resolve( promiseValue );
87 | }
88 |
89 | return reject( promiseValue );
90 | };
91 |
92 | // Network errors
93 | request.onerror = function() {
94 | return reject( that._createPromiseValue( request, "error" ) );
95 | };
96 |
97 | // create promise arguments
98 | this._createPromiseValue = function( request, status ) {
99 | return {
100 | data: request.response,
101 | statusText: request.statusText || status,
102 | agXHR: request
103 | };
104 | };
105 |
106 | request.send( settings.data );
107 | });
108 | };
109 | /**
110 | Performs a register request against the UnifiedPush Server using the given metadata which represents a client that wants to register with the server.
111 | @param {Object} settings The settings to pass in
112 | @param {Object} settings.metadata - the metadata for the client
113 | @param {String} settings.metadata.deviceToken - identifies the client within its PushNetwork. On Android this is the registrationID, on iOS this is the deviceToken and on SimplePush this is the URL of the given SimplePush server/network.
114 | @param {String} [settings.metadata.alias] - Application specific alias to identify users with the system. Common use case would be an email address or a username.
115 | @param {Array} [settings.metadata.categories] - In SimplePush this is the name of the registration endpoint. On Hybrid platforms like Apache Cordova this is used for tagging the registered client.
116 | @param {String} [settings.metadata.operatingSystem] - Useful on Hybrid platforms like Apache Cordova to specifiy the underlying operating system.
117 | @param {String} [settings.metadata.osVersion] - Useful on Hybrid platforms like Apache Cordova to specify the version of the underlying operating system.
118 | @param {String} [settings.metadata.deviceType] - Useful on Hybrid platforms like Apache Cordova to specify the type of the used device, like iPad or Android-Phone.
119 | @returns {Object} An ES6 Promise
120 | */
121 | this.registerWithPushServer = function( settings ) {
122 | settings = settings || {};
123 | var metadata = settings.metadata || {};
124 |
125 | // we need a deviceToken, registrationID or a channelID:
126 | if ( !metadata.deviceToken ) {
127 | throw "UnifiedPushRegistrationException";
128 | }
129 |
130 | // Make sure that settings.metadata.categories is an Array
131 | metadata.categories = Array.isArray( metadata.categories ) ? metadata.categories : ( metadata.categories ? [ metadata.categories ] : [] );
132 |
133 | return this._ajax({
134 | type: "POST",
135 | url: pushServerURL + "rest/registry/device",
136 | headers: {
137 | "Authorization": "Basic " + window.btoa(variantID + ":" + variantSecret)
138 | },
139 | data: JSON.stringify( metadata )
140 | });
141 | };
142 |
143 | /**
144 | Performs an unregister request against the UnifiedPush Server for the given deviceToken. The deviceToken identifies the client within its PushNetwork. On Android this is the registrationID, on iOS this is the deviceToken and on SimplePush this is the URL of the given SimplePush server/network.
145 | @param {String} deviceToken - unique String which identifies the client that is being unregistered.
146 | @returns {Object} An ES6 Promise
147 | */
148 | this.unregisterWithPushServer = function( deviceToken ) {
149 | return this._ajax({
150 | type: "DELETE",
151 | url: pushServerURL + "rest/registry/device/" + deviceToken,
152 | headers: {
153 | "Authorization": "Basic " + window.btoa(variantID + ":" + variantSecret)
154 | }
155 | });
156 | };
157 | };
158 |
159 | })( AeroGear );
160 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "browser": true,
3 | "curly": true,
4 | "eqeqeq": true,
5 | "latedef": true,
6 | "loopfunc": true,
7 | "noarg": true,
8 | "noempty": true,
9 | "undef": true,
10 | "trailing": true,
11 | "globals": {
12 | "suiteData": true,
13 | "ok": true,
14 | "throws": true,
15 | "raises": true,
16 | "start": true,
17 | "stop": true,
18 | "console": true,
19 | "equal": true,
20 | "strictEqual": true,
21 | "notEqual": true,
22 | "asyncTest": true,
23 | "test": true,
24 | "sinon": true,
25 | "module": true,
26 | "expect": true,
27 | "jQuery": true,
28 | "AeroGear": true,
29 | "Promise": true,
30 | "require": true,
31 | "uuid": true,
32 | "vertx": true,
33 | "SockJS": true,
34 | "Stomp": true,
35 | "Messaging": true,
36 | "File": true,
37 | "sjcl": true,
38 | "crypto": true,
39 | "diff_match_patch": true,
40 | "jsonpatch": true
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/polyfill/bind-polyfill.js:
--------------------------------------------------------------------------------
1 | if (!Function.prototype.bind) {
2 | Function.prototype.bind = function(oThis) {
3 | if (typeof this !== 'function') {
4 | // closest thing possible to the ECMAScript 5
5 | // internal IsCallable function
6 | throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
7 | }
8 |
9 | var aArgs = Array.prototype.slice.call(arguments, 1),
10 | fToBind = this,
11 | fNOP = function() {},
12 | fBound = function() {
13 | return fToBind.apply(this instanceof fNOP && oThis
14 | ? this
15 | : oThis,
16 | aArgs.concat(Array.prototype.slice.call(arguments)));
17 | };
18 |
19 | fNOP.prototype = this.prototype;
20 | fBound.prototype = new fNOP();
21 |
22 | return fBound;
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/tests/unit/all.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AeroGear.js Test Suite
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
37 |
38 |
39 |
40 |