import { FindFailActions } from "./find-fail-actions.js" ; import { BaseWriteActionsInterface , TransactionModes } from "./model.interface.js" ; import { IDBResultEvent } from "../connection/idb-event.interface.js" ; import { InvalidTransaction } from "../errors/invalid-transaction.js" ; import { mergeDeep as _mergeDeep } from "../utils.js" ; export abstract class BaseWriteActions extends FindFailActions implements BaseWriteActionsInterface { param data public create < T > ( data ) ; public create ( data ) { const tables = this . tableNames ( this . connector . migrationSchema . tables ) . concat ( this . table . name ) ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; const request = objectStore . add ( data ) ; return new Promise < any [ ] > ( ( resolve , reject ) => { request . addEventListener < 'success' > ( "success" , ( event ) => { data [ this . primaryId ] = ( event as IDBResultEvent ) . target . result ; resolve ( data ) ; } ) ; request . addEventListener < 'error' > ( "error" , ( error ) => reject ( error ) ) ; } ) ; } param entries public createMultiple < T > ( entries ) ; public createMultiple ( entries ) { const tables = this . tableNames ( this . connector . migrationSchema . tables ) . concat ( this . table . name ) ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; const promises = [ ] ; for ( const entry of entries ) { const promise = new Promise < any [ ] > ( ( resolve , reject ) => { const request = objectStore . add ( entry ) ; request . addEventListener < 'success' > ( "success" , ( event ) => { entry [ this . primaryId ] = ( event as IDBResultEvent ) . target . result ; resolve ( entry ) ; } ) ; request . addEventListener < 'error' > ( "error" , ( error ) => { reject ( error ) ; transaction . abort ( ) ; } ) ; } ) ; promises . push ( promise ) ; } return Promise . all ( promises ) ; } /**
     * Deletes matching entry.
     * If no builder/index for filtering is provided then throws error.
     */ public destroy ( ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; let request ; if ( this . builder . length === 0 && this . indexBuilder === null ) { throw new Error ( 'Deletion without builder is not allowed. Call truncate if you want to delete all records.' ) ; } if ( this . builder . length === 0 && this . indexBuilder !== null && this . primaryId === this . indexBuilder . index ) { request = objectStore . delete ( this . keyRange ( this . indexBuilder ) ) ; } else { request = this . request ( objectStore ) ; } return new Promise < boolean > ( ( resolve , reject ) => { const deletePromises = [ ] ; request . addEventListener < 'success' > ( "success" , async ( event ) => { if ( this . builder . length === 0 && this . indexBuilder !== null && this . primaryId === this . indexBuilder . index ) { return resolve ( true ) ; } const cursor = ( < IDBResultEvent > event ) . target . result as IDBCursorWithValue | undefined ; if ( cursor ) { if ( ! this . allowedToProcess ( cursor . value ) ) { return cursor . continue ( ) ; } deletePromises . push ( this . delete ( cursor . value [ this . primaryId ] ) ) ; return cursor . continue ( ) ; } await Promise . all ( deletePromises ) ; resolve ( true ) ; } ) ; request . addEventListener < 'error' > ( "error" , ( error ) => reject ( error ) ) ; } ) ; } param id public async delete ( id ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; const request = objectStore . delete ( id ) ; return new Promise < boolean > ( ( resolve , reject ) => { request . addEventListener < 'success' > ( "success" , ( ) => resolve ( true ) ) ; request . addEventListener < 'error' > ( "error" , ( error ) => reject ( error ) ) ; } ) ; } param indexName param value param isMulti public deleteIndex ( indexName , value , isMulti = false ) { this . resetBuilder ( ) ; if ( isMulti ) { this . whereIndex ( indexName , value ) ; } else { this . whereMultiIndexIn ( indexName , [ value ] ) ; } return this . destroy ( ) ; } /**
     * Clears entire object store
     */ public truncate ( ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; const request = objectStore . clear ( ) ; return new Promise < boolean > ( ( resolve , reject ) => { request . addEventListener < 'success' > ( "success" , ( ) => resolve ( true ) ) ; request . addEventListener < 'error' > ( "error" , ( error ) => reject ( error ) ) ; } ) ; } deprecated param id public destroyId ( id ) { return this . delete ( id ) ; } param data param mergeDeep public update ( data , mergeDeep = true ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const objectStore = transaction . objectStore ( this . table . name ) ; const request = this . request ( objectStore ) ; return new Promise < number > ( ( resolve , reject ) => { let totalUpdatedRecords = 0 ; const updatePromises = [ ] ; request . addEventListener < 'success' > ( 'success' , async ( event ) => { const cursor = ( < IDBResultEvent > event ) . target . result as IDBCursorWithValue | undefined ; if ( cursor ) { if ( ! this . allowedToProcess ( cursor . value ) ) { return cursor . continue ( ) ; } updatePromises . push ( this . save ( cursor . value [ this . primaryId ] , data , mergeDeep ) ) ; totalUpdatedRecords ++ ; cursor . continue ( ) ; } await Promise . all ( updatePromises ) ; resolve ( totalUpdatedRecords ) ; } ) ; request . addEventListener < 'error' > ( 'error' , ( event ) => reject ( event ) ) ; } ) ; } param id param data param mergeDeep throws public async save ( id , data , mergeDeep = true ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const record = await this . findOrFail < any > ( id ) ; if ( transaction . mode !== TransactionModes . Write ) { throw new InvalidTransaction ( 'Transaction not in write mode' ) ; } const objectStore = transaction . objectStore ( this . table . name ) ; const saveData = mergeDeep ? _mergeDeep ( record , data ) : data ; saveData [ this . primaryId ] = id ; const request = objectStore . put ( saveData ) ; return new Promise < boolean > ( ( resolve , reject ) => { request . addEventListener < 'success' > ( "success" , ( ) => { resolve ( true ) ; } ) ; request . addEventListener < 'error' > ( "error" , ( error ) => reject ( error ) ) ; } ) ; } param indexName param id param data param mergeDeep throws public async saveIndex ( indexName , id , data , mergeDeep = true ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; const record = await this . findIndexOrFail < any > ( indexName , id ) ; if ( transaction . mode !== TransactionModes . Write ) { throw new InvalidTransaction ( 'Transaction not in write mode' ) ; } return this . save ( record [ this . primaryId ] , data , mergeDeep ) ; } param indexName param id param data param mergeDeep throws public async saveAllIndex ( indexName , id , data , mergeDeep = true ) { const tables = [ this . table . name ] ; const transaction = this . getTransaction ( tables , TransactionModes . Write ) ; if ( transaction . mode !== TransactionModes . Write ) { throw new InvalidTransaction ( 'Transaction not in write mode' ) ; } this . resetBuilder ( ) . whereIndex ( indexName , id ) ; await this . update ( data , mergeDeep ) ; return Promise . resolve ( true ) ; } }