realm
Version:
Realm by MongoDB is an offline-first mobile database: an alternative to SQLite and key-value stores
272 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.
//
////////////////////////////////////////////////////////////////////////////
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = exports.fromBindingMetadataModeToMetaDataMode = exports.MetadataMode = void 0;
const internal_1 = require("../internal");
/**
* 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.
*/
MetadataMode["NoMetadata"] = "noMetadata";
})(MetadataMode = exports.MetadataMode || (exports.MetadataMode = {}));
/** internal */
function toBindingMetadataMode(arg) {
const bindingMetadataMode = inverseTranslationTable[arg];
(0, internal_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.NoMetadata */]: MetadataMode.NoMetadata,
};
const inverseTranslationTable = Object.fromEntries(Object.entries(translationTable).map(([key, val]) => [val, Number(key)]));
/** @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 internal_1.binding.WeakRef(newApp));
return newApp;
}
/** @internal */
static deviceInfo = internal_1.deviceInfo.create();
/** @internal */
static userAgent = `RealmJS/${App.deviceInfo.sdkVersion} (v${App.deviceInfo.platformVersion})`;
/** @internal */
static getAppByUser(userInternal) {
const app = App.appByUserId.get(userInternal.identity)?.deref();
if (!app) {
throw new Error(`Cannot determine which app is associated with user (id = ${userInternal.identity})`);
}
return app;
}
/** @internal */
static setAppByUser(userInternal, currentApp) {
App.appByUserId.set(userInternal.identity, new internal_1.binding.WeakRef(currentApp));
}
/** @internal */
internal;
listeners = new internal_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;
internal_1.assert.object(config, "config");
const { id, baseUrl, timeout, multiplexSessions = true, baseFilePath, metadata, fetch } = config;
internal_1.assert.string(id, "id");
if (timeout !== undefined) {
internal_1.assert.number(timeout, "timeout");
}
internal_1.assert.boolean(multiplexSessions, "multiplexSessions");
if (baseFilePath !== undefined) {
internal_1.assert.string(baseFilePath, "baseFilePath");
}
if (metadata !== undefined) {
internal_1.assert.object(metadata, "metadata");
if (metadata.mode === MetadataMode.Encryption) {
(0, internal_1.assert)(metadata.encryptionKey, "encryptionKey is required");
}
}
if (fetch !== undefined) {
internal_1.assert.function(fetch, "fetch");
}
internal_1.fs.ensureDirectoryForFile(internal_1.fs.joinPaths(baseFilePath || internal_1.fs.getDefaultDirectoryPath(), "mongodb-realm"));
// TODO: This used getSharedApp in the legacy SDK, but it's failing AppTests
this.internal = internal_1.binding.App.getApp(1 /* binding.AppCacheMode.Disabled */, {
appId: id,
deviceInfo: App.deviceInfo,
transport: (0, internal_1.createNetworkTransport)(fetch),
baseUrl,
defaultRequestTimeoutMs: timeout ? internal_1.binding.Int64.numToInt(timeout) : undefined,
}, {
baseFilePath: baseFilePath ? baseFilePath : internal_1.fs.getDefaultDirectoryPath(),
metadataMode: metadata ? toBindingMetadataMode(metadata.mode) : 0 /* binding.MetadataMode.NoEncryption */,
customEncryptionKey: metadata?.encryptionKey,
userAgentBindingInfo: App.userAgent,
multiplexSessions,
});
}
/**
* @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 internal_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 internal_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 ? internal_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.identity, internal_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;
const internal = __importStar(require("../internal"));
// eslint-disable-next-line @typescript-eslint/no-namespace
(function (App) {
App.Sync = internal.Sync;
})(App = exports.App || (exports.App = {}));
exports.App = App;
//# sourceMappingURL=App.js.map