1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 18:23:31 +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:
Addison Beck
2025-06-23 16:00:54 -04:00
committed by GitHub
parent 5bd4d1691e
commit 95841eb078
32 changed files with 1918 additions and 1354 deletions

View File

@@ -1,45 +1,7 @@
/**
* Default storage location options.
*
* `disk` generally means state that is accessible between restarts of the application,
* with the exception of the web client. In web this means `sessionStorage`. The data
* persists through refreshes of the page but not available once that tab is closed or
* from any other tabs.
*
* `memory` means that the information stored there goes away during application
* restarts.
*/
export type StorageLocation = "disk" | "memory";
import { StorageLocation, ClientLocations } from "@bitwarden/storage-core";
/**
* *Note*: The property names of this object should match exactly with the string values of the {@link ClientType} enum
*/
export type ClientLocations = {
/**
* Overriding storage location for the web client.
*
* Includes an extra storage location to store data in `localStorage`
* that is available from different tabs and after a tab has closed.
*/
web: StorageLocation | "disk-local";
/**
* Overriding storage location for browser clients.
*
* `"memory-large-object"` is used to store non-countable objects in memory. This exists due to limited persistent memory available to browser extensions.
*
* `"disk-backup-local-storage"` is used to store object in both disk and in `localStorage`. Data is stored in both locations but is only retrieved
* from `localStorage` when a null-ish value is retrieved from disk first.
*/
browser: StorageLocation | "memory-large-object" | "disk-backup-local-storage";
/**
* Overriding storage location for desktop clients.
*/
//desktop: StorageLocation;
/**
* Overriding storage location for CLI clients.
*/
//cli: StorageLocation;
};
// To be removed once references are updated to point to @bitwarden/storage-core
export { StorageLocation, ClientLocations };
/**
* Defines the base location and instruction of where this state is expected to be located.

View File

@@ -1,53 +0,0 @@
import { MemoryStorageService } from "./memory-storage.service";
describe("MemoryStorageService", () => {
let sut: MemoryStorageService;
const key = "key";
const value = { test: "value" };
beforeEach(() => {
sut = new MemoryStorageService();
});
afterEach(() => {
jest.resetAllMocks();
});
describe("get", () => {
it("should return null if the key does not exist", async () => {
const result = await sut.get(key);
expect(result).toBeNull();
});
it("should return the value if the key exists", async () => {
await sut.save(key, value);
const result = await sut.get(key);
expect(result).toEqual(value);
});
it("should json parse stored values", async () => {
sut["store"][key] = JSON.stringify({ test: "value" });
const result = await sut.get(key);
expect(result).toEqual({ test: "value" });
});
});
describe("save", () => {
it("should store the value as json string", async () => {
const value = { test: "value" };
await sut.save(key, value);
expect(sut["store"][key]).toEqual(JSON.stringify(value));
});
});
describe("remove", () => {
it("should remove a value from store", async () => {
await sut.save(key, value);
await sut.remove(key);
expect(Object.keys(sut["store"])).not.toContain(key);
});
});
});

View File

@@ -1,54 +1 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Subject } from "rxjs";
import {
AbstractStorageService,
ObservableStorageService,
StorageUpdate,
} from "../../abstractions/storage.service";
export class MemoryStorageService
extends AbstractStorageService
implements ObservableStorageService
{
protected store: Record<string, string> = {};
private updatesSubject = new Subject<StorageUpdate>();
get valuesRequireDeserialization(): boolean {
return true;
}
get updates$() {
return this.updatesSubject.asObservable();
}
get<T>(key: string): Promise<T> {
const json = this.store[key];
if (json) {
const obj = JSON.parse(json as string);
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
this.store[key] = JSON.stringify(obj);
this.updatesSubject.next({ key, updateType: "save" });
return Promise.resolve();
}
remove(key: string): Promise<void> {
delete this.store[key];
this.updatesSubject.next({ key, updateType: "remove" });
return Promise.resolve();
}
}
export { SerializedMemoryStorageService as MemoryStorageService } from "@bitwarden/storage-core";