@nozbe/watermelondb
Version:
Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast
135 lines (133 loc) • 5.73 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.getDispatcherType = getDispatcherType;
exports.makeDispatcher = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _reactNative = require("react-native");
var _common = require("../../../utils/common");
var _Result = require("../../../utils/fp/Result");
/* eslint-disable global-require */
var {
WMDatabaseBridge: WMDatabaseBridge,
WMDatabaseJSIBridge: WMDatabaseJSIBridge
} = _reactNative.NativeModules;
var SqliteNativeModulesDispatcher = /*#__PURE__*/function () {
function SqliteNativeModulesDispatcher(tag, bridge, {
experimentalUnsafeNativeReuse: experimentalUnsafeNativeReuse
}) {
this._tag = tag;
this._bridge = bridge;
this._unsafeNativeReuse = experimentalUnsafeNativeReuse;
if ('production' !== process.env.NODE_ENV) {
(0, _common.invariant)(this._bridge, "NativeModules.WMDatabaseBridge is not defined! This means that you haven't properly linked WatermelonDB native module. Refer to docs for instructions about installation (and the changelog if this happened after an upgrade).");
(0, _common.invariant)('windows' !== _reactNative.Platform.OS, 'Windows is only supported via JSI. Pass { jsi: true } to SQLiteAdapter constructor.');
}
}
var _proto = SqliteNativeModulesDispatcher.prototype;
_proto.call = function (name, _args, callback) {
var _this$_bridge;
var methodName = name;
var args = _args;
if ('batch' === methodName && this._bridge.batchJSON) {
methodName = 'batchJSON';
args = [JSON.stringify(args[0])];
} else if (['initialize', 'setUpWithSchema', 'setUpWithMigrations'].includes(methodName) && 'android' === _reactNative.Platform.OS) {
// FIXME: Hacky, refactor once native reuse isn't an "unsafe experimental" option
args.push(this._unsafeNativeReuse);
}
(0, _Result.fromPromise)((_this$_bridge = this._bridge)[methodName].apply(_this$_bridge, [this._tag].concat((0, _toConsumableArray2.default)(args))), callback);
};
return SqliteNativeModulesDispatcher;
}();
var SqliteJsiDispatcher = /*#__PURE__*/function () {
// debug hook for NT use
function SqliteJsiDispatcher(dbName, {
usesExclusiveLocking: usesExclusiveLocking
}) {
this._db = global.nativeWatermelonCreateAdapter(dbName, usesExclusiveLocking);
this._unsafeErrorListener = function () {};
}
var _proto2 = SqliteJsiDispatcher.prototype;
_proto2.call = function (name, _args, callback) {
var methodName = name;
var args = _args;
if ('query' === methodName && !global.HermesInternal) {
// NOTE: compressing results of a query into a compact array makes querying 15-30% faster on JSC
// but actually 9% slower on Hermes (presumably because Hermes has faster C++ JSI and slower JS execution)
methodName = 'queryAsArray';
} else if ('batch' === methodName) {
methodName = 'batchJSON';
args = [JSON.stringify(args[0])];
} else if ('windows' === _reactNative.Platform.OS && ('provideSyncJson' === methodName || 'unsafeLoadFromSync' === methodName)) {
callback({
error: new Error("".concat(methodName, " unavailable on Windows. Please contribute."))
});
} else if ('provideSyncJson' === methodName) {
(0, _Result.fromPromise)(WMDatabaseBridge.provideSyncJson.apply(WMDatabaseBridge, (0, _toConsumableArray2.default)(args)), callback);
return;
}
try {
var method = this._db[methodName];
if (!method) {
throw new Error("Cannot run database method ".concat(methodName, " because database failed to open. Hint: Did you install JSI correctly? This happens if you forgot to configure Proguard correctly ").concat(Object.keys(this._db).join(',')));
}
var result = method.apply(void 0, (0, _toConsumableArray2.default)(args));
// On Android, errors are returned, not thrown - see DatabaseBridge.cpp
if (result instanceof Error) {
throw result;
} else {
if ('queryAsArray' === methodName) {
result = require('./decodeQueryResult').default(result);
}
callback({
value: result
});
}
} catch (error) {
this._unsafeErrorListener(error);
callback({
error: error
});
}
};
return SqliteJsiDispatcher;
}();
var makeDispatcher = exports.makeDispatcher = function (type, tag, dbName, options) {
switch (type) {
case 'jsi':
return new SqliteJsiDispatcher(dbName, options);
case 'asynchronous':
return new SqliteNativeModulesDispatcher(tag, WMDatabaseBridge, options);
default:
throw new Error('Unknown DispatcherType');
}
};
var initializeJSI = function () {
if (global.nativeWatermelonCreateAdapter) {
return true;
}
var bridge = WMDatabaseBridge;
if (bridge.initializeJSI) {
try {
bridge.initializeJSI();
return !!global.nativeWatermelonCreateAdapter;
} catch (e) {
_common.logger.error('[SQLite] Failed to initialize JSI');
_common.logger.error(e);
}
} else if (WMDatabaseJSIBridge && WMDatabaseJSIBridge.install) {
WMDatabaseJSIBridge.install();
return !!global.nativeWatermelonCreateAdapter;
}
return false;
};
function getDispatcherType(options) {
if (options.jsi) {
if (initializeJSI()) {
return 'jsi';
}
_common.logger.warn("JSI SQLiteAdapter not available\u2026 falling back to asynchronous operation. This will happen if you're using remote debugger, and may happen if you forgot to recompile native app after WatermelonDB update");
}
return 'asynchronous';
}