import { DbConnectionInfo } from "../.." ; import { SqLiteBaseAdapter } from "../adapter-sqlite-base/sqlite-base-adapter" ; import { DbLocalContext } from "../db-local-context" ; import { SqlQueryBuilder , SqlQueryResultSet } from "../db-operations" ; interface DbOptions { name : string ; location ? : "default" ; iosDatabaseLocation ? : "default" | "Library" | "Documents" ; } /**
 * An SQLite adapter for the cordova-sqlite-storage plugin. Supports SQLite
 * databases on Android, iOS and Windows.
 *
 * This adapter supports SQL operations, transactions, and local
 * store operations exposed by a local database context (of class `DbLocalContext`).
 * The `iquery` operation is not supported.
 *
 * This adapter provides an extension method `deleteDatabase` for deleting the
 * local SQLite database file specified in the connection options.
 *
 * This adapter accepts the following connection info: `connectionString`
 * specifies the name of the database file. `connectionOptions` accepts a
 * `location` option (defaults to `default`). To specify a different location,
 * (affects iOS only) use the `iosDatabaseLocation` option with one of the
 * following choices:
 * * `default`: stored in Library/LocalDatabase subdirectory, **not** visible to
 * iTunes and **not** backed up by iCloud
 * * `Library`: stored in Library subdirectory, backed up by iCloud, **not**
 * visible to iTunes
 * * `Documents`: stored in Documents subdirectory, visible to iTunes and backed
 * up by iCloud
 *
 * Like with other Cordova plugins you must wait for the `deviceready` event
 * in your app before instantiating a local database context with this adapter.
 * Note that controllers and other service classes injected into Ionic/Angular
 * UI components are created before the `deviceready` event is fired. Thus, you
 * should never execute operations on a local database context on this adapter
 * in the constructor of such a class.
 *
 * As a prerequisite you need to install the cordova plugin as explained here:
 * [cordova-sqlite-storage](https://www.npmjs.com/package/cordova-sqlite-storage)
 */ export class SqLiteCordovaAdapter extends SqLiteBaseAdapter { private _dbOptions : DbOptions ; private _db : any ; private _transaction : any ; constructor ( connectionInfo ) { super ( connectionInfo ) ; this . _dbOptions = this . _getDbOptions ( ) ; this . _transaction = undefined ; this . registerExtension ( "deleteDatabase" ) ; } query ( sql ) { const promise = ( dbOrTx ) => new Promise < SqlQueryResultSet > ( ( resolve , reject ) => { const [ text , params ] = this . getSqlQuery ( sql ) ; dbOrTx . executeSql ( text , params , resultSet => resolve ( this . _extractRows ( resultSet ) ) , err => { reject ( err ) ; return false ; } ) ; } ) ; if ( this . _transaction !== undefined ) { return promise ( this . _transaction ) ; } return this . _getDatabase ( ) . then ( db => promise ( db ) ) ; } transaction ( action ) { return new Promise < void > ( ( resolve , reject ) => { this . _getDatabase ( ) . then ( db => { db . transaction ( tx => { const ctx = new DbLocalContext ( this . connectionInfo ) ; ( ctx . adapter as SqLiteCordovaAdapter ) . _transaction = tx ; action ( ctx ) . then ( result => { ( ctx . adapter as SqLiteCordovaAdapter ) . _transaction = undefined ; return result ; } ) . catch ( err => { ( ctx . adapter as SqLiteCordovaAdapter ) . _transaction = undefined ; return Promise . reject ( err ) ; } ) ; } , err => { reject ( err ) ; } , ( ) => { resolve ( ) ; } ) ; } ) . catch ( error => reject ( error ) ) ; } ) ; } close ( ) { return new Promise < void > ( ( resolve , reject ) => { if ( ! this . _db ) { resolve ( ) ; } else { this . _db . close ( ( ) => { this . _db = undefined ; resolve ( ) ; } , err => { reject ( err ) ; } ) ; } } ) ; } /**
     * Deletes the database specified by the connection info if it exists.
     * Returns a promise that is fullfilled if the database has been
     * deleted or didn't exist. The promise is rejected if an error occurs.
     */ deleteDatabase ( ) { return new Promise < void > ( ( resolve , reject ) => { ( window as any ) . sqlitePlugin . deleteDatabase ( this . _dbOptions , ( ) => resolve ( ) , err => reject ( err ) ) ; } ) ; } private _getDbOptions ( ) { const options = { name : this . connectionInfo . connectionString , location : "default" , } ; const connOpts = this . connectionInfo . connectionOptions ; if ( connOpts ) { if ( connOpts . iosDatabaseLocation ) { options . iosDatabaseLocation = connOpts . iosDatabaseLocation ; options . location = undefined ; } else if ( connOpts . location ) { options . location = connOpts . location ; } } return options ; } private _getDatabase ( ) { return new Promise < any > ( ( resolve , reject ) => { if ( this . _db ) { resolve ( this . _db ) ; return ; } ( window as any ) . sqlitePlugin . openDatabase ( this . _dbOptions , db => { this . _db = db ; this . query ( this . getStoreQuery ( "CREATE" ) ) . then ( ( ) => resolve ( db ) ) . catch ( error => reject ( error ) ) ; } , err => reject ( err ) ) ; } ) ; } private _extractRows ( resultSet ) { const rows = [ ] ; const rowLen = resultSet . rows . length ; for ( let i = 0 ; i < rowLen ; i ++ ) { rows . push ( resultSet . rows . item ( i ) ) ; } return { rows : rows } ; } }