import { IndexedDBError } from './IndexedDBError' import type { CoreAccessors } from './core' import { getObjectStore } from './store' export async function openCursor(accessors: CoreAccessors, direction?: IDBCursorDirection, range?: IDBKeyRange): Promise { const {storeName} = accessors.getConfig() try { const store = await getObjectStore(accessors, 'readonly') const request = range ? store.openCursor(range, direction) : store.openCursor(direction) return await wrapCursorRequest(request, 'openCursor', storeName) } catch (error) { throw ensureIndexedDBError(error, 'openCursor', storeName) } } export async function openCursorOnIndex( accessors: CoreAccessors, indexName: string, direction?: IDBCursorDirection, range?: IDBKeyRange ): Promise { const {storeName} = accessors.getConfig() try { const store = await getObjectStore(accessors, 'readonly') const index = store.index(indexName) const request = range ? index.openCursor(range, direction) : index.openCursor(direction) return await wrapCursorRequest(request, 'openCursorOnIndex', storeName) } catch (error) { throw ensureIndexedDBError(error, 'openCursorOnIndex', storeName) } } export async function count(accessors: CoreAccessors, range?: IDBKeyRange): Promise { const {storeName} = accessors.getConfig() try { const store = await getObjectStore(accessors, 'readonly') const request = range ? store.count(range) : store.count() return await wrapNumberRequest(request, 'count', storeName) } catch (error) { throw ensureIndexedDBError(error, 'count', storeName) } } export async function countByIndex(accessors: CoreAccessors, indexName: string, range?: IDBKeyRange): Promise { const {storeName} = accessors.getConfig() try { const store = await getObjectStore(accessors, 'readonly') const index = store.index(indexName) const request = range ? index.count(range) : index.count() return await wrapNumberRequest(request, 'countByIndex', storeName) } catch (error) { throw ensureIndexedDBError(error, 'countByIndex', storeName) } } function wrapCursorRequest(requestParam: IDBRequest, operation: string, storeName: string): Promise { return new Promise((resolve, reject) => { const request = requestParam request.onsuccess = (): void => resolve(request.result as IDBCursorWithValue | null) request.onerror = (): void => reject(new IndexedDBError(`Failed to ${operation}: ${request.error}`, operation, storeName, request.error)) }) } function wrapNumberRequest(requestParam: IDBRequest, operation: string, storeName: string): Promise { return new Promise((resolve, reject) => { const request = requestParam request.onsuccess = (): void => resolve(request.result as number) request.onerror = (): void => reject(new IndexedDBError(`Failed to ${operation}: ${request.error}`, operation, storeName, request.error)) }) } function ensureIndexedDBError(error: unknown, operation: string, storeName: string): IndexedDBError { if (error instanceof IndexedDBError) { return error } return new IndexedDBError(error instanceof Error ? error.message : 'Unknown error', operation, storeName, error) }