UNPKG

stream-chat-react-native-core

Version:

The official React Native and Expo components for Stream Chat, a service for building chat applications

275 lines 11.1 kB
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.SqliteClientError = exports.SqliteClient = void 0; var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _constants = require("./constants"); var _schema = require("./schema"); var _createCreateTableQuery = require("./sqlite-utils/createCreateTableQuery"); var sqlite; try { sqlite = require('@op-engineering/op-sqlite'); } catch (e) { var isRemoteDebuggerError = e instanceof Error && e.message.includes('Failed to install'); if (isRemoteDebuggerError) { throw e; } } class SqliteClientError extends Error { constructor(code, message, options) { super(message); this.name = 'SqliteClientError'; this.code = code; this.cause = options == null ? void 0 : options.cause; } } exports.SqliteClientError = SqliteClientError; class SqliteClient { static dbVersion = 16; static dbName = _constants.DB_NAME; static dbLocation = _constants.DB_LOCATION; static TRANSIENT_ERROR = /database is locked|SQLITE_BUSY|SQLITE_LOCKED|disk i\/o|SQLITE_IOERR|unable to open|SQLITE_CANTOPEN|out of memory|readonly/i; static UNREADABLE_ERROR = /not a database|file is encrypted|malformed|disk image is malformed|SQLite (?:error )?code:?\s*(?:26|11)\b|NOTADB|SQLITE_CORRUPT/i; static getDbVersion = () => SqliteClient.dbVersion; static setDbVersion = version => SqliteClient.dbVersion = version; static recordError = e => { SqliteClient.logger == null || SqliteClient.logger('error', e.message, { tag: e.code }); throw e; }; static preflightEncryption = (0, _asyncToGenerator2.default)(function* () { try { SqliteClient.preflightedKey = yield SqliteClient.resolveEncryptionKey(); } catch (e) { if (e instanceof SqliteClientError) { SqliteClient.recordError(e); } throw e; } }); static resolveEncryptionKey = (0, _asyncToGenerator2.default)(function* () { var getEncryptionKey = SqliteClient.getEncryptionKey; if (!getEncryptionKey) { return undefined; } if (sqlite === undefined) { throw new SqliteClientError('SQLCIPHER_BUILD_MISSING', 'An offline database encryption key was provided but "@op-engineering/op-sqlite" ' + 'is not installed.'); } if (typeof sqlite.isSQLCipher !== 'function' || !sqlite.isSQLCipher()) { throw new SqliteClientError('SQLCIPHER_BUILD_MISSING', 'An offline database encryption key was provided but @op-engineering/op-sqlite was ' + 'not built with SQLCipher, so the key would be silently ignored and the offline ' + 'database written in plaintext. Add { "op-sqlite": { "sqlcipher": true } } to your ' + "application's package.json and rebuild, or stop providing a key."); } var encryptionKey; try { encryptionKey = yield getEncryptionKey(); } catch (error) { throw new SqliteClientError('ENCRYPTION_KEY_UNAVAILABLE', 'The offline database encryption key getter threw, so the database cannot be opened.', { cause: error }); } if (!encryptionKey) { throw new SqliteClientError('ENCRYPTION_KEY_UNAVAILABLE', 'The offline database encryption key getter resolved without a key, so the database ' + 'cannot be opened.'); } return encryptionKey; }); static openDB = (0, _asyncToGenerator2.default)(function* () { try { var _SqliteClient$preflig, _SqliteClient$db; if (sqlite === undefined) { throw new Error('Please install "@op-engineering/op-sqlite" package to enable offline support'); } var encryptionKey = (_SqliteClient$preflig = SqliteClient.preflightedKey) != null ? _SqliteClient$preflig : yield SqliteClient.resolveEncryptionKey(); SqliteClient.preflightedKey = undefined; SqliteClient.db = sqlite.open({ location: SqliteClient.dbLocation, name: SqliteClient.dbName, ...(encryptionKey ? { encryptionKey } : {}) }); yield (_SqliteClient$db = SqliteClient.db) == null ? void 0 : _SqliteClient$db.execute('PRAGMA foreign_keys = ON', []); } catch (e) { if (e instanceof SqliteClientError) { throw e; } SqliteClient.logger == null || SqliteClient.logger('error', `Error opening database ${SqliteClient.dbName}`, { error: e }); console.error(`Error opening database ${SqliteClient.dbName}: ${e}`); } }); static closeDB = () => { try { if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } SqliteClient.db.close(); SqliteClient.db = undefined; } catch (e) { SqliteClient.logger == null || SqliteClient.logger('error', `Error closing database ${SqliteClient.dbName}`, { error: e }); console.error(`Error closing database ${SqliteClient.dbName}: ${e}`); } }; static executeSqlBatch = function () { var _ref4 = (0, _asyncToGenerator2.default)(function* (queries) { if (!queries || !queries.length) { return; } try { if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } var finalQueries = queries.map(query => { if (query.length === 1) { query.push([]); } return query; }); yield SqliteClient.db.executeBatch(finalQueries); } catch (e) { SqliteClient.logger == null || SqliteClient.logger('error', 'SqlBatch queries failed', { error: e, queries }); throw new Error(`Queries failed: ${e}`); } }); return function (_x) { return _ref4.apply(this, arguments); }; }(); static executeSql = function () { var _ref5 = (0, _asyncToGenerator2.default)(function* (query, params) { try { if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } var _yield$SqliteClient$d = yield SqliteClient.db.execute(query, params), rows = _yield$SqliteClient$d.rows; return rows ? rows : []; } catch (e) { SqliteClient.logger == null || SqliteClient.logger('error', 'Sql single query failed', { error: e, query }); throw new Error(`Query failed: ${e}: `); } }); return function (_x2, _x3) { return _ref5.apply(this, arguments); }; }(); static dropTables = (0, _asyncToGenerator2.default)(function* () { var queries = Object.keys(_schema.tables).map(table => [`DROP TABLE IF EXISTS ${table}`, []]); SqliteClient.logger == null || SqliteClient.logger('info', 'Dropping tables', { tables: Object.keys(_schema.tables) }); yield SqliteClient.executeSqlBatch(queries); }); static deleteDatabase = () => { SqliteClient.logger == null || SqliteClient.logger('info', 'deleteDatabase', { dbLocation: SqliteClient.dbLocation, dbname: SqliteClient.dbName }); try { if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } SqliteClient.db.delete(); } catch (e) { SqliteClient.logger == null || SqliteClient.logger('error', 'Error deleting DB', { dbLocation: SqliteClient.dbLocation, dbname: SqliteClient.dbName, error: e }); throw new Error(`Error deleting DB: ${e}`); } return true; }; static isUnreadableDbError = e => { var _message; var message = String((_message = e == null ? void 0 : e.message) != null ? _message : e); if (SqliteClient.TRANSIENT_ERROR.test(message)) { return false; } return SqliteClient.UNREADABLE_ERROR.test(message); }; static initializeDatabase = (0, _asyncToGenerator2.default)(function* () { try { yield SqliteClient.openDB(); var version = yield SqliteClient.getUserPragmaVersion(); if (version !== SqliteClient.dbVersion) { SqliteClient.logger == null || SqliteClient.logger('info', 'DB version mismatch'); yield SqliteClient.dropTables(); yield SqliteClient.updateUserPragmaVersion(SqliteClient.dbVersion); } SqliteClient.logger == null || SqliteClient.logger('info', 'create tables if not exists', { tables: Object.keys(_schema.tables) }); var q = Object.keys(_schema.tables).reduce((queriesSoFar, tableName) => { queriesSoFar.push(...(0, _createCreateTableQuery.createCreateTableQuery)(tableName)); return queriesSoFar; }, []); yield SqliteClient.executeSqlBatch(q); return true; } catch (e) { if (e instanceof SqliteClientError) { SqliteClient.recordError(e); } if (SqliteClient.isUnreadableDbError(e)) { SqliteClient.recordError(new SqliteClientError('OFFLINE_DB_UNREADABLE', 'The offline database exists but could not be read. Usually the encryption ' + 'key changed, or encryption was turned on or off while a database from ' + 'the other mode was still on disk. Delete it with ' + 'SqliteClient.deleteDatabase() and re-mount to rebuild from the server - ' + 'everything in it is a cache, except queued offline actions, which are lost.', { cause: e })); } console.log('Error initializing DB', e); SqliteClient.logger == null || SqliteClient.logger('error', 'Error initializing DB', { dbLocation: SqliteClient.dbLocation, dbname: SqliteClient.dbName, error: e }); return false; } }); static updateUserPragmaVersion = function () { var _ref8 = (0, _asyncToGenerator2.default)(function* (version) { SqliteClient.logger == null || SqliteClient.logger('info', `updateUserPragmaVersion to ${version}`); if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } yield SqliteClient.db.execute(`PRAGMA user_version = ${version}`, []); }); return function (_x4) { return _ref8.apply(this, arguments); }; }(); static getUserPragmaVersion = (0, _asyncToGenerator2.default)(function* () { try { if (!SqliteClient.db) { throw new Error('DB is not open or initialized.'); } var _yield$SqliteClient$d2 = yield SqliteClient.db.execute('PRAGMA user_version', []), rows = _yield$SqliteClient$d2.rows; var result = rows ? rows : []; SqliteClient.logger == null || SqliteClient.logger('info', 'getUserPragmaVersion', { result }); return result[0].user_version; } catch (e) { console.log('Error getting user_version', e); throw new Error(`Querying for user_version failed: ${e}`); } }); static resetDB = (0, _asyncToGenerator2.default)(function* () { SqliteClient.logger == null || SqliteClient.logger('info', 'resetDB'); if (SqliteClient.db) { yield SqliteClient.dropTables(); SqliteClient.closeDB(); } yield SqliteClient.initializeDatabase(); }); } exports.SqliteClient = SqliteClient; //# sourceMappingURL=SqliteClient.js.map