Browse Source
* feat: add support for IPC client managed session storage * feat: update SDK * fix: using undecorated service in jslib module directly * feat: add test case for web * chore: document why we use any type * fix: `ipc` too short * typo: omg * Revert "typo: omg" This reverts commitpull/17384/head559b05eb5a. * Revert "fix: `ipc` too short" This reverts commit35fc99e10b. * fix: use camelCase
10 changed files with 140 additions and 15 deletions
@ -1,2 +1,3 @@
@@ -1,2 +1,3 @@
|
||||
export * from "./ipc-message"; |
||||
export * from "./ipc.service"; |
||||
export * from "./ipc-session-repository"; |
||||
|
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
import { FakeActiveUserAccessor, FakeStateProvider } from "../../../spec"; |
||||
import { UserId } from "../../types/guid"; |
||||
|
||||
import { IpcSessionRepository } from "./ipc-session-repository"; |
||||
|
||||
describe("IpcSessionRepository", () => { |
||||
const userId = "user-id" as UserId; |
||||
let stateProvider!: FakeStateProvider; |
||||
let repository!: IpcSessionRepository; |
||||
|
||||
beforeEach(() => { |
||||
stateProvider = new FakeStateProvider(new FakeActiveUserAccessor(userId)); |
||||
repository = new IpcSessionRepository(stateProvider); |
||||
}); |
||||
|
||||
it("returns undefined when empty", async () => { |
||||
const result = await repository.get("BrowserBackground"); |
||||
|
||||
expect(result).toBeUndefined(); |
||||
}); |
||||
|
||||
it("saves and retrieves a session", async () => { |
||||
const session = { some: "data" }; |
||||
await repository.save("BrowserBackground", session); |
||||
|
||||
const result = await repository.get("BrowserBackground"); |
||||
|
||||
expect(result).toEqual(session); |
||||
}); |
||||
|
||||
it("saves and retrieves a web session", async () => { |
||||
const session = { some: "data" }; |
||||
await repository.save({ Web: { id: 9001 } }, session); |
||||
|
||||
const result = await repository.get({ Web: { id: 9001 } }); |
||||
|
||||
expect(result).toEqual(session); |
||||
}); |
||||
|
||||
it("removes a session", async () => { |
||||
const session = { some: "data" }; |
||||
await repository.save("BrowserBackground", session); |
||||
|
||||
await repository.remove("BrowserBackground"); |
||||
const result = await repository.get("BrowserBackground"); |
||||
|
||||
expect(result).toBeUndefined(); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
import { firstValueFrom, map } from "rxjs"; |
||||
|
||||
import { Endpoint, IpcSessionRepository as SdkIpcSessionRepository } from "@bitwarden/sdk-internal"; |
||||
|
||||
import { GlobalState, IPC_MEMORY, KeyDefinition, StateProvider } from "../state"; |
||||
|
||||
const IPC_SESSIONS = KeyDefinition.record<object, string>(IPC_MEMORY, "ipcSessions", { |
||||
deserializer: (value: object) => value, |
||||
}); |
||||
|
||||
/** |
||||
* Implementation of SDK-defined repository interface/trait. Do not use directly. |
||||
* All error handling is done by the caller (the SDK). |
||||
* For more information see IPC docs. |
||||
* |
||||
* Interface uses `any` type as defined by the SDK until we get a concrete session type. |
||||
*/ |
||||
export class IpcSessionRepository implements SdkIpcSessionRepository { |
||||
private states: GlobalState<Record<string, any>>; |
||||
|
||||
constructor(private stateProvider: StateProvider) { |
||||
this.states = this.stateProvider.getGlobal(IPC_SESSIONS); |
||||
} |
||||
|
||||
get(endpoint: Endpoint): Promise<any | undefined> { |
||||
return firstValueFrom(this.states.state$.pipe(map((s) => s?.[endpointToString(endpoint)]))); |
||||
} |
||||
|
||||
async save(endpoint: Endpoint, session: any): Promise<void> { |
||||
await this.states.update((s) => ({ |
||||
...s, |
||||
[endpointToString(endpoint)]: session, |
||||
})); |
||||
} |
||||
|
||||
async remove(endpoint: Endpoint): Promise<void> { |
||||
await this.states.update((s) => { |
||||
const newState = { ...s }; |
||||
delete newState[endpointToString(endpoint)]; |
||||
return newState; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
function endpointToString(endpoint: Endpoint): string { |
||||
if (typeof endpoint === "object" && "Web" in endpoint) { |
||||
return `Web(${endpoint.Web.id})`; |
||||
} |
||||
|
||||
return endpoint; |
||||
} |
||||
Loading…
Reference in new issue