import { App } from 'firebase-admin/app'; import { CreateRequest, UpdateRequest, UserImportRecord, UserRecord } from 'firebase-admin/auth'; import { AltKey, AuthKey } from '../types.js'; import { AuthInstance } from './auth-types.js'; /** * Predicate used to filter {@link AuthInstance} entries in the internal user store. */ export type AuthInstancePredicate = (ai: AuthInstance) => boolean; /** * Manages an in-memory collection of {@link AuthInstance} objects across tenants. * * @remarks * This class provides the backing store for a mock implementation of * `firebase-admin/auth` user-management APIs. It tracks default identities * (registered by key), active users, and per-tenant state, and enforces * constraints such as UID, email, and phone-number uniqueness. * * The manager is multi-tenant aware and supports both global (no tenant) * and tenant-scoped identities, closely mirroring Firebase Authentication * and Identity Platform semantics sufficiently for unit tests. * * @typeParam TKey - Application-specific key type used to register default identities. */ export declare class InternalTenantManager { readonly now: () => number; private _defaults; private _global; private _tenants; private _tenantScoped; readonly app: App; /** * Creates a new tenant manager. * * @param now - A time provider returning the current time in milliseconds * since the Unix epoch. Used for metadata fields such as `creationTime` * and `lastSignInTime`. */ constructor(now: () => number, app?: App); /** * Gets the current time according to the configured {@link now} generator, * expressed as seconds since the Unix epoch. */ epoch(): number; /** * Gets the current time according to the configured {@link now} generator, * formatted as an ISO-8601 string. */ isoNow(): string; /** * Resets all active state to match the registered default identities. * * @remarks * - Clears the global, tenant, and tenant-scoped stores. * - Re-clones each default {@link AuthInstance} into the active stores. * - Useful for restoring a known baseline between unit tests. */ reset(): void; /** * Clears all state. * * @remarks * - Clears the default, global, tenant, and tenant-scoped stores. */ clear(): void; /** * Creates a new user in the specified tenant. * * @remarks * - Generates a UID if one is not supplied in {@link CreateRequest.uid}. * - Validates UID format and uniqueness. * - Applies the supplied properties, including password if present. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param properties - User properties matching `CreateRequest` from * `firebase-admin/auth`. * @returns A promise that resolves with the created {@link UserRecord}. */ create(tenantId: string | null | undefined, properties: CreateRequest): Promise; /** * Updates an existing user in the specified tenant. * * @remarks * - Applies `UpdateRequest` semantics, including email/phone uniqueness * checks within the tenant. * - Updates password hash/salt if `password` is provided. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param uid - UID of the user to update. * @param properties - Properties to update, matching `UpdateRequest` from * `firebase-admin/auth`. * @returns A promise that resolves with the updated {@link UserRecord}, * or rejects if the user does not exist. */ update(tenantId: string | null | undefined, uid: string, properties: UpdateRequest): Promise; /** * Imports a user into the specified tenant without returning a {@link UserRecord}. * * @remarks * - Used to seed the in-memory store from {@link UserImportRecord} data. * - Applies metadata, custom claims, password hash/salt, multi-factor * enrollment, and provider data. * - Overwrites any existing user with the same UID. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param user - User data to import. */ import(tenantId: string | null | undefined, user: UserImportRecord): void; /** * Deletes a user from the specified tenant. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param uid - UID of the user to delete. * @returns `true` if the user existed and was deleted; otherwise, `false`. */ delete(tenantId: string | null | undefined, uid: string): boolean; /** * Registers a default identity under the specified key. * * @remarks * - Fails if the key has already been registered. * - Fails if a user with the same UID already exists in the global store. * - Validates and normalizes custom claims. * - The registered {@link AuthInstance} is treated as a template; a cloned, * mutable copy is stored as the active instance. * * @param key - Application-defined key identifying the default identity. * @param ai - Auth instance to register as the default for the given key. */ register(key: TKey, ai: AuthInstance): void; /** * Deregisters a default identity previously registered with {@link register}. * * @param key - Key identifying the default identity. * @returns `true` if the identity was found and deregistered; otherwise, `false`. */ deregister(key: TKey): boolean; /** * Attempts to retrieve an active {@link AuthInstance} by UID within * the specified tenant. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param uid - UID of the user to retrieve. * @returns The matching {@link AuthInstance}, or `undefined` if not found. */ tryGet(tenantId: string | null | undefined, uid: string): AuthInstance | undefined; /** * Searches for the first {@link AuthInstance} in the specified tenant * that matches the given predicate. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param predicate - Predicate applied to each {@link AuthInstance}. * @returns The first matching instance, or `undefined` if none match. */ find(tenantId: string | null | undefined, predicate: AuthInstancePredicate): AuthInstance | undefined; /** * Gets all active {@link AuthInstance} objects for the specified tenant. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @returns An array containing all active instances for the tenant. */ all(tenantId: string | null | undefined): AuthInstance[]; /** * Resolves the active {@link AuthInstance} associated with a registered key. * * @remarks * - Uses the UID from the default identity stored under the given key. * - Throws if the key is not registered or the active instance has been deleted. * * @param key - Registered identity key. * @returns The active {@link AuthInstance} corresponding to the registered key. * @throws {@link Error} if the key is not registered or the instance is missing. */ getByKey(key: TKey | AltKey): AuthInstance; /** * Determines whether a user with the given UID exists in the global store, * regardless of tenant. * * @param uid - UID to check. * @returns `true` if the UID exists; otherwise, `false`. */ uidExists(uid: string): boolean; /** * Determines whether an email address is already in use by another user * within the specified tenant. * * @remarks * - The check ignores the user identified by {@link uid}. * - Used to emulate `email-already-exists` errors. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param uid - UID of the user being created/updated (to be excluded). * @param email - Email address to check. * @returns `true` if a different user already has this email; otherwise, `false`. */ emailExists(tenantId: string | null | undefined, uid: string, email: string): boolean; /** * Determines whether a phone number is already in use by another user * within the specified tenant. * * @remarks * - The check ignores the user identified by {@link uid}. * - Used to emulate `phone-number-already-exists` errors. * * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param uid - UID of the user being created/updated (to be excluded). * @param phoneNumber - Phone number to check. * @returns `true` if a different user already has this phone number; otherwise, `false`. */ phoneExists(tenantId: string | null | undefined, uid: string, phoneNumber: string): boolean; /** * Retrieves or lazily creates a tenant-scoped singleton value. * * @remarks * This is a generic cache that can be used by higher-level mocks to store * arbitrary per-tenant resources (for example, statistics or auxiliary * state). The value is created with {@link factory} on first access and * reused for subsequent calls. * * @typeParam T - Type of the cached value. * @param tenantId - Target tenant identifier, or `null`/`undefined` for the * default (unscoped) tenant. * @param key - Cache key within the tenant scope. * @param factory - Factory invoked to create the value when it does not exist. * @returns The existing or newly created value. */ tenantScoped(tenantId: string | null | undefined, key: string, factory: () => T): T; /** * Gets the tenant-specific user store, creating it on first use. * * @param tenantId - Tenant identifier or `null`/`undefined` for the default tenant. * @returns A mutable map of UID to {@link AuthInstance} for the tenant. */ private getTenantStore; /** * Initializes a new {@link AuthInstance} for the given tenant and UID. * * @remarks * - Validates UID presence, format, and uniqueness. * - Initializes metadata timestamps using the configured {@link now} generator. * * @param tenantId - Tenant identifier or `null`/`undefined` for the default tenant. * @param uid - UID of the user being created. * @returns A newly constructed {@link AuthInstance}. * @throws {@link Error} if the UID is missing, invalid, or already exists. */ private initInstance; /** * Applies an `UpdateRequest`-style payload to an {@link AuthInstance}. * * @remarks * - Enforces email and phone-number uniqueness within the tenant. * - Assigns email, phone number, display name, photo URL, disabled flags * and password-related fields. * * @param ai - Target auth instance to mutate. * @param properties - User properties to assign. * @throws {@link Error} if email or phone-number conflicts are detected. */ private assignUpdateRequest; } //# sourceMappingURL=tenant-manager.d.ts.map