ng-db-helper
Version:
Simple db helper for typescript like an orm with plugable connectors.
321 lines • 13.9 kB
JavaScript
import { QueryResultWrapper } from './query-result-wrapper';
import { UnsatisfiedRequirementError, QueryError } from 'ts-db-helper';
import { Observable } from 'rxjs/Observable';
/**
* @class CordovaSqliteConnector
*
* @description
* This class is a default connector for rdb module see {@link NgDbHelperModuleConfig}
* This class provides config key to add copy informations.
*
* This default connector allow query to database provided with cordova-sqlite-storage
* use {@link CordovaSqliteConnectorConfiguration} to override default migrations logics.
*
* To understand QueryConnectors or ModelMigrations see respectively {@link QueryConnectors},
* {@link ModelMigrations} and configuration default script configuration
*
* Requirements: cordova, cordova-plugin-file, cordova-sqlite-storage
*
* @example
* ```typescript
* const connectorConfig = new CordovaSqliteConnectorConfiguration();
* // configure db name on device
* connectorConfig.dbName = app.sqlite;
* // add config to connector
* const connector = CordovaSqliteConnector(connectorConfig);
* // create module config
* const config = new NgDbHelperModuleConfig();
* config.queryConnector = connector;
* config.modelMigration = connector;
* config.version = '1';
* // add config to module with forRoot method
* ```
*
* @author Olivier Margarit
* @since 0.1
*/
var CordovaSqliteConnector = (function () {
/**
* @constructor
* @throws {UnsatisfiedRequirementError} thrown if cordova is missing
* connector start logic after 'deviceready' signal firing.
*
* @param {CordovaSqliteConnectorConfiguration} config configuration of the connector,
* see {@link CordovaSqliteConnectorConfiguration}
* and connector documentation header.
*/
function CordovaSqliteConnector(config) {
var _this = this;
this.config = config;
/**
* @private
* @property {boolean} ready flag updated with connector state to indicate that connector can query
*/
this.ready = false;
this.supportRowid = true;
if (!window.cordova) {
throw (new UnsatisfiedRequirementError('You use cordova connector but cordova is not present !'));
}
document.addEventListener('deviceready', function () {
if (_this.checkRequirements()) {
_this.ready = true;
}
else {
// requirements is missing, module could not be ready
_this.ready = false;
}
// callback onReady subscribers
if (_this.onReadyObserver) {
_this.onReadyObserver.next(_this.ready);
_this.onReadyObserver.complete();
}
});
}
Object.defineProperty(CordovaSqliteConnector.prototype, "db", {
/**
* @private
* @property {SQLiteDatabase} db getter that open database on demand
*/
get: function () {
if (!this.dbValue) {
this.dbValue = window
.sqlitePlugin.openDatabase({ name: this.config.dbName, location: this.config.location });
}
return this.dbValue;
},
enumerable: true,
configurable: true
});
/**
* @private
* @method checkRequirements check if all platform requirement are satisfied
*
* @throws {UnsatisfiedRequirementError} log error if cordova-plugin-file or cordova-sqlite-storage is missing
*/
CordovaSqliteConnector.prototype.checkRequirements = function () {
var isRequirementVerified = true;
if (!window.resolveLocalFileSystemURL) {
var err = new UnsatisfiedRequirementError('CordovaSqliteConnector needs cordova-plugin-file !');
console.error(err);
isRequirementVerified = false;
}
if (!window.sqlitePlugin) {
var err = new UnsatisfiedRequirementError('CordovaSqliteConnector needs cordova-sqlite-storage !');
console.error(err);
isRequirementVerified = false;
}
return isRequirementVerified;
};
/**
* @public
* @method query connector method to fire query
*
* @param {DbQuery} dbQuery DbQuery object containing query and query params.
* see {@link DbQuery}
*
* @return {Observable<QueryResult<any>>} passing {@link QueryResult<any>} on query success
* passing {@link QueryError} on query error
*/
CordovaSqliteConnector.prototype.query = function (dbQuery) {
var _this = this;
return Observable.create(function (observer) {
var q = dbQuery.query;
if (dbQuery.type === 'SELECT' &&
dbQuery.query.toUpperCase().indexOf('LIMIT') < 0 &&
dbQuery.query.toUpperCase().indexOf('OFFSET') < 0) {
var offset = dbQuery.page * dbQuery.size;
q += ' LIMIT ' + (offset + dbQuery.size);
q += ' OFFSET ' + offset;
}
if (_this.db) {
_this.db.executeSql(q, dbQuery.params, function (results) {
observer.next(new QueryResultWrapper(results));
observer.complete();
}, function (err) { return observer.error(new QueryError(err.message, q, dbQuery.params ? dbQuery.params.join(', ') : '')); });
}
else {
observer.error(new QueryError('no database opened', q, dbQuery.params ? dbQuery.params.join(', ') : ''));
}
});
};
/**
* @public
* @method queryBatch make multiple queries in an unique transaction
*
* @param {DbQuery} dbQueries multiple queries to run in the same transaction
*
* @return {Observable<QueryResult<any>>} passing {@link QueryResult<any>} on query success
* passing {@link QueryError} on query error
*/
CordovaSqliteConnector.prototype.queryBatch = function (dbQueries) {
var _this = this;
var queries = [];
for (var _i = 0, dbQueries_1 = dbQueries; _i < dbQueries_1.length; _i++) {
var dbQuery = dbQueries_1[_i];
queries.push([dbQuery.query, dbQuery.params]);
}
return Observable.create(function (observer) {
if (_this.db) {
_this.db.sqlBatch(queries, function (results) {
observer.next(new QueryResultWrapper(results));
observer.complete();
}, function (err) { return observer.error(new QueryError(err.message, '', '')); });
}
else {
observer.error(new QueryError('no database opened', '', ''));
}
});
};
/**
* @public
* @method isReady to check if module is ready, if not, caller should
* subscribe to {@link CordovaSqliteConnector.onReady}
*
* @return {boolean} should be true if connector can query else false
*/
CordovaSqliteConnector.prototype.isReady = function () {
return this.ready;
};
/**
* @public
* @method onReady should be subscribed if connector is not ready
* if connector is ready, observable is immediatly called, else all check will
* be done after 'deviceready' signal
*
* @return {Observable<boolean>} passing true if connector is ready
* passing false if connector will never be ready
*/
CordovaSqliteConnector.prototype.onReady = function () {
var _this = this;
return Observable.create(function (observer) {
if (_this.ready) {
observer.next(_this.ready);
observer.complete();
}
else {
_this.onReadyObserver = observer;
}
});
};
/**
* @public
* @method getDbVersion called to check db version, should be called only if connector
* is ready.
*
* @return {Observable<string>} passing string version after version is checked
*/
CordovaSqliteConnector.prototype.getDbVersion = function () {
var _this = this;
return Observable.create(function (observer) {
if (_this.db) {
_this.db.executeSql('PRAGMA user_version;', [], function (results) {
if (results.rows.length) {
observer.next(results.rows.item(0));
}
else {
observer.next('');
}
observer.complete();
}, function (err) { return observer.error(err); });
}
else {
observer.next('');
observer.complete();
}
});
};
/**
* @private
* @method isDbCreated is private method to check if db is created before copy
*
* @return {Observable<boolean>} passing true if db file is present
* passing false if db file is missing
*/
CordovaSqliteConnector.prototype.isDbCreated = function () {
var _this = this;
var targetDirName = window.cordova.file.dataDirectory;
if (window.device.platform === 'Android') {
targetDirName = window.cordova.file.applicationStorageDirectory + 'databases/';
console.log('platform is android');
console.log('targetDirName: ' + targetDirName);
}
return Observable.create(function (observer) {
var onTargetDirResolved = function (targetDir) {
_this.targetDir = targetDir;
targetDir.getFile(_this.config.dbName, {}, function () {
_this.dbValue = window.sqlitePlugin
.openDatabase({ name: _this.config.dbName, location: _this.config.location });
observer.next(true);
observer.complete();
}, function () {
observer.next(false);
observer.complete();
});
};
window.resolveLocalFileSystemURL(targetDirName, onTargetDirResolved, function (err) {
if (window.device.platform === 'Android') {
window
.resolveLocalFileSystemURL(window.cordova.file.applicationStorageDirectory, function (dir) {
dir.getDirectory('databases', { create: true }, function (entry) { return onTargetDirResolved(entry); }, function (error) { return observer.error(error); });
}, function (error) { return observer.error(error); });
}
else {
observer.error(err);
}
});
});
};
/**
* @public
* @method initModel is implemented method from ModelMigration, see {@link ModelMigration} to understand usage.
* {@link CordovaSqliteConnectorConfiguration.doCopyDb} is checked:
* - if true datamodel is initialized by copy or using config
* - if false {@link CordovaSqliteConnectorConfiguration.initDataModel} is called
*
* @param {DataModel} dataModel data model generated with model annotations
*
* @return {Observable<any>} resolved on initModel finish
*/
CordovaSqliteConnector.prototype.initModel = function (dataModel) {
var _this = this;
if (this.config.doCopyDb) {
var sourceFileName_1 = window.cordova.file.applicationDirectory +
this.config.sourceDbPath + this.config.sourceDbName;
return Observable.create(function (observer) {
_this.isDbCreated().subscribe(function (isCreated) {
if (isCreated) {
observer.next(null);
observer.complete();
}
else {
window.resolveLocalFileSystemURL(sourceFileName_1, function (sourceFile) {
sourceFile.copyTo(_this.targetDir, _this.config.dbName, function () {
observer.next(null);
observer.complete();
}, function (err) { return observer.error(err); });
}, function (err) { return observer.error(err); });
}
}, function (err) { return observer.error(err); });
});
}
else {
return this.config.initDataModel(dataModel, this.db);
}
};
/**
* @public
* @method upgradeModel is implemented method from ModelMigration, see {@link ModelMigration} to understand usage.
* directly call {@link CordovaSqliteConnectorConfiguration.upgradeDataModel}
*
* @param {DataModel} dataModel data model generated with model annotations
* @param {string} oldVersion old model version
*
* @return {Observable<any>} resolved on upgradeModel finish
*/
CordovaSqliteConnector.prototype.upgradeModel = function (dataModel, oldVersion) {
return this.config.upgradeDataModel(dataModel, this.db);
};
return CordovaSqliteConnector;
}());
export { CordovaSqliteConnector };
//# sourceMappingURL=cordova-sqlite-connector.js.map