import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; import * as i0 from "@angular/core"; /** * Event emitted when the active organization changes. */ export interface OrgChangedEvent { /** Org the user was on before the switch. May be empty on first sign-in. */ previousOrg: string; /** Org the user just switched to. */ newOrg: string; } /** * Options for `OrgSwitchService.switchTo`. */ export interface SwitchOrgOptions { /** * If `true`, after the switch succeeds the page is fully reloaded via * `window.location.reload()`. Useful for apps with significant in-memory * state tied to the previous org that's hard to invalidate piece by piece. * * Trade-off: reload loses all in-memory state (forms, scroll position). * Default: `false` — relies on `orgChanged$` and `auth.user()` signal * propagation for components to react. */ reload?: boolean; } /** * OrgSwitchService — orchestrates active organization changes across the app. * * Built on top of `AuthService.switchOrg`, which already: * - Hits `POST /v2/auth/switch-org` and receives a new Firebase custom token. * - Re-authenticates Firebase Auth with the new token (RBAC claims update). * - Broadcasts `ORG_SWITCH` to other tabs via `AuthSyncService` (multi-tab sync). * * What this service adds on top: * - A `switching` signal so the UI can show a loading indicator (1-2s switch). * - An `orgChanged$` Observable that components subscribe to in order to * invalidate their org-scoped caches (e.g. drop old query results, reset * page state) without a full page reload. * - Optional `reload: true` for apps where invalidating in-memory state piece * by piece is impractical. * * **What this service does NOT do automatically:** * * 1. **Teardown Firestore listeners.** Listeners are owned by their subscribing * components (typically via `takeUntilDestroyed` or async pipe). When the * component re-renders or unsubscribes, the listener disposes. If a * component does NOT unsubscribe on org change, its listener will keep * pointing at the previous org's path and may start failing rules. The fix * is component-level: subscribe to `orgChanged$` and reset state, or use * the `reload: true` option. * * 2. **Re-instantiate routed components.** Angular keeps mounted components * alive across navigations. If you need fresh state, either subscribe to * `orgChanged$` in the component, or use `reload: true`. * * @example Basic switch with loading state * ```typescript * private orgSwitch = inject(OrgSwitchService); * * async onSwitchOrg(orgId: string) { * await this.orgSwitch.switchTo(orgId); * // Components subscribed to orgChanged$ have already reset their state. * } * * // In template: * @if (orgSwitch.switching()) { } * ``` * * @example Component reacting to org change * ```typescript * private orgSwitch = inject(OrgSwitchService); * * constructor() { * this.orgSwitch.orgChanged$ * .pipe(takeUntilDestroyed()) * .subscribe(() => this.resetState()); * } * ``` * * @example Brutal reload mode * ```typescript * await this.orgSwitch.switchTo(orgId, { reload: true }); * // window.location.reload() — clean slate, loses scroll position * ``` */ export declare class OrgSwitchService { private auth; private readonly _switching; private readonly _orgChanged; /** * `true` while a switch is in flight. UI should disable interactions * with org-scoped data and show a loading indicator. */ readonly switching: import("@angular/core").Signal; /** * Fires after a successful switch, with the previous and new org ids. * Components subscribe to invalidate caches / reset state. * * Fires AFTER the Firebase re-auth completes — listeners attached here * see the updated Firebase user / activeOrg claim. */ readonly orgChanged$: Observable; constructor(auth: AuthService); /** * Switch the user's active organization. * * Re-entrant safe: while a switch is in flight, additional calls are * rejected silently (returns immediately). Inspect `switching()` to gate UI. * * @param orgId Target organization id. Must be one the user has a role in * — backend rejects otherwise with `PERMISSION_DENIED`. * @param options See `SwitchOrgOptions`. * * @throws The error from `auth.switchOrg` if the backend call fails. * `switching` returns to `false` before the error propagates. */ switchTo(orgId: string, options?: SwitchOrgOptions): Promise; /** * Read the current `activeOrg` from the auth user signal. * Falls back to empty string if the user isn't loaded yet. */ private currentActiveOrg; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; }