@ledgerhq/device-management-kit 0.0.0-z-intent-queue-7-20251204111630 → 0.0.0-zzz-solana-20251204140055
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/src/api/DeviceManagementKit.js +1 -1
- package/lib/cjs/src/api/DeviceManagementKit.js.map +2 -2
- package/lib/cjs/src/api/device-action/DeviceAction.js +1 -1
- package/lib/cjs/src/api/device-action/DeviceAction.js.map +1 -1
- package/lib/cjs/src/api/device-action/__test-utils__/makeInternalApi.js +1 -1
- package/lib/cjs/src/api/device-action/__test-utils__/makeInternalApi.js.map +3 -3
- package/lib/cjs/src/api/logger-subscriber/service/WebLogsExporterLogger.test.js +1 -1
- package/lib/cjs/src/api/logger-subscriber/service/WebLogsExporterLogger.test.js.map +2 -2
- package/lib/cjs/src/api/secure-channel/task/ConnectToSecureChannelTask.js +1 -1
- package/lib/cjs/src/api/secure-channel/task/ConnectToSecureChannelTask.js.map +3 -3
- package/lib/cjs/src/api/transport/model/Errors.js +1 -1
- package/lib/cjs/src/api/transport/model/Errors.js.map +3 -3
- package/lib/cjs/src/internal/device-session/di/deviceSessionModule.js +1 -1
- package/lib/cjs/src/internal/device-session/di/deviceSessionModule.js.map +3 -3
- package/lib/cjs/src/internal/device-session/di/deviceSessionTypes.js +1 -1
- package/lib/cjs/src/internal/device-session/di/deviceSessionTypes.js.map +2 -2
- package/lib/cjs/src/internal/device-session/model/DeviceSession.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSession.js.map +3 -3
- package/lib/cjs/src/internal/device-session/model/DeviceSessionEventDispatcher.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSessionEventDispatcher.js.map +2 -2
- package/lib/cjs/src/internal/device-session/model/DeviceSessionRefresher.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSessionRefresher.js.map +3 -3
- package/lib/cjs/src/internal/device-session/model/DeviceSessionRefresher.test.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSessionRefresher.test.js.map +2 -2
- package/lib/cjs/src/internal/device-session/model/DeviceSessionStateHandler.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSessionStateHandler.js.map +3 -3
- package/lib/cjs/src/internal/device-session/model/DeviceSessionStateHandler.test.js +1 -1
- package/lib/cjs/src/internal/device-session/model/DeviceSessionStateHandler.test.js.map +2 -2
- package/lib/cjs/src/internal/device-session/service/MutexService.js +2 -0
- package/lib/cjs/src/internal/device-session/service/MutexService.js.map +7 -0
- package/lib/cjs/src/internal/device-session/service/MutexService.test.js +2 -0
- package/lib/cjs/src/internal/device-session/service/MutexService.test.js.map +7 -0
- package/lib/cjs/src/internal/discovery/use-case/ConnectUseCase.test.js +1 -1
- package/lib/cjs/src/internal/discovery/use-case/ConnectUseCase.test.js.map +3 -3
- package/lib/cjs/src/internal/send/use-case/SendApduUseCase.test.js +1 -1
- package/lib/cjs/src/internal/send/use-case/SendApduUseCase.test.js.map +3 -3
- package/lib/esm/package.json +1 -1
- package/lib/esm/src/api/DeviceManagementKit.js +1 -1
- package/lib/esm/src/api/DeviceManagementKit.js.map +2 -2
- package/lib/esm/src/api/device-action/__test-utils__/makeInternalApi.js +1 -1
- package/lib/esm/src/api/device-action/__test-utils__/makeInternalApi.js.map +3 -3
- package/lib/esm/src/api/logger-subscriber/service/WebLogsExporterLogger.test.js +1 -1
- package/lib/esm/src/api/logger-subscriber/service/WebLogsExporterLogger.test.js.map +3 -3
- package/lib/esm/src/api/secure-channel/task/ConnectToSecureChannelTask.js +1 -1
- package/lib/esm/src/api/secure-channel/task/ConnectToSecureChannelTask.js.map +3 -3
- package/lib/esm/src/api/transport/model/Errors.js +1 -1
- package/lib/esm/src/api/transport/model/Errors.js.map +3 -3
- package/lib/esm/src/internal/device-session/di/deviceSessionModule.js +1 -1
- package/lib/esm/src/internal/device-session/di/deviceSessionModule.js.map +3 -3
- package/lib/esm/src/internal/device-session/di/deviceSessionTypes.js +1 -1
- package/lib/esm/src/internal/device-session/di/deviceSessionTypes.js.map +2 -2
- package/lib/esm/src/internal/device-session/model/DeviceSession.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSession.js.map +3 -3
- package/lib/esm/src/internal/device-session/model/DeviceSessionEventDispatcher.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSessionEventDispatcher.js.map +2 -2
- package/lib/esm/src/internal/device-session/model/DeviceSessionRefresher.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSessionRefresher.js.map +3 -3
- package/lib/esm/src/internal/device-session/model/DeviceSessionRefresher.test.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSessionRefresher.test.js.map +2 -2
- package/lib/esm/src/internal/device-session/model/DeviceSessionStateHandler.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSessionStateHandler.js.map +3 -3
- package/lib/esm/src/internal/device-session/model/DeviceSessionStateHandler.test.js +1 -1
- package/lib/esm/src/internal/device-session/model/DeviceSessionStateHandler.test.js.map +2 -2
- package/lib/esm/src/internal/device-session/service/MutexService.js +2 -0
- package/lib/esm/src/internal/device-session/service/MutexService.js.map +7 -0
- package/lib/esm/src/internal/device-session/service/MutexService.test.js +2 -0
- package/lib/esm/src/internal/device-session/service/MutexService.test.js.map +7 -0
- package/lib/esm/src/internal/discovery/use-case/ConnectUseCase.test.js +1 -1
- package/lib/esm/src/internal/discovery/use-case/ConnectUseCase.test.js.map +3 -3
- package/lib/esm/src/internal/send/use-case/SendApduUseCase.test.js +1 -1
- package/lib/esm/src/internal/send/use-case/SendApduUseCase.test.js.map +3 -3
- package/lib/types/src/api/DeviceManagementKit.d.ts +0 -10
- package/lib/types/src/api/DeviceManagementKit.d.ts.map +1 -1
- package/lib/types/src/api/device-action/DeviceAction.d.ts +1 -0
- package/lib/types/src/api/device-action/DeviceAction.d.ts.map +1 -1
- package/lib/types/src/api/device-action/__test-utils__/makeInternalApi.d.ts.map +1 -1
- package/lib/types/src/api/secure-channel/task/ConnectToSecureChannelTask.d.ts.map +1 -1
- package/lib/types/src/api/transport/model/Errors.d.ts +0 -5
- package/lib/types/src/api/transport/model/Errors.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/di/deviceSessionModule.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/di/deviceSessionTypes.d.ts +0 -1
- package/lib/types/src/internal/device-session/di/deviceSessionTypes.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/model/DeviceSession.d.ts +2 -12
- package/lib/types/src/internal/device-session/model/DeviceSession.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/model/DeviceSessionEventDispatcher.d.ts +1 -3
- package/lib/types/src/internal/device-session/model/DeviceSessionEventDispatcher.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/model/DeviceSessionRefresher.d.ts +1 -0
- package/lib/types/src/internal/device-session/model/DeviceSessionRefresher.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/model/DeviceSessionStateHandler.d.ts +0 -1
- package/lib/types/src/internal/device-session/model/DeviceSessionStateHandler.d.ts.map +1 -1
- package/lib/types/src/internal/device-session/service/MutexService.d.ts +6 -0
- package/lib/types/src/internal/device-session/service/MutexService.d.ts.map +1 -0
- package/lib/types/src/internal/device-session/service/MutexService.test.d.ts +2 -0
- package/lib/types/src/internal/device-session/service/MutexService.test.d.ts.map +1 -0
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/lib/cjs/src/internal/device-session/model/DeviceSession.test.js +0 -2
- package/lib/cjs/src/internal/device-session/model/DeviceSession.test.js.map +0 -7
- package/lib/cjs/src/internal/device-session/service/IntentQueueService.js +0 -2
- package/lib/cjs/src/internal/device-session/service/IntentQueueService.js.map +0 -7
- package/lib/cjs/src/internal/device-session/service/IntentQueueService.test.js +0 -2
- package/lib/cjs/src/internal/device-session/service/IntentQueueService.test.js.map +0 -7
- package/lib/cjs/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.js +0 -2
- package/lib/cjs/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.js.map +0 -7
- package/lib/esm/src/internal/device-session/model/DeviceSession.test.js +0 -2
- package/lib/esm/src/internal/device-session/model/DeviceSession.test.js.map +0 -7
- package/lib/esm/src/internal/device-session/service/IntentQueueService.js +0 -2
- package/lib/esm/src/internal/device-session/service/IntentQueueService.js.map +0 -7
- package/lib/esm/src/internal/device-session/service/IntentQueueService.test.js +0 -2
- package/lib/esm/src/internal/device-session/service/IntentQueueService.test.js.map +0 -7
- package/lib/esm/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.js +0 -2
- package/lib/esm/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.js.map +0 -7
- package/lib/types/src/internal/device-session/model/DeviceSession.test.d.ts +0 -2
- package/lib/types/src/internal/device-session/model/DeviceSession.test.d.ts.map +0 -1
- package/lib/types/src/internal/device-session/service/IntentQueueService.d.ts +0 -101
- package/lib/types/src/internal/device-session/service/IntentQueueService.d.ts.map +0 -1
- package/lib/types/src/internal/device-session/service/IntentQueueService.test.d.ts +0 -2
- package/lib/types/src/internal/device-session/service/IntentQueueService.test.d.ts.map +0 -1
- package/lib/types/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.d.ts +0 -19
- package/lib/types/src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"ts-node": "10.9.2",
|
|
23
23
|
"@ledgerhq/eslint-config-dsdk": "^0.0.2",
|
|
24
24
|
"@ledgerhq/ldmk-tool": "^0.0.1",
|
|
25
|
-
"@ledgerhq/prettier-config-dsdk": "^0.0.2",
|
|
26
25
|
"@ledgerhq/tsconfig-dsdk": "^1.0.1",
|
|
27
|
-
"@ledgerhq/vitest-config-dmk": "^0.0.0"
|
|
26
|
+
"@ledgerhq/vitest-config-dmk": "^0.0.0",
|
|
27
|
+
"@ledgerhq/prettier-config-dsdk": "^0.0.2"
|
|
28
28
|
},
|
|
29
29
|
"exports": {
|
|
30
30
|
".": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"type": "git",
|
|
48
48
|
"url": "https://github.com/LedgerHQ/device-sdk-ts.git"
|
|
49
49
|
},
|
|
50
|
-
"version": "0.0.0-
|
|
50
|
+
"version": "0.0.0-zzz-solana-20251204140055",
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "pnpm ldmk-tool build --entryPoints index.ts,src/**/*.ts --tsconfig tsconfig.prod.json",
|
|
53
53
|
"dev": "concurrently \"pnpm watch:builds\" \"pnpm watch:types\"",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var y=require("purify-ts"),r=require("rxjs"),m=require("rxjs/operators"),D=require("../../../api/command/model/CommandResult"),S=require("../../../api/device/DeviceStatus"),h=require("../../../api/device-session/DeviceSessionState"),C=require("../../../api/transport/model/TransportConnectedDevice.stub"),g=require("../../logger-publisher/service/DefaultLoggerPublisherService"),v=require("./DeviceSession");describe("DeviceSession",()=>{let e,k,u,d,l,o,p,b;const a=(0,C.connectedDeviceStubBuilder)();beforeEach(()=>{k=new g.DefaultLoggerPublisherService([],"device-session-test"),u=vi.fn(()=>k),d={getAppList:vi.fn(),getAppsByHash:vi.fn(),getCurrentFirmware:vi.fn(),getLatestFirmware:vi.fn()},l={genuineCheck:vi.fn(),listInstalledApps:vi.fn(),updateMcu:vi.fn(),updateFirmware:vi.fn(),installApp:vi.fn(),uninstallApp:vi.fn()},o={enqueue:vi.fn().mockReturnValue({observable:(0,r.of)(null).pipe((0,m.delay)(1)),cancel:vi.fn()})},p=()=>o,b={isRefresherDisabled:!0}}),afterEach(()=>{e?.close(),vi.restoreAllMocks()}),describe("constructor",()=>{it("should create a device session with default id",()=>{e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p),expect(e).toBeDefined(),expect(e.id).toBeDefined(),expect(e.connectedDevice).toBe(a)}),it("should create a device session with custom id",()=>{const t="custom-session-id";e=new v.DeviceSession({connectedDevice:a,id:t},u,d,l,b,p),expect(e.id).toBe(t)})}),describe("initialiseSession",()=>{it("should successfully initialize session",()=>{e=new v.DeviceSession({connectedDevice:a},u,d,l,{isRefresherDisabled:!1,pollingInterval:1e3},p);const t=vi.spyOn(e._deviceSessionRefresher,"startRefresher");e.initialiseSession(),expect(t).toHaveBeenCalled()})}),describe("getters",()=>{beforeEach(()=>{e=new v.DeviceSession({connectedDevice:a,id:"test-id"},u,d,l,b,p)}),it("should return session id",()=>{expect(e.id).toBe("test-id")}),it("should return connected device",()=>{expect(e.connectedDevice).toBe(a)}),it("should return state as observable",async()=>{const t=e.state;await new Promise(s=>{t.pipe((0,m.take)(1)).subscribe(n=>{expect(n.sessionStateType).toBe(h.DeviceSessionStateType.Connected),expect(n.deviceStatus).toBe(S.DeviceStatus.CONNECTED),s()})})})}),describe("getDeviceSessionState and setDeviceSessionState",()=>{beforeEach(()=>{e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p)}),it("should get current device session state",()=>{const t=e.getDeviceSessionState();expect(t.sessionStateType).toBe(h.DeviceSessionStateType.Connected),expect(t.deviceStatus).toBe(S.DeviceStatus.CONNECTED)}),it("should set device session state",async()=>{const t={sessionStateType:h.DeviceSessionStateType.ReadyWithoutSecureChannel,deviceStatus:S.DeviceStatus.LOCKED,deviceModelId:a.deviceModel.id,currentApp:{name:"Test",version:"1.0.0"},installedApps:[],isSecureConnectionAllowed:!1};await new Promise(s=>{let n=!1;const c=e.state.subscribe(i=>{i.sessionStateType===h.DeviceSessionStateType.ReadyWithoutSecureChannel?(expect(i).toMatchObject({sessionStateType:h.DeviceSessionStateType.ReadyWithoutSecureChannel,deviceStatus:S.DeviceStatus.LOCKED,deviceModelId:a.deviceModel.id}),c.unsubscribe(),s()):n||(n=!0)});e.setDeviceSessionState(t)})})}),describe("sendApdu",()=>{let t,s;beforeEach(()=>{t=new Uint8Array([224,1,0,0]),s={data:new Uint8Array([1,2]),statusCode:new Uint8Array([144,0])},e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p)}),it("should successfully send APDU",async()=>{const n=(0,r.of)((0,y.Right)(s)).pipe((0,m.delay)(1));o.enqueue.mockReturnValue({observable:n,cancel:vi.fn()});const c=await e.sendApdu(t);expect(o.enqueue).toHaveBeenCalledWith({type:"send-apdu",execute:expect.any(Function)}),expect(c.isRight()).toBe(!0),c.ifRight(i=>{expect(i).toEqual(s)})}),it("should handle APDU send error",async()=>{const n={_tag:"SendApduError"},c=(0,r.of)((0,y.Left)(n)).pipe((0,m.delay)(1));o.enqueue.mockReturnValue({observable:c,cancel:vi.fn()});const i=await e.sendApdu(t);expect(i.isLeft()).toBe(!0),i.ifLeft(f=>{expect(f).toEqual(n)})}),it("should handle APDU timeout",async()=>{const n=vi.fn(),c=new r.Subject;o.enqueue.mockReturnValue({observable:c.asObservable(),cancel:n}),vi.useFakeTimers();const i=e.sendApdu(t,{abortTimeout:1e3});vi.advanceTimersByTime(1100);let f;try{await i}catch(x){f=x}vi.useRealTimers(),expect(f).toBeDefined(),expect(o.enqueue).toHaveBeenCalled()})}),describe("sendCommand",()=>{let t,s;beforeEach(()=>{s={status:D.CommandResultStatus.Success,data:{test:"data"}},t={getApdu:vi.fn().mockReturnValue({getRawApdu:()=>new Uint8Array([224,1,0,0])}),parseResponse:vi.fn().mockReturnValue(s),triggersDisconnection:!1},e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p)}),it("should successfully send command",async()=>{const n=(0,r.of)(s).pipe((0,m.delay)(1));o.enqueue.mockReturnValue({observable:n,cancel:vi.fn()});const c=await e.sendCommand(t);expect(o.enqueue).toHaveBeenCalledWith({type:"send-command",execute:expect.any(Function)}),expect(c).toEqual(s)}),it("should handle command timeout",async()=>{const n=vi.fn(),c=new r.Subject;o.enqueue.mockReturnValue({observable:c.asObservable(),cancel:n}),vi.useFakeTimers();const i=e.sendCommand(t,1e3);vi.advanceTimersByTime(1100);try{await i}catch{}vi.useRealTimers(),expect(o.enqueue).toHaveBeenCalled()}),it("should handle command error",async()=>{const n=new Error("Command failed"),c=(0,r.throwError)(()=>n);o.enqueue.mockReturnValue({observable:c,cancel:vi.fn()}),await expect(e.sendCommand(t)).rejects.toThrow("Command failed")})}),describe("executeDeviceAction",()=>{let t;beforeEach(()=>{const s=(0,r.of)({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe((0,m.delay)(1));t={_execute:vi.fn().mockReturnValue({observable:s})},e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p)}),it("should execute device action",async()=>{const s=(0,r.of)({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe((0,m.delay)(1)),n=vi.fn();o.enqueue.mockReturnValue({observable:s,cancel:n});const{observable:c,cancel:i}=e.executeDeviceAction(t);expect(o.enqueue).toHaveBeenCalledWith({type:"device-action",execute:expect.any(Function)}),expect(c).toBeDefined(),expect(i).toBeTypeOf("function");const f=[];await new Promise(x=>{c.subscribe({next:A=>f.push(A),complete:()=>x()})}),expect(f).toEqual([{intermediateValue:"test",requiredUserInteraction:"SignTransaction"}]),i(),expect(n).toHaveBeenCalled()}),it("should provide correct internal API to device action",()=>{const s=(0,r.of)({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe((0,m.delay)(1));o.enqueue.mockImplementation(n=>(n.execute(),{observable:s,cancel:vi.fn()})),e.executeDeviceAction(t),expect(t._execute).toHaveBeenCalledWith({sendApdu:expect.any(Function),sendCommand:expect.any(Function),getDeviceModel:expect.any(Function),getDeviceSessionState:expect.any(Function),getDeviceSessionStateObservable:expect.any(Function),setDeviceSessionState:expect.any(Function),getManagerApiService:expect.any(Function),getSecureChannelService:expect.any(Function)})}),it("should allow cancelling device action",()=>{const s=vi.fn(),n=new r.Subject;o.enqueue.mockReturnValue({observable:n.asObservable(),cancel:s});const{cancel:c}=e.executeDeviceAction(t);c(),expect(s).toHaveBeenCalled()})}),describe("close",()=>{it("should close the session and update device status",()=>{e=new v.DeviceSession({connectedDevice:a},u,d,l,b,p);let t=!1;e.state.subscribe({complete:()=>{t=!0}}),e.close();const s=e.getDeviceSessionState();expect(s.deviceStatus).toBe(S.DeviceStatus.NOT_CONNECTED),expect(t).toBe(!0)})})});
|
|
2
|
-
//# sourceMappingURL=DeviceSession.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/model/DeviceSession.test.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { Left, Right } from \"purify-ts\";\nimport { of, Subject, throwError } from \"rxjs\";\nimport { delay, take } from \"rxjs/operators\";\nimport { type Mocked } from \"vitest\";\n\nimport { type Command } from \"@api/command/Command\";\nimport {\n type CommandResult,\n CommandResultStatus,\n} from \"@api/command/model/CommandResult\";\nimport { DeviceStatus } from \"@api/device/DeviceStatus\";\nimport { type DeviceAction } from \"@api/device-action/DeviceAction\";\nimport { type ApduResponse } from \"@api/device-session/ApduResponse\";\nimport { DeviceSessionStateType } from \"@api/device-session/DeviceSessionState\";\nimport { type DmkError } from \"@api/Error\";\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { connectedDeviceStubBuilder } from \"@api/transport/model/TransportConnectedDevice.stub\";\nimport { type IntentQueueService } from \"@internal/device-session/service/IntentQueueService\";\nimport { DefaultLoggerPublisherService } from \"@internal/logger-publisher/service/DefaultLoggerPublisherService\";\nimport { type ManagerApiService } from \"@internal/manager-api/service/ManagerApiService\";\nimport { type SecureChannelService } from \"@internal/secure-channel/service/SecureChannelService\";\n\nimport {\n DeviceSession,\n type DeviceSessionRefresherOptions,\n} from \"./DeviceSession\";\n\ndescribe(\"DeviceSession\", () => {\n let deviceSession: DeviceSession;\n let mockLogger: LoggerPublisherService;\n let mockLoggerFactory: ReturnType<typeof vi.fn>;\n let mockManagerApi: Mocked<ManagerApiService>;\n let mockSecureChannel: Mocked<SecureChannelService>;\n let mockIntentQueueService: Mocked<IntentQueueService>;\n let mockIntentQueueServiceFactory: () => IntentQueueService;\n let refresherOptions: DeviceSessionRefresherOptions;\n const mockConnectedDevice = connectedDeviceStubBuilder();\n\n beforeEach(() => {\n // Setup logger\n mockLogger = new DefaultLoggerPublisherService([], \"device-session-test\");\n mockLoggerFactory = vi.fn(() => mockLogger);\n\n // Setup mocks\n mockManagerApi = {\n getAppList: vi.fn(),\n getAppsByHash: vi.fn(),\n getCurrentFirmware: vi.fn(),\n getLatestFirmware: vi.fn(),\n } as unknown as Mocked<ManagerApiService>;\n\n mockSecureChannel = {\n genuineCheck: vi.fn(),\n listInstalledApps: vi.fn(),\n updateMcu: vi.fn(),\n updateFirmware: vi.fn(),\n installApp: vi.fn(),\n uninstallApp: vi.fn(),\n } as unknown as Mocked<SecureChannelService>;\n\n // Setup intent queue service with default mock\n mockIntentQueueService = {\n enqueue: vi.fn().mockReturnValue({\n observable: of(null).pipe(delay(1)),\n cancel: vi.fn(),\n }),\n } as unknown as Mocked<IntentQueueService>;\n\n mockIntentQueueServiceFactory = () => mockIntentQueueService;\n\n refresherOptions = {\n isRefresherDisabled: true,\n };\n });\n\n afterEach(() => {\n deviceSession?.close();\n vi.restoreAllMocks();\n });\n\n describe(\"constructor\", () => {\n it(\"should create a device session with default id\", () => {\n // when\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n // then\n expect(deviceSession).toBeDefined();\n expect(deviceSession.id).toBeDefined();\n expect(deviceSession.connectedDevice).toBe(mockConnectedDevice);\n });\n\n it(\"should create a device session with custom id\", () => {\n // given\n const customId = \"custom-session-id\";\n\n // when\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice, id: customId },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n // then\n expect(deviceSession.id).toBe(customId);\n });\n });\n\n describe(\"initialiseSession\", () => {\n it(\"should successfully initialize session\", () => {\n // given\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n { isRefresherDisabled: false, pollingInterval: 1000 },\n mockIntentQueueServiceFactory,\n );\n\n const mockRefresherStartSpy = vi.spyOn(\n deviceSession[\"_deviceSessionRefresher\"],\n \"startRefresher\",\n );\n\n // when\n deviceSession.initialiseSession();\n\n // then\n expect(mockRefresherStartSpy).toHaveBeenCalled();\n });\n });\n\n describe(\"getters\", () => {\n beforeEach(() => {\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice, id: \"test-id\" },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should return session id\", () => {\n expect(deviceSession.id).toBe(\"test-id\");\n });\n\n it(\"should return connected device\", () => {\n expect(deviceSession.connectedDevice).toBe(mockConnectedDevice);\n });\n\n it(\"should return state as observable\", async () => {\n const stateObservable = deviceSession.state;\n\n await new Promise<void>((resolve) => {\n stateObservable.pipe(take(1)).subscribe((state) => {\n expect(state.sessionStateType).toBe(DeviceSessionStateType.Connected);\n expect(state.deviceStatus).toBe(DeviceStatus.CONNECTED);\n resolve();\n });\n });\n });\n });\n\n describe(\"getDeviceSessionState and setDeviceSessionState\", () => {\n beforeEach(() => {\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should get current device session state\", () => {\n // when\n const state = deviceSession.getDeviceSessionState();\n\n // then\n expect(state.sessionStateType).toBe(DeviceSessionStateType.Connected);\n expect(state.deviceStatus).toBe(DeviceStatus.CONNECTED);\n });\n\n it(\"should set device session state\", async () => {\n // given\n const newState = {\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n deviceModelId: mockConnectedDevice.deviceModel.id,\n currentApp: { name: \"Test\", version: \"1.0.0\" },\n installedApps: [],\n isSecureConnectionAllowed: false,\n };\n\n // when\n await new Promise<void>((resolve) => {\n let subscriptionStarted = false;\n const subscription = deviceSession.state.subscribe((state) => {\n if (\n state.sessionStateType ===\n DeviceSessionStateType.ReadyWithoutSecureChannel\n ) {\n expect(state).toMatchObject({\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n deviceModelId: mockConnectedDevice.deviceModel.id,\n });\n subscription.unsubscribe();\n resolve();\n } else if (!subscriptionStarted) {\n subscriptionStarted = true;\n }\n });\n\n deviceSession.setDeviceSessionState(newState);\n });\n });\n });\n\n describe(\"sendApdu\", () => {\n let mockApdu: Uint8Array;\n let mockResponse: ApduResponse;\n\n beforeEach(() => {\n mockApdu = new Uint8Array([0xe0, 0x01, 0x00, 0x00]);\n mockResponse = {\n data: new Uint8Array([0x01, 0x02]),\n statusCode: new Uint8Array([0x90, 0x00]),\n };\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should successfully send APDU\", async () => {\n // given\n const mockObservable = of(Right(mockResponse)).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendApdu(mockApdu);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"send-apdu\",\n execute: expect.any(Function),\n });\n expect(result.isRight()).toBe(true);\n result.ifRight((response) => {\n expect(response).toEqual(mockResponse);\n });\n });\n\n it(\"should handle APDU send error\", async () => {\n // given\n const error = { _tag: \"SendApduError\" } as DmkError;\n const mockObservable = of(Left(error)).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendApdu(mockApdu);\n\n // then\n expect(result.isLeft()).toBe(true);\n result.ifLeft((err) => {\n expect(err).toEqual(error);\n });\n });\n\n it(\"should handle APDU timeout\", async () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n vi.useFakeTimers();\n\n // when\n const sendPromise = deviceSession.sendApdu(mockApdu, {\n abortTimeout: 1000,\n });\n\n // Advance timers to trigger timeout\n vi.advanceTimersByTime(1100);\n\n let caughtError: Error | undefined;\n try {\n await sendPromise;\n } catch (error) {\n caughtError = error as Error;\n }\n\n vi.useRealTimers();\n\n // then\n expect(caughtError).toBeDefined();\n expect(mockIntentQueueService.enqueue).toHaveBeenCalled();\n });\n });\n\n describe(\"sendCommand\", () => {\n type TestData = { test: string };\n type TestArgs = Record<string, never>;\n type TestErrorCodes = number;\n\n let mockCommand: Mocked<Command<TestData, TestArgs, TestErrorCodes>>;\n let mockCommandResult: CommandResult<TestData, TestErrorCodes>;\n\n beforeEach(() => {\n mockCommandResult = {\n status: CommandResultStatus.Success,\n data: { test: \"data\" },\n };\n\n mockCommand = {\n getApdu: vi.fn().mockReturnValue({\n getRawApdu: () => new Uint8Array([0xe0, 0x01, 0x00, 0x00]),\n }),\n parseResponse: vi.fn().mockReturnValue(mockCommandResult),\n triggersDisconnection: false,\n } as unknown as Mocked<Command<TestData, TestArgs, TestErrorCodes>>;\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should successfully send command\", async () => {\n // given\n const mockObservable = of(mockCommandResult).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendCommand(mockCommand);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"send-command\",\n execute: expect.any(Function),\n });\n expect(result).toEqual(mockCommandResult);\n });\n\n it(\"should handle command timeout\", async () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n vi.useFakeTimers();\n\n // when\n const commandPromise = deviceSession.sendCommand(mockCommand, 1000);\n\n // Advance timers to trigger timeout\n vi.advanceTimersByTime(1100);\n\n try {\n await commandPromise;\n } catch {\n // Expected to timeout\n }\n\n vi.useRealTimers();\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalled();\n });\n\n it(\"should handle command error\", async () => {\n // given\n const error = new Error(\"Command failed\");\n const mockObservable = throwError(() => error);\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when/then\n await expect(deviceSession.sendCommand(mockCommand)).rejects.toThrow(\n \"Command failed\",\n );\n });\n });\n\n describe(\"executeDeviceAction\", () => {\n type TestOutput = { result: string };\n type TestInput = { input: string };\n type TestError = DmkError;\n type TestIntermediateValue = {\n intermediateValue: string;\n requiredUserInteraction:\n | \"UnlockDevice\"\n | \"ConfirmOpenApp\"\n | \"ConfirmCloseApp\"\n | \"AllowListAccess\"\n | \"AllowSecureChannelConnection\"\n | \"AllowedDataRecording\"\n | \"SignTransaction\";\n };\n\n let mockDeviceAction: Mocked<\n DeviceAction<TestOutput, TestInput, TestError, TestIntermediateValue>\n >;\n\n beforeEach(() => {\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n\n mockDeviceAction = {\n _execute: vi.fn().mockReturnValue({\n observable: mockActionObservable,\n }),\n } as unknown as Mocked<\n DeviceAction<TestOutput, TestInput, TestError, TestIntermediateValue>\n >;\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should execute device action\", async () => {\n // given\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n const mockCancel = vi.fn();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockActionObservable,\n cancel: mockCancel,\n });\n\n // when\n const { observable, cancel } =\n deviceSession.executeDeviceAction(mockDeviceAction);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"device-action\",\n execute: expect.any(Function),\n });\n expect(observable).toBeDefined();\n expect(cancel).toBeTypeOf(\"function\");\n\n // Verify observable emits values\n const values: unknown[] = [];\n await new Promise<void>((resolve) => {\n observable.subscribe({\n next: (value) => values.push(value),\n complete: () => resolve(),\n });\n });\n\n expect(values).toEqual([\n {\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\",\n },\n ]);\n\n // Verify cancel is called\n cancel();\n expect(mockCancel).toHaveBeenCalled();\n });\n\n it(\"should provide correct internal API to device action\", () => {\n // given\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n\n mockIntentQueueService.enqueue.mockImplementation((intent) => {\n // Execute the device action to verify the internal API\n void intent.execute();\n\n return {\n observable: mockActionObservable,\n cancel: vi.fn(),\n };\n });\n\n // when\n deviceSession.executeDeviceAction(mockDeviceAction);\n\n // then\n expect(mockDeviceAction._execute).toHaveBeenCalledWith({\n sendApdu: expect.any(Function),\n sendCommand: expect.any(Function),\n getDeviceModel: expect.any(Function),\n getDeviceSessionState: expect.any(Function),\n getDeviceSessionStateObservable: expect.any(Function),\n setDeviceSessionState: expect.any(Function),\n getManagerApiService: expect.any(Function),\n getSecureChannelService: expect.any(Function),\n });\n });\n\n it(\"should allow cancelling device action\", () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n // when\n const { cancel } = deviceSession.executeDeviceAction(mockDeviceAction);\n cancel();\n\n // then\n expect(mockCancel).toHaveBeenCalled();\n });\n });\n\n describe(\"close\", () => {\n it(\"should close the session and update device status\", () => {\n // given\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n let isComplete = false;\n deviceSession.state.subscribe({\n complete: () => {\n isComplete = true;\n },\n });\n\n // when\n deviceSession.close();\n\n // then\n const state = deviceSession.getDeviceSessionState();\n expect(state.deviceStatus).toBe(DeviceStatus.NOT_CONNECTED);\n expect(isComplete).toBe(true);\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "aACA,IAAAA,EAA4B,qBAC5BC,EAAwC,gBACxCC,EAA4B,0BAI5BC,EAGO,4CACPC,EAA6B,oCAG7BC,EAAuC,kDAGvCC,EAA2C,8DAE3CC,EAA8C,4EAI9CC,EAGO,2BAEP,SAAS,gBAAiB,IAAM,CAC9B,IAAIC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACJ,MAAMC,KAAsB,8BAA2B,EAEvD,WAAW,IAAM,CAEfP,EAAa,IAAI,gCAA8B,CAAC,EAAG,qBAAqB,EACxEC,EAAoB,GAAG,GAAG,IAAMD,CAAU,EAG1CE,EAAiB,CACf,WAAY,GAAG,GAAG,EAClB,cAAe,GAAG,GAAG,EACrB,mBAAoB,GAAG,GAAG,EAC1B,kBAAmB,GAAG,GAAG,CAC3B,EAEAC,EAAoB,CAClB,aAAc,GAAG,GAAG,EACpB,kBAAmB,GAAG,GAAG,EACzB,UAAW,GAAG,GAAG,EACjB,eAAgB,GAAG,GAAG,EACtB,WAAY,GAAG,GAAG,EAClB,aAAc,GAAG,GAAG,CACtB,EAGAC,EAAyB,CACvB,QAAS,GAAG,GAAG,EAAE,gBAAgB,CAC/B,cAAY,MAAG,IAAI,EAAE,QAAK,SAAM,CAAC,CAAC,EAClC,OAAQ,GAAG,GAAG,CAChB,CAAC,CACH,EAEAC,EAAgC,IAAMD,EAEtCE,EAAmB,CACjB,oBAAqB,EACvB,CACF,CAAC,EAED,UAAU,IAAM,CACdP,GAAe,MAAM,EACrB,GAAG,gBAAgB,CACrB,CAAC,EAED,SAAS,cAAe,IAAM,CAC5B,GAAG,iDAAkD,IAAM,CAEzDA,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,EAGA,OAAON,CAAa,EAAE,YAAY,EAClC,OAAOA,EAAc,EAAE,EAAE,YAAY,EACrC,OAAOA,EAAc,eAAe,EAAE,KAAKQ,CAAmB,CAChE,CAAC,EAED,GAAG,gDAAiD,IAAM,CAExD,MAAMC,EAAW,oBAGjBT,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,EAAqB,GAAIC,CAAS,EACrDP,EACAC,EACAC,EACAG,EACAD,CACF,EAGA,OAAON,EAAc,EAAE,EAAE,KAAKS,CAAQ,CACxC,CAAC,CACH,CAAC,EAED,SAAS,oBAAqB,IAAM,CAClC,GAAG,yCAA0C,IAAM,CAEjDT,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACA,CAAE,oBAAqB,GAAO,gBAAiB,GAAK,EACpDE,CACF,EAEA,MAAMI,EAAwB,GAAG,MAC/BV,EAAc,wBACd,gBACF,EAGAA,EAAc,kBAAkB,EAGhC,OAAOU,CAAqB,EAAE,iBAAiB,CACjD,CAAC,CACH,CAAC,EAED,SAAS,UAAW,IAAM,CACxB,WAAW,IAAM,CACfV,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,EAAqB,GAAI,SAAU,EACtDN,EACAC,EACAC,EACAG,EACAD,CACF,CACF,CAAC,EAED,GAAG,2BAA4B,IAAM,CACnC,OAAON,EAAc,EAAE,EAAE,KAAK,SAAS,CACzC,CAAC,EAED,GAAG,iCAAkC,IAAM,CACzC,OAAOA,EAAc,eAAe,EAAE,KAAKQ,CAAmB,CAChE,CAAC,EAED,GAAG,oCAAqC,SAAY,CAClD,MAAMG,EAAkBX,EAAc,MAEtC,MAAM,IAAI,QAAeY,GAAY,CACnCD,EAAgB,QAAK,QAAK,CAAC,CAAC,EAAE,UAAWE,GAAU,CACjD,OAAOA,EAAM,gBAAgB,EAAE,KAAK,yBAAuB,SAAS,EACpE,OAAOA,EAAM,YAAY,EAAE,KAAK,eAAa,SAAS,EACtDD,EAAQ,CACV,CAAC,CACH,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,kDAAmD,IAAM,CAChE,WAAW,IAAM,CACfZ,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,CACF,CAAC,EAED,GAAG,0CAA2C,IAAM,CAElD,MAAMO,EAAQb,EAAc,sBAAsB,EAGlD,OAAOa,EAAM,gBAAgB,EAAE,KAAK,yBAAuB,SAAS,EACpE,OAAOA,EAAM,YAAY,EAAE,KAAK,eAAa,SAAS,CACxD,CAAC,EAED,GAAG,kCAAmC,SAAY,CAEhD,MAAMC,EAAW,CACf,iBAAkB,yBAAuB,0BACzC,aAAc,eAAa,OAC3B,cAAeN,EAAoB,YAAY,GAC/C,WAAY,CAAE,KAAM,OAAQ,QAAS,OAAQ,EAC7C,cAAe,CAAC,EAChB,0BAA2B,EAC7B,EAGA,MAAM,IAAI,QAAeI,GAAY,CACnC,IAAIG,EAAsB,GAC1B,MAAMC,EAAehB,EAAc,MAAM,UAAWa,GAAU,CAE1DA,EAAM,mBACN,yBAAuB,2BAEvB,OAAOA,CAAK,EAAE,cAAc,CAC1B,iBACE,yBAAuB,0BACzB,aAAc,eAAa,OAC3B,cAAeL,EAAoB,YAAY,EACjD,CAAC,EACDQ,EAAa,YAAY,EACzBJ,EAAQ,GACEG,IACVA,EAAsB,GAE1B,CAAC,EAEDf,EAAc,sBAAsBc,CAAQ,CAC9C,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,WAAY,IAAM,CACzB,IAAIG,EACAC,EAEJ,WAAW,IAAM,CACfD,EAAW,IAAI,WAAW,CAAC,IAAM,EAAM,EAAM,CAAI,CAAC,EAClDC,EAAe,CACb,KAAM,IAAI,WAAW,CAAC,EAAM,CAAI,CAAC,EACjC,WAAY,IAAI,WAAW,CAAC,IAAM,CAAI,CAAC,CACzC,EAEAlB,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,CACF,CAAC,EAED,GAAG,gCAAiC,SAAY,CAE9C,MAAMa,KAAiB,SAAG,SAAMD,CAAY,CAAC,EAAE,QAAK,SAAM,CAAC,CAAC,EAC5Db,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYc,EACZ,OAAQ,GAAG,GAAG,CAChB,CAAC,EAGD,MAAMC,EAAS,MAAMpB,EAAc,SAASiB,CAAQ,EAGpD,OAAOZ,EAAuB,OAAO,EAAE,qBAAqB,CAC1D,KAAM,YACN,QAAS,OAAO,IAAI,QAAQ,CAC9B,CAAC,EACD,OAAOe,EAAO,QAAQ,CAAC,EAAE,KAAK,EAAI,EAClCA,EAAO,QAASC,GAAa,CAC3B,OAAOA,CAAQ,EAAE,QAAQH,CAAY,CACvC,CAAC,CACH,CAAC,EAED,GAAG,gCAAiC,SAAY,CAE9C,MAAMI,EAAQ,CAAE,KAAM,eAAgB,EAChCH,KAAiB,SAAG,QAAKG,CAAK,CAAC,EAAE,QAAK,SAAM,CAAC,CAAC,EACpDjB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYc,EACZ,OAAQ,GAAG,GAAG,CAChB,CAAC,EAGD,MAAMC,EAAS,MAAMpB,EAAc,SAASiB,CAAQ,EAGpD,OAAOG,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,EACjCA,EAAO,OAAQG,GAAQ,CACrB,OAAOA,CAAG,EAAE,QAAQD,CAAK,CAC3B,CAAC,CACH,CAAC,EAED,GAAG,6BAA8B,SAAY,CAE3C,MAAME,EAAa,GAAG,GAAG,EACnBC,EAAU,IAAI,UAEpBpB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYoB,EAAQ,aAAa,EACjC,OAAQD,CACV,CAAC,EAED,GAAG,cAAc,EAGjB,MAAME,EAAc1B,EAAc,SAASiB,EAAU,CACnD,aAAc,GAChB,CAAC,EAGD,GAAG,oBAAoB,IAAI,EAE3B,IAAIU,EACJ,GAAI,CACF,MAAMD,CACR,OAASJ,EAAO,CACdK,EAAcL,CAChB,CAEA,GAAG,cAAc,EAGjB,OAAOK,CAAW,EAAE,YAAY,EAChC,OAAOtB,EAAuB,OAAO,EAAE,iBAAiB,CAC1D,CAAC,CACH,CAAC,EAED,SAAS,cAAe,IAAM,CAK5B,IAAIuB,EACAC,EAEJ,WAAW,IAAM,CACfA,EAAoB,CAClB,OAAQ,sBAAoB,QAC5B,KAAM,CAAE,KAAM,MAAO,CACvB,EAEAD,EAAc,CACZ,QAAS,GAAG,GAAG,EAAE,gBAAgB,CAC/B,WAAY,IAAM,IAAI,WAAW,CAAC,IAAM,EAAM,EAAM,CAAI,CAAC,CAC3D,CAAC,EACD,cAAe,GAAG,GAAG,EAAE,gBAAgBC,CAAiB,EACxD,sBAAuB,EACzB,EAEA7B,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,CACF,CAAC,EAED,GAAG,mCAAoC,SAAY,CAEjD,MAAMa,KAAiB,MAAGU,CAAiB,EAAE,QAAK,SAAM,CAAC,CAAC,EAC1DxB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYc,EACZ,OAAQ,GAAG,GAAG,CAChB,CAAC,EAGD,MAAMC,EAAS,MAAMpB,EAAc,YAAY4B,CAAW,EAG1D,OAAOvB,EAAuB,OAAO,EAAE,qBAAqB,CAC1D,KAAM,eACN,QAAS,OAAO,IAAI,QAAQ,CAC9B,CAAC,EACD,OAAOe,CAAM,EAAE,QAAQS,CAAiB,CAC1C,CAAC,EAED,GAAG,gCAAiC,SAAY,CAE9C,MAAML,EAAa,GAAG,GAAG,EACnBC,EAAU,IAAI,UAEpBpB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYoB,EAAQ,aAAa,EACjC,OAAQD,CACV,CAAC,EAED,GAAG,cAAc,EAGjB,MAAMM,EAAiB9B,EAAc,YAAY4B,EAAa,GAAI,EAGlE,GAAG,oBAAoB,IAAI,EAE3B,GAAI,CACF,MAAME,CACR,MAAQ,CAER,CAEA,GAAG,cAAc,EAGjB,OAAOzB,EAAuB,OAAO,EAAE,iBAAiB,CAC1D,CAAC,EAED,GAAG,8BAA+B,SAAY,CAE5C,MAAMiB,EAAQ,IAAI,MAAM,gBAAgB,EAClCH,KAAiB,cAAW,IAAMG,CAAK,EAC7CjB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYc,EACZ,OAAQ,GAAG,GAAG,CAChB,CAAC,EAGD,MAAM,OAAOnB,EAAc,YAAY4B,CAAW,CAAC,EAAE,QAAQ,QAC3D,gBACF,CACF,CAAC,CACH,CAAC,EAED,SAAS,sBAAuB,IAAM,CAgBpC,IAAIG,EAIJ,WAAW,IAAM,CACf,MAAMC,KAAuB,MAAG,CAC9B,kBAAmB,OACnB,wBAAyB,iBAC3B,CAAC,EAAE,QAAK,SAAM,CAAC,CAAC,EAEhBD,EAAmB,CACjB,SAAU,GAAG,GAAG,EAAE,gBAAgB,CAChC,WAAYC,CACd,CAAC,CACH,EAIAhC,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,CACF,CAAC,EAED,GAAG,+BAAgC,SAAY,CAE7C,MAAM0B,KAAuB,MAAG,CAC9B,kBAAmB,OACnB,wBAAyB,iBAC3B,CAAC,EAAE,QAAK,SAAM,CAAC,CAAC,EACVR,EAAa,GAAG,GAAG,EAEzBnB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAY2B,EACZ,OAAQR,CACV,CAAC,EAGD,KAAM,CAAE,WAAAS,EAAY,OAAAC,CAAO,EACzBlC,EAAc,oBAAoB+B,CAAgB,EAGpD,OAAO1B,EAAuB,OAAO,EAAE,qBAAqB,CAC1D,KAAM,gBACN,QAAS,OAAO,IAAI,QAAQ,CAC9B,CAAC,EACD,OAAO4B,CAAU,EAAE,YAAY,EAC/B,OAAOC,CAAM,EAAE,WAAW,UAAU,EAGpC,MAAMC,EAAoB,CAAC,EAC3B,MAAM,IAAI,QAAevB,GAAY,CACnCqB,EAAW,UAAU,CACnB,KAAOG,GAAUD,EAAO,KAAKC,CAAK,EAClC,SAAU,IAAMxB,EAAQ,CAC1B,CAAC,CACH,CAAC,EAED,OAAOuB,CAAM,EAAE,QAAQ,CACrB,CACE,kBAAmB,OACnB,wBAAyB,iBAC3B,CACF,CAAC,EAGDD,EAAO,EACP,OAAOV,CAAU,EAAE,iBAAiB,CACtC,CAAC,EAED,GAAG,uDAAwD,IAAM,CAE/D,MAAMQ,KAAuB,MAAG,CAC9B,kBAAmB,OACnB,wBAAyB,iBAC3B,CAAC,EAAE,QAAK,SAAM,CAAC,CAAC,EAEhB3B,EAAuB,QAAQ,mBAAoBgC,IAE5CA,EAAO,QAAQ,EAEb,CACL,WAAYL,EACZ,OAAQ,GAAG,GAAG,CAChB,EACD,EAGDhC,EAAc,oBAAoB+B,CAAgB,EAGlD,OAAOA,EAAiB,QAAQ,EAAE,qBAAqB,CACrD,SAAU,OAAO,IAAI,QAAQ,EAC7B,YAAa,OAAO,IAAI,QAAQ,EAChC,eAAgB,OAAO,IAAI,QAAQ,EACnC,sBAAuB,OAAO,IAAI,QAAQ,EAC1C,gCAAiC,OAAO,IAAI,QAAQ,EACpD,sBAAuB,OAAO,IAAI,QAAQ,EAC1C,qBAAsB,OAAO,IAAI,QAAQ,EACzC,wBAAyB,OAAO,IAAI,QAAQ,CAC9C,CAAC,CACH,CAAC,EAED,GAAG,wCAAyC,IAAM,CAEhD,MAAMP,EAAa,GAAG,GAAG,EACnBC,EAAU,IAAI,UAEpBpB,EAAuB,QAAQ,gBAAgB,CAC7C,WAAYoB,EAAQ,aAAa,EACjC,OAAQD,CACV,CAAC,EAGD,KAAM,CAAE,OAAAU,CAAO,EAAIlC,EAAc,oBAAoB+B,CAAgB,EACrEG,EAAO,EAGP,OAAOV,CAAU,EAAE,iBAAiB,CACtC,CAAC,CACH,CAAC,EAED,SAAS,QAAS,IAAM,CACtB,GAAG,oDAAqD,IAAM,CAE5DxB,EAAgB,IAAI,gBAClB,CAAE,gBAAiBQ,CAAoB,EACvCN,EACAC,EACAC,EACAG,EACAD,CACF,EAEA,IAAIgC,EAAa,GACjBtC,EAAc,MAAM,UAAU,CAC5B,SAAU,IAAM,CACdsC,EAAa,EACf,CACF,CAAC,EAGDtC,EAAc,MAAM,EAGpB,MAAMa,EAAQb,EAAc,sBAAsB,EAClD,OAAOa,EAAM,YAAY,EAAE,KAAK,eAAa,aAAa,EAC1D,OAAOyB,CAAU,EAAE,KAAK,EAAI,CAC9B,CAAC,CACH,CAAC,CACH,CAAC",
|
|
6
|
-
"names": ["import_purify_ts", "import_rxjs", "import_operators", "import_CommandResult", "import_DeviceStatus", "import_DeviceSessionState", "import_TransportConnectedDevice", "import_DefaultLoggerPublisherService", "import_DeviceSession", "deviceSession", "mockLogger", "mockLoggerFactory", "mockManagerApi", "mockSecureChannel", "mockIntentQueueService", "mockIntentQueueServiceFactory", "refresherOptions", "mockConnectedDevice", "customId", "mockRefresherStartSpy", "stateObservable", "resolve", "state", "newState", "subscriptionStarted", "subscription", "mockApdu", "mockResponse", "mockObservable", "result", "response", "error", "err", "mockCancel", "subject", "sendPromise", "caughtError", "mockCommand", "mockCommandResult", "commandPromise", "mockDeviceAction", "mockActionObservable", "observable", "cancel", "values", "value", "intent", "isComplete"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var a=(s,e)=>{for(var t in e)u(s,t,{get:e[t],enumerable:!0})},h=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of l(e))!p.call(s,n)&&n!==t&&u(s,n,{get:()=>e[n],enumerable:!(i=c(e,n))||i.enumerable});return s};var g=s=>h(u({},"__esModule",{value:!0}),s);var _={};a(_,{IntentQueueService:()=>b});module.exports=g(_);var r=require("rxjs"),o=require("../../device-session/model/DeviceSessionEventDispatcher");class b{constructor(e,t){this.loggerModuleFactory=e;this.sessionEventDispatcher=t;this._logger=this.loggerModuleFactory("IntentQueueService")}_logger;_queue=[];_isProcessing=!1;_currentSubscription=null;enqueue(e){this._logger.debug("Enqueueing intent",{data:{type:e.type}});const t=new r.Subject,i={intent:e,subject:t,isCancelled:!1};this._queue.push(i);const n=()=>{this._logger.debug("Cancelling intent",{data:{type:e.type}}),i.isCancelled=!0,this._queue[0]===i&&this._currentSubscription?(this._currentSubscription.unsubscribe(),this._currentSubscription=null,t.complete(),this._queue.shift(),this._isProcessing=!1,this._processQueue()):(!this._isProcessing||this._queue[0]!==i)&&t.complete()};return this._isProcessing||this._processQueue(),{observable:t.asObservable().pipe((0,r.finalize)(()=>{this._logger.debug("Intent observable finalized",{data:{type:e.type}})})),cancel:n}}_processQueue(){if(this._isProcessing)return;if(this._queue.length===0){this.sessionEventDispatcher.dispatch({eventName:o.SessionEvents.NEW_STATE});return}this.sessionEventDispatcher.dispatch({eventName:o.SessionEvents.DEVICE_STATE_UPDATE_BUSY}),this._isProcessing=!0;const e=this._queue[0];if(e.isCancelled){this._logger.debug("Skipping cancelled intent",{data:{type:e.intent.type}}),e.subject.complete(),this._queue.shift(),this._isProcessing=!1,this._processQueue();return}this._logger.debug("Processing intent",{data:{type:e.intent.type}}),this._currentSubscription=e.intent.execute().subscribe({next:t=>{e.isCancelled||e.subject.next(t)},error:t=>{e.isCancelled||e.subject.error(t),this._onIntentComplete()},complete:()=>{e.isCancelled||e.subject.complete(),this._onIntentComplete()}})}_onIntentComplete(){this._logger.debug("Intent completed"),this._currentSubscription=null,this._queue.shift(),this._isProcessing=!1,this._processQueue()}}0&&(module.exports={IntentQueueService});
|
|
2
|
-
//# sourceMappingURL=IntentQueueService.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/service/IntentQueueService.ts"],
|
|
4
|
-
"sourcesContent": ["import { finalize, type Observable, Subject, type Subscription } from \"rxjs\";\n\nimport {\n type DeviceSessionEventDispatcher,\n SessionEvents,\n} from \"@internal/device-session/model/DeviceSessionEventDispatcher\";\nimport { type LoggerPublisherService } from \"@root/src\";\n\nexport type IntentType = \"device-action\" | \"send-apdu\" | \"send-command\";\n\nexport type Intent<T> = {\n type: IntentType;\n execute: () => Observable<T>;\n};\n\ntype QueueItem<T> = {\n intent: Intent<T>;\n subject: Subject<T>;\n isCancelled: boolean;\n};\n\n/**\n * Intent Queue Service\n *\n * Manages a sequential queue of intents (device actions, APDUs, commands) that must be\n * executed one at a time. Each intent returns an Observable and a cancel function.\n *\n * @remarks\n * **Queue Processing:**\n * - Intents are processed in FIFO (First-In-First-Out) order\n * - Only one intent executes at a time (sequential processing)\n * - Subsequent intents wait for the current one to complete\n *\n * **Graphical Representation:**\n *\n * Normal Sequential Processing:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 2: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n *\n * Queue: [1,2,3] \u2192 [2,3] \u2192 [3] \u2192 []\n * ```\n *\n * Cancelling Currently Executing Intent:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588XX]\n * Intent 2: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * \u2191 Intent 2 starts immediately\n * Queue: [1,2,3] \u2192 [2,3] \u2192 [3] \u2192 []\n * Cancel 1 \u2191\n * ```\n *\n * Cancelling Queued Intent:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 2: [CANCELLED]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * \u2191 Intent 3 starts immediately\n * Queue: [1,2,3] \u2192 [1,3] \u2192 [3] \u2192 []\n * Cancel 2 \u2191\n * ```\n *\n * @example\n * ```typescript\n * const { observable, cancel } = intentQueue.enqueue({\n * type: \"device-action\",\n * execute: () => of(result)\n * });\n *\n * observable.subscribe({\n * next: (value) => console.log(value),\n * complete: () => console.log('Done')\n * });\n *\n * // Cancel if needed\n * cancel();\n * ```\n */\nexport class IntentQueueService {\n private readonly _logger: LoggerPublisherService;\n private readonly _queue: QueueItem<unknown>[] = [];\n private _isProcessing = false;\n private _currentSubscription: Subscription | null = null;\n\n constructor(\n private readonly loggerModuleFactory: (\n tag: string,\n ) => LoggerPublisherService,\n private readonly sessionEventDispatcher: DeviceSessionEventDispatcher,\n ) {\n this._logger = this.loggerModuleFactory(\"IntentQueueService\");\n }\n\n /**\n * Enqueues an intent and returns an observable that will emit the result\n * of the intent execution, along with a cancel function.\n */\n public enqueue<T>(intent: Intent<T>): {\n observable: Observable<T>;\n cancel: () => void;\n } {\n this._logger.debug(\"Enqueueing intent\", { data: { type: intent.type } });\n\n const subject = new Subject<T>();\n const queueItem: QueueItem<T> = {\n intent,\n subject,\n isCancelled: false,\n };\n\n this._queue.push(queueItem as QueueItem<unknown>);\n\n const cancel = () => {\n this._logger.debug(\"Cancelling intent\", { data: { type: intent.type } });\n queueItem.isCancelled = true;\n\n // If this is the currently executing intent, cancel the subscription\n if (this._queue[0] === queueItem && this._currentSubscription) {\n this._currentSubscription.unsubscribe();\n this._currentSubscription = null;\n subject.complete();\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n } else if (!this._isProcessing || this._queue[0] !== queueItem) {\n // If not currently executing, just complete the subject\n subject.complete();\n }\n };\n\n // Start processing if not already processing\n if (!this._isProcessing) {\n this._processQueue();\n }\n\n return {\n observable: subject.asObservable().pipe(\n finalize(() => {\n this._logger.debug(\"Intent observable finalized\", {\n data: { type: intent.type },\n });\n }),\n ),\n cancel,\n };\n }\n\n /**\n * Processes the queue sequentially.\n * Skips cancelled items and continues to the next one.\n */\n private _processQueue(): void {\n // If already processing or queue is empty, do nothing\n if (this._isProcessing) {\n return;\n }\n\n if (this._queue.length === 0) {\n this.sessionEventDispatcher.dispatch({\n eventName: SessionEvents.NEW_STATE,\n });\n return;\n }\n\n this.sessionEventDispatcher.dispatch({\n eventName: SessionEvents.DEVICE_STATE_UPDATE_BUSY,\n });\n\n this._isProcessing = true;\n\n // Get the next item from the queue\n const queueItem = this._queue[0] as QueueItem<unknown>;\n\n // Skip cancelled items\n if (queueItem.isCancelled) {\n this._logger.debug(\"Skipping cancelled intent\", {\n data: { type: queueItem.intent.type },\n });\n queueItem.subject.complete();\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n return;\n }\n\n this._logger.debug(\"Processing intent\", {\n data: { type: queueItem.intent.type },\n });\n\n // Execute the intent\n this._currentSubscription = queueItem.intent.execute().subscribe({\n next: (value) => {\n if (!queueItem.isCancelled) {\n queueItem.subject.next(value);\n }\n },\n error: (error) => {\n if (!queueItem.isCancelled) {\n queueItem.subject.error(error);\n }\n this._onIntentComplete();\n },\n complete: () => {\n if (!queueItem.isCancelled) {\n queueItem.subject.complete();\n }\n this._onIntentComplete();\n },\n });\n }\n\n /**\n * Called when an intent completes (either successfully or with error).\n * Removes the completed item from the queue and processes the next one.\n */\n private _onIntentComplete(): void {\n this._logger.debug(\"Intent completed\");\n this._currentSubscription = null;\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n }\n}\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAsE,gBAEtEC,EAGO,uEAiFA,MAAMH,CAAmB,CAM9B,YACmBI,EAGAC,EACjB,CAJiB,yBAAAD,EAGA,4BAAAC,EAEjB,KAAK,QAAU,KAAK,oBAAoB,oBAAoB,CAC9D,CAZiB,QACA,OAA+B,CAAC,EACzC,cAAgB,GAChB,qBAA4C,KAe7C,QAAWC,EAGhB,CACA,KAAK,QAAQ,MAAM,oBAAqB,CAAE,KAAM,CAAE,KAAMA,EAAO,IAAK,CAAE,CAAC,EAEvE,MAAMC,EAAU,IAAI,UACdC,EAA0B,CAC9B,OAAAF,EACA,QAAAC,EACA,YAAa,EACf,EAEA,KAAK,OAAO,KAAKC,CAA+B,EAEhD,MAAMC,EAAS,IAAM,CACnB,KAAK,QAAQ,MAAM,oBAAqB,CAAE,KAAM,CAAE,KAAMH,EAAO,IAAK,CAAE,CAAC,EACvEE,EAAU,YAAc,GAGpB,KAAK,OAAO,CAAC,IAAMA,GAAa,KAAK,sBACvC,KAAK,qBAAqB,YAAY,EACtC,KAAK,qBAAuB,KAC5BD,EAAQ,SAAS,EACjB,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,IACV,CAAC,KAAK,eAAiB,KAAK,OAAO,CAAC,IAAMC,IAEnDD,EAAQ,SAAS,CAErB,EAGA,OAAK,KAAK,eACR,KAAK,cAAc,EAGd,CACL,WAAYA,EAAQ,aAAa,EAAE,QACjC,YAAS,IAAM,CACb,KAAK,QAAQ,MAAM,8BAA+B,CAChD,KAAM,CAAE,KAAMD,EAAO,IAAK,CAC5B,CAAC,CACH,CAAC,CACH,EACA,OAAAG,CACF,CACF,CAMQ,eAAsB,CAE5B,GAAI,KAAK,cACP,OAGF,GAAI,KAAK,OAAO,SAAW,EAAG,CAC5B,KAAK,uBAAuB,SAAS,CACnC,UAAW,gBAAc,SAC3B,CAAC,EACD,MACF,CAEA,KAAK,uBAAuB,SAAS,CACnC,UAAW,gBAAc,wBAC3B,CAAC,EAED,KAAK,cAAgB,GAGrB,MAAMD,EAAY,KAAK,OAAO,CAAC,EAG/B,GAAIA,EAAU,YAAa,CACzB,KAAK,QAAQ,MAAM,4BAA6B,CAC9C,KAAM,CAAE,KAAMA,EAAU,OAAO,IAAK,CACtC,CAAC,EACDA,EAAU,QAAQ,SAAS,EAC3B,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,EACnB,MACF,CAEA,KAAK,QAAQ,MAAM,oBAAqB,CACtC,KAAM,CAAE,KAAMA,EAAU,OAAO,IAAK,CACtC,CAAC,EAGD,KAAK,qBAAuBA,EAAU,OAAO,QAAQ,EAAE,UAAU,CAC/D,KAAOE,GAAU,CACVF,EAAU,aACbA,EAAU,QAAQ,KAAKE,CAAK,CAEhC,EACA,MAAQC,GAAU,CACXH,EAAU,aACbA,EAAU,QAAQ,MAAMG,CAAK,EAE/B,KAAK,kBAAkB,CACzB,EACA,SAAU,IAAM,CACTH,EAAU,aACbA,EAAU,QAAQ,SAAS,EAE7B,KAAK,kBAAkB,CACzB,CACF,CAAC,CACH,CAMQ,mBAA0B,CAChC,KAAK,QAAQ,MAAM,kBAAkB,EACrC,KAAK,qBAAuB,KAC5B,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,CACrB,CACF",
|
|
6
|
-
"names": ["IntentQueueService_exports", "__export", "IntentQueueService", "__toCommonJS", "import_rxjs", "import_DeviceSessionEventDispatcher", "loggerModuleFactory", "sessionEventDispatcher", "intent", "subject", "queueItem", "cancel", "value", "error"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var o=require("rxjs"),b=require("rxjs/operators"),w=require("../../logger-publisher/service/DefaultLoggerPublisherService"),q=require("./IntentQueueService");let i,x,h;describe("IntentQueueService",()=>{beforeEach(()=>{x=new w.DefaultLoggerPublisherService([],"intent-queue-service");const e=()=>x;h={listen:()=>(0,o.of)(void 0).pipe((0,b.delay)(1)),dispatch:vi.fn()},i=new q.IntentQueueService(e,h)}),it("should enqueue an observable and emit each value",async()=>{const e={type:"device-action",execute:()=>(0,o.of)(1,2,3).pipe((0,b.delay)(1))},{observable:c}=i.enqueue(e),r=[];await new Promise(n=>{c.subscribe({next:s=>r.push(s),complete:()=>n()})}),expect(r).toEqual([1,2,3])}),it("should enqueue two observables and emit each value sequentially",async()=>{const e={type:"device-action",execute:()=>(0,o.of)("a","b").pipe((0,b.delay)(10))},c={type:"send-apdu",execute:()=>(0,o.of)("c","d")},{observable:r}=i.enqueue(e),{observable:a}=i.enqueue(c),n=[];await Promise.all([new Promise(s=>{r.subscribe({next:t=>n.push(t),complete:()=>s()})}),new Promise(s=>{a.subscribe({next:t=>n.push(t),complete:()=>s()})})]),expect(n).toEqual(["a","b","c","d"])}),it("should enqueue an observable and cancel it",async()=>{const e=new o.Subject,c={type:"device-action",execute:()=>e.asObservable()},{observable:r,cancel:a}=i.enqueue(c),n=[];let s=!1;r.subscribe({next:t=>n.push(t),complete:()=>{s=!0}}),e.next(1),e.next(2),a(),await new Promise(t=>setTimeout(t,10)),expect(n).toEqual([1,2]),expect(s).toBe(!0)}),it("should enqueue two observables and cancel the first one",async()=>{const e=new o.Subject,c={type:"device-action",execute:()=>e.asObservable()},r={type:"send-apdu",execute:()=>(0,o.of)("x","y").pipe((0,b.delay)(1))},{observable:a,cancel:n}=i.enqueue(c),{observable:s}=i.enqueue(r),t=[];let p=!1;a.subscribe({next:u=>t.push(u),complete:()=>{p=!0}});const l=new Promise(u=>{s.subscribe({next:m=>t.push(m),complete:()=>u()})});e.next("a"),e.next("b"),expect(t).toEqual(["a","b"]),n(),await new Promise(u=>setTimeout(u,10)),expect(p).toBe(!0),await l,expect(t).toEqual(["a","b","x","y"])}),it("should enqueue two observables and cancel the second one",async()=>{const e=[],c={type:"device-action",execute:()=>(0,o.of)("a","b").pipe((0,b.delay)(10))},r={type:"send-apdu",execute:()=>(0,o.of)("x","y").pipe((0,b.delay)(10))},{observable:a}=i.enqueue(c),{observable:n,cancel:s}=i.enqueue(r),t=new Promise(l=>{a.subscribe({next:u=>e.push(u),complete:()=>l()})});let p=!1;n.subscribe({next:l=>e.push(l),complete:()=>{p=!0}}),s(),await t,await new Promise(l=>setTimeout(l,20)),expect(e).toEqual(["a","b"]),expect(p).toBe(!0)}),it("should enqueue three observables and cancel the second one",async()=>{const e=[],c={type:"device-action",execute:()=>(0,o.of)("a","b").pipe((0,b.delay)(10))},r={type:"send-apdu",execute:()=>(0,o.of)("x","y").pipe((0,b.delay)(10))},a={type:"send-command",execute:()=>(0,o.of)("1","2").pipe((0,b.delay)(10))},{observable:n}=i.enqueue(c),{observable:s,cancel:t}=i.enqueue(r),{observable:p}=i.enqueue(a),l=new Promise(d=>{n.subscribe({next:v=>e.push(v),complete:()=>d()})});let u=!1;s.subscribe({next:d=>e.push(d),complete:()=>{u=!0}});const m=new Promise(d=>{p.subscribe({next:v=>e.push(v),complete:()=>d()})});t(),await l,expect(e).toEqual(["a","b"]),await m,expect(u).toBe(!0),expect(e).toEqual(["a","b","1","2"])}),it("should handle errors in intent execution",async()=>{const e=new Error("Test error"),c={type:"device-action",execute:()=>(0,o.throwError)(()=>e)},{observable:r}=i.enqueue(c);await expect(new Promise((a,n)=>{r.subscribe({error:s=>n(s)})})).rejects.toThrow("Test error")}),it("should continue processing queue after error",async()=>{const e=[],c=new Error("Test error"),r={type:"device-action",execute:()=>(0,o.throwError)(()=>c).pipe((0,b.delay)(10))},a={type:"send-apdu",execute:()=>(0,o.of)("success").pipe((0,b.delay)(10))},{observable:n}=i.enqueue(r),{observable:s}=i.enqueue(a);let t=!1;const p=new Promise(u=>{n.subscribe({next:m=>e.push(String(m)),error:m=>{expect(m).toEqual(c),t=!0,u()}})}),l=new Promise(u=>{s.subscribe({next:m=>e.push(m),complete:()=>u()})});await p,await l,expect(t).toBe(!0),expect(e).toEqual(["success"])})});
|
|
2
|
-
//# sourceMappingURL=IntentQueueService.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/service/IntentQueueService.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { of, Subject, throwError } from \"rxjs\";\nimport { delay } from \"rxjs/operators\";\n\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { type DeviceSessionEventDispatcher } from \"@internal/device-session/model/DeviceSessionEventDispatcher\";\nimport { DefaultLoggerPublisherService } from \"@internal/logger-publisher/service/DefaultLoggerPublisherService\";\n\nimport { type Intent, IntentQueueService } from \"./IntentQueueService\";\n\nlet service: IntentQueueService;\nlet logger: LoggerPublisherService;\nlet mockSessionEventDispatcher: DeviceSessionEventDispatcher;\n\ndescribe(\"IntentQueueService\", () => {\n beforeEach(() => {\n logger = new DefaultLoggerPublisherService([], \"intent-queue-service\");\n const loggerFactory = () => logger;\n mockSessionEventDispatcher = {\n listen: () => of(undefined).pipe(delay(1)),\n dispatch: vi.fn(),\n } as unknown as DeviceSessionEventDispatcher;\n service = new IntentQueueService(loggerFactory, mockSessionEventDispatcher);\n });\n\n it(\"should enqueue an observable and emit each value\", async () => {\n // Arrange\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => of(1, 2, 3).pipe(delay(1)), // Make it async\n };\n\n // Act\n const { observable } = service.enqueue(intent);\n const results: number[] = [];\n const promise = new Promise<void>((resolve) => {\n observable.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Wait for completion\n await promise;\n\n // Assert\n expect(results).toEqual([1, 2, 3]);\n });\n\n it(\"should enqueue two observables and emit each value sequentially\", async () => {\n // Arrange\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"c\", \"d\"),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n const results: string[] = [];\n\n await Promise.all([\n new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n }),\n new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n }),\n ]);\n\n // Assert\n expect(results).toEqual([\"a\", \"b\", \"c\", \"d\"]);\n });\n\n it(\"should enqueue an observable and cancel it\", async () => {\n // Arrange\n const subject = new Subject<number>();\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => subject.asObservable(),\n };\n\n // Act\n const { observable, cancel } = service.enqueue(intent);\n const results: number[] = [];\n let completed = false;\n\n observable.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed = true;\n },\n });\n\n // Emit some values\n subject.next(1);\n subject.next(2);\n\n // Cancel the intent\n cancel();\n\n // Wait a bit to ensure cancellation is processed\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n // Assert\n expect(results).toEqual([1, 2]);\n expect(completed).toBe(true);\n });\n\n it(\"should enqueue two observables and cancel the first one\", async () => {\n // Arrange\n const subject1 = new Subject<string>();\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => subject1.asObservable(),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(1)), // Make it async\n };\n\n // Act\n const { observable: obs1, cancel: cancel1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n const results: string[] = [];\n let completed1 = false;\n\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed1 = true;\n },\n });\n\n const Promise2 = new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Emit some values from first intent\n subject1.next(\"a\");\n subject1.next(\"b\");\n\n expect(results).toEqual([\"a\", \"b\"]);\n\n // Cancel the first intent\n cancel1();\n\n // Wait a bit for cancellation to process and queue to continue\n await new Promise((resolve) => setTimeout(resolve, 10));\n expect(completed1).toBe(true);\n\n // Wait for second to complete\n await Promise2;\n expect(results).toEqual([\"a\", \"b\", \"x\", \"y\"]);\n });\n\n it(\"should enqueue two observables and cancel the second one\", async () => {\n // Arrange\n const results: string[] = [];\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2, cancel: cancel2 } = service.enqueue(intent2);\n\n const results1Promise = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n let completed2 = false;\n\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed2 = true;\n },\n });\n\n // Cancel the second intent before first completes\n cancel2();\n\n // Wait for first to complete\n await results1Promise;\n\n // Wait a bit for cancellation to be processed\n await new Promise((resolve) => setTimeout(resolve, 20));\n\n // Assert\n expect(results).toEqual([\"a\", \"b\"]);\n expect(completed2).toBe(true);\n });\n\n it(\"should enqueue three observables and cancel the second one\", async () => {\n // Arrange\n const results: string[] = [];\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(10)),\n };\n\n const intent3: Intent<string> = {\n type: \"send-command\",\n execute: () => of(\"1\", \"2\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2, cancel: cancel2 } = service.enqueue(intent2);\n const { observable: obs3 } = service.enqueue(intent3);\n\n const results1Promise = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n let completed2 = false;\n\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed2 = true;\n },\n });\n\n const results3Promise = new Promise<void>((resolve) => {\n obs3.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Cancel the second intent before first completes\n cancel2();\n\n // Wait for first and third to complete\n await results1Promise;\n expect(results).toEqual([\"a\", \"b\"]);\n await results3Promise;\n expect(completed2).toBe(true);\n expect(results).toEqual([\"a\", \"b\", \"1\", \"2\"]);\n });\n\n it(\"should handle errors in intent execution\", async () => {\n // Arrange\n const error = new Error(\"Test error\");\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => throwError(() => error),\n };\n\n // Act\n const { observable } = service.enqueue(intent);\n\n // Assert\n await expect(\n new Promise((_, reject) => {\n observable.subscribe({\n error: (err) => reject(err),\n });\n }),\n ).rejects.toThrow(\"Test error\");\n });\n\n it(\"should continue processing queue after error\", async () => {\n // Arrange\n const results: string[] = [];\n const error = new Error(\"Test error\");\n const intent1: Intent<number> = {\n type: \"device-action\",\n execute: () => throwError(() => error).pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"success\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n let error1Caught = false;\n\n // Subscribe to both immediately\n const promise1 = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(String(value)),\n error: (err) => {\n expect(err).toEqual(error);\n error1Caught = true;\n resolve();\n },\n });\n });\n\n const promise2 = new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Wait for both to complete\n await promise1;\n await promise2;\n\n // Assert\n expect(error1Caught).toBe(true);\n expect(results).toEqual([\"success\"]);\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_rxjs", "import_operators", "import_DefaultLoggerPublisherService", "import_IntentQueueService", "service", "logger", "mockSessionEventDispatcher", "loggerFactory", "intent", "observable", "results", "resolve", "value", "intent1", "intent2", "obs1", "obs2", "subject", "cancel", "completed", "subject1", "cancel1", "completed1", "Promise2", "cancel2", "results1Promise", "completed2", "intent3", "obs3", "results3Promise", "error", "_", "reject", "err", "error1Caught", "promise1", "promise2"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var c=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var u=(s,e)=>{for(var r in e)c(s,r,{get:e[r],enumerable:!0})},f=(s,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of y(e))!h.call(s,i)&&i!==r&&c(s,i,{get:()=>e[i],enumerable:!(o=a(e,i))||o.enumerable});return s};var D=s=>f(c({},"__esModule",{value:!0}),s),p=(s,e,r,o)=>{for(var i=o>1?void 0:o?a(e,r):e,g=s.length-1,v;g>=0;g--)(v=s[g])&&(i=(o?v(e,r,i):v(i))||i);return o&&i&&c(e,r,i),i},S=(s,e)=>(r,o)=>e(r,o,s);var b={};u(b,{UnsafeBypassIntentQueueUseCase:()=>t});module.exports=D(b);var n=require("inversify"),l=require("../../device-session/di/deviceSessionTypes"),m=require("../../logger-publisher/di/loggerTypes");let t=class{_sessionService;_logger;constructor(e,r){this._sessionService=e,this._logger=r("UnsafeBypassIntentQueueUseCase")}execute({sessionId:e,bypass:r}){this._sessionService.getDeviceSessionById(e).caseOf({Left:i=>{throw this._logger.error("Error getting session",{data:{error:i}}),i},Right:i=>{this._logger.warn(`UNSAFE: ${r?"Enabling":"Disabling"} intent queue bypass for session ${e}`),i._unsafeBypassIntentQueue(r)}})}};t=p([(0,n.injectable)(),S(0,(0,n.inject)(l.deviceSessionTypes.DeviceSessionService)),S(1,(0,n.inject)(m.loggerTypes.LoggerPublisherServiceFactory))],t);0&&(module.exports={UnsafeBypassIntentQueueUseCase});
|
|
2
|
-
//# sourceMappingURL=UnsafeBypassIntentQueueUseCase.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.ts"],
|
|
4
|
-
"sourcesContent": ["import { inject, injectable } from \"inversify\";\n\nimport { type DeviceSessionId } from \"@api/device-session/types\";\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { deviceSessionTypes } from \"@internal/device-session/di/deviceSessionTypes\";\nimport { type DeviceSessionService } from \"@internal/device-session/service/DeviceSessionService\";\nimport { loggerTypes } from \"@internal/logger-publisher/di/loggerTypes\";\n\nexport type UnsafeBypassIntentQueueUseCaseArgs = {\n sessionId: DeviceSessionId;\n bypass: boolean;\n};\n\n/**\n * UNSAFE: Bypasses the intent queue for a device session.\n * This allows intents to execute directly without being queued.\n * Use with caution as this can lead to race conditions.\n */\n@injectable()\nexport class UnsafeBypassIntentQueueUseCase {\n private readonly _sessionService: DeviceSessionService;\n private readonly _logger: LoggerPublisherService;\n\n constructor(\n @inject(deviceSessionTypes.DeviceSessionService)\n sessionService: DeviceSessionService,\n @inject(loggerTypes.LoggerPublisherServiceFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this._sessionService = sessionService;\n this._logger = loggerFactory(\"UnsafeBypassIntentQueueUseCase\");\n }\n\n execute({ sessionId, bypass }: UnsafeBypassIntentQueueUseCaseArgs): void {\n const errorOrDeviceSession =\n this._sessionService.getDeviceSessionById(sessionId);\n\n errorOrDeviceSession.caseOf({\n Left: (error) => {\n this._logger.error(\"Error getting session\", { data: { error } });\n throw error;\n },\n Right: (deviceSession) => {\n this._logger.warn(\n `UNSAFE: ${bypass ? \"Enabling\" : \"Disabling\"} intent queue bypass for session ${sessionId}`,\n );\n deviceSession._unsafeBypassIntentQueue(bypass);\n },\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oCAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAmC,qBAInCC,EAAmC,0DAEnCC,EAA4B,qDAarB,IAAMC,EAAN,KAAqC,CACzB,gBACA,QAEjB,YAEEC,EAEAC,EACA,CACA,KAAK,gBAAkBD,EACvB,KAAK,QAAUC,EAAc,gCAAgC,CAC/D,CAEA,QAAQ,CAAE,UAAAC,EAAW,OAAAC,CAAO,EAA6C,CAErE,KAAK,gBAAgB,qBAAqBD,CAAS,EAEhC,OAAO,CAC1B,KAAOE,GAAU,CACf,WAAK,QAAQ,MAAM,wBAAyB,CAAE,KAAM,CAAE,MAAAA,CAAM,CAAE,CAAC,EACzDA,CACR,EACA,MAAQC,GAAkB,CACxB,KAAK,QAAQ,KACX,WAAWF,EAAS,WAAa,WAAW,oCAAoCD,CAAS,EAC3F,EACAG,EAAc,yBAAyBF,CAAM,CAC/C,CACF,CAAC,CACH,CACF,EA/BaJ,EAANO,EAAA,IADN,cAAW,EAMPC,EAAA,eAAO,qBAAmB,oBAAoB,GAE9CA,EAAA,eAAO,cAAY,6BAA6B,IAPxCR",
|
|
6
|
-
"names": ["UnsafeBypassIntentQueueUseCase_exports", "__export", "UnsafeBypassIntentQueueUseCase", "__toCommonJS", "import_inversify", "import_deviceSessionTypes", "import_loggerTypes", "UnsafeBypassIntentQueueUseCase", "sessionService", "loggerFactory", "sessionId", "bypass", "error", "deviceSession", "__decorateClass", "__decorateParam"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{Left as C,Right as g}from"purify-ts";import{of as b,Subject as x,throwError as A}from"rxjs";import{delay as f,take as T}from"rxjs/operators";import{CommandResultStatus as w}from"../../../api/command/model/CommandResult";import{DeviceStatus as S}from"../../../api/device/DeviceStatus";import{DeviceSessionStateType as h}from"../../../api/device-session/DeviceSessionState";import{connectedDeviceStubBuilder as R}from"../../../api/transport/model/TransportConnectedDevice.stub";import{DefaultLoggerPublisherService as E}from"../../logger-publisher/service/DefaultLoggerPublisherService";import{DeviceSession as v}from"./DeviceSession";describe("DeviceSession",()=>{let e,k,a,u,d,o,l,p;const r=R();beforeEach(()=>{k=new E([],"device-session-test"),a=vi.fn(()=>k),u={getAppList:vi.fn(),getAppsByHash:vi.fn(),getCurrentFirmware:vi.fn(),getLatestFirmware:vi.fn()},d={genuineCheck:vi.fn(),listInstalledApps:vi.fn(),updateMcu:vi.fn(),updateFirmware:vi.fn(),installApp:vi.fn(),uninstallApp:vi.fn()},o={enqueue:vi.fn().mockReturnValue({observable:b(null).pipe(f(1)),cancel:vi.fn()})},l=()=>o,p={isRefresherDisabled:!0}}),afterEach(()=>{e?.close(),vi.restoreAllMocks()}),describe("constructor",()=>{it("should create a device session with default id",()=>{e=new v({connectedDevice:r},a,u,d,p,l),expect(e).toBeDefined(),expect(e.id).toBeDefined(),expect(e.connectedDevice).toBe(r)}),it("should create a device session with custom id",()=>{const t="custom-session-id";e=new v({connectedDevice:r,id:t},a,u,d,p,l),expect(e.id).toBe(t)})}),describe("initialiseSession",()=>{it("should successfully initialize session",()=>{e=new v({connectedDevice:r},a,u,d,{isRefresherDisabled:!1,pollingInterval:1e3},l);const t=vi.spyOn(e._deviceSessionRefresher,"startRefresher");e.initialiseSession(),expect(t).toHaveBeenCalled()})}),describe("getters",()=>{beforeEach(()=>{e=new v({connectedDevice:r,id:"test-id"},a,u,d,p,l)}),it("should return session id",()=>{expect(e.id).toBe("test-id")}),it("should return connected device",()=>{expect(e.connectedDevice).toBe(r)}),it("should return state as observable",async()=>{const t=e.state;await new Promise(s=>{t.pipe(T(1)).subscribe(n=>{expect(n.sessionStateType).toBe(h.Connected),expect(n.deviceStatus).toBe(S.CONNECTED),s()})})})}),describe("getDeviceSessionState and setDeviceSessionState",()=>{beforeEach(()=>{e=new v({connectedDevice:r},a,u,d,p,l)}),it("should get current device session state",()=>{const t=e.getDeviceSessionState();expect(t.sessionStateType).toBe(h.Connected),expect(t.deviceStatus).toBe(S.CONNECTED)}),it("should set device session state",async()=>{const t={sessionStateType:h.ReadyWithoutSecureChannel,deviceStatus:S.LOCKED,deviceModelId:r.deviceModel.id,currentApp:{name:"Test",version:"1.0.0"},installedApps:[],isSecureConnectionAllowed:!1};await new Promise(s=>{let n=!1;const c=e.state.subscribe(i=>{i.sessionStateType===h.ReadyWithoutSecureChannel?(expect(i).toMatchObject({sessionStateType:h.ReadyWithoutSecureChannel,deviceStatus:S.LOCKED,deviceModelId:r.deviceModel.id}),c.unsubscribe(),s()):n||(n=!0)});e.setDeviceSessionState(t)})})}),describe("sendApdu",()=>{let t,s;beforeEach(()=>{t=new Uint8Array([224,1,0,0]),s={data:new Uint8Array([1,2]),statusCode:new Uint8Array([144,0])},e=new v({connectedDevice:r},a,u,d,p,l)}),it("should successfully send APDU",async()=>{const n=b(g(s)).pipe(f(1));o.enqueue.mockReturnValue({observable:n,cancel:vi.fn()});const c=await e.sendApdu(t);expect(o.enqueue).toHaveBeenCalledWith({type:"send-apdu",execute:expect.any(Function)}),expect(c.isRight()).toBe(!0),c.ifRight(i=>{expect(i).toEqual(s)})}),it("should handle APDU send error",async()=>{const n={_tag:"SendApduError"},c=b(C(n)).pipe(f(1));o.enqueue.mockReturnValue({observable:c,cancel:vi.fn()});const i=await e.sendApdu(t);expect(i.isLeft()).toBe(!0),i.ifLeft(m=>{expect(m).toEqual(n)})}),it("should handle APDU timeout",async()=>{const n=vi.fn(),c=new x;o.enqueue.mockReturnValue({observable:c.asObservable(),cancel:n}),vi.useFakeTimers();const i=e.sendApdu(t,{abortTimeout:1e3});vi.advanceTimersByTime(1100);let m;try{await i}catch(y){m=y}vi.useRealTimers(),expect(m).toBeDefined(),expect(o.enqueue).toHaveBeenCalled()})}),describe("sendCommand",()=>{let t,s;beforeEach(()=>{s={status:w.Success,data:{test:"data"}},t={getApdu:vi.fn().mockReturnValue({getRawApdu:()=>new Uint8Array([224,1,0,0])}),parseResponse:vi.fn().mockReturnValue(s),triggersDisconnection:!1},e=new v({connectedDevice:r},a,u,d,p,l)}),it("should successfully send command",async()=>{const n=b(s).pipe(f(1));o.enqueue.mockReturnValue({observable:n,cancel:vi.fn()});const c=await e.sendCommand(t);expect(o.enqueue).toHaveBeenCalledWith({type:"send-command",execute:expect.any(Function)}),expect(c).toEqual(s)}),it("should handle command timeout",async()=>{const n=vi.fn(),c=new x;o.enqueue.mockReturnValue({observable:c.asObservable(),cancel:n}),vi.useFakeTimers();const i=e.sendCommand(t,1e3);vi.advanceTimersByTime(1100);try{await i}catch{}vi.useRealTimers(),expect(o.enqueue).toHaveBeenCalled()}),it("should handle command error",async()=>{const n=new Error("Command failed"),c=A(()=>n);o.enqueue.mockReturnValue({observable:c,cancel:vi.fn()}),await expect(e.sendCommand(t)).rejects.toThrow("Command failed")})}),describe("executeDeviceAction",()=>{let t;beforeEach(()=>{const s=b({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe(f(1));t={_execute:vi.fn().mockReturnValue({observable:s})},e=new v({connectedDevice:r},a,u,d,p,l)}),it("should execute device action",async()=>{const s=b({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe(f(1)),n=vi.fn();o.enqueue.mockReturnValue({observable:s,cancel:n});const{observable:c,cancel:i}=e.executeDeviceAction(t);expect(o.enqueue).toHaveBeenCalledWith({type:"device-action",execute:expect.any(Function)}),expect(c).toBeDefined(),expect(i).toBeTypeOf("function");const m=[];await new Promise(y=>{c.subscribe({next:D=>m.push(D),complete:()=>y()})}),expect(m).toEqual([{intermediateValue:"test",requiredUserInteraction:"SignTransaction"}]),i(),expect(n).toHaveBeenCalled()}),it("should provide correct internal API to device action",()=>{const s=b({intermediateValue:"test",requiredUserInteraction:"SignTransaction"}).pipe(f(1));o.enqueue.mockImplementation(n=>(n.execute(),{observable:s,cancel:vi.fn()})),e.executeDeviceAction(t),expect(t._execute).toHaveBeenCalledWith({sendApdu:expect.any(Function),sendCommand:expect.any(Function),getDeviceModel:expect.any(Function),getDeviceSessionState:expect.any(Function),getDeviceSessionStateObservable:expect.any(Function),setDeviceSessionState:expect.any(Function),getManagerApiService:expect.any(Function),getSecureChannelService:expect.any(Function)})}),it("should allow cancelling device action",()=>{const s=vi.fn(),n=new x;o.enqueue.mockReturnValue({observable:n.asObservable(),cancel:s});const{cancel:c}=e.executeDeviceAction(t);c(),expect(s).toHaveBeenCalled()})}),describe("close",()=>{it("should close the session and update device status",()=>{e=new v({connectedDevice:r},a,u,d,p,l);let t=!1;e.state.subscribe({complete:()=>{t=!0}}),e.close();const s=e.getDeviceSessionState();expect(s.deviceStatus).toBe(S.NOT_CONNECTED),expect(t).toBe(!0)})})});
|
|
2
|
-
//# sourceMappingURL=DeviceSession.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/model/DeviceSession.test.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { Left, Right } from \"purify-ts\";\nimport { of, Subject, throwError } from \"rxjs\";\nimport { delay, take } from \"rxjs/operators\";\nimport { type Mocked } from \"vitest\";\n\nimport { type Command } from \"@api/command/Command\";\nimport {\n type CommandResult,\n CommandResultStatus,\n} from \"@api/command/model/CommandResult\";\nimport { DeviceStatus } from \"@api/device/DeviceStatus\";\nimport { type DeviceAction } from \"@api/device-action/DeviceAction\";\nimport { type ApduResponse } from \"@api/device-session/ApduResponse\";\nimport { DeviceSessionStateType } from \"@api/device-session/DeviceSessionState\";\nimport { type DmkError } from \"@api/Error\";\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { connectedDeviceStubBuilder } from \"@api/transport/model/TransportConnectedDevice.stub\";\nimport { type IntentQueueService } from \"@internal/device-session/service/IntentQueueService\";\nimport { DefaultLoggerPublisherService } from \"@internal/logger-publisher/service/DefaultLoggerPublisherService\";\nimport { type ManagerApiService } from \"@internal/manager-api/service/ManagerApiService\";\nimport { type SecureChannelService } from \"@internal/secure-channel/service/SecureChannelService\";\n\nimport {\n DeviceSession,\n type DeviceSessionRefresherOptions,\n} from \"./DeviceSession\";\n\ndescribe(\"DeviceSession\", () => {\n let deviceSession: DeviceSession;\n let mockLogger: LoggerPublisherService;\n let mockLoggerFactory: ReturnType<typeof vi.fn>;\n let mockManagerApi: Mocked<ManagerApiService>;\n let mockSecureChannel: Mocked<SecureChannelService>;\n let mockIntentQueueService: Mocked<IntentQueueService>;\n let mockIntentQueueServiceFactory: () => IntentQueueService;\n let refresherOptions: DeviceSessionRefresherOptions;\n const mockConnectedDevice = connectedDeviceStubBuilder();\n\n beforeEach(() => {\n // Setup logger\n mockLogger = new DefaultLoggerPublisherService([], \"device-session-test\");\n mockLoggerFactory = vi.fn(() => mockLogger);\n\n // Setup mocks\n mockManagerApi = {\n getAppList: vi.fn(),\n getAppsByHash: vi.fn(),\n getCurrentFirmware: vi.fn(),\n getLatestFirmware: vi.fn(),\n } as unknown as Mocked<ManagerApiService>;\n\n mockSecureChannel = {\n genuineCheck: vi.fn(),\n listInstalledApps: vi.fn(),\n updateMcu: vi.fn(),\n updateFirmware: vi.fn(),\n installApp: vi.fn(),\n uninstallApp: vi.fn(),\n } as unknown as Mocked<SecureChannelService>;\n\n // Setup intent queue service with default mock\n mockIntentQueueService = {\n enqueue: vi.fn().mockReturnValue({\n observable: of(null).pipe(delay(1)),\n cancel: vi.fn(),\n }),\n } as unknown as Mocked<IntentQueueService>;\n\n mockIntentQueueServiceFactory = () => mockIntentQueueService;\n\n refresherOptions = {\n isRefresherDisabled: true,\n };\n });\n\n afterEach(() => {\n deviceSession?.close();\n vi.restoreAllMocks();\n });\n\n describe(\"constructor\", () => {\n it(\"should create a device session with default id\", () => {\n // when\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n // then\n expect(deviceSession).toBeDefined();\n expect(deviceSession.id).toBeDefined();\n expect(deviceSession.connectedDevice).toBe(mockConnectedDevice);\n });\n\n it(\"should create a device session with custom id\", () => {\n // given\n const customId = \"custom-session-id\";\n\n // when\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice, id: customId },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n // then\n expect(deviceSession.id).toBe(customId);\n });\n });\n\n describe(\"initialiseSession\", () => {\n it(\"should successfully initialize session\", () => {\n // given\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n { isRefresherDisabled: false, pollingInterval: 1000 },\n mockIntentQueueServiceFactory,\n );\n\n const mockRefresherStartSpy = vi.spyOn(\n deviceSession[\"_deviceSessionRefresher\"],\n \"startRefresher\",\n );\n\n // when\n deviceSession.initialiseSession();\n\n // then\n expect(mockRefresherStartSpy).toHaveBeenCalled();\n });\n });\n\n describe(\"getters\", () => {\n beforeEach(() => {\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice, id: \"test-id\" },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should return session id\", () => {\n expect(deviceSession.id).toBe(\"test-id\");\n });\n\n it(\"should return connected device\", () => {\n expect(deviceSession.connectedDevice).toBe(mockConnectedDevice);\n });\n\n it(\"should return state as observable\", async () => {\n const stateObservable = deviceSession.state;\n\n await new Promise<void>((resolve) => {\n stateObservable.pipe(take(1)).subscribe((state) => {\n expect(state.sessionStateType).toBe(DeviceSessionStateType.Connected);\n expect(state.deviceStatus).toBe(DeviceStatus.CONNECTED);\n resolve();\n });\n });\n });\n });\n\n describe(\"getDeviceSessionState and setDeviceSessionState\", () => {\n beforeEach(() => {\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should get current device session state\", () => {\n // when\n const state = deviceSession.getDeviceSessionState();\n\n // then\n expect(state.sessionStateType).toBe(DeviceSessionStateType.Connected);\n expect(state.deviceStatus).toBe(DeviceStatus.CONNECTED);\n });\n\n it(\"should set device session state\", async () => {\n // given\n const newState = {\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n deviceModelId: mockConnectedDevice.deviceModel.id,\n currentApp: { name: \"Test\", version: \"1.0.0\" },\n installedApps: [],\n isSecureConnectionAllowed: false,\n };\n\n // when\n await new Promise<void>((resolve) => {\n let subscriptionStarted = false;\n const subscription = deviceSession.state.subscribe((state) => {\n if (\n state.sessionStateType ===\n DeviceSessionStateType.ReadyWithoutSecureChannel\n ) {\n expect(state).toMatchObject({\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n deviceModelId: mockConnectedDevice.deviceModel.id,\n });\n subscription.unsubscribe();\n resolve();\n } else if (!subscriptionStarted) {\n subscriptionStarted = true;\n }\n });\n\n deviceSession.setDeviceSessionState(newState);\n });\n });\n });\n\n describe(\"sendApdu\", () => {\n let mockApdu: Uint8Array;\n let mockResponse: ApduResponse;\n\n beforeEach(() => {\n mockApdu = new Uint8Array([0xe0, 0x01, 0x00, 0x00]);\n mockResponse = {\n data: new Uint8Array([0x01, 0x02]),\n statusCode: new Uint8Array([0x90, 0x00]),\n };\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should successfully send APDU\", async () => {\n // given\n const mockObservable = of(Right(mockResponse)).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendApdu(mockApdu);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"send-apdu\",\n execute: expect.any(Function),\n });\n expect(result.isRight()).toBe(true);\n result.ifRight((response) => {\n expect(response).toEqual(mockResponse);\n });\n });\n\n it(\"should handle APDU send error\", async () => {\n // given\n const error = { _tag: \"SendApduError\" } as DmkError;\n const mockObservable = of(Left(error)).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendApdu(mockApdu);\n\n // then\n expect(result.isLeft()).toBe(true);\n result.ifLeft((err) => {\n expect(err).toEqual(error);\n });\n });\n\n it(\"should handle APDU timeout\", async () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n vi.useFakeTimers();\n\n // when\n const sendPromise = deviceSession.sendApdu(mockApdu, {\n abortTimeout: 1000,\n });\n\n // Advance timers to trigger timeout\n vi.advanceTimersByTime(1100);\n\n let caughtError: Error | undefined;\n try {\n await sendPromise;\n } catch (error) {\n caughtError = error as Error;\n }\n\n vi.useRealTimers();\n\n // then\n expect(caughtError).toBeDefined();\n expect(mockIntentQueueService.enqueue).toHaveBeenCalled();\n });\n });\n\n describe(\"sendCommand\", () => {\n type TestData = { test: string };\n type TestArgs = Record<string, never>;\n type TestErrorCodes = number;\n\n let mockCommand: Mocked<Command<TestData, TestArgs, TestErrorCodes>>;\n let mockCommandResult: CommandResult<TestData, TestErrorCodes>;\n\n beforeEach(() => {\n mockCommandResult = {\n status: CommandResultStatus.Success,\n data: { test: \"data\" },\n };\n\n mockCommand = {\n getApdu: vi.fn().mockReturnValue({\n getRawApdu: () => new Uint8Array([0xe0, 0x01, 0x00, 0x00]),\n }),\n parseResponse: vi.fn().mockReturnValue(mockCommandResult),\n triggersDisconnection: false,\n } as unknown as Mocked<Command<TestData, TestArgs, TestErrorCodes>>;\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should successfully send command\", async () => {\n // given\n const mockObservable = of(mockCommandResult).pipe(delay(1));\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when\n const result = await deviceSession.sendCommand(mockCommand);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"send-command\",\n execute: expect.any(Function),\n });\n expect(result).toEqual(mockCommandResult);\n });\n\n it(\"should handle command timeout\", async () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n vi.useFakeTimers();\n\n // when\n const commandPromise = deviceSession.sendCommand(mockCommand, 1000);\n\n // Advance timers to trigger timeout\n vi.advanceTimersByTime(1100);\n\n try {\n await commandPromise;\n } catch {\n // Expected to timeout\n }\n\n vi.useRealTimers();\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalled();\n });\n\n it(\"should handle command error\", async () => {\n // given\n const error = new Error(\"Command failed\");\n const mockObservable = throwError(() => error);\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockObservable,\n cancel: vi.fn(),\n });\n\n // when/then\n await expect(deviceSession.sendCommand(mockCommand)).rejects.toThrow(\n \"Command failed\",\n );\n });\n });\n\n describe(\"executeDeviceAction\", () => {\n type TestOutput = { result: string };\n type TestInput = { input: string };\n type TestError = DmkError;\n type TestIntermediateValue = {\n intermediateValue: string;\n requiredUserInteraction:\n | \"UnlockDevice\"\n | \"ConfirmOpenApp\"\n | \"ConfirmCloseApp\"\n | \"AllowListAccess\"\n | \"AllowSecureChannelConnection\"\n | \"AllowedDataRecording\"\n | \"SignTransaction\";\n };\n\n let mockDeviceAction: Mocked<\n DeviceAction<TestOutput, TestInput, TestError, TestIntermediateValue>\n >;\n\n beforeEach(() => {\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n\n mockDeviceAction = {\n _execute: vi.fn().mockReturnValue({\n observable: mockActionObservable,\n }),\n } as unknown as Mocked<\n DeviceAction<TestOutput, TestInput, TestError, TestIntermediateValue>\n >;\n\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n });\n\n it(\"should execute device action\", async () => {\n // given\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n const mockCancel = vi.fn();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: mockActionObservable,\n cancel: mockCancel,\n });\n\n // when\n const { observable, cancel } =\n deviceSession.executeDeviceAction(mockDeviceAction);\n\n // then\n expect(mockIntentQueueService.enqueue).toHaveBeenCalledWith({\n type: \"device-action\",\n execute: expect.any(Function),\n });\n expect(observable).toBeDefined();\n expect(cancel).toBeTypeOf(\"function\");\n\n // Verify observable emits values\n const values: unknown[] = [];\n await new Promise<void>((resolve) => {\n observable.subscribe({\n next: (value) => values.push(value),\n complete: () => resolve(),\n });\n });\n\n expect(values).toEqual([\n {\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\",\n },\n ]);\n\n // Verify cancel is called\n cancel();\n expect(mockCancel).toHaveBeenCalled();\n });\n\n it(\"should provide correct internal API to device action\", () => {\n // given\n const mockActionObservable = of({\n intermediateValue: \"test\",\n requiredUserInteraction: \"SignTransaction\" as const,\n }).pipe(delay(1));\n\n mockIntentQueueService.enqueue.mockImplementation((intent) => {\n // Execute the device action to verify the internal API\n void intent.execute();\n\n return {\n observable: mockActionObservable,\n cancel: vi.fn(),\n };\n });\n\n // when\n deviceSession.executeDeviceAction(mockDeviceAction);\n\n // then\n expect(mockDeviceAction._execute).toHaveBeenCalledWith({\n sendApdu: expect.any(Function),\n sendCommand: expect.any(Function),\n getDeviceModel: expect.any(Function),\n getDeviceSessionState: expect.any(Function),\n getDeviceSessionStateObservable: expect.any(Function),\n setDeviceSessionState: expect.any(Function),\n getManagerApiService: expect.any(Function),\n getSecureChannelService: expect.any(Function),\n });\n });\n\n it(\"should allow cancelling device action\", () => {\n // given\n const mockCancel = vi.fn();\n const subject = new Subject();\n\n mockIntentQueueService.enqueue.mockReturnValue({\n observable: subject.asObservable(),\n cancel: mockCancel,\n });\n\n // when\n const { cancel } = deviceSession.executeDeviceAction(mockDeviceAction);\n cancel();\n\n // then\n expect(mockCancel).toHaveBeenCalled();\n });\n });\n\n describe(\"close\", () => {\n it(\"should close the session and update device status\", () => {\n // given\n deviceSession = new DeviceSession(\n { connectedDevice: mockConnectedDevice },\n mockLoggerFactory,\n mockManagerApi,\n mockSecureChannel,\n refresherOptions,\n mockIntentQueueServiceFactory,\n );\n\n let isComplete = false;\n deviceSession.state.subscribe({\n complete: () => {\n isComplete = true;\n },\n });\n\n // when\n deviceSession.close();\n\n // then\n const state = deviceSession.getDeviceSessionState();\n expect(state.deviceStatus).toBe(DeviceStatus.NOT_CONNECTED);\n expect(isComplete).toBe(true);\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Left", "Right", "of", "Subject", "throwError", "delay", "take", "CommandResultStatus", "DeviceStatus", "DeviceSessionStateType", "connectedDeviceStubBuilder", "DefaultLoggerPublisherService", "DeviceSession", "deviceSession", "mockLogger", "mockLoggerFactory", "mockManagerApi", "mockSecureChannel", "mockIntentQueueService", "mockIntentQueueServiceFactory", "refresherOptions", "mockConnectedDevice", "customId", "mockRefresherStartSpy", "stateObservable", "resolve", "state", "newState", "subscriptionStarted", "subscription", "mockApdu", "mockResponse", "mockObservable", "result", "response", "error", "err", "mockCancel", "subject", "sendPromise", "caughtError", "mockCommand", "mockCommandResult", "commandPromise", "mockDeviceAction", "mockActionObservable", "observable", "cancel", "values", "value", "intent", "isComplete"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{finalize as r,Subject as u}from"rxjs";import{SessionEvents as i}from"../../device-session/model/DeviceSessionEventDispatcher";class p{constructor(e,t){this.loggerModuleFactory=e;this.sessionEventDispatcher=t;this._logger=this.loggerModuleFactory("IntentQueueService")}_logger;_queue=[];_isProcessing=!1;_currentSubscription=null;enqueue(e){this._logger.debug("Enqueueing intent",{data:{type:e.type}});const t=new u,s={intent:e,subject:t,isCancelled:!1};this._queue.push(s);const n=()=>{this._logger.debug("Cancelling intent",{data:{type:e.type}}),s.isCancelled=!0,this._queue[0]===s&&this._currentSubscription?(this._currentSubscription.unsubscribe(),this._currentSubscription=null,t.complete(),this._queue.shift(),this._isProcessing=!1,this._processQueue()):(!this._isProcessing||this._queue[0]!==s)&&t.complete()};return this._isProcessing||this._processQueue(),{observable:t.asObservable().pipe(r(()=>{this._logger.debug("Intent observable finalized",{data:{type:e.type}})})),cancel:n}}_processQueue(){if(this._isProcessing)return;if(this._queue.length===0){this.sessionEventDispatcher.dispatch({eventName:i.NEW_STATE});return}this.sessionEventDispatcher.dispatch({eventName:i.DEVICE_STATE_UPDATE_BUSY}),this._isProcessing=!0;const e=this._queue[0];if(e.isCancelled){this._logger.debug("Skipping cancelled intent",{data:{type:e.intent.type}}),e.subject.complete(),this._queue.shift(),this._isProcessing=!1,this._processQueue();return}this._logger.debug("Processing intent",{data:{type:e.intent.type}}),this._currentSubscription=e.intent.execute().subscribe({next:t=>{e.isCancelled||e.subject.next(t)},error:t=>{e.isCancelled||e.subject.error(t),this._onIntentComplete()},complete:()=>{e.isCancelled||e.subject.complete(),this._onIntentComplete()}})}_onIntentComplete(){this._logger.debug("Intent completed"),this._currentSubscription=null,this._queue.shift(),this._isProcessing=!1,this._processQueue()}}export{p as IntentQueueService};
|
|
2
|
-
//# sourceMappingURL=IntentQueueService.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/service/IntentQueueService.ts"],
|
|
4
|
-
"sourcesContent": ["import { finalize, type Observable, Subject, type Subscription } from \"rxjs\";\n\nimport {\n type DeviceSessionEventDispatcher,\n SessionEvents,\n} from \"@internal/device-session/model/DeviceSessionEventDispatcher\";\nimport { type LoggerPublisherService } from \"@root/src\";\n\nexport type IntentType = \"device-action\" | \"send-apdu\" | \"send-command\";\n\nexport type Intent<T> = {\n type: IntentType;\n execute: () => Observable<T>;\n};\n\ntype QueueItem<T> = {\n intent: Intent<T>;\n subject: Subject<T>;\n isCancelled: boolean;\n};\n\n/**\n * Intent Queue Service\n *\n * Manages a sequential queue of intents (device actions, APDUs, commands) that must be\n * executed one at a time. Each intent returns an Observable and a cancel function.\n *\n * @remarks\n * **Queue Processing:**\n * - Intents are processed in FIFO (First-In-First-Out) order\n * - Only one intent executes at a time (sequential processing)\n * - Subsequent intents wait for the current one to complete\n *\n * **Graphical Representation:**\n *\n * Normal Sequential Processing:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 2: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n *\n * Queue: [1,2,3] \u2192 [2,3] \u2192 [3] \u2192 []\n * ```\n *\n * Cancelling Currently Executing Intent:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588XX]\n * Intent 2: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * \u2191 Intent 2 starts immediately\n * Queue: [1,2,3] \u2192 [2,3] \u2192 [3] \u2192 []\n * Cancel 1 \u2191\n * ```\n *\n * Cancelling Queued Intent:\n * ```\n * Time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500>\n *\n * Intent 1: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * Intent 2: [CANCELLED]\n * Intent 3: [\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588]\n * \u2191 Intent 3 starts immediately\n * Queue: [1,2,3] \u2192 [1,3] \u2192 [3] \u2192 []\n * Cancel 2 \u2191\n * ```\n *\n * @example\n * ```typescript\n * const { observable, cancel } = intentQueue.enqueue({\n * type: \"device-action\",\n * execute: () => of(result)\n * });\n *\n * observable.subscribe({\n * next: (value) => console.log(value),\n * complete: () => console.log('Done')\n * });\n *\n * // Cancel if needed\n * cancel();\n * ```\n */\nexport class IntentQueueService {\n private readonly _logger: LoggerPublisherService;\n private readonly _queue: QueueItem<unknown>[] = [];\n private _isProcessing = false;\n private _currentSubscription: Subscription | null = null;\n\n constructor(\n private readonly loggerModuleFactory: (\n tag: string,\n ) => LoggerPublisherService,\n private readonly sessionEventDispatcher: DeviceSessionEventDispatcher,\n ) {\n this._logger = this.loggerModuleFactory(\"IntentQueueService\");\n }\n\n /**\n * Enqueues an intent and returns an observable that will emit the result\n * of the intent execution, along with a cancel function.\n */\n public enqueue<T>(intent: Intent<T>): {\n observable: Observable<T>;\n cancel: () => void;\n } {\n this._logger.debug(\"Enqueueing intent\", { data: { type: intent.type } });\n\n const subject = new Subject<T>();\n const queueItem: QueueItem<T> = {\n intent,\n subject,\n isCancelled: false,\n };\n\n this._queue.push(queueItem as QueueItem<unknown>);\n\n const cancel = () => {\n this._logger.debug(\"Cancelling intent\", { data: { type: intent.type } });\n queueItem.isCancelled = true;\n\n // If this is the currently executing intent, cancel the subscription\n if (this._queue[0] === queueItem && this._currentSubscription) {\n this._currentSubscription.unsubscribe();\n this._currentSubscription = null;\n subject.complete();\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n } else if (!this._isProcessing || this._queue[0] !== queueItem) {\n // If not currently executing, just complete the subject\n subject.complete();\n }\n };\n\n // Start processing if not already processing\n if (!this._isProcessing) {\n this._processQueue();\n }\n\n return {\n observable: subject.asObservable().pipe(\n finalize(() => {\n this._logger.debug(\"Intent observable finalized\", {\n data: { type: intent.type },\n });\n }),\n ),\n cancel,\n };\n }\n\n /**\n * Processes the queue sequentially.\n * Skips cancelled items and continues to the next one.\n */\n private _processQueue(): void {\n // If already processing or queue is empty, do nothing\n if (this._isProcessing) {\n return;\n }\n\n if (this._queue.length === 0) {\n this.sessionEventDispatcher.dispatch({\n eventName: SessionEvents.NEW_STATE,\n });\n return;\n }\n\n this.sessionEventDispatcher.dispatch({\n eventName: SessionEvents.DEVICE_STATE_UPDATE_BUSY,\n });\n\n this._isProcessing = true;\n\n // Get the next item from the queue\n const queueItem = this._queue[0] as QueueItem<unknown>;\n\n // Skip cancelled items\n if (queueItem.isCancelled) {\n this._logger.debug(\"Skipping cancelled intent\", {\n data: { type: queueItem.intent.type },\n });\n queueItem.subject.complete();\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n return;\n }\n\n this._logger.debug(\"Processing intent\", {\n data: { type: queueItem.intent.type },\n });\n\n // Execute the intent\n this._currentSubscription = queueItem.intent.execute().subscribe({\n next: (value) => {\n if (!queueItem.isCancelled) {\n queueItem.subject.next(value);\n }\n },\n error: (error) => {\n if (!queueItem.isCancelled) {\n queueItem.subject.error(error);\n }\n this._onIntentComplete();\n },\n complete: () => {\n if (!queueItem.isCancelled) {\n queueItem.subject.complete();\n }\n this._onIntentComplete();\n },\n });\n }\n\n /**\n * Called when an intent completes (either successfully or with error).\n * Removes the completed item from the queue and processes the next one.\n */\n private _onIntentComplete(): void {\n this._logger.debug(\"Intent completed\");\n this._currentSubscription = null;\n this._queue.shift();\n this._isProcessing = false;\n this._processQueue();\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAS,YAAAA,EAA2B,WAAAC,MAAkC,OAEtE,OAEE,iBAAAC,MACK,8DAiFA,MAAMC,CAAmB,CAM9B,YACmBC,EAGAC,EACjB,CAJiB,yBAAAD,EAGA,4BAAAC,EAEjB,KAAK,QAAU,KAAK,oBAAoB,oBAAoB,CAC9D,CAZiB,QACA,OAA+B,CAAC,EACzC,cAAgB,GAChB,qBAA4C,KAe7C,QAAWC,EAGhB,CACA,KAAK,QAAQ,MAAM,oBAAqB,CAAE,KAAM,CAAE,KAAMA,EAAO,IAAK,CAAE,CAAC,EAEvE,MAAMC,EAAU,IAAIN,EACdO,EAA0B,CAC9B,OAAAF,EACA,QAAAC,EACA,YAAa,EACf,EAEA,KAAK,OAAO,KAAKC,CAA+B,EAEhD,MAAMC,EAAS,IAAM,CACnB,KAAK,QAAQ,MAAM,oBAAqB,CAAE,KAAM,CAAE,KAAMH,EAAO,IAAK,CAAE,CAAC,EACvEE,EAAU,YAAc,GAGpB,KAAK,OAAO,CAAC,IAAMA,GAAa,KAAK,sBACvC,KAAK,qBAAqB,YAAY,EACtC,KAAK,qBAAuB,KAC5BD,EAAQ,SAAS,EACjB,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,IACV,CAAC,KAAK,eAAiB,KAAK,OAAO,CAAC,IAAMC,IAEnDD,EAAQ,SAAS,CAErB,EAGA,OAAK,KAAK,eACR,KAAK,cAAc,EAGd,CACL,WAAYA,EAAQ,aAAa,EAAE,KACjCP,EAAS,IAAM,CACb,KAAK,QAAQ,MAAM,8BAA+B,CAChD,KAAM,CAAE,KAAMM,EAAO,IAAK,CAC5B,CAAC,CACH,CAAC,CACH,EACA,OAAAG,CACF,CACF,CAMQ,eAAsB,CAE5B,GAAI,KAAK,cACP,OAGF,GAAI,KAAK,OAAO,SAAW,EAAG,CAC5B,KAAK,uBAAuB,SAAS,CACnC,UAAWP,EAAc,SAC3B,CAAC,EACD,MACF,CAEA,KAAK,uBAAuB,SAAS,CACnC,UAAWA,EAAc,wBAC3B,CAAC,EAED,KAAK,cAAgB,GAGrB,MAAMM,EAAY,KAAK,OAAO,CAAC,EAG/B,GAAIA,EAAU,YAAa,CACzB,KAAK,QAAQ,MAAM,4BAA6B,CAC9C,KAAM,CAAE,KAAMA,EAAU,OAAO,IAAK,CACtC,CAAC,EACDA,EAAU,QAAQ,SAAS,EAC3B,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,EACnB,MACF,CAEA,KAAK,QAAQ,MAAM,oBAAqB,CACtC,KAAM,CAAE,KAAMA,EAAU,OAAO,IAAK,CACtC,CAAC,EAGD,KAAK,qBAAuBA,EAAU,OAAO,QAAQ,EAAE,UAAU,CAC/D,KAAOE,GAAU,CACVF,EAAU,aACbA,EAAU,QAAQ,KAAKE,CAAK,CAEhC,EACA,MAAQC,GAAU,CACXH,EAAU,aACbA,EAAU,QAAQ,MAAMG,CAAK,EAE/B,KAAK,kBAAkB,CACzB,EACA,SAAU,IAAM,CACTH,EAAU,aACbA,EAAU,QAAQ,SAAS,EAE7B,KAAK,kBAAkB,CACzB,CACF,CAAC,CACH,CAMQ,mBAA0B,CAChC,KAAK,QAAQ,MAAM,kBAAkB,EACrC,KAAK,qBAAuB,KAC5B,KAAK,OAAO,MAAM,EAClB,KAAK,cAAgB,GACrB,KAAK,cAAc,CACrB,CACF",
|
|
6
|
-
"names": ["finalize", "Subject", "SessionEvents", "IntentQueueService", "loggerModuleFactory", "sessionEventDispatcher", "intent", "subject", "queueItem", "cancel", "value", "error"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{of as b,Subject as x,throwError as h}from"rxjs";import{delay as l}from"rxjs/operators";import{DefaultLoggerPublisherService as y}from"../../logger-publisher/service/DefaultLoggerPublisherService";import{IntentQueueService as g}from"./IntentQueueService";let r,w,q;describe("IntentQueueService",()=>{beforeEach(()=>{w=new y([],"intent-queue-service");const e=()=>w;q={listen:()=>b(void 0).pipe(l(1)),dispatch:vi.fn()},r=new g(e,q)}),it("should enqueue an observable and emit each value",async()=>{const e={type:"device-action",execute:()=>b(1,2,3).pipe(l(1))},{observable:o}=r.enqueue(e),c=[];await new Promise(n=>{o.subscribe({next:s=>c.push(s),complete:()=>n()})}),expect(c).toEqual([1,2,3])}),it("should enqueue two observables and emit each value sequentially",async()=>{const e={type:"device-action",execute:()=>b("a","b").pipe(l(10))},o={type:"send-apdu",execute:()=>b("c","d")},{observable:c}=r.enqueue(e),{observable:u}=r.enqueue(o),n=[];await Promise.all([new Promise(s=>{c.subscribe({next:t=>n.push(t),complete:()=>s()})}),new Promise(s=>{u.subscribe({next:t=>n.push(t),complete:()=>s()})})]),expect(n).toEqual(["a","b","c","d"])}),it("should enqueue an observable and cancel it",async()=>{const e=new x,o={type:"device-action",execute:()=>e.asObservable()},{observable:c,cancel:u}=r.enqueue(o),n=[];let s=!1;c.subscribe({next:t=>n.push(t),complete:()=>{s=!0}}),e.next(1),e.next(2),u(),await new Promise(t=>setTimeout(t,10)),expect(n).toEqual([1,2]),expect(s).toBe(!0)}),it("should enqueue two observables and cancel the first one",async()=>{const e=new x,o={type:"device-action",execute:()=>e.asObservable()},c={type:"send-apdu",execute:()=>b("x","y").pipe(l(1))},{observable:u,cancel:n}=r.enqueue(o),{observable:s}=r.enqueue(c),t=[];let p=!1;u.subscribe({next:i=>t.push(i),complete:()=>{p=!0}});const a=new Promise(i=>{s.subscribe({next:m=>t.push(m),complete:()=>i()})});e.next("a"),e.next("b"),expect(t).toEqual(["a","b"]),n(),await new Promise(i=>setTimeout(i,10)),expect(p).toBe(!0),await a,expect(t).toEqual(["a","b","x","y"])}),it("should enqueue two observables and cancel the second one",async()=>{const e=[],o={type:"device-action",execute:()=>b("a","b").pipe(l(10))},c={type:"send-apdu",execute:()=>b("x","y").pipe(l(10))},{observable:u}=r.enqueue(o),{observable:n,cancel:s}=r.enqueue(c),t=new Promise(a=>{u.subscribe({next:i=>e.push(i),complete:()=>a()})});let p=!1;n.subscribe({next:a=>e.push(a),complete:()=>{p=!0}}),s(),await t,await new Promise(a=>setTimeout(a,20)),expect(e).toEqual(["a","b"]),expect(p).toBe(!0)}),it("should enqueue three observables and cancel the second one",async()=>{const e=[],o={type:"device-action",execute:()=>b("a","b").pipe(l(10))},c={type:"send-apdu",execute:()=>b("x","y").pipe(l(10))},u={type:"send-command",execute:()=>b("1","2").pipe(l(10))},{observable:n}=r.enqueue(o),{observable:s,cancel:t}=r.enqueue(c),{observable:p}=r.enqueue(u),a=new Promise(d=>{n.subscribe({next:v=>e.push(v),complete:()=>d()})});let i=!1;s.subscribe({next:d=>e.push(d),complete:()=>{i=!0}});const m=new Promise(d=>{p.subscribe({next:v=>e.push(v),complete:()=>d()})});t(),await a,expect(e).toEqual(["a","b"]),await m,expect(i).toBe(!0),expect(e).toEqual(["a","b","1","2"])}),it("should handle errors in intent execution",async()=>{const e=new Error("Test error"),o={type:"device-action",execute:()=>h(()=>e)},{observable:c}=r.enqueue(o);await expect(new Promise((u,n)=>{c.subscribe({error:s=>n(s)})})).rejects.toThrow("Test error")}),it("should continue processing queue after error",async()=>{const e=[],o=new Error("Test error"),c={type:"device-action",execute:()=>h(()=>o).pipe(l(10))},u={type:"send-apdu",execute:()=>b("success").pipe(l(10))},{observable:n}=r.enqueue(c),{observable:s}=r.enqueue(u);let t=!1;const p=new Promise(i=>{n.subscribe({next:m=>e.push(String(m)),error:m=>{expect(m).toEqual(o),t=!0,i()}})}),a=new Promise(i=>{s.subscribe({next:m=>e.push(m),complete:()=>i()})});await p,await a,expect(t).toBe(!0),expect(e).toEqual(["success"])})});
|
|
2
|
-
//# sourceMappingURL=IntentQueueService.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/service/IntentQueueService.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { of, Subject, throwError } from \"rxjs\";\nimport { delay } from \"rxjs/operators\";\n\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { type DeviceSessionEventDispatcher } from \"@internal/device-session/model/DeviceSessionEventDispatcher\";\nimport { DefaultLoggerPublisherService } from \"@internal/logger-publisher/service/DefaultLoggerPublisherService\";\n\nimport { type Intent, IntentQueueService } from \"./IntentQueueService\";\n\nlet service: IntentQueueService;\nlet logger: LoggerPublisherService;\nlet mockSessionEventDispatcher: DeviceSessionEventDispatcher;\n\ndescribe(\"IntentQueueService\", () => {\n beforeEach(() => {\n logger = new DefaultLoggerPublisherService([], \"intent-queue-service\");\n const loggerFactory = () => logger;\n mockSessionEventDispatcher = {\n listen: () => of(undefined).pipe(delay(1)),\n dispatch: vi.fn(),\n } as unknown as DeviceSessionEventDispatcher;\n service = new IntentQueueService(loggerFactory, mockSessionEventDispatcher);\n });\n\n it(\"should enqueue an observable and emit each value\", async () => {\n // Arrange\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => of(1, 2, 3).pipe(delay(1)), // Make it async\n };\n\n // Act\n const { observable } = service.enqueue(intent);\n const results: number[] = [];\n const promise = new Promise<void>((resolve) => {\n observable.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Wait for completion\n await promise;\n\n // Assert\n expect(results).toEqual([1, 2, 3]);\n });\n\n it(\"should enqueue two observables and emit each value sequentially\", async () => {\n // Arrange\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"c\", \"d\"),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n const results: string[] = [];\n\n await Promise.all([\n new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n }),\n new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n }),\n ]);\n\n // Assert\n expect(results).toEqual([\"a\", \"b\", \"c\", \"d\"]);\n });\n\n it(\"should enqueue an observable and cancel it\", async () => {\n // Arrange\n const subject = new Subject<number>();\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => subject.asObservable(),\n };\n\n // Act\n const { observable, cancel } = service.enqueue(intent);\n const results: number[] = [];\n let completed = false;\n\n observable.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed = true;\n },\n });\n\n // Emit some values\n subject.next(1);\n subject.next(2);\n\n // Cancel the intent\n cancel();\n\n // Wait a bit to ensure cancellation is processed\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n // Assert\n expect(results).toEqual([1, 2]);\n expect(completed).toBe(true);\n });\n\n it(\"should enqueue two observables and cancel the first one\", async () => {\n // Arrange\n const subject1 = new Subject<string>();\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => subject1.asObservable(),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(1)), // Make it async\n };\n\n // Act\n const { observable: obs1, cancel: cancel1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n const results: string[] = [];\n let completed1 = false;\n\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed1 = true;\n },\n });\n\n const Promise2 = new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Emit some values from first intent\n subject1.next(\"a\");\n subject1.next(\"b\");\n\n expect(results).toEqual([\"a\", \"b\"]);\n\n // Cancel the first intent\n cancel1();\n\n // Wait a bit for cancellation to process and queue to continue\n await new Promise((resolve) => setTimeout(resolve, 10));\n expect(completed1).toBe(true);\n\n // Wait for second to complete\n await Promise2;\n expect(results).toEqual([\"a\", \"b\", \"x\", \"y\"]);\n });\n\n it(\"should enqueue two observables and cancel the second one\", async () => {\n // Arrange\n const results: string[] = [];\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2, cancel: cancel2 } = service.enqueue(intent2);\n\n const results1Promise = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n let completed2 = false;\n\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed2 = true;\n },\n });\n\n // Cancel the second intent before first completes\n cancel2();\n\n // Wait for first to complete\n await results1Promise;\n\n // Wait a bit for cancellation to be processed\n await new Promise((resolve) => setTimeout(resolve, 20));\n\n // Assert\n expect(results).toEqual([\"a\", \"b\"]);\n expect(completed2).toBe(true);\n });\n\n it(\"should enqueue three observables and cancel the second one\", async () => {\n // Arrange\n const results: string[] = [];\n const intent1: Intent<string> = {\n type: \"device-action\",\n execute: () => of(\"a\", \"b\").pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"x\", \"y\").pipe(delay(10)),\n };\n\n const intent3: Intent<string> = {\n type: \"send-command\",\n execute: () => of(\"1\", \"2\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2, cancel: cancel2 } = service.enqueue(intent2);\n const { observable: obs3 } = service.enqueue(intent3);\n\n const results1Promise = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n let completed2 = false;\n\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => {\n completed2 = true;\n },\n });\n\n const results3Promise = new Promise<void>((resolve) => {\n obs3.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Cancel the second intent before first completes\n cancel2();\n\n // Wait for first and third to complete\n await results1Promise;\n expect(results).toEqual([\"a\", \"b\"]);\n await results3Promise;\n expect(completed2).toBe(true);\n expect(results).toEqual([\"a\", \"b\", \"1\", \"2\"]);\n });\n\n it(\"should handle errors in intent execution\", async () => {\n // Arrange\n const error = new Error(\"Test error\");\n const intent: Intent<number> = {\n type: \"device-action\",\n execute: () => throwError(() => error),\n };\n\n // Act\n const { observable } = service.enqueue(intent);\n\n // Assert\n await expect(\n new Promise((_, reject) => {\n observable.subscribe({\n error: (err) => reject(err),\n });\n }),\n ).rejects.toThrow(\"Test error\");\n });\n\n it(\"should continue processing queue after error\", async () => {\n // Arrange\n const results: string[] = [];\n const error = new Error(\"Test error\");\n const intent1: Intent<number> = {\n type: \"device-action\",\n execute: () => throwError(() => error).pipe(delay(10)),\n };\n\n const intent2: Intent<string> = {\n type: \"send-apdu\",\n execute: () => of(\"success\").pipe(delay(10)),\n };\n\n // Act\n const { observable: obs1 } = service.enqueue(intent1);\n const { observable: obs2 } = service.enqueue(intent2);\n\n let error1Caught = false;\n\n // Subscribe to both immediately\n const promise1 = new Promise<void>((resolve) => {\n obs1.subscribe({\n next: (value) => results.push(String(value)),\n error: (err) => {\n expect(err).toEqual(error);\n error1Caught = true;\n resolve();\n },\n });\n });\n\n const promise2 = new Promise<void>((resolve) => {\n obs2.subscribe({\n next: (value) => results.push(value),\n complete: () => resolve(),\n });\n });\n\n // Wait for both to complete\n await promise1;\n await promise2;\n\n // Assert\n expect(error1Caught).toBe(true);\n expect(results).toEqual([\"success\"]);\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["of", "Subject", "throwError", "delay", "DefaultLoggerPublisherService", "IntentQueueService", "service", "logger", "mockSessionEventDispatcher", "loggerFactory", "intent", "observable", "results", "resolve", "value", "intent1", "intent2", "obs1", "obs2", "subject", "cancel", "completed", "subject1", "cancel1", "completed1", "Promise2", "cancel2", "results1Promise", "completed2", "intent3", "obs3", "results3Promise", "error", "_", "reject", "err", "error1Caught", "promise1", "promise2"]
|
|
7
|
-
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var a=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var v=(o,i,r,s)=>{for(var e=s>1?void 0:s?p(i,r):i,n=o.length-1,c;n>=0;n--)(c=o[n])&&(e=(s?c(i,r,e):c(e))||e);return s&&e&&a(i,r,e),e},g=(o,i)=>(r,s)=>i(r,s,o);import{inject as S,injectable as l}from"inversify";import{deviceSessionTypes as m}from"../../device-session/di/deviceSessionTypes";import{loggerTypes as y}from"../../logger-publisher/di/loggerTypes";let t=class{_sessionService;_logger;constructor(i,r){this._sessionService=i,this._logger=r("UnsafeBypassIntentQueueUseCase")}execute({sessionId:i,bypass:r}){this._sessionService.getDeviceSessionById(i).caseOf({Left:e=>{throw this._logger.error("Error getting session",{data:{error:e}}),e},Right:e=>{this._logger.warn(`UNSAFE: ${r?"Enabling":"Disabling"} intent queue bypass for session ${i}`),e._unsafeBypassIntentQueue(r)}})}};t=v([l(),g(0,S(m.DeviceSessionService)),g(1,S(y.LoggerPublisherServiceFactory))],t);export{t as UnsafeBypassIntentQueueUseCase};
|
|
2
|
-
//# sourceMappingURL=UnsafeBypassIntentQueueUseCase.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../src/internal/device-session/use-case/UnsafeBypassIntentQueueUseCase.ts"],
|
|
4
|
-
"sourcesContent": ["import { inject, injectable } from \"inversify\";\n\nimport { type DeviceSessionId } from \"@api/device-session/types\";\nimport { type LoggerPublisherService } from \"@api/logger-publisher/service/LoggerPublisherService\";\nimport { deviceSessionTypes } from \"@internal/device-session/di/deviceSessionTypes\";\nimport { type DeviceSessionService } from \"@internal/device-session/service/DeviceSessionService\";\nimport { loggerTypes } from \"@internal/logger-publisher/di/loggerTypes\";\n\nexport type UnsafeBypassIntentQueueUseCaseArgs = {\n sessionId: DeviceSessionId;\n bypass: boolean;\n};\n\n/**\n * UNSAFE: Bypasses the intent queue for a device session.\n * This allows intents to execute directly without being queued.\n * Use with caution as this can lead to race conditions.\n */\n@injectable()\nexport class UnsafeBypassIntentQueueUseCase {\n private readonly _sessionService: DeviceSessionService;\n private readonly _logger: LoggerPublisherService;\n\n constructor(\n @inject(deviceSessionTypes.DeviceSessionService)\n sessionService: DeviceSessionService,\n @inject(loggerTypes.LoggerPublisherServiceFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this._sessionService = sessionService;\n this._logger = loggerFactory(\"UnsafeBypassIntentQueueUseCase\");\n }\n\n execute({ sessionId, bypass }: UnsafeBypassIntentQueueUseCaseArgs): void {\n const errorOrDeviceSession =\n this._sessionService.getDeviceSessionById(sessionId);\n\n errorOrDeviceSession.caseOf({\n Left: (error) => {\n this._logger.error(\"Error getting session\", { data: { error } });\n throw error;\n },\n Right: (deviceSession) => {\n this._logger.warn(\n `UNSAFE: ${bypass ? \"Enabling\" : \"Disabling\"} intent queue bypass for session ${sessionId}`,\n );\n deviceSession._unsafeBypassIntentQueue(bypass);\n },\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "iOAAA,OAAS,UAAAA,EAAQ,cAAAC,MAAkB,YAInC,OAAS,sBAAAC,MAA0B,iDAEnC,OAAS,eAAAC,MAAmB,4CAarB,IAAMC,EAAN,KAAqC,CACzB,gBACA,QAEjB,YAEEC,EAEAC,EACA,CACA,KAAK,gBAAkBD,EACvB,KAAK,QAAUC,EAAc,gCAAgC,CAC/D,CAEA,QAAQ,CAAE,UAAAC,EAAW,OAAAC,CAAO,EAA6C,CAErE,KAAK,gBAAgB,qBAAqBD,CAAS,EAEhC,OAAO,CAC1B,KAAOE,GAAU,CACf,WAAK,QAAQ,MAAM,wBAAyB,CAAE,KAAM,CAAE,MAAAA,CAAM,CAAE,CAAC,EACzDA,CACR,EACA,MAAQC,GAAkB,CACxB,KAAK,QAAQ,KACX,WAAWF,EAAS,WAAa,WAAW,oCAAoCD,CAAS,EAC3F,EACAG,EAAc,yBAAyBF,CAAM,CAC/C,CACF,CAAC,CACH,CACF,EA/BaJ,EAANO,EAAA,CADNC,EAAW,EAMPC,EAAA,EAAAC,EAAOC,EAAmB,oBAAoB,GAE9CF,EAAA,EAAAC,EAAOE,EAAY,6BAA6B,IAPxCZ",
|
|
6
|
-
"names": ["inject", "injectable", "deviceSessionTypes", "loggerTypes", "UnsafeBypassIntentQueueUseCase", "sessionService", "loggerFactory", "sessionId", "bypass", "error", "deviceSession", "__decorateClass", "injectable", "__decorateParam", "inject", "deviceSessionTypes", "loggerTypes"]
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceSession.test.d.ts","sourceRoot":"","sources":["../../../../../../src/internal/device-session/model/DeviceSession.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { type Observable } from "rxjs";
|
|
2
|
-
import { type DeviceSessionEventDispatcher } from "../../device-session/model/DeviceSessionEventDispatcher";
|
|
3
|
-
import { type LoggerPublisherService } from "../../../../src";
|
|
4
|
-
export type IntentType = "device-action" | "send-apdu" | "send-command";
|
|
5
|
-
export type Intent<T> = {
|
|
6
|
-
type: IntentType;
|
|
7
|
-
execute: () => Observable<T>;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Intent Queue Service
|
|
11
|
-
*
|
|
12
|
-
* Manages a sequential queue of intents (device actions, APDUs, commands) that must be
|
|
13
|
-
* executed one at a time. Each intent returns an Observable and a cancel function.
|
|
14
|
-
*
|
|
15
|
-
* @remarks
|
|
16
|
-
* **Queue Processing:**
|
|
17
|
-
* - Intents are processed in FIFO (First-In-First-Out) order
|
|
18
|
-
* - Only one intent executes at a time (sequential processing)
|
|
19
|
-
* - Subsequent intents wait for the current one to complete
|
|
20
|
-
*
|
|
21
|
-
* **Graphical Representation:**
|
|
22
|
-
*
|
|
23
|
-
* Normal Sequential Processing:
|
|
24
|
-
* ```
|
|
25
|
-
* Time ──────────────────────────────────────────────────>
|
|
26
|
-
*
|
|
27
|
-
* Intent 1: [████████████]
|
|
28
|
-
* Intent 2: [██████████]
|
|
29
|
-
* Intent 3: [████████]
|
|
30
|
-
*
|
|
31
|
-
* Queue: [1,2,3] → [2,3] → [3] → []
|
|
32
|
-
* ```
|
|
33
|
-
*
|
|
34
|
-
* Cancelling Currently Executing Intent:
|
|
35
|
-
* ```
|
|
36
|
-
* Time ──────────────────────────────────────────────────>
|
|
37
|
-
*
|
|
38
|
-
* Intent 1: [████XX]
|
|
39
|
-
* Intent 2: [██████████]
|
|
40
|
-
* Intent 3: [████████]
|
|
41
|
-
* ↑ Intent 2 starts immediately
|
|
42
|
-
* Queue: [1,2,3] → [2,3] → [3] → []
|
|
43
|
-
* Cancel 1 ↑
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* Cancelling Queued Intent:
|
|
47
|
-
* ```
|
|
48
|
-
* Time ──────────────────────────────────────────────────>
|
|
49
|
-
*
|
|
50
|
-
* Intent 1: [████████████]
|
|
51
|
-
* Intent 2: [CANCELLED]
|
|
52
|
-
* Intent 3: [████████]
|
|
53
|
-
* ↑ Intent 3 starts immediately
|
|
54
|
-
* Queue: [1,2,3] → [1,3] → [3] → []
|
|
55
|
-
* Cancel 2 ↑
|
|
56
|
-
* ```
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const { observable, cancel } = intentQueue.enqueue({
|
|
61
|
-
* type: "device-action",
|
|
62
|
-
* execute: () => of(result)
|
|
63
|
-
* });
|
|
64
|
-
*
|
|
65
|
-
* observable.subscribe({
|
|
66
|
-
* next: (value) => console.log(value),
|
|
67
|
-
* complete: () => console.log('Done')
|
|
68
|
-
* });
|
|
69
|
-
*
|
|
70
|
-
* // Cancel if needed
|
|
71
|
-
* cancel();
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
export declare class IntentQueueService {
|
|
75
|
-
private readonly loggerModuleFactory;
|
|
76
|
-
private readonly sessionEventDispatcher;
|
|
77
|
-
private readonly _logger;
|
|
78
|
-
private readonly _queue;
|
|
79
|
-
private _isProcessing;
|
|
80
|
-
private _currentSubscription;
|
|
81
|
-
constructor(loggerModuleFactory: (tag: string) => LoggerPublisherService, sessionEventDispatcher: DeviceSessionEventDispatcher);
|
|
82
|
-
/**
|
|
83
|
-
* Enqueues an intent and returns an observable that will emit the result
|
|
84
|
-
* of the intent execution, along with a cancel function.
|
|
85
|
-
*/
|
|
86
|
-
enqueue<T>(intent: Intent<T>): {
|
|
87
|
-
observable: Observable<T>;
|
|
88
|
-
cancel: () => void;
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Processes the queue sequentially.
|
|
92
|
-
* Skips cancelled items and continues to the next one.
|
|
93
|
-
*/
|
|
94
|
-
private _processQueue;
|
|
95
|
-
/**
|
|
96
|
-
* Called when an intent completes (either successfully or with error).
|
|
97
|
-
* Removes the completed item from the queue and processes the next one.
|
|
98
|
-
*/
|
|
99
|
-
private _onIntentComplete;
|
|
100
|
-
}
|
|
101
|
-
//# sourceMappingURL=IntentQueueService.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IntentQueueService.d.ts","sourceRoot":"","sources":["../../../../../../src/internal/device-session/service/IntentQueueService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,UAAU,EAA8B,MAAM,MAAM,CAAC;AAE7E,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;AAExE,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC;CAC9B,CAAC;AAQF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,qBAAa,kBAAkB;IAO3B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAGpC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IATzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,oBAAoB,CAA6B;gBAGtC,mBAAmB,EAAE,CACpC,GAAG,EAAE,MAAM,KACR,sBAAsB,EACV,sBAAsB,EAAE,4BAA4B;IAKvE;;;OAGG;IACI,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG;QACpC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB;IA+CD;;;OAGG;IACH,OAAO,CAAC,aAAa;IA4DrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CAO1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IntentQueueService.test.d.ts","sourceRoot":"","sources":["../../../../../../src/internal/device-session/service/IntentQueueService.test.ts"],"names":[],"mappings":""}
|