Skip to content

Commit c6d5239

Browse files
committed
♻️ (dmk): Handle PR comments
1 parent a9fa7bc commit c6d5239

File tree

3 files changed

+71
-87
lines changed

3 files changed

+71
-87
lines changed

packages/device-management-kit/src/internal/device-session/model/DeviceSession.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,17 @@ describe("DeviceSession", () => {
314314
// Advance timers to trigger timeout
315315
vi.advanceTimersByTime(1100);
316316

317+
let caughtError: Error | undefined;
317318
try {
318319
await sendPromise;
319-
} catch {
320-
// Expected to timeout
320+
} catch (error) {
321+
caughtError = error as Error;
321322
}
322323

323324
vi.useRealTimers();
324325

325326
// then
327+
expect(caughtError).toBeDefined();
326328
expect(mockIntentQueueService.enqueue).toHaveBeenCalled();
327329
});
328330
});
@@ -491,7 +493,7 @@ describe("DeviceSession", () => {
491493
execute: expect.any(Function),
492494
});
493495
expect(observable).toBeDefined();
494-
expect(cancel).toBe(mockCancel);
496+
expect(cancel).toBeTypeOf("function");
495497

496498
// Verify observable emits values
497499
const values: unknown[] = [];
@@ -508,6 +510,10 @@ describe("DeviceSession", () => {
508510
requiredUserInteraction: "SignTransaction",
509511
},
510512
]);
513+
514+
// Verify cancel is called
515+
cancel();
516+
expect(mockCancel).toHaveBeenCalled();
511517
});
512518

513519
it("should provide correct internal API to device action", () => {

packages/device-management-kit/src/internal/device-session/model/DeviceSession.ts

Lines changed: 61 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -227,51 +227,36 @@ export class DeviceSession {
227227
options: SendApduOptions = {
228228
isPolling: false,
229229
triggersDisconnection: false,
230+
abortTimeout: undefined,
230231
},
231232
): Promise<Either<DmkError, ApduResponse>> {
232-
const abortTimeout = (options as SendApduOptions).abortTimeout;
233-
234-
const sendApduPromise = async () => {
235-
this._logger.debug(`[exchange] => ${bufferToHexaString(rawApdu, false)}`);
236-
const result = await this._connectedDevice.sendApdu(
237-
rawApdu,
238-
options.triggersDisconnection,
239-
abortTimeout,
240-
);
241-
242-
result
243-
.ifRight((response: ApduResponse) => {
244-
this._logger.debug(
245-
`[exchange] <= ${bufferToHexaString(response.data, false)}${bufferToHexaString(response.statusCode, false)}`,
246-
);
247-
if (CommandUtils.isLockedDeviceResponse(response)) {
248-
this._sessionEventDispatcher.dispatch({
249-
eventName: SessionEvents.DEVICE_STATE_UPDATE_LOCKED,
250-
});
251-
} else {
252-
this._sessionEventDispatcher.dispatch({
253-
eventName: SessionEvents.DEVICE_STATE_UPDATE_CONNECTED,
254-
});
255-
}
256-
})
257-
.ifLeft(() => {
233+
this._logger.debug(`[exchange] => ${bufferToHexaString(rawApdu, false)}`);
234+
const result = await this._connectedDevice.sendApdu(
235+
rawApdu,
236+
options.triggersDisconnection,
237+
options.abortTimeout,
238+
);
239+
240+
return result
241+
.ifRight((response: ApduResponse) => {
242+
this._logger.debug(
243+
`[exchange] <= ${bufferToHexaString(response.data, false)}${bufferToHexaString(response.statusCode, false)}`,
244+
);
245+
if (CommandUtils.isLockedDeviceResponse(response)) {
246+
this._sessionEventDispatcher.dispatch({
247+
eventName: SessionEvents.DEVICE_STATE_UPDATE_LOCKED,
248+
});
249+
} else {
258250
this._sessionEventDispatcher.dispatch({
259-
eventName: SessionEvents.DEVICE_STATE_UPDATE_UNKNOWN,
251+
eventName: SessionEvents.DEVICE_STATE_UPDATE_CONNECTED,
260252
});
253+
}
254+
})
255+
.ifLeft(() => {
256+
this._sessionEventDispatcher.dispatch({
257+
eventName: SessionEvents.DEVICE_STATE_UPDATE_UNKNOWN,
261258
});
262-
return result;
263-
};
264-
265-
if (abortTimeout) {
266-
return Promise.race([
267-
sendApduPromise(),
268-
new Promise<never>((_, reject) => {
269-
setTimeout(() => reject(new SendApduTimeoutError()), abortTimeout);
270-
}),
271-
]);
272-
}
273-
274-
return sendApduPromise();
259+
});
275260
}
276261

277262
public sendCommand<Response, Args, ErrorStatusCodes>(
@@ -328,41 +313,28 @@ export class DeviceSession {
328313
command: Command<Response, Args, ErrorStatusCodes>,
329314
abortTimeout?: number,
330315
): Promise<CommandResult<Response, ErrorStatusCodes>> {
331-
const sendCommandPromise = async () => {
332-
const apdu = command.getApdu();
333-
334-
const response = await this._unsafeInternalSendApdu(apdu.getRawApdu(), {
335-
isPolling: false,
336-
triggersDisconnection: command.triggersDisconnection ?? false,
337-
abortTimeout,
338-
});
339-
340-
return response.caseOf({
341-
Left: (err) => {
342-
this._logger.error("[sendCommand] error", { data: { err } });
343-
throw err;
344-
},
345-
Right: (r) => {
346-
const result = command.parseResponse(
347-
r,
348-
this._connectedDevice.deviceModel.id,
349-
);
350-
this._logger.debug("[sendCommand] result", { data: { result } });
351-
return result;
352-
},
353-
});
354-
};
316+
const apdu = command.getApdu();
355317

356-
if (abortTimeout) {
357-
return Promise.race([
358-
sendCommandPromise(),
359-
new Promise<never>((_, reject) => {
360-
setTimeout(() => reject(new SendCommandTimeoutError()), abortTimeout);
361-
}),
362-
]);
363-
}
318+
const response = await this._unsafeInternalSendApdu(apdu.getRawApdu(), {
319+
isPolling: false,
320+
triggersDisconnection: command.triggersDisconnection ?? false,
321+
abortTimeout,
322+
});
364323

365-
return sendCommandPromise();
324+
return response.caseOf({
325+
Left: (err) => {
326+
this._logger.error("[sendCommand] error", { data: { err } });
327+
throw err;
328+
},
329+
Right: (r) => {
330+
const result = command.parseResponse(
331+
r,
332+
this._connectedDevice.deviceModel.id,
333+
);
334+
this._logger.debug("[sendCommand] result", { data: { result } });
335+
return result;
336+
},
337+
});
366338
}
367339

368340
public executeDeviceAction<
@@ -388,19 +360,25 @@ export class DeviceSession {
388360
>(
389361
deviceAction: DeviceAction<Output, Input, E, IntermediateValue>,
390362
): ExecuteDeviceActionReturnType<Output, E, IntermediateValue> {
391-
const { observable: o, cancel: c } = this._intentQueueService.enqueue({
392-
type: "device-action",
393-
execute: () => {
394-
const { observable } =
395-
this._unsafeInternalExecuteDeviceAction(deviceAction);
396-
// The queue service will handle the subscription lifecycle
397-
return observable;
398-
},
399-
});
363+
let deviceActionCancel: (() => void) | undefined;
364+
365+
const { observable: o, cancel: queueCancel } =
366+
this._intentQueueService.enqueue({
367+
type: "device-action",
368+
execute: () => {
369+
const { observable, cancel } =
370+
this._unsafeInternalExecuteDeviceAction(deviceAction);
371+
deviceActionCancel = cancel;
372+
return observable;
373+
},
374+
});
400375

401376
return {
402377
observable: o,
403-
cancel: c,
378+
cancel: () => {
379+
deviceActionCancel?.();
380+
queueCancel();
381+
},
404382
};
405383
}
406384

packages/device-management-kit/src/internal/device-session/model/DeviceSessionStateHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class DeviceSessionStateHandler {
9595
this._pendingDeviceStatus = DeviceStatus.CONNECTED;
9696
return;
9797
case SessionEvents.NEW_STATE: {
98-
// On new state, if an intent is successfull,
98+
// On new state, if an intent is successful,
9999
// we should have a DEVICE_STATE_UPDATE_LOCKED or DEVICE_STATE_UPDATE_CONNECTED as pending status event
100100
// If not, we should still have a BUSY status as fallback waiting for the transport to disconnect
101101
const newDeviceStatus = this._pendingDeviceStatus;

0 commit comments

Comments
 (0)