/**
* @param {string} [storeName]
*/
export async function openDatabase(storeName) {
return new Promise((resolve, reject) => {
const request = indexedDB.open('loopgpt_js_data')
request.onupgradeneeded = (ev) => {
// @ts-ignore
const db = ev.target ? ev.target.result : null
if (!db.objectStoreNames.contains(storeName)) {
db.createObjectStore(storeName)
}
}
request.onsuccess = (ev) => {
// @ts-ignore
const db = ev.target ? ev.target.result : null
if (db) {
if (!db.objectStoreNames.contains(storeName)) {
db.close()
const version = db.version + 1
const upgradeRequest = indexedDB.open('loopgpt_js_data', version)
upgradeRequest.onupgradeneeded = (upgradeEv) => {
// @ts-ignore
const upgradedDb = upgradeEv.target ? upgradeEv.target.result : null
if (!upgradedDb.objectStoreNames.contains(storeName)) {
upgradedDb.createObjectStore(storeName)
}
}
upgradeRequest.onsuccess = (upgradeEv) => {
// @ts-ignore
const upgradedDb = upgradeEv.target ? upgradeEv.target.result : null
resolve(upgradedDb)
}
upgradeRequest.onerror = (upgradeEv) => {
const error =
// @ts-ignore
upgradeEv.target.error ||
new Error('An error occurred while opening the database.')
reject(error)
}
} else {
resolve(db)
}
} else {
reject(new Error('Failed to open the database.'))
}
}
request.onerror = (ev) => {
// @ts-ignore
const error = ev.target ? ev.target.error : null
reject(
error || new Error('An error occurred while opening the database.')
)
}
})
}
/**
* Saves the text for later summarization using IndexedDB.
* @param {string} storeName The name of the object store.
* @param {object} context The context associated with the text.
* @param {string} text The text to be saved.
* @returns {Promise<string>} The key under which the text is saved.
*/
export async function saveTextToIndexedDB(storeName, context, text) {
// Generate a unique key for the text
const generateUniqueKey = require('../utils/generateUniqueKey.js')
const key = generateUniqueKey()
// Create a new IndexedDB database or open an existing one
const db = await openDatabase(storeName)
// Create a transaction and access the object store
const transaction = db.transaction(storeName, 'readwrite')
const objectStore = transaction.objectStore(storeName)
// Save the context and text using the generated key
const data = { context, text }
objectStore.put(data, key)
// Wait for the transaction to complete
await new Promise((resolve, reject) => {
transaction.oncomplete = resolve
transaction.onerror = reject
})
// Close the database connection
db.close()
return key
}
/**
* Retrieves the saved text from IndexedDB using the key.
* @param {string} storeName The name of the object store.
* @param {string} key The key under which the text is saved.
* @returns {Promise<{ context: object, text: string }>} The saved context and text.
*/
export async function retrieveText(storeName, key) {
const db = await openDatabase(storeName)
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly')
const objectStore = transaction.objectStore(storeName)
const request = objectStore.get(key)
request.onsuccess = (
/** @type {{ target: { result: any } }} */ event
) => {
// @ts-ignore
const data = event.target ? event.target.result : null
if (data) {
resolve(data)
} else {
reject(new Error('Text not found'))
}
}
request.onerror = (/** @type {{ target: { error: any } }} */ event) => {
// @ts-ignore
const error = event.target ? event.target.error : null
reject(
error ||
new Error(
'An error occurred while retrieving the text from the database.'
)
)
}
})
}
/**
* Retrieves the saved text from IndexedDB using the key.
* @param {string} storeName The name of the object store.
* @returns {Promise<Array<{ key: string, context: object }>>} The list of keys and corresponding context.
*/
export async function retrieveKeysAndContext(storeName) {
const db = await openDatabase(storeName)
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly')
const objectStore = transaction.objectStore(storeName)
const request = objectStore.openCursor()
/**
* @type {PromiseLike<Array<{ key: string, context: object }>> | Array<{ key: string, context: object }>}
*/
const keysAndContext = []
request.onsuccess = (
/** @type {{ target: { result: any } }} */ event
) => {
const cursor = event.target.result
if (cursor) {
const key = cursor.key
const context = cursor.value.context
keysAndContext.push({ key, context })
cursor.continue()
} else {
resolve(keysAndContext)
}
}
request.onerror = (/** @type {{ target: { error: Error } }} */ event) => {
const error =
event.target.error ||
new Error(
'An error occurred while retrieving the data from the database.'
)
reject(error)
}
})
}