-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathStore.ts
119 lines (101 loc) · 3.21 KB
/
Store.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { CollectionsOfDatabase, MangoQuery, RxDatabase, RxDatabaseCreator, RxDocument, addRxPlugin, createRxDatabase, removeRxDatabase } from 'rxdb';
import { RxDBJsonDumpPlugin } from 'rxdb/plugins/json-dump';
import { RxDBQueryBuilderPlugin } from 'rxdb/plugins/query-builder';
import { CollectionList, makeCollections } from "./collections";
import type { Pluto } from "../Pluto";
import { Model } from '../models';
import { RxDBEncryptedMigrationPlugin } from '../migration';
import { Domain } from '../..';
import { RxDBUpdatePlugin } from 'rxdb/plugins/update';
export class RxdbStore implements Pluto.Store {
private _db?: RxDatabase<CollectionsOfDatabase, any, any>;
constructor(
private readonly options: RxDatabaseCreator,
private readonly collections?: CollectionList
) {
addRxPlugin(RxDBQueryBuilderPlugin);
addRxPlugin(RxDBJsonDumpPlugin);
addRxPlugin(RxDBEncryptedMigrationPlugin);
addRxPlugin(RxDBUpdatePlugin);
}
get db() {
if (!this._db) {
throw new Error('Start Pluto first.');
}
return this._db;
}
/**
* Start the database and build collections
*/
async start(): Promise<void> {
if (!this._db) {
this._db = await createRxDatabase({
...this.options,
multiInstance: true
});
const collections = makeCollections(this.collections ?? {});
await this._db.addCollections(collections);
}
}
async stop(): Promise<void> {
await this.db.destroy();
delete this._db;
}
async update<T extends Domain.Pluto.Storable>(name: string, model: T): Promise<void> {
const table = this.getCollection(name);
const row = await table.findOne({
selector: {
uuid: model.uuid
}
}).exec();
if (row) {
//Improve error handling when not found
await row.patch(model);
}
}
async delete(name: string, uuid: string): Promise<void> {
const table = this.getCollection(name);
const row = await table.findOne({
selector: {
uuid: uuid
}
});
//TODO: Improve error handling, specially when not found
await row?.remove();
}
getCollection(name: string) {
const safeName = name.replace(/([A-Z])/g, "-$1").toLowerCase();
if (!this.db.collections[safeName]) {
throw new Error("Collection does not exist");
}
return this.db.collections[safeName];
}
async query<T extends Model>(name: string, query?: MangoQuery<T>) {
const collection = this.getCollection(name);
const rxQuery = collection.find(query);
const result: RxDocument[] = await rxQuery.exec();
const models = result.map(x => x._data);
return models as any;
}
async insert(name: string, data: any) {
const table = this.getCollection(name);
await table.insert(data);
}
/**
* Use with caution, this will remove all entries from database
*/
async cleanup() {
const storages = Array.from(this.db.storageInstances.values());
for (const storage of storages) {
await storage.cleanup(Infinity);
}
}
/**
* Use with caution, this will remove all entries from database
* and then destroy the database itself.
*/
async clear() {
await this.cleanup();
await removeRxDatabase(this.options.name, this.db.storage);
}
}