Skip to content

Commit 07cd2c2

Browse files
authored
πŸ”– (release) [NO-ISSUE]: New release incoming DMK 0.11.1 (#1121)
2 parents 02eeb53 + c1d304d commit 07cd2c2

15 files changed

Lines changed: 184 additions & 110 deletions

File tree

β€Žapps/docs/pages/docs/getting-started.mdxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Here you can found a summary of all the libraries that are composing the DMK
3939

4040
| Library | NPM | Version |
4141
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
42-
| Device Management Kit | [@ledgerhq/device-management-kit](https://www.npmjs.com/package/@ledgerhq/device-management-kit) | 0.11.0 |
42+
| Device Management Kit | [@ledgerhq/device-management-kit](https://www.npmjs.com/package/@ledgerhq/device-management-kit) | 0.11.1 |
4343
| Device Signer Ethereum | [@ledgerhq/device-signer-kit-ethereum](https://www.npmjs.com/package/@ledgerhq/device-signer-kit-ethereum) | 1.9.2 |
4444
| Device Signer Bitcoin | [@ledgerhq/device-signer-kit-bitcoin](https://www.npmjs.com/package/@ledgerhq/device-signer-kit-bitcoin) | 1.0.2 |
4545
| Device Signer Solana | [@ledgerhq/device-signer-kit-solana](https://www.npmjs.com/package/@ledgerhq/device-signer-kit-solana) | 1.4.1 |

β€Žpackages/device-management-kit/CHANGELOG.mdβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @ledgerhq/device-management-kit
22

3+
## 0.11.1
4+
5+
### Patch Changes
6+
7+
- [#1119](https://github.com/LedgerHQ/device-sdk-ts/pull/1119) [`0e4ae29`](https://github.com/LedgerHQ/device-sdk-ts/commit/0e4ae2941f93448d8d1439f9d26166ffa5633a54) Thanks [@jiyuzhuang](https://github.com/jiyuzhuang)! - Clean up all device sessions of the same device when device disconnected
8+
39
## 0.11.0
410

511
### Minor Changes

β€Žpackages/device-management-kit/package.jsonβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ledgerhq/device-management-kit",
3-
"version": "0.11.0",
3+
"version": "0.11.1",
44
"private": false,
55
"license": "Apache-2.0",
66
"exports": {

β€Žpackages/device-management-kit/src/internal/device-session/service/DefaultDeviceSessionService.test.tsβ€Ž

Lines changed: 93 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Either, Left } from "purify-ts";
22
import { Observable } from "rxjs";
33

44
import { type DmkConfig } from "@api/DmkConfig";
5+
import { connectedDeviceStubBuilder } from "@api/transport/model/TransportConnectedDevice.stub";
56
import { DEVICE_SESSION_REFRESHER_DEFAULT_OPTIONS } from "@internal/device-session/data/DeviceSessionRefresherConst";
67
import { type DeviceSession } from "@internal/device-session/model/DeviceSession";
78
import { deviceSessionStubBuilder } from "@internal/device-session/model/DeviceSession.stub";
@@ -24,23 +25,26 @@ vi.mock("@internal/manager-api/data/AxiosManagerApiDataSource");
2425
let sessionService: DefaultDeviceSessionService;
2526
let loggerService: DefaultLoggerPublisherService;
2627
let deviceSession: DeviceSession;
28+
let deviceSession1: DeviceSession;
29+
let deviceSession2: DeviceSession;
2730
let managerApiDataSource: ManagerApiDataSource;
2831
let managerApi: ManagerApiService;
2932
let secureChannelDataSource: SecureChannelDataSource;
3033
let secureChannel: SecureChannelService;
3134

3235
describe("DefaultDeviceSessionService", () => {
36+
// Initialize shared resources
37+
loggerService = new DefaultLoggerPublisherService([], "deviceSession");
38+
managerApiDataSource = new AxiosManagerApiDataSource({} as DmkConfig);
39+
managerApi = new DefaultManagerApiService(managerApiDataSource);
40+
secureChannelDataSource = new DefaultSecureChannelDataSource({} as DmkConfig);
41+
secureChannel = new DefaultSecureChannelService(secureChannelDataSource);
42+
3343
beforeEach(() => {
3444
vi.restoreAllMocks();
35-
loggerService = new DefaultLoggerPublisherService([], "deviceSession");
45+
// Create a new instance before each test
3646
sessionService = new DefaultDeviceSessionService(() => loggerService);
37-
managerApiDataSource = new AxiosManagerApiDataSource({} as DmkConfig);
38-
managerApi = new DefaultManagerApiService(managerApiDataSource);
39-
secureChannelDataSource = new DefaultSecureChannelDataSource(
40-
{} as DmkConfig,
41-
);
42-
secureChannel = new DefaultSecureChannelService(secureChannelDataSource);
43-
47+
// Create a device session stub with default properties
4448
deviceSession = deviceSessionStubBuilder(
4549
{},
4650
() => loggerService,
@@ -54,43 +58,96 @@ describe("DefaultDeviceSessionService", () => {
5458
deviceSession.close();
5559
});
5660

57-
it("should have an empty sessions list", () => {
61+
it("should have an empty DeviceSession list", () => {
5862
expect(sessionService.getDeviceSessions()).toEqual([]);
5963
});
6064

61-
it("should add a deviceSession", () => {
62-
sessionService.addDeviceSession(deviceSession);
63-
expect(sessionService.getDeviceSessions()).toEqual([deviceSession]);
64-
});
65-
66-
it("should not add a deviceSession if it already exists", () => {
67-
sessionService.addDeviceSession(deviceSession);
68-
sessionService.addDeviceSession(deviceSession);
69-
expect(sessionService.getDeviceSessions()).toEqual([deviceSession]);
70-
});
71-
72-
it("should remove a deviceSession", () => {
73-
sessionService.addDeviceSession(deviceSession);
74-
sessionService.removeDeviceSession(deviceSession.id);
75-
expect(sessionService.getDeviceSessions()).toEqual([]);
65+
describe("DeviceSessionService addDeviceSession", () => {
66+
it("should add a DeviceSession if it does not already exist", () => {
67+
sessionService.addDeviceSession(deviceSession);
68+
expect(sessionService.getDeviceSessions()).toEqual([deviceSession]);
69+
});
70+
it("should not add a DeviceSession if it already exists", () => {
71+
sessionService.addDeviceSession(deviceSession);
72+
sessionService.addDeviceSession(deviceSession);
73+
expect(sessionService.getDeviceSessions()).toEqual([deviceSession]);
74+
});
7675
});
7776

78-
it("should not remove a deviceSession if it does not exist", () => {
79-
sessionService.removeDeviceSession(deviceSession.id);
80-
expect(sessionService.getDeviceSessions()).toEqual([]);
77+
describe("DeviceSessionService removeDeviceSession", () => {
78+
it("should remove the DeviceSession of given ID", () => {
79+
sessionService.addDeviceSession(deviceSession);
80+
sessionService.removeDeviceSession(deviceSession.id);
81+
expect(sessionService.getDeviceSessions()).toEqual([]);
82+
});
83+
it("should not remove the DeviceSession of given ID if it does not exist", () => {
84+
sessionService.addDeviceSession(deviceSession);
85+
sessionService.removeDeviceSession("non-existent-id");
86+
expect(sessionService.getDeviceSessions()).toEqual([deviceSession]);
87+
});
8188
});
8289

83-
it("should get a deviceSession", () => {
84-
sessionService.addDeviceSession(deviceSession);
85-
expect(sessionService.getDeviceSessionById(deviceSession.id)).toEqual(
86-
Either.of(deviceSession),
87-
);
90+
describe("DeviceSessionService getDeviceSessionById", () => {
91+
it("should get the DeviceSession of given ID if it exists", () => {
92+
sessionService.addDeviceSession(deviceSession);
93+
expect(sessionService.getDeviceSessionById(deviceSession.id)).toEqual(
94+
Either.of(deviceSession),
95+
);
96+
});
97+
it("should not get the DeviceSession if it does not exist", () => {
98+
sessionService.addDeviceSession(deviceSession);
99+
expect(sessionService.getDeviceSessionById("non-existent-id")).toEqual(
100+
Left(new DeviceSessionNotFound()),
101+
);
102+
});
88103
});
89104

90-
it("should not get a deviceSession if it does not exist", () => {
91-
expect(sessionService.getDeviceSessionById(deviceSession.id)).toEqual(
92-
Left(new DeviceSessionNotFound()),
93-
);
105+
describe("DeviceSessionService getDeviceSessionsByDeviceId", () => {
106+
it("should not get device sessions by deviceId if none exist", () => {
107+
sessionService.addDeviceSession(deviceSession);
108+
expect(
109+
sessionService.getDeviceSessionsByDeviceId("non-existent-device-id"),
110+
).toEqual(Left(new DeviceSessionNotFound()));
111+
});
112+
it("should get a single device session by deviceId", () => {
113+
sessionService.addDeviceSession(deviceSession);
114+
expect(
115+
sessionService.getDeviceSessionsByDeviceId(
116+
deviceSession.connectedDevice.id,
117+
),
118+
).toEqual(Either.of([deviceSession]));
119+
});
120+
it("should get device sessions by deviceId", () => {
121+
sessionService.addDeviceSession(deviceSession);
122+
deviceSession1 = deviceSessionStubBuilder(
123+
{
124+
connectedDevice: connectedDeviceStubBuilder({ id: "device-1" }),
125+
id: "session-1",
126+
},
127+
() => loggerService,
128+
managerApi,
129+
secureChannel,
130+
DEVICE_SESSION_REFRESHER_DEFAULT_OPTIONS,
131+
);
132+
133+
deviceSession2 = deviceSessionStubBuilder(
134+
{
135+
connectedDevice: connectedDeviceStubBuilder({ id: "device-1" }),
136+
id: "session-2",
137+
},
138+
() => loggerService,
139+
managerApi,
140+
secureChannel,
141+
DEVICE_SESSION_REFRESHER_DEFAULT_OPTIONS,
142+
);
143+
sessionService.addDeviceSession(deviceSession1);
144+
sessionService.addDeviceSession(deviceSession2);
145+
expect(sessionService.getDeviceSessionsByDeviceId("device-1")).toEqual(
146+
Either.of([deviceSession1, deviceSession2]),
147+
);
148+
deviceSession1.close();
149+
deviceSession2.close();
150+
});
94151
});
95152

96153
it("should get all sessions", () => {
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { inject, injectable } from "inversify";
2-
import { Maybe } from "purify-ts";
2+
import { Either, Maybe } from "purify-ts";
33
import { Observable, ReplaySubject } from "rxjs";
44

55
import { LoggerPublisherService } from "@api/logger-publisher/service/LoggerPublisherService";
6+
import { DeviceId } from "@api/types";
67
import { DeviceSession } from "@internal/device-session/model/DeviceSession";
78
import { DeviceSessionNotFound } from "@internal/device-session/model/Errors";
89
import { DeviceSessionService } from "@internal/device-session/service/DeviceSessionService";
@@ -11,8 +12,8 @@ import { loggerTypes } from "@internal/logger-publisher/di/loggerTypes";
1112
@injectable()
1213
export class DefaultDeviceSessionService implements DeviceSessionService {
1314
private _sessions: DeviceSession[];
15+
private readonly _sessionsSubject: ReplaySubject<DeviceSession>;
1416
private readonly _logger: LoggerPublisherService;
15-
private _sessionsSubject: ReplaySubject<DeviceSession>;
1617

1718
constructor(
1819
@inject(loggerTypes.LoggerPublisherServiceFactory)
@@ -27,15 +28,14 @@ export class DefaultDeviceSessionService implements DeviceSessionService {
2728
return this._sessionsSubject.asObservable();
2829
}
2930

30-
addDeviceSession(deviceSession: DeviceSession) {
31+
addDeviceSession(deviceSession: DeviceSession): DeviceSessionService {
3132
const found = this._sessions.find((s) => s.id === deviceSession.id);
3233
if (found) {
3334
this._logger.warn("DeviceSession already exists", {
3435
data: { deviceSession },
3536
});
3637
return this;
3738
}
38-
3939
this._sessions.push(deviceSession);
4040
this._sessionsSubject.next(deviceSession);
4141
this._logger.info("DeviceSession added", {
@@ -44,36 +44,36 @@ export class DefaultDeviceSessionService implements DeviceSessionService {
4444
return this;
4545
}
4646

47-
removeDeviceSession(sessionId: string) {
47+
removeDeviceSession(sessionId: string): DeviceSessionService {
4848
const found = this._sessions.find((s) => s.id === sessionId);
4949
if (found) {
5050
found.close();
5151
this._sessions = this._sessions.filter((s) => s.id !== sessionId);
5252
this._logger.info("DeviceSession removed", { data: { sessionId } });
5353
return this;
5454
}
55-
5655
this._logger.warn("DeviceSession not found", { data: { sessionId } });
5756
return this;
5857
}
5958

60-
getDeviceSessionById(sessionId: string) {
61-
const deviceSession = Maybe.fromNullable(
59+
getDeviceSessionById(
60+
sessionId: string,
61+
): Either<DeviceSessionNotFound, DeviceSession> {
62+
return Maybe.fromNullable(
6263
this._sessions.find((s) => s.id === sessionId),
63-
);
64-
65-
return deviceSession.toEither(new DeviceSessionNotFound());
64+
).toEither(new DeviceSessionNotFound());
6665
}
6766

68-
getDeviceSessionByDeviceId(deviceId: string) {
69-
const deviceSession = Maybe.fromNullable(
70-
this._sessions.find((s) => s.connectedDevice.id === deviceId),
71-
);
72-
73-
return deviceSession.toEither(new DeviceSessionNotFound());
67+
getDeviceSessionsByDeviceId(
68+
deviceId: DeviceId,
69+
): Either<DeviceSessionNotFound, DeviceSession[]> {
70+
return Maybe.fromPredicate(
71+
({ length }) => length > 0,
72+
this._sessions.filter((s) => s.connectedDevice.id === deviceId),
73+
).toEither(new DeviceSessionNotFound());
7474
}
7575

76-
getDeviceSessions() {
76+
getDeviceSessions(): DeviceSession[] {
7777
return this._sessions;
7878
}
7979
}

β€Žpackages/device-management-kit/src/internal/device-session/service/DeviceSessionService.tsβ€Ž

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,47 @@ import { type Either } from "purify-ts";
22
import { type Observable } from "rxjs";
33

44
import { type DmkError } from "@api/Error";
5+
import { type DeviceId } from "@api/types";
56
import { type DeviceSession } from "@internal/device-session/model/DeviceSession";
67

78
export interface DeviceSessionService {
9+
/**
10+
* Add a device session.
11+
* @param deviceSession The device session to add.
12+
*/
813
addDeviceSession(deviceSession: DeviceSession): DeviceSessionService;
14+
15+
/**
16+
* Get a device session by its ID.
17+
* @param sessionId The ID of the session to retrieve.
18+
* @returns The device session or an error if not found.
19+
*/
920
getDeviceSessionById(sessionId: string): Either<DmkError, DeviceSession>;
10-
getDeviceSessionByDeviceId(deviceId: string): Either<DmkError, DeviceSession>;
21+
22+
/**
23+
* Get device sessions by device ID.
24+
* @param deviceId The ID of the device.
25+
* @returns The device sessions of the device or an error if not found.
26+
*/
27+
getDeviceSessionsByDeviceId(
28+
deviceId: DeviceId,
29+
): Either<DmkError, DeviceSession[]>;
30+
31+
/**
32+
* Remove a device session by its ID.
33+
* @param sessionId The ID of the session to remove.
34+
*/
1135
removeDeviceSession(sessionId: string): DeviceSessionService;
36+
37+
/**
38+
* Get all device sessions.
39+
* @returns An array of device sessions.
40+
*/
1241
getDeviceSessions(): DeviceSession[];
42+
43+
/**
44+
* Get an observable of device sessions.
45+
* @returns An observable of device sessions.
46+
*/
1347
get sessionsObs(): Observable<DeviceSession>;
1448
}

β€Žpackages/device-management-kit/src/internal/discovery/use-case/ConnectUseCase.tsβ€Ž

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,16 @@ export class ConnectUseCase {
7171
}
7272

7373
private handleDeviceDisconnect(deviceId: DeviceId) {
74-
const deviceSessionOrError =
75-
this._sessionService.getDeviceSessionByDeviceId(deviceId);
76-
deviceSessionOrError.map((deviceSession) => {
77-
this._sessionService.removeDeviceSession(deviceSession.id);
78-
});
74+
this._sessionService
75+
.getDeviceSessionsByDeviceId(deviceId)
76+
.ifRight((deviceSessions) => {
77+
deviceSessions.forEach((deviceSession) => {
78+
this._sessionService.removeDeviceSession(deviceSession.id);
79+
this._logger.info("Session removed", {
80+
data: { deviceId, sessionId: deviceSession.id },
81+
});
82+
});
83+
});
7984
}
8085

8186
async execute({

β€Žpackages/signer/signer-btc/package.jsonβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"license": "Apache-2.0",
55
"main": "lib/cjs/index.js",
66
"types": "lib/cjs/index.d.ts",
7-
"private": false,
7+
"private": true,
88
"exports": {
99
".": {
1010
"types": "./lib/types/index.d.ts",

β€Žpackages/signer/signer-eth/package.jsonβ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@ledgerhq/device-signer-kit-ethereum",
33
"version": "1.9.2",
4-
"private": false,
4+
"private": true,
55
"license": "Apache-2.0",
66
"exports": {
77
".": {
@@ -35,7 +35,7 @@
3535
"test:coverage": "vitest run --coverage"
3636
},
3737
"dependencies": {
38-
"@ledgerhq/signer-utils": "^1.1.0",
38+
"@ledgerhq/signer-utils": "workspace:*",
3939
"ethers": "catalog:",
4040
"inversify": "catalog:",
4141
"purify-ts": "catalog:",
@@ -56,7 +56,7 @@
5656
"ts-node": "catalog:"
5757
},
5858
"peerDependencies": {
59-
"@ledgerhq/context-module": "^1.10.0",
59+
"@ledgerhq/context-module": "workspace:*",
6060
"@ledgerhq/device-management-kit": "workspace:*"
6161
}
6262
}

0 commit comments

Comments
Β (0)