Skip to content

Commit

Permalink
♻️ (core) [DSDK-290]: Session refinements (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdabbech-ledger authored May 15, 2024
2 parents a807f59 + 56cb882 commit b512289
Show file tree
Hide file tree
Showing 41 changed files with 432 additions and 407 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-knives-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/device-sdk-core": patch
---

Naming DeviceSession
6 changes: 3 additions & 3 deletions apps/sample/src/app/client-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import styled, { DefaultTheme } from "styled-components";
import { Header } from "@/components/Header";
import { Sidebar } from "@/components/Sidebar";
import { SdkProvider } from "@/providers/DeviceSdkProvider";
import { SessionProvider } from "@/providers/SessionsProvider";
import { DeviceSessionsProvider } from "@/providers/DeviceSessionsProvider";
import { GlobalStyle } from "@/styles/globalstyles";

type ClientRootLayoutProps = {
Expand Down Expand Up @@ -45,13 +45,13 @@ const ClientRootLayout: React.FC<ClientRootLayoutProps> = ({ children }) => {
<GlobalStyle />
<body>
<Root>
<SessionProvider>
<DeviceSessionsProvider>
<Sidebar />
<PageContainer>
<Header />
{children}
</PageContainer>
</SessionProvider>
</DeviceSessionsProvider>
</Root>
</body>
</StyleProvider>
Expand Down
4 changes: 2 additions & 2 deletions apps/sample/src/components/ApduView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import styled, { DefaultTheme } from "styled-components";

import { useApduForm } from "@/hooks/useApduForm";
import { useSdk } from "@/providers/DeviceSdkProvider";
import { useSessionContext } from "@/providers/SessionsProvider";
import { useDeviceSessionsContext } from "@/providers/DeviceSessionsProvider";

const Root = styled(Flex).attrs({ mx: 15, mt: 10, mb: 5 })`
flex-direction: column;
Expand Down Expand Up @@ -70,7 +70,7 @@ export const ApduView: React.FC = () => {
const sdk = useSdk();
const {
state: { selectedId: selectedSessionId },
} = useSessionContext();
} = useDeviceSessionsContext();
const onSubmit = useCallback(
async (values: typeof apduFormValues) => {
setLoading(true);
Expand Down
8 changes: 4 additions & 4 deletions apps/sample/src/components/Device/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import React from "react";
import {
ConnectionType,
DeviceModelId,
SessionId,
DeviceSessionId,
} from "@ledgerhq/device-sdk-core";
import { Box, DropdownGeneric, Flex, Icons, Text } from "@ledgerhq/react-ui";
import styled, { DefaultTheme } from "styled-components";

import { useSessionState } from "@/hooks/useSessionState";
import { useDeviceSessionState } from "@/hooks/useDeviceSessionState";

import { StatusText } from "./StatusText";

Expand Down Expand Up @@ -38,7 +38,7 @@ const ActionRow = styled(Flex).attrs({ py: 4, px: 2 })`
type DeviceProps = {
name: string;
type: ConnectionType;
sessionId: SessionId;
sessionId: DeviceSessionId;
model: DeviceModelId;
onDisconnect: () => Promise<void>;
};
Expand All @@ -50,7 +50,7 @@ export const Device: React.FC<DeviceProps> = ({
onDisconnect,
sessionId,
}) => {
const sessionState = useSessionState(sessionId);
const sessionState = useDeviceSessionState(sessionId);
return (
<Root>
<IconContainer>
Expand Down
4 changes: 2 additions & 2 deletions apps/sample/src/components/MainView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Image from "next/image";
import styled, { DefaultTheme } from "styled-components";

import { useSdk } from "@/providers/DeviceSdkProvider";
import { useSessionContext } from "@/providers/SessionsProvider";
import { useDeviceSessionsContext } from "@/providers/DeviceSessionsProvider";

const Root = styled(Flex)`
flex: 1;
Expand All @@ -23,7 +23,7 @@ const NanoLogo = styled(Image).attrs({ mb: 8 })`

export const MainView: React.FC = () => {
const sdk = useSdk();
const { dispatch } = useSessionContext();
const { dispatch } = useDeviceSessionsContext();

// Example starting the discovery on a user action
const onSelectDeviceClicked = useCallback(() => {
Expand Down
4 changes: 2 additions & 2 deletions apps/sample/src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import styled, { DefaultTheme } from "styled-components";
import { Device } from "@/components/Device";
import { Menu } from "@/components/Menu";
import { useSdk } from "@/providers/DeviceSdkProvider";
import { useSessionContext } from "@/providers/SessionsProvider";
import { useDeviceSessionsContext } from "@/providers/DeviceSessionsProvider";

const Root = styled(Flex).attrs({ py: 8, px: 6 })`
flex-direction: column;
Expand Down Expand Up @@ -46,7 +46,7 @@ export const Sidebar: React.FC = () => {
const {
state: { deviceById },
dispatch,
} = useSessionContext();
} = useDeviceSessionsContext();

useEffect(() => {
sdk
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { useEffect, useState } from "react";
import { SessionDeviceState, SessionId } from "@ledgerhq/device-sdk-core";
import { DeviceSessionId, DeviceSessionState } from "@ledgerhq/device-sdk-core";

import { useSdk } from "@/providers/DeviceSdkProvider";

export function useSessionState(sessionId: SessionId) {
export function useDeviceSessionState(sessionId: DeviceSessionId) {
const sdk = useSdk();
const [sessionState, setSessionState] = useState<SessionDeviceState>();
const [deviceSessionState, setDeviceSessionState] =
useState<DeviceSessionState>();

useEffect(() => {
if (sessionId) {
const subscription = sdk
.getSessionDeviceState({
.getDeviceSessionState({
sessionId,
})
.subscribe((state) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
setSessionState(state);
setDeviceSessionState(state);
});

return () => {
Expand All @@ -24,5 +25,5 @@ export function useSessionState(sessionId: SessionId) {
}
}, [sessionId, sdk]);

return sessionState;
return deviceSessionState;
}
38 changes: 38 additions & 0 deletions apps/sample/src/providers/DeviceSessionsProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { Context, createContext, useContext, useReducer } from "react";

import {
AddSessionAction,
DeviceSessionsInitialState,
deviceSessionsReducer,
DeviceSessionsState,
RemoveSessionAction,
} from "@/reducers/deviceSessions";

type DeviceSessionsContextType = {
state: DeviceSessionsState;
dispatch: (value: AddSessionAction | RemoveSessionAction) => void;
};

const DeviceSessionsContext: Context<DeviceSessionsContextType> =
createContext<DeviceSessionsContextType>({
state: DeviceSessionsInitialState,
dispatch: () => null,
});

export const DeviceSessionsProvider: React.FC<React.PropsWithChildren> = ({
children,
}) => {
const [state, dispatch] = useReducer(
deviceSessionsReducer,
DeviceSessionsInitialState,
);

return (
<DeviceSessionsContext.Provider value={{ state, dispatch }}>
{children}
</DeviceSessionsContext.Provider>
);
};

export const useDeviceSessionsContext = () =>
useContext<DeviceSessionsContextType>(DeviceSessionsContext);
35 changes: 0 additions & 35 deletions apps/sample/src/providers/SessionsProvider/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { Reducer } from "react";
import { ConnectedDevice, SessionId } from "@ledgerhq/device-sdk-core";
import { ConnectedDevice, DeviceSessionId } from "@ledgerhq/device-sdk-core";

export type SessionsState = {
selectedId: SessionId | null;
deviceById: Record<SessionId, ConnectedDevice>;
export type DeviceSessionsState = {
selectedId: DeviceSessionId | null;
deviceById: Record<DeviceSessionId, ConnectedDevice>;
};

export type AddSessionAction = {
type: "add_session";
payload: { sessionId: SessionId; connectedDevice: ConnectedDevice };
payload: { sessionId: DeviceSessionId; connectedDevice: ConnectedDevice };
};

export type RemoveSessionAction = {
type: "remove_session";
payload: { sessionId: SessionId };
payload: { sessionId: DeviceSessionId };
};

export const SessionsInitialState: SessionsState = {
export const DeviceSessionsInitialState: DeviceSessionsState = {
selectedId: null,
deviceById: {},
};

export const sessionsReducer: Reducer<
SessionsState,
export const deviceSessionsReducer: Reducer<
DeviceSessionsState,
AddSessionAction | RemoveSessionAction
> = (state, action) => {
switch (action.type) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/api/DeviceSdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe("DeviceSdk", () => {
[commandTypes.SendCommandUseCase],
[usbDiTypes.GetConnectedDeviceUseCase],
[discoveryTypes.DisconnectUseCase],
[deviceSessionTypes.GetSessionDeviceStateUseCase],
[deviceSessionTypes.GetDeviceSessionStateUseCase],
])("should have %p use case", (diSymbol) => {
const uc = sdk.container.get<StubUseCase>(diSymbol);
expect(uc).toBeInstanceOf(StubUseCase);
Expand Down
18 changes: 9 additions & 9 deletions packages/core/src/api/DeviceSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {
SendCommandUseCase,
SendCommandUseCaseArgs,
} from "@api/command/use-case/SendCommandUseCase";
import { SessionDeviceState } from "@api/session/SessionDeviceState";
import { SessionId } from "@api/session/types";
import { DeviceSessionState } from "@api/device-session/DeviceSessionState";
import { DeviceSessionId } from "@api/device-session/types";
import { ConnectedDevice } from "@api/usb/model/ConnectedDevice";
import { configTypes } from "@internal/config/di/configTypes";
import { GetSdkVersionUseCase } from "@internal/config/use-case/GetSdkVersionUseCase";
import { deviceSessionTypes } from "@internal/device-session/di/deviceSessionTypes";
import { ApduResponse } from "@internal/device-session/model/ApduResponse";
import { GetSessionDeviceStateUseCase } from "@internal/device-session/use-case/GetSessionDeviceStateUseCase";
import { GetDeviceSessionStateUseCase } from "@internal/device-session/use-case/GetDeviceSessionStateUseCase";
import { discoveryTypes } from "@internal/discovery/di/discoveryTypes";
import {
ConnectUseCase,
Expand Down Expand Up @@ -66,7 +66,7 @@ export class DeviceSdk {
.execute();
}

connect(args: ConnectUseCaseArgs): Promise<SessionId> {
connect(args: ConnectUseCaseArgs): Promise<DeviceSessionId> {
return this.container
.get<ConnectUseCase>(discoveryTypes.ConnectUseCase)
.execute(args);
Expand Down Expand Up @@ -96,12 +96,12 @@ export class DeviceSdk {
.execute(args);
}

getSessionDeviceState(args: {
sessionId: SessionId;
}): Observable<SessionDeviceState> {
getDeviceSessionState(args: {
sessionId: DeviceSessionId;
}): Observable<DeviceSessionState> {
return this.container
.get<GetSessionDeviceStateUseCase>(
deviceSessionTypes.GetSessionDeviceStateUseCase,
.get<GetDeviceSessionStateUseCase>(
deviceSessionTypes.GetDeviceSessionStateUseCase,
)
.execute(args);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Left } from "purify-ts";

import { Command } from "@api/command/Command";
import { sessionStubBuilder } from "@internal/device-session/model/Session.stub";
import { DefaultSessionService } from "@internal/device-session/service/DefaultSessionService";
import { SessionService } from "@internal/device-session/service/SessionService";
import { deviceSessionStubBuilder } from "@internal/device-session/model/DeviceSession.stub";
import { DefaultDeviceSessionService } from "@internal/device-session/service/DefaultDeviceSessionService";
import { DeviceSessionService } from "@internal/device-session/service/DeviceSessionService";
import { DefaultLoggerPublisherService } from "@internal/logger-publisher/service/DefaultLoggerPublisherService";
import { LoggerPublisherService } from "@internal/logger-publisher/service/LoggerPublisherService";

Expand All @@ -13,14 +13,14 @@ import {
} from "./SendCommandUseCase";

let logger: LoggerPublisherService;
let sessionService: SessionService;
let sessionService: DeviceSessionService;
const fakeSessionId = "fakeSessionId";
let command: Command<{ status: string }>;

describe("SendCommandUseCase", () => {
beforeEach(() => {
logger = new DefaultLoggerPublisherService([], "send-command-use-case");
sessionService = new DefaultSessionService(() => logger);
sessionService = new DefaultDeviceSessionService(() => logger);
command = {
getApdu: jest.fn(),
parseResponse: jest.fn(),
Expand All @@ -32,12 +32,12 @@ describe("SendCommandUseCase", () => {
});

it("should send a command to a connected device", async () => {
const session = sessionStubBuilder();
sessionService.addSession(session);
const deviceSession = deviceSessionStubBuilder();
sessionService.addDeviceSession(deviceSession);
const useCase = new SendCommandUseCase(sessionService, () => logger);

jest
.spyOn(session, "getCommand")
.spyOn(deviceSession, "getCommand")
.mockReturnValue(async () => Promise.resolve({ status: "success" }));

const response = await useCase.execute<{ status: string }>({
Expand All @@ -52,7 +52,7 @@ describe("SendCommandUseCase", () => {
it("should throw an error if the session is not found", async () => {
const useCase = new SendCommandUseCase(sessionService, () => logger);
jest
.spyOn(sessionService, "getSessionById")
.spyOn(sessionService, "getDeviceSessionById")
.mockReturnValue(Left({ _tag: "DeviceSessionNotFound" }));

const res = useCase.execute<{ status: string }>({
Expand Down
Loading

0 comments on commit b512289

Please sign in to comment.