1import './polyfillNextTick'; 2import customOpenDatabase from '@expo/websql/custom'; 3import { NativeModulesProxy } from 'expo-modules-core'; 4import { Platform } from 'react-native'; 5const { ExponentSQLite } = NativeModulesProxy; 6function zipObject(keys, values) { 7 const result = {}; 8 for (let i = 0; i < keys.length; i++) { 9 result[keys[i]] = values[i]; 10 } 11 return result; 12} 13class SQLiteDatabase { 14 _name; 15 _closed = false; 16 constructor(name) { 17 this._name = name; 18 } 19 exec(queries, readOnly, callback) { 20 if (this._closed) { 21 throw new Error(`The SQLite database is closed`); 22 } 23 ExponentSQLite.exec(this._name, queries.map(_serializeQuery), readOnly).then((nativeResultSets) => { 24 callback(null, nativeResultSets.map(_deserializeResultSet)); 25 }, (error) => { 26 // TODO: make the native API consistently reject with an error, not a string or other type 27 callback(error instanceof Error ? error : new Error(error)); 28 }); 29 } 30 close() { 31 this._closed = true; 32 ExponentSQLite.close(this._name); 33 } 34} 35function _serializeQuery(query) { 36 return [query.sql, Platform.OS === 'android' ? query.args.map(_escapeBlob) : query.args]; 37} 38function _deserializeResultSet(nativeResult) { 39 const [errorMessage, insertId, rowsAffected, columns, rows] = nativeResult; 40 // TODO: send more structured error information from the native module so we can better construct 41 // a SQLException object 42 if (errorMessage !== null) { 43 return { error: new Error(errorMessage) }; 44 } 45 return { 46 insertId, 47 rowsAffected, 48 rows: rows.map((row) => zipObject(columns, row)), 49 }; 50} 51function _escapeBlob(data) { 52 if (typeof data === 'string') { 53 /* eslint-disable no-control-regex */ 54 return data 55 .replace(/\u0002/g, '\u0002\u0002') 56 .replace(/\u0001/g, '\u0001\u0002') 57 .replace(/\u0000/g, '\u0001\u0001'); 58 /* eslint-enable no-control-regex */ 59 } 60 else { 61 return data; 62 } 63} 64const _openExpoSQLiteDatabase = customOpenDatabase(SQLiteDatabase); 65function addExecMethod(db) { 66 db.exec = (queries, readOnly, callback) => { 67 db._db.exec(queries, readOnly, callback); 68 }; 69 return db; 70} 71// @needsAudit @docsMissing 72/** 73 * Open a database, creating it if it doesn't exist, and return a `Database` object. On disk, 74 * the database will be created under the app's [documents directory](../filesystem), i.e. 75 * `${FileSystem.documentDirectory}/SQLite/${name}`. 76 * > The `version`, `description` and `size` arguments are ignored, but are accepted by the function 77 * for compatibility with the WebSQL specification. 78 * @param name Name of the database file to open. 79 * @param version 80 * @param description 81 * @param size 82 * @param callback 83 * @return 84 */ 85export function openDatabase(name, version = '1.0', description = name, size = 1, callback) { 86 if (name === undefined) { 87 throw new TypeError(`The database name must not be undefined`); 88 } 89 const db = _openExpoSQLiteDatabase(name, version, description, size, callback); 90 const dbWithExec = addExecMethod(db); 91 return dbWithExec; 92} 93//# sourceMappingURL=SQLite.js.map