Skip to content

Commit

Permalink
feat: metadata, version and random changes
Browse files Browse the repository at this point in the history
  • Loading branch information
WilsontheWolf committed Jul 1, 2023
1 parent 5646460 commit 36f4b89
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 14 deletions.
64 changes: 61 additions & 3 deletions packages/indexeddb/src/lib/DbHandler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import type { JoshProvider, Semver } from '@joshdb/provider';
import { version } from './helpers';

export default class DbHandler<StoredValue = unknown> {
private idb: IDBFactory;
private db!: IDBDatabase;
Expand All @@ -10,22 +13,34 @@ export default class DbHandler<StoredValue = unknown> {
this.idb = globalThis.indexedDB;
}

public init() {
const request = this.idb.open('josh');
public init(context: JoshProvider.Context) {
const { name } = context;
const request = this.idb.open(`joshdb-${name}`, 1);

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

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

if (!db.objectStoreNames.contains('meta')) {
db.createObjectStore('meta', { keyPath: 'key' });
}

if (!db.objectStoreNames.contains('store')) {
db.createObjectStore('store', { keyPath: 'key' });
}
};

request.onsuccess = () => {
request.onsuccess = async () => {
this.db = request.result;

const storedVersion = (await this.getMetadata('version')) as Semver | undefined;

if (!storedVersion) {
await this.setMetadata('version', version);
}

resolve();
};
});
Expand Down Expand Up @@ -101,6 +116,42 @@ export default class DbHandler<StoredValue = unknown> {
return (await this.get(key)) !== undefined;
}

public async getMetadata(key: string): Promise<unknown | undefined> {
const all = this.openMetadata();
const request = all.get(key);
const result = (await this.handleEvents(request)) as {
value: unknown | undefined; // Its shit like this why I don't like TS
};

return result?.value;
}

public async setMetadata(key: string, value: unknown) {
const all = this.openMetadata();
const doc = {
key,
value
};

const request = all.put(doc);

await this.handleEvents(request);
}

public async deleteMetadata(key: string) {
const all = this.openMetadata();
const request = all.delete(key);

return this.handleEvents(request);
}

public async clearMetadata() {
const all = this.openMetadata();
const request = all.clear();

return this.handleEvents(request);
}

private handleEvents(request: IDBRequest) {
return new Promise((res, rej) => {
request.onsuccess = () => {
Expand All @@ -119,4 +170,11 @@ export default class DbHandler<StoredValue = unknown> {

return all;
}

private openMetadata() {
const transaction = this.db.transaction('meta', 'readwrite');
const all = transaction.objectStore('meta');

return all;
}
}
24 changes: 16 additions & 8 deletions packages/indexeddb/src/lib/IndexedDBProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,33 @@ import {
MathOperator,
Method,
Payload,
resolveVersion,
type Semver
} from '@joshdb/provider';
import { deleteProperty, getProperty, hasProperty, PROPERTY_NOT_FOUND, setProperty } from 'property-helpers';
import DbHandler from './DbHandler';
import { handleSubCallFail, isPrimitive } from './helpers';
import { handleSubCallFail, isPrimitive, version } from './helpers';

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

private db: DbHandler;

public constructor(options: IndexedDBProvider.Options) {
super(options);
this.db = new DbHandler<StoredValue>();
}

public get version(): Semver {
return resolveVersion('[VI]{version}[/VI]');
public deleteMetadata(key: string): void {
return this.db.deleteMetadata(key);
}

public getMetadata(key: string): unknown {
return this.db.getMetadata(key);
}

public setMetadata(key: string, value: unknown): void {
return this.db.setMetadata(key, value);
}

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

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

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

public override async init(context: JoshProvider.Context): Promise<JoshProvider.Context> {
await this.db.init(context);
context = await super.init(context);
await this.db.init();

return context;
}
Expand Down Expand Up @@ -516,7 +524,7 @@ export class IndexedDBProvider<StoredValue = unknown> extends JoshProvider<Store
}

protected fetchVersion() {
return this.version;
return this.getMetadata('version');
}

private async check(key: string | null = null, type: string[] | null = null, path: string[] = []) {
Expand Down
6 changes: 4 additions & 2 deletions packages/indexeddb/src/lib/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Payload } from '@joshdb/provider';
import { resolveVersion, type Payload } from '@joshdb/provider';

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

export { handleSubCallFail, isPrimitive };
const version = resolveVersion('[VI]{version}[/VI]');

export { handleSubCallFail, isPrimitive, version };
35 changes: 34 additions & 1 deletion packages/indexeddb/tests/lib/DbHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('DbHandler', () => {
const handler = new DbHandler();

beforeAll(async () => {
await handler.init();
await handler.init({ name: 'test' });
});

beforeEach(async () => {
Expand Down Expand Up @@ -80,4 +80,37 @@ describe('DbHandler', () => {
expect(await handler.count()).toEqual(0);
});
});

describe('Can manipulate metadata.', () => {
const handler = new DbHandler();

beforeAll(async () => {
await handler.init({ name: 'meta-test' });
});

beforeEach(async () => {
await handler.clear();
});

test('Can set and subsequently get metadata', async () => {
await handler.setMetadata('string', 'hello world');
await handler.setMetadata('num', 420);
await handler.setMetadata('obj', { hello: 'world' });
await handler.setMetadata('array', [1, 2, 3]);
expect(await handler.getMetadata('string')).toEqual('hello world');
expect(await handler.getMetadata('num')).toEqual(420);
expect(await handler.getMetadata('obj')).toEqual({ hello: 'world' });
expect(await handler.getMetadata('array')).toEqual([1, 2, 3]);
});

test('Can clear metadata', async () => {
await handler.setMetadata('string', 'hello world');
await handler.setMetadata('string2', 'hello world');
await handler.setMetadata('string3', 'hello world');
await handler.clearMetadata();
expect(await handler.getMetadata('string')).toBeUndefined();
expect(await handler.getMetadata('string2')).toBeUndefined();
expect(await handler.getMetadata('string3')).toBeUndefined();
});
});
});

0 comments on commit 36f4b89

Please sign in to comment.