Join our webinar on Wednesday, June 26, at 1pm EDTHow Chia Mitigates Risk in the Crypto Industry.Register
Socket
Socket
Sign inDemoInstall

@n1md7/indexeddb-promise

Package Overview
Dependencies
6
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.23 to 6.0.0

lib/Database.d.ts

85

lib/index.d.ts

@@ -1,84 +0,1 @@

import { Optional } from 'utility-types';
export declare type Config = {
version: number;
name: string;
tables: {
name: string;
primaryKey: {
name: string;
autoIncrement: boolean;
unique: boolean;
};
initData?: {
[key: string]: IDBValidKey | IDBKeyRange;
}[];
indexes: {
[key: string]: {
unique?: boolean;
multiEntry?: boolean;
};
};
timestamps?: boolean;
}[];
};
export declare type TimeStamps = {
createdAt: number;
updatedAt: number;
};
declare type OptionsWhereAsCallback<I> = (list: I[]) => Partial<I>[];
declare type OptionsWhereAsObject<T extends keyof any = any> = {
[key in T]: IDBValidKey | IDBKeyRange;
};
export declare type Options<I, T extends keyof any = any> = {
where?: OptionsWhereAsObject<T> | OptionsWhereAsCallback<I>;
limit?: number;
orderByDESC?: boolean;
sortBy?: keyof I | keyof I[];
};
export declare class Database<DataType extends Optional<TimeStamps>> {
protected readonly config: Config;
protected readonly databaseName: string;
protected readonly tables: string[];
protected readonly databaseVersion: number;
protected readonly connection: Promise<IDBDatabase>;
protected activeTableName: string;
protected activeTableDetails: Config['tables'][0];
constructor(config: Config);
private static onUpgradeNeeded;
/**
* @description This method is used to get the indexes of the table, verify and return it.
*/
private static verify;
setTable(table: string): this;
/**
* @description This method is used to insert data into the table.
*/
insert(data: Partial<DataType>): Promise<Partial<DataType>>;
/**
* @description This method is used to select data from the table by Primary key.
*/
selectByPk(pKey: IDBValidKey | IDBKeyRange): Promise<DataType | undefined>;
/**
* @description This method is used to select data from the table by defined Index key.
*/
selectByIndex(indexName: string, value: IDBValidKey | IDBKeyRange): Promise<DataType | undefined>;
/**
* @description This method is used to select all the data from the table.
*/
selectAll(): Promise<DataType[] | undefined>;
/**
* @description This method is used to select data from the table.
*/
select(options: Options<DataType>): Promise<DataType[] | undefined>;
/**
* @description This method is used to update data in the table by primary key.
* It combines original and updateData and the same keys will be overridden.
*/
updateByPk(pKey: IDBValidKey | IDBKeyRange, dataToUpdate: Partial<DataType>): Promise<DataType | undefined>;
/**
* @description This method is used to delete data from the table.
*/
deleteByPk(pKey: IDBValidKey | IDBKeyRange): Promise<IDBValidKey | IDBKeyRange | undefined>;
static removeDatabase(name: string): Promise<string>;
}
export {};
export { Database } from './Database';
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Database = void 0;
var array_sorter_1 = __importDefault(require("./array-sorter"));
var Database = /** @class */ (function () {
function Database(config) {
var _this = this;
var _a;
this.config = config;
this.databaseName = 'DefaultDatabase';
this.tables = ['DefaultTable'];
this.databaseVersion = 1;
this.activeTableName = 'DefaultTable';
if (Array.isArray(config)) {
throw new Error('Config has to be an Object');
}
this.tables = (_a = config.tables) === null || _a === void 0 ? void 0 : _a.map(function (table) { return table.name; });
this.databaseName = config.name;
this.databaseVersion = config.version;
this.connection = new Promise(function (resolve, reject) {
if (!window || !('indexedDB' in window) || !('open' in window.indexedDB)) {
return reject('Unsupported environment');
}
var request = window.indexedDB.open(_this.databaseName, _this.databaseVersion);
request.onerror = function () { return reject(request.error); };
request.onsuccess = function () {
var connection = request.result;
connection.onversionchange = function () {
connection.close();
console.info('connection closed...');
};
return resolve(connection);
};
request.onblocked = function () {
request.result.close();
console.error(request.error || 'Database blocked');
};
request.onupgradeneeded = function (event) { return Database.onUpgradeNeeded(request.result, config, event.oldVersion); };
});
}
Database.onUpgradeNeeded = function (db, database, oldVersion) {
var e_1, _a;
var _b, _c;
return __awaiter(this, void 0, void 0, function () {
var _d, _e, table, store, key, _i, _f, data, _g, _h, e_1_1;
return __generator(this, function (_j) {
switch (_j.label) {
case 0:
_j.trys.push([0, 8, 9, 14]);
_d = __asyncValues(database.tables);
_j.label = 1;
case 1: return [4 /*yield*/, _d.next()];
case 2:
if (!(_e = _j.sent(), !_e.done)) return [3 /*break*/, 7];
table = _e.value;
if ((oldVersion < database.version && oldVersion) || db.objectStoreNames.contains(table.name)) {
db.deleteObjectStore(table.name);
console.info("DB version changed, removing table: " + table.name + " for the fresh start");
}
store = db.createObjectStore(table.name, {
keyPath: ((_b = table.primaryKey) === null || _b === void 0 ? void 0 : _b.name) || 'id',
autoIncrement: ((_c = table.primaryKey) === null || _c === void 0 ? void 0 : _c.autoIncrement) || true,
});
for (key in table.indexes) {
if (key in table.indexes) {
store.createIndex(key, key, {
unique: !!table.indexes[key].unique,
multiEntry: !!table.indexes[key].multiEntry,
});
}
}
_i = 0, _f = (table.initData || []).map(function (item) { return (__assign(__assign({}, item), (table.timestamps && {
createdAt: Date.now(),
updatedAt: Date.now(),
}))); });
_j.label = 3;
case 3:
if (!(_i < _f.length)) return [3 /*break*/, 6];
data = _f[_i];
_h = (_g = store).add;
return [4 /*yield*/, Database.verify(data, database)];
case 4:
_h.apply(_g, [_j.sent()]);
_j.label = 5;
case 5:
_i++;
return [3 /*break*/, 3];
case 6: return [3 /*break*/, 1];
case 7: return [3 /*break*/, 14];
case 8:
e_1_1 = _j.sent();
e_1 = { error: e_1_1 };
return [3 /*break*/, 14];
case 9:
_j.trys.push([9, , 12, 13]);
if (!(_e && !_e.done && (_a = _d.return))) return [3 /*break*/, 11];
return [4 /*yield*/, _a.call(_d)];
case 10:
_j.sent();
_j.label = 11;
case 11: return [3 /*break*/, 13];
case 12:
if (e_1) throw e_1.error;
return [7 /*endfinally*/];
case 13: return [7 /*endfinally*/];
case 14: return [2 /*return*/];
}
});
});
};
/**
* @description This method is used to get the indexes of the table, verify and return it.
*/
Database.verify = function (data, config) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
var keys = Object.keys(data);
config.tables.forEach(function (table) {
var _a, _b;
if (((_a = table.primaryKey) === null || _a === void 0 ? void 0 : _a.autoIncrement) === false) {
if (!keys.includes((_b = table.primaryKey) === null || _b === void 0 ? void 0 : _b.name)) {
return reject('Either include primary key as well or set {autoincrement: true}.');
}
}
});
return resolve(data);
})];
});
});
};
Database.prototype.setTable = function (table) {
var _this = this;
if (!this.tables.includes(table)) {
throw new Error("Table " + table + " does not exist");
}
this.activeTableName = table;
this.activeTableDetails = this.config.tables.find(function (_a) {
var name = _a.name;
return name === _this.activeTableName;
});
return this;
};
/**
* @description This method is used to insert data into the table.
*/
Database.prototype.insert = function (data) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var verifiedInsertData_1, _a, e_2;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_a = [{}];
return [4 /*yield*/, Database.verify(data, this.config)];
case 1:
verifiedInsertData_1 = __assign.apply(void 0, [__assign.apply(void 0, _a.concat([(_b.sent())])), (this.activeTableDetails.timestamps && {
createdAt: Date.now(),
updatedAt: Date.now(),
})]);
this.connection.then(function (db) {
var request = db
.transaction(_this.tables, 'readwrite')
.objectStore(_this.activeTableName)
.add(verifiedInsertData_1);
request.onsuccess = function () { return resolve(data); };
request.onerror = function () { return reject(request.error || 'Unable to add data. Check the unique values'); };
});
return [3 /*break*/, 3];
case 2:
e_2 = _b.sent();
return [2 /*return*/, reject(e_2)];
case 3: return [2 /*return*/];
}
});
}); })];
});
});
};
/**
* @description This method is used to select data from the table by Primary key.
*/
Database.prototype.selectByPk = function (pKey) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.connection.then(function (db) {
var transaction = db.transaction(_this.tables);
var objectStore = transaction.objectStore(_this.activeTableName);
var request = objectStore.get(pKey);
request.onerror = function () { return reject(request.error || 'Unable to retrieve data from the model'); };
request.onsuccess = function () { return resolve(request.result); };
});
})];
});
});
};
/**
* @description This method is used to select data from the table by defined Index key.
*/
Database.prototype.selectByIndex = function (indexName, value) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.connection.then(function (db) {
var transaction = db.transaction(_this.tables);
var objectStore = transaction.objectStore(_this.activeTableName);
var request = objectStore.index(indexName).get(value);
request.onerror = function () { return reject(request.error || "Unable to retrieve data from the model by " + indexName); };
request.onsuccess = function () { return resolve(request.result); };
});
})];
});
});
};
/**
* @description This method is used to select all the data from the table.
*/
Database.prototype.selectAll = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.connection.then(function (db) {
var objectStore = db.transaction(_this.tables).objectStore(_this.activeTableName);
var request = objectStore.getAll();
request.onsuccess = function () { return resolve(request.result); };
request.onerror = function () { return reject(request.error || "Can't get data from database"); };
});
})];
});
});
};
/**
* @description This method is used to select data from the table.
*/
Database.prototype.select = function (options) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.selectAll().then(function (data) {
var result = [];
if (Reflect.has(options, 'where') && options.where) {
if (!data)
return [];
if (typeof options.where === 'function') {
result = options.where(data);
}
else {
var whereKeys_1 = Object.keys(options.where);
result = data.filter(function (item) {
var dataKeys = Object.keys(item);
for (var _i = 0, whereKeys_2 = whereKeys_1; _i < whereKeys_2.length; _i++) {
var key = whereKeys_2[_i];
if (dataKeys.includes(key) && item[key] === options.where[key]) {
return true;
}
}
return false;
});
}
}
if (Reflect.has(options, 'sortBy') && options.sortBy) {
// sort data
result = new array_sorter_1.default(result).sortBy({
desc: Reflect.has(options, 'orderByDESC') && options.orderByDESC,
keys: [options.sortBy],
});
}
if (Reflect.has(options, 'limit') && options.limit) {
// slice data
result = result.slice(0, +options.limit);
}
return result;
})];
});
});
};
/**
* @description This method is used to update data in the table by primary key.
* It combines original and updateData and the same keys will be overridden.
*/
Database.prototype.updateByPk = function (pKey, dataToUpdate) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.connection.then(function (db) {
_this.selectByPk(pKey).then(function (fetchedData) {
var transaction = db.transaction(_this.tables, 'readwrite');
var store = transaction.objectStore(_this.activeTableName);
var data = Object.assign(fetchedData, dataToUpdate);
if (_this.activeTableDetails.timestamps)
data.createdAt = Date.now();
var save = store.put(data);
save.onsuccess = function () { return resolve(data); };
save.onerror = function () { return reject(save.error || "Couldn't update data"); };
});
});
});
};
/**
* @description This method is used to delete data from the table.
*/
Database.prototype.deleteByPk = function (pKey) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.connection.then(function (db) {
var transaction = db.transaction(_this.tables, 'readwrite');
var request = transaction.objectStore(_this.activeTableName).delete(pKey);
request.onsuccess = function () { return resolve(pKey); };
request.onerror = function () { return reject(request.error || "Couldn't remove an item"); };
});
});
};
Database.removeDatabase = function (name) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
var request = window.indexedDB.deleteDatabase(name);
request.onblocked = function () {
console.log("Couldn't delete database due to the operation being blocked");
};
request.onsuccess = function () { return resolve('Database has been removed'); };
request.onerror = function () { return reject(request.error || "Couldn't remove database"); };
})];
});
});
};
return Database;
}());
exports.Database = Database;
var Database_1 = require("./Database");
Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return Database_1.Database; } });
//# sourceMappingURL=index.js.map
{
"name": "@n1md7/indexeddb-promise",
"version": "5.0.23",
"version": "6.0.0",
"description": "Indexed DB wrapper with promises",

@@ -81,3 +81,6 @@ "main": "./lib/index.js",

]
},
"dependencies": {
"joi": "^17.5.0"
}
}

@@ -35,2 +35,3 @@ [![npm databaseVersion](https://badge.fury.io/js/@n1md7%2Findexeddb-promise.svg)](https://badge.fury.io/js/@n1md7%2Findexeddb-promise)

- selectAll
- openCursor
- setTable

@@ -184,3 +185,4 @@ - selectByIndex

// add a new record
db.setTable('myNewTable')
const model = db.useModel('myNewTable');
model
.insert({

@@ -201,7 +203,5 @@ id: Math.random() * 10,

// Get all results from the database
db.setTable('myNewTable')
.selectAll()
.then(function (results) {
console.log(...results);
});
model.selectAll().then(function (results) {
console.log(...results);
});
</script>

@@ -245,4 +245,4 @@ </body>

const database = new Database<Users | ToDos>({
version: 2,
const database = new Database({
version: 1,
name: 'Todo-list',

@@ -282,7 +282,9 @@ tables: [

(async () => {
const user = await database.setTable('users').insert({
const users = database.useModel<Users>('users');
await users.insert({
username: 'admin',
password: 'admin',
});
await database.setTable('todos').insert({
const todos = database.useModel<ToDos>('todos');
await todos.insert({
userId: user.id,

@@ -289,0 +291,0 @@ title: 'Todo 1',

@@ -1,302 +0,1 @@

import ArraySorter from './array-sorter';
import { Optional } from 'utility-types';
export type Config = {
version: number;
name: string;
tables: {
name: string;
primaryKey: {
name: string;
autoIncrement: boolean;
unique: boolean;
};
initData?: {
[key: string]: IDBValidKey | IDBKeyRange;
}[];
indexes: {
[key: string]: {
unique?: boolean;
multiEntry?: boolean;
};
};
timestamps?: boolean;
}[];
};
export type TimeStamps = {
createdAt: number;
updatedAt: number;
};
type OptionsWhereAsCallback<I> = (list: I[]) => Partial<I>[];
type OptionsWhereAsObject<T extends keyof any = any> = {
[key in T]: IDBValidKey | IDBKeyRange;
};
export type Options<I, T extends keyof any = any> = {
where?: OptionsWhereAsObject<T> | OptionsWhereAsCallback<I>;
limit?: number;
orderByDESC?: boolean;
sortBy?: keyof I | keyof I[];
};
export class Database<DataType extends Optional<TimeStamps>> {
protected readonly databaseName: string = 'DefaultDatabase';
protected readonly tables: string[] = ['DefaultTable'];
protected readonly databaseVersion: number = 1;
protected readonly connection: Promise<IDBDatabase>;
protected activeTableName: string = 'DefaultTable';
protected activeTableDetails: Config['tables'][0];
constructor(protected readonly config: Config) {
if (Array.isArray(config)) {
throw new Error('Config has to be an Object');
}
this.tables = config.tables?.map((table) => table.name);
this.databaseName = config.name;
this.databaseVersion = config.version;
this.connection = new Promise((resolve, reject) => {
if (!window || !('indexedDB' in window) || !('open' in window.indexedDB)) {
return reject('Unsupported environment');
}
const request = window.indexedDB.open(this.databaseName, this.databaseVersion);
request.onerror = () => reject(request.error);
request.onsuccess = function () {
const connection = request.result;
connection.onversionchange = function () {
connection.close();
console.info('connection closed...');
};
return resolve(connection);
};
request.onblocked = function () {
request.result.close();
console.error(request.error || 'Database blocked');
};
request.onupgradeneeded = (event) => Database.onUpgradeNeeded(request.result, config, event.oldVersion);
});
}
private static async onUpgradeNeeded(db: IDBDatabase, database: Config, oldVersion: number) {
for await (const table of database.tables) {
if ((oldVersion < database.version && oldVersion) || db.objectStoreNames.contains(table.name)) {
db.deleteObjectStore(table.name);
console.info(`DB version changed, removing table: ${table.name} for the fresh start`);
}
const store = db.createObjectStore(table.name, {
keyPath: table.primaryKey?.name || 'id',
autoIncrement: table.primaryKey?.autoIncrement || true,
});
for (const key in table.indexes) {
if (key in table.indexes) {
store.createIndex(key, key, {
unique: !!table.indexes[key].unique,
multiEntry: !!table.indexes[key].multiEntry,
});
}
}
for (const data of (table.initData || []).map((item) => ({
...item,
...(table.timestamps && {
createdAt: Date.now(),
updatedAt: Date.now(),
}),
}))) {
store.add(await Database.verify(data, database));
}
}
}
/**
* @description This method is used to get the indexes of the table, verify and return it.
*/
private static async verify<T>(data: T, config: Config): Promise<T> {
return new Promise((resolve, reject) => {
const keys = Object.keys(data);
config.tables.forEach((table) => {
if (table.primaryKey?.autoIncrement === false) {
if (!keys.includes(table.primaryKey?.name)) {
return reject('Either include primary key as well or set {autoincrement: true}.');
}
}
});
return resolve(data);
});
}
public setTable(table: string) {
if (!this.tables.includes(table)) {
throw new Error(`Table ${table} does not exist`);
}
this.activeTableName = table;
this.activeTableDetails = this.config.tables.find(({ name }) => name === this.activeTableName);
return this;
}
/**
* @description This method is used to insert data into the table.
*/
public async insert(data: Partial<DataType>): Promise<Partial<DataType>> {
return new Promise(async (resolve, reject) => {
try {
const verifiedInsertData: Partial<DataType> = {
...(await Database.verify<Partial<DataType>>(data, this.config)),
// Adding timestamps when enabled
...(this.activeTableDetails.timestamps && {
createdAt: Date.now(),
updatedAt: Date.now(),
}),
};
this.connection.then((db) => {
const request = db
.transaction(this.tables, 'readwrite')
.objectStore(this.activeTableName)
.add(verifiedInsertData);
request.onsuccess = () => resolve(data);
request.onerror = () => reject(request.error || 'Unable to add data. Check the unique values');
});
} catch (e) {
return reject(e);
}
});
}
/**
* @description This method is used to select data from the table by Primary key.
*/
public async selectByPk(pKey: IDBValidKey | IDBKeyRange): Promise<DataType | undefined> {
return new Promise((resolve, reject) => {
this.connection.then((db) => {
const transaction = db.transaction(this.tables);
const objectStore = transaction.objectStore(this.activeTableName);
const request = objectStore.get(pKey);
request.onerror = () => reject(request.error || 'Unable to retrieve data from the model');
request.onsuccess = () => resolve(request.result);
});
});
}
/**
* @description This method is used to select data from the table by defined Index key.
*/
public async selectByIndex(indexName: string, value: IDBValidKey | IDBKeyRange): Promise<DataType | undefined> {
return new Promise((resolve, reject) => {
this.connection.then((db) => {
const transaction = db.transaction(this.tables);
const objectStore = transaction.objectStore(this.activeTableName);
const request = objectStore.index(indexName).get(value);
request.onerror = () => reject(request.error || `Unable to retrieve data from the model by ${indexName}`);
request.onsuccess = () => resolve(request.result);
});
});
}
/**
* @description This method is used to select all the data from the table.
*/
public async selectAll(): Promise<DataType[] | undefined> {
return new Promise((resolve, reject) => {
this.connection.then((db) => {
const objectStore = db.transaction(this.tables).objectStore(this.activeTableName);
const request = objectStore.getAll();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error || "Can't get data from database");
});
});
}
/**
* @description This method is used to select data from the table.
*/
public async select(options: Options<DataType>): Promise<DataType[] | undefined> {
return this.selectAll().then((data) => {
let result: DataType[] = [];
if (Reflect.has(options, 'where') && options.where) {
if (!data) return [];
if (typeof options.where === 'function') {
result = (options.where as Function)(data);
} else {
const whereKeys = Object.keys(options.where);
result = data.filter((item) => {
const dataKeys = Object.keys(item);
for (const key of whereKeys) {
if (dataKeys.includes(key) && (item as any)[key] === (options.where as OptionsWhereAsObject)[key]) {
return true;
}
}
return false;
});
}
}
if (Reflect.has(options, 'sortBy') && options.sortBy) {
// sort data
result = new ArraySorter<DataType>(result).sortBy({
desc: Reflect.has(options, 'orderByDESC') && options.orderByDESC,
keys: [options.sortBy as string],
});
}
if (Reflect.has(options, 'limit') && options.limit) {
// slice data
result = result.slice(0, +options.limit);
}
return result;
});
}
/**
* @description This method is used to update data in the table by primary key.
* It combines original and updateData and the same keys will be overridden.
*/
updateByPk(pKey: IDBValidKey | IDBKeyRange, dataToUpdate: Partial<DataType>): Promise<DataType | undefined> {
return new Promise((resolve, reject) => {
this.connection.then((db) => {
this.selectByPk(pKey).then((fetchedData) => {
const transaction = db.transaction(this.tables, 'readwrite');
const store = transaction.objectStore(this.activeTableName);
const data = Object.assign(fetchedData, dataToUpdate);
if (this.activeTableDetails.timestamps) data.createdAt = Date.now();
const save = store.put(data);
save.onsuccess = () => resolve(data);
save.onerror = () => reject(save.error || "Couldn't update data");
});
});
});
}
/**
* @description This method is used to delete data from the table.
*/
deleteByPk(pKey: IDBValidKey | IDBKeyRange): Promise<IDBValidKey | IDBKeyRange | undefined> {
return new Promise((resolve, reject) => {
this.connection.then((db) => {
const transaction = db.transaction(this.tables, 'readwrite');
const request = transaction.objectStore(this.activeTableName).delete(pKey);
request.onsuccess = () => resolve(pKey);
request.onerror = () => reject(request.error || "Couldn't remove an item");
});
});
}
static async removeDatabase(name: string): Promise<string> {
return new Promise((resolve, reject) => {
const request = window.indexedDB.deleteDatabase(name);
request.onblocked = function () {
console.log("Couldn't delete database due to the operation being blocked");
};
request.onsuccess = () => resolve('Database has been removed');
request.onerror = () => reject(request.error || "Couldn't remove database");
});
}
}
export { Database } from './Database';

@@ -12,3 +12,2 @@ import { Database } from '../src';

jest.clearAllTimers();
await Database.removeDatabase(`Test-db-0${ref.i}`);
});

@@ -23,3 +22,3 @@

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -44,9 +43,9 @@ {

});
expect(db.insert).toBeDefined();
expect(db.selectAll).toBeDefined();
expect(db.selectByPk).toBeDefined();
expect(db.select).toBeDefined();
expect(db.setTable).toBeDefined();
expect(db.deleteByPk).toBeDefined();
expect(db.updateByPk).toBeDefined();
const table = db.useModel('users');
expect(table.insert).toBeDefined();
expect(table.selectAll).toBeDefined();
expect(table.selectByPk).toBeDefined();
expect(table.select).toBeDefined();
expect(table.deleteByPk).toBeDefined();
expect(table.updateByPk).toBeDefined();
});

@@ -61,3 +60,3 @@

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -80,6 +79,6 @@ {

const data = { username: 'michael', password: 'passwd' };
db.setTable('users');
db.insert(data).then((inserted) => {
const table = db.useModel('users');
table.insert(data).then((inserted) => {
expect(inserted).toEqual(data);
db.selectAll().then((all) => {
table.selectAll().then((all) => {
expect(all).toEqual(expect.arrayContaining(initData.concat(data)));

@@ -94,3 +93,3 @@ done();

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -115,4 +114,4 @@ {

});
db.setTable('users');
db.selectByPk('admin').then((selected) => {
const model = db.useModel('users');
model.selectByPk('admin').then((selected) => {
expect(selected).toEqual({ username: 'admin', password: 'admin123' });

@@ -126,3 +125,3 @@ done();

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -147,3 +146,3 @@ {

});
const _data = await db.setTable('users').selectAll();
const _data = await db.useModel('users').selectAll();
expect(_data).not.toBeNull();

@@ -155,3 +154,3 @@ });

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -176,4 +175,4 @@ {

});
db.setTable('users');
db.selectByIndex('username', 'admin').then((data) => {
const model = db.useModel('users');
model.selectByIndex('username', 'admin').then((data) => {
expect(data).toEqual({ username: 'admin', password: 'admin123' });

@@ -186,3 +185,3 @@ });

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -207,5 +206,5 @@ {

});
db.setTable('users');
const model = db.useModel('users');
expect(
await db.select({
await model.select({
where: {

@@ -217,3 +216,3 @@ password: 'admin123',

expect(
await db.select({
await model.select({
where: {

@@ -225,3 +224,3 @@ username: 'admin',

expect(
await db.select({
await model.select({
where: {

@@ -234,3 +233,3 @@ username: 'admin',

expect(
await db.select({
await model.select({
where: (data) => data,

@@ -245,3 +244,3 @@ }),

expect(
await db.select({
await model.select({
where: (data) => data,

@@ -257,3 +256,3 @@ sortBy: 'username',

expect(
await db.select({
await model.select({
where: (data) => data,

@@ -265,3 +264,3 @@ sortBy: 'username',

expect(
await db.select({
await model.select({
where: (data) => data,

@@ -278,3 +277,3 @@ sortBy: 'username',

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -299,7 +298,8 @@ {

});
const update = await db.setTable('users').updateByPk('admin', {
const model = db.useModel('users');
const update = await model.updateByPk('admin', {
password: 'strongerPassword',
});
expect(update).toEqual({ username: 'admin', password: 'strongerPassword' });
expect(await db.selectByPk('admin')).toEqual({
expect(await model.selectByPk('admin')).toEqual({
password: 'strongerPassword',

@@ -313,3 +313,3 @@ username: 'admin',

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -334,5 +334,6 @@ {

});
const deleted = await db.setTable('users').deleteByPk('admin');
const model = db.useModel('users');
const deleted = await model.deleteByPk('admin');
expect(deleted).toEqual('admin');
expect(await db.selectByPk('admin')).toBeUndefined();
expect(await model.selectByPk('admin')).toBeUndefined();
});

@@ -343,3 +344,3 @@

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -361,2 +362,3 @@ {

},
timestamps: false,
},

@@ -366,34 +368,5 @@ ],

const db = new Database(config);
db.setTable('users');
expect(db.config).toEqual(config);
});
it('should throw Either include primary key as well or set {autoincrement: true}.', async () => {
const users = new Database({
version: 1,
databaseName: `Test-db-0${ref.i}`,
tables: [
{
name: 'users',
primaryKey: {
name: 'username',
autoIncrement: false,
unique: false,
},
initData: [
{ password: 'passwd' }, //missing username and it should throw
],
indexes: {},
},
],
});
try {
users.setTable('users');
await users.insert({ password: 'passwd' });
} catch (e) {
expect(e).toEqual('Either include primary key as well or set {autoincrement: true}.');
}
});
it('should throw Unsupported environment', () => {

@@ -406,3 +379,3 @@ jest.spyOn(window.indexedDB, 'open').mockImplementation(() => {

version: 1,
databaseName: `Test-db-0${ref.i}`,
name: `Test-db-0${ref.i}`,
tables: [

@@ -409,0 +382,0 @@ {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc