1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-26 01:23:24 +00:00
Files
browser/libs/common/src/tools/extension/extension.service.ts
2025-03-06 11:32:42 -05:00

64 lines
2.3 KiB
TypeScript

import { shareReplay } from "rxjs";
import { Account } from "../../auth/abstractions/account.service";
import { BoundDependency } from "../dependencies";
import { SemanticLogger } from "../log";
import { UserStateSubject } from "../state/user-state-subject";
import { UserStateSubjectDependencyProvider } from "../state/user-state-subject-dependency-provider";
import { ExtensionRegistry } from "./extension-registry.abstraction";
import { ExtensionProfileMetadata, SiteId, VendorId } from "./type";
import { toObjectKey } from "./util";
/** Provides configuration and storage support for Bitwarden client extensions.
* These extensions integrate 3rd party services into Bitwarden.
*/
export class ExtensionService {
/** Instantiate the extension service.
* @param registry provides runtime status for extension sites
* @param providers provide persistent data
*/
constructor(
private registry: ExtensionRegistry,
private readonly providers: UserStateSubjectDependencyProvider,
) {
this.log = providers.log({
type: "ExtensionService",
});
}
private log: SemanticLogger;
/** Get a subject bound to a user's extension settings
* @param profile the site's extension profile
* @param vendor the vendor integrated at the extension site
* @param dependencies.account$ the account to which the settings are bound
* @returns a subject bound to the requested user's generator settings
*/
settings<Settings extends object, Site extends SiteId>(
profile: ExtensionProfileMetadata<Settings, Site>,
vendor: VendorId,
dependencies: BoundDependency<"account", Account>,
): UserStateSubject<Settings> {
const metadata = this.registry.extension(profile.site, vendor);
if (!metadata) {
this.log.panic({ site: profile.site as string, vendor }, "extension not defined");
}
const key = toObjectKey(profile, metadata);
const account$ = dependencies.account$.pipe(shareReplay({ bufferSize: 1, refCount: true }));
// FIXME: load and apply constraints
const subject = new UserStateSubject(key, this.providers, { account$ });
return subject;
}
/** Look up extension metadata for a site
* @param site defines the site to retrieve.
* @returns the extensions available at the site.
*/
site(site: SiteId) {
return this.registry.build(site);
}
}