@react-native-oh-tpl/realm
Version:
Realm by MongoDB is an offline-first mobile database: an alternative to SQLite and key-value stores
273 lines • 11 kB
JavaScript
;
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2022 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = exports.fromBindingMetadataModeToMetaDataMode = exports.MetadataMode = void 0;
const binding_1 = require("../binding");
const assert_1 = require("../assert");
const indirect_1 = require("../indirect");
const Listeners_1 = require("../Listeners");
const platform_1 = require("../platform");
const User_1 = require("./User");
const EmailPasswordAuth_1 = require("./EmailPasswordAuth");
const NetworkTransport_1 = require("./NetworkTransport");
/**
* Persistence modes for metadata.
*/
var MetadataMode;
(function (MetadataMode) {
/**
* Persist {@link User} objects, but do not encrypt them.
*/
MetadataMode["NoEncryption"] = "noEncryption";
/**
* Persist {@link User} objects in an encrypted store.
*/
MetadataMode["Encryption"] = "encryption";
/**
* Do not persist {@link User} objects.
* @deprecated will be removed; use `InMemory` instead.
*/
MetadataMode["NoMetadata"] = "noMetadata";
/**
* Do not persist {@link User} objects.
*/
MetadataMode["InMemory"] = "inMemory";
})(MetadataMode = exports.MetadataMode || (exports.MetadataMode = {}));
/** internal */
function toBindingMetadataMode(arg) {
const bindingMetadataMode = inverseTranslationTable[arg];
(0, assert_1.assert)(bindingMetadataMode !== undefined, `Unexpected metadata mode: ${arg}`);
return bindingMetadataMode;
}
const translationTable = {
[0 /* binding.MetadataMode.NoEncryption */]: MetadataMode.NoEncryption,
[1 /* binding.MetadataMode.Encryption */]: MetadataMode.Encryption,
[2 /* binding.MetadataMode.InMemory */]: MetadataMode.InMemory,
};
const inverseTranslationTable = {
[MetadataMode.Encryption]: 1 /* binding.MetadataMode.Encryption */,
[MetadataMode.NoEncryption]: 0 /* binding.MetadataMode.NoEncryption */,
[MetadataMode.NoMetadata]: 2 /* binding.MetadataMode.InMemory */,
[MetadataMode.InMemory]: 2 /* binding.MetadataMode.InMemory */,
};
/** @internal */
function fromBindingMetadataModeToMetaDataMode(arg) {
return translationTable[arg];
}
exports.fromBindingMetadataModeToMetaDataMode = fromBindingMetadataModeToMetaDataMode;
/**
* The class represents an Atlas App Services Application.
*
* ```js
* const app = new App({ id: "my-app-qwert" });
* ```
*/
class App {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static appById = new Map();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static appByUserId = new Map();
/**
* Get or create a singleton Realm App from an ID.
* Calling this function multiple times with the same ID will return the same instance.
* @deprecated Use {@link App.get}.
* @param id - The Realm App ID visible from the Atlas App Services UI or a configuration.
* @returns The Realm App instance.
*/
static getApp(id) {
return this.get(id);
}
/**
* Get or create a singleton Realm App from an ID.
* Calling this function multiple times with the same ID will return the same instance.
* @param id - The Realm App ID visible from the Atlas App Services UI or a configuration.
* @returns The Realm App instance.
*/
static get(id) {
const cachedApp = App.appById.get(id)?.deref();
if (cachedApp) {
return cachedApp;
}
const newApp = new App(id);
App.appById.set(id, new binding_1.binding.WeakRef(newApp));
return newApp;
}
/** @internal */
static deviceInfo = platform_1.deviceInfo.create();
/** @internal */
static userAgent = `RealmJS/${App.deviceInfo.sdkVersion} (v${App.deviceInfo.platformVersion})`;
/** @internal */
static getAppByUser(userInternal) {
const app = App.appByUserId.get(userInternal.userId)?.deref();
if (!app) {
throw new Error(`Cannot determine which app is associated with user (id = ${userInternal.userId})`);
}
return app;
}
/** @internal */
static setAppByUser(userInternal, currentApp) {
App.appByUserId.set(userInternal.userId, new binding_1.binding.WeakRef(currentApp));
}
/** @internal */
internal;
listeners = new Listeners_1.Listeners({
add: (callback) => {
return this.internal.subscribe(callback);
},
remove: (token) => {
this.internal.unsubscribe(token);
},
});
constructor(configOrId) {
const config = typeof configOrId === "string" ? { id: configOrId } : configOrId;
assert_1.assert.object(config, "config");
const { id, baseUrl, timeout, multiplexSessions = true, baseFilePath, metadata, fetch, app } = config;
assert_1.assert.string(id, "id");
if (timeout !== undefined) {
assert_1.assert.number(timeout, "timeout");
}
assert_1.assert.boolean(multiplexSessions, "multiplexSessions");
if (baseFilePath !== undefined) {
assert_1.assert.string(baseFilePath, "baseFilePath");
}
if (metadata !== undefined) {
assert_1.assert.object(metadata, "metadata");
if (metadata.mode === MetadataMode.Encryption) {
(0, assert_1.assert)(metadata.encryptionKey, "encryptionKey is required");
}
}
if (fetch !== undefined) {
assert_1.assert.function(fetch, "fetch");
}
// TODO: Delete this warning once the app field has been removed from the SDK.
if (app !== undefined) {
// eslint-disable-next-line no-console
console.warn(`The "app" field in the App.Configuration is no longer used by Atlas Device Sync. It will be removed in future SDK releases and should not be used.`);
}
platform_1.fs.ensureDirectoryForFile(platform_1.fs.joinPaths(baseFilePath || platform_1.fs.getDefaultDirectoryPath(), "mongodb-realm"));
// TODO: This used getSharedApp in the legacy SDK, but it's failing AppTests
this.internal = binding_1.binding.App.getApp(0 /* binding.AppCacheMode.Enabled */, {
appId: id,
deviceInfo: App.deviceInfo,
transport: (0, NetworkTransport_1.createNetworkTransport)(fetch),
baseUrl,
defaultRequestTimeoutMs: timeout ? binding_1.binding.Int64.numToInt(timeout) : undefined,
baseFilePath: baseFilePath ? baseFilePath : platform_1.fs.getDefaultDirectoryPath(),
metadataMode: metadata ? toBindingMetadataMode(metadata.mode) : 0 /* binding.MetadataMode.NoEncryption */,
customEncryptionKey: metadata?.encryptionKey,
syncClientConfig: {
multiplexSessions,
userAgentBindingInfo: App.userAgent,
},
});
}
/**
* @returns The app ID.
*/
get id() {
return this.internal.config.appId;
}
/**
* Log in a user.
* @param credentials - A credentials object describing the type of authentication provider and its parameters.
* @returns A promise that resolves to the logged in {@link User}.
* @throws An {@link Error} if the login failed.
*/
async logIn(credentials) {
const userInternal = await this.internal.logInWithCredentials(credentials.internal);
return User_1.User.get(userInternal, this);
}
/**
* Perform operations related to the email/password auth provider.
* @returns An instance of the email password authentication provider.
*/
get emailPasswordAuth() {
// TODO: Add memoization
const internal = this.internal.usernamePasswordProviderClient();
return new EmailPasswordAuth_1.EmailPasswordAuth(internal);
}
/**
* The last user to log in or being switched to.
* @returns A {@link User} object representing the currently logged in user. If no user is logged in, `null` is returned.
*/
get currentUser() {
const currentUser = this.internal.currentUser;
return currentUser ? User_1.User.get(currentUser, this) : null;
}
/**
* All users that have logged into the device and have not been removed.
* @returns A mapping from user ID to user.
*/
get allUsers() {
return Object.fromEntries(this.internal.allUsers.map((user) => [user.userId, User_1.User.get(user, this)]));
}
/**
* Switches the current user to the one specified in {@link user}.
* @throws an {@link Error} if the new user is logged out or removed.
* @param user - The user to switch to.
*/
switchUser(user) {
this.internal.switchUser(user.internal);
}
/**
* Logs out and removes a user from the client.
* @returns A promise that resolves once the user has been logged out and removed from the app.
*/
async removeUser(user) {
await this.internal.removeUser(user.internal);
}
/**
* Delete the user.
* NOTE: This irrecoverably deletes the user from the device as well as the server!
* @returns A promise that resolves once the user has been deleted.
*/
async deleteUser(user) {
await this.internal.deleteUser(user.internal);
}
/**
* Adds a listener that will be fired on various user events.
* This includes login, logout, switching users, linking users and refreshing custom data.
* @param callback - A callback function that will be called when the event occurs.
*/
addListener(callback) {
this.listeners.add(callback);
}
/**
* Removes an event listener previously added via {@link App.addListener}.
* @param callback - The callback to remove.
*/
removeListener(callback) {
this.listeners.remove(callback);
}
/**
* Removes all event listeners previously added via {@link App.addListener}.
*/
removeAllListeners() {
this.listeners.removeAll();
}
}
exports.App = App;
(0, indirect_1.injectIndirect)("App", App);
const Sync_1 = require("./Sync");
// eslint-disable-next-line @typescript-eslint/no-namespace
(function (App) {
App.Sync = Sync_1.Sync;
})(App = exports.App || (exports.App = {}));
exports.App = App;
//# sourceMappingURL=App.js.map