Showing
31 changed files
with
1453 additions
and
503 deletions
| ... | @@ -4,21 +4,64 @@ Allows downloading of files referenced by a http/https URI inside a couchdb/pouc | ... | @@ -4,21 +4,64 @@ Allows downloading of files referenced by a http/https URI inside a couchdb/pouc |
| 4 | 4 | ||
| 5 | # Usage | 5 | # Usage |
| 6 | 6 | ||
| 7 | -### In cordova projects | 7 | +## Use it with pouchdb |
| 8 | 8 | ||
| 9 | -### In electron projects | 9 | +```typescript |
| 10 | +import {ServiceLocator} from 'bsync-client/dist/browser-build'; | ||
| 10 | 11 | ||
| 11 | -Within the main process bsync needs to be integrated an initiated. | 12 | +ServiceLocator.getConfig().setConfig('itemKey', 'type'); |
| 13 | +ServiceLocator.getConfig().setConfig('itemValue', 'asset'); | ||
| 12 | 14 | ||
| 13 | - import {Bsync} from 'bsync'; | 15 | +let localDb = new PouchDB('local-pouch-db'); |
| 14 | - Bsync.init(ipcMain, filePath); | 16 | +let fileReplicator = ServiceLocator.getFileReplicator(); |
| 15 | 17 | ||
| 16 | -# Testing (Browser) | 18 | +localDb.put({ |
| 19 | + _id : "_design/index_type", | ||
| 20 | + views : { | ||
| 21 | + type : { | ||
| 22 | + map : function(doc) { | ||
| 23 | + if (doc[fileReplicator.itemKey]) { emit(doc[fileReplicator.itemKey]); } | ||
| 24 | + }.toString() | ||
| 25 | + } | ||
| 26 | + } | ||
| 27 | +}); | ||
| 28 | + | ||
| 29 | +fileReplicator.once('complete', () => { | ||
| 30 | + // All file are downloaded | ||
| 31 | +}); | ||
| 32 | + | ||
| 33 | +db.query('index_type/type',{ | ||
| 34 | + include_docs : true, | ||
| 35 | + key : fileReplicator.itemValue | ||
| 36 | +}).then((res) => { | ||
| 37 | + let docs = { docs : [] }; | ||
| 38 | + for (let r of res.rows) { | ||
| 39 | + docs.docs.push(r.doc); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + fileReplicator.pushChanges(docs); | ||
| 43 | + fileReplicator.start(); | ||
| 44 | +}); | ||
| 45 | +``` | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +## In electron projects | ||
| 49 | + | ||
| 50 | +Within the `main process` bsync needs to be integrated an initiated. | ||
| 51 | + | ||
| 52 | +```typescript | ||
| 53 | +import {Bsync} from 'bsync'; | ||
| 54 | +Bsync.init(ipcMain, filePath); | ||
| 55 | +``` | ||
| 56 | + | ||
| 57 | +# Testing (Browser/Node) | ||
| 17 | 58 | ||
| 18 | `npm test` | 59 | `npm test` |
| 19 | 60 | ||
| 20 | # Testing (Cordova) | 61 | # Testing (Cordova) |
| 21 | 62 | ||
| 63 | +`npm run test:cordova` | ||
| 64 | + | ||
| 22 | 65 | ||
| 23 | 66 | ||
| 24 | 67 | ... | ... |
| ... | @@ -9,13 +9,13 @@ export default { | ... | @@ -9,13 +9,13 @@ export default { |
| 9 | entry: './src/browser-main.ts', | 9 | entry: './src/browser-main.ts', |
| 10 | dest: './dist/browser-build.js', | 10 | dest: './dist/browser-build.js', |
| 11 | 11 | ||
| 12 | - format: 'cjs', | 12 | + format: 'umd', |
| 13 | 13 | ||
| 14 | sourceMap: true , | 14 | sourceMap: true , |
| 15 | 15 | ||
| 16 | plugins: [ | 16 | plugins: [ |
| 17 | typescript(), | 17 | typescript(), |
| 18 | - // globals(), | 18 | + globals(), |
| 19 | - // builtins() | 19 | + builtins() |
| 20 | ] | 20 | ] |
| 21 | }; | 21 | }; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | import typescript from 'rollup-plugin-typescript'; | 1 | import typescript from 'rollup-plugin-typescript'; |
| 2 | +import builtins from 'rollup-plugin-node-builtins'; | ||
| 3 | +import globals from 'rollup-plugin-node-globals'; | ||
| 2 | 4 | ||
| 3 | export default { | 5 | export default { |
| 4 | 6 | ||
| ... | @@ -10,6 +12,8 @@ export default { | ... | @@ -10,6 +12,8 @@ export default { |
| 10 | format: 'cjs', | 12 | format: 'cjs', |
| 11 | 13 | ||
| 12 | plugins: [ | 14 | plugins: [ |
| 13 | - typescript() | 15 | + typescript(), |
| 16 | + globals(), | ||
| 17 | + builtins() | ||
| 14 | ] | 18 | ] |
| 15 | }; | 19 | }; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -'use strict'; | 1 | +(function (global, factory) { |
| 2 | + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
| 3 | + typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
| 4 | + (factory((global.bsync = global.bsync || {}))); | ||
| 5 | +}(this, (function (exports) { 'use strict'; | ||
| 2 | 6 | ||
| 3 | -Object.defineProperty(exports, '__esModule', { value: true }); | 7 | +var domain; |
| 8 | + | ||
| 9 | +// This constructor is used to store event handlers. Instantiating this is | ||
| 10 | +// faster than explicitly calling `Object.create(null)` to get a "clean" empty | ||
| 11 | +// object (tested with v8 v4.9). | ||
| 12 | +function EventHandlers() {} | ||
| 13 | +EventHandlers.prototype = Object.create(null); | ||
| 14 | + | ||
| 15 | +function EventEmitter() { | ||
| 16 | + EventEmitter.init.call(this); | ||
| 17 | +} | ||
| 18 | +EventEmitter.usingDomains = false; | ||
| 19 | + | ||
| 20 | +EventEmitter.prototype.domain = undefined; | ||
| 21 | +EventEmitter.prototype._events = undefined; | ||
| 22 | +EventEmitter.prototype._maxListeners = undefined; | ||
| 23 | + | ||
| 24 | +// By default EventEmitters will print a warning if more than 10 listeners are | ||
| 25 | +// added to it. This is a useful default which helps finding memory leaks. | ||
| 26 | +EventEmitter.defaultMaxListeners = 10; | ||
| 27 | + | ||
| 28 | +EventEmitter.init = function() { | ||
| 29 | + this.domain = null; | ||
| 30 | + if (EventEmitter.usingDomains) { | ||
| 31 | + // if there is an active domain, then attach to it. | ||
| 32 | + if (domain.active && !(this instanceof domain.Domain)) { | ||
| 33 | + this.domain = domain.active; | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + if (!this._events || this._events === Object.getPrototypeOf(this)._events) { | ||
| 38 | + this._events = new EventHandlers(); | ||
| 39 | + this._eventsCount = 0; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + this._maxListeners = this._maxListeners || undefined; | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +// Obviously not all Emitters should be limited to 10. This function allows | ||
| 46 | +// that to be increased. Set to zero for unlimited. | ||
| 47 | +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { | ||
| 48 | + if (typeof n !== 'number' || n < 0 || isNaN(n)) | ||
| 49 | + throw new TypeError('"n" argument must be a positive number'); | ||
| 50 | + this._maxListeners = n; | ||
| 51 | + return this; | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +function $getMaxListeners(that) { | ||
| 55 | + if (that._maxListeners === undefined) | ||
| 56 | + return EventEmitter.defaultMaxListeners; | ||
| 57 | + return that._maxListeners; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { | ||
| 61 | + return $getMaxListeners(this); | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +// These standalone emit* functions are used to optimize calling of event | ||
| 65 | +// handlers for fast cases because emit() itself often has a variable number of | ||
| 66 | +// arguments and can be deoptimized because of that. These functions always have | ||
| 67 | +// the same number of arguments and thus do not get deoptimized, so the code | ||
| 68 | +// inside them can execute faster. | ||
| 69 | +function emitNone(handler, isFn, self) { | ||
| 70 | + if (isFn) | ||
| 71 | + handler.call(self); | ||
| 72 | + else { | ||
| 73 | + var len = handler.length; | ||
| 74 | + var listeners = arrayClone(handler, len); | ||
| 75 | + for (var i = 0; i < len; ++i) | ||
| 76 | + listeners[i].call(self); | ||
| 77 | + } | ||
| 78 | +} | ||
| 79 | +function emitOne(handler, isFn, self, arg1) { | ||
| 80 | + if (isFn) | ||
| 81 | + handler.call(self, arg1); | ||
| 82 | + else { | ||
| 83 | + var len = handler.length; | ||
| 84 | + var listeners = arrayClone(handler, len); | ||
| 85 | + for (var i = 0; i < len; ++i) | ||
| 86 | + listeners[i].call(self, arg1); | ||
| 87 | + } | ||
| 88 | +} | ||
| 89 | +function emitTwo(handler, isFn, self, arg1, arg2) { | ||
| 90 | + if (isFn) | ||
| 91 | + handler.call(self, arg1, arg2); | ||
| 92 | + else { | ||
| 93 | + var len = handler.length; | ||
| 94 | + var listeners = arrayClone(handler, len); | ||
| 95 | + for (var i = 0; i < len; ++i) | ||
| 96 | + listeners[i].call(self, arg1, arg2); | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | +function emitThree(handler, isFn, self, arg1, arg2, arg3) { | ||
| 100 | + if (isFn) | ||
| 101 | + handler.call(self, arg1, arg2, arg3); | ||
| 102 | + else { | ||
| 103 | + var len = handler.length; | ||
| 104 | + var listeners = arrayClone(handler, len); | ||
| 105 | + for (var i = 0; i < len; ++i) | ||
| 106 | + listeners[i].call(self, arg1, arg2, arg3); | ||
| 107 | + } | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +function emitMany(handler, isFn, self, args) { | ||
| 111 | + if (isFn) | ||
| 112 | + handler.apply(self, args); | ||
| 113 | + else { | ||
| 114 | + var len = handler.length; | ||
| 115 | + var listeners = arrayClone(handler, len); | ||
| 116 | + for (var i = 0; i < len; ++i) | ||
| 117 | + listeners[i].apply(self, args); | ||
| 118 | + } | ||
| 119 | +} | ||
| 4 | 120 | ||
| 5 | -var events = require('events'); | 121 | +EventEmitter.prototype.emit = function emit(type) { |
| 6 | -var rxjs = require('rxjs'); | 122 | + var er, handler, len, args, i, events, domain; |
| 123 | + var needDomainExit = false; | ||
| 124 | + var doError = (type === 'error'); | ||
| 125 | + | ||
| 126 | + events = this._events; | ||
| 127 | + if (events) | ||
| 128 | + doError = (doError && events.error == null); | ||
| 129 | + else if (!doError) | ||
| 130 | + return false; | ||
| 131 | + | ||
| 132 | + domain = this.domain; | ||
| 133 | + | ||
| 134 | + // If there is no 'error' event listener then throw. | ||
| 135 | + if (doError) { | ||
| 136 | + er = arguments[1]; | ||
| 137 | + if (domain) { | ||
| 138 | + if (!er) | ||
| 139 | + er = new Error('Uncaught, unspecified "error" event'); | ||
| 140 | + er.domainEmitter = this; | ||
| 141 | + er.domain = domain; | ||
| 142 | + er.domainThrown = false; | ||
| 143 | + domain.emit('error', er); | ||
| 144 | + } else if (er instanceof Error) { | ||
| 145 | + throw er; // Unhandled 'error' event | ||
| 146 | + } else { | ||
| 147 | + // At least give some kind of context to the user | ||
| 148 | + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); | ||
| 149 | + err.context = er; | ||
| 150 | + throw err; | ||
| 151 | + } | ||
| 152 | + return false; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + handler = events[type]; | ||
| 156 | + | ||
| 157 | + if (!handler) | ||
| 158 | + return false; | ||
| 159 | + | ||
| 160 | + var isFn = typeof handler === 'function'; | ||
| 161 | + len = arguments.length; | ||
| 162 | + switch (len) { | ||
| 163 | + // fast cases | ||
| 164 | + case 1: | ||
| 165 | + emitNone(handler, isFn, this); | ||
| 166 | + break; | ||
| 167 | + case 2: | ||
| 168 | + emitOne(handler, isFn, this, arguments[1]); | ||
| 169 | + break; | ||
| 170 | + case 3: | ||
| 171 | + emitTwo(handler, isFn, this, arguments[1], arguments[2]); | ||
| 172 | + break; | ||
| 173 | + case 4: | ||
| 174 | + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); | ||
| 175 | + break; | ||
| 176 | + // slower | ||
| 177 | + default: | ||
| 178 | + args = new Array(len - 1); | ||
| 179 | + for (i = 1; i < len; i++) | ||
| 180 | + args[i - 1] = arguments[i]; | ||
| 181 | + emitMany(handler, isFn, this, args); | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + if (needDomainExit) | ||
| 185 | + domain.exit(); | ||
| 186 | + | ||
| 187 | + return true; | ||
| 188 | +}; | ||
| 189 | + | ||
| 190 | +function _addListener(target, type, listener, prepend) { | ||
| 191 | + var m; | ||
| 192 | + var events; | ||
| 193 | + var existing; | ||
| 194 | + | ||
| 195 | + if (typeof listener !== 'function') | ||
| 196 | + throw new TypeError('"listener" argument must be a function'); | ||
| 197 | + | ||
| 198 | + events = target._events; | ||
| 199 | + if (!events) { | ||
| 200 | + events = target._events = new EventHandlers(); | ||
| 201 | + target._eventsCount = 0; | ||
| 202 | + } else { | ||
| 203 | + // To avoid recursion in the case that type === "newListener"! Before | ||
| 204 | + // adding it to the listeners, first emit "newListener". | ||
| 205 | + if (events.newListener) { | ||
| 206 | + target.emit('newListener', type, | ||
| 207 | + listener.listener ? listener.listener : listener); | ||
| 208 | + | ||
| 209 | + // Re-assign `events` because a newListener handler could have caused the | ||
| 210 | + // this._events to be assigned to a new object | ||
| 211 | + events = target._events; | ||
| 212 | + } | ||
| 213 | + existing = events[type]; | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + if (!existing) { | ||
| 217 | + // Optimize the case of one listener. Don't need the extra array object. | ||
| 218 | + existing = events[type] = listener; | ||
| 219 | + ++target._eventsCount; | ||
| 220 | + } else { | ||
| 221 | + if (typeof existing === 'function') { | ||
| 222 | + // Adding the second element, need to change to array. | ||
| 223 | + existing = events[type] = prepend ? [listener, existing] : | ||
| 224 | + [existing, listener]; | ||
| 225 | + } else { | ||
| 226 | + // If we've already got an array, just append. | ||
| 227 | + if (prepend) { | ||
| 228 | + existing.unshift(listener); | ||
| 229 | + } else { | ||
| 230 | + existing.push(listener); | ||
| 231 | + } | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + // Check for listener leak | ||
| 235 | + if (!existing.warned) { | ||
| 236 | + m = $getMaxListeners(target); | ||
| 237 | + if (m && m > 0 && existing.length > m) { | ||
| 238 | + existing.warned = true; | ||
| 239 | + var w = new Error('Possible EventEmitter memory leak detected. ' + | ||
| 240 | + existing.length + ' ' + type + ' listeners added. ' + | ||
| 241 | + 'Use emitter.setMaxListeners() to increase limit'); | ||
| 242 | + w.name = 'MaxListenersExceededWarning'; | ||
| 243 | + w.emitter = target; | ||
| 244 | + w.type = type; | ||
| 245 | + w.count = existing.length; | ||
| 246 | + emitWarning(w); | ||
| 247 | + } | ||
| 248 | + } | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + return target; | ||
| 252 | +} | ||
| 253 | +function emitWarning(e) { | ||
| 254 | + typeof console.warn === 'function' ? console.warn(e) : console.log(e); | ||
| 255 | +} | ||
| 256 | +EventEmitter.prototype.addListener = function addListener(type, listener) { | ||
| 257 | + return _addListener(this, type, listener, false); | ||
| 258 | +}; | ||
| 259 | + | ||
| 260 | +EventEmitter.prototype.on = EventEmitter.prototype.addListener; | ||
| 261 | + | ||
| 262 | +EventEmitter.prototype.prependListener = | ||
| 263 | + function prependListener(type, listener) { | ||
| 264 | + return _addListener(this, type, listener, true); | ||
| 265 | + }; | ||
| 266 | + | ||
| 267 | +function _onceWrap(target, type, listener) { | ||
| 268 | + var fired = false; | ||
| 269 | + function g() { | ||
| 270 | + target.removeListener(type, g); | ||
| 271 | + if (!fired) { | ||
| 272 | + fired = true; | ||
| 273 | + listener.apply(target, arguments); | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + g.listener = listener; | ||
| 277 | + return g; | ||
| 278 | +} | ||
| 279 | + | ||
| 280 | +EventEmitter.prototype.once = function once(type, listener) { | ||
| 281 | + if (typeof listener !== 'function') | ||
| 282 | + throw new TypeError('"listener" argument must be a function'); | ||
| 283 | + this.on(type, _onceWrap(this, type, listener)); | ||
| 284 | + return this; | ||
| 285 | +}; | ||
| 286 | + | ||
| 287 | +EventEmitter.prototype.prependOnceListener = | ||
| 288 | + function prependOnceListener(type, listener) { | ||
| 289 | + if (typeof listener !== 'function') | ||
| 290 | + throw new TypeError('"listener" argument must be a function'); | ||
| 291 | + this.prependListener(type, _onceWrap(this, type, listener)); | ||
| 292 | + return this; | ||
| 293 | + }; | ||
| 294 | + | ||
| 295 | +// emits a 'removeListener' event iff the listener was removed | ||
| 296 | +EventEmitter.prototype.removeListener = | ||
| 297 | + function removeListener(type, listener) { | ||
| 298 | + var list, events, position, i, originalListener; | ||
| 299 | + | ||
| 300 | + if (typeof listener !== 'function') | ||
| 301 | + throw new TypeError('"listener" argument must be a function'); | ||
| 302 | + | ||
| 303 | + events = this._events; | ||
| 304 | + if (!events) | ||
| 305 | + return this; | ||
| 306 | + | ||
| 307 | + list = events[type]; | ||
| 308 | + if (!list) | ||
| 309 | + return this; | ||
| 310 | + | ||
| 311 | + if (list === listener || (list.listener && list.listener === listener)) { | ||
| 312 | + if (--this._eventsCount === 0) | ||
| 313 | + this._events = new EventHandlers(); | ||
| 314 | + else { | ||
| 315 | + delete events[type]; | ||
| 316 | + if (events.removeListener) | ||
| 317 | + this.emit('removeListener', type, list.listener || listener); | ||
| 318 | + } | ||
| 319 | + } else if (typeof list !== 'function') { | ||
| 320 | + position = -1; | ||
| 321 | + | ||
| 322 | + for (i = list.length; i-- > 0;) { | ||
| 323 | + if (list[i] === listener || | ||
| 324 | + (list[i].listener && list[i].listener === listener)) { | ||
| 325 | + originalListener = list[i].listener; | ||
| 326 | + position = i; | ||
| 327 | + break; | ||
| 328 | + } | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + if (position < 0) | ||
| 332 | + return this; | ||
| 333 | + | ||
| 334 | + if (list.length === 1) { | ||
| 335 | + list[0] = undefined; | ||
| 336 | + if (--this._eventsCount === 0) { | ||
| 337 | + this._events = new EventHandlers(); | ||
| 338 | + return this; | ||
| 339 | + } else { | ||
| 340 | + delete events[type]; | ||
| 341 | + } | ||
| 342 | + } else { | ||
| 343 | + spliceOne(list, position); | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + if (events.removeListener) | ||
| 347 | + this.emit('removeListener', type, originalListener || listener); | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + return this; | ||
| 351 | + }; | ||
| 352 | + | ||
| 353 | +EventEmitter.prototype.removeAllListeners = | ||
| 354 | + function removeAllListeners(type) { | ||
| 355 | + var listeners, events; | ||
| 356 | + | ||
| 357 | + events = this._events; | ||
| 358 | + if (!events) | ||
| 359 | + return this; | ||
| 360 | + | ||
| 361 | + // not listening for removeListener, no need to emit | ||
| 362 | + if (!events.removeListener) { | ||
| 363 | + if (arguments.length === 0) { | ||
| 364 | + this._events = new EventHandlers(); | ||
| 365 | + this._eventsCount = 0; | ||
| 366 | + } else if (events[type]) { | ||
| 367 | + if (--this._eventsCount === 0) | ||
| 368 | + this._events = new EventHandlers(); | ||
| 369 | + else | ||
| 370 | + delete events[type]; | ||
| 371 | + } | ||
| 372 | + return this; | ||
| 373 | + } | ||
| 374 | + | ||
| 375 | + // emit removeListener for all listeners on all events | ||
| 376 | + if (arguments.length === 0) { | ||
| 377 | + var keys = Object.keys(events); | ||
| 378 | + for (var i = 0, key; i < keys.length; ++i) { | ||
| 379 | + key = keys[i]; | ||
| 380 | + if (key === 'removeListener') continue; | ||
| 381 | + this.removeAllListeners(key); | ||
| 382 | + } | ||
| 383 | + this.removeAllListeners('removeListener'); | ||
| 384 | + this._events = new EventHandlers(); | ||
| 385 | + this._eventsCount = 0; | ||
| 386 | + return this; | ||
| 387 | + } | ||
| 388 | + | ||
| 389 | + listeners = events[type]; | ||
| 390 | + | ||
| 391 | + if (typeof listeners === 'function') { | ||
| 392 | + this.removeListener(type, listeners); | ||
| 393 | + } else if (listeners) { | ||
| 394 | + // LIFO order | ||
| 395 | + do { | ||
| 396 | + this.removeListener(type, listeners[listeners.length - 1]); | ||
| 397 | + } while (listeners[0]); | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + return this; | ||
| 401 | + }; | ||
| 402 | + | ||
| 403 | +EventEmitter.prototype.listeners = function listeners(type) { | ||
| 404 | + var evlistener; | ||
| 405 | + var ret; | ||
| 406 | + var events = this._events; | ||
| 407 | + | ||
| 408 | + if (!events) | ||
| 409 | + ret = []; | ||
| 410 | + else { | ||
| 411 | + evlistener = events[type]; | ||
| 412 | + if (!evlistener) | ||
| 413 | + ret = []; | ||
| 414 | + else if (typeof evlistener === 'function') | ||
| 415 | + ret = [evlistener.listener || evlistener]; | ||
| 416 | + else | ||
| 417 | + ret = unwrapListeners(evlistener); | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + return ret; | ||
| 421 | +}; | ||
| 422 | + | ||
| 423 | +EventEmitter.listenerCount = function(emitter, type) { | ||
| 424 | + if (typeof emitter.listenerCount === 'function') { | ||
| 425 | + return emitter.listenerCount(type); | ||
| 426 | + } else { | ||
| 427 | + return listenerCount.call(emitter, type); | ||
| 428 | + } | ||
| 429 | +}; | ||
| 430 | + | ||
| 431 | +EventEmitter.prototype.listenerCount = listenerCount; | ||
| 432 | +function listenerCount(type) { | ||
| 433 | + var events = this._events; | ||
| 434 | + | ||
| 435 | + if (events) { | ||
| 436 | + var evlistener = events[type]; | ||
| 437 | + | ||
| 438 | + if (typeof evlistener === 'function') { | ||
| 439 | + return 1; | ||
| 440 | + } else if (evlistener) { | ||
| 441 | + return evlistener.length; | ||
| 442 | + } | ||
| 443 | + } | ||
| 444 | + | ||
| 445 | + return 0; | ||
| 446 | +} | ||
| 447 | + | ||
| 448 | +EventEmitter.prototype.eventNames = function eventNames() { | ||
| 449 | + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; | ||
| 450 | +}; | ||
| 451 | + | ||
| 452 | +// About 1.5x faster than the two-arg version of Array#splice(). | ||
| 453 | +function spliceOne(list, index) { | ||
| 454 | + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) | ||
| 455 | + list[i] = list[k]; | ||
| 456 | + list.pop(); | ||
| 457 | +} | ||
| 458 | + | ||
| 459 | +function arrayClone(arr, i) { | ||
| 460 | + var copy = new Array(i); | ||
| 461 | + while (i--) | ||
| 462 | + copy[i] = arr[i]; | ||
| 463 | + return copy; | ||
| 464 | +} | ||
| 465 | + | ||
| 466 | +function unwrapListeners(arr) { | ||
| 467 | + var ret = new Array(arr.length); | ||
| 468 | + for (var i = 0; i < ret.length; ++i) { | ||
| 469 | + ret[i] = arr[i].listener || arr[i]; | ||
| 470 | + } | ||
| 471 | + return ret; | ||
| 472 | +} | ||
| 7 | 473 | ||
| 8 | function __extends(d, b) { | 474 | function __extends(d, b) { |
| 9 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; | 475 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; |
| ... | @@ -11,56 +477,45 @@ function __extends(d, b) { | ... | @@ -11,56 +477,45 @@ function __extends(d, b) { |
| 11 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | 477 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); |
| 12 | } | 478 | } |
| 13 | 479 | ||
| 14 | -var ElectronFileHandler = (function () { | 480 | +var ElectronFileHandler = (function (_super) { |
| 481 | + __extends(ElectronFileHandler, _super); | ||
| 15 | function ElectronFileHandler(ipcRenderer) { | 482 | function ElectronFileHandler(ipcRenderer) { |
| 483 | + _super.call(this); | ||
| 16 | this.ipcRenderer = ipcRenderer; | 484 | this.ipcRenderer = ipcRenderer; |
| 17 | } | 485 | } |
| 18 | ElectronFileHandler.prototype.download = function (source, target) { | 486 | ElectronFileHandler.prototype.download = function (source, target) { |
| 19 | var _this = this; | 487 | var _this = this; |
| 20 | - return rxjs.Observable.create(function (subscriber) { | 488 | + this.ipcRenderer.once('bsync-download-complete', function () { |
| 21 | - _this.ipcRenderer.once('bsync-download-complete', function () { | 489 | + _this.ipcRenderer.removeAllListeners('bsync-download-progress'); |
| 22 | - _this.ipcRenderer.removeAllListeners('bsync-download-progress'); | 490 | + _this.ipcRenderer.removeAllListeners('bsync-download-error'); |
| 23 | - _this.ipcRenderer.removeAllListeners('bsync-download-error'); | 491 | + _this.emit('complete'); |
| 24 | - subscriber.complete(); | 492 | + }); |
| 25 | - }); | 493 | + this.ipcRenderer.on('bsync-download-progress', function (progress) { |
| 26 | - _this.ipcRenderer.on('bsync-download-progress', function (progress) { | 494 | + _this.emit('progress', progress); |
| 27 | - subscriber.next(progress); | 495 | + }); |
| 28 | - }); | 496 | + this.ipcRenderer.once('bsync-download-error', function (error) { |
| 29 | - _this.ipcRenderer.once('bsync-download-error', function (error) { | 497 | + _this.ipcRenderer.removeAllListeners('bsync-download-progress'); |
| 30 | - _this.ipcRenderer.removeAllListeners('bsync-download-progress'); | 498 | + _this.ipcRenderer.removeAllListeners('bsync-download-complete'); |
| 31 | - _this.ipcRenderer.removeAllListeners('bsync-download-complete'); | 499 | + _this.emit('error', error); |
| 32 | - subscriber.error(error); | ||
| 33 | - }); | ||
| 34 | - _this.ipcRenderer.send('bsync-download', { | ||
| 35 | - source: source, | ||
| 36 | - target: target | ||
| 37 | - }); | ||
| 38 | }); | 500 | }); |
| 501 | + this.ipcRenderer.send('bsync-download', { | ||
| 502 | + source: source, | ||
| 503 | + target: target | ||
| 504 | + }); | ||
| 505 | + return this; | ||
| 39 | }; | 506 | }; |
| 40 | - return ElectronFileHandler; | 507 | + ElectronFileHandler.prototype.cleanup = function (files) { |
| 41 | -}()); | 508 | + var _this = this; |
| 42 | - | 509 | + return new Promise(function (resolve, reject) { |
| 43 | -var CordovaDownloader = (function () { | 510 | + _this.ipcRenderer.once('bsync-cleanup-complete', function () { |
| 44 | - function CordovaDownloader() { | 511 | + _this.emit('cleanup-complete'); |
| 45 | - } | 512 | + resolve(); |
| 46 | - CordovaDownloader.prototype.download = function (source, target) { | 513 | + }); |
| 47 | - return Rx.Observable.create(function (subscriber) { | 514 | + _this.ipcRenderer.send('bsync-cleanup', files); |
| 48 | - if (!window['FileTransfer']) { | ||
| 49 | - subscriber.error("Cordova FileTransfer object undefined"); | ||
| 50 | - } | ||
| 51 | - var fileTransfer = new window['FileTransfer'](); | ||
| 52 | - fileTransfer.onprogress = function (progress) { | ||
| 53 | - subscriber.next(progress.loaded / progress.total); | ||
| 54 | - }; | ||
| 55 | - fileTransfer.download(source, target, function (entry) { | ||
| 56 | - subscriber.complete(); | ||
| 57 | - }, function (error) { | ||
| 58 | - subscriber.error(error); | ||
| 59 | - }, true); | ||
| 60 | }); | 515 | }); |
| 61 | }; | 516 | }; |
| 62 | - return CordovaDownloader; | 517 | + return ElectronFileHandler; |
| 63 | -}()); | 518 | +}(EventEmitter)); |
| 64 | 519 | ||
| 65 | var Util = (function () { | 520 | var Util = (function () { |
| 66 | function Util() { | 521 | function Util() { |
| ... | @@ -71,9 +526,120 @@ var Util = (function () { | ... | @@ -71,9 +526,120 @@ var Util = (function () { |
| 71 | } | 526 | } |
| 72 | return "bsync_" + Math.abs(r); | 527 | return "bsync_" + Math.abs(r); |
| 73 | }; | 528 | }; |
| 529 | + /** | ||
| 530 | + * index >= 0, localFile is in files | ||
| 531 | + * index < 0, localFile is not in files | ||
| 532 | + */ | ||
| 533 | + Util.getFileIndex = function (files, localFile) { | ||
| 534 | + for (var i = 0; i < files.length; i++) { | ||
| 535 | + if (localFile == files[i].target) { | ||
| 536 | + return i; | ||
| 537 | + } | ||
| 538 | + } | ||
| 539 | + return -1; | ||
| 540 | + }; | ||
| 541 | + Util.getFilesForCleanup = function (files, localFiles) { | ||
| 542 | + var filesForCleanup = []; | ||
| 543 | + for (var _i = 0, localFiles_1 = localFiles; _i < localFiles_1.length; _i++) { | ||
| 544 | + var localFile = localFiles_1[_i]; | ||
| 545 | + var index = -1; | ||
| 546 | + index = Util.getFileIndex(files, localFile); | ||
| 547 | + if (index < 0) { | ||
| 548 | + filesForCleanup.push(localFile); | ||
| 549 | + } | ||
| 550 | + else { | ||
| 551 | + // splice for performance improvement only | ||
| 552 | + files.splice(index, 1); | ||
| 553 | + } | ||
| 554 | + } | ||
| 555 | + return filesForCleanup; | ||
| 556 | + }; | ||
| 74 | return Util; | 557 | return Util; |
| 75 | }()); | 558 | }()); |
| 76 | 559 | ||
| 560 | +var CordovaFileHandler = (function (_super) { | ||
| 561 | + __extends(CordovaFileHandler, _super); | ||
| 562 | + function CordovaFileHandler() { | ||
| 563 | + _super.apply(this, arguments); | ||
| 564 | + } | ||
| 565 | + CordovaFileHandler.prototype.triggerFileTransfer = function (source, target) { | ||
| 566 | + var _this = this; | ||
| 567 | + var fileTransfer = new window['FileTransfer'](); | ||
| 568 | + fileTransfer.onprogress = function (progress) { | ||
| 569 | + _this.emit('progress', progress.loaded / progress.total); | ||
| 570 | + }; | ||
| 571 | + fileTransfer.download(source, target, function (entry) { | ||
| 572 | + _this.emit('complete', entry); | ||
| 573 | + }, function (error) { | ||
| 574 | + _this.emit('error', error); | ||
| 575 | + }, true); | ||
| 576 | + }; | ||
| 577 | + CordovaFileHandler.prototype.download = function (source, target) { | ||
| 578 | + var _this = this; | ||
| 579 | + if (!window['FileTransfer']) { | ||
| 580 | + this.emit('error', 'Cordova FileTransfer object undefined'); | ||
| 581 | + } | ||
| 582 | + window['resolveLocalFileSystemURL'](target, function (entry) { | ||
| 583 | + entry.getMetadata(function (metadata) { | ||
| 584 | + if (metadata.size > 0) { | ||
| 585 | + _this.emit('complete', entry); | ||
| 586 | + } | ||
| 587 | + else { | ||
| 588 | + // file empty trigger transfer | ||
| 589 | + _this.triggerFileTransfer(source, target); | ||
| 590 | + } | ||
| 591 | + }, function () { | ||
| 592 | + // cannot read metadata trigger transfer | ||
| 593 | + _this.triggerFileTransfer(source, target); | ||
| 594 | + }); | ||
| 595 | + }, function () { | ||
| 596 | + // file not found, so download it | ||
| 597 | + _this.triggerFileTransfer(source, target); | ||
| 598 | + }); | ||
| 599 | + return this; | ||
| 600 | + }; | ||
| 601 | + CordovaFileHandler.prototype.cleanup = function (files, basePath) { | ||
| 602 | + var _this = this; | ||
| 603 | + var filesForCleanup = []; | ||
| 604 | + return new Promise(function (resolve, reject) { | ||
| 605 | + if (window['resolveLocalFileSystemURL']) { | ||
| 606 | + window['resolveLocalFileSystemURL'](basePath, function (entry) { | ||
| 607 | + var reader = entry.createReader(); | ||
| 608 | + reader.readEntries(function (entries) { | ||
| 609 | + for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) { | ||
| 610 | + var e = entries_1[_i]; | ||
| 611 | + if (e && e.isFile) { | ||
| 612 | + if (Util.getFileIndex(files, e.name) < 0) { | ||
| 613 | + filesForCleanup.push(e); | ||
| 614 | + } | ||
| 615 | + } | ||
| 616 | + } | ||
| 617 | + var index = 0; | ||
| 618 | + var error = false; | ||
| 619 | + var cleanupError = function (error) { | ||
| 620 | + _this.emit('cleanup-error', error); | ||
| 621 | + reject(); | ||
| 622 | + error = true; | ||
| 623 | + }; | ||
| 624 | + var cleanupNext = function () { | ||
| 625 | + if (index < filesForCleanup.length && !error) { | ||
| 626 | + filesForCleanup[index].remove(cleanupNext, cleanupError); | ||
| 627 | + index += 1; | ||
| 628 | + } | ||
| 629 | + else if (!error) { | ||
| 630 | + _this.emit('cleanup-complete', filesForCleanup); | ||
| 631 | + resolve(); | ||
| 632 | + } | ||
| 633 | + }; | ||
| 634 | + cleanupNext(); | ||
| 635 | + }, function (error) { _this.emit('cleanup-error', error); reject(); }); | ||
| 636 | + }); | ||
| 637 | + } | ||
| 638 | + }); | ||
| 639 | + }; | ||
| 640 | + return CordovaFileHandler; | ||
| 641 | +}(EventEmitter)); | ||
| 642 | + | ||
| 77 | var FileReplicator = (function (_super) { | 643 | var FileReplicator = (function (_super) { |
| 78 | __extends(FileReplicator, _super); | 644 | __extends(FileReplicator, _super); |
| 79 | function FileReplicator() { | 645 | function FileReplicator() { |
| ... | @@ -81,11 +647,13 @@ var FileReplicator = (function (_super) { | ... | @@ -81,11 +647,13 @@ var FileReplicator = (function (_super) { |
| 81 | this._files = []; | 647 | this._files = []; |
| 82 | this._itemValidator = null; | 648 | this._itemValidator = null; |
| 83 | this._fileHandler = null; | 649 | this._fileHandler = null; |
| 84 | - this._retryTimeout = 0; | 650 | + this._retryTimeout = 100; |
| 651 | + this._retries = 10; | ||
| 85 | this._itemKey = "type"; | 652 | this._itemKey = "type"; |
| 86 | this._itemValue = "asset"; | 653 | this._itemValue = "asset"; |
| 87 | this._itemSourceAttribute = "source"; | 654 | this._itemSourceAttribute = "source"; |
| 88 | this._itemTargetAttribute = "target"; | 655 | this._itemTargetAttribute = "target"; |
| 656 | + this._targetDirectory = ""; | ||
| 89 | } | 657 | } |
| 90 | Object.defineProperty(FileReplicator.prototype, "files", { | 658 | Object.defineProperty(FileReplicator.prototype, "files", { |
| 91 | get: function () { | 659 | get: function () { |
| ... | @@ -95,6 +663,9 @@ var FileReplicator = (function (_super) { | ... | @@ -95,6 +663,9 @@ var FileReplicator = (function (_super) { |
| 95 | configurable: true | 663 | configurable: true |
| 96 | }); | 664 | }); |
| 97 | Object.defineProperty(FileReplicator.prototype, "fileHandler", { | 665 | Object.defineProperty(FileReplicator.prototype, "fileHandler", { |
| 666 | + get: function () { | ||
| 667 | + return this._fileHandler; | ||
| 668 | + }, | ||
| 98 | set: function (handler) { | 669 | set: function (handler) { |
| 99 | this._fileHandler = handler; | 670 | this._fileHandler = handler; |
| 100 | }, | 671 | }, |
| ... | @@ -155,26 +726,36 @@ var FileReplicator = (function (_super) { | ... | @@ -155,26 +726,36 @@ var FileReplicator = (function (_super) { |
| 155 | enumerable: true, | 726 | enumerable: true, |
| 156 | configurable: true | 727 | configurable: true |
| 157 | }); | 728 | }); |
| 158 | - FileReplicator.prototype.init = function (files) { | 729 | + Object.defineProperty(FileReplicator.prototype, "targetDirectory", { |
| 730 | + get: function () { | ||
| 731 | + return this._targetDirectory; | ||
| 732 | + }, | ||
| 733 | + set: function (targetDirectory) { | ||
| 734 | + this._targetDirectory = targetDirectory; | ||
| 735 | + }, | ||
| 736 | + enumerable: true, | ||
| 737 | + configurable: true | ||
| 738 | + }); | ||
| 739 | + FileReplicator.prototype.clear = function (files) { | ||
| 159 | if (files === void 0) { files = []; } | 740 | if (files === void 0) { files = []; } |
| 160 | this._files = files; | 741 | this._files = files; |
| 161 | }; | 742 | }; |
| 162 | /** | 743 | /** |
| 163 | * change from pouchdb replicate | 744 | * change from pouchdb replicate |
| 164 | */ | 745 | */ |
| 165 | - FileReplicator.prototype.pushChanges = function (change) { | 746 | + FileReplicator.prototype.pushChanges = function (docs) { |
| 166 | var items = []; | 747 | var items = []; |
| 167 | - if (change && change.docs && change.docs.length > 0) { | 748 | + if (docs && docs.length > 0) { |
| 168 | - for (var _i = 0, _a = change.docs; _i < _a.length; _i++) { | 749 | + for (var _i = 0, docs_1 = docs; _i < docs_1.length; _i++) { |
| 169 | - var item = _a[_i]; | 750 | + var item = docs_1[_i]; |
| 170 | if (item[this._itemKey] && item[this._itemKey] === this._itemValue) { | 751 | if (item[this._itemKey] && item[this._itemKey] === this._itemValue) { |
| 171 | items.push(item); | 752 | items.push(item); |
| 172 | } | 753 | } |
| 173 | } | 754 | } |
| 174 | } | 755 | } |
| 175 | var files = this.prepareFiles(items); | 756 | var files = this.prepareFiles(items); |
| 176 | - for (var _b = 0, files_1 = files; _b < files_1.length; _b++) { | 757 | + for (var _a = 0, files_1 = files; _a < files_1.length; _a++) { |
| 177 | - var file = files_1[_b]; | 758 | + var file = files_1[_a]; |
| 178 | this._files.push(file); | 759 | this._files.push(file); |
| 179 | } | 760 | } |
| 180 | }; | 761 | }; |
| ... | @@ -186,15 +767,19 @@ var FileReplicator = (function (_super) { | ... | @@ -186,15 +767,19 @@ var FileReplicator = (function (_super) { |
| 186 | } | 767 | } |
| 187 | this.emit('start', { progress: 0, index: index, length: files.length }); | 768 | this.emit('start', { progress: 0, index: index, length: files.length }); |
| 188 | fileHandler | 769 | fileHandler |
| 189 | - .download(files[index].source, files[index].target) | 770 | + .on('progress', function (progress) { |
| 190 | - .subscribe(function (progress) { | 771 | + _this.emit('file-progress', { progress: progress, index: index, length: files.length }); |
| 191 | - _this.emit('progress', { progress: progress, index: index, length: files.length }); | 772 | + }) |
| 192 | - }, function (error) { | 773 | + .once('error', function (error) { |
| 193 | - _this.emit('error', { progress: 0, index: index, length: files.length, error: error }); | 774 | + _this.emit('file-error', { progress: 0, index: index, length: files.length, error: error }); |
| 194 | - }, function () { | 775 | + fileHandler.removeAllListeners(); |
| 195 | - _this.emit('complete', { progress: 100, index: index, length: files.length }); | 776 | + }) |
| 777 | + .once('complete', function () { | ||
| 778 | + _this.emit('file-complete', { progress: 100, index: index, length: files.length }); | ||
| 779 | + fileHandler.removeAllListeners(); | ||
| 196 | _this.downloadFiles(files, fileHandler, index + 1); | 780 | _this.downloadFiles(files, fileHandler, index + 1); |
| 197 | - }); | 781 | + }) |
| 782 | + .download(files[index].source, this.targetDirectory + files[index].target); | ||
| 198 | }; | 783 | }; |
| 199 | FileReplicator.prototype.prepareFiles = function (items) { | 784 | FileReplicator.prototype.prepareFiles = function (items) { |
| 200 | var output = []; | 785 | var output = []; |
| ... | @@ -213,41 +798,62 @@ var FileReplicator = (function (_super) { | ... | @@ -213,41 +798,62 @@ var FileReplicator = (function (_super) { |
| 213 | } | 798 | } |
| 214 | return output; | 799 | return output; |
| 215 | }; | 800 | }; |
| 216 | - FileReplicator.prototype.start = function () { | 801 | + FileReplicator.prototype.start = function (retries) { |
| 217 | var _this = this; | 802 | var _this = this; |
| 218 | - this.on('complete', function (event) { | 803 | + if (retries === void 0) { retries = 10; } |
| 804 | + this._retries = retries; | ||
| 805 | + this.on('file-complete', function (event) { | ||
| 219 | if ((event.index + 1) >= event.length) { | 806 | if ((event.index + 1) >= event.length) { |
| 220 | _this.replicationFinalized(event.index); | 807 | _this.replicationFinalized(event.index); |
| 221 | } | 808 | } |
| 222 | }); | 809 | }); |
| 223 | - this.on('error', function (event) { | 810 | + this.on('file-error', function (event) { |
| 224 | _this.replicationFinalized(event.index); | 811 | _this.replicationFinalized(event.index); |
| 225 | }); | 812 | }); |
| 226 | - this.downloadFiles(this._files, this._fileHandler); | 813 | + if (this._fileHandler && this._files.length > 0) { |
| 814 | + this.downloadFiles(this._files, this._fileHandler); | ||
| 815 | + } | ||
| 816 | + else { | ||
| 817 | + this.emit('complete'); | ||
| 818 | + } | ||
| 819 | + }; | ||
| 820 | + FileReplicator.prototype.cleanup = function () { | ||
| 821 | + var _this = this; | ||
| 822 | + this.fileHandler | ||
| 823 | + .cleanup(this._files, this._targetDirectory) | ||
| 824 | + .then(function () { | ||
| 825 | + _this.emit('cleanup-complete'); | ||
| 826 | + }).catch(function () { | ||
| 827 | + _this.emit('cleanup-error'); | ||
| 828 | + }); | ||
| 227 | }; | 829 | }; |
| 228 | FileReplicator.prototype.replicationFinalized = function (lastIndex) { | 830 | FileReplicator.prototype.replicationFinalized = function (lastIndex) { |
| 229 | var _this = this; | 831 | var _this = this; |
| 230 | if (lastIndex + 1 >= this._files.length) { | 832 | if (lastIndex + 1 >= this._files.length) { |
| 231 | - this._files = []; | 833 | + this.emit('complete'); |
| 232 | - this.emit('final'); | ||
| 233 | } | 834 | } |
| 234 | - else if (this._retryTimeout > 0) { | 835 | + else if (this._retries > 0) { |
| 235 | this._files.splice(0, lastIndex); | 836 | this._files.splice(0, lastIndex); |
| 236 | setTimeout(function () { | 837 | setTimeout(function () { |
| 838 | + _this._retries = -1; | ||
| 237 | _this.downloadFiles(_this._files, _this._fileHandler); | 839 | _this.downloadFiles(_this._files, _this._fileHandler); |
| 238 | }, this._retryTimeout); | 840 | }, this._retryTimeout); |
| 239 | } | 841 | } |
| 842 | + else { | ||
| 843 | + this.emit('error'); | ||
| 844 | + } | ||
| 240 | }; | 845 | }; |
| 241 | return FileReplicator; | 846 | return FileReplicator; |
| 242 | -}(events.EventEmitter)); | 847 | +}(EventEmitter)); |
| 243 | 848 | ||
| 244 | var CONFIG_ITEM_KEY = "itemKey"; | 849 | var CONFIG_ITEM_KEY = "itemKey"; |
| 245 | var CONFIG_ITEM_VALUE = "itemValue"; | 850 | var CONFIG_ITEM_VALUE = "itemValue"; |
| 246 | var CONFIG_ITEM_SOURCE_ATTRIBUTE = "itemSourceAttribute"; | 851 | var CONFIG_ITEM_SOURCE_ATTRIBUTE = "itemSourceAttribute"; |
| 247 | var CONFIG_ITEM_TARGET_ATTRIBUTE = "itemTargetAttribute"; | 852 | var CONFIG_ITEM_TARGET_ATTRIBUTE = "itemTargetAttribute"; |
| 248 | - | 853 | +var CONFIG_ITEM_VALIDATOR = "itemValidator"; |
| 249 | var CONFIG_RETRY_TIMEOUT = "retryTimeout"; | 854 | var CONFIG_RETRY_TIMEOUT = "retryTimeout"; |
| 250 | - | 855 | +var CONFIG_FILE_HANDLER = "fileHandler"; |
| 856 | +var CONFIG_TARGET_DIRECTORY = "targetDirectory"; | ||
| 251 | var Config = (function () { | 857 | var Config = (function () { |
| 252 | function Config() { | 858 | function Config() { |
| 253 | this.config = {}; | 859 | this.config = {}; |
| ... | @@ -263,6 +869,7 @@ var Config = (function () { | ... | @@ -263,6 +869,7 @@ var Config = (function () { |
| 263 | }; | 869 | }; |
| 264 | Config.prototype.setConfig = function (key, value) { | 870 | Config.prototype.setConfig = function (key, value) { |
| 265 | this.config[key] = value; | 871 | this.config[key] = value; |
| 872 | + return this; | ||
| 266 | }; | 873 | }; |
| 267 | return Config; | 874 | return Config; |
| 268 | }()); | 875 | }()); |
| ... | @@ -300,7 +907,7 @@ var ServiceLocator = (function () { | ... | @@ -300,7 +907,7 @@ var ServiceLocator = (function () { |
| 300 | return new ElectronFileHandler(window['require']('electron').ipcRenderer); | 907 | return new ElectronFileHandler(window['require']('electron').ipcRenderer); |
| 301 | } | 908 | } |
| 302 | if (environment === ENV_CORDOVA) { | 909 | if (environment === ENV_CORDOVA) { |
| 303 | - return new CordovaDownloader(); | 910 | + return new CordovaFileHandler(); |
| 304 | } | 911 | } |
| 305 | return null; | 912 | return null; |
| 306 | }; | 913 | }; |
| ... | @@ -308,21 +915,24 @@ var ServiceLocator = (function () { | ... | @@ -308,21 +915,24 @@ var ServiceLocator = (function () { |
| 308 | if (!ServiceLocator.fileReplicator) { | 915 | if (!ServiceLocator.fileReplicator) { |
| 309 | ServiceLocator.fileReplicator = new FileReplicator(); | 916 | ServiceLocator.fileReplicator = new FileReplicator(); |
| 310 | ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler(); | 917 | ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler(); |
| 311 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) { | 918 | + } |
| 312 | - ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT); | 919 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) { |
| 313 | - } | 920 | + ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT); |
| 314 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) { | 921 | + } |
| 315 | - ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY); | 922 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) { |
| 316 | - } | 923 | + ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY); |
| 317 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) { | 924 | + } |
| 318 | - ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE); | 925 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) { |
| 319 | - } | 926 | + ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE); |
| 320 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) { | 927 | + } |
| 321 | - ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE); | 928 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) { |
| 322 | - } | 929 | + ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE); |
| 323 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) { | 930 | + } |
| 324 | - ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE); | 931 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) { |
| 325 | - } | 932 | + ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE); |
| 933 | + } | ||
| 934 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_TARGET_DIRECTORY)) { | ||
| 935 | + ServiceLocator.fileReplicator.targetDirectory = ServiceLocator.getConfig().getConfig(CONFIG_TARGET_DIRECTORY); | ||
| 326 | } | 936 | } |
| 327 | return ServiceLocator.fileReplicator; | 937 | return ServiceLocator.fileReplicator; |
| 328 | }; | 938 | }; |
| ... | @@ -330,61 +940,21 @@ var ServiceLocator = (function () { | ... | @@ -330,61 +940,21 @@ var ServiceLocator = (function () { |
| 330 | return ServiceLocator; | 940 | return ServiceLocator; |
| 331 | }()); | 941 | }()); |
| 332 | 942 | ||
| 333 | -function loadBsyncPlugin(PouchDB) { | ||
| 334 | - var pouchReplicate = PouchDB.replicate; | ||
| 335 | - PouchDB.plugin(function (PouchDB) { | ||
| 336 | - PouchDB.replicate = function () { | ||
| 337 | - var eventEmitter = new events.EventEmitter(); | ||
| 338 | - var emitter = pouchReplicate.apply(this, arguments); | ||
| 339 | - var replicator = ServiceLocator.getFileReplicator(); | ||
| 340 | - var db = arguments[1]; | ||
| 341 | - replicator.once('final', function (event) { | ||
| 342 | - eventEmitter.emit('complete'); | ||
| 343 | - eventEmitter.removeAllListeners(); | ||
| 344 | - }); | ||
| 345 | - replicator.on('error', function (event) { | ||
| 346 | - eventEmitter.emit('file-replicator-error', event); | ||
| 347 | - }); | ||
| 348 | - replicator.on('complete', function (event) { | ||
| 349 | - eventEmitter.emit('file-replicator-complete', event); | ||
| 350 | - }); | ||
| 351 | - replicator.on('progress', function (event) { | ||
| 352 | - eventEmitter.emit('file-replicator-progress', event); | ||
| 353 | - }); | ||
| 354 | - emitter.once('change', function (info) { | ||
| 355 | - eventEmitter.emit('change', info); | ||
| 356 | - }); | ||
| 357 | - emitter.once('complete', function (info) { | ||
| 358 | - db.query('index_type/type', { | ||
| 359 | - include_docs: true, | ||
| 360 | - key: replicator.itemValue | ||
| 361 | - }).then(function (res) { | ||
| 362 | - var docs = { docs: [] }; | ||
| 363 | - for (var _i = 0, _a = res.rows; _i < _a.length; _i++) { | ||
| 364 | - var r = _a[_i]; | ||
| 365 | - docs.docs.push(r.doc); | ||
| 366 | - } | ||
| 367 | - replicator.pushChanges(docs); | ||
| 368 | - replicator.start(); | ||
| 369 | - }).catch(function (error) { | ||
| 370 | - eventEmitter.emit('error', error); | ||
| 371 | - }); | ||
| 372 | - }); | ||
| 373 | - emitter.once('error', function (error) { | ||
| 374 | - eventEmitter.emit('error', error); | ||
| 375 | - }); | ||
| 376 | - return eventEmitter; | ||
| 377 | - }; | ||
| 378 | - }); | ||
| 379 | -} | ||
| 380 | - | ||
| 381 | -if (typeof window !== 'undefined' && window['PouchDB']) { | ||
| 382 | - loadBsyncPlugin(window['PouchDB']); | ||
| 383 | -} | ||
| 384 | - | ||
| 385 | -exports.loadBsyncPlugin = loadBsyncPlugin; | ||
| 386 | exports.ENV_ELECTRON = ENV_ELECTRON; | 943 | exports.ENV_ELECTRON = ENV_ELECTRON; |
| 387 | exports.ENV_CORDOVA = ENV_CORDOVA; | 944 | exports.ENV_CORDOVA = ENV_CORDOVA; |
| 388 | exports.ENV_UNKNOWN = ENV_UNKNOWN; | 945 | exports.ENV_UNKNOWN = ENV_UNKNOWN; |
| 389 | exports.ServiceLocator = ServiceLocator; | 946 | exports.ServiceLocator = ServiceLocator; |
| 947 | +exports.CONFIG_ITEM_KEY = CONFIG_ITEM_KEY; | ||
| 948 | +exports.CONFIG_ITEM_VALUE = CONFIG_ITEM_VALUE; | ||
| 949 | +exports.CONFIG_ITEM_SOURCE_ATTRIBUTE = CONFIG_ITEM_SOURCE_ATTRIBUTE; | ||
| 950 | +exports.CONFIG_ITEM_TARGET_ATTRIBUTE = CONFIG_ITEM_TARGET_ATTRIBUTE; | ||
| 951 | +exports.CONFIG_ITEM_VALIDATOR = CONFIG_ITEM_VALIDATOR; | ||
| 952 | +exports.CONFIG_RETRY_TIMEOUT = CONFIG_RETRY_TIMEOUT; | ||
| 953 | +exports.CONFIG_FILE_HANDLER = CONFIG_FILE_HANDLER; | ||
| 954 | +exports.CONFIG_TARGET_DIRECTORY = CONFIG_TARGET_DIRECTORY; | ||
| 955 | +exports.Config = Config; | ||
| 956 | + | ||
| 957 | +Object.defineProperty(exports, '__esModule', { value: true }); | ||
| 958 | + | ||
| 959 | +}))); | ||
| 390 | //# sourceMappingURL=browser-build.js.map | 960 | //# sourceMappingURL=browser-build.js.map | ... | ... |
| 1 | -{"version":3,"file":null,"sources":["../src/file-handler/electron-file-handler.ts","../src/file-handler/cordova-file-handler.ts","../src/util.ts","../src/file-replicator.ts","../src/config.ts","../src/service-locator.ts","../src/browser-main.ts"],"sourcesContent":["import { Observable, Subscriber } from 'rxjs';\nimport { FileHandler } from '../api/file-handler';\n\nexport class ElectronFileHandler implements FileHandler {\n\n constructor (private ipcRenderer:any) {\n }\n\n download(source:string, target:string) : Observable<number> {\n return Observable.create((subscriber:Subscriber<number>) => {\n\n this.ipcRenderer.once('bsync-download-complete', () => {\n this.ipcRenderer.removeAllListeners('bsync-download-progress');\n this.ipcRenderer.removeAllListeners('bsync-download-error');\n subscriber.complete();\n });\n\n this.ipcRenderer.on('bsync-download-progress', (progress:number) => {\n subscriber.next(progress);\n });\n\n this.ipcRenderer.once('bsync-download-error', (error:any) => {\n this.ipcRenderer.removeAllListeners('bsync-download-progress');\n this.ipcRenderer.removeAllListeners('bsync-download-complete');\n subscriber.error(error);\n });\n\n this.ipcRenderer.send('bsync-download', {\n source : source ,\n target : target\n });\n });\n }\n\n}","import { FileHandler } from '../api/file-handler';\n\ndeclare var Rx;\n\nexport class CordovaDownloader implements FileHandler {\n\n download(source:string, target:string) : Rx.Observable<number> {\n return Rx.Observable.create((subscriber:Rx.Subscriber<number>) => {\n\n if (!window['FileTransfer']) {\n subscriber.error(\"Cordova FileTransfer object undefined\");\n }\n\n let fileTransfer = new window['FileTransfer']();\n\n fileTransfer.onprogress = (progress:ProgressEvent) => {\n subscriber.next(progress.loaded / progress.total);\n };\n\n fileTransfer.download(\n source ,\n target ,\n (entry:any) => {\n subscriber.complete();\n } ,\n (error:any) => {\n subscriber.error(error);\n },\n true\n );\n\n }); \n }\n\n}","export class Util {\n\n static getNameHash(path:string) {\n for(var r=0,i=0;i<path.length;i++) {\n r=(r<<5)-r+path.charCodeAt(i),r&=r;\n }\n return \"bsync_\" + Math.abs(r);\n }\n\n}","import {FileHandler} from './api/file-handler';\nimport {File} from './api/file';\nimport {Util} from './util';\nimport {EventEmitter} from 'events';\n\nexport class FileReplicator extends EventEmitter {\n\n constructor() {\n super();\n }\n\n protected _files:Array<File> = [];\n\n protected _itemValidator: (item:any) => boolean = null; \n protected _fileHandler:FileHandler = null; \n protected _retryTimeout:number = 0;\n \n protected _itemKey = \"type\";\n protected _itemValue = \"asset\";\n protected _itemSourceAttribute = \"source\";\n protected _itemTargetAttribute = \"target\";\n\n get files(): Array<File> {\n return this._files;\n }\n\n set fileHandler (handler:FileHandler) {\n this._fileHandler = handler;\n }\n\n set retryTimeout (timeout:number) {\n this._retryTimeout = timeout;\n }\n\n set itemValidator(validator:(item:any) => boolean) {\n this._itemValidator = validator;\n }\n\n set itemKey(key:string) {\n this._itemKey = key;\n }\n\n set itemValue(value:string) {\n this._itemValue = value;\n }\n\n set itemSourceAttribute(sourceAttribute:string) {\n this._itemSourceAttribute = sourceAttribute;\n }\n\n set itemTargetAttribute(targetAttribute:string) {\n this._itemTargetAttribute = targetAttribute;\n }\n\n get itemKey() {\n return this._itemKey;\n }\n\n get itemValue() {\n return this._itemValue;\n }\n\n get itemSourceAttribute() {\n return this._itemSourceAttribute;\n }\n\n get itemTargetAttribute() {\n return this._itemTargetAttribute;\n }\n\n init(files: Array<File> = []) {\n this._files = files;\n }\n\n /**\n * change from pouchdb replicate\n */\n pushChanges(change:any) {\n let items:Array<any> = [];\n\n if (change && change.docs && change.docs.length > 0) {\n for (let item of change.docs) {\n if (item[this._itemKey] && item[this._itemKey] === this._itemValue) {\n items.push(item);\n }\n }\n }\n \n let files = this.prepareFiles(items);\n\n for (let file of files) {\n this._files.push(file);\n }\n }\n\n downloadFiles(files:Array<File>, fileHandler:FileHandler, index:number = 0) { \n if (index >= files.length) {\n return;\n }\n\n this.emit('start', { progress: 0, index : index, length : files.length });\n\n fileHandler\n .download(files[index].source, files[index].target)\n .subscribe(\n progress => {\n this.emit('progress', { progress : progress, index : index, length : files.length })\n } ,\n error => {\n this.emit('error', { progress : 0, index : index, length : files.length, error: error });\n } ,\n () => {\n this.emit('complete', { progress : 100 , index : index, length : files.length });\n this.downloadFiles(files, fileHandler, index+1);\n }\n );\n }\n\n prepareFiles(items: Array<any>) : Array<File> {\n let output = [];\n\n for (let item of items) {\n if (item[this._itemSourceAttribute] && (!this._itemValidator || this._itemValidator(item))) {\n let file = { source : item[this._itemSourceAttribute] , target : '' };\n\n if (item[this._itemTargetAttribute]) {\n file.target = item[this._itemTargetAttribute];\n } else {\n file.target = Util.getNameHash(file.source);\n }\n\n output.push(file);\n }\n }\n\n return output;\n }\n\n start() {\n this.on('complete', (event:any) => {\n if ((event.index + 1) >= event.length) {\n this.replicationFinalized(event.index);\n }\n });\n\n this.on('error', (event:any) => {\n this.replicationFinalized(event.index);\n }); \n\n this.downloadFiles(this._files, this._fileHandler);\n }\n\n replicationFinalized(lastIndex:number) { \n if (lastIndex+1 >= this._files.length) { // all finished\n this._files = [];\n this.emit('final');\n } else if (this._retryTimeout > 0) { // restart after last success \n this._files.splice(0,lastIndex);\n setTimeout(() => { \n this.downloadFiles(this._files, this._fileHandler);\n }, this._retryTimeout);\n } \n }\n\n}","export const CONFIG_ITEM_KEY = \"itemKey\";\nexport const CONFIG_ITEM_VALUE = \"itemValue\";\nexport const CONFIG_ITEM_SOURCE_ATTRIBUTE = \"itemSourceAttribute\";\nexport const CONFIG_ITEM_TARGET_ATTRIBUTE = \"itemTargetAttribute\";\nexport const CONFIG_ITEM_VALIDATOR = \"itemValidator\";\nexport const CONFIG_RETRY_TIMEOUT = \"retryTimeout\";\nexport const CONFIG_FILE_HANDLER = \"fileHandler\";\n\nexport class Config {\n\n protected config:any = {};\n\n hasConfig(key:string) {\n if (this.config[key]) {\n return true;\n }\n return false;\n }\n\n getConfig(key:string) {\n return this.config[key];\n }\n\n setConfig(key:string, value:any) {\n this.config[key] = value;\n }\n\n}","import {FileHandler} from './api/file-handler';\nimport {ElectronFileHandler} from './file-handler/electron-file-handler';\nimport {CordovaDownloader} from './file-handler/cordova-file-handler';\nimport {FileReplicator} from './file-replicator';\nimport {\n Config,\n CONFIG_RETRY_TIMEOUT,\n CONFIG_ITEM_KEY,\n CONFIG_ITEM_VALUE,\n CONFIG_ITEM_TARGET_ATTRIBUTE,\n CONFIG_ITEM_SOURCE_ATTRIBUTE\n} from './config';\n\nexport const ENV_ELECTRON = \"electron\";\nexport const ENV_CORDOVA = \"cordova\";\nexport const ENV_UNKNOWN = \"unknown\";\n\nexport class ServiceLocator {\n\n protected static fileHandlers:any = {};\n protected static fileReplicator: FileReplicator;\n protected static config: Config;\n\n static addFileHandler(environment:string, fileHandler:FileHandler) {\n ServiceLocator.fileHandlers[environment] = fileHandler;\n }\n\n static getConfig() : Config {\n if (!ServiceLocator.config) {\n ServiceLocator.config = new Config();\n }\n\n return ServiceLocator.config;\n }\n\n static getEnvironment() {\n if (typeof window['require'] === 'function' && window['require']('electron')) {\n return ENV_ELECTRON;\n }\n if (typeof window['FileTransfer'] === 'function') {\n return ENV_CORDOVA;\n }\n\n return ENV_UNKNOWN;\n }\n\n static getFileHandler() : FileHandler {\n let environment = ServiceLocator.getEnvironment();\n\n if (ServiceLocator.fileHandlers[environment]) {\n return ServiceLocator.fileHandlers[environment];\n }\n\n if (environment === ENV_ELECTRON) {\n return new ElectronFileHandler(window['require']('electron').ipcRenderer);\n }\n\n if (environment === ENV_CORDOVA) {\n return new CordovaDownloader();\n }\n \n return null;\n }\n\n static getFileReplicator() : FileReplicator {\n if (!ServiceLocator.fileReplicator) {\n\n ServiceLocator.fileReplicator = new FileReplicator();\n\n ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler();\n\n if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) {\n ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) {\n ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) {\n ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) {\n ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) {\n ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE);\n }\n } \n\n return ServiceLocator.fileReplicator;\n }\n\n}","import { EventEmitter } from 'events';\nimport { ServiceLocator } from './service-locator';\n\nexport * from './service-locator';\n\nexport function loadBsyncPlugin (PouchDB) {\n let pouchReplicate = PouchDB.replicate; \n\n PouchDB.plugin((PouchDB) => {\n PouchDB.replicate = function() {\n let eventEmitter = new EventEmitter();\n let emitter = pouchReplicate.apply(this, arguments);\n let replicator = ServiceLocator.getFileReplicator();\n let db = arguments[1]; \n \n replicator.once('final', event => { \n eventEmitter.emit('complete');\n eventEmitter.removeAllListeners();\n });\n\n replicator.on('error', event => {\n eventEmitter.emit('file-replicator-error', event);\n });\n\n replicator.on('complete', event => {\n eventEmitter.emit('file-replicator-complete', event);\n });\n\n replicator.on('progress', event => {\n eventEmitter.emit('file-replicator-progress', event);\n });\n \n emitter.once('change', info => { \n eventEmitter.emit('change', info);\n });\n\n emitter.once('complete', info => { \n db.query('index_type/type',{\n include_docs : true,\n key : replicator.itemValue\n }).then((res) => { \n let docs = { docs : [] }; \n for (let r of res.rows) {\n docs.docs.push(r.doc);\n }\n\n replicator.pushChanges(docs);\n replicator.start();\n }).catch(error => {\n eventEmitter.emit('error', error);\n });\n });\n\n emitter.once('error', (error) => {\n eventEmitter.emit('error', error);\n });\n\n return eventEmitter;\n };\n });\n};\n\nif (typeof window !== 'undefined' && window['PouchDB']) {\n loadBsyncPlugin(window['PouchDB']);\n}\n"],"names":["Observable","EventEmitter"],"mappings":"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"} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +{"version":3,"file":null,"sources":["../node_modules/rollup-plugin-node-builtins/src/es6/events.js","../src/file-handler/electron-file-handler.ts","../src/util.ts","../src/file-handler/cordova-file-handler.ts","../src/file-replicator.ts","../src/config.ts","../src/service-locator.ts"],"sourcesContent":["'use strict';\n\nvar domain;\n\n// This constructor is used to store event handlers. Instantiating this is\n// faster than explicitly calling `Object.create(null)` to get a \"clean\" empty\n// object (tested with v8 v4.9).\nfunction EventHandlers() {}\nEventHandlers.prototype = Object.create(null);\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nexport default EventEmitter;\nexport {EventEmitter};\n\nEventEmitter.usingDomains = false;\n\nEventEmitter.prototype.domain = undefined;\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nEventEmitter.defaultMaxListeners = 10;\n\nEventEmitter.init = function() {\n this.domain = null;\n if (EventEmitter.usingDomains) {\n // if there is an active domain, then attach to it.\n if (domain.active && !(this instanceof domain.Domain)) {\n this.domain = domain.active;\n }\n }\n\n if (!this._events || this._events === Object.getPrototypeOf(this)._events) {\n this._events = new EventHandlers();\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || isNaN(n))\n throw new TypeError('\"n\" argument must be a positive number');\n this._maxListeners = n;\n return this;\n};\n\nfunction $getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return $getMaxListeners(this);\n};\n\n// These standalone emit* functions are used to optimize calling of event\n// handlers for fast cases because emit() itself often has a variable number of\n// arguments and can be deoptimized because of that. These functions always have\n// the same number of arguments and thus do not get deoptimized, so the code\n// inside them can execute faster.\nfunction emitNone(handler, isFn, self) {\n if (isFn)\n handler.call(self);\n else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n listeners[i].call(self);\n }\n}\nfunction emitOne(handler, isFn, self, arg1) {\n if (isFn)\n handler.call(self, arg1);\n else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n listeners[i].call(self, arg1);\n }\n}\nfunction emitTwo(handler, isFn, self, arg1, arg2) {\n if (isFn)\n handler.call(self, arg1, arg2);\n else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n listeners[i].call(self, arg1, arg2);\n }\n}\nfunction emitThree(handler, isFn, self, arg1, arg2, arg3) {\n if (isFn)\n handler.call(self, arg1, arg2, arg3);\n else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n listeners[i].call(self, arg1, arg2, arg3);\n }\n}\n\nfunction emitMany(handler, isFn, self, args) {\n if (isFn)\n handler.apply(self, args);\n else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n listeners[i].apply(self, args);\n }\n}\n\nEventEmitter.prototype.emit = function emit(type) {\n var er, handler, len, args, i, events, domain;\n var needDomainExit = false;\n var doError = (type === 'error');\n\n events = this._events;\n if (events)\n doError = (doError && events.error == null);\n else if (!doError)\n return false;\n\n domain = this.domain;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n er = arguments[1];\n if (domain) {\n if (!er)\n er = new Error('Uncaught, unspecified \"error\" event');\n er.domainEmitter = this;\n er.domain = domain;\n er.domainThrown = false;\n domain.emit('error', er);\n } else if (er instanceof Error) {\n throw er; // Unhandled 'error' event\n } else {\n // At least give some kind of context to the user\n var err = new Error('Uncaught, unspecified \"error\" event. (' + er + ')');\n err.context = er;\n throw err;\n }\n return false;\n }\n\n handler = events[type];\n\n if (!handler)\n return false;\n\n var isFn = typeof handler === 'function';\n len = arguments.length;\n switch (len) {\n // fast cases\n case 1:\n emitNone(handler, isFn, this);\n break;\n case 2:\n emitOne(handler, isFn, this, arguments[1]);\n break;\n case 3:\n emitTwo(handler, isFn, this, arguments[1], arguments[2]);\n break;\n case 4:\n emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);\n break;\n // slower\n default:\n args = new Array(len - 1);\n for (i = 1; i < len; i++)\n args[i - 1] = arguments[i];\n emitMany(handler, isFn, this, args);\n }\n\n if (needDomainExit)\n domain.exit();\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n if (typeof listener !== 'function')\n throw new TypeError('\"listener\" argument must be a function');\n\n events = target._events;\n if (!events) {\n events = target._events = new EventHandlers();\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (!existing) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] = prepend ? [listener, existing] :\n [existing, listener];\n } else {\n // If we've already got an array, just append.\n if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n }\n\n // Check for listener leak\n if (!existing.warned) {\n m = $getMaxListeners(target);\n if (m && m > 0 && existing.length > m) {\n existing.warned = true;\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + type + ' listeners added. ' +\n 'Use emitter.setMaxListeners() to increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n emitWarning(w);\n }\n }\n }\n\n return target;\n}\nfunction emitWarning(e) {\n typeof console.warn === 'function' ? console.warn(e) : console.log(e);\n}\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction _onceWrap(target, type, listener) {\n var fired = false;\n function g() {\n target.removeListener(type, g);\n if (!fired) {\n fired = true;\n listener.apply(target, arguments);\n }\n }\n g.listener = listener;\n return g;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n if (typeof listener !== 'function')\n throw new TypeError('\"listener\" argument must be a function');\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n if (typeof listener !== 'function')\n throw new TypeError('\"listener\" argument must be a function');\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n if (typeof listener !== 'function')\n throw new TypeError('\"listener\" argument must be a function');\n\n events = this._events;\n if (!events)\n return this;\n\n list = events[type];\n if (!list)\n return this;\n\n if (list === listener || (list.listener && list.listener === listener)) {\n if (--this._eventsCount === 0)\n this._events = new EventHandlers();\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length; i-- > 0;) {\n if (list[i] === listener ||\n (list[i].listener && list[i].listener === listener)) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (list.length === 1) {\n list[0] = undefined;\n if (--this._eventsCount === 0) {\n this._events = new EventHandlers();\n return this;\n } else {\n delete events[type];\n }\n } else {\n spliceOne(list, position);\n }\n\n if (events.removeListener)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events;\n\n events = this._events;\n if (!events)\n return this;\n\n // not listening for removeListener, no need to emit\n if (!events.removeListener) {\n if (arguments.length === 0) {\n this._events = new EventHandlers();\n this._eventsCount = 0;\n } else if (events[type]) {\n if (--this._eventsCount === 0)\n this._events = new EventHandlers();\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n for (var i = 0, key; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = new EventHandlers();\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners) {\n // LIFO order\n do {\n this.removeListener(type, listeners[listeners.length - 1]);\n } while (listeners[0]);\n }\n\n return this;\n };\n\nEventEmitter.prototype.listeners = function listeners(type) {\n var evlistener;\n var ret;\n var events = this._events;\n\n if (!events)\n ret = [];\n else {\n evlistener = events[type];\n if (!evlistener)\n ret = [];\n else if (typeof evlistener === 'function')\n ret = [evlistener.listener || evlistener];\n else\n ret = unwrapListeners(evlistener);\n }\n\n return ret;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];\n};\n\n// About 1.5x faster than the two-arg version of Array#splice().\nfunction spliceOne(list, index) {\n for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)\n list[i] = list[k];\n list.pop();\n}\n\nfunction arrayClone(arr, i) {\n var copy = new Array(i);\n while (i--)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n","import { EventEmitter } from 'events';\nimport { FileHandler } from '../api/file-handler';\nimport { File } from '../api/file';\n\nexport class ElectronFileHandler extends EventEmitter implements FileHandler {\n\n constructor (private ipcRenderer:any) {\n super();\n }\n\n download(source:string, target:string) {\n this.ipcRenderer.once('bsync-download-complete', () => {\n this.ipcRenderer.removeAllListeners('bsync-download-progress');\n this.ipcRenderer.removeAllListeners('bsync-download-error');\n this.emit('complete');\n });\n\n this.ipcRenderer.on('bsync-download-progress', (progress:number) => {\n this.emit('progress', progress);\n });\n\n this.ipcRenderer.once('bsync-download-error', (error:any) => {\n this.ipcRenderer.removeAllListeners('bsync-download-progress');\n this.ipcRenderer.removeAllListeners('bsync-download-complete');\n this.emit('error', error);\n });\n\n this.ipcRenderer.send('bsync-download', {\n source : source ,\n target : target\n });\n\n return this; \n }\n\n cleanup(files:Array<File>) : Promise<void> {\n return new Promise<void>((resolve, reject) => {\n\n this.ipcRenderer.once('bsync-cleanup-complete', () => {\n this.emit('cleanup-complete');\n resolve();\n });\n\n this.ipcRenderer.send('bsync-cleanup', files);\n\n });\n }\n\n}","import { File } from './api/file';\n\nexport class Util {\n\n static getNameHash(path:string) {\n for(var r=0,i=0;i<path.length;i++) {\n r=(r<<5)-r+path.charCodeAt(i),r&=r;\n }\n return \"bsync_\" + Math.abs(r);\n }\n\n /**\n * index >= 0, localFile is in files\n * index < 0, localFile is not in files\n */\n static getFileIndex(files:Array<File>, localFile:string) : number {\n for (let i = 0; i < files.length; i++) {\n if (localFile == files[i].target) {\n return i;\n }\n }\n return -1;\n }\n\n static getFilesForCleanup(files:Array<File>, localFiles:Array<string>) : Array<string> {\n let filesForCleanup = [];\n\n for (let localFile of localFiles) {\n let index = -1;\n\n index = Util.getFileIndex(files, localFile);\n \n if (index < 0) {\n filesForCleanup.push(localFile);\n } else {\n // splice for performance improvement only\n files.splice(index,1);\n }\n }\n\n return filesForCleanup;\n }\n\n}","import { Util } from './../util';\nimport { EventEmitter } from 'events';\nimport { FileHandler } from '../api/file-handler';\nimport { File } from '../api/file';\n\nexport class CordovaFileHandler extends EventEmitter implements FileHandler {\n\n triggerFileTransfer(source:string, target:string) {\n let fileTransfer = new window['FileTransfer']();\n\n fileTransfer.onprogress = (progress:ProgressEvent) => {\n this.emit('progress', progress.loaded / progress.total);\n };\n\n fileTransfer.download(\n source ,\n target ,\n (entry:any) => {\n this.emit('complete', entry);\n } ,\n (error:any) => {\n this.emit('error', error);\n },\n true\n );\n }\n\n download(source:string, target:string) {\n if (!window['FileTransfer']) {\n this.emit('error','Cordova FileTransfer object undefined');\n }\n\n window['resolveLocalFileSystemURL'](target, (entry:any) => {\n entry.getMetadata((metadata) => {\n if (metadata.size > 0) {\n this.emit('complete', entry);\n } else {\n // file empty trigger transfer\n this.triggerFileTransfer(source,target);\n }\n }, () => {\n // cannot read metadata trigger transfer\n this.triggerFileTransfer(source,target);\n });\n }, () => {\n // file not found, so download it\n this.triggerFileTransfer(source,target);\n });\n\n return this; \n }\n\n cleanup(files:Array<File>, basePath:string) : Promise<void> {\n let filesForCleanup = [];\n\n return new Promise<void>((resolve, reject) => {\n\n if (window['resolveLocalFileSystemURL']) {\n window['resolveLocalFileSystemURL'](basePath, (entry) => {\n let reader = entry.createReader();\n reader.readEntries((entries) => {\n\n for (let e of entries) {\n if (e && e.isFile) {\n if (Util.getFileIndex(files, e.name) < 0) {\n filesForCleanup.push(e);\n }\n }\n }\n \n let index = 0;\n let error = false;\n\n let cleanupError = (error) => {\n this.emit('cleanup-error', error);\n reject();\n error = true;\n };\n\n let cleanupNext = () => {\n if (index < filesForCleanup.length && !error) {\n filesForCleanup[index].remove(cleanupNext, cleanupError);\n index += 1;\n } else if (!error) { \n this.emit('cleanup-complete', filesForCleanup);\n resolve();\n }\n };\n \n cleanupNext();\n\n }, (error) => { this.emit('cleanup-error', error); reject(); });\n });\n }\n\n });\n }\n\n}","import { FileHandler } from './api/file-handler';\nimport { File } from './api/file';\nimport { Util } from './util';\nimport { EventEmitter } from 'events';\n\nexport class FileReplicator extends EventEmitter {\n\n constructor() {\n super();\n }\n\n protected _files: Array<File> = [];\n\n protected _itemValidator: (item: any) => boolean = null;\n protected _fileHandler: FileHandler = null;\n protected _retryTimeout: number = 100;\n protected _retries: number = 10;\n\n protected _itemKey = \"type\";\n protected _itemValue = \"asset\";\n protected _itemSourceAttribute = \"source\";\n protected _itemTargetAttribute = \"target\";\n protected _targetDirectory = \"\";\n\n get files(): Array<File> {\n return this._files;\n }\n\n set fileHandler(handler: FileHandler) {\n this._fileHandler = handler;\n }\n\n get fileHandler() : FileHandler {\n return this._fileHandler;\n }\n\n set retryTimeout(timeout: number) {\n this._retryTimeout = timeout;\n }\n\n set itemValidator(validator: (item: any) => boolean) {\n this._itemValidator = validator;\n }\n\n set itemKey(key: string) {\n this._itemKey = key;\n }\n\n set itemValue(value: string) {\n this._itemValue = value;\n }\n\n set itemSourceAttribute(sourceAttribute: string) {\n this._itemSourceAttribute = sourceAttribute;\n }\n\n set itemTargetAttribute(targetAttribute: string) {\n this._itemTargetAttribute = targetAttribute;\n }\n\n get itemKey() {\n return this._itemKey;\n }\n\n get itemValue() {\n return this._itemValue;\n }\n\n get itemSourceAttribute() {\n return this._itemSourceAttribute;\n }\n\n get itemTargetAttribute() {\n return this._itemTargetAttribute;\n }\n\n set targetDirectory(targetDirectory: string) {\n this._targetDirectory = targetDirectory;\n }\n\n get targetDirectory() {\n return this._targetDirectory;\n }\n\n clear(files: Array<File> = []) {\n this._files = files;\n }\n\n /**\n * change from pouchdb replicate\n */\n pushChanges(docs: Array<any>) {\n let items: Array<any> = [];\n\n if (docs && docs.length > 0) {\n for (let item of docs) {\n if (item[this._itemKey] && item[this._itemKey] === this._itemValue) {\n items.push(item);\n }\n }\n }\n\n let files = this.prepareFiles(items);\n\n for (let file of files) {\n this._files.push(file);\n }\n }\n\n downloadFiles(files: Array<File>, fileHandler: FileHandler, index: number = 0) {\n if (index >= files.length) {\n return;\n }\n\n this.emit('start', { progress: 0, index: index, length: files.length });\n \n fileHandler\n .on('progress', (progress) => {\n this.emit('file-progress', { progress: progress, index: index, length: files.length })\n })\n .once('error', error => {\n this.emit('file-error', { progress: 0, index: index, length: files.length, error: error });\n fileHandler.removeAllListeners();\n })\n .once('complete', () => {\n this.emit('file-complete', { progress: 100, index: index, length: files.length });\n fileHandler.removeAllListeners();\n this.downloadFiles(files, fileHandler, index + 1);\n })\n .download(files[index].source, this.targetDirectory + files[index].target); \n }\n\n prepareFiles(items: Array<any>): Array<File> {\n let output = [];\n\n for (let item of items) {\n if (item[this._itemSourceAttribute] && (!this._itemValidator || this._itemValidator(item))) {\n let file = { source: item[this._itemSourceAttribute], target: '' };\n\n if (item[this._itemTargetAttribute]) {\n file.target = item[this._itemTargetAttribute];\n } else {\n file.target = Util.getNameHash(file.source);\n }\n\n output.push(file);\n }\n }\n\n return output;\n }\n\n start(retries:number = 10) {\n this._retries = retries;\n\n this.on('file-complete', (event: any) => {\n if ((event.index + 1) >= event.length) {\n this.replicationFinalized(event.index);\n }\n });\n\n this.on('file-error', (event: any) => {\n this.replicationFinalized(event.index);\n });\n\n if (this._fileHandler && this._files.length > 0) {\n this.downloadFiles(this._files, this._fileHandler);\n } else {\n this.emit('complete');\n } \n }\n\n cleanup() {\n this.fileHandler\n .cleanup(this._files, this._targetDirectory)\n .then(() => {\n this.emit('cleanup-complete');\n }).catch(() => {\n this.emit('cleanup-error');\n });\n }\n\n replicationFinalized(lastIndex: number) {\n if (lastIndex + 1 >= this._files.length) { // all finished\n this.emit('complete');\n } else if (this._retries > 0) { // restart after last success \n this._files.splice(0, lastIndex);\n setTimeout(() => {\n this._retries =- 1;\n this.downloadFiles(this._files, this._fileHandler);\n }, this._retryTimeout);\n } else {\n this.emit('error');\n }\n }\n\n}","export const CONFIG_ITEM_KEY = \"itemKey\";\nexport const CONFIG_ITEM_VALUE = \"itemValue\";\nexport const CONFIG_ITEM_SOURCE_ATTRIBUTE = \"itemSourceAttribute\";\nexport const CONFIG_ITEM_TARGET_ATTRIBUTE = \"itemTargetAttribute\";\nexport const CONFIG_ITEM_VALIDATOR = \"itemValidator\";\nexport const CONFIG_RETRY_TIMEOUT = \"retryTimeout\";\nexport const CONFIG_FILE_HANDLER = \"fileHandler\";\nexport const CONFIG_TARGET_DIRECTORY = \"targetDirectory\";\n\nexport class Config {\n\n protected config:any = {};\n\n hasConfig(key:string) : boolean {\n if (this.config[key]) {\n return true;\n }\n return false;\n }\n\n getConfig(key:string) : any {\n return this.config[key];\n }\n\n setConfig(key:string, value:any) : Config {\n this.config[key] = value;\n return this;\n }\n\n}","import {FileHandler} from './api/file-handler';\nimport {ElectronFileHandler} from './file-handler/electron-file-handler';\nimport {CordovaFileHandler} from './file-handler/cordova-file-handler';\nimport {FileReplicator} from './file-replicator';\nimport {\n Config,\n CONFIG_RETRY_TIMEOUT,\n CONFIG_ITEM_KEY,\n CONFIG_ITEM_VALUE,\n CONFIG_ITEM_TARGET_ATTRIBUTE,\n CONFIG_ITEM_SOURCE_ATTRIBUTE,\n CONFIG_TARGET_DIRECTORY\n} from './config';\n\nexport const ENV_ELECTRON = \"electron\";\nexport const ENV_CORDOVA = \"cordova\";\nexport const ENV_UNKNOWN = \"unknown\";\n\nexport class ServiceLocator {\n\n protected static fileHandlers:any = {};\n protected static fileReplicator: FileReplicator;\n protected static config: Config;\n\n static addFileHandler(environment:string, fileHandler:FileHandler) {\n ServiceLocator.fileHandlers[environment] = fileHandler;\n }\n\n static getConfig() : Config {\n if (!ServiceLocator.config) {\n ServiceLocator.config = new Config();\n }\n\n return ServiceLocator.config;\n }\n\n static getEnvironment() {\n if (typeof window['require'] === 'function' && window['require']('electron')) {\n return ENV_ELECTRON;\n }\n if (typeof window['FileTransfer'] === 'function') {\n return ENV_CORDOVA;\n }\n\n return ENV_UNKNOWN;\n }\n\n static getFileHandler() : FileHandler {\n let environment = ServiceLocator.getEnvironment();\n\n if (ServiceLocator.fileHandlers[environment]) {\n return ServiceLocator.fileHandlers[environment];\n }\n\n if (environment === ENV_ELECTRON) {\n return new ElectronFileHandler(window['require']('electron').ipcRenderer);\n }\n\n if (environment === ENV_CORDOVA) {\n return new CordovaFileHandler();\n }\n \n return null;\n }\n\n static getFileReplicator() : FileReplicator {\n if (!ServiceLocator.fileReplicator) {\n ServiceLocator.fileReplicator = new FileReplicator();\n ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler();\n }\n\n if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) {\n ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) {\n ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) {\n ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) {\n ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) {\n ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE);\n }\n if (ServiceLocator.getConfig().hasConfig(CONFIG_TARGET_DIRECTORY)) {\n ServiceLocator.fileReplicator.targetDirectory = ServiceLocator.getConfig().getConfig(CONFIG_TARGET_DIRECTORY);\n }\n \n return ServiceLocator.fileReplicator;\n }\n\n}"],"names":[],"mappings":"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"} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | 'use strict'; | 1 | 'use strict'; |
| 2 | 2 | ||
| 3 | -var rxjs_Observable = require('rxjs/Observable'); | 3 | +var events = require('events'); |
| 4 | var http = require('http'); | 4 | var http = require('http'); |
| 5 | var https = require('https'); | 5 | var https = require('https'); |
| 6 | var fs = require('fs'); | 6 | var fs = require('fs'); |
| 7 | 7 | ||
| 8 | -var NodeFileHandler = (function () { | 8 | +function __extends(d, b) { |
| 9 | + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; | ||
| 10 | + function __() { this.constructor = d; } | ||
| 11 | + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +var Util = (function () { | ||
| 15 | + function Util() { | ||
| 16 | + } | ||
| 17 | + Util.getNameHash = function (path) { | ||
| 18 | + for (var r = 0, i = 0; i < path.length; i++) { | ||
| 19 | + r = (r << 5) - r + path.charCodeAt(i), r &= r; | ||
| 20 | + } | ||
| 21 | + return "bsync_" + Math.abs(r); | ||
| 22 | + }; | ||
| 23 | + /** | ||
| 24 | + * index >= 0, localFile is in files | ||
| 25 | + * index < 0, localFile is not in files | ||
| 26 | + */ | ||
| 27 | + Util.getFileIndex = function (files, localFile) { | ||
| 28 | + for (var i = 0; i < files.length; i++) { | ||
| 29 | + if (localFile == files[i].target) { | ||
| 30 | + return i; | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + return -1; | ||
| 34 | + }; | ||
| 35 | + Util.getFilesForCleanup = function (files, localFiles) { | ||
| 36 | + var filesForCleanup = []; | ||
| 37 | + for (var _i = 0, localFiles_1 = localFiles; _i < localFiles_1.length; _i++) { | ||
| 38 | + var localFile = localFiles_1[_i]; | ||
| 39 | + var index = -1; | ||
| 40 | + index = Util.getFileIndex(files, localFile); | ||
| 41 | + if (index < 0) { | ||
| 42 | + filesForCleanup.push(localFile); | ||
| 43 | + } | ||
| 44 | + else { | ||
| 45 | + // splice for performance improvement only | ||
| 46 | + files.splice(index, 1); | ||
| 47 | + } | ||
| 48 | + } | ||
| 49 | + return filesForCleanup; | ||
| 50 | + }; | ||
| 51 | + return Util; | ||
| 52 | +}()); | ||
| 53 | + | ||
| 54 | +var NodeFileHandler = (function (_super) { | ||
| 55 | + __extends(NodeFileHandler, _super); | ||
| 9 | function NodeFileHandler() { | 56 | function NodeFileHandler() { |
| 57 | + _super.apply(this, arguments); | ||
| 10 | } | 58 | } |
| 11 | NodeFileHandler.prototype.selectProtocol = function (url) { | 59 | NodeFileHandler.prototype.selectProtocol = function (url) { |
| 12 | if (url.search(/^http:\/\//) === 0) { | 60 | if (url.search(/^http:\/\//) === 0) { |
| ... | @@ -20,18 +68,19 @@ var NodeFileHandler = (function () { | ... | @@ -20,18 +68,19 @@ var NodeFileHandler = (function () { |
| 20 | } | 68 | } |
| 21 | }; | 69 | }; |
| 22 | NodeFileHandler.prototype.download = function (source, target) { | 70 | NodeFileHandler.prototype.download = function (source, target) { |
| 71 | + var _this = this; | ||
| 23 | var handler = this.selectProtocol(source); | 72 | var handler = this.selectProtocol(source); |
| 24 | - return rxjs_Observable.Observable.create(function (subscriber) { | 73 | + if (!handler) { |
| 25 | - if (!handler) { | 74 | + this.emit("error", "No handler for source: " + source); |
| 26 | - subscriber.error("No handler for source: " + source); | 75 | + return this; |
| 27 | - return; | 76 | + } |
| 28 | - } | 77 | + // file already exists and is not empty |
| 29 | - // file already exists and is not empty | 78 | + if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) { |
| 30 | - if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) { | 79 | + this.emit("complete"); |
| 31 | - subscriber.complete(); | 80 | + return this; |
| 32 | - return; | 81 | + } |
| 33 | - } | 82 | + else { |
| 34 | - var file = fs.createWriteStream(target, { 'flags': 'a' }); | 83 | + var file_1 = fs.createWriteStream(target, { 'flags': 'a' }); |
| 35 | handler.get(source, function (response) { | 84 | handler.get(source, function (response) { |
| 36 | var size = response.headers['content-length']; // in bytes | 85 | var size = response.headers['content-length']; // in bytes |
| 37 | var prog = 0; // already downloaded | 86 | var prog = 0; // already downloaded |
| ... | @@ -39,33 +88,53 @@ var NodeFileHandler = (function () { | ... | @@ -39,33 +88,53 @@ var NodeFileHandler = (function () { |
| 39 | var nextProg = (1 / progCounts); | 88 | var nextProg = (1 / progCounts); |
| 40 | response.on('data', function (chunk) { | 89 | response.on('data', function (chunk) { |
| 41 | prog += chunk.length; | 90 | prog += chunk.length; |
| 42 | - file.write(chunk, 'binary'); | 91 | + file_1.write(chunk, 'binary'); |
| 43 | if ((prog / size) > nextProg) { | 92 | if ((prog / size) > nextProg) { |
| 44 | - subscriber.next(prog / size); | 93 | + _this.emit('progress', prog / size); |
| 45 | nextProg += (1 / progCounts); | 94 | nextProg += (1 / progCounts); |
| 46 | } | 95 | } |
| 47 | }); | 96 | }); |
| 48 | - response.on('end', function () { | 97 | + response.once('end', function () { |
| 49 | - file.end(); | 98 | + file_1.end(); |
| 50 | - subscriber.complete(); | 99 | + _this.emit('complete'); |
| 51 | }); | 100 | }); |
| 52 | }).on('error', function (error) { | 101 | }).on('error', function (error) { |
| 53 | fs.unlink(target); | 102 | fs.unlink(target); |
| 54 | - subscriber.error("Error while downloading: " + error); | 103 | + _this.emit("error", "Error while downloading: " + error); |
| 55 | }); | 104 | }); |
| 56 | - }); | 105 | + return this; |
| 106 | + } | ||
| 107 | + }; | ||
| 108 | + NodeFileHandler.prototype.cleanup = function (files, basePath) { | ||
| 109 | + try { | ||
| 110 | + var localFiles = fs.readdirSync(basePath); | ||
| 111 | + Util.getFilesForCleanup(files, localFiles) | ||
| 112 | + .forEach(function (file) { | ||
| 113 | + fs.unlinkSync(basePath + "/" + file); | ||
| 114 | + }); | ||
| 115 | + } | ||
| 116 | + catch (e) { | ||
| 117 | + } | ||
| 118 | + return this; | ||
| 57 | }; | 119 | }; |
| 58 | return NodeFileHandler; | 120 | return NodeFileHandler; |
| 59 | -}()); | 121 | +}(events.EventEmitter)); |
| 60 | 122 | ||
| 61 | var Bsync = (function () { | 123 | var Bsync = (function () { |
| 62 | function Bsync() { | 124 | function Bsync() { |
| 63 | } | 125 | } |
| 64 | - Bsync.configIpcMain = function (ipcMain, downloadDir) { | 126 | + Bsync.configIpcMain = function (ipcMain, basePath) { |
| 65 | - var nodeFileHander = new NodeFileHandler(); | ||
| 66 | ipcMain.on('bsync-download', function (event, args) { | 127 | ipcMain.on('bsync-download', function (event, args) { |
| 67 | - nodeFileHander.download(args.source, downloadDir + args.target) | 128 | + var nodeFileHander = new NodeFileHandler(); |
| 68 | - .subscribe(function (progress) { event.sender.send('bsync-download-progress', progress); }, function (error) { event.sender.send('bsync-download-error', error); }, function () { event.sender.send('bsync-download-complete'); }); | 129 | + nodeFileHander.download(args.source, basePath + "/" + args.target) |
| 130 | + .on('progress', function (progress) { event.sender.send('bsync-download-progress', progress); }) | ||
| 131 | + .once('error', function (error) { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-error', error); }) | ||
| 132 | + .once('complete', function () { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-complete'); }); | ||
| 133 | + }); | ||
| 134 | + ipcMain.on('bsync-cleanup', function (event, args) { | ||
| 135 | + var nodeFileHandler = new NodeFileHandler(); | ||
| 136 | + nodeFileHandler.cleanup(args.files, basePath); | ||
| 137 | + event.sender.send('bsync-cleanup-complete'); | ||
| 69 | }); | 138 | }); |
| 70 | }; | 139 | }; |
| 71 | return Bsync; | 140 | return Bsync; | ... | ... |
| 1 | -{"version":3,"file":null,"sources":["../src/file-handler/node-file-handler.ts","../src/node-main.ts"],"sourcesContent":["import { Observable } from 'rxjs/Observable';\nimport { Subscriber } from 'rxjs/Subscriber';\nimport { FileHandler } from '../api/file-handler';\nimport * as http from 'http';\nimport * as https from 'https';\nimport * as fs from 'fs';\n\nexport class NodeFileHandler implements FileHandler {\n\n selectProtocol(url:string) : any {\n if (url.search(/^http:\\/\\//) === 0) {\n return http;\n } else if (url.search(/^https:\\/\\//) === 0) {\n return https;\n } else {\n return null;\n }\n }\n\n download(source:string, target:string) : Observable<number> {\n\n let handler = this.selectProtocol(source);\n\n return Observable.create((subscriber:Subscriber<number>) => {\n \n if (!handler) {\n subscriber.error(\"No handler for source: \" + source);\n return;\n }\n\n // file already exists and is not empty\n if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) {\n subscriber.complete();\n return;\n }\n\n let file = fs.createWriteStream(target, {'flags': 'a'});\n\n handler.get(source, (response) => {\n let size = response.headers['content-length']; // in bytes\n let prog = 0; // already downloaded\n let progCounts = 100; // how many progress events should be triggerd (1-100 %)\n let nextProg = (1/progCounts);\n \n response.on('data', (chunk) => {\n prog += chunk.length;\n file.write(chunk, 'binary');\n\n if ((prog / size) > nextProg) {\n subscriber.next(prog / size);\n nextProg += (1 / progCounts);\n } \n });\n\n response.on('end', () => {\n file.end();\n subscriber.complete();\n });\n \n }).on('error', (error) => {\n fs.unlink(target);\n subscriber.error(\"Error while downloading: \" + error);\n });\n\n });\n\n }\n\n}","import { NodeFileHandler } from './file-handler/node-file-handler';\n\nexport default class Bsync {\n\n static configIpcMain(ipcMain: any, downloadDir:string) {\n let nodeFileHander = new NodeFileHandler();\n\n ipcMain.on('bsync-download', (event, args) => {\n nodeFileHander.download(args.source, downloadDir + args.target)\n .subscribe(\n (progress:number) => { event.sender.send('bsync-download-progress', progress); } ,\n (error:any) => { event.sender.send('bsync-download-error', error); } ,\n () => { event.sender.send('bsync-download-complete'); }\n );\n });\n }\n\n}"],"names":["Observable","fs.existsSync","fs.statSync","fs.createWriteStream","fs.unlink"],"mappings":"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"} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +{"version":3,"file":null,"sources":["../src/util.ts","../src/file-handler/node-file-handler.ts","../src/node-main.ts"],"sourcesContent":["import { File } from './api/file';\n\nexport class Util {\n\n static getNameHash(path:string) {\n for(var r=0,i=0;i<path.length;i++) {\n r=(r<<5)-r+path.charCodeAt(i),r&=r;\n }\n return \"bsync_\" + Math.abs(r);\n }\n\n /**\n * index >= 0, localFile is in files\n * index < 0, localFile is not in files\n */\n static getFileIndex(files:Array<File>, localFile:string) : number {\n for (let i = 0; i < files.length; i++) {\n if (localFile == files[i].target) {\n return i;\n }\n }\n return -1;\n }\n\n static getFilesForCleanup(files:Array<File>, localFiles:Array<string>) : Array<string> {\n let filesForCleanup = [];\n\n for (let localFile of localFiles) {\n let index = -1;\n\n index = Util.getFileIndex(files, localFile);\n \n if (index < 0) {\n filesForCleanup.push(localFile);\n } else {\n // splice for performance improvement only\n files.splice(index,1);\n }\n }\n\n return filesForCleanup;\n }\n\n}","import { Util } from './../util';\nimport { EventEmitter } from 'events';\nimport { FileHandler } from '../api/file-handler';\nimport { File } from '../api/file';\nimport * as http from 'http';\nimport * as https from 'https';\nimport * as fs from 'fs';\n\nexport class NodeFileHandler extends EventEmitter implements FileHandler {\n\n selectProtocol(url:string) : any {\n if (url.search(/^http:\\/\\//) === 0) {\n return http;\n } else if (url.search(/^https:\\/\\//) === 0) {\n return https;\n } else {\n return null;\n }\n }\n\n download(source:string, target:string) {\n\n let handler = this.selectProtocol(source);\n\n if (!handler) {\n this.emit(\"error\",\"No handler for source: \" + source);\n return this;\n }\n\n // file already exists and is not empty\n if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) {\n this.emit(\"complete\");\n return this;\n } else {\n let file = fs.createWriteStream(target, {'flags': 'a'});\n\n handler.get(source, (response) => {\n let size = response.headers['content-length']; // in bytes\n let prog = 0; // already downloaded\n let progCounts = 100; // how many progress events should be triggerd (1-100 %)\n let nextProg = (1/progCounts);\n \n response.on('data', (chunk) => {\n prog += chunk.length;\n file.write(chunk, 'binary');\n\n if ((prog / size) > nextProg) {\n this.emit('progress',prog / size);\n nextProg += (1 / progCounts);\n } \n });\n\n response.once('end', () => {\n file.end();\n this.emit('complete');\n }); \n\n }).on('error', (error) => {\n fs.unlink(target);\n this.emit(\"error\", \"Error while downloading: \" + error);\n });\n\n return this;\n } \n }\n\n cleanup(files:Array<File>, basePath?:string) {\n try {\n let localFiles = fs.readdirSync(basePath);\n Util.getFilesForCleanup(files, localFiles)\n .forEach((file) => {\n fs.unlinkSync(basePath + \"/\" + file);\n }); \n } catch (e) {\n }\n \n return this;\n }\n\n}","import { NodeFileHandler } from './file-handler/node-file-handler';\n\nexport default class Bsync {\n\n static configIpcMain(ipcMain: any, basePath: string) { \n \n ipcMain.on('bsync-download', (event, args) => {\n let nodeFileHander = new NodeFileHandler();\n nodeFileHander.download(args.source, basePath + \"/\" + args.target)\n .on('progress', (progress:number) => { event.sender.send('bsync-download-progress', progress); })\n .once('error', (error) => { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-error', error); })\n .once('complete', () => { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-complete'); });\n });\n\n ipcMain.on('bsync-cleanup', (event, args) => {\n let nodeFileHandler = new NodeFileHandler();\n nodeFileHandler.cleanup(args.files, basePath);\n event.sender.send('bsync-cleanup-complete');\n });\n\n }\n\n}"],"names":["fs.existsSync","fs.statSync","fs.createWriteStream","fs.unlink","fs.readdirSync","fs.unlinkSync","EventEmitter"],"mappings":"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"} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
index.d.ts
0 → 100644
| 1 | + | ||
| 2 | +interface FileReplicator { | ||
| 3 | + start(retries?:number) : void; | ||
| 4 | + clear() : void; | ||
| 5 | + cleanup() : void; | ||
| 6 | + pushChanges(change: any) : void; | ||
| 7 | + on(event:string, handler:(...params: any[]) => void) : FileReplicator; | ||
| 8 | + once(event:string, handler:(...params: any[]) => void) : FileReplicator; | ||
| 9 | + removeAllListeners() : FileReplicator; | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +declare var bsyncClient: { | ||
| 13 | + | ||
| 14 | + CONFIG_TARGET_DIRECTORY : string ; | ||
| 15 | + | ||
| 16 | + ServiceLocator : { | ||
| 17 | + | ||
| 18 | + getConfig : () => { | ||
| 19 | + getConfig : (key:string) => any; | ||
| 20 | + setConfig : (key:string, value:any) => void; | ||
| 21 | + hasConfig : (key:string) => boolean; | ||
| 22 | + }; | ||
| 23 | + | ||
| 24 | + getFileReplicator : () => FileReplicator; | ||
| 25 | + | ||
| 26 | + } | ||
| 27 | +}; | ||
| 28 | + | ||
| 29 | +declare module "bsync-client" { | ||
| 30 | + export = bsyncClient; | ||
| 31 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -3,6 +3,7 @@ | ... | @@ -3,6 +3,7 @@ |
| 3 | "version": "1.0.0", | 3 | "version": "1.0.0", |
| 4 | "description": "", | 4 | "description": "", |
| 5 | "main": "dist/browser-build.js", | 5 | "main": "dist/browser-build.js", |
| 6 | + "typings": "index.d.ts", | ||
| 6 | "scripts": { | 7 | "scripts": { |
| 7 | "build": "npm run build:node && npm run build:browser", | 8 | "build": "npm run build:node && npm run build:browser", |
| 8 | "build:node": "rollup -c ./config/rollup.config.node.js", | 9 | "build:node": "rollup -c ./config/rollup.config.node.js", |
| ... | @@ -16,9 +17,6 @@ | ... | @@ -16,9 +17,6 @@ |
| 16 | }, | 17 | }, |
| 17 | "author": "", | 18 | "author": "", |
| 18 | "license": "ISC", | 19 | "license": "ISC", |
| 19 | - "dependencies": { | ||
| 20 | - "rxjs": "^5.0.2" | ||
| 21 | - }, | ||
| 22 | "devDependencies": { | 20 | "devDependencies": { |
| 23 | "@types/jasmine": "^2.5.40", | 21 | "@types/jasmine": "^2.5.40", |
| 24 | "cordova": "^6.4.0", | 22 | "cordova": "^6.4.0", | ... | ... |
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | 2 | ||
| 3 | curl -X DELETE http://admin:admin@127.0.0.1:5984/pouch_test_db | 3 | curl -X DELETE http://admin:admin@127.0.0.1:5984/pouch_test_db |
| 4 | -rm -R ./.tmp | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 4 | +rm -rf ./.tmp | ||
| 5 | +rm -rf ./.tmp-files | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | - | 2 | +rm -rf ./.tmp |
| 3 | +rm -rf ./.tmp-files | ||
| 3 | curl -X DELETE http://admin:admin@127.0.0.1:5984/pouch_test_db | 4 | curl -X DELETE http://admin:admin@127.0.0.1:5984/pouch_test_db |
| 4 | curl -X PUT http://admin:admin@127.0.0.1:5984/pouch_test_db | 5 | curl -X PUT http://admin:admin@127.0.0.1:5984/pouch_test_db | ... | ... |
| ... | @@ -7,15 +7,14 @@ echo "cordova $COMMAND $PLATFORM" | ... | @@ -7,15 +7,14 @@ echo "cordova $COMMAND $PLATFORM" |
| 7 | 7 | ||
| 8 | rollup --config ./config/rollup.config.cordova-test.js | 8 | rollup --config ./config/rollup.config.cordova-test.js |
| 9 | cp ./spec/cordova-plugin-test/plugin.xml .tmp/plugin.xml | 9 | cp ./spec/cordova-plugin-test/plugin.xml .tmp/plugin.xml |
| 10 | -cp ./node_modules/rxjs/bundles/Rx.min.js .tmp/Rx.min.js | ||
| 11 | 10 | ||
| 12 | cd .. | 11 | cd .. |
| 13 | -rm -r ./bsync-client-test-app | 12 | +rm -rf ./bsync-client-test-app |
| 14 | ./bsync-client/node_modules/.bin/cordova create bsync-client-test-app | 13 | ./bsync-client/node_modules/.bin/cordova create bsync-client-test-app |
| 15 | cd ./bsync-client-test-app | 14 | cd ./bsync-client-test-app |
| 16 | 15 | ||
| 17 | ../bsync-client/node_modules/.bin/cordova platform add $PLATFORM | 16 | ../bsync-client/node_modules/.bin/cordova platform add $PLATFORM |
| 18 | -../bsync-client/node_modules/.bin/cordova plugin add ../bsync-client | 17 | +# ../bsync-client/node_modules/.bin/cordova plugin add ../bsync-client |
| 19 | ../bsync-client/node_modules/.bin/cordova plugin add ../bsync-client/.tmp | 18 | ../bsync-client/node_modules/.bin/cordova plugin add ../bsync-client/.tmp |
| 20 | ../bsync-client/node_modules/.bin/cordova plugin add cordova-plugin-test-framework | 19 | ../bsync-client/node_modules/.bin/cordova plugin add cordova-plugin-test-framework |
| 21 | 20 | ||
| ... | @@ -27,4 +26,4 @@ else | ... | @@ -27,4 +26,4 @@ else |
| 27 | cordova emulate $PLATFORM | 26 | cordova emulate $PLATFORM |
| 28 | fi | 27 | fi |
| 29 | 28 | ||
| 30 | -rm -R ../bsync-client/.tmp | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 29 | +rm -rf ../bsync-client/.tmp | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -5,8 +5,6 @@ import {TestFileHandler} from './file-handler/test-file-handler'; | ... | @@ -5,8 +5,6 @@ import {TestFileHandler} from './file-handler/test-file-handler'; |
| 5 | 5 | ||
| 6 | ServiceLocator.addFileHandler(ENV_UNKNOWN, new TestFileHandler()); | 6 | ServiceLocator.addFileHandler(ENV_UNKNOWN, new TestFileHandler()); |
| 7 | 7 | ||
| 8 | -import '../src/browser-main'; | ||
| 9 | - | ||
| 10 | declare var emit:any; | 8 | declare var emit:any; |
| 11 | 9 | ||
| 12 | const dbUrl = 'http://admin:admin@localhost:5984/pouch_test_db'; | 10 | const dbUrl = 'http://admin:admin@localhost:5984/pouch_test_db'; |
| ... | @@ -49,32 +47,71 @@ describe("Integration tests with couchdb", () => { | ... | @@ -49,32 +47,71 @@ describe("Integration tests with couchdb", () => { |
| 49 | 47 | ||
| 50 | it("Should successfully download several files", (done) => { | 48 | it("Should successfully download several files", (done) => { |
| 51 | TestFileHandler.setErrorRate(0); | 49 | TestFileHandler.setErrorRate(0); |
| 52 | - ServiceLocator.getFileReplicator().init(); | 50 | + let replicator = ServiceLocator.getFileReplicator(); |
| 53 | let index = 0; | 51 | let index = 0; |
| 54 | 52 | ||
| 55 | - localDb.replicate.from(dbUrl) | 53 | + replicator.clear(); |
| 56 | - .on('file-replicator-complete', event => { | 54 | + |
| 55 | + replicator | ||
| 56 | + .on('file-complete', () => { | ||
| 57 | index++; | 57 | index++; |
| 58 | }) | 58 | }) |
| 59 | - .on('complete', () => { | 59 | + .once('complete', () => { |
| 60 | expect(index).toEqual(3); | 60 | expect(index).toEqual(3); |
| 61 | - done(); | 61 | + done(); |
| 62 | + }); | ||
| 63 | + | ||
| 64 | + localDb.replicate.from(dbUrl) | ||
| 65 | + .once('complete', () => { | ||
| 66 | + | ||
| 67 | + localDb.query('index_type/type',{ | ||
| 68 | + include_docs : true, | ||
| 69 | + key : replicator.itemValue | ||
| 70 | + }).then((res) => { | ||
| 71 | + let docs = []; | ||
| 72 | + for (let r of res.rows) { | ||
| 73 | + docs.push(r.doc); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + replicator.pushChanges(docs); | ||
| 77 | + replicator.start(); | ||
| 78 | + }); | ||
| 62 | }); | 79 | }); |
| 63 | }); | 80 | }); |
| 64 | 81 | ||
| 65 | it("Should trigger errors, but successfully download with retries", (done) => { | 82 | it("Should trigger errors, but successfully download with retries", (done) => { |
| 66 | TestFileHandler.setErrorRate(0.8); | 83 | TestFileHandler.setErrorRate(0.8); |
| 67 | - ServiceLocator.getFileReplicator().init(); | 84 | + let replicator = ServiceLocator.getFileReplicator(); |
| 68 | let errors = 0; | 85 | let errors = 0; |
| 69 | 86 | ||
| 70 | - localDb.replicate.from(dbUrl) | 87 | + replicator.clear(); |
| 71 | - .on('file-replicator-error', event => { | 88 | + |
| 89 | + replicator | ||
| 90 | + .on('file-error', () => { | ||
| 72 | errors++; | 91 | errors++; |
| 73 | }) | 92 | }) |
| 74 | - .on('complete', () => { | 93 | + .once('complete', () => { |
| 75 | expect(errors).toBeGreaterThanOrEqual(1); | 94 | expect(errors).toBeGreaterThanOrEqual(1); |
| 76 | - done(); | 95 | + done(); |
| 96 | + }); | ||
| 97 | + | ||
| 98 | + localDb.replicate.from(dbUrl) | ||
| 99 | + .once('complete', () => { | ||
| 100 | + | ||
| 101 | + localDb.query('index_type/type',{ | ||
| 102 | + include_docs : true, | ||
| 103 | + key : replicator.itemValue | ||
| 104 | + }).then((res) => { | ||
| 105 | + let docs = []; | ||
| 106 | + for (let r of res.rows) { | ||
| 107 | + docs.push(r.doc); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + replicator.pushChanges(docs); | ||
| 111 | + replicator.start(); | ||
| 112 | + }); | ||
| 77 | }); | 113 | }); |
| 114 | + | ||
| 78 | }); | 115 | }); |
| 79 | 116 | ||
| 80 | }); | 117 | }); | ... | ... |
| ... | @@ -5,14 +5,11 @@ | ... | @@ -5,14 +5,11 @@ |
| 5 | version="1.0.0" | 5 | version="1.0.0" |
| 6 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | 6 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| 7 | 7 | ||
| 8 | - <name>bsync cordova test</name> | 8 | + <name>bsync test in cordova environment</name> |
| 9 | <license>Apache 2.0 License</license> | 9 | <license>Apache 2.0 License</license> |
| 10 | - | ||
| 11 | - <js-module src="Rx.min.js" name="Rx"> | ||
| 12 | - <clobbers target="Rx" /> | ||
| 13 | - </js-module> | ||
| 14 | - | ||
| 15 | <js-module src="cordova-test-build.js" name="tests"> | 10 | <js-module src="cordova-test-build.js" name="tests"> |
| 16 | </js-module> | 11 | </js-module> |
| 17 | 12 | ||
| 13 | + <dependency id="cordova-plugin-file-transfer" url="https://github.com/apache/cordova-plugin-file-transfer" commit="master" /> | ||
| 14 | + | ||
| 18 | </plugin> | 15 | </plugin> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -import { CordovaDownloader } from '../src/file-handler/cordova-file-handler'; | 1 | +import { CordovaFileHandler } from '../src/file-handler/cordova-file-handler'; |
| 2 | 2 | ||
| 3 | declare var cordova; | 3 | declare var cordova; |
| 4 | 4 | ||
| 5 | exports.defineAutoTests = function() { | 5 | exports.defineAutoTests = function() { |
| 6 | 6 | ||
| 7 | + let createFilesHelper = (filenames:Array<string>, successCallback, errorCallback) => { | ||
| 8 | + let index = 0; | ||
| 9 | + | ||
| 10 | + let create = () => { | ||
| 11 | + if (index < filenames.length) { | ||
| 12 | + console.log("try creating file: ", filenames[index]); | ||
| 13 | + createFileHelper(filenames[index], create, errorCallback); | ||
| 14 | + index += 1; | ||
| 15 | + } else { | ||
| 16 | + successCallback(); | ||
| 17 | + } | ||
| 18 | + }; | ||
| 19 | + create(); | ||
| 20 | + }; | ||
| 21 | + | ||
| 22 | + let createFileHelper = (filename, successCallback, errorCallback) => { | ||
| 23 | + window['requestFileSystem'](window['LocalFileSystem'].TEMPORARY, 0, (fs) => { | ||
| 24 | + fs.root.getFile(filename, { create: true, exclusive: false },(fileEntry) => { | ||
| 25 | + fileEntry.createWriter((fileWriter) => { | ||
| 26 | + fileWriter.onwriteend = function() { | ||
| 27 | + console.log("file created", filename); | ||
| 28 | + successCallback(); | ||
| 29 | + }; | ||
| 30 | + fileWriter.onerror = function (e) { | ||
| 31 | + console.error("file error", e); | ||
| 32 | + errorCallback(e); | ||
| 33 | + }; | ||
| 34 | + fileWriter.write(new Blob(['some arbitrary file data'], { type: 'text/plain' })); | ||
| 35 | + }); | ||
| 36 | + }, errorCallback); | ||
| 37 | + }, errorCallback); | ||
| 38 | + }; | ||
| 39 | + | ||
| 40 | + jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000; | ||
| 41 | + | ||
| 7 | describe("Cordova downloader", () => { | 42 | describe("Cordova downloader", () => { |
| 8 | 43 | ||
| 9 | - let downloader = new CordovaDownloader(); | 44 | + let handler = new CordovaFileHandler(); |
| 10 | 45 | ||
| 11 | it("should download sample image from https source and store with new name", (done) => { | 46 | it("should download sample image from https source and store with new name", (done) => { |
| 12 | 47 | ||
| 13 | - let source = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/800px-FullMoon2010.jpg"; | 48 | + let source = "https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg"; |
| 14 | - let target = cordova.file.dataDirectory + "full-moon.jpg"; | 49 | + // let target = cordova.file.dataDirectory + "full-moon.jpg"; |
| 50 | + let target = "cdvfile://localhost/temporary/full-moon.jpg"; | ||
| 15 | let lastProgress = 0; | 51 | let lastProgress = 0; |
| 16 | 52 | ||
| 17 | - downloader.download(source, target) | 53 | + handler.download(source, target) |
| 18 | - .subscribe( | 54 | + .on('progress', (progress: number) => { |
| 19 | - (progress: number) => { | 55 | + expect(progress).toBeGreaterThan(lastProgress); |
| 20 | - expect(progress).toBeGreaterThan(lastProgress); | 56 | + lastProgress = progress; |
| 21 | - lastProgress = progress; | 57 | + }).once('error', (error:any) => { |
| 22 | - } , | 58 | + fail(); |
| 23 | - (error:any) => { | 59 | + }).once('complete', () => { |
| 24 | - fail(); | 60 | + expect(lastProgress).toEqual(1); |
| 25 | - } , | 61 | + |
| 26 | - () => { | 62 | + window['resolveLocalFileSystemURL'](target, (entry:any) => { |
| 27 | - expect(lastProgress).toEqual(1); | 63 | + expect(entry.isFile).toBeTruthy(); |
| 28 | - | 64 | + expect(entry.name).toEqual("full-moon.jpg"); |
| 29 | - window['resolveLocalFileSystemURL'](target, (entry:any) => { | 65 | + done(); |
| 30 | - expect(entry.isFile).toBeTruthy(); | 66 | + }); |
| 31 | - expect(entry.name).toEqual("full-moon.jpg"); | 67 | + }); |
| 32 | - done(); | 68 | + }); |
| 33 | - }); | 69 | + |
| 34 | - } | 70 | + it('should cleanup successfully', (done) => { |
| 35 | - ); | 71 | + createFilesHelper(['file-1', 'file-2', 'file-3'], () => { |
| 72 | + console.log("files are created, now start with cleanup"); | ||
| 73 | + | ||
| 74 | + handler.once('cleanup-complete', (files) => { | ||
| 75 | + console.log(files); | ||
| 76 | + expect(files.length).toBeGreaterThan(1); | ||
| 77 | + done(); | ||
| 78 | + }); | ||
| 79 | + | ||
| 80 | + handler.once('cleanup-error', (files) => { | ||
| 81 | + fail('cleanup error'); | ||
| 82 | + }); | ||
| 36 | 83 | ||
| 84 | + handler.cleanup([ | ||
| 85 | + { source: '', target: 'file-1' } , | ||
| 86 | + { source: '', target: 'file-2' } | ||
| 87 | + ], 'cdvfile://localhost/temporary/'); | ||
| 88 | + }, (error) => { | ||
| 89 | + console.error(error); | ||
| 90 | + fail('error while creating files'); | ||
| 91 | + }); | ||
| 37 | }); | 92 | }); |
| 38 | 93 | ||
| 39 | }); | 94 | }); | ... | ... |
| 1 | -import { Observable, Subscriber } from 'rxjs'; | 1 | +import { EventEmitter } from 'events'; |
| 2 | import { FileHandler } from '../../src/api/file-handler'; | 2 | import { FileHandler } from '../../src/api/file-handler'; |
| 3 | 3 | ||
| 4 | -export class TestFileHandler implements FileHandler { | 4 | +export class TestFileHandler extends EventEmitter implements FileHandler { |
| 5 | 5 | ||
| 6 | protected static errorRate:number = 0; | 6 | protected static errorRate:number = 0; |
| 7 | 7 | ||
| ... | @@ -9,27 +9,30 @@ export class TestFileHandler implements FileHandler { | ... | @@ -9,27 +9,30 @@ export class TestFileHandler implements FileHandler { |
| 9 | TestFileHandler.errorRate = rate; | 9 | TestFileHandler.errorRate = rate; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | - download(source:string, target:string) : Observable<number> { | 12 | + cleanup() { return this; } |
| 13 | - return Observable.create((subscriber:Subscriber<number>) => { | ||
| 14 | - let random = Math.random(); | ||
| 15 | - let error:boolean = random < TestFileHandler.errorRate; | ||
| 16 | - let counter = 1; | ||
| 17 | 13 | ||
| 18 | - if (error) { | 14 | + download(source:string, target:string) { |
| 19 | - subscriber.error("random error triggered"); | 15 | + let random = Math.random(); |
| 20 | - return; | 16 | + let error:boolean = random < TestFileHandler.errorRate; |
| 21 | - } | 17 | + let counter = 1; |
| 22 | 18 | ||
| 19 | + if (error) { | ||
| 20 | + setTimeout(() => { | ||
| 21 | + this.emit("error", "random error triggered"); | ||
| 22 | + },200); | ||
| 23 | + } else { | ||
| 23 | let interval = setInterval(() => { | 24 | let interval = setInterval(() => { |
| 24 | if (counter < 4) { | 25 | if (counter < 4) { |
| 25 | - subscriber.next(counter * 25); | 26 | + this.emit('progress', counter * 25); |
| 26 | } else { | 27 | } else { |
| 27 | - subscriber.complete(); | 28 | + this.emit('complete'); |
| 28 | clearInterval(interval); | 29 | clearInterval(interval); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | ++counter; | 32 | ++counter; |
| 32 | }, 10); | 33 | }, 10); |
| 33 | - }); | 34 | + } |
| 35 | + | ||
| 36 | + return this; | ||
| 34 | } | 37 | } |
| 35 | } | 38 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | export * from './test/file-handler/node-file-handler'; | 1 | export * from './test/file-handler/node-file-handler'; |
| 2 | -export * from './test/file-replicator'; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 2 | +export * from './test/file-replicator'; | ||
| 3 | +export * from './test/util'; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -7,6 +7,10 @@ describe("Node Downloader", () => { | ... | @@ -7,6 +7,10 @@ describe("Node Downloader", () => { |
| 7 | 7 | ||
| 8 | let nodeFileHandler = new NodeFileHandler(); | 8 | let nodeFileHandler = new NodeFileHandler(); |
| 9 | 9 | ||
| 10 | + beforeEach(() => { | ||
| 11 | + nodeFileHandler.removeAllListeners(); | ||
| 12 | + }); | ||
| 13 | + | ||
| 10 | it("should retrieve right handler", () => { | 14 | it("should retrieve right handler", () => { |
| 11 | 15 | ||
| 12 | let httpHandler = nodeFileHandler.selectProtocol("http://someurl.com/image.jpg"); | 16 | let httpHandler = nodeFileHandler.selectProtocol("http://someurl.com/image.jpg"); |
| ... | @@ -23,27 +27,26 @@ describe("Node Downloader", () => { | ... | @@ -23,27 +27,26 @@ describe("Node Downloader", () => { |
| 23 | it("should download sample image from https source and store with new name", (done) => { | 27 | it("should download sample image from https source and store with new name", (done) => { |
| 24 | 28 | ||
| 25 | let source = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/800px-FullMoon2010.jpg"; | 29 | let source = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/800px-FullMoon2010.jpg"; |
| 26 | - let target = ".tmp/full-moon.jpg"; | 30 | + let target = "./.tmp/full-moon-" + (new Date()).getTime() + ".jpg"; |
| 27 | let lastProgress = 0; | 31 | let lastProgress = 0; |
| 28 | 32 | ||
| 29 | - nodeFileHandler.download(source, target) | 33 | + nodeFileHandler |
| 30 | - .subscribe( | 34 | + .on('progress', (progress: number) => { |
| 31 | - (progress: number) => { | 35 | + expect(progress).toBeGreaterThan(lastProgress); |
| 32 | - expect(progress).toBeGreaterThan(lastProgress); | 36 | + lastProgress = progress; |
| 33 | - lastProgress = progress; | 37 | + }) |
| 34 | - } , | 38 | + .once('error', (error) => {}) |
| 35 | - (error:any) => {} , | 39 | + .once('complete', () => { |
| 36 | - () => { | 40 | + expect(lastProgress).toEqual(1); |
| 37 | - expect(lastProgress).toEqual(1); | 41 | + expect(fs.existsSync(target)).toBeTruthy(); |
| 38 | - expect(fs.existsSync(target)).toBeTruthy(); | 42 | + done(); |
| 39 | - done(); | 43 | + }) |
| 40 | - } | 44 | + .download(source, target); |
| 41 | - ); | ||
| 42 | }); | 45 | }); |
| 43 | 46 | ||
| 44 | it('should not download if file with same name exists and bytesize > 0', (done) => { | 47 | it('should not download if file with same name exists and bytesize > 0', (done) => { |
| 45 | let source = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/800px-FullMoon2010.jpg"; | 48 | let source = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/FullMoon2010.jpg/800px-FullMoon2010.jpg"; |
| 46 | - let target = ".tmp/full-moon-sensless.jpg"; | 49 | + let target = "./.tmp/full-moon-sensless.jpg"; |
| 47 | let lastProgress = 0; | 50 | let lastProgress = 0; |
| 48 | 51 | ||
| 49 | let file = fs.createWriteStream(target, {'flags': 'a'}); | 52 | let file = fs.createWriteStream(target, {'flags': 'a'}); |
| ... | @@ -51,18 +54,32 @@ describe("Node Downloader", () => { | ... | @@ -51,18 +54,32 @@ describe("Node Downloader", () => { |
| 51 | 54 | ||
| 52 | file.write(new Buffer(dummyData)); | 55 | file.write(new Buffer(dummyData)); |
| 53 | file.end(() => { | 56 | file.end(() => { |
| 54 | - | 57 | + nodeFileHandler |
| 55 | - nodeFileHandler.download(source, target) | 58 | + .on('progress', () => { fail("progress should not be called"); }) |
| 56 | - .subscribe( | 59 | + .once('error', () => {}) |
| 57 | - () => { fail("progress should not be called"); } , | 60 | + .once('complete', () => { |
| 58 | - () => {} , | ||
| 59 | - () => { | ||
| 60 | expect(fs.existsSync(target)).toBeTruthy(); | 61 | expect(fs.existsSync(target)).toBeTruthy(); |
| 61 | done(); | 62 | done(); |
| 62 | - } | 63 | + }) |
| 63 | - ); | 64 | + .download(source, target); |
| 64 | - | ||
| 65 | }); | 65 | }); |
| 66 | }); | 66 | }); |
| 67 | 67 | ||
| 68 | + it('should correctly cleanup files', () => { | ||
| 69 | + let basePath = "./.tmp-files"; | ||
| 70 | + fs.mkdirSync(basePath); | ||
| 71 | + fs.writeFileSync(basePath + "/file1", "some data for file 1"); | ||
| 72 | + fs.writeFileSync(basePath + "/file2", "some data for file 2"); | ||
| 73 | + fs.writeFileSync(basePath + "/file3", "some data for file 3"); | ||
| 74 | + fs.writeFileSync(basePath + "/file4", "some data for file 4"); | ||
| 75 | + | ||
| 76 | + nodeFileHandler.cleanup([ | ||
| 77 | + { source : '' , target : 'file1' }, | ||
| 78 | + { source : '' , target : 'file2' }], basePath); | ||
| 79 | + | ||
| 80 | + let files = fs.readdirSync(basePath); | ||
| 81 | + | ||
| 82 | + expect(files.length).toEqual(2); | ||
| 83 | + }); | ||
| 84 | + | ||
| 68 | }); | 85 | }); |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | import { FileReplicator } from '../../src/file-replicator'; | 1 | import { FileReplicator } from '../../src/file-replicator'; |
| 2 | 2 | ||
| 3 | - | ||
| 4 | describe("File Replicator", () => { | 3 | describe("File Replicator", () => { |
| 5 | 4 | ||
| 6 | let fileReplicator = new FileReplicator(); | 5 | let fileReplicator = new FileReplicator(); |
| 7 | 6 | ||
| 8 | - let change = { | 7 | + let change = [ |
| 9 | - docs : [ | 8 | + { language: 'de', type : "asset", source : "http://someplace.com/icon.jpg" , target : "icon.jpg" } , |
| 10 | - { language: 'de', type : "asset", source : "http://someplace.com/icon.jpg" , target : "icon.jpg" } , | 9 | + { language: 'de', type : "asset", source : "http://sampleuri.com/image.png" } , |
| 11 | - { language: 'de', type : "asset", source : "http://sampleuri.com/image.png" } , | 10 | + { language: 'en', type : "asset", source : "https://secureasset.com/asset.mp3" , target : "music.mp3" } |
| 12 | - { language: 'en', type : "asset", source : "https://secureasset.com/asset.mp3" , target : "music.mp3" } | 11 | + ]; |
| 13 | - ] | ||
| 14 | - }; | ||
| 15 | 12 | ||
| 16 | beforeEach(() => { | 13 | beforeEach(() => { |
| 17 | - fileReplicator.init(); | 14 | + fileReplicator.clear(); |
| 18 | }); | 15 | }); |
| 19 | 16 | ||
| 20 | it("should contain several assets", () => { | 17 | it("should contain several assets", () => { |
| ... | @@ -23,7 +20,7 @@ describe("File Replicator", () => { | ... | @@ -23,7 +20,7 @@ describe("File Replicator", () => { |
| 23 | }); | 20 | }); |
| 24 | 21 | ||
| 25 | it("should get correct asset names", () => { | 22 | it("should get correct asset names", () => { |
| 26 | - let files = fileReplicator.prepareFiles(change.docs); | 23 | + let files = fileReplicator.prepareFiles(change); |
| 27 | 24 | ||
| 28 | expect(files[0].target).toEqual("icon.jpg"); | 25 | expect(files[0].target).toEqual("icon.jpg"); |
| 29 | expect(files[1].target).toEqual("bsync_707608502"); | 26 | expect(files[1].target).toEqual("bsync_707608502"); |
| ... | @@ -38,7 +35,7 @@ describe("File Replicator", () => { | ... | @@ -38,7 +35,7 @@ describe("File Replicator", () => { |
| 38 | return false; | 35 | return false; |
| 39 | }; | 36 | }; |
| 40 | 37 | ||
| 41 | - let files = fileReplicator.prepareFiles(change.docs); | 38 | + let files = fileReplicator.prepareFiles(change); |
| 42 | 39 | ||
| 43 | expect(files.length).toEqual(2); | 40 | expect(files.length).toEqual(2); |
| 44 | expect(files[0].target).toEqual("icon.jpg"); | 41 | expect(files[0].target).toEqual("icon.jpg"); | ... | ... |
spec/test/util.ts
0 → 100644
| 1 | +import { Util } from '../../src/util'; | ||
| 2 | + | ||
| 3 | +describe('Util', () => { | ||
| 4 | + | ||
| 5 | + let files = [ | ||
| 6 | + { source : '' , target : 'file-1'} , | ||
| 7 | + { source : '' , target : 'file-2'} , | ||
| 8 | + { source : '' , target : 'file-3'} , | ||
| 9 | + ]; | ||
| 10 | + | ||
| 11 | + it('should show files to remove', () => { | ||
| 12 | + let cleanupFiles = Util.getFilesForCleanup(files, ['file-1','file-4']); | ||
| 13 | + expect(cleanupFiles[0]).toEqual('file-4'); | ||
| 14 | + }); | ||
| 15 | + | ||
| 16 | +}); | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | -import { Observable } from 'rxjs/Observable'; | 1 | +import { File } from './file'; |
| 2 | 2 | ||
| 3 | export interface FileHandler { | 3 | export interface FileHandler { |
| 4 | 4 | ||
| ... | @@ -8,6 +8,17 @@ export interface FileHandler { | ... | @@ -8,6 +8,17 @@ export interface FileHandler { |
| 8 | * - if the download is in progress: trigger next (0-1 progress for percent of download) | 8 | * - if the download is in progress: trigger next (0-1 progress for percent of download) |
| 9 | * - if the download enters any error condition, trigger error and an already downloaded part of the file | 9 | * - if the download enters any error condition, trigger error and an already downloaded part of the file |
| 10 | */ | 10 | */ |
| 11 | - download(source:string, target:string) : Observable<number>; | 11 | + download(source:string, target:string) : FileHandler; |
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * Remove all files, which are not inside the files array from local storage | ||
| 15 | + */ | ||
| 16 | + cleanup(files: Array<File>, basePath?: string); | ||
| 17 | + | ||
| 18 | + on(event:string, handler:(...params: any[]) => void) : FileHandler; | ||
| 19 | + | ||
| 20 | + once(event:string, handler:(...params: any[]) => void) : FileHandler; | ||
| 21 | + | ||
| 22 | + removeAllListeners() : FileHandler; | ||
| 12 | 23 | ||
| 13 | } | 24 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -import { EventEmitter } from 'events'; | ||
| 2 | import { ServiceLocator } from './service-locator'; | 1 | import { ServiceLocator } from './service-locator'; |
| 3 | 2 | ||
| 4 | export * from './service-locator'; | 3 | export * from './service-locator'; |
| 5 | 4 | ||
| 6 | -export function loadBsyncPlugin (PouchDB) { | 5 | +export * from './config'; |
| 7 | - let pouchReplicate = PouchDB.replicate; | ||
| 8 | - | ||
| 9 | - PouchDB.plugin((PouchDB) => { | ||
| 10 | - PouchDB.replicate = function() { | ||
| 11 | - let eventEmitter = new EventEmitter(); | ||
| 12 | - let emitter = pouchReplicate.apply(this, arguments); | ||
| 13 | - let replicator = ServiceLocator.getFileReplicator(); | ||
| 14 | - let db = arguments[1]; | ||
| 15 | - | ||
| 16 | - replicator.once('final', event => { | ||
| 17 | - eventEmitter.emit('complete'); | ||
| 18 | - eventEmitter.removeAllListeners(); | ||
| 19 | - }); | ||
| 20 | - | ||
| 21 | - replicator.on('error', event => { | ||
| 22 | - eventEmitter.emit('file-replicator-error', event); | ||
| 23 | - }); | ||
| 24 | - | ||
| 25 | - replicator.on('complete', event => { | ||
| 26 | - eventEmitter.emit('file-replicator-complete', event); | ||
| 27 | - }); | ||
| 28 | - | ||
| 29 | - replicator.on('progress', event => { | ||
| 30 | - eventEmitter.emit('file-replicator-progress', event); | ||
| 31 | - }); | ||
| 32 | - | ||
| 33 | - emitter.once('change', info => { | ||
| 34 | - eventEmitter.emit('change', info); | ||
| 35 | - }); | ||
| 36 | - | ||
| 37 | - emitter.once('complete', info => { | ||
| 38 | - db.query('index_type/type',{ | ||
| 39 | - include_docs : true, | ||
| 40 | - key : replicator.itemValue | ||
| 41 | - }).then((res) => { | ||
| 42 | - let docs = { docs : [] }; | ||
| 43 | - for (let r of res.rows) { | ||
| 44 | - docs.docs.push(r.doc); | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | - replicator.pushChanges(docs); | ||
| 48 | - replicator.start(); | ||
| 49 | - }).catch(error => { | ||
| 50 | - eventEmitter.emit('error', error); | ||
| 51 | - }); | ||
| 52 | - }); | ||
| 53 | - | ||
| 54 | - emitter.once('error', (error) => { | ||
| 55 | - eventEmitter.emit('error', error); | ||
| 56 | - }); | ||
| 57 | - | ||
| 58 | - return eventEmitter; | ||
| 59 | - }; | ||
| 60 | - }); | ||
| 61 | -}; | ||
| 62 | - | ||
| 63 | -if (typeof window !== 'undefined' && window['PouchDB']) { | ||
| 64 | - loadBsyncPlugin(window['PouchDB']); | ||
| 65 | -} | ... | ... |
| ... | @@ -5,24 +5,26 @@ export const CONFIG_ITEM_TARGET_ATTRIBUTE = "itemTargetAttribute"; | ... | @@ -5,24 +5,26 @@ export const CONFIG_ITEM_TARGET_ATTRIBUTE = "itemTargetAttribute"; |
| 5 | export const CONFIG_ITEM_VALIDATOR = "itemValidator"; | 5 | export const CONFIG_ITEM_VALIDATOR = "itemValidator"; |
| 6 | export const CONFIG_RETRY_TIMEOUT = "retryTimeout"; | 6 | export const CONFIG_RETRY_TIMEOUT = "retryTimeout"; |
| 7 | export const CONFIG_FILE_HANDLER = "fileHandler"; | 7 | export const CONFIG_FILE_HANDLER = "fileHandler"; |
| 8 | +export const CONFIG_TARGET_DIRECTORY = "targetDirectory"; | ||
| 8 | 9 | ||
| 9 | export class Config { | 10 | export class Config { |
| 10 | 11 | ||
| 11 | protected config:any = {}; | 12 | protected config:any = {}; |
| 12 | 13 | ||
| 13 | - hasConfig(key:string) { | 14 | + hasConfig(key:string) : boolean { |
| 14 | if (this.config[key]) { | 15 | if (this.config[key]) { |
| 15 | return true; | 16 | return true; |
| 16 | } | 17 | } |
| 17 | return false; | 18 | return false; |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | - getConfig(key:string) { | 21 | + getConfig(key:string) : any { |
| 21 | return this.config[key]; | 22 | return this.config[key]; |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | - setConfig(key:string, value:any) { | 25 | + setConfig(key:string, value:any) : Config { |
| 25 | this.config[key] = value; | 26 | this.config[key] = value; |
| 27 | + return this; | ||
| 26 | } | 28 | } |
| 27 | 29 | ||
| 28 | } | 30 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | +import { Util } from './../util'; | ||
| 2 | +import { EventEmitter } from 'events'; | ||
| 1 | import { FileHandler } from '../api/file-handler'; | 3 | import { FileHandler } from '../api/file-handler'; |
| 4 | +import { File } from '../api/file'; | ||
| 2 | 5 | ||
| 3 | -declare var Rx; | 6 | +export class CordovaFileHandler extends EventEmitter implements FileHandler { |
| 4 | 7 | ||
| 5 | -export class CordovaDownloader implements FileHandler { | 8 | + triggerFileTransfer(source:string, target:string) { |
| 9 | + let fileTransfer = new window['FileTransfer'](); | ||
| 6 | 10 | ||
| 7 | - download(source:string, target:string) : Rx.Observable<number> { | 11 | + fileTransfer.onprogress = (progress:ProgressEvent) => { |
| 8 | - return Rx.Observable.create((subscriber:Rx.Subscriber<number>) => { | 12 | + this.emit('progress', progress.loaded / progress.total); |
| 13 | + }; | ||
| 9 | 14 | ||
| 10 | - if (!window['FileTransfer']) { | 15 | + fileTransfer.download( |
| 11 | - subscriber.error("Cordova FileTransfer object undefined"); | 16 | + source , |
| 17 | + target , | ||
| 18 | + (entry:any) => { | ||
| 19 | + this.emit('complete', entry); | ||
| 20 | + } , | ||
| 21 | + (error:any) => { | ||
| 22 | + this.emit('error', error); | ||
| 23 | + }, | ||
| 24 | + true | ||
| 25 | + ); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + download(source:string, target:string) { | ||
| 29 | + if (!window['FileTransfer']) { | ||
| 30 | + this.emit('error','Cordova FileTransfer object undefined'); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + window['resolveLocalFileSystemURL'](target, (entry:any) => { | ||
| 34 | + entry.getMetadata((metadata) => { | ||
| 35 | + if (metadata.size > 0) { | ||
| 36 | + this.emit('complete', entry); | ||
| 37 | + } else { | ||
| 38 | + // file empty trigger transfer | ||
| 39 | + this.triggerFileTransfer(source,target); | ||
| 40 | + } | ||
| 41 | + }, () => { | ||
| 42 | + // cannot read metadata trigger transfer | ||
| 43 | + this.triggerFileTransfer(source,target); | ||
| 44 | + }); | ||
| 45 | + }, () => { | ||
| 46 | + // file not found, so download it | ||
| 47 | + this.triggerFileTransfer(source,target); | ||
| 48 | + }); | ||
| 49 | + | ||
| 50 | + return this; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + cleanup(files:Array<File>, basePath:string) : Promise<void> { | ||
| 54 | + let filesForCleanup = []; | ||
| 55 | + | ||
| 56 | + return new Promise<void>((resolve, reject) => { | ||
| 57 | + | ||
| 58 | + if (window['resolveLocalFileSystemURL']) { | ||
| 59 | + window['resolveLocalFileSystemURL'](basePath, (entry) => { | ||
| 60 | + let reader = entry.createReader(); | ||
| 61 | + reader.readEntries((entries) => { | ||
| 62 | + | ||
| 63 | + for (let e of entries) { | ||
| 64 | + if (e && e.isFile) { | ||
| 65 | + if (Util.getFileIndex(files, e.name) < 0) { | ||
| 66 | + filesForCleanup.push(e); | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + let index = 0; | ||
| 72 | + let error = false; | ||
| 73 | + | ||
| 74 | + let cleanupError = (error) => { | ||
| 75 | + this.emit('cleanup-error', error); | ||
| 76 | + reject(); | ||
| 77 | + error = true; | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + let cleanupNext = () => { | ||
| 81 | + if (index < filesForCleanup.length && !error) { | ||
| 82 | + filesForCleanup[index].remove(cleanupNext, cleanupError); | ||
| 83 | + index += 1; | ||
| 84 | + } else if (!error) { | ||
| 85 | + this.emit('cleanup-complete', filesForCleanup); | ||
| 86 | + resolve(); | ||
| 87 | + } | ||
| 88 | + }; | ||
| 89 | + | ||
| 90 | + cleanupNext(); | ||
| 91 | + | ||
| 92 | + }, (error) => { this.emit('cleanup-error', error); reject(); }); | ||
| 93 | + }); | ||
| 12 | } | 94 | } |
| 13 | 95 | ||
| 14 | - let fileTransfer = new window['FileTransfer'](); | 96 | + }); |
| 15 | - | ||
| 16 | - fileTransfer.onprogress = (progress:ProgressEvent) => { | ||
| 17 | - subscriber.next(progress.loaded / progress.total); | ||
| 18 | - }; | ||
| 19 | - | ||
| 20 | - fileTransfer.download( | ||
| 21 | - source , | ||
| 22 | - target , | ||
| 23 | - (entry:any) => { | ||
| 24 | - subscriber.complete(); | ||
| 25 | - } , | ||
| 26 | - (error:any) => { | ||
| 27 | - subscriber.error(error); | ||
| 28 | - }, | ||
| 29 | - true | ||
| 30 | - ); | ||
| 31 | - | ||
| 32 | - }); | ||
| 33 | } | 97 | } |
| 34 | 98 | ||
| 35 | } | 99 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -import { Observable, Subscriber } from 'rxjs'; | 1 | +import { EventEmitter } from 'events'; |
| 2 | import { FileHandler } from '../api/file-handler'; | 2 | import { FileHandler } from '../api/file-handler'; |
| 3 | +import { File } from '../api/file'; | ||
| 3 | 4 | ||
| 4 | -export class ElectronFileHandler implements FileHandler { | 5 | +export class ElectronFileHandler extends EventEmitter implements FileHandler { |
| 5 | 6 | ||
| 6 | constructor (private ipcRenderer:any) { | 7 | constructor (private ipcRenderer:any) { |
| 8 | + super(); | ||
| 7 | } | 9 | } |
| 8 | 10 | ||
| 9 | - download(source:string, target:string) : Observable<number> { | 11 | + download(source:string, target:string) { |
| 10 | - return Observable.create((subscriber:Subscriber<number>) => { | 12 | + this.ipcRenderer.once('bsync-download-complete', () => { |
| 13 | + this.ipcRenderer.removeAllListeners('bsync-download-progress'); | ||
| 14 | + this.ipcRenderer.removeAllListeners('bsync-download-error'); | ||
| 15 | + this.emit('complete'); | ||
| 16 | + }); | ||
| 11 | 17 | ||
| 12 | - this.ipcRenderer.once('bsync-download-complete', () => { | 18 | + this.ipcRenderer.on('bsync-download-progress', (progress:number) => { |
| 13 | - this.ipcRenderer.removeAllListeners('bsync-download-progress'); | 19 | + this.emit('progress', progress); |
| 14 | - this.ipcRenderer.removeAllListeners('bsync-download-error'); | 20 | + }); |
| 15 | - subscriber.complete(); | ||
| 16 | - }); | ||
| 17 | 21 | ||
| 18 | - this.ipcRenderer.on('bsync-download-progress', (progress:number) => { | 22 | + this.ipcRenderer.once('bsync-download-error', (error:any) => { |
| 19 | - subscriber.next(progress); | 23 | + this.ipcRenderer.removeAllListeners('bsync-download-progress'); |
| 20 | - }); | 24 | + this.ipcRenderer.removeAllListeners('bsync-download-complete'); |
| 25 | + this.emit('error', error); | ||
| 26 | + }); | ||
| 21 | 27 | ||
| 22 | - this.ipcRenderer.once('bsync-download-error', (error:any) => { | 28 | + this.ipcRenderer.send('bsync-download', { |
| 23 | - this.ipcRenderer.removeAllListeners('bsync-download-progress'); | 29 | + source : source , |
| 24 | - this.ipcRenderer.removeAllListeners('bsync-download-complete'); | 30 | + target : target |
| 25 | - subscriber.error(error); | 31 | + }); |
| 26 | - }); | 32 | + |
| 33 | + return this; | ||
| 34 | + } | ||
| 27 | 35 | ||
| 28 | - this.ipcRenderer.send('bsync-download', { | 36 | + cleanup(files:Array<File>) : Promise<void> { |
| 29 | - source : source , | 37 | + return new Promise<void>((resolve, reject) => { |
| 30 | - target : target | 38 | + |
| 39 | + this.ipcRenderer.once('bsync-cleanup-complete', () => { | ||
| 40 | + this.emit('cleanup-complete'); | ||
| 41 | + resolve(); | ||
| 31 | }); | 42 | }); |
| 43 | + | ||
| 44 | + this.ipcRenderer.send('bsync-cleanup', files); | ||
| 45 | + | ||
| 32 | }); | 46 | }); |
| 33 | } | 47 | } |
| 34 | 48 | ... | ... |
| 1 | -import { Observable } from 'rxjs/Observable'; | 1 | +import { Util } from './../util'; |
| 2 | -import { Subscriber } from 'rxjs/Subscriber'; | 2 | +import { EventEmitter } from 'events'; |
| 3 | import { FileHandler } from '../api/file-handler'; | 3 | import { FileHandler } from '../api/file-handler'; |
| 4 | +import { File } from '../api/file'; | ||
| 4 | import * as http from 'http'; | 5 | import * as http from 'http'; |
| 5 | import * as https from 'https'; | 6 | import * as https from 'https'; |
| 6 | import * as fs from 'fs'; | 7 | import * as fs from 'fs'; |
| 7 | 8 | ||
| 8 | -export class NodeFileHandler implements FileHandler { | 9 | +export class NodeFileHandler extends EventEmitter implements FileHandler { |
| 9 | 10 | ||
| 10 | selectProtocol(url:string) : any { | 11 | selectProtocol(url:string) : any { |
| 11 | if (url.search(/^http:\/\//) === 0) { | 12 | if (url.search(/^http:\/\//) === 0) { |
| ... | @@ -17,23 +18,20 @@ export class NodeFileHandler implements FileHandler { | ... | @@ -17,23 +18,20 @@ export class NodeFileHandler implements FileHandler { |
| 17 | } | 18 | } |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | - download(source:string, target:string) : Observable<number> { | 21 | + download(source:string, target:string) { |
| 21 | 22 | ||
| 22 | let handler = this.selectProtocol(source); | 23 | let handler = this.selectProtocol(source); |
| 23 | 24 | ||
| 24 | - return Observable.create((subscriber:Subscriber<number>) => { | 25 | + if (!handler) { |
| 25 | - | 26 | + this.emit("error","No handler for source: " + source); |
| 26 | - if (!handler) { | 27 | + return this; |
| 27 | - subscriber.error("No handler for source: " + source); | 28 | + } |
| 28 | - return; | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - // file already exists and is not empty | ||
| 32 | - if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) { | ||
| 33 | - subscriber.complete(); | ||
| 34 | - return; | ||
| 35 | - } | ||
| 36 | 29 | ||
| 30 | + // file already exists and is not empty | ||
| 31 | + if (fs.existsSync(target) && (fs.statSync(target)['size'] > 0)) { | ||
| 32 | + this.emit("complete"); | ||
| 33 | + return this; | ||
| 34 | + } else { | ||
| 37 | let file = fs.createWriteStream(target, {'flags': 'a'}); | 35 | let file = fs.createWriteStream(target, {'flags': 'a'}); |
| 38 | 36 | ||
| 39 | handler.get(source, (response) => { | 37 | handler.get(source, (response) => { |
| ... | @@ -41,29 +39,42 @@ export class NodeFileHandler implements FileHandler { | ... | @@ -41,29 +39,42 @@ export class NodeFileHandler implements FileHandler { |
| 41 | let prog = 0; // already downloaded | 39 | let prog = 0; // already downloaded |
| 42 | let progCounts = 100; // how many progress events should be triggerd (1-100 %) | 40 | let progCounts = 100; // how many progress events should be triggerd (1-100 %) |
| 43 | let nextProg = (1/progCounts); | 41 | let nextProg = (1/progCounts); |
| 44 | - | 42 | + |
| 45 | response.on('data', (chunk) => { | 43 | response.on('data', (chunk) => { |
| 46 | prog += chunk.length; | 44 | prog += chunk.length; |
| 47 | file.write(chunk, 'binary'); | 45 | file.write(chunk, 'binary'); |
| 48 | 46 | ||
| 49 | if ((prog / size) > nextProg) { | 47 | if ((prog / size) > nextProg) { |
| 50 | - subscriber.next(prog / size); | 48 | + this.emit('progress',prog / size); |
| 51 | nextProg += (1 / progCounts); | 49 | nextProg += (1 / progCounts); |
| 52 | } | 50 | } |
| 53 | }); | 51 | }); |
| 54 | 52 | ||
| 55 | - response.on('end', () => { | 53 | + response.once('end', () => { |
| 56 | file.end(); | 54 | file.end(); |
| 57 | - subscriber.complete(); | 55 | + this.emit('complete'); |
| 58 | - }); | 56 | + }); |
| 59 | - | 57 | + |
| 60 | }).on('error', (error) => { | 58 | }).on('error', (error) => { |
| 61 | fs.unlink(target); | 59 | fs.unlink(target); |
| 62 | - subscriber.error("Error while downloading: " + error); | 60 | + this.emit("error", "Error while downloading: " + error); |
| 63 | }); | 61 | }); |
| 64 | 62 | ||
| 65 | - }); | 63 | + return this; |
| 64 | + } | ||
| 65 | + } | ||
| 66 | 66 | ||
| 67 | + cleanup(files:Array<File>, basePath?:string) { | ||
| 68 | + try { | ||
| 69 | + let localFiles = fs.readdirSync(basePath); | ||
| 70 | + Util.getFilesForCleanup(files, localFiles) | ||
| 71 | + .forEach((file) => { | ||
| 72 | + fs.unlinkSync(basePath + "/" + file); | ||
| 73 | + }); | ||
| 74 | + } catch (e) { | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + return this; | ||
| 67 | } | 78 | } |
| 68 | 79 | ||
| 69 | } | 80 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -import {FileHandler} from './api/file-handler'; | 1 | +import { FileHandler } from './api/file-handler'; |
| 2 | -import {File} from './api/file'; | 2 | +import { File } from './api/file'; |
| 3 | -import {Util} from './util'; | 3 | +import { Util } from './util'; |
| 4 | -import {EventEmitter} from 'events'; | 4 | +import { EventEmitter } from 'events'; |
| 5 | 5 | ||
| 6 | export class FileReplicator extends EventEmitter { | 6 | export class FileReplicator extends EventEmitter { |
| 7 | 7 | ||
| ... | @@ -9,46 +9,52 @@ export class FileReplicator extends EventEmitter { | ... | @@ -9,46 +9,52 @@ export class FileReplicator extends EventEmitter { |
| 9 | super(); | 9 | super(); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | - protected _files:Array<File> = []; | 12 | + protected _files: Array<File> = []; |
| 13 | 13 | ||
| 14 | - protected _itemValidator: (item:any) => boolean = null; | 14 | + protected _itemValidator: (item: any) => boolean = null; |
| 15 | - protected _fileHandler:FileHandler = null; | 15 | + protected _fileHandler: FileHandler = null; |
| 16 | - protected _retryTimeout:number = 0; | 16 | + protected _retryTimeout: number = 100; |
| 17 | - | 17 | + protected _retries: number = 10; |
| 18 | - protected _itemKey = "type"; | 18 | + |
| 19 | + protected _itemKey = "type"; | ||
| 19 | protected _itemValue = "asset"; | 20 | protected _itemValue = "asset"; |
| 20 | protected _itemSourceAttribute = "source"; | 21 | protected _itemSourceAttribute = "source"; |
| 21 | protected _itemTargetAttribute = "target"; | 22 | protected _itemTargetAttribute = "target"; |
| 23 | + protected _targetDirectory = ""; | ||
| 22 | 24 | ||
| 23 | get files(): Array<File> { | 25 | get files(): Array<File> { |
| 24 | return this._files; | 26 | return this._files; |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | - set fileHandler (handler:FileHandler) { | 29 | + set fileHandler(handler: FileHandler) { |
| 28 | this._fileHandler = handler; | 30 | this._fileHandler = handler; |
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | - set retryTimeout (timeout:number) { | 33 | + get fileHandler() : FileHandler { |
| 34 | + return this._fileHandler; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + set retryTimeout(timeout: number) { | ||
| 32 | this._retryTimeout = timeout; | 38 | this._retryTimeout = timeout; |
| 33 | } | 39 | } |
| 34 | 40 | ||
| 35 | - set itemValidator(validator:(item:any) => boolean) { | 41 | + set itemValidator(validator: (item: any) => boolean) { |
| 36 | this._itemValidator = validator; | 42 | this._itemValidator = validator; |
| 37 | } | 43 | } |
| 38 | 44 | ||
| 39 | - set itemKey(key:string) { | 45 | + set itemKey(key: string) { |
| 40 | this._itemKey = key; | 46 | this._itemKey = key; |
| 41 | } | 47 | } |
| 42 | 48 | ||
| 43 | - set itemValue(value:string) { | 49 | + set itemValue(value: string) { |
| 44 | this._itemValue = value; | 50 | this._itemValue = value; |
| 45 | } | 51 | } |
| 46 | 52 | ||
| 47 | - set itemSourceAttribute(sourceAttribute:string) { | 53 | + set itemSourceAttribute(sourceAttribute: string) { |
| 48 | this._itemSourceAttribute = sourceAttribute; | 54 | this._itemSourceAttribute = sourceAttribute; |
| 49 | } | 55 | } |
| 50 | 56 | ||
| 51 | - set itemTargetAttribute(targetAttribute:string) { | 57 | + set itemTargetAttribute(targetAttribute: string) { |
| 52 | this._itemTargetAttribute = targetAttribute; | 58 | this._itemTargetAttribute = targetAttribute; |
| 53 | } | 59 | } |
| 54 | 60 | ||
| ... | @@ -68,24 +74,32 @@ export class FileReplicator extends EventEmitter { | ... | @@ -68,24 +74,32 @@ export class FileReplicator extends EventEmitter { |
| 68 | return this._itemTargetAttribute; | 74 | return this._itemTargetAttribute; |
| 69 | } | 75 | } |
| 70 | 76 | ||
| 71 | - init(files: Array<File> = []) { | 77 | + set targetDirectory(targetDirectory: string) { |
| 78 | + this._targetDirectory = targetDirectory; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + get targetDirectory() { | ||
| 82 | + return this._targetDirectory; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + clear(files: Array<File> = []) { | ||
| 72 | this._files = files; | 86 | this._files = files; |
| 73 | } | 87 | } |
| 74 | 88 | ||
| 75 | /** | 89 | /** |
| 76 | * change from pouchdb replicate | 90 | * change from pouchdb replicate |
| 77 | */ | 91 | */ |
| 78 | - pushChanges(change:any) { | 92 | + pushChanges(docs: Array<any>) { |
| 79 | - let items:Array<any> = []; | 93 | + let items: Array<any> = []; |
| 80 | 94 | ||
| 81 | - if (change && change.docs && change.docs.length > 0) { | 95 | + if (docs && docs.length > 0) { |
| 82 | - for (let item of change.docs) { | 96 | + for (let item of docs) { |
| 83 | if (item[this._itemKey] && item[this._itemKey] === this._itemValue) { | 97 | if (item[this._itemKey] && item[this._itemKey] === this._itemValue) { |
| 84 | items.push(item); | 98 | items.push(item); |
| 85 | } | 99 | } |
| 86 | } | 100 | } |
| 87 | } | 101 | } |
| 88 | - | 102 | + |
| 89 | let files = this.prepareFiles(items); | 103 | let files = this.prepareFiles(items); |
| 90 | 104 | ||
| 91 | for (let file of files) { | 105 | for (let file of files) { |
| ... | @@ -93,35 +107,35 @@ export class FileReplicator extends EventEmitter { | ... | @@ -93,35 +107,35 @@ export class FileReplicator extends EventEmitter { |
| 93 | } | 107 | } |
| 94 | } | 108 | } |
| 95 | 109 | ||
| 96 | - downloadFiles(files:Array<File>, fileHandler:FileHandler, index:number = 0) { | 110 | + downloadFiles(files: Array<File>, fileHandler: FileHandler, index: number = 0) { |
| 97 | if (index >= files.length) { | 111 | if (index >= files.length) { |
| 98 | return; | 112 | return; |
| 99 | } | 113 | } |
| 100 | 114 | ||
| 101 | - this.emit('start', { progress: 0, index : index, length : files.length }); | 115 | + this.emit('start', { progress: 0, index: index, length: files.length }); |
| 102 | - | 116 | + |
| 103 | fileHandler | 117 | fileHandler |
| 104 | - .download(files[index].source, files[index].target) | 118 | + .on('progress', (progress) => { |
| 105 | - .subscribe( | 119 | + this.emit('file-progress', { progress: progress, index: index, length: files.length }) |
| 106 | - progress => { | 120 | + }) |
| 107 | - this.emit('progress', { progress : progress, index : index, length : files.length }) | 121 | + .once('error', error => { |
| 108 | - } , | 122 | + this.emit('file-error', { progress: 0, index: index, length: files.length, error: error }); |
| 109 | - error => { | 123 | + fileHandler.removeAllListeners(); |
| 110 | - this.emit('error', { progress : 0, index : index, length : files.length, error: error }); | 124 | + }) |
| 111 | - } , | 125 | + .once('complete', () => { |
| 112 | - () => { | 126 | + this.emit('file-complete', { progress: 100, index: index, length: files.length }); |
| 113 | - this.emit('complete', { progress : 100 , index : index, length : files.length }); | 127 | + fileHandler.removeAllListeners(); |
| 114 | - this.downloadFiles(files, fileHandler, index+1); | 128 | + this.downloadFiles(files, fileHandler, index + 1); |
| 115 | - } | 129 | + }) |
| 116 | - ); | 130 | + .download(files[index].source, this.targetDirectory + files[index].target); |
| 117 | - } | 131 | + } |
| 118 | - | 132 | + |
| 119 | - prepareFiles(items: Array<any>) : Array<File> { | 133 | + prepareFiles(items: Array<any>): Array<File> { |
| 120 | let output = []; | 134 | let output = []; |
| 121 | 135 | ||
| 122 | for (let item of items) { | 136 | for (let item of items) { |
| 123 | if (item[this._itemSourceAttribute] && (!this._itemValidator || this._itemValidator(item))) { | 137 | if (item[this._itemSourceAttribute] && (!this._itemValidator || this._itemValidator(item))) { |
| 124 | - let file = { source : item[this._itemSourceAttribute] , target : '' }; | 138 | + let file = { source: item[this._itemSourceAttribute], target: '' }; |
| 125 | 139 | ||
| 126 | if (item[this._itemTargetAttribute]) { | 140 | if (item[this._itemTargetAttribute]) { |
| 127 | file.target = item[this._itemTargetAttribute]; | 141 | file.target = item[this._itemTargetAttribute]; |
| ... | @@ -136,30 +150,48 @@ export class FileReplicator extends EventEmitter { | ... | @@ -136,30 +150,48 @@ export class FileReplicator extends EventEmitter { |
| 136 | return output; | 150 | return output; |
| 137 | } | 151 | } |
| 138 | 152 | ||
| 139 | - start() { | 153 | + start(retries:number = 10) { |
| 140 | - this.on('complete', (event:any) => { | 154 | + this._retries = retries; |
| 155 | + | ||
| 156 | + this.on('file-complete', (event: any) => { | ||
| 141 | if ((event.index + 1) >= event.length) { | 157 | if ((event.index + 1) >= event.length) { |
| 142 | this.replicationFinalized(event.index); | 158 | this.replicationFinalized(event.index); |
| 143 | } | 159 | } |
| 144 | }); | 160 | }); |
| 145 | 161 | ||
| 146 | - this.on('error', (event:any) => { | 162 | + this.on('file-error', (event: any) => { |
| 147 | this.replicationFinalized(event.index); | 163 | this.replicationFinalized(event.index); |
| 148 | - }); | 164 | + }); |
| 149 | 165 | ||
| 150 | - this.downloadFiles(this._files, this._fileHandler); | 166 | + if (this._fileHandler && this._files.length > 0) { |
| 167 | + this.downloadFiles(this._files, this._fileHandler); | ||
| 168 | + } else { | ||
| 169 | + this.emit('complete'); | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + cleanup() { | ||
| 174 | + this.fileHandler | ||
| 175 | + .cleanup(this._files, this._targetDirectory) | ||
| 176 | + .then(() => { | ||
| 177 | + this.emit('cleanup-complete'); | ||
| 178 | + }).catch(() => { | ||
| 179 | + this.emit('cleanup-error'); | ||
| 180 | + }); | ||
| 151 | } | 181 | } |
| 152 | 182 | ||
| 153 | - replicationFinalized(lastIndex:number) { | 183 | + replicationFinalized(lastIndex: number) { |
| 154 | - if (lastIndex+1 >= this._files.length) { // all finished | 184 | + if (lastIndex + 1 >= this._files.length) { // all finished |
| 155 | - this._files = []; | 185 | + this.emit('complete'); |
| 156 | - this.emit('final'); | 186 | + } else if (this._retries > 0) { // restart after last success |
| 157 | - } else if (this._retryTimeout > 0) { // restart after last success | 187 | + this._files.splice(0, lastIndex); |
| 158 | - this._files.splice(0,lastIndex); | 188 | + setTimeout(() => { |
| 159 | - setTimeout(() => { | 189 | + this._retries =- 1; |
| 160 | this.downloadFiles(this._files, this._fileHandler); | 190 | this.downloadFiles(this._files, this._fileHandler); |
| 161 | }, this._retryTimeout); | 191 | }, this._retryTimeout); |
| 162 | - } | 192 | + } else { |
| 193 | + this.emit('error'); | ||
| 194 | + } | ||
| 163 | } | 195 | } |
| 164 | 196 | ||
| 165 | } | 197 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -2,17 +2,22 @@ import { NodeFileHandler } from './file-handler/node-file-handler'; | ... | @@ -2,17 +2,22 @@ import { NodeFileHandler } from './file-handler/node-file-handler'; |
| 2 | 2 | ||
| 3 | export default class Bsync { | 3 | export default class Bsync { |
| 4 | 4 | ||
| 5 | - static configIpcMain(ipcMain: any, downloadDir:string) { | 5 | + static configIpcMain(ipcMain: any, basePath: string) { |
| 6 | - let nodeFileHander = new NodeFileHandler(); | 6 | + |
| 7 | - | ||
| 8 | ipcMain.on('bsync-download', (event, args) => { | 7 | ipcMain.on('bsync-download', (event, args) => { |
| 9 | - nodeFileHander.download(args.source, downloadDir + args.target) | 8 | + let nodeFileHander = new NodeFileHandler(); |
| 10 | - .subscribe( | 9 | + nodeFileHander.download(args.source, basePath + "/" + args.target) |
| 11 | - (progress:number) => { event.sender.send('bsync-download-progress', progress); } , | 10 | + .on('progress', (progress:number) => { event.sender.send('bsync-download-progress', progress); }) |
| 12 | - (error:any) => { event.sender.send('bsync-download-error', error); } , | 11 | + .once('error', (error) => { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-error', error); }) |
| 13 | - () => { event.sender.send('bsync-download-complete'); } | 12 | + .once('complete', () => { nodeFileHander.removeAllListeners(); event.sender.send('bsync-download-complete'); }); |
| 14 | - ); | 13 | + }); |
| 14 | + | ||
| 15 | + ipcMain.on('bsync-cleanup', (event, args) => { | ||
| 16 | + let nodeFileHandler = new NodeFileHandler(); | ||
| 17 | + nodeFileHandler.cleanup(args.files, basePath); | ||
| 18 | + event.sender.send('bsync-cleanup-complete'); | ||
| 15 | }); | 19 | }); |
| 20 | + | ||
| 16 | } | 21 | } |
| 17 | 22 | ||
| 18 | } | 23 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | import {FileHandler} from './api/file-handler'; | 1 | import {FileHandler} from './api/file-handler'; |
| 2 | import {ElectronFileHandler} from './file-handler/electron-file-handler'; | 2 | import {ElectronFileHandler} from './file-handler/electron-file-handler'; |
| 3 | -import {CordovaDownloader} from './file-handler/cordova-file-handler'; | 3 | +import {CordovaFileHandler} from './file-handler/cordova-file-handler'; |
| 4 | import {FileReplicator} from './file-replicator'; | 4 | import {FileReplicator} from './file-replicator'; |
| 5 | import { | 5 | import { |
| 6 | Config, | 6 | Config, |
| ... | @@ -8,7 +8,8 @@ import { | ... | @@ -8,7 +8,8 @@ import { |
| 8 | CONFIG_ITEM_KEY, | 8 | CONFIG_ITEM_KEY, |
| 9 | CONFIG_ITEM_VALUE, | 9 | CONFIG_ITEM_VALUE, |
| 10 | CONFIG_ITEM_TARGET_ATTRIBUTE, | 10 | CONFIG_ITEM_TARGET_ATTRIBUTE, |
| 11 | - CONFIG_ITEM_SOURCE_ATTRIBUTE | 11 | + CONFIG_ITEM_SOURCE_ATTRIBUTE, |
| 12 | + CONFIG_TARGET_DIRECTORY | ||
| 12 | } from './config'; | 13 | } from './config'; |
| 13 | 14 | ||
| 14 | export const ENV_ELECTRON = "electron"; | 15 | export const ENV_ELECTRON = "electron"; |
| ... | @@ -56,7 +57,7 @@ export class ServiceLocator { | ... | @@ -56,7 +57,7 @@ export class ServiceLocator { |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | if (environment === ENV_CORDOVA) { | 59 | if (environment === ENV_CORDOVA) { |
| 59 | - return new CordovaDownloader(); | 60 | + return new CordovaFileHandler(); |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | return null; | 63 | return null; |
| ... | @@ -64,28 +65,29 @@ export class ServiceLocator { | ... | @@ -64,28 +65,29 @@ export class ServiceLocator { |
| 64 | 65 | ||
| 65 | static getFileReplicator() : FileReplicator { | 66 | static getFileReplicator() : FileReplicator { |
| 66 | if (!ServiceLocator.fileReplicator) { | 67 | if (!ServiceLocator.fileReplicator) { |
| 67 | - | ||
| 68 | ServiceLocator.fileReplicator = new FileReplicator(); | 68 | ServiceLocator.fileReplicator = new FileReplicator(); |
| 69 | - | ||
| 70 | ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler(); | 69 | ServiceLocator.fileReplicator.fileHandler = ServiceLocator.getFileHandler(); |
| 70 | + } | ||
| 71 | 71 | ||
| 72 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) { | 72 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_RETRY_TIMEOUT)) { |
| 73 | - ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT); | 73 | + ServiceLocator.fileReplicator.retryTimeout = ServiceLocator.getConfig().getConfig(CONFIG_RETRY_TIMEOUT); |
| 74 | - } | 74 | + } |
| 75 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) { | 75 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_KEY)) { |
| 76 | - ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY); | 76 | + ServiceLocator.fileReplicator.itemKey = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_KEY); |
| 77 | - } | 77 | + } |
| 78 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) { | 78 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_VALUE)) { |
| 79 | - ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE); | 79 | + ServiceLocator.fileReplicator.itemValue = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_VALUE); |
| 80 | - } | 80 | + } |
| 81 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) { | 81 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE)) { |
| 82 | - ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE); | 82 | + ServiceLocator.fileReplicator.itemSourceAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_SOURCE_ATTRIBUTE); |
| 83 | - } | 83 | + } |
| 84 | - if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) { | 84 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_ITEM_TARGET_ATTRIBUTE)) { |
| 85 | - ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE); | 85 | + ServiceLocator.fileReplicator.itemTargetAttribute = ServiceLocator.getConfig().getConfig(CONFIG_ITEM_TARGET_ATTRIBUTE); |
| 86 | - } | 86 | + } |
| 87 | - } | 87 | + if (ServiceLocator.getConfig().hasConfig(CONFIG_TARGET_DIRECTORY)) { |
| 88 | - | 88 | + ServiceLocator.fileReplicator.targetDirectory = ServiceLocator.getConfig().getConfig(CONFIG_TARGET_DIRECTORY); |
| 89 | + } | ||
| 90 | + | ||
| 89 | return ServiceLocator.fileReplicator; | 91 | return ServiceLocator.fileReplicator; |
| 90 | } | 92 | } |
| 91 | 93 | ... | ... |
| 1 | +import { File } from './api/file'; | ||
| 2 | + | ||
| 1 | export class Util { | 3 | export class Util { |
| 2 | 4 | ||
| 3 | static getNameHash(path:string) { | 5 | static getNameHash(path:string) { |
| ... | @@ -7,4 +9,36 @@ export class Util { | ... | @@ -7,4 +9,36 @@ export class Util { |
| 7 | return "bsync_" + Math.abs(r); | 9 | return "bsync_" + Math.abs(r); |
| 8 | } | 10 | } |
| 9 | 11 | ||
| 12 | + /** | ||
| 13 | + * index >= 0, localFile is in files | ||
| 14 | + * index < 0, localFile is not in files | ||
| 15 | + */ | ||
| 16 | + static getFileIndex(files:Array<File>, localFile:string) : number { | ||
| 17 | + for (let i = 0; i < files.length; i++) { | ||
| 18 | + if (localFile == files[i].target) { | ||
| 19 | + return i; | ||
| 20 | + } | ||
| 21 | + } | ||
| 22 | + return -1; | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + static getFilesForCleanup(files:Array<File>, localFiles:Array<string>) : Array<string> { | ||
| 26 | + let filesForCleanup = []; | ||
| 27 | + | ||
| 28 | + for (let localFile of localFiles) { | ||
| 29 | + let index = -1; | ||
| 30 | + | ||
| 31 | + index = Util.getFileIndex(files, localFile); | ||
| 32 | + | ||
| 33 | + if (index < 0) { | ||
| 34 | + filesForCleanup.push(localFile); | ||
| 35 | + } else { | ||
| 36 | + // splice for performance improvement only | ||
| 37 | + files.splice(index,1); | ||
| 38 | + } | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + return filesForCleanup; | ||
| 42 | + } | ||
| 43 | + | ||
| 10 | } | 44 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment