Skip to content

Commit 36f4b89

Browse files
committed
feat: metadata, version and random changes
1 parent 5646460 commit 36f4b89

File tree

4 files changed

+115
-14
lines changed

4 files changed

+115
-14
lines changed

packages/indexeddb/src/lib/DbHandler.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { JoshProvider, Semver } from '@joshdb/provider';
2+
import { version } from './helpers';
3+
14
export default class DbHandler<StoredValue = unknown> {
25
private idb: IDBFactory;
36
private db!: IDBDatabase;
@@ -10,22 +13,34 @@ export default class DbHandler<StoredValue = unknown> {
1013
this.idb = globalThis.indexedDB;
1114
}
1215

13-
public init() {
14-
const request = this.idb.open('josh');
16+
public init(context: JoshProvider.Context) {
17+
const { name } = context;
18+
const request = this.idb.open(`joshdb-${name}`, 1);
1519

1620
return new Promise<void>((resolve, reject) => {
1721
request.onerror = reject;
1822

1923
request.onupgradeneeded = () => {
2024
const db = request.result;
2125

26+
if (!db.objectStoreNames.contains('meta')) {
27+
db.createObjectStore('meta', { keyPath: 'key' });
28+
}
29+
2230
if (!db.objectStoreNames.contains('store')) {
2331
db.createObjectStore('store', { keyPath: 'key' });
2432
}
2533
};
2634

27-
request.onsuccess = () => {
35+
request.onsuccess = async () => {
2836
this.db = request.result;
37+
38+
const storedVersion = (await this.getMetadata('version')) as Semver | undefined;
39+
40+
if (!storedVersion) {
41+
await this.setMetadata('version', version);
42+
}
43+
2944
resolve();
3045
};
3146
});
@@ -101,6 +116,42 @@ export default class DbHandler<StoredValue = unknown> {
101116
return (await this.get(key)) !== undefined;
102117
}
103118

119+
public async getMetadata(key: string): Promise<unknown | undefined> {
120+
const all = this.openMetadata();
121+
const request = all.get(key);
122+
const result = (await this.handleEvents(request)) as {
123+
value: unknown | undefined; // Its shit like this why I don't like TS
124+
};
125+
126+
return result?.value;
127+
}
128+
129+
public async setMetadata(key: string, value: unknown) {
130+
const all = this.openMetadata();
131+
const doc = {
132+
key,
133+
value
134+
};
135+
136+
const request = all.put(doc);
137+
138+
await this.handleEvents(request);
139+
}
140+
141+
public async deleteMetadata(key: string) {
142+
const all = this.openMetadata();
143+
const request = all.delete(key);
144+
145+
return this.handleEvents(request);
146+
}
147+
148+
public async clearMetadata() {
149+
const all = this.openMetadata();
150+
const request = all.clear();
151+
152+
return this.handleEvents(request);
153+
}
154+
104155
private handleEvents(request: IDBRequest) {
105156
return new Promise((res, rej) => {
106157
request.onsuccess = () => {
@@ -119,4 +170,11 @@ export default class DbHandler<StoredValue = unknown> {
119170

120171
return all;
121172
}
173+
174+
private openMetadata() {
175+
const transaction = this.db.transaction('meta', 'readwrite');
176+
const all = transaction.objectStore('meta');
177+
178+
return all;
179+
}
122180
}

packages/indexeddb/src/lib/IndexedDBProvider.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,33 @@ import {
1111
MathOperator,
1212
Method,
1313
Payload,
14-
resolveVersion,
1514
type Semver
1615
} from '@joshdb/provider';
1716
import { deleteProperty, getProperty, hasProperty, PROPERTY_NOT_FOUND, setProperty } from 'property-helpers';
1817
import DbHandler from './DbHandler';
19-
import { handleSubCallFail, isPrimitive } from './helpers';
18+
import { handleSubCallFail, isPrimitive, version } from './helpers';
2019

2120
export class IndexedDBProvider<StoredValue = unknown> extends JoshProvider<StoredValue> {
21+
public version: Semver = version;
2222
public declare options: IndexedDBProvider.Options;
2323

2424
private db: DbHandler;
25+
2526
public constructor(options: IndexedDBProvider.Options) {
2627
super(options);
2728
this.db = new DbHandler<StoredValue>();
2829
}
2930

30-
public get version(): Semver {
31-
return resolveVersion('[VI]{version}[/VI]');
31+
public deleteMetadata(key: string): void {
32+
return this.db.deleteMetadata(key);
33+
}
34+
35+
public getMetadata(key: string): unknown {
36+
return this.db.getMetadata(key);
37+
}
38+
39+
public setMetadata(key: string, value: unknown): void {
40+
return this.db.setMetadata(key, value);
3241
}
3342

3443
public async [Method.Each]<Value = StoredValue>(payload: Payload.Each<Value>): Promise<Payload.Each<Value>> {
@@ -189,8 +198,7 @@ export class IndexedDBProvider<StoredValue = unknown> extends JoshProvider<Store
189198
public async [Method.RandomKey](payload: Payload.RandomKey): Promise<Payload.RandomKey> {
190199
await this.check();
191200

192-
const { count, duplicates } = payload;
193-
const unique = !duplicates; // Duplicates is too hard for my head to work around
201+
const { count, unique } = payload;
194202
const keys = await this.db.getKeys();
195203

196204
if (unique && keys.length < count) {
@@ -234,8 +242,8 @@ export class IndexedDBProvider<StoredValue = unknown> extends JoshProvider<Store
234242
}
235243

236244
public override async init(context: JoshProvider.Context): Promise<JoshProvider.Context> {
245+
await this.db.init(context);
237246
context = await super.init(context);
238-
await this.db.init();
239247

240248
return context;
241249
}
@@ -516,7 +524,7 @@ export class IndexedDBProvider<StoredValue = unknown> extends JoshProvider<Store
516524
}
517525

518526
protected fetchVersion() {
519-
return this.version;
527+
return this.getMetadata('version');
520528
}
521529

522530
private async check(key: string | null = null, type: string[] | null = null, path: string[] = []) {

packages/indexeddb/src/lib/helpers.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Payload } from '@joshdb/provider';
1+
import { resolveVersion, type Payload } from '@joshdb/provider';
22

33
const handleSubCallFail = (res: Payload, payload: Payload) => {
44
if (res.errors.length) {
@@ -16,4 +16,6 @@ const isPrimitive = (val: any) => {
1616
return (typeof val !== 'object' && typeof val !== 'function') || val === null;
1717
};
1818

19-
export { handleSubCallFail, isPrimitive };
19+
const version = resolveVersion('[VI]{version}[/VI]');
20+
21+
export { handleSubCallFail, isPrimitive, version };

packages/indexeddb/tests/lib/DbHandler.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('DbHandler', () => {
1616
const handler = new DbHandler();
1717

1818
beforeAll(async () => {
19-
await handler.init();
19+
await handler.init({ name: 'test' });
2020
});
2121

2222
beforeEach(async () => {
@@ -80,4 +80,37 @@ describe('DbHandler', () => {
8080
expect(await handler.count()).toEqual(0);
8181
});
8282
});
83+
84+
describe('Can manipulate metadata.', () => {
85+
const handler = new DbHandler();
86+
87+
beforeAll(async () => {
88+
await handler.init({ name: 'meta-test' });
89+
});
90+
91+
beforeEach(async () => {
92+
await handler.clear();
93+
});
94+
95+
test('Can set and subsequently get metadata', async () => {
96+
await handler.setMetadata('string', 'hello world');
97+
await handler.setMetadata('num', 420);
98+
await handler.setMetadata('obj', { hello: 'world' });
99+
await handler.setMetadata('array', [1, 2, 3]);
100+
expect(await handler.getMetadata('string')).toEqual('hello world');
101+
expect(await handler.getMetadata('num')).toEqual(420);
102+
expect(await handler.getMetadata('obj')).toEqual({ hello: 'world' });
103+
expect(await handler.getMetadata('array')).toEqual([1, 2, 3]);
104+
});
105+
106+
test('Can clear metadata', async () => {
107+
await handler.setMetadata('string', 'hello world');
108+
await handler.setMetadata('string2', 'hello world');
109+
await handler.setMetadata('string3', 'hello world');
110+
await handler.clearMetadata();
111+
expect(await handler.getMetadata('string')).toBeUndefined();
112+
expect(await handler.getMetadata('string2')).toBeUndefined();
113+
expect(await handler.getMetadata('string3')).toBeUndefined();
114+
});
115+
});
83116
});

0 commit comments

Comments
 (0)