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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user