mirror of
https://github.com/bitwarden/browser
synced 2026-01-02 08:33:43 +00:00
refactor(storage-core): move storage files out of @bitwarden/common (#15076)
* refactor(platform): generate @bitwarden/storage-core boilerplate * refactor(storage-core): move storage files out of @bitwarden/common * chore(naming): rename AbstractStorageService to StorageService
This commit is contained in:
@@ -1,47 +1 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
import { AbstractStorageService, StorageUpdate } from "../abstractions/storage.service";
|
||||
|
||||
export class MemoryStorageService extends AbstractStorageService {
|
||||
protected store = new Map<string, unknown>();
|
||||
private updatesSubject = new Subject<StorageUpdate>();
|
||||
|
||||
get valuesRequireDeserialization(): boolean {
|
||||
return false;
|
||||
}
|
||||
get updates$() {
|
||||
return this.updatesSubject.asObservable();
|
||||
}
|
||||
|
||||
get<T>(key: string): Promise<T> {
|
||||
if (this.store.has(key)) {
|
||||
const obj = this.store.get(key);
|
||||
return Promise.resolve(obj as T);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
async has(key: string): Promise<boolean> {
|
||||
return (await this.get(key)) != null;
|
||||
}
|
||||
|
||||
save<T>(key: string, obj: T): Promise<void> {
|
||||
if (obj == null) {
|
||||
return this.remove(key);
|
||||
}
|
||||
// TODO: Remove once foreground/background contexts are separated in browser
|
||||
// Needed to ensure ownership of all memory by the context running the storage service
|
||||
const toStore = structuredClone(obj);
|
||||
this.store.set(key, toStore);
|
||||
this.updatesSubject.next({ key, updateType: "save" });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
remove(key: string): Promise<void> {
|
||||
this.store.delete(key);
|
||||
this.updatesSubject.next({ key, updateType: "remove" });
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
export { MemoryStorageService } from "@bitwarden/storage-core";
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { AbstractStorageService, ObservableStorageService } from "../abstractions/storage.service";
|
||||
|
||||
import { StorageServiceProvider } from "./storage-service.provider";
|
||||
|
||||
describe("StorageServiceProvider", () => {
|
||||
const mockDiskStorage = mock<AbstractStorageService & ObservableStorageService>();
|
||||
const mockMemoryStorage = mock<AbstractStorageService & ObservableStorageService>();
|
||||
|
||||
const sut = new StorageServiceProvider(mockDiskStorage, mockMemoryStorage);
|
||||
|
||||
describe("get", () => {
|
||||
it("gets disk service when default location is disk", () => {
|
||||
const [computedLocation, computedService] = sut.get("disk", {});
|
||||
|
||||
expect(computedLocation).toBe("disk");
|
||||
expect(computedService).toStrictEqual(mockDiskStorage);
|
||||
});
|
||||
|
||||
it("gets memory service when default location is memory", () => {
|
||||
const [computedLocation, computedService] = sut.get("memory", {});
|
||||
|
||||
expect(computedLocation).toBe("memory");
|
||||
expect(computedService).toStrictEqual(mockMemoryStorage);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,39 +1,2 @@
|
||||
import { AbstractStorageService, ObservableStorageService } from "../abstractions/storage.service";
|
||||
// eslint-disable-next-line import/no-restricted-paths
|
||||
import { ClientLocations, StorageLocation } from "../state/state-definition";
|
||||
|
||||
export type PossibleLocation = StorageLocation | ClientLocations[keyof ClientLocations];
|
||||
|
||||
/**
|
||||
* A provider for getting client specific computed storage locations and services.
|
||||
*/
|
||||
export class StorageServiceProvider {
|
||||
constructor(
|
||||
protected readonly diskStorageService: AbstractStorageService & ObservableStorageService,
|
||||
protected readonly memoryStorageService: AbstractStorageService & ObservableStorageService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Computes the location and corresponding service for a given client.
|
||||
*
|
||||
* **NOTE** The default implementation does not respect client overrides and if clients
|
||||
* have special overrides they are responsible for implementing this service.
|
||||
* @param defaultLocation The default location to use if no client specific override is preferred.
|
||||
* @param overrides Client specific overrides
|
||||
* @returns The computed storage location and corresponding storage service to use to get/store state.
|
||||
* @throws If there is no configured storage service for the given inputs.
|
||||
*/
|
||||
get(
|
||||
defaultLocation: PossibleLocation,
|
||||
overrides: Partial<ClientLocations>,
|
||||
): [location: PossibleLocation, service: AbstractStorageService & ObservableStorageService] {
|
||||
switch (defaultLocation) {
|
||||
case "disk":
|
||||
return [defaultLocation, this.diskStorageService];
|
||||
case "memory":
|
||||
return [defaultLocation, this.memoryStorageService];
|
||||
default:
|
||||
throw new Error(`Unexpected location: ${defaultLocation}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
export { StorageServiceProvider } from "@bitwarden/storage-core";
|
||||
export type { PossibleLocation } from "@bitwarden/storage-core";
|
||||
|
||||
Reference in New Issue
Block a user