nativescript-sqlite
Version:
A sqlite NativeScript module for Android and iOS
1,022 lines (905 loc) • 32.7 kB
JavaScript
/************************************************************************************
* (c) 2015-2021 Master Technology
* Licensed under the MIT license or contact me for a support, changes, enhancements,
* and/or if you require a commercial licensing
*
* Any questions please feel free to email me or put a issue up on github
* Nathan@master-technology.com http://nativescript.tools
* Version 2.7.0 - iOS
***********************************************************************************/
/* global global, require, module */
"use strict";
const fs = require('@nativescript/core/file-system');
/* jshint undef: true, camelcase: false */
/* global Promise, NSFileManager, NSBundle, NSString, interop, sqlite3_open_v2, sqlite3_close, sqlite3_prepare_v2, sqlite3_step,
sqlite3_finalize, sqlite3_bind_null, sqlite3_bind_text, sqlite3_column_type, sqlite3_column_int64,
sqlite3_column_double, sqlite3_column_text, sqlite3_column_count, sqlite3_column_name, sqlite3_bind_blob */
let _DatabasePluginInits = [];
const TRANSIENT = new interop.Pointer(-1);
/***
* Converts a string to a UTF-8 char array and wraps it in an adopted pointer
* (which is GC managed and kept alive until it's referenced by a variable).
* The reason for doing it is that iOS runtime marshals JS string arguments via
* temporary buffers which are deallocated immediately after the call returns. In
* some cases however, we need them to stay alive for subsequent native calls
* because otherwise attempts to read the freed memory may lead to unpredictable
* app crashes.
* E.g. `sqlite3_step` function happens to use the stored `char *` passed as
* `dbname` to `sqlite3_open_v2`.
* @param str
* @returns {AdoptedPointer} object
*/
function toCharPtr(str) {
const objcStr = NSString.stringWithString(str);
// UTF8 strings can be encoded in 4 byte representing each character
// We are wasting a few bytes of memory, just to make sure we have enough room to copy it...
const bufferSize = ((str.length) * 4) + 1;
const buffer = interop.alloc(bufferSize);
objcStr.getCStringMaxLengthEncoding(buffer, bufferSize, NSUTF8StringEncoding);
return buffer;
}
/***
* Creates a Cursor Tracking Statement for reading result sets
* @param statement
* @param resultType
* @param valuesType
* @constructor
*/
function CursorStatement(statement, resultType, valuesType) {
this.statement = statement;
this.resultType = resultType;
this.valuesType = valuesType;
this.built = false;
this.columns = [];
}
//noinspection JSValidateJSDoc
/***
* Database Constructor
* @param dbname - Database Name
* @param options - options
* @param callback - Callback when Done
* @returns {Promise} object
* @constructor
*/
function Database(dbname, options, callback) {
if (!(this instanceof Database)) { // jshint ignore:line
//noinspection JSValidateTypes
return new Database(dbname, options, callback);
}
this._messageHandlers = [];
this._isOpen = false;
this._resultType = Database.RESULTSASARRAY;
this._valuesType = Database.VALUESARENATIVE;
if (typeof options === 'function') {
callback = options;
options = {};
} else {
options = options || {};
}
this._options = options;
// Check to see if it has a path, or if it is a relative dbname
// DBNAME = "" - is a Temporary Database
// DBNAME = ":memory:" - is a Memory only database
if (dbname !== "" && dbname !== ":memory:") {
let path;
if (dbname.indexOf('/') === -1) {
// noinspection JSUnresolvedVariable, JSUnresolvedFunction
path = fs.knownFolders.documents().path;
dbname = path + '/' + dbname;
} else {
path = dbname.substr(0, dbname.lastIndexOf('/') + 1);
}
// Create "databases" folder if it is missing. This causes issues on Emulators if it is missing
// So we create it if it is missing
try {
// noinspection JSUnresolvedVariable
if (!fs.File.exists(path)) {
//noinspection JSUnresolvedFunction
const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
//noinspection JSUnresolvedFunction
if (!fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(path, true, null, null)) {
console.warn("SQLITE.CONSTRUCTOR - Creating DB Folder Error");
}
}
}
catch (err) {
console.warn("SQLITE.CONSTRUCTOR - Creating DB Folder Error", err);
}
}
this._dbnamePtr = toCharPtr(dbname);
const self = this;
//noinspection JSUnresolvedFunction
return new Promise(function (resolve, reject) {
let error;
try {
let flags = 0;
if (typeof options.iosFlags !== 'undefined') {
flags = options.iosFlags;
}
self._db = new interop.Reference();
if (options && options.readOnly) {
// SQLITE_OPEN_FULLMUTEX = 65536, SQLITE_OPEN_READONLY = 1 ---- 1 | 65536 = 65537
error = sqlite3_open_v2(self._dbnamePtr, self._db, 65537 | flags, null);
} else {
// SQLITE_OPEN_FULLMUTEX = 65536, SQLITE_OPEN_CREATE = 4, SQLITE_OPEN_READWRITE = 2 --- 4 | 2 | 65536 = 65542
error = sqlite3_open_v2(self._dbnamePtr, self._db, 65542 | flags, null);
}
self._db = self._db.value;
} catch (err) {
if (callback) { callback(err, null); }
reject(err);
return;
}
if (error) {
if (callback) { callback(error, null); }
reject(error);
return;
}
self._isOpen = true;
let doneCnt = _DatabasePluginInits.length, doneHandled = 0;
const done = function(err) {
if (err) {
doneHandled = doneCnt; // We don't want any more triggers after this
if (callback) { callback(err, null); }
reject(err);
return;
}
doneHandled++;
if (doneHandled === doneCnt) {
if (callback) { callback(null, self); }
resolve(self);
}
};
if (doneCnt) {
try {
for (let i = 0; i < doneCnt; i++) {
_DatabasePluginInits[i].call(self, options, done);
}
} catch (err) {
done(err);
}
} else {
if (callback) { callback(null, self); }
resolve(self);
}
});
}
/***
* Constant that this structure is a sqlite structure
* @type {boolean}
*/
Database.prototype._isSqlite = true;
/***
* This gets or sets the database version
* @param valueOrCallback to set or callback(err, version)
* @returns Promise
*/
Database.prototype.version = function(valueOrCallback) {
return new Promise((resolve, reject) => {
if (typeof valueOrCallback === 'function') {
this.get('PRAGMA user_version', function (err, data) {
const value = data && parseInt(data[0], 10);
valueOrCallback(err, value);
if (err) { reject(err); }
else resolve(value);
}, Database.RESULTSASARRAY);
} else if (!isNaN(valueOrCallback + 0)) {
this.execSQL('PRAGMA user_version=' + (valueOrCallback + 0).toString()).then(resolve, reject);
} else {
this.get('PRAGMA user_version', undefined, undefined, Database.RESULTSASARRAY).then((data) => {
resolve(data && parseInt(data[0], 10))
}).catch(reject);
}
});
};
/***
* Is the database currently open
* @returns {boolean} - true if the db is open
*/
Database.prototype.isOpen = function() {
return this._isOpen;
};
/***
* Gets/Sets whether you get Arrays or Objects for the row values
* @param value - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
* @returns {number} - Database.RESULTSASARRAY or Database.RESULTSASOBJECT
*/
Database.prototype.resultType = function(value) {
if (value === Database.RESULTSASARRAY) {
this._resultType = Database.RESULTSASARRAY;
} else if (value === Database.RESULTSASOBJECT) {
this._resultType = Database.RESULTSASOBJECT;
}
return this._resultType;
};
/***
* Gets/Sets whether you get Native or Strings for the row values
* @param value - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
* @returns {number} - Database.VALUESARENATIVE or Database.VALUESARESTRINGS
*/
Database.prototype.valueType = function(value) {
if (value === Database.VALUESARENATIVE) {
this._valuesType = Database.VALUESARENATIVE;
} else if (value === Database.VALUESARESTRINGS) {
this._valuesType = Database.VALUESARESTRINGS;
}
return this._valuesType;
};
/**
* Dummy transaction function for public version
* @param callback
* @returns {Promise<T>}
*/
Database.prototype.begin = function(callback) {
throw new Error("Transactions are a Commercial version feature.");
};
/**
* Dummy prepare function for public version
* @param sql
* @returns {*}
*/
Database.prototype.prepare = function(sql) {
throw new Error("Prepared statements are a Commercial version feature.");
};
// noinspection JSUnusedLocalSymbols
/**
* Dummy sync enable tracking function for public version
* @returns {*}
*/
Database.prototype.enableTracking = function(tables, options, callback) {
throw new Error("Table sync is a Commercial version feature.");
};
/***
* Closes this database, any queries after this will fail with an error
* @param callback
* @returns Promise
*/
Database.prototype.close = function(callback) {
const self = this;
return new Promise( function (resolve, reject) {
if (!self._isOpen) {
if (callback) {
callback('SQLITE.CLOSE - Database is already closed');
}
reject('SQLITE.CLOSE - Database is already closed');
return;
}
sqlite3_close(self._db);
self._db = null;
self._isOpen = false;
if (self._dbnamePtr != null) {
interop.free(self._dbnamePtr);
self._dbnamePtr = null;
}
if (callback) {
callback(null, null);
}
resolve();
});
};
/***
* Exec SQL
* @param sql - sql to use
* @param params - optional array of parameters
* @param callback - (err, result) - can be last_row_id for insert, and rows affected for update/delete
* @returns Promise
*/
Database.prototype.execSQL = function(sql, params, callback) {
if (typeof params === 'function') {
callback = params;
params = undefined;
}
const self = this;
return new Promise( function(resolve, reject) {
let hasCallback = true;
if (typeof callback !== 'function') {
callback = reject;
hasCallback = false;
}
if (!self._isOpen) {
callback("SQLITE.EXECSQL - Database is not open");
return;
}
// Need to see if we have to run any status queries afterwords
let flags = 0;
let test = sql.trim().substr(0, 7).toLowerCase();
if (test === 'insert ') {
flags = 1;
} else if (test === 'update ' || test === 'delete ') {
flags = 2;
}
let res;
try {
let statement = new interop.Reference();
res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
statement = statement.value;
if (res) {
callback("SQLITE.ExecSQL Failed Prepare: " + res);
return;
}
if (params !== undefined) {
if (!self._bind(statement, params)) {
sqlite3_finalize(statement);
callback("SQLITE.ExecSQL Bind Error");
return;
}
}
let result = sqlite3_step(statement);
sqlite3_finalize(statement);
if (result && result !== 100 && result !== 101) {
callback("SQLITE.ExecSQL Failed " + result);
return;
}
} catch (Err) {
callback(Err, null);
return;
}
switch (flags) {
case 0:
if (hasCallback) {
callback();
}
resolve();
break;
case 1:
self.get('select last_insert_rowid()', function (err, data) {
if (hasCallback) {
callback(err, data && data[0]);
}
if (err) {
reject(err);
} else {
resolve(data && data[0]);
}
}, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
break;
case 2:
self.get('select changes()', function (err, data) {
if (hasCallback) {
callback(err, data && data[0]);
}
if (err) {
reject(err);
} else {
resolve(data && data[0]);
}
}, Database.RESULTSASARRAY | Database.VALUESARENATIVE);
break;
default:
if (hasCallback) {
callback();
}
resolve();
}
});
};
/***
* Get the first record result set
* @param sql - sql to run
* @param params - optional
* @param callback - callback (error, results)
* @param mode - allows you to manually override the results set to be a array or object
* @returns Promise
*/
Database.prototype.get = function(sql, params, callback, mode) {
if (typeof params === 'function') {
mode = callback;
callback = params;
params = undefined;
}
const self = this;
return new Promise( function (resolve, reject) {
let hasCallback = true;
if (typeof callback !== 'function') {
callback = reject;
hasCallback = false;
}
if (!self._isOpen) {
callback("SQLITE.GET - Database is not open");
return;
}
let cursor;
try {
let statement = new interop.Reference();
let res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
if (res) {
callback("SQLITE.GET Failed Prepare: " + res);
return;
}
statement = statement.value;
let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
if (params !== undefined) {
if (!self._bind(statement, params)) {
sqlite3_finalize(statement);
callback("SQLITE.GET Bind Error");
return;
}
}
let result = sqlite3_step(statement);
if (result === 100) {
cursor = self._getResults(cursorStatement, mode);
}
sqlite3_finalize(statement);
if (result && result !== 100 && result !== 101) {
callback("SQLITE.GET - Step Error" + result);
return;
}
} catch (err) {
callback(err);
return;
}
// No Records
if (!cursor) {
if (hasCallback) {
callback(null, null);
}
resolve(null);
return;
}
if (hasCallback) {
callback(null, cursor);
}
resolve(cursor);
});
};
/***
* This returns the entire result set in a array of rows
* @param sql - Sql to run
* @param params - optional
* @param callback - (err, results)
* @param mode - set a specific return mode
* @returns Promise
*/
Database.prototype.all = function(sql, params, callback, mode) {
if (typeof params === 'function') {
callback = params;
params = undefined;
}
const self = this;
return new Promise(function(resolve, reject) {
let hasCallback = true;
if (typeof callback !== 'function') {
callback = reject;
hasCallback = false;
}
if (!self._isOpen) {
callback("SQLITE.ALL - Database is not open");
return;
}
let rows = [], res;
try {
let statement = new interop.Reference();
res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
if (res) {
callback("SQLITE.ALL - Prepare Error " + res);
return;
}
statement = statement.value;
let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
if (params !== undefined) {
if (!self._bind(statement, params)) {
sqlite3_finalize(statement);
callback("SQLITE.ALL Bind Error");
return;
}
}
let result;
do {
result = sqlite3_step(statement);
if (result === 100) {
let cursor = self._getResults(cursorStatement, mode);
if (cursor) {
rows.push(cursor);
}
} else if (result && result !== 101) {
sqlite3_finalize(statement);
callback("SQLITE.ALL - Database Error" + result);
return;
}
} while (result === 100);
sqlite3_finalize(statement);
} catch (err) {
callback(err, null);
return;
}
// No Records
if (rows.length === 0) {
if (hasCallback) {
callback(null, []);
}
resolve([]);
return;
}
if (hasCallback) {
callback(null, rows);
}
resolve(rows);
});
};
/***
* This sends each row of the result set to the "Callback" and at the end calls the complete callback upon completion
* @param sql - sql to run
* @param params - optional
* @param callback - callback (err, rowsResult)
* @param complete - callback (err, recordCount)
* @returns {Promise}
*/
Database.prototype.each = function(sql, params, callback, complete) {
if (typeof params === 'function') {
complete = callback;
callback = params;
params = undefined;
}
// Callback is required
if (typeof callback !== 'function') {
throw new Error("SQLITE.EACH - requires a callback");
}
const self = this;
return new Promise (function(resolve, reject) {
// Set the error Callback
let errorCB = complete || callback;
let count = 0, res;
try {
let statement = new interop.Reference();
res = sqlite3_prepare_v2(self._db, sql, -1, statement, null);
if (res) {
errorCB("SQLITE.EACH Error in Prepare" + res);
reject("SQLITE.EACH Error in Prepare" + res);
return;
}
statement = statement.value;
let cursorStatement = new CursorStatement(statement, self._resultType, self._valuesType);
if (params !== undefined) {
if (!self._bind(statement, params)) {
sqlite3_finalize(statement);
errorCB("SQLITE.EACH Bind Error");
reject("SQLITE.EACH Bind Error");
return;
}
}
let result;
do {
result = sqlite3_step(statement);
if (result === 100) {
let cursor = self._getResults(cursorStatement);
if (cursor) {
count++;
callback(null, cursor);
}
} else if (result && result !== 101) {
sqlite3_finalize(statement);
errorCB("SQLITE.EACH - Database Error " + result);
reject("SQLITE.EACH - Database Error " + result);
return;
}
} while (result === 100);
sqlite3_finalize(statement);
} catch (err) {
errorCB(err, null);
reject(err);
return;
}
if (complete) {
complete(null, count);
}
resolve(count);
});
};
/**
* Binds the Parameters in a Statement
* @param statement
* @param params
* @private
*/
Database.prototype._bind = function(statement, params) {
let param, res;
let autoDetect = -1;
if (Array.isArray(params)) {
const count = params.length;
for (let i=0; i<count; ++i) {
if (params[i] == null) { // jshint ignore:line
res = sqlite3_bind_null(statement, i + 1);
} else if (params[i].isKindOfClass && (params[i].isKindOfClass(NSData.class()))) {
const obj = params[i];
res = sqlite3_bind_blob(statement, i + 1, obj.bytes, obj.length, TRANSIENT);
} else {
param = params[i].toString();
if (param.length === 0) { autoDetect = 0; } else { autoDetect = -1; }
res = sqlite3_bind_text(statement, i+1, param, autoDetect, TRANSIENT );
}
if (res) {
console.error("SQLITE.Binding Error ", res);
return false;
}
}
} else {
if (params == null) { // jshint ignore:line
res = sqlite3_bind_null(statement, 1);
} else if (params.isKindOfClass && (params.isKindOfClass(NSData.class()))) {
const obj = params;
res = sqlite3_bind_blob(statement, 1, obj.bytes, obj.length, TRANSIENT);
} else {
param = params.toString();
res = sqlite3_bind_text(statement, 1, param, -1, TRANSIENT );
}
if (res) {
console.error("SQLITE.Binding Error ", res);
return false;
}
}
return true;
};
Database.prototype._getNativeResult = function(statement, column) {
const resultType = sqlite3_column_type(statement, column);
switch (resultType) {
case 1: // Int
return sqlite3_column_int64(statement, column);
case 2: // Float
return sqlite3_column_double(statement, column);
case 3: // Text
//noinspection JSUnresolvedFunction
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
case 4: // Blob
return NSData.dataWithBytesLength(sqlite3_column_blob(statement, column), sqlite3_column_bytes(statement, column));
case 5: // Null
return null;
default:
//noinspection JSUnresolvedFunction
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
}
};
Database.prototype._getStringResult = function(statement, column) {
const resultType = sqlite3_column_type(statement, column);
switch (resultType) {
case 1: // Int
//return sqlite3_column_int(statement, column).toString();
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
case 2: // Float
//return sqlite3_column_double(statement, column).toString();
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
case 3: // Text
//noinspection JSUnresolvedFunction
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
case 4: // Blob
return NSData.dataWithBytesLength(sqlite3_column_blob(statement, column), sqlite3_column_bytes(statement, column));
case 5: // Null
return null;
default:
//noinspection JSUnresolvedFunction
return NSString.stringWithUTF8String(sqlite3_column_text(statement, column)).toString();
}
};
Database.prototype._getResults = function(cursorStatement, mode) {
let resultType, valueType;
let statement = cursorStatement.statement;
let i;
if (!mode) {
resultType = cursorStatement.resultType;
valueType = cursorStatement.valuesType;
} else {
resultType = (mode & (Database.RESULTSASARRAY | Database.RESULTSASOBJECT));
valueType = (mode & (Database.VALUESARENATIVE | Database.VALUESARESTRINGS));
if (resultType <= 0) {
resultType = cursorStatement.resultType;
}
if (valueType <= 0) {
valueType = cursorStatement.valuesType;
}
}
// Track this statements information so we don't have to build it each time
if (!cursorStatement.built) {
cursorStatement.count = sqlite3_column_count(statement);
if (resultType === Database.RESULTSASOBJECT) {
for (i=0;i<cursorStatement.count;i++) {
//noinspection JSUnresolvedFunction
let cn = NSString.stringWithUTF8String(sqlite3_column_name(statement, i)).toString();
if (!cn || cursorStatement.columns.indexOf(cn) >= 0) {
cn = "column"+i;
}
cursorStatement.columns.push(cn);
}
}
cursorStatement.built=true;
}
let cnt = cursorStatement.count, data;
if (cnt === 0) { return null; }
if (resultType === Database.RESULTSASARRAY) {
data = [];
if (valueType === Database.VALUESARESTRINGS) {
for (i = 0; i < cnt; i++) {
data.push(this._getStringResult(statement, i));
}
} else {
for (i = 0; i < cnt; i++) {
data.push(this._getNativeResult(statement, i));
}
}
return data;
} else {
let colName = cursorStatement.columns;
data = {};
if (valueType === Database.VALUESARESTRINGS) {
for (i = 0; i < cnt; i++) {
data[colName[i]] = this._getStringResult(statement, i);
}
} else {
for (i = 0; i < cnt; i++) {
data[colName[i]] = this._getNativeResult(statement, i);
}
}
return data;
}
};
Database.prototype.notify = function(type, message) {
if (typeof global.postMessage === 'function') {
postMessage({id: -2, type: type, message: message});
} else {
console.error("SQLite: Not in a thread");
// Local Notify
this._notify(type, message);
}
};
Database.prototype._notify = function(type, message) {
if (type == null || typeof this._messageHandlers[type] === "undefined") {
return;
}
let handlers = this._messageHandlers[type];
try {
for (let i = 0; i < handlers; i++) {
handlers[i](message, type, this);
}
} catch (err) {
console.error("SQLite: Error in user code ", err, err.stack);
}
}
Database.prototype.addMessageHandler = function(type, callback) {
if (typeof this._messageHandlers[type] === 'undefined') {
this._messageHandlers[type] = [];
}
this._messageHandlers[type].push(callback);
};
Database.prototype.removeMessageHandler = function(type, callback) {
if (type != null && typeof this._messageHandlers[type] === "undefined") {
console.error("SQLite: This message handler " + type + " does not exist.");
return;
}
if (callback) {
// Remove all message handles that match this callback & this db...
for (let i = 0; i < this._messageHandlers[type].length; i++) {
if (this._messageHandlers[type][i].callback === callback) {
this._messageHandlers[type].splice(i, 1);
i--;
}
}
} else if (type != null) {
// Remove all message handlers for this type
this._messageHandlers[type] = [];
} else {
// Remove all message handlers for this database
this._messageHandlers = [];
}
};
/***
* Is this a SQLite object
* @param obj - possible sqlite object to check
* @returns {boolean}
*/
Database.isSqlite = function(obj) {
return obj && obj._isSqlite;
};
Database.exists = function(name) {
if (name.indexOf('/') === -1) {
name = fs.knownFolders.documents().path + '/' + name;
}
//noinspection JSUnresolvedFunction
const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
return fileManager.fileExistsAtPath(name);
};
Database.deleteDatabase = function(name) {
//noinspection JSUnresolvedFunction
const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
let path;
if (name.indexOf('/') === -1) {
path = fs.knownFolders.documents().path + '/';
} else {
path = name.substr(0, name.lastIndexOf('/') + 1);
name = name.substr(path.length);
}
if (!fileManager.fileExistsAtPath(path + name)) { return; }
// Need to remove the trailing .sqlite
let idx = name.lastIndexOf('.');
if (idx) {
name = name.substr(0,idx);
}
let files = fileManager.contentsOfDirectoryAtPathError(path, null);
if (!files) {
return;
}
for (let i = 0; i < files.count; i++) {
const fileName = files.objectAtIndex(i);
if (fileName.indexOf(name) !== -1) {
fileManager.removeItemAtPathError(path + fileName, null);
}
}
};
Database.copyDatabase = function (name, destName) {
//noinspection JSUnresolvedFunction
const fileManager = iosProperty(NSFileManager, NSFileManager.defaultManager);
let path;
if (name.indexOf('/') === -1) {
path = fs.knownFolders.documents().path + '/';
} else {
path = name.substr(0, name.lastIndexOf('/') + 1);
name = name.substr(path.length);
}
let source = fs.knownFolders.currentApp().path + '/' + name;
if (!destName) { destName = name; }
else if (destName.indexOf("/") >= 0) {
destName = destName.substring(destName.lastIndexOf('/') + 1);
}
let destination = path + destName;
fileManager.copyItemAtPathToPathError(source, destination, null);
};
function UsePlugin(loadedSrc, DBModule) {
if (loadedSrc.prototypes) {
for (let key in loadedSrc.prototypes) {
if (!loadedSrc.prototypes.hasOwnProperty(key)) { continue; }
if (DBModule.prototype[key]) {
DBModule.prototype["_"+key] = DBModule.prototype[key];
}
DBModule.prototype[key] = loadedSrc.prototypes[key];
}
}
if (loadedSrc.statics) {
for (let key in loadedSrc.statics) {
if (!loadedSrc.statics.hasOwnProperty(key)) { continue; }
DBModule[key] = loadedSrc.statics[key];
}
}
if (typeof loadedSrc.init === 'function') {
_DatabasePluginInits.push(loadedSrc.init);
}
}
function iosProperty(_this, property) {
if (typeof property === "function") {
// xCode < 8
return property.call(_this);
} else {
// xCode >= 8
return property;
}
}
// Literal Defines
Database.prototype.RESULTSASARRAY = Database.RESULTSASARRAY = 1;
Database.prototype.RESULTSASOBJECT = Database.RESULTSASOBJECT = 2;
Database.prototype.VALUESARENATIVE = Database.VALUESARENATIVE = 4;
Database.prototype.VALUESARESTRINGS = Database.VALUESARESTRINGS = 8;
/** These are optional plugins, must have a static require statement for webpack **/
TryLoadingCommercialPlugin();
TryLoadingEncryptionPlugin();
TryLoadingSyncPlugin();
function TryLoadingCommercialPlugin() {
try {
const sqlCom = require('nativescript-sqlite-commercial');
UsePlugin(sqlCom, Database);
}
catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
}
}
function TryLoadingEncryptionPlugin() {
try {
const sqlEnc = require('nativescript-sqlite-encrypted');
UsePlugin(sqlEnc, Database);
}
catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
}
}
function TryLoadingSyncPlugin() {
try {
const sqlSync = require('nativescript-sqlite-sync');
UsePlugin(sqlSync, Database);
}
catch (e) { /* Do Nothing if it doesn't exist as it is an optional plugin */
}
}
module.exports = Database;