Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/sessionManager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const storageSettings: StorageSettingsType = {
maxLength: 2000,
};

export { MemoryStorage } from "./stores/memory.ts";
export { ChromeStore } from "./stores/chromeStore.ts";
export { ExpoSecureStore } from "./stores/expoSecureStore.ts";
export { MemoryStorage } from "./stores/memory.js";
export { ChromeStore } from "./stores/chromeStore.js";
export { ExpoSecureStore } from "./stores/expoSecureStore.js";
export { LocalStorage } from "./stores/localStorage.ts";
export * from "./types.ts";
export { type SessionManager, StorageKeys } from "./types.ts";
13 changes: 13 additions & 0 deletions lib/sessionManager/stores/chromeStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ describe.skip("GoogleStorage standard keys", () => {
await sessionManager.getSessionItem(StorageKeys.accessToken),
).toBeNull();
});

it("should set many items", async () => {
await sessionManager.setItems({
[StorageKeys.accessToken]: "accessTokenValue",
[StorageKeys.idToken]: "idTokenValue",
});
expect(await sessionManager.getSessionItem(StorageKeys.accessToken)).toBe(
"accessTokenValue",
);
expect(await sessionManager.getSessionItem(StorageKeys.idToken)).toBe(
"idTokenValue",
);
});
});

// TODO: Fix tests, need to mock chrome storage
Expand Down
7 changes: 5 additions & 2 deletions lib/sessionManager/stores/chromeStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { storageSettings } from "../index.js";
import { StorageKeys, type SessionManager } from "../types.js";
import { SessionBase, StorageKeys, type SessionManager } from "../types.js";
import { splitString } from "../utils.js";

function getStorageValue(key: string): unknown | undefined {
Expand All @@ -18,7 +18,10 @@ function getStorageValue(key: string): unknown | undefined {
* Provides a chrome.store.local based session manager implementation for the browser.
* @class ChromeStore
*/
export class ChromeStore<V = StorageKeys> implements SessionManager<V> {
export class ChromeStore<V extends string = StorageKeys>
extends SessionBase<V>
implements SessionManager<V>
{
/**
* Clears all items from session store.
* @returns {void}
Expand Down
13 changes: 13 additions & 0 deletions lib/sessionManager/stores/expoSecureStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ describe.skip("ExpoSecureStore standard keys", () => {
await sessionManager.getSessionItem(StorageKeys.accessToken),
).toBeNull();
});

it("should set many items", async () => {
await sessionManager.setItems({
[StorageKeys.accessToken]: "accessTokenValue",
[StorageKeys.idToken]: "idTokenValue",
});
expect(await sessionManager.getSessionItem(StorageKeys.accessToken)).toBe(
"accessTokenValue",
);
expect(await sessionManager.getSessionItem(StorageKeys.idToken)).toBe(
"idTokenValue",
);
});
});

describe.skip("ExpoSecureStore keys: storageKeys", () => {
Expand Down
7 changes: 5 additions & 2 deletions lib/sessionManager/stores/expoSecureStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { storageSettings } from "../index.js";
import { StorageKeys, type SessionManager } from "../types.js";
import { SessionBase, StorageKeys } from "../types.js";
import { splitString } from "../utils.js";

let expoSecureStore: typeof import("expo-secure-store") | undefined = undefined;
Expand All @@ -16,8 +16,11 @@
* Provides a expo local store based session manager implementation for the browser.
* @class ExpoSecureStore
*/
export class ExpoSecureStore<V = StorageKeys> implements SessionManager<V> {
export class ExpoSecureStore<
V extends string = StorageKeys,
> extends SessionBase<V> {
constructor() {
super();

Check warning on line 23 in lib/sessionManager/stores/expoSecureStore.ts

View check run for this annotation

Codecov / codecov/patch

lib/sessionManager/stores/expoSecureStore.ts#L23

Added line #L23 was not covered by tests
this.loadExpoStore();
}

Expand Down
1 change: 0 additions & 1 deletion lib/sessionManager/stores/localStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ describe("LocalStorage standard keys", () => {
});

it("should set and get an item in session storage", async () => {
console.log("here");
await sessionManager.setSessionItem(StorageKeys.accessToken, "testValue");
expect(await sessionManager.getSessionItem(StorageKeys.accessToken)).toBe(
"testValue",
Expand Down
16 changes: 10 additions & 6 deletions lib/sessionManager/stores/localStorage.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { storageSettings } from "../index.js";
import { StorageKeys, type SessionManager } from "../types.js";
import { SessionBase, StorageKeys, type SessionManager } from "../types.js";
import { splitString } from "../utils.js";

/**
* Provides a localStorage based session manager implementation for the browser.
* @class LocalStorage
*/
export class LocalStorage<V = StorageKeys> implements SessionManager<V> {
export class LocalStorage<V extends string = StorageKeys>
extends SessionBase<V>
implements SessionManager<V>
{
constructor() {
super();
console.warn("LocalStorage store should not be used in production");
}

setItems: Set<V | StorageKeys> = new Set<V>();
private internalItems: Set<V | StorageKeys> = new Set<V>();

/**
* Clears all items from session store.
* @returns {void}
*/
async destroySession(): Promise<void> {
this.setItems.forEach((key) => {
this.internalItems.forEach((key) => {
this.removeSessionItem(key);
});
}
Expand All @@ -35,7 +39,7 @@ export class LocalStorage<V = StorageKeys> implements SessionManager<V> {
): Promise<void> {
// clear items first
await this.removeSessionItem(itemKey);
this.setItems.add(itemKey);
this.internalItems.add(itemKey);

if (typeof itemValue === "string") {
splitString(itemValue, storageSettings.maxLength).forEach(
Expand Down Expand Up @@ -97,6 +101,6 @@ export class LocalStorage<V = StorageKeys> implements SessionManager<V> {

index++;
}
this.setItems.delete(itemKey);
this.internalItems.delete(itemKey);
}
}
13 changes: 13 additions & 0 deletions lib/sessionManager/stores/memory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ describe("MemoryStorage standard keys", () => {
await sessionManager.getSessionItem(StorageKeys.accessToken),
).toBeNull();
});

it("should set many items", async () => {
await sessionManager.setItems({
[StorageKeys.accessToken]: "accessTokenValue",
[StorageKeys.idToken]: "idTokenValue",
});
expect(await sessionManager.getSessionItem(StorageKeys.accessToken)).toBe(
"accessTokenValue",
);
expect(await sessionManager.getSessionItem(StorageKeys.idToken)).toBe(
"idTokenValue",
);
});
});

describe("MemoryStorage keys: storageKeys", () => {
Expand Down
7 changes: 5 additions & 2 deletions lib/sessionManager/stores/memory.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { storageSettings } from "../index.js";
import { StorageKeys, type SessionManager } from "../types.js";
import { SessionBase, StorageKeys, type SessionManager } from "../types.js";
import { splitString } from "../utils.js";

/**
* Provides a memory based session manager implementation for the browser.
* @class MemoryStorage
*/
export class MemoryStorage<V = StorageKeys> implements SessionManager<V> {
export class MemoryStorage<V extends string = StorageKeys>
extends SessionBase<V>
implements SessionManager<V>
{
private memCache: Record<string, unknown> = {};

/**
Expand Down
33 changes: 32 additions & 1 deletion lib/sessionManager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,31 @@ export type StorageSettingsType = {
maxLength: number;
};

export interface SessionManager<V = StorageKeys> {
export abstract class SessionBase<V extends string = StorageKeys>
implements SessionManager<V>
{
abstract getSessionItem<T = unknown>(
itemKey: V | StorageKeys,
): Awaitable<T | unknown | null>;
abstract setSessionItem<T = unknown>(
itemKey: V | StorageKeys,
itemValue: T,
): Awaitable<void>;
abstract removeSessionItem(itemKey: V | StorageKeys): Awaitable<void>;
abstract destroySession(): Awaitable<void>;

async setItems(items: Partial<Record<V, unknown>>): Awaitable<void> {
await Promise.all(
(Object.entries(items) as [V | StorageKeys, unknown][]).map(
([key, value]) => {
return this.setSessionItem(key, value);
},
),
);
}
}

export interface SessionManager<V extends string = StorageKeys> {
/**
*
* Gets the item for the provided key from the storage.
Expand Down Expand Up @@ -49,4 +73,11 @@ export interface SessionManager<V = StorageKeys> {
* Destroys the session
*/
destroySession: () => Awaitable<void>;

/**
* Sets multiple items simultaneously.
* @param {Record<V | StorageKeys, unknown>} items - Object containing key-value pairs to store
* @returns {Promise<void>}
*/
setItems(items: Partial<Record<V, unknown>>): Awaitable<void>;
}
Loading