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