I have made an async
function in TypeScript
that responds to Events and returns an object with methods that return a promise. I would like help making it better and prettier. :)
My interface files:
config.model.ts
export interface IDBUConfigModel {
version: number;
dbName: string;
storeNames: string[];
keyPath?: string;
}
IDBUtility.model.ts
export interface IDBUtility {
add: (storeName: string, value: {}) => Promise<string | {}>;
put: (storeName: string, value: {}) => Promise<string | {}>;
update: (storeName: string, keyValue: string, value: {}) => Promise<string | {}>;
get: (storeName: string, keyValue: string) => Promise<any>;
remove: (storeName: string, keyValue: string) => Promise<{} | void>;
}
My main function:
import { IDBUConfigModel } from '../models/config.model';
import { IDBUtility } from '../models/idb-utility.model';
export async function openIDB(config: IDBUConfigModel): Promise<IDBUtility> {
if (!window.indexedDB) {
// console.log("Your browser doesn't support a stable version of IndexedDB. IndexedDB will not be available.");
return void 0;
}
return new Promise<IDBUtility>((resolve, reject) => {
const request = indexedDB.open(config.dbName, config.version);
request.onerror = (evt: ErrorEvent | any) => {
reject(request.result);
};
request.onupgradeneeded = (evt: IDBVersionChangeEvent | any): void => {
const nextDb = evt.target.result;
if(config.keyPath){
config.storeNames
.forEach((storeName: string) => {
nextDb.createObjectStore(
storeName,
{
keyPath: config.keyPath
}
);
});
} else {
config.storeNames
.forEach((storeName: string) => {
nextDb.createObjectStore(
storeName,
{
autoIncrement: true
}
);
});
}
};
request.onsuccess = (evt) => {
const db = request.result;
resolve({
async add(storeName: string, value: {}): Promise<string | {}> {
return new Promise((res, rej) => {
const request = db.transaction([storeName], 'readwrite')
.objectStore(`${storeName}`)
.add(value);
request.onsuccess = (evt) => {
res(request.result);
};
request.onerror = () => {
rej(request.result);
};
});
},
async put(storeName: string, value: {}): Promise<string | {}> {
return new Promise((res, rej) => {
const request = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.put(value);
request.onsuccess = () => {
res(request.result);
};
request.onerror = () => {
rej(request.result);
};
});
},
async update(storeName: string, key: string, value: ({} | any[])): Promise<string | {}> {
return new Promise((res, rej) => {
const transaction = db.transaction([storeName], 'readwrite');
const getRequest = transaction
.objectStore(storeName)
.get(key);
transaction.onerror = () => {
rej(request.result);
};
getRequest.onsuccess = () => {
const currentValue = getRequest.result;
const updatedValue = mergeDeep(currentValue, value);
const delRequest = transaction
.objectStore(storeName)
.delete(key);
delRequest.onsuccess = () => {
const addRequest = transaction
.objectStore(storeName)
.add(updatedValue);
addRequest.onsuccess = () => {
res(addRequest.result);
};
};
};
});
},
async remove(storeName: string, keyValue: string): Promise<any> {
return new Promise((res, rej) => {
const delRequest = db.transaction([storeName], 'readwrite')
.objectStore(storeName)
.delete(keyValue);
delRequest.onsuccess = () => {
res(delRequest.result);
};
delRequest.onerror = () => {
rej(delRequest.result);
};
});
},
async get(storeName: string, key: string): Promise<{}> {
return new Promise((res, rej) => {
const request = db.transaction([storeName])
.objectStore(storeName)
.get(key);
request.onsuccess = () => {
res(request.result);
};
request.onerror = () => {
rej(request.result);
};
});
}
});
};
});
}
function mergeDeep (target, source) {
if (typeof target == "object" && typeof source == "object") {
for (const key in source) {
if (source[key] === null && (target[key] === undefined || target[key] === null)) {
target[key] = null;
} else if (source[key] instanceof Array) {
if (!target[key]) target[key] = [];
target[key] = target[key].concat(source[key]);
} else if (typeof source[key] == "object") {
if (!target[key]) target[key] = {};
this.mergeDeep(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}