|
/******************************************************** |
|
install pouchdb and pouch db types |
|
npm install pouchdb --save |
|
npm install @types/pouchdb --save --save-exact |
|
fix CORS issues |
|
npm install -g add-cors-to-couchdb |
|
add-cors-to-couchdb |
|
********************************************************/ |
|
|
|
import { Injectable } from '@angular/core'; |
|
import { Scheduler } from 'rxjs/Rx'; |
|
import { Subject } from 'rxjs/Subject'; |
|
import * as PouchDB from 'pouchdb'; |
|
|
|
@Injectable() |
|
export class OfflineDbService { |
|
|
|
private remoteDb; |
|
private localDb; |
|
private interval; |
|
|
|
private isOnlineSource = new Subject<string>(); |
|
public isOnlineStream = this.isOnlineSource.asObservable(); |
|
private notifyOffline(msg){ |
|
this.isOnlineSource.next(JSON.stringify(msg)); |
|
} |
|
|
|
private docsSource = new Subject<string>(); |
|
public docsStream = this.docsSource.asObservable(); |
|
private pushDocs(msg){ |
|
this.docsSource.next(JSON.stringify(msg)); |
|
} |
|
|
|
private dispatchDocs(data={}):void { |
|
this.localDb.allDocs({ include_docs: true }) |
|
.then( res => this.pushDocs(Object.assign({}, data, { docs: res.rows.map( row => row.doc)})) ) |
|
.catch( err => this.pushDocs({ error: err }) ); |
|
} |
|
|
|
constructor() { } |
|
|
|
public initService(localDbName, remoteDbName, remoteDbUrl, interval=10) { |
|
this.remoteDb = new PouchDB(remoteDbUrl + '/' + remoteDbName); |
|
this.localDb = new PouchDB(localDbName); |
|
this.interval = interval * 1000; |
|
//emit a stream of database changes |
|
this.localDb.changes({live: true, since: 'now', include_docs: true}) |
|
.on('change', change => this.dispatchDocs({ updated: true, change: change })) |
|
.on('error', error => this.pushDocs({ updated: false, error: error })); |
|
//stream db docs on initialization |
|
this.pushDocs({ docs: this.dispatchDocs() }); |
|
} |
|
|
|
// periodically sync the db in the background |
|
public initSync = () => |
|
this.localDb.sync(this.remoteDb) |
|
.on('complete', () => { |
|
this.notifyOffline({onLine: true}); |
|
Scheduler.asap.schedule( () => this.initSync(), this.interval); |
|
}) |
|
.on('error', err => { |
|
this.notifyOffline({onLine: false});//emit a notification that the app is offline |
|
Scheduler.asap.schedule( () => this.initSync(), this.interval); |
|
}); |
|
|
|
public addItem(item) { |
|
return this.localDb.post(item); |
|
} |
|
|
|
public removeItem(item) { |
|
return this.localDb.remove(item._id, item._rev); |
|
} |
|
|
|
public updateItem(item, updates) { |
|
return this.localDb.put(Object.assign(item, updates)); |
|
} |
|
|
|
} |