-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathPouchDbCollectionStore.ts
72 lines (64 loc) · 2.3 KB
/
PouchDbCollectionStore.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { CollectionStore } from '../types';
import { EMPTY, Observable, Subject, from } from 'rxjs';
import { Logger } from 'ts-log';
import { PouchDbStore } from './PouchDbStore';
import { observeAll } from '../util';
import { sanitizePouchDbDoc } from './util';
export type ComputePouchDbDocId<T> = (doc: T) => string;
export interface PouchDbCollectionStoreProps<T> {
dbName: string;
computeDocId?: ComputePouchDbDocId<T>;
}
/** PouchDB database that implements CollectionStore. Supports sorting by custom document _id */
export class PouchDbCollectionStore<T extends {}> extends PouchDbStore<T> implements CollectionStore<T> {
readonly #computeDocId: ComputePouchDbDocId<T> | undefined;
readonly #updates$ = new Subject<T[]>();
observeAll: CollectionStore<T>['observeAll'];
/**
* @param props store properties
* @param props.dbName PouchDB database name
* @param props.computeDocId used for document sort order
* @param logger will silently swallow the errors if not set
*/
constructor({ dbName, computeDocId }: PouchDbCollectionStoreProps<T>, logger: Logger) {
// Using a db per collection
super(dbName, logger);
this.observeAll = observeAll(this, this.#updates$);
this.#computeDocId = computeDocId;
}
getAll(): Observable<T[]> {
if (this.destroyed) return EMPTY;
return new Observable((observer) => {
this.fetchAllDocs({ include_docs: true })
.then((result) => {
const docs = result.map(({ doc }) => sanitizePouchDbDoc(doc!));
if (docs.length > 0) observer.next(docs);
observer.complete();
})
.catch(observer.complete.bind(observer));
});
}
setAll(docs: T[]): Observable<void> {
if (this.destroyed) return EMPTY;
return from(
(this.idle = this.idle.then(async (): Promise<void> => {
try {
await this.clearDB();
await this.db.bulkDocs(
docs.map((doc) => ({
...this.toPouchDbDoc(doc),
_id: this.#computeDocId?.(doc)
}))
);
this.#updates$.next(docs);
} catch (error) {
this.logger.error(`PouchDbCollectionStore(${this.dbName}): failed to setAll`, docs, error);
}
}))
);
}
destroy(): Observable<void> {
this.#updates$.complete();
return super.destroy();
}
}