@blakewatson/datastore
Version:
Save data to IndexedDB using localStorage APIs.
253 lines (251 loc) • 8.55 kB
JavaScript
var _DataStoreExports = (() => {
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// DataStore.js
var DataStore_exports = {};
__export(DataStore_exports, {
default: () => DataStore
});
var DEFAULT_DB_NAME = "Default DB";
var DEFAULT_STORE_NAME = "data";
var DataStore = class _DataStore {
/** @type {string | null} */
dbName = null;
/** @type {string | null} */
storeName = null;
/**
* Create a new database with one or more stores.
* @param {SetupDbOptions} options
*/
static setupDb(options) {
const {
name,
version = 1,
storesToCreate = DEFAULT_STORE_NAME,
onUpgradeNeeded = null
} = options;
return new Promise((resolve, reject) => {
const request = indexedDB.open(name, version);
request.onerror = (event) => {
console.error("Error opening database:", event.target.error);
reject(new Error("Error opening database"));
};
request.onsuccess = (event) => {
resolve(request.result);
};
request.onupgradeneeded = (event) => {
const db = request.result;
const existingStores = db.objectStoreNames;
const dataStoreInstances = [];
if (Array.isArray(storesToCreate)) {
storesToCreate.forEach((storeName) => {
if (existingStores.contains(storeName)) {
return;
}
db.createObjectStore(storeName);
dataStoreInstances.push(new _DataStore(name, storeName));
});
} else {
if (existingStores.contains(storesToCreate)) {
return;
}
db.createObjectStore(storesToCreate);
dataStoreInstances.push(new _DataStore(name, storesToCreate));
}
if (onUpgradeNeeded) {
onUpgradeNeeded(db, dataStoreInstances);
}
};
});
}
/**
* @param {string} dbName
* @param {string} storeName
*/
constructor(dbName = DEFAULT_DB_NAME, storeName = DEFAULT_STORE_NAME) {
this.dbName = dbName;
this.storeName = storeName;
}
getDb() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onerror = (event) => {
console.error("Error opening database:", event.target.error);
reject(new Error("Error opening database"));
};
request.onsuccess = (event) => {
resolve(request.result);
};
request.onupgradeneeded = (event) => {
console.log("Upgrade needed");
const db = request.result;
const existingStores = db.objectStoreNames;
if (!existingStores.contains(this.storeName)) {
db.createObjectStore(this.storeName);
}
};
});
}
/** @param {string | number} key */
async getItem(key) {
const db = await this.getDb();
if (typeof key === "number") {
key = key.toString();
}
if (typeof key !== "string") {
throw new Error("Key must be a string");
}
return new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readonly");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.get(key);
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
resolve(request.result);
db.close();
};
});
}
/**
* @param {string | number} key
* @param {any} value
*/
async setItem(key, value) {
const db = await this.getDb();
if (typeof key === "number") {
key = key.toString();
}
if (typeof key !== "string") {
throw new Error("Key must be a string");
}
return (
/** @type {Promise<void>} */
new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readwrite");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.put(value, key);
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
db.close();
resolve();
};
})
);
}
/** @param {string | number} key */
async removeItem(key) {
const db = await this.getDb();
if (typeof key === "number") {
key = key.toString();
}
if (typeof key !== "string") {
throw new Error("Key must be a string");
}
return (
/** @type {Promise<void>} */
new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readwrite");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.delete(key);
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
db.close();
resolve();
};
})
);
}
async keys() {
const db = await this.getDb();
return new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readonly");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.getAllKeys();
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
resolve(request.result);
db.close();
};
});
}
async count() {
const db = await this.getDb();
return new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readonly");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.count();
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
resolve(request.result);
db.close();
};
});
}
async length() {
return this.count();
}
async clear() {
const db = await this.getDb();
return (
/** @type {Promise<void>} */
new Promise((resolve, reject) => {
if (!this.storeName) {
reject(new Error("Store name not set"));
return;
}
const transaction = db.transaction(this.storeName, "readwrite");
transaction.onerror = (event) => reject(transaction.error);
const store = transaction.objectStore(this.storeName);
const request = store.clear();
request.onerror = (event) => reject(request.error);
request.onsuccess = () => {
db.close();
resolve();
};
})
);
}
};
return __toCommonJS(DataStore_exports);
})();
self.DataStore = _DataStoreExports.default;