@ohos-ports/cross-storage 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/hub.js ADDED
@@ -0,0 +1,299 @@
1
+ ;(function(root) {
2
+ var CrossStorageHub = {};
3
+
4
+ /**
5
+ * In Node.js/OHOS in-process mode, _storage holds a localStorage-compatible
6
+ * object. When set, all hub methods use this instead of window.localStorage.
7
+ *
8
+ * @private
9
+ */
10
+ CrossStorageHub._storage = null;
11
+
12
+ /**
13
+ * Returns the active storage backend. Uses _storage if set (in-process mode),
14
+ * otherwise falls back to window.localStorage (browser mode).
15
+ *
16
+ * @private
17
+ * @returns {object} localStorage-compatible storage
18
+ */
19
+ CrossStorageHub._getStorage = function() {
20
+ if (CrossStorageHub._storage) {
21
+ return CrossStorageHub._storage;
22
+ }
23
+ return window.localStorage;
24
+ };
25
+
26
+ /**
27
+ * Accepts an array of objects with two keys: origin and allow. The value
28
+ * of origin is expected to be a RegExp, and allow, an array of strings.
29
+ * The cross storage hub is then initialized to accept requests from any of
30
+ * the matching origins, allowing access to the associated lists of methods.
31
+ * Methods may include any of: get, set, del, getKeys and clear. A 'ready'
32
+ * message is sent to the parent window once complete.
33
+ *
34
+ * @example
35
+ * // Subdomain can get, but only root domain can set and del
36
+ * CrossStorageHub.init([
37
+ * {origin: /\.example.com$/, allow: ['get']},
38
+ * {origin: /:(www\.)?example.com$/, allow: ['get', 'set', 'del']}
39
+ * ]);
40
+ *
41
+ * @param {array} permissions An array of objects with origin and allow
42
+ */
43
+ CrossStorageHub.init = function(permissions) {
44
+ // In-process mode: skip browser checks
45
+ if (CrossStorageHub._storage) {
46
+ CrossStorageHub._permissions = permissions || [];
47
+ return;
48
+ }
49
+
50
+ var available = true;
51
+
52
+ // Return if localStorage is unavailable, or third party
53
+ // access is disabled
54
+ try {
55
+ if (!window.localStorage) available = false;
56
+ } catch (e) {
57
+ available = false;
58
+ }
59
+
60
+ if (!available) {
61
+ try {
62
+ return window.parent.postMessage('cross-storage:unavailable', '*');
63
+ } catch (e) {
64
+ return;
65
+ }
66
+ }
67
+
68
+ CrossStorageHub._permissions = permissions || [];
69
+ CrossStorageHub._installListener();
70
+ window.parent.postMessage('cross-storage:ready', '*');
71
+ };
72
+
73
+ /**
74
+ * Installs the necessary listener for the window message event. Accommodates
75
+ * IE8 and up.
76
+ *
77
+ * @private
78
+ */
79
+ CrossStorageHub._installListener = function() {
80
+ var listener = CrossStorageHub._listener;
81
+ if (window.addEventListener) {
82
+ window.addEventListener('message', listener, false);
83
+ } else {
84
+ window.attachEvent('onmessage', listener);
85
+ }
86
+ };
87
+
88
+ /**
89
+ * The message handler for all requests posted to the window. It ignores any
90
+ * messages having an origin that does not match the originally supplied
91
+ * pattern. Given a JSON object with one of get, set, del or getKeys as the
92
+ * method, the function performs the requested action and returns its result.
93
+ *
94
+ * @param {MessageEvent} message A message to be processed
95
+ */
96
+ CrossStorageHub._listener = function(message) {
97
+ var origin, targetOrigin, request, method, error, result, response;
98
+
99
+ // postMessage returns the string "null" as the origin for "file://"
100
+ origin = (message.origin === 'null') ? 'file://' : message.origin;
101
+
102
+ // Handle polling for a ready message
103
+ if (message.data === 'cross-storage:poll') {
104
+ return window.parent.postMessage('cross-storage:ready', message.origin);
105
+ }
106
+
107
+ // Ignore the ready message when viewing the hub directly
108
+ if (message.data === 'cross-storage:ready') return;
109
+
110
+ // Check whether message.data is a valid json
111
+ try {
112
+ request = JSON.parse(message.data);
113
+ } catch (err) {
114
+ return;
115
+ }
116
+
117
+ // Check whether request.method is a string
118
+ if (!request || typeof request.method !== 'string') {
119
+ return;
120
+ }
121
+
122
+ method = request.method.split('cross-storage:')[1];
123
+
124
+ if (!method) {
125
+ return;
126
+ } else if (!CrossStorageHub._permitted(origin, method)) {
127
+ error = 'Invalid permissions for ' + method;
128
+ } else {
129
+ try {
130
+ result = CrossStorageHub['_' + method](request.params);
131
+ } catch (err) {
132
+ error = err.message;
133
+ }
134
+ }
135
+
136
+ response = JSON.stringify({
137
+ id: request.id,
138
+ error: error,
139
+ result: result
140
+ });
141
+
142
+ // postMessage requires that the target origin be set to "*" for "file://"
143
+ targetOrigin = (origin === 'file://') ? '*' : origin;
144
+
145
+ window.parent.postMessage(response, targetOrigin);
146
+ };
147
+
148
+ /**
149
+ * Returns a boolean indicating whether or not the requested method is
150
+ * permitted for the given origin. The argument passed to method is expected
151
+ * to be one of 'get', 'set', 'del' or 'getKeys'.
152
+ *
153
+ * @param {string} origin The origin for which to determine permissions
154
+ * @param {string} method Requested action
155
+ * @returns {bool} Whether or not the request is permitted
156
+ */
157
+ CrossStorageHub._permitted = function(origin, method) {
158
+ var available, i, entry, match;
159
+
160
+ available = ['get', 'set', 'del', 'clear', 'getKeys'];
161
+ if (!CrossStorageHub._inArray(method, available)) {
162
+ return false;
163
+ }
164
+
165
+ for (i = 0; i < CrossStorageHub._permissions.length; i++) {
166
+ entry = CrossStorageHub._permissions[i];
167
+ if (!(entry.origin instanceof RegExp) || !(entry.allow instanceof Array)) {
168
+ continue;
169
+ }
170
+
171
+ match = entry.origin.test(origin);
172
+ if (match && CrossStorageHub._inArray(method, entry.allow)) {
173
+ return true;
174
+ }
175
+ }
176
+
177
+ return false;
178
+ };
179
+
180
+ /**
181
+ * Sets a key to the specified value.
182
+ *
183
+ * @param {object} params An object with key and value
184
+ */
185
+ CrossStorageHub._set = function(params) {
186
+ CrossStorageHub._getStorage().setItem(params.key, params.value);
187
+ };
188
+
189
+ /**
190
+ * Accepts an object with an array of keys for which to retrieve their values.
191
+ * Returns a single value if only one key was supplied, otherwise it returns
192
+ * an array. Any keys not set result in a null element in the resulting array.
193
+ *
194
+ * @param {object} params An object with an array of keys
195
+ * @returns {*|*[]} Either a single value, or an array
196
+ */
197
+ CrossStorageHub._get = function(params) {
198
+ var storage, result, i, value;
199
+
200
+ storage = CrossStorageHub._getStorage();
201
+ result = [];
202
+
203
+ for (i = 0; i < params.keys.length; i++) {
204
+ try {
205
+ value = storage.getItem(params.keys[i]);
206
+ } catch (e) {
207
+ value = null;
208
+ }
209
+
210
+ result.push(value);
211
+ }
212
+
213
+ return (result.length > 1) ? result : result[0];
214
+ };
215
+
216
+ /**
217
+ * Deletes all keys specified in the array found at params.keys.
218
+ *
219
+ * @param {object} params An object with an array of keys
220
+ */
221
+ CrossStorageHub._del = function(params) {
222
+ var storage = CrossStorageHub._getStorage();
223
+ for (var i = 0; i < params.keys.length; i++) {
224
+ storage.removeItem(params.keys[i]);
225
+ }
226
+ };
227
+
228
+ /**
229
+ * Clears localStorage.
230
+ */
231
+ CrossStorageHub._clear = function() {
232
+ CrossStorageHub._getStorage().clear();
233
+ };
234
+
235
+ /**
236
+ * Returns an array of all keys stored in localStorage.
237
+ *
238
+ * @returns {string[]} The array of keys
239
+ */
240
+ CrossStorageHub._getKeys = function(params) {
241
+ var i, length, keys, storage;
242
+
243
+ storage = CrossStorageHub._getStorage();
244
+ keys = [];
245
+ length = storage.length;
246
+
247
+ for (i = 0; i < length; i++) {
248
+ keys.push(storage.key(i));
249
+ }
250
+
251
+ return keys;
252
+ };
253
+
254
+ /**
255
+ * Returns whether or not a value is present in the array. Consists of an
256
+ * alternative to extending the array prototype for indexOf, since it's
257
+ * unavailable for IE8.
258
+ *
259
+ * @param {*} value The value to find
260
+ * @parma {[]*} array The array in which to search
261
+ * @returns {bool} Whether or not the value was found
262
+ */
263
+ CrossStorageHub._inArray = function(value, array) {
264
+ for (var i = 0; i < array.length; i++) {
265
+ if (value === array[i]) return true;
266
+ }
267
+
268
+ return false;
269
+ };
270
+
271
+ /**
272
+ * A cross-browser version of Date.now compatible with IE8 that avoids
273
+ * modifying the Date object.
274
+ *
275
+ * @return {int} The current timestamp in milliseconds
276
+ */
277
+ CrossStorageHub._now = function() {
278
+ if (typeof Date.now === 'function') {
279
+ return Date.now();
280
+ }
281
+
282
+ return new Date().getTime();
283
+ };
284
+
285
+ /**
286
+ * Export for various environments.
287
+ */
288
+ if (typeof module !== 'undefined' && module.exports) {
289
+ module.exports = CrossStorageHub;
290
+ } else if (typeof exports !== 'undefined') {
291
+ exports.CrossStorageHub = CrossStorageHub;
292
+ } else if (typeof define === 'function' && define.amd) {
293
+ define([], function() {
294
+ return CrossStorageHub;
295
+ });
296
+ } else {
297
+ root.CrossStorageHub = CrossStorageHub;
298
+ }
299
+ }(typeof global !== 'undefined' ? global : this));
package/lib/index.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ CrossStorageClient: require('./client.js'),
3
+ CrossStorageHub: require('./hub.js')
4
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@ohos-ports/cross-storage",
3
+ "version": "1.0.0-beta.0",
4
+ "description": "Cross domain local storage",
5
+ "keywords": [
6
+ "local",
7
+ "storage",
8
+ "cross",
9
+ "domain"
10
+ ],
11
+ "main": "lib/index.js",
12
+ "author": "Daniel St. Jules <danielst.jules@gmail.com>",
13
+ "license": "Apache-2.0",
14
+ "homepage": "https://github.com/zendesk/cross-storage",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/ohos-ports/ohos-ports.git",
18
+ "directory": "ports/cross-storage/1.0.0"
19
+ },
20
+ "devDependencies": {
21
+ "connect": "^2.25.7",
22
+ "expect.js": "^0.3.1",
23
+ "gulp": "*",
24
+ "gulp-header": "^1.1.1",
25
+ "gulp-jshint": "^1.8.4",
26
+ "gulp-rename": "^1.2.0",
27
+ "gulp-rimraf": "^0.1.0",
28
+ "gulp-uglify": "^0.3.1",
29
+ "serve-static": "^1.5.3",
30
+ "zuul": "~3.10.1"
31
+ },
32
+ "scripts": {
33
+ "test": "node test/ohos-test.js",
34
+ "saucetest": "./node_modules/.bin/zuul --ui mocha-bdd -- test/test.js"
35
+ },
36
+ "dependencies": {},
37
+ "files": [
38
+ "lib/",
39
+ "dist/"
40
+ ]
41
+ }