xref: /expo/packages/expo-sqlite/build/SQLite.js (revision e331da1d)
1import './polyfillNextTick';
2import customOpenDatabase from '@expo/websql/custom';
3import { NativeModulesProxy } from '@unimodules/core';
4import zipObject from 'lodash/zipObject';
5import { Platform } from 'react-native';
6const { ExponentSQLite } = NativeModulesProxy;
7class SQLiteDatabase {
8    constructor(name) {
9        this._closed = false;
10        this._name = name;
11    }
12    exec(queries, readOnly, callback) {
13        if (this._closed) {
14            throw new Error(`The SQLite database is closed`);
15        }
16        ExponentSQLite.exec(this._name, queries.map(_serializeQuery), readOnly).then(nativeResultSets => {
17            callback(null, nativeResultSets.map(_deserializeResultSet));
18        }, error => {
19            // TODO: make the native API consistently reject with an error, not a string or other type
20            callback(error instanceof Error ? error : new Error(error));
21        });
22    }
23    close() {
24        this._closed = true;
25        ExponentSQLite.close(this._name);
26    }
27}
28function _serializeQuery(query) {
29    return [query.sql, Platform.OS === 'android' ? query.args.map(_escapeBlob) : query.args];
30}
31function _deserializeResultSet(nativeResult) {
32    const [errorMessage, insertId, rowsAffected, columns, rows] = nativeResult;
33    // TODO: send more structured error information from the native module so we can better construct
34    // a SQLException object
35    if (errorMessage !== null) {
36        return { error: new Error(errorMessage) };
37    }
38    return {
39        insertId,
40        rowsAffected,
41        rows: rows.map(row => zipObject(columns, row)),
42    };
43}
44function _escapeBlob(data) {
45    if (typeof data === 'string') {
46        /* eslint-disable no-control-regex */
47        return data
48            .replace(/\u0002/g, '\u0002\u0002')
49            .replace(/\u0001/g, '\u0001\u0002')
50            .replace(/\u0000/g, '\u0001\u0001');
51        /* eslint-enable no-control-regex */
52    }
53    else {
54        return data;
55    }
56}
57const _openExpoSQLiteDatabase = customOpenDatabase(SQLiteDatabase);
58function addExecMethod(db) {
59    db.exec = (queries, readOnly, callback) => {
60        db._db.exec(queries, readOnly, callback);
61    };
62    return db;
63}
64export function openDatabase(name, version = '1.0', description = name, size = 1, callback) {
65    if (name === undefined) {
66        throw new TypeError(`The database name must not be undefined`);
67    }
68    const db = _openExpoSQLiteDatabase(name, version, description, size, callback);
69    const dbWithExec = addExecMethod(db);
70    return dbWithExec;
71}
72//# sourceMappingURL=SQLite.js.map