@ledgerhq/device-mockserver-client 0.0.0-develop-20260623003456 → 0.0.0-develop-20260625003437

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.
Files changed (154) hide show
  1. package/lib/cjs/package.json +8 -2
  2. package/lib/cjs/src/DmkNetworkClient.stub.js +2 -0
  3. package/lib/cjs/src/DmkNetworkClient.stub.js.map +7 -0
  4. package/lib/cjs/src/MockClient.js +1 -1
  5. package/lib/cjs/src/MockClient.js.map +3 -3
  6. package/lib/cjs/src/MockClient.test.js +2 -0
  7. package/lib/cjs/src/MockClient.test.js.map +7 -0
  8. package/lib/cjs/src/index.js +1 -1
  9. package/lib/cjs/src/index.js.map +3 -3
  10. package/lib/cjs/src/model/Auth.js +2 -0
  11. package/lib/cjs/src/model/Auth.js.map +7 -0
  12. package/lib/cjs/src/model/CommandResponse.js +1 -1
  13. package/lib/cjs/src/model/CommandResponse.js.map +3 -3
  14. package/lib/cjs/src/model/Device.js +1 -1
  15. package/lib/cjs/src/model/Device.js.map +3 -3
  16. package/lib/cjs/src/model/Mock.js +1 -1
  17. package/lib/cjs/src/model/Mock.js.map +3 -3
  18. package/lib/cjs/src/model/Session.js +1 -1
  19. package/lib/cjs/src/model/Session.js.map +3 -3
  20. package/lib/cjs/src/model/SessionExport.js +2 -0
  21. package/lib/cjs/src/model/SessionExport.js.map +7 -0
  22. package/lib/cjs/src/model/Speculos.js +2 -0
  23. package/lib/cjs/src/model/Speculos.js.map +7 -0
  24. package/lib/esm/package.json +8 -2
  25. package/lib/esm/src/DmkNetworkClient.stub.js +2 -0
  26. package/lib/esm/src/DmkNetworkClient.stub.js.map +7 -0
  27. package/lib/esm/src/MockClient.js +1 -1
  28. package/lib/esm/src/MockClient.js.map +3 -3
  29. package/lib/esm/src/MockClient.test.js +2 -0
  30. package/lib/esm/src/MockClient.test.js.map +7 -0
  31. package/lib/esm/src/index.js +1 -1
  32. package/lib/esm/src/index.js.map +3 -3
  33. package/lib/esm/src/model/Auth.js +2 -0
  34. package/lib/esm/src/model/Auth.js.map +7 -0
  35. package/lib/esm/src/model/CommandResponse.js +1 -1
  36. package/lib/esm/src/model/CommandResponse.js.map +3 -3
  37. package/lib/esm/src/model/Device.js +1 -1
  38. package/lib/esm/src/model/Device.js.map +3 -3
  39. package/lib/esm/src/model/Mock.js +1 -1
  40. package/lib/esm/src/model/Mock.js.map +3 -3
  41. package/lib/esm/src/model/Session.js +1 -1
  42. package/lib/esm/src/model/Session.js.map +3 -3
  43. package/lib/esm/src/model/SessionExport.js +2 -0
  44. package/lib/esm/src/model/SessionExport.js.map +7 -0
  45. package/lib/esm/src/model/Speculos.js +2 -0
  46. package/lib/esm/src/model/Speculos.js.map +7 -0
  47. package/lib/types/src/DmkNetworkClient.stub.d.ts +18 -0
  48. package/lib/types/src/DmkNetworkClient.stub.d.ts.map +1 -0
  49. package/lib/types/src/MockClient.d.ts +64 -21
  50. package/lib/types/src/MockClient.d.ts.map +1 -1
  51. package/lib/types/src/MockClient.test.d.ts +2 -0
  52. package/lib/types/src/MockClient.test.d.ts.map +1 -0
  53. package/lib/types/src/index.d.ts +8 -4
  54. package/lib/types/src/index.d.ts.map +1 -1
  55. package/lib/types/src/model/Auth.d.ts +38 -0
  56. package/lib/types/src/model/Auth.d.ts.map +1 -0
  57. package/lib/types/src/model/CommandResponse.d.ts +11 -5
  58. package/lib/types/src/model/CommandResponse.d.ts.map +1 -1
  59. package/lib/types/src/model/Device.d.ts +65 -7
  60. package/lib/types/src/model/Device.d.ts.map +1 -1
  61. package/lib/types/src/model/Mock.d.ts +32 -6
  62. package/lib/types/src/model/Mock.d.ts.map +1 -1
  63. package/lib/types/src/model/Session.d.ts +27 -10
  64. package/lib/types/src/model/Session.d.ts.map +1 -1
  65. package/lib/types/src/model/SessionExport.d.ts +32 -0
  66. package/lib/types/src/model/SessionExport.d.ts.map +1 -0
  67. package/lib/types/src/model/Speculos.d.ts +20 -0
  68. package/lib/types/src/model/Speculos.d.ts.map +1 -0
  69. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  70. package/package.json +8 -2
  71. package/lib/cjs/src/DefaultHttpClient.js +0 -2
  72. package/lib/cjs/src/DefaultHttpClient.js.map +0 -7
  73. package/lib/cjs/src/DefaultHttpClient.stub.js +0 -2
  74. package/lib/cjs/src/DefaultHttpClient.stub.js.map +0 -7
  75. package/lib/cjs/src/HttpClient.js +0 -2
  76. package/lib/cjs/src/HttpClient.js.map +0 -7
  77. package/lib/cjs/src/model/ComandResponse.test.js +0 -2
  78. package/lib/cjs/src/model/ComandResponse.test.js.map +0 -7
  79. package/lib/cjs/src/model/CommandResponse.stub.js +0 -2
  80. package/lib/cjs/src/model/CommandResponse.stub.js.map +0 -7
  81. package/lib/cjs/src/model/Device.stub.js +0 -2
  82. package/lib/cjs/src/model/Device.stub.js.map +0 -7
  83. package/lib/cjs/src/model/Mock.stub.js +0 -2
  84. package/lib/cjs/src/model/Mock.stub.js.map +0 -7
  85. package/lib/cjs/src/model/Session.stub.js +0 -2
  86. package/lib/cjs/src/model/Session.stub.js.map +0 -7
  87. package/lib/cjs/src/service/ConnectivityService.js +0 -2
  88. package/lib/cjs/src/service/ConnectivityService.js.map +0 -7
  89. package/lib/cjs/src/service/ConnectivityService.test.js +0 -2
  90. package/lib/cjs/src/service/ConnectivityService.test.js.map +0 -7
  91. package/lib/cjs/src/service/DiscoveryService.js +0 -2
  92. package/lib/cjs/src/service/DiscoveryService.js.map +0 -7
  93. package/lib/cjs/src/service/DiscoveryService.test.js +0 -2
  94. package/lib/cjs/src/service/DiscoveryService.test.js.map +0 -7
  95. package/lib/cjs/src/service/MockService.js +0 -2
  96. package/lib/cjs/src/service/MockService.js.map +0 -7
  97. package/lib/cjs/src/service/SendService.js +0 -2
  98. package/lib/cjs/src/service/SendService.js.map +0 -7
  99. package/lib/esm/src/DefaultHttpClient.js +0 -2
  100. package/lib/esm/src/DefaultHttpClient.js.map +0 -7
  101. package/lib/esm/src/DefaultHttpClient.stub.js +0 -2
  102. package/lib/esm/src/DefaultHttpClient.stub.js.map +0 -7
  103. package/lib/esm/src/HttpClient.js +0 -1
  104. package/lib/esm/src/HttpClient.js.map +0 -7
  105. package/lib/esm/src/model/ComandResponse.test.js +0 -2
  106. package/lib/esm/src/model/ComandResponse.test.js.map +0 -7
  107. package/lib/esm/src/model/CommandResponse.stub.js +0 -2
  108. package/lib/esm/src/model/CommandResponse.stub.js.map +0 -7
  109. package/lib/esm/src/model/Device.stub.js +0 -2
  110. package/lib/esm/src/model/Device.stub.js.map +0 -7
  111. package/lib/esm/src/model/Mock.stub.js +0 -2
  112. package/lib/esm/src/model/Mock.stub.js.map +0 -7
  113. package/lib/esm/src/model/Session.stub.js +0 -2
  114. package/lib/esm/src/model/Session.stub.js.map +0 -7
  115. package/lib/esm/src/service/ConnectivityService.js +0 -2
  116. package/lib/esm/src/service/ConnectivityService.js.map +0 -7
  117. package/lib/esm/src/service/ConnectivityService.test.js +0 -2
  118. package/lib/esm/src/service/ConnectivityService.test.js.map +0 -7
  119. package/lib/esm/src/service/DiscoveryService.js +0 -2
  120. package/lib/esm/src/service/DiscoveryService.js.map +0 -7
  121. package/lib/esm/src/service/DiscoveryService.test.js +0 -2
  122. package/lib/esm/src/service/DiscoveryService.test.js.map +0 -7
  123. package/lib/esm/src/service/MockService.js +0 -2
  124. package/lib/esm/src/service/MockService.js.map +0 -7
  125. package/lib/esm/src/service/SendService.js +0 -2
  126. package/lib/esm/src/service/SendService.js.map +0 -7
  127. package/lib/types/src/DefaultHttpClient.d.ts +0 -14
  128. package/lib/types/src/DefaultHttpClient.d.ts.map +0 -1
  129. package/lib/types/src/DefaultHttpClient.stub.d.ts +0 -16
  130. package/lib/types/src/DefaultHttpClient.stub.d.ts.map +0 -1
  131. package/lib/types/src/HttpClient.d.ts +0 -6
  132. package/lib/types/src/HttpClient.d.ts.map +0 -1
  133. package/lib/types/src/model/ComandResponse.test.d.ts +0 -2
  134. package/lib/types/src/model/ComandResponse.test.d.ts.map +0 -1
  135. package/lib/types/src/model/CommandResponse.stub.d.ts +0 -3
  136. package/lib/types/src/model/CommandResponse.stub.d.ts.map +0 -1
  137. package/lib/types/src/model/Device.stub.d.ts +0 -3
  138. package/lib/types/src/model/Device.stub.d.ts.map +0 -1
  139. package/lib/types/src/model/Mock.stub.d.ts +0 -3
  140. package/lib/types/src/model/Mock.stub.d.ts.map +0 -1
  141. package/lib/types/src/model/Session.stub.d.ts +0 -3
  142. package/lib/types/src/model/Session.stub.d.ts.map +0 -1
  143. package/lib/types/src/service/ConnectivityService.d.ts +0 -15
  144. package/lib/types/src/service/ConnectivityService.d.ts.map +0 -1
  145. package/lib/types/src/service/ConnectivityService.test.d.ts +0 -2
  146. package/lib/types/src/service/ConnectivityService.test.d.ts.map +0 -1
  147. package/lib/types/src/service/DiscoveryService.d.ts +0 -11
  148. package/lib/types/src/service/DiscoveryService.d.ts.map +0 -1
  149. package/lib/types/src/service/DiscoveryService.test.d.ts +0 -2
  150. package/lib/types/src/service/DiscoveryService.test.d.ts.map +0 -1
  151. package/lib/types/src/service/MockService.d.ts +0 -10
  152. package/lib/types/src/service/MockService.d.ts.map +0 -1
  153. package/lib/types/src/service/SendService.d.ts +0 -8
  154. package/lib/types/src/service/SendService.d.ts.map +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/MockClient.ts"],
4
- "sourcesContent": ["import { type CommandResponse } from \"./model/CommandResponse\";\nimport { type Device } from \"./model/Device\";\nimport { type Mock } from \"./model/Mock\";\nimport { type Session } from \"./model/Session\";\nimport { ConnectivityService } from \"./service/ConnectivityService\";\nimport { DiscoveryService } from \"./service/DiscoveryService\";\nimport { MockService } from \"./service/MockService\";\nimport { SendService } from \"./service/SendService\";\nimport { DefaultHttpClient } from \"./DefaultHttpClient\";\n\nexport class MockClient {\n // Services\n connectivityService: ConnectivityService;\n sendService: SendService;\n discoveryService: DiscoveryService;\n mockService: MockService;\n\n constructor(baseUrl: string) {\n const client = new DefaultHttpClient({ baseUrl: baseUrl + \"/\" });\n this.connectivityService = new ConnectivityService({ client });\n this.sendService = new SendService(client);\n this.discoveryService = new DiscoveryService({ client });\n this.mockService = new MockService(client);\n }\n\n async connect(sessionId: string): Promise<Session> {\n return this.connectivityService.connect(sessionId);\n }\n\n async disconnect(sessionId: string): Promise<boolean> {\n return this.connectivityService.disconnect(sessionId);\n }\n\n async disconnectAll(): Promise<boolean> {\n return this.connectivityService.disconnectAll();\n }\n\n async getConnected(): Promise<Session[]> {\n return this.connectivityService.getConnected();\n }\n\n async send(\n sessionId: string,\n binaryCommand: Uint8Array,\n ): Promise<CommandResponse> {\n const command = this.toHexString(binaryCommand);\n return this.sendService.send(sessionId, command);\n }\n\n async scan(nbDevices?: number): Promise<Device[]> {\n return this.discoveryService.scanDevices(nbDevices);\n }\n\n async addMock(\n sessionId: string,\n prefix: string,\n response: string,\n ): Promise<boolean> {\n return this.mockService.add(sessionId, prefix, response);\n }\n\n async getMocks(sessionId: string): Promise<Mock[]> {\n return this.mockService.get(sessionId);\n }\n\n async deleteMocks(sessionId: string): Promise<boolean> {\n return this.mockService.delete(sessionId);\n }\n\n //TODO: Move to Helper ?\n toHexString(arr: Uint8Array): string {\n return Array.from(arr, (i) => i.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n fromHexString(hexString: string): Uint8Array {\n if (!hexString) {\n return Uint8Array.from([]);\n }\n return new Uint8Array(\n hexString.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)),\n );\n }\n}\n"],
5
- "mappings": "AAIA,OAAS,uBAAAA,MAA2B,gCACpC,OAAS,oBAAAC,MAAwB,6BACjC,OAAS,eAAAC,MAAmB,wBAC5B,OAAS,eAAAC,MAAmB,wBAC5B,OAAS,qBAAAC,MAAyB,sBAE3B,MAAMC,CAAW,CAEtB,oBACA,YACA,iBACA,YAEA,YAAYC,EAAiB,CAC3B,MAAMC,EAAS,IAAIH,EAAkB,CAAE,QAASE,EAAU,GAAI,CAAC,EAC/D,KAAK,oBAAsB,IAAIN,EAAoB,CAAE,OAAAO,CAAO,CAAC,EAC7D,KAAK,YAAc,IAAIJ,EAAYI,CAAM,EACzC,KAAK,iBAAmB,IAAIN,EAAiB,CAAE,OAAAM,CAAO,CAAC,EACvD,KAAK,YAAc,IAAIL,EAAYK,CAAM,CAC3C,CAEA,MAAM,QAAQC,EAAqC,CACjD,OAAO,KAAK,oBAAoB,QAAQA,CAAS,CACnD,CAEA,MAAM,WAAWA,EAAqC,CACpD,OAAO,KAAK,oBAAoB,WAAWA,CAAS,CACtD,CAEA,MAAM,eAAkC,CACtC,OAAO,KAAK,oBAAoB,cAAc,CAChD,CAEA,MAAM,cAAmC,CACvC,OAAO,KAAK,oBAAoB,aAAa,CAC/C,CAEA,MAAM,KACJA,EACAC,EAC0B,CAC1B,MAAMC,EAAU,KAAK,YAAYD,CAAa,EAC9C,OAAO,KAAK,YAAY,KAAKD,EAAWE,CAAO,CACjD,CAEA,MAAM,KAAKC,EAAuC,CAChD,OAAO,KAAK,iBAAiB,YAAYA,CAAS,CACpD,CAEA,MAAM,QACJH,EACAI,EACAC,EACkB,CAClB,OAAO,KAAK,YAAY,IAAIL,EAAWI,EAAQC,CAAQ,CACzD,CAEA,MAAM,SAASL,EAAoC,CACjD,OAAO,KAAK,YAAY,IAAIA,CAAS,CACvC,CAEA,MAAM,YAAYA,EAAqC,CACrD,OAAO,KAAK,YAAY,OAAOA,CAAS,CAC1C,CAGA,YAAYM,EAAyB,CACnC,OAAO,MAAM,KAAKA,EAAMC,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CACxE,CAEA,cAAcC,EAA+B,CAC3C,OAAKA,EAGE,IAAI,WACTA,EAAU,MAAM,SAAS,EAAG,IAAKC,GAAS,SAASA,EAAM,EAAE,CAAC,CAC9D,EAJS,WAAW,KAAK,CAAC,CAAC,CAK7B,CACF",
6
- "names": ["ConnectivityService", "DiscoveryService", "MockService", "SendService", "DefaultHttpClient", "MockClient", "baseUrl", "client", "sessionId", "binaryCommand", "command", "nbDevices", "prefix", "response", "arr", "i", "hexString", "byte"]
4
+ "sourcesContent": ["import {\n bufferToHexaString,\n DmkNetworkClient,\n} from \"@ledgerhq/device-management-kit\";\nimport { array, type Codec } from \"purify-ts\";\n\nimport {\n authResponseCodec,\n type ConnectionState,\n connectionStateCodec,\n} from \"./model/Auth\";\nimport {\n type CommandResponse,\n commandResponseCodec,\n} from \"./model/CommandResponse\";\nimport { type Device, deviceCodec, type DeviceConfig } from \"./model/Device\";\nimport { type Mock, mockCodec, type MockConfig } from \"./model/Mock\";\nimport { type Session, sessionCodec } from \"./model/Session\";\nimport { type SessionExport, sessionExportCodec } from \"./model/SessionExport\";\nimport { type SpeculosInstance, speculosInstanceCodec } from \"./model/Speculos\";\n\nexport interface MockClientOptions {\n /**\n * An existing mock server session token. When provided the client operates\n * within that session; when omitted the client lazily creates its own session\n * through POST /auth.\n */\n readonly token?: string;\n /** Inject a custom network client (mainly for testing). */\n readonly httpClient?: DmkNetworkClient;\n}\n\n/**\n * HTTP client for the device mock server.\n *\n * Implements the bearer-token contract: the session is\n * resolved from an `Authorization: Bearer <token>` header rather than a\n * `session_id` header, and sessions, devices and mocks are exposed as REST\n * resources. The token can be injected or self-provisioned via /auth.\n */\nexport class MockClient {\n private readonly client: DmkNetworkClient;\n private token?: string;\n private authPromise?: Promise<string>;\n\n constructor(baseUrl: string, options: MockClientOptions = {}) {\n this.client =\n options.httpClient ??\n new DmkNetworkClient({ baseUrl: this.normalizeUrl(baseUrl) });\n this.token = options.token;\n }\n\n // --- Authentication -------------------------------------------------------\n\n /** Create a session and store the returned bearer token. */\n async authenticate(): Promise<string> {\n const data = await this.client.post(\"auth\", {});\n const token = this.decode(authResponseCodec, data).token;\n this.token = token;\n return token;\n }\n\n /** The current bearer token, if a session has been established. */\n getToken(): string | undefined {\n return this.token;\n }\n\n // --- Devices --------------------------------------------------------------\n\n async listDevices(): Promise<Device[]> {\n const data = await this.client.get(\"devices\", {\n headers: await this.authHeaders(),\n });\n return this.decode(array(deviceCodec), data);\n }\n\n async addDevice(config: DeviceConfig = {}): Promise<Device> {\n const data = await this.client.post(\"devices\", config, {\n headers: await this.authHeaders(),\n });\n return this.decode(deviceCodec, data);\n }\n\n async getDevice(deviceId: string): Promise<Device> {\n const data = await this.client.get(`devices/${deviceId}`, {\n headers: await this.authHeaders(),\n });\n return this.decode(deviceCodec, data);\n }\n\n async editDevice(deviceId: string, config: DeviceConfig): Promise<Device> {\n const data = await this.client.patch(`devices/${deviceId}`, config, {\n headers: await this.authHeaders(),\n });\n return this.decode(deviceCodec, data);\n }\n\n async deleteDevice(deviceId: string): Promise<boolean> {\n await this.client.delete(`devices/${deviceId}`, {\n headers: await this.authHeaders(),\n });\n return true;\n }\n\n // --- Connection state -----------------------------------------------------\n\n async connect(deviceId: string): Promise<ConnectionState> {\n const data = await this.client.post(\n `devices/${deviceId}/connect`,\n {},\n { headers: await this.authHeaders() },\n );\n return this.decode(connectionStateCodec, data);\n }\n\n async disconnect(deviceId: string): Promise<boolean> {\n await this.client.post(\n `devices/${deviceId}/disconnect`,\n {},\n { headers: await this.authHeaders() },\n );\n return true;\n }\n\n /** Disconnect every device attached to the session. */\n async disconnectAll(): Promise<boolean> {\n const devices = await this.listDevices();\n await Promise.all(\n devices\n .filter((device) => device.connected)\n .map((device) => this.disconnect(device.id)),\n );\n return true;\n }\n\n // --- APDU simulation ------------------------------------------------------\n\n async sendApdu(\n deviceId: string,\n apdu: Uint8Array | string,\n ): Promise<CommandResponse> {\n const hex =\n typeof apdu === \"string\" ? apdu : bufferToHexaString(apdu, false);\n const data = await this.client.post(\n `devices/${deviceId}/apdu`,\n { apdu: hex },\n { headers: await this.authHeaders() },\n );\n return this.decode(commandResponseCodec, data);\n }\n\n // --- Mocks (device-scoped) ------------------------------------------------\n\n async listMocks(deviceId: string): Promise<Mock[]> {\n const data = await this.client.get(`devices/${deviceId}/mocks`, {\n headers: await this.authHeaders(),\n });\n return this.decode(array(mockCodec), data);\n }\n\n async addMock(deviceId: string, config: MockConfig): Promise<Mock> {\n const data = await this.client.post(`devices/${deviceId}/mocks`, config, {\n headers: await this.authHeaders(),\n });\n return this.decode(mockCodec, data);\n }\n\n async editMock(\n deviceId: string,\n mockId: string,\n config: MockConfig,\n ): Promise<Mock> {\n const data = await this.client.patch(\n `devices/${deviceId}/mocks/${mockId}`,\n config,\n { headers: await this.authHeaders() },\n );\n return this.decode(mockCodec, data);\n }\n\n async deleteMock(deviceId: string, mockId: string): Promise<boolean> {\n await this.client.delete(`devices/${deviceId}/mocks/${mockId}`, {\n headers: await this.authHeaders(),\n });\n return true;\n }\n\n async clearMocks(deviceId: string): Promise<boolean> {\n await this.client.delete(`devices/${deviceId}/mocks`, {\n headers: await this.authHeaders(),\n });\n return true;\n }\n\n // --- Speculos -------------------------------------------------------------\n\n /**\n * Resolve the live Speculos instance backing a device (the one currently\n * proxying its APDUs). Throws if the device has no active instance.\n */\n async getSpeculos(deviceId: string): Promise<SpeculosInstance> {\n const data = await this.client.get(`devices/${deviceId}/speculos`, {\n headers: await this.authHeaders(),\n });\n return this.decode(speculosInstanceCodec, data);\n }\n\n // --- Session --------------------------------------------------------------\n\n async getSession(): Promise<Session> {\n const data = await this.client.get(\"sessions/current\", {\n headers: await this.authHeaders(),\n });\n return this.decode(sessionCodec, data);\n }\n\n async disposeSession(): Promise<boolean> {\n await this.client.delete(\"sessions/current\", {\n headers: await this.authHeaders(),\n });\n this.token = undefined;\n this.authPromise = undefined;\n return true;\n }\n\n // --- Import / Export ------------------------------------------------------\n\n /** Export the session's devices and mocks as a portable snapshot. */\n async exportSession(): Promise<SessionExport> {\n const data = await this.client.get(\"export\", {\n headers: await this.authHeaders(),\n });\n return this.decode(sessionExportCodec, data);\n }\n\n /**\n * Replace the session's devices and mocks with a previously exported\n * snapshot, returning the resulting (normalized) state.\n */\n async importSession(snapshot: SessionExport): Promise<SessionExport> {\n const data = await this.client.post(\"import\", snapshot, {\n headers: await this.authHeaders(),\n });\n return this.decode(sessionExportCodec, data);\n }\n\n // --- Helpers --------------------------------------------------------------\n\n private decode<T>(codec: Codec<T>, data: unknown): T {\n return codec.decode(data).caseOf({\n Left: (error) => {\n throw new Error(`MockClient: invalid server response (${error})`);\n },\n Right: (value) => value,\n });\n }\n\n private async authHeaders(): Promise<Record<string, string>> {\n const token = await this.ensureToken();\n return { Authorization: `Bearer ${token}` };\n }\n\n private ensureToken(): Promise<string> {\n if (this.token) {\n return Promise.resolve(this.token);\n }\n if (!this.authPromise) {\n this.authPromise = this.authenticate();\n }\n return this.authPromise;\n }\n\n private normalizeUrl(baseUrl: string): string {\n return baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["bufferToHexaString", "DmkNetworkClient", "array", "authResponseCodec", "connectionStateCodec", "commandResponseCodec", "deviceCodec", "mockCodec", "sessionCodec", "sessionExportCodec", "speculosInstanceCodec", "MockClient", "baseUrl", "options", "data", "token", "config", "deviceId", "devices", "device", "apdu", "hex", "mockId", "snapshot", "codec", "error", "value"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{httpClientStubBuilder as s}from"./DmkNetworkClient.stub";import{MockClient as n}from"./MockClient";const i=(e={})=>({id:"dev-1",name:"Ledger Nano X",device_type:"nanoX",connectivity_type:"USB",...e});describe("MockClient",()=>{describe("authentication",()=>{it("lazily creates a session via /auth when no token is provided",async()=>{const e=s().mockResponse({method:"post",endpoint:"auth",response:{token:"tok-123",expires_at:42}}).mockResponse({method:"get",endpoint:"devices",response:[]}),t=new n("http://localhost:8080",{httpClient:e}),o=await t.listDevices();expect(t.getToken()).toBe("tok-123"),expect(e.calls).toContainEqual({method:"post",endpoint:"auth",body:{}}),expect(o).toEqual([])}),it("does not call /auth when a token is injected",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices",response:[]}),t=new n("http://localhost:8080",{token:"injected",httpClient:e});await t.listDevices(),expect(t.getToken()).toBe("injected"),expect(e.calls.find(o=>o.endpoint==="auth")).toBeUndefined()}),it("returns the token from an explicit authenticate() call",async()=>{const e=s().mockResponse({method:"post",endpoint:"auth",response:{token:"tok-abc",expires_at:99}}),t=new n("http://localhost:8080",{httpClient:e}),o=await t.authenticate();expect(o).toBe("tok-abc"),expect(t.getToken()).toBe("tok-abc")}),it("reuses a single in-flight /auth call for concurrent requests",async()=>{const e=s().mockResponse({method:"post",endpoint:"auth",response:{token:"tok-shared",expires_at:1}}).mockResponse({method:"get",endpoint:"devices",response:[]}),t=new n("http://localhost:8080",{httpClient:e});await Promise.all([t.listDevices(),t.listDevices()]);const o=e.calls.filter(c=>c.endpoint==="auth");expect(o).toHaveLength(1)}),it("returns undefined token before any session is established",()=>{const e=new n("http://localhost:8080",{httpClient:s()});expect(e.getToken()).toBeUndefined()})}),describe("constructor",()=>{it("normalizes a base url without a trailing slash",()=>{const e=new n("http://localhost:8080/"),t=new n("http://localhost:8080");expect(e.getToken()).toBeUndefined(),expect(t.getToken()).toBeUndefined()})}),describe("devices",()=>{it("lists devices",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices",response:[i()]}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).listDevices();expect(o).toEqual([expect.objectContaining({id:"dev-1"})])}),it("adds a device with a default empty config",async()=>{const e=s().mockResponse({method:"post",endpoint:"devices",response:i()}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).addDevice();expect(o.id).toBe("dev-1"),expect(e.calls).toContainEqual({method:"post",endpoint:"devices",body:{}})}),it("gets a single device",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices/dev-1",response:i()}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).getDevice("dev-1");expect(o.id).toBe("dev-1")}),it("edits a device",async()=>{const e=s().mockResponse({method:"patch",endpoint:"devices/dev-1",response:i({name:"Renamed"})}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).editDevice("dev-1",{name:"Renamed"});expect(o.name).toBe("Renamed"),expect(e.calls).toContainEqual({method:"patch",endpoint:"devices/dev-1",body:{name:"Renamed"}})}),it("deletes a device",async()=>{const e=s().mockResponse({method:"delete",endpoint:"devices/dev-1",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.deleteDevice("dev-1")).resolves.toBe(!0),expect(e.calls).toContainEqual({method:"delete",endpoint:"devices/dev-1"})})}),describe("connection state",()=>{it("connects a device",async()=>{const e=s().mockResponse({method:"post",endpoint:"devices/dev-1/connect",response:{device:i(),connected:!0}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).connect("dev-1");expect(o.connected).toBe(!0),expect(o.device.id).toBe("dev-1")}),it("disconnects a device",async()=>{const e=s().mockResponse({method:"post",endpoint:"devices/dev-1/disconnect",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.disconnect("dev-1")).resolves.toBe(!0)}),it("disconnects every connected device",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices",response:[i({id:"dev-1",connected:!0}),i({id:"dev-2",connected:!1}),i({id:"dev-3",connected:!0})]}).mockResponse({method:"post",endpoint:"devices/dev-1/disconnect",response:{}}).mockResponse({method:"post",endpoint:"devices/dev-3/disconnect",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.disconnectAll()).resolves.toBe(!0);const o=e.calls.filter(c=>c.endpoint.endsWith("/disconnect"));expect(o.map(c=>c.endpoint)).toEqual(["devices/dev-1/disconnect","devices/dev-3/disconnect"])})}),describe("mocks",()=>{it("lists device-scoped mocks",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices/dev-1/mocks",response:[{id:"m1",prefix:"e0010000",responses:["9000"]}]}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).listMocks("dev-1");expect(o).toEqual([expect.objectContaining({id:"m1"})])}),it("creates a device-scoped mock",async()=>{const e=s().mockResponse({method:"post",endpoint:"devices/dev-1/mocks",response:{id:"m1",prefix:"e0010000",responses:["9000"]}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).addMock("dev-1",{prefix:"e0010000",response:"9000"});expect(o.id).toBe("m1"),expect(e.calls).toContainEqual({method:"post",endpoint:"devices/dev-1/mocks",body:{prefix:"e0010000",response:"9000"}})}),it("edits a mock",async()=>{const e=s().mockResponse({method:"patch",endpoint:"devices/dev-1/mocks/m1",response:{id:"m1",prefix:"e0010000",responses:["6985"]}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).editMock("dev-1","m1",{prefix:"e0010000",response:"6985"});expect(o.responses).toEqual(["6985"]),expect(e.calls).toContainEqual({method:"patch",endpoint:"devices/dev-1/mocks/m1",body:{prefix:"e0010000",response:"6985"}})}),it("deletes a single mock",async()=>{const e=s().mockResponse({method:"delete",endpoint:"devices/dev-1/mocks/m1",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.deleteMock("dev-1","m1")).resolves.toBe(!0),expect(e.calls).toContainEqual({method:"delete",endpoint:"devices/dev-1/mocks/m1"})}),it("clears all mocks of a device",async()=>{const e=s().mockResponse({method:"delete",endpoint:"devices/dev-1/mocks",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.clearMocks("dev-1")).resolves.toBe(!0),expect(e.calls).toContainEqual({method:"delete",endpoint:"devices/dev-1/mocks"})})}),describe("speculos",()=>{it("resolves the live speculos instance backing a device",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices/dev-1/speculos",response:{run_id:"run-1",speculos_url:"https://speculos:5000",model:"stax"}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).getSpeculos("dev-1");expect(o).toEqual({run_id:"run-1",speculos_url:"https://speculos:5000",model:"stax"})})}),describe("session",()=>{it("fetches the current session",async()=>{const e=s().mockResponse({method:"get",endpoint:"sessions/current",response:{id:"sess-1",created_at:1,expires_at:2,devices:[i()]}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).getSession();expect(o.id).toBe("sess-1"),expect(o.devices).toHaveLength(1)}),it("disposes the session and clears the stored token",async()=>{const e=s().mockResponse({method:"delete",endpoint:"sessions/current",response:{}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.disposeSession()).resolves.toBe(!0),expect(t.getToken()).toBeUndefined()})}),describe("response validation",()=>{it("throws a descriptive error when the server response is malformed",async()=>{const e=s().mockResponse({method:"get",endpoint:"devices/dev-1",response:{id:123}}),t=new n("http://localhost:8080",{token:"tok",httpClient:e});await expect(t.getDevice("dev-1")).rejects.toThrow(/MockClient: invalid server response/)})}),describe("import/export",()=>{it("exports the session snapshot",async()=>{const e={devices:[{name:"Ledger Stax",device_type:"stax",mocks:[{prefix:"ff",responses:["9000"]}]}]},t=s().mockResponse({method:"get",endpoint:"export",response:e}),c=await new n("http://localhost:8080",{token:"tok",httpClient:t}).exportSession();expect(c).toEqual(e)}),it("posts a snapshot to the import endpoint",async()=>{const e={devices:[{name:"Ledger Flex",device_type:"flex",mocks:[{prefix:"e0010000",responses:["aa9000","5515"]}]}]},t=s().mockResponse({method:"post",endpoint:"import",response:e}),c=await new n("http://localhost:8080",{token:"tok",httpClient:t}).importSession(e);expect(c).toEqual(e),expect(t.calls).toContainEqual({method:"post",endpoint:"import",body:e})})}),describe("apdu",()=>{it("sends a binary APDU as hex to the device apdu endpoint",async()=>{const e=s().mockResponse({method:"post",endpoint:"devices/dev-1/apdu",response:{response:"9000"}}),o=await new n("http://localhost:8080",{token:"tok",httpClient:e}).sendApdu("dev-1",Uint8Array.from([224,1,0,0]));expect(o.response).toBe("9000"),expect(e.calls).toContainEqual({method:"post",endpoint:"devices/dev-1/apdu",body:{apdu:"e0010000"}})})})});
2
+ //# sourceMappingURL=MockClient.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/MockClient.test.ts"],
4
+ "sourcesContent": ["import { httpClientStubBuilder } from \"./DmkNetworkClient.stub\";\nimport { MockClient } from \"./MockClient\";\n\nconst aDevice = (overrides: Record<string, unknown> = {}) => ({\n id: \"dev-1\",\n name: \"Ledger Nano X\",\n device_type: \"nanoX\",\n connectivity_type: \"USB\",\n ...overrides,\n});\n\ndescribe(\"MockClient\", () => {\n describe(\"authentication\", () => {\n it(\"lazily creates a session via /auth when no token is provided\", async () => {\n const http = httpClientStubBuilder()\n .mockResponse({\n method: \"post\",\n endpoint: \"auth\",\n response: { token: \"tok-123\", expires_at: 42 },\n })\n .mockResponse({\n method: \"get\",\n endpoint: \"devices\",\n response: [],\n });\n const client = new MockClient(\"http://localhost:8080\", {\n httpClient: http,\n });\n\n const devices = await client.listDevices();\n\n expect(client.getToken()).toBe(\"tok-123\");\n expect(http.calls).toContainEqual({\n method: \"post\",\n endpoint: \"auth\",\n body: {},\n });\n expect(devices).toEqual([]);\n });\n\n it(\"does not call /auth when a token is injected\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices\",\n response: [],\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"injected\",\n httpClient: http,\n });\n\n await client.listDevices();\n\n expect(client.getToken()).toBe(\"injected\");\n expect(\n http.calls.find((call) => call.endpoint === \"auth\"),\n ).toBeUndefined();\n });\n\n it(\"returns the token from an explicit authenticate() call\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"auth\",\n response: { token: \"tok-abc\", expires_at: 99 },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n httpClient: http,\n });\n\n const token = await client.authenticate();\n\n expect(token).toBe(\"tok-abc\");\n expect(client.getToken()).toBe(\"tok-abc\");\n });\n\n it(\"reuses a single in-flight /auth call for concurrent requests\", async () => {\n const http = httpClientStubBuilder()\n .mockResponse({\n method: \"post\",\n endpoint: \"auth\",\n response: { token: \"tok-shared\", expires_at: 1 },\n })\n .mockResponse({ method: \"get\", endpoint: \"devices\", response: [] });\n const client = new MockClient(\"http://localhost:8080\", {\n httpClient: http,\n });\n\n await Promise.all([client.listDevices(), client.listDevices()]);\n\n const authCalls = http.calls.filter((call) => call.endpoint === \"auth\");\n expect(authCalls).toHaveLength(1);\n });\n\n it(\"returns undefined token before any session is established\", () => {\n const client = new MockClient(\"http://localhost:8080\", {\n httpClient: httpClientStubBuilder(),\n });\n\n expect(client.getToken()).toBeUndefined();\n });\n });\n\n describe(\"constructor\", () => {\n it(\"normalizes a base url without a trailing slash\", () => {\n const withSlash = new MockClient(\"http://localhost:8080/\");\n const withoutSlash = new MockClient(\"http://localhost:8080\");\n\n expect(withSlash.getToken()).toBeUndefined();\n expect(withoutSlash.getToken()).toBeUndefined();\n });\n });\n\n describe(\"devices\", () => {\n it(\"lists devices\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices\",\n response: [aDevice()],\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const devices = await client.listDevices();\n\n expect(devices).toEqual([expect.objectContaining({ id: \"dev-1\" })]);\n });\n\n it(\"adds a device with a default empty config\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"devices\",\n response: aDevice(),\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const device = await client.addDevice();\n\n expect(device.id).toBe(\"dev-1\");\n expect(http.calls).toContainEqual({\n method: \"post\",\n endpoint: \"devices\",\n body: {},\n });\n });\n\n it(\"gets a single device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices/dev-1\",\n response: aDevice(),\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const device = await client.getDevice(\"dev-1\");\n\n expect(device.id).toBe(\"dev-1\");\n });\n\n it(\"edits a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"patch\",\n endpoint: \"devices/dev-1\",\n response: aDevice({ name: \"Renamed\" }),\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const device = await client.editDevice(\"dev-1\", { name: \"Renamed\" });\n\n expect(device.name).toBe(\"Renamed\");\n expect(http.calls).toContainEqual({\n method: \"patch\",\n endpoint: \"devices/dev-1\",\n body: { name: \"Renamed\" },\n });\n });\n\n it(\"deletes a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"delete\",\n endpoint: \"devices/dev-1\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.deleteDevice(\"dev-1\")).resolves.toBe(true);\n expect(http.calls).toContainEqual({\n method: \"delete\",\n endpoint: \"devices/dev-1\",\n });\n });\n });\n\n describe(\"connection state\", () => {\n it(\"connects a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-1/connect\",\n response: { device: aDevice(), connected: true },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const state = await client.connect(\"dev-1\");\n\n expect(state.connected).toBe(true);\n expect(state.device.id).toBe(\"dev-1\");\n });\n\n it(\"disconnects a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-1/disconnect\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.disconnect(\"dev-1\")).resolves.toBe(true);\n });\n\n it(\"disconnects every connected device\", async () => {\n const http = httpClientStubBuilder()\n .mockResponse({\n method: \"get\",\n endpoint: \"devices\",\n response: [\n aDevice({ id: \"dev-1\", connected: true }),\n aDevice({ id: \"dev-2\", connected: false }),\n aDevice({ id: \"dev-3\", connected: true }),\n ],\n })\n .mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-1/disconnect\",\n response: {},\n })\n .mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-3/disconnect\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.disconnectAll()).resolves.toBe(true);\n\n const disconnectCalls = http.calls.filter((call) =>\n call.endpoint.endsWith(\"/disconnect\"),\n );\n expect(disconnectCalls.map((call) => call.endpoint)).toEqual([\n \"devices/dev-1/disconnect\",\n \"devices/dev-3/disconnect\",\n ]);\n });\n });\n\n describe(\"mocks\", () => {\n it(\"lists device-scoped mocks\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices/dev-1/mocks\",\n response: [{ id: \"m1\", prefix: \"e0010000\", responses: [\"9000\"] }],\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const mocks = await client.listMocks(\"dev-1\");\n\n expect(mocks).toEqual([expect.objectContaining({ id: \"m1\" })]);\n });\n\n it(\"creates a device-scoped mock\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-1/mocks\",\n response: { id: \"m1\", prefix: \"e0010000\", responses: [\"9000\"] },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const mock = await client.addMock(\"dev-1\", {\n prefix: \"e0010000\",\n response: \"9000\",\n });\n\n expect(mock.id).toBe(\"m1\");\n expect(http.calls).toContainEqual({\n method: \"post\",\n endpoint: \"devices/dev-1/mocks\",\n body: { prefix: \"e0010000\", response: \"9000\" },\n });\n });\n\n it(\"edits a mock\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"patch\",\n endpoint: \"devices/dev-1/mocks/m1\",\n response: { id: \"m1\", prefix: \"e0010000\", responses: [\"6985\"] },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const mock = await client.editMock(\"dev-1\", \"m1\", {\n prefix: \"e0010000\",\n response: \"6985\",\n });\n\n expect(mock.responses).toEqual([\"6985\"]);\n expect(http.calls).toContainEqual({\n method: \"patch\",\n endpoint: \"devices/dev-1/mocks/m1\",\n body: { prefix: \"e0010000\", response: \"6985\" },\n });\n });\n\n it(\"deletes a single mock\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"delete\",\n endpoint: \"devices/dev-1/mocks/m1\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.deleteMock(\"dev-1\", \"m1\")).resolves.toBe(true);\n expect(http.calls).toContainEqual({\n method: \"delete\",\n endpoint: \"devices/dev-1/mocks/m1\",\n });\n });\n\n it(\"clears all mocks of a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"delete\",\n endpoint: \"devices/dev-1/mocks\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.clearMocks(\"dev-1\")).resolves.toBe(true);\n expect(http.calls).toContainEqual({\n method: \"delete\",\n endpoint: \"devices/dev-1/mocks\",\n });\n });\n });\n\n describe(\"speculos\", () => {\n it(\"resolves the live speculos instance backing a device\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices/dev-1/speculos\",\n response: {\n run_id: \"run-1\",\n speculos_url: \"https://speculos:5000\",\n model: \"stax\",\n },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const instance = await client.getSpeculos(\"dev-1\");\n\n expect(instance).toEqual({\n run_id: \"run-1\",\n speculos_url: \"https://speculos:5000\",\n model: \"stax\",\n });\n });\n });\n\n describe(\"session\", () => {\n it(\"fetches the current session\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"sessions/current\",\n response: {\n id: \"sess-1\",\n created_at: 1,\n expires_at: 2,\n devices: [aDevice()],\n },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const session = await client.getSession();\n\n expect(session.id).toBe(\"sess-1\");\n expect(session.devices).toHaveLength(1);\n });\n\n it(\"disposes the session and clears the stored token\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"delete\",\n endpoint: \"sessions/current\",\n response: {},\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.disposeSession()).resolves.toBe(true);\n expect(client.getToken()).toBeUndefined();\n });\n });\n\n describe(\"response validation\", () => {\n it(\"throws a descriptive error when the server response is malformed\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"devices/dev-1\",\n response: { id: 123 } as unknown as object,\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n await expect(client.getDevice(\"dev-1\")).rejects.toThrow(\n /MockClient: invalid server response/,\n );\n });\n });\n\n describe(\"import/export\", () => {\n it(\"exports the session snapshot\", async () => {\n const snapshot = {\n devices: [\n {\n name: \"Ledger Stax\",\n device_type: \"stax\",\n mocks: [{ prefix: \"ff\", responses: [\"9000\"] }],\n },\n ],\n };\n const http = httpClientStubBuilder().mockResponse({\n method: \"get\",\n endpoint: \"export\",\n response: snapshot,\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const result = await client.exportSession();\n\n expect(result).toEqual(snapshot);\n });\n\n it(\"posts a snapshot to the import endpoint\", async () => {\n const snapshot = {\n devices: [\n {\n name: \"Ledger Flex\",\n device_type: \"flex\",\n mocks: [{ prefix: \"e0010000\", responses: [\"aa9000\", \"5515\"] }],\n },\n ],\n };\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"import\",\n response: snapshot,\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const result = await client.importSession(snapshot);\n\n expect(result).toEqual(snapshot);\n expect(http.calls).toContainEqual({\n method: \"post\",\n endpoint: \"import\",\n body: snapshot,\n });\n });\n });\n\n describe(\"apdu\", () => {\n it(\"sends a binary APDU as hex to the device apdu endpoint\", async () => {\n const http = httpClientStubBuilder().mockResponse({\n method: \"post\",\n endpoint: \"devices/dev-1/apdu\",\n response: { response: \"9000\" },\n });\n const client = new MockClient(\"http://localhost:8080\", {\n token: \"tok\",\n httpClient: http,\n });\n\n const result = await client.sendApdu(\n \"dev-1\",\n Uint8Array.from([0xe0, 0x01, 0x00, 0x00]),\n );\n\n expect(result.response).toBe(\"9000\");\n expect(http.calls).toContainEqual({\n method: \"post\",\n endpoint: \"devices/dev-1/apdu\",\n body: { apdu: \"e0010000\" },\n });\n });\n });\n});\n"],
5
+ "mappings": "AAAA,OAAS,yBAAAA,MAA6B,0BACtC,OAAS,cAAAC,MAAkB,eAE3B,MAAMC,EAAU,CAACC,EAAqC,CAAC,KAAO,CAC5D,GAAI,QACJ,KAAM,gBACN,YAAa,QACb,kBAAmB,MACnB,GAAGA,CACL,GAEA,SAAS,aAAc,IAAM,CAC3B,SAAS,iBAAkB,IAAM,CAC/B,GAAG,+DAAgE,SAAY,CAC7E,MAAMC,EAAOJ,EAAsB,EAChC,aAAa,CACZ,OAAQ,OACR,SAAU,OACV,SAAU,CAAE,MAAO,UAAW,WAAY,EAAG,CAC/C,CAAC,EACA,aAAa,CACZ,OAAQ,MACR,SAAU,UACV,SAAU,CAAC,CACb,CAAC,EACGK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,WAAYG,CACd,CAAC,EAEKE,EAAU,MAAMD,EAAO,YAAY,EAEzC,OAAOA,EAAO,SAAS,CAAC,EAAE,KAAK,SAAS,EACxC,OAAOD,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,OACR,SAAU,OACV,KAAM,CAAC,CACT,CAAC,EACD,OAAOE,CAAO,EAAE,QAAQ,CAAC,CAAC,CAC5B,CAAC,EAED,GAAG,+CAAgD,SAAY,CAC7D,MAAMF,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,UACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,WACP,WAAYG,CACd,CAAC,EAED,MAAMC,EAAO,YAAY,EAEzB,OAAOA,EAAO,SAAS,CAAC,EAAE,KAAK,UAAU,EACzC,OACED,EAAK,MAAM,KAAMG,GAASA,EAAK,WAAa,MAAM,CACpD,EAAE,cAAc,CAClB,CAAC,EAED,GAAG,yDAA0D,SAAY,CACvE,MAAMH,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,OACV,SAAU,CAAE,MAAO,UAAW,WAAY,EAAG,CAC/C,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,WAAYG,CACd,CAAC,EAEKI,EAAQ,MAAMH,EAAO,aAAa,EAExC,OAAOG,CAAK,EAAE,KAAK,SAAS,EAC5B,OAAOH,EAAO,SAAS,CAAC,EAAE,KAAK,SAAS,CAC1C,CAAC,EAED,GAAG,+DAAgE,SAAY,CAC7E,MAAMD,EAAOJ,EAAsB,EAChC,aAAa,CACZ,OAAQ,OACR,SAAU,OACV,SAAU,CAAE,MAAO,aAAc,WAAY,CAAE,CACjD,CAAC,EACA,aAAa,CAAE,OAAQ,MAAO,SAAU,UAAW,SAAU,CAAC,CAAE,CAAC,EAC9DK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,WAAYG,CACd,CAAC,EAED,MAAM,QAAQ,IAAI,CAACC,EAAO,YAAY,EAAGA,EAAO,YAAY,CAAC,CAAC,EAE9D,MAAMI,EAAYL,EAAK,MAAM,OAAQG,GAASA,EAAK,WAAa,MAAM,EACtE,OAAOE,CAAS,EAAE,aAAa,CAAC,CAClC,CAAC,EAED,GAAG,4DAA6D,IAAM,CACpE,MAAMJ,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,WAAYD,EAAsB,CACpC,CAAC,EAED,OAAOK,EAAO,SAAS,CAAC,EAAE,cAAc,CAC1C,CAAC,CACH,CAAC,EAED,SAAS,cAAe,IAAM,CAC5B,GAAG,iDAAkD,IAAM,CACzD,MAAMK,EAAY,IAAIT,EAAW,wBAAwB,EACnDU,EAAe,IAAIV,EAAW,uBAAuB,EAE3D,OAAOS,EAAU,SAAS,CAAC,EAAE,cAAc,EAC3C,OAAOC,EAAa,SAAS,CAAC,EAAE,cAAc,CAChD,CAAC,CACH,CAAC,EAED,SAAS,UAAW,IAAM,CACxB,GAAG,gBAAiB,SAAY,CAC9B,MAAMP,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,UACV,SAAU,CAACE,EAAQ,CAAC,CACtB,CAAC,EAMKI,EAAU,MALD,IAAIL,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE4B,YAAY,EAEzC,OAAOE,CAAO,EAAE,QAAQ,CAAC,OAAO,iBAAiB,CAAE,GAAI,OAAQ,CAAC,CAAC,CAAC,CACpE,CAAC,EAED,GAAG,4CAA6C,SAAY,CAC1D,MAAMF,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,UACV,SAAUE,EAAQ,CACpB,CAAC,EAMKU,EAAS,MALA,IAAIX,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,UAAU,EAEtC,OAAOQ,EAAO,EAAE,EAAE,KAAK,OAAO,EAC9B,OAAOR,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,OACR,SAAU,UACV,KAAM,CAAC,CACT,CAAC,CACH,CAAC,EAED,GAAG,uBAAwB,SAAY,CACrC,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,gBACV,SAAUE,EAAQ,CACpB,CAAC,EAMKU,EAAS,MALA,IAAIX,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,UAAU,OAAO,EAE7C,OAAOQ,EAAO,EAAE,EAAE,KAAK,OAAO,CAChC,CAAC,EAED,GAAG,iBAAkB,SAAY,CAC/B,MAAMR,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,QACR,SAAU,gBACV,SAAUE,EAAQ,CAAE,KAAM,SAAU,CAAC,CACvC,CAAC,EAMKU,EAAS,MALA,IAAIX,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,WAAW,QAAS,CAAE,KAAM,SAAU,CAAC,EAEnE,OAAOQ,EAAO,IAAI,EAAE,KAAK,SAAS,EAClC,OAAOR,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,QACR,SAAU,gBACV,KAAM,CAAE,KAAM,SAAU,CAC1B,CAAC,CACH,CAAC,EAED,GAAG,mBAAoB,SAAY,CACjC,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,SACR,SAAU,gBACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,aAAa,OAAO,CAAC,EAAE,SAAS,KAAK,EAAI,EAC7D,OAAOD,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,SACR,SAAU,eACZ,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,mBAAoB,IAAM,CACjC,GAAG,oBAAqB,SAAY,CAClC,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,wBACV,SAAU,CAAE,OAAQE,EAAQ,EAAG,UAAW,EAAK,CACjD,CAAC,EAMKW,EAAQ,MALC,IAAIZ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE0B,QAAQ,OAAO,EAE1C,OAAOS,EAAM,SAAS,EAAE,KAAK,EAAI,EACjC,OAAOA,EAAM,OAAO,EAAE,EAAE,KAAK,OAAO,CACtC,CAAC,EAED,GAAG,uBAAwB,SAAY,CACrC,MAAMT,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,2BACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,WAAW,OAAO,CAAC,EAAE,SAAS,KAAK,EAAI,CAC7D,CAAC,EAED,GAAG,qCAAsC,SAAY,CACnD,MAAMD,EAAOJ,EAAsB,EAChC,aAAa,CACZ,OAAQ,MACR,SAAU,UACV,SAAU,CACRE,EAAQ,CAAE,GAAI,QAAS,UAAW,EAAK,CAAC,EACxCA,EAAQ,CAAE,GAAI,QAAS,UAAW,EAAM,CAAC,EACzCA,EAAQ,CAAE,GAAI,QAAS,UAAW,EAAK,CAAC,CAC1C,CACF,CAAC,EACA,aAAa,CACZ,OAAQ,OACR,SAAU,2BACV,SAAU,CAAC,CACb,CAAC,EACA,aAAa,CACZ,OAAQ,OACR,SAAU,2BACV,SAAU,CAAC,CACb,CAAC,EACGG,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,cAAc,CAAC,EAAE,SAAS,KAAK,EAAI,EAEvD,MAAMS,EAAkBV,EAAK,MAAM,OAAQG,GACzCA,EAAK,SAAS,SAAS,aAAa,CACtC,EACA,OAAOO,EAAgB,IAAKP,GAASA,EAAK,QAAQ,CAAC,EAAE,QAAQ,CAC3D,2BACA,0BACF,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,QAAS,IAAM,CACtB,GAAG,4BAA6B,SAAY,CAC1C,MAAMH,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,sBACV,SAAU,CAAC,CAAE,GAAI,KAAM,OAAQ,WAAY,UAAW,CAAC,MAAM,CAAE,CAAC,CAClE,CAAC,EAMKe,EAAQ,MALC,IAAId,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE0B,UAAU,OAAO,EAE5C,OAAOW,CAAK,EAAE,QAAQ,CAAC,OAAO,iBAAiB,CAAE,GAAI,IAAK,CAAC,CAAC,CAAC,CAC/D,CAAC,EAED,GAAG,+BAAgC,SAAY,CAC7C,MAAMX,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,sBACV,SAAU,CAAE,GAAI,KAAM,OAAQ,WAAY,UAAW,CAAC,MAAM,CAAE,CAChE,CAAC,EAMKgB,EAAO,MALE,IAAIf,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAEyB,QAAQ,QAAS,CACzC,OAAQ,WACR,SAAU,MACZ,CAAC,EAED,OAAOY,EAAK,EAAE,EAAE,KAAK,IAAI,EACzB,OAAOZ,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,OACR,SAAU,sBACV,KAAM,CAAE,OAAQ,WAAY,SAAU,MAAO,CAC/C,CAAC,CACH,CAAC,EAED,GAAG,eAAgB,SAAY,CAC7B,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,QACR,SAAU,yBACV,SAAU,CAAE,GAAI,KAAM,OAAQ,WAAY,UAAW,CAAC,MAAM,CAAE,CAChE,CAAC,EAMKgB,EAAO,MALE,IAAIf,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAEyB,SAAS,QAAS,KAAM,CAChD,OAAQ,WACR,SAAU,MACZ,CAAC,EAED,OAAOY,EAAK,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvC,OAAOZ,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,QACR,SAAU,yBACV,KAAM,CAAE,OAAQ,WAAY,SAAU,MAAO,CAC/C,CAAC,CACH,CAAC,EAED,GAAG,wBAAyB,SAAY,CACtC,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,SACR,SAAU,yBACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,WAAW,QAAS,IAAI,CAAC,EAAE,SAAS,KAAK,EAAI,EACjE,OAAOD,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,SACR,SAAU,wBACZ,CAAC,CACH,CAAC,EAED,GAAG,+BAAgC,SAAY,CAC7C,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,SACR,SAAU,sBACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,WAAW,OAAO,CAAC,EAAE,SAAS,KAAK,EAAI,EAC3D,OAAOD,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,SACR,SAAU,qBACZ,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,WAAY,IAAM,CACzB,GAAG,uDAAwD,SAAY,CACrE,MAAMA,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,yBACV,SAAU,CACR,OAAQ,QACR,aAAc,wBACd,MAAO,MACT,CACF,CAAC,EAMKiB,EAAW,MALF,IAAIhB,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE6B,YAAY,OAAO,EAEjD,OAAOa,CAAQ,EAAE,QAAQ,CACvB,OAAQ,QACR,aAAc,wBACd,MAAO,MACT,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,UAAW,IAAM,CACxB,GAAG,8BAA+B,SAAY,CAC5C,MAAMb,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,mBACV,SAAU,CACR,GAAI,SACJ,WAAY,EACZ,WAAY,EACZ,QAAS,CAACE,EAAQ,CAAC,CACrB,CACF,CAAC,EAMKgB,EAAU,MALD,IAAIjB,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE4B,WAAW,EAExC,OAAOc,EAAQ,EAAE,EAAE,KAAK,QAAQ,EAChC,OAAOA,EAAQ,OAAO,EAAE,aAAa,CAAC,CACxC,CAAC,EAED,GAAG,mDAAoD,SAAY,CACjE,MAAMd,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,SACR,SAAU,mBACV,SAAU,CAAC,CACb,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,eAAe,CAAC,EAAE,SAAS,KAAK,EAAI,EACxD,OAAOA,EAAO,SAAS,CAAC,EAAE,cAAc,CAC1C,CAAC,CACH,CAAC,EAED,SAAS,sBAAuB,IAAM,CACpC,GAAG,mEAAoE,SAAY,CACjF,MAAMD,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,gBACV,SAAU,CAAE,GAAI,GAAI,CACtB,CAAC,EACKK,EAAS,IAAIJ,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAED,MAAM,OAAOC,EAAO,UAAU,OAAO,CAAC,EAAE,QAAQ,QAC9C,qCACF,CACF,CAAC,CACH,CAAC,EAED,SAAS,gBAAiB,IAAM,CAC9B,GAAG,+BAAgC,SAAY,CAC7C,MAAMc,EAAW,CACf,QAAS,CACP,CACE,KAAM,cACN,YAAa,OACb,MAAO,CAAC,CAAE,OAAQ,KAAM,UAAW,CAAC,MAAM,CAAE,CAAC,CAC/C,CACF,CACF,EACMf,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,MACR,SAAU,SACV,SAAUmB,CACZ,CAAC,EAMKC,EAAS,MALA,IAAInB,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,cAAc,EAE1C,OAAOgB,CAAM,EAAE,QAAQD,CAAQ,CACjC,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMA,EAAW,CACf,QAAS,CACP,CACE,KAAM,cACN,YAAa,OACb,MAAO,CAAC,CAAE,OAAQ,WAAY,UAAW,CAAC,SAAU,MAAM,CAAE,CAAC,CAC/D,CACF,CACF,EACMf,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,SACV,SAAUmB,CACZ,CAAC,EAMKC,EAAS,MALA,IAAInB,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,cAAce,CAAQ,EAElD,OAAOC,CAAM,EAAE,QAAQD,CAAQ,EAC/B,OAAOf,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,OACR,SAAU,SACV,KAAMe,CACR,CAAC,CACH,CAAC,CACH,CAAC,EAED,SAAS,OAAQ,IAAM,CACrB,GAAG,yDAA0D,SAAY,CACvE,MAAMf,EAAOJ,EAAsB,EAAE,aAAa,CAChD,OAAQ,OACR,SAAU,qBACV,SAAU,CAAE,SAAU,MAAO,CAC/B,CAAC,EAMKoB,EAAS,MALA,IAAInB,EAAW,wBAAyB,CACrD,MAAO,MACP,WAAYG,CACd,CAAC,EAE2B,SAC1B,QACA,WAAW,KAAK,CAAC,IAAM,EAAM,EAAM,CAAI,CAAC,CAC1C,EAEA,OAAOgB,EAAO,QAAQ,EAAE,KAAK,MAAM,EACnC,OAAOhB,EAAK,KAAK,EAAE,eAAe,CAChC,OAAQ,OACR,SAAU,qBACV,KAAM,CAAE,KAAM,UAAW,CAC3B,CAAC,CACH,CAAC,CACH,CAAC,CACH,CAAC",
6
+ "names": ["httpClientStubBuilder", "MockClient", "aDevice", "overrides", "http", "client", "devices", "call", "token", "authCalls", "withSlash", "withoutSlash", "device", "state", "disconnectCalls", "mocks", "mock", "instance", "session", "snapshot", "result"]
7
+ }
@@ -1,2 +1,2 @@
1
- import{MockClient as r}from"./MockClient";import{CommandResponse as p}from"./model/CommandResponse";import{Device as f}from"./model/Device";import{Mock as n}from"./model/Mock";import{Session as c}from"./model/Session";export{p as CommandResponse,f as Device,n as Mock,r as MockClient,c as Session};
1
+ import{MockClient as t}from"./MockClient";import{deviceConfigCodec as n}from"./model/Device";import{mockConfigCodec as r}from"./model/Mock";import{sessionExportCodec as s}from"./model/SessionExport";export{t as MockClient,n as deviceConfigCodec,r as mockConfigCodec,s as sessionExportCodec};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/index.ts"],
4
- "sourcesContent": ["export { MockClient } from \"./MockClient\";\nexport { CommandResponse } from \"./model/CommandResponse\";\nexport { Device } from \"./model/Device\";\nexport { Mock } from \"./model/Mock\";\nexport { Session } from \"./model/Session\";\n"],
5
- "mappings": "AAAA,OAAS,cAAAA,MAAkB,eAC3B,OAAS,mBAAAC,MAAuB,0BAChC,OAAS,UAAAC,MAAc,iBACvB,OAAS,QAAAC,MAAY,eACrB,OAAS,WAAAC,MAAe",
6
- "names": ["MockClient", "CommandResponse", "Device", "Mock", "Session"]
4
+ "sourcesContent": ["export type { MockClientOptions } from \"./MockClient\";\nexport { MockClient } from \"./MockClient\";\nexport type { AuthResponse, ConnectionState } from \"./model/Auth\";\nexport type { CommandResponse } from \"./model/CommandResponse\";\nexport {\n type Device,\n type DeviceApp,\n type DeviceConfig,\n deviceConfigCodec,\n type DeviceConnectivityType,\n} from \"./model/Device\";\nexport { type Mock, type MockConfig, mockConfigCodec } from \"./model/Mock\";\nexport type { Session } from \"./model/Session\";\nexport { type SessionExport, sessionExportCodec } from \"./model/SessionExport\";\nexport type { SpeculosInstance } from \"./model/Speculos\";\n"],
5
+ "mappings": "AACA,OAAS,cAAAA,MAAkB,eAG3B,OAIE,qBAAAC,MAEK,iBACP,OAAqC,mBAAAC,MAAuB,eAE5D,OAA6B,sBAAAC,MAA0B",
6
+ "names": ["MockClient", "deviceConfigCodec", "mockConfigCodec", "sessionExportCodec"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{boolean as o,Codec as e,number as n,string as t}from"purify-ts";import{deviceCodec as c}from"./Device";const a=e.interface({token:t,expires_at:n}),d=e.interface({device:c,connected:o});export{a as authResponseCodec,d as connectionStateCodec};
2
+ //# sourceMappingURL=Auth.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/model/Auth.ts"],
4
+ "sourcesContent": ["import { boolean, Codec, number, string } from \"purify-ts\";\n\nimport { type Device, deviceCodec } from \"./Device\";\n\n/**\n * Response of POST /auth: an opaque bearer token identifying a session and its\n * expiry timestamp (epoch ms).\n */\nexport interface AuthResponse {\n readonly token: string;\n readonly expires_at: number;\n}\n\nexport const authResponseCodec = Codec.interface({\n token: string,\n expires_at: number,\n});\n\n/**\n * State returned when connecting a device (POST /devices/:id/connect).\n */\nexport interface ConnectionState {\n readonly device: Device;\n readonly connected: boolean;\n}\n\nexport const connectionStateCodec = Codec.interface({\n device: deviceCodec,\n connected: boolean,\n});\n"],
5
+ "mappings": "AAAA,OAAS,WAAAA,EAAS,SAAAC,EAAO,UAAAC,EAAQ,UAAAC,MAAc,YAE/C,OAAsB,eAAAC,MAAmB,WAWlC,MAAMC,EAAoBJ,EAAM,UAAU,CAC/C,MAAOE,EACP,WAAYD,CACd,CAAC,EAUYI,EAAuBL,EAAM,UAAU,CAClD,OAAQG,EACR,UAAWJ,CACb,CAAC",
6
+ "names": ["boolean", "Codec", "number", "string", "deviceCodec", "authResponseCodec", "connectionStateCodec"]
7
+ }
@@ -1,2 +1,2 @@
1
- class o{response;constructor({response:s}){this.response=s}}export{o as CommandResponse};
1
+ import{Codec as e,string as o}from"purify-ts";const r=e.interface({response:o});export{r as commandResponseCodec};
2
2
  //# sourceMappingURL=CommandResponse.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/model/CommandResponse.ts"],
4
- "sourcesContent": ["export type CommandResponseArgs = {\n readonly response: string;\n};\n\nexport class CommandResponse {\n readonly response: string;\n\n constructor({ response }: CommandResponseArgs) {\n this.response = response;\n }\n}\n"],
5
- "mappings": "AAIO,MAAMA,CAAgB,CAClB,SAET,YAAY,CAAE,SAAAC,CAAS,EAAwB,CAC7C,KAAK,SAAWA,CAClB,CACF",
6
- "names": ["CommandResponse", "response"]
4
+ "sourcesContent": ["import { Codec, string } from \"purify-ts\";\n\n/**\n * The result of simulating an APDU exchange (POST /devices/:id/apdu).\n *\n * {@link CommandResponse.response} is the full response hex, data followed by the\n * two-byte status word.\n */\nexport interface CommandResponse {\n readonly response: string;\n}\n\nexport const commandResponseCodec = Codec.interface({\n response: string,\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,UAAAC,MAAc,YAYvB,MAAMC,EAAuBF,EAAM,UAAU,CAClD,SAAUC,CACZ,CAAC",
6
+ "names": ["Codec", "string", "commandResponseCodec"]
7
7
  }
@@ -1,2 +1,2 @@
1
- class y{id;name;device_type;connectivity_type;constructor({id:e,name:t,device_type:i,connectivity_type:n}){this.id=e,this.name=t,this.device_type=i,this.connectivity_type=n}}export{y as Device};
1
+ import{array as o,boolean as a,Codec as r,number as i,optional as e,string as n}from"purify-ts";import{mockConfigCodec as c}from"./Mock";const t=r.interface({name:n,version:n}),y=r.interface({id:n,name:n,device_type:n,connectivity_type:n,firmware_version:e(n),apps:e(o(t)),masks:e(o(i)),connected:e(a)}),d=r.interface({name:e(n),device_type:e(n),connectivity_type:e(n),firmware_version:e(n),apps:e(o(t)),masks:e(o(i)),mocks:e(o(c))});export{t as deviceAppCodec,y as deviceCodec,d as deviceConfigCodec};
2
2
  //# sourceMappingURL=Device.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/model/Device.ts"],
4
- "sourcesContent": ["export type DeviceArgs = {\n readonly id: string;\n readonly name: string;\n readonly device_type: string;\n readonly connectivity_type: string;\n};\n\nexport class Device {\n readonly id: string;\n readonly name: string;\n readonly device_type: string;\n readonly connectivity_type: string;\n\n constructor({ id, name, device_type, connectivity_type }: DeviceArgs) {\n this.id = id;\n this.name = name;\n this.device_type = device_type;\n this.connectivity_type = connectivity_type;\n }\n}\n"],
5
- "mappings": "AAOO,MAAMA,CAAO,CACT,GACA,KACA,YACA,kBAET,YAAY,CAAE,GAAAC,EAAI,KAAAC,EAAM,YAAAC,EAAa,kBAAAC,CAAkB,EAAe,CACpE,KAAK,GAAKH,EACV,KAAK,KAAOC,EACZ,KAAK,YAAcC,EACnB,KAAK,kBAAoBC,CAC3B,CACF",
6
- "names": ["Device", "id", "name", "device_type", "connectivity_type"]
4
+ "sourcesContent": ["import { array, boolean, Codec, number, optional, string } from \"purify-ts\";\n\nimport { type MockConfig, mockConfigCodec } from \"./Mock\";\n\nexport type DeviceConnectivityType = \"USB\" | \"BLE\";\n\nexport interface DeviceApp {\n readonly name: string;\n readonly version: string;\n}\n\nexport const deviceAppCodec = Codec.interface({\n name: string,\n version: string,\n});\n\n/**\n * A mocked device attached to a session.\n *\n * The device exposes rich metadata (firmware\n * version, installed applications, memory masks) so DMK can build a realistic\n * device session.\n */\nexport interface Device {\n readonly id: string;\n readonly name: string;\n /** DeviceModelId enum value, e.g. \"nanoX\", \"stax\", \"flex\". */\n readonly device_type: string;\n readonly connectivity_type: string;\n readonly firmware_version?: string;\n readonly apps?: DeviceApp[];\n readonly masks?: number[];\n readonly connected?: boolean;\n}\n\nexport const deviceCodec = Codec.interface({\n id: string,\n name: string,\n device_type: string,\n connectivity_type: string,\n firmware_version: optional(string),\n apps: optional(array(deviceAppCodec)),\n masks: optional(array(number)),\n connected: optional(boolean),\n});\n\n/**\n * Payload used to attach (POST /devices) or edit (PATCH /devices/:id) a device.\n */\nexport interface DeviceConfig {\n readonly name?: string;\n readonly device_type?: string;\n readonly connectivity_type?: string;\n readonly firmware_version?: string;\n readonly apps?: DeviceApp[];\n readonly masks?: number[];\n /** Device-scoped APDU mocks, used when attaching (POST) or importing a device. */\n readonly mocks?: MockConfig[];\n}\n\nexport const deviceConfigCodec = Codec.interface({\n name: optional(string),\n device_type: optional(string),\n connectivity_type: optional(string),\n firmware_version: optional(string),\n apps: optional(array(deviceAppCodec)),\n masks: optional(array(number)),\n mocks: optional(array(mockConfigCodec)),\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,WAAAC,EAAS,SAAAC,EAAO,UAAAC,EAAQ,YAAAC,EAAU,UAAAC,MAAc,YAEhE,OAA0B,mBAAAC,MAAuB,SAS1C,MAAMC,EAAiBL,EAAM,UAAU,CAC5C,KAAMG,EACN,QAASA,CACX,CAAC,EAqBYG,EAAcN,EAAM,UAAU,CACzC,GAAIG,EACJ,KAAMA,EACN,YAAaA,EACb,kBAAmBA,EACnB,iBAAkBD,EAASC,CAAM,EACjC,KAAMD,EAASJ,EAAMO,CAAc,CAAC,EACpC,MAAOH,EAASJ,EAAMG,CAAM,CAAC,EAC7B,UAAWC,EAASH,CAAO,CAC7B,CAAC,EAgBYQ,EAAoBP,EAAM,UAAU,CAC/C,KAAME,EAASC,CAAM,EACrB,YAAaD,EAASC,CAAM,EAC5B,kBAAmBD,EAASC,CAAM,EAClC,iBAAkBD,EAASC,CAAM,EACjC,KAAMD,EAASJ,EAAMO,CAAc,CAAC,EACpC,MAAOH,EAASJ,EAAMG,CAAM,CAAC,EAC7B,MAAOC,EAASJ,EAAMM,CAAe,CAAC,CACxC,CAAC",
6
+ "names": ["array", "boolean", "Codec", "number", "optional", "string", "mockConfigCodec", "deviceAppCodec", "deviceCodec", "deviceConfigCodec"]
7
7
  }
@@ -1,2 +1,2 @@
1
- class o{prefix;response;constructor({prefix:r,response:s}){this.prefix=r,this.response=s}}export{o as Mock};
1
+ import{array as o,Codec as n,optional as r,string as e}from"purify-ts";const i=n.interface({id:e,prefix:e,responses:o(e)}),t=n.interface({prefix:e,response:r(e),responses:r(o(e))});export{i as mockCodec,t as mockConfigCodec};
2
2
  //# sourceMappingURL=Mock.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/model/Mock.ts"],
4
- "sourcesContent": ["export type MockArgs = {\n readonly prefix: string;\n readonly response: string;\n};\n\nexport class Mock {\n readonly prefix: string;\n readonly response: string;\n\n constructor({ prefix, response }: MockArgs) {\n this.prefix = prefix;\n this.response = response;\n }\n}\n"],
5
- "mappings": "AAKO,MAAMA,CAAK,CACP,OACA,SAET,YAAY,CAAE,OAAAC,EAAQ,SAAAC,CAAS,EAAa,CAC1C,KAAK,OAASD,EACd,KAAK,SAAWC,CAClB,CACF",
6
- "names": ["Mock", "prefix", "response"]
4
+ "sourcesContent": ["import { array, Codec, optional, string } from \"purify-ts\";\n\n/**\n * A canned APDU response registered against a device.\n *\n * Whenever an incoming APDU starts with {@link Mock.prefix} (hex), the mock\n * server returns the next entry of {@link Mock.responses}, advancing one entry\n * per matching APDU and looping back to the start once the list is exhausted.\n * Mocks are device-scoped: each device owns its own independent mock table.\n */\nexport interface Mock {\n readonly id: string;\n readonly prefix: string;\n readonly responses: string[];\n}\n\nexport const mockCodec = Codec.interface({\n id: string,\n prefix: string,\n responses: array(string),\n});\n\n/**\n * Payload used to create (POST /mocks) or edit (PATCH /mocks/:id) a mock.\n *\n * Provide either an ordered {@link MockConfig.responses} list or a single\n * {@link MockConfig.response} (shorthand for `responses: [response]`).\n */\nexport interface MockConfig {\n readonly prefix: string;\n readonly response?: string;\n readonly responses?: string[];\n}\n\nexport const mockConfigCodec = Codec.interface({\n prefix: string,\n response: optional(string),\n responses: optional(array(string)),\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,SAAAC,EAAO,YAAAC,EAAU,UAAAC,MAAc,YAgBxC,MAAMC,EAAYH,EAAM,UAAU,CACvC,GAAIE,EACJ,OAAQA,EACR,UAAWH,EAAMG,CAAM,CACzB,CAAC,EAcYE,EAAkBJ,EAAM,UAAU,CAC7C,OAAQE,EACR,SAAUD,EAASC,CAAM,EACzB,UAAWD,EAASF,EAAMG,CAAM,CAAC,CACnC,CAAC",
6
+ "names": ["array", "Codec", "optional", "string", "mockCodec", "mockConfigCodec"]
7
7
  }
@@ -1,2 +1,2 @@
1
- class s{id;device;currentApp;created_at;constructor({id:e,device:r,current_app:t,created_at:i}){this.id=e,this.device=r,this.currentApp=t,this.created_at=i}}export{s as Session};
1
+ import{array as r,Codec as i,number as e,string as o}from"purify-ts";import{deviceCodec as t}from"./Device";const n=i.interface({id:o,created_at:e,expires_at:e,devices:r(t)});export{n as sessionCodec};
2
2
  //# sourceMappingURL=Session.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/model/Session.ts"],
4
- "sourcesContent": ["import { type Device } from \"./Device\";\n\nexport type SessionArgs = {\n readonly id: string;\n readonly device: Device;\n readonly current_app: string;\n readonly created_at: number;\n};\n\nexport class Session {\n readonly id: string;\n readonly device: Device;\n readonly currentApp: string;\n readonly created_at: number;\n\n constructor({ id, device, current_app, created_at }: SessionArgs) {\n this.id = id;\n this.device = device;\n this.currentApp = current_app;\n this.created_at = created_at;\n }\n}\n"],
5
- "mappings": "AASO,MAAMA,CAAQ,CACV,GACA,OACA,WACA,WAET,YAAY,CAAE,GAAAC,EAAI,OAAAC,EAAQ,YAAAC,EAAa,WAAAC,CAAW,EAAgB,CAChE,KAAK,GAAKH,EACV,KAAK,OAASC,EACd,KAAK,WAAaC,EAClB,KAAK,WAAaC,CACpB,CACF",
6
- "names": ["Session", "id", "device", "current_app", "created_at"]
4
+ "sourcesContent": ["import { array, Codec, number, string } from \"purify-ts\";\n\nimport { type Device, deviceCodec } from \"./Device\";\n\n/**\n * A mock server session, resolved from a bearer token.\n *\n * All devices and mocks are scoped to the session that owns the token.\n */\nexport interface Session {\n readonly id: string;\n readonly created_at: number;\n readonly expires_at: number;\n readonly devices: Device[];\n}\n\nexport const sessionCodec = Codec.interface({\n id: string,\n created_at: number,\n expires_at: number,\n devices: array(deviceCodec),\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,SAAAC,EAAO,UAAAC,EAAQ,UAAAC,MAAc,YAE7C,OAAsB,eAAAC,MAAmB,WAclC,MAAMC,EAAeJ,EAAM,UAAU,CAC1C,GAAIE,EACJ,WAAYD,EACZ,WAAYA,EACZ,QAASF,EAAMI,CAAW,CAC5B,CAAC",
6
+ "names": ["array", "Codec", "number", "string", "deviceCodec", "sessionCodec"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{array as e,Codec as o}from"purify-ts";import{deviceConfigCodec as i}from"./Device";const t=o.interface({devices:e(i)});export{t as sessionExportCodec};
2
+ //# sourceMappingURL=SessionExport.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/model/SessionExport.ts"],
4
+ "sourcesContent": ["import { array, Codec } from \"purify-ts\";\n\nimport { type DeviceConfig, deviceConfigCodec } from \"./Device\";\n\n/**\n * A portable snapshot of a session's devices (and their mocks).\n *\n * Produced by `GET /export` and consumed by `POST /import` to save and restore\n * complex scenarios. Only configuration is captured (no ids, connection state\n * or response cursors), so importing recreates a fresh, deterministic session\n * state. Mocks are nested under each device (`DeviceConfig.mocks`).\n */\nexport interface SessionExport {\n readonly devices: DeviceConfig[];\n}\n\nexport const sessionExportCodec = Codec.interface({\n devices: array(deviceConfigCodec),\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,SAAAC,MAAa,YAE7B,OAA4B,qBAAAC,MAAyB,WAc9C,MAAMC,EAAqBF,EAAM,UAAU,CAChD,QAASD,EAAME,CAAiB,CAClC,CAAC",
6
+ "names": ["array", "Codec", "deviceConfigCodec", "sessionExportCodec"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{Codec as r,string as e}from"purify-ts";const o=r.interface({run_id:e,speculos_url:e,model:e});export{o as speculosInstanceCodec};
2
+ //# sourceMappingURL=Speculos.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/model/Speculos.ts"],
4
+ "sourcesContent": ["import { Codec, string } from \"purify-ts\";\n\n/**\n * The live Speculos emulator instance backing a device, returned by\n * `GET /devices/:id/speculos`. Control calls are proxied through\n * `/devices/:id/speculos/*`.\n */\nexport interface SpeculosInstance {\n /** Speculinho run id owning the emulator pod. */\n readonly run_id: string;\n /** Per-pod emulator URL (reachable from the mock server). */\n readonly speculos_url: string;\n /** Device model (e.g. \"nanoX\", \"stax\", \"flex\"). */\n readonly model: string;\n}\n\nexport const speculosInstanceCodec = Codec.interface({\n run_id: string,\n speculos_url: string,\n model: string,\n});\n"],
5
+ "mappings": "AAAA,OAAS,SAAAA,EAAO,UAAAC,MAAc,YAgBvB,MAAMC,EAAwBF,EAAM,UAAU,CACnD,OAAQC,EACR,aAAcA,EACd,MAAOA,CACT,CAAC",
6
+ "names": ["Codec", "string", "speculosInstanceCodec"]
7
+ }
@@ -0,0 +1,18 @@
1
+ import { type DmkNetworkClient } from "@ledgerhq/device-management-kit";
2
+ type Method = "get" | "post" | "patch" | "delete";
3
+ export type DmkNetworkClientStub = DmkNetworkClient & {
4
+ responses: Record<Method, Record<string, unknown>>;
5
+ calls: {
6
+ method: Method;
7
+ endpoint: string;
8
+ body?: object;
9
+ }[];
10
+ mockResponse(args: {
11
+ method: Method;
12
+ endpoint: string;
13
+ response: object;
14
+ }): DmkNetworkClientStub;
15
+ };
16
+ export declare const httpClientStubBuilder: () => DmkNetworkClientStub;
17
+ export {};
18
+ //# sourceMappingURL=DmkNetworkClient.stub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DmkNetworkClient.stub.d.ts","sourceRoot":"","sources":["../../../src/DmkNetworkClient.stub.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,iCAAiC,CAAC;AAEzC,KAAK,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7D,YAAY,CAAC,IAAI,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,oBAAoB,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,oBA2DxC,CAAC"}
@@ -1,27 +1,70 @@
1
+ import { DmkNetworkClient } from "@ledgerhq/device-management-kit";
2
+ import { type ConnectionState } from "./model/Auth";
1
3
  import { type CommandResponse } from "./model/CommandResponse";
2
- import { type Device } from "./model/Device";
3
- import { type Mock } from "./model/Mock";
4
+ import { type Device, type DeviceConfig } from "./model/Device";
5
+ import { type Mock, type MockConfig } from "./model/Mock";
4
6
  import { type Session } from "./model/Session";
5
- import { ConnectivityService } from "./service/ConnectivityService";
6
- import { DiscoveryService } from "./service/DiscoveryService";
7
- import { MockService } from "./service/MockService";
8
- import { SendService } from "./service/SendService";
7
+ import { type SessionExport } from "./model/SessionExport";
8
+ import { type SpeculosInstance } from "./model/Speculos";
9
+ export interface MockClientOptions {
10
+ /**
11
+ * An existing mock server session token. When provided the client operates
12
+ * within that session; when omitted the client lazily creates its own session
13
+ * through POST /auth.
14
+ */
15
+ readonly token?: string;
16
+ /** Inject a custom network client (mainly for testing). */
17
+ readonly httpClient?: DmkNetworkClient;
18
+ }
19
+ /**
20
+ * HTTP client for the device mock server.
21
+ *
22
+ * Implements the bearer-token contract: the session is
23
+ * resolved from an `Authorization: Bearer <token>` header rather than a
24
+ * `session_id` header, and sessions, devices and mocks are exposed as REST
25
+ * resources. The token can be injected or self-provisioned via /auth.
26
+ */
9
27
  export declare class MockClient {
10
- connectivityService: ConnectivityService;
11
- sendService: SendService;
12
- discoveryService: DiscoveryService;
13
- mockService: MockService;
14
- constructor(baseUrl: string);
15
- connect(sessionId: string): Promise<Session>;
16
- disconnect(sessionId: string): Promise<boolean>;
28
+ private readonly client;
29
+ private token?;
30
+ private authPromise?;
31
+ constructor(baseUrl: string, options?: MockClientOptions);
32
+ /** Create a session and store the returned bearer token. */
33
+ authenticate(): Promise<string>;
34
+ /** The current bearer token, if a session has been established. */
35
+ getToken(): string | undefined;
36
+ listDevices(): Promise<Device[]>;
37
+ addDevice(config?: DeviceConfig): Promise<Device>;
38
+ getDevice(deviceId: string): Promise<Device>;
39
+ editDevice(deviceId: string, config: DeviceConfig): Promise<Device>;
40
+ deleteDevice(deviceId: string): Promise<boolean>;
41
+ connect(deviceId: string): Promise<ConnectionState>;
42
+ disconnect(deviceId: string): Promise<boolean>;
43
+ /** Disconnect every device attached to the session. */
17
44
  disconnectAll(): Promise<boolean>;
18
- getConnected(): Promise<Session[]>;
19
- send(sessionId: string, binaryCommand: Uint8Array): Promise<CommandResponse>;
20
- scan(nbDevices?: number): Promise<Device[]>;
21
- addMock(sessionId: string, prefix: string, response: string): Promise<boolean>;
22
- getMocks(sessionId: string): Promise<Mock[]>;
23
- deleteMocks(sessionId: string): Promise<boolean>;
24
- toHexString(arr: Uint8Array): string;
25
- fromHexString(hexString: string): Uint8Array;
45
+ sendApdu(deviceId: string, apdu: Uint8Array | string): Promise<CommandResponse>;
46
+ listMocks(deviceId: string): Promise<Mock[]>;
47
+ addMock(deviceId: string, config: MockConfig): Promise<Mock>;
48
+ editMock(deviceId: string, mockId: string, config: MockConfig): Promise<Mock>;
49
+ deleteMock(deviceId: string, mockId: string): Promise<boolean>;
50
+ clearMocks(deviceId: string): Promise<boolean>;
51
+ /**
52
+ * Resolve the live Speculos instance backing a device (the one currently
53
+ * proxying its APDUs). Throws if the device has no active instance.
54
+ */
55
+ getSpeculos(deviceId: string): Promise<SpeculosInstance>;
56
+ getSession(): Promise<Session>;
57
+ disposeSession(): Promise<boolean>;
58
+ /** Export the session's devices and mocks as a portable snapshot. */
59
+ exportSession(): Promise<SessionExport>;
60
+ /**
61
+ * Replace the session's devices and mocks with a previously exported
62
+ * snapshot, returning the resulting (normalized) state.
63
+ */
64
+ importSession(snapshot: SessionExport): Promise<SessionExport>;
65
+ private decode;
66
+ private authHeaders;
67
+ private ensureToken;
68
+ private normalizeUrl;
26
69
  }
27
70
  //# sourceMappingURL=MockClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MockClient.d.ts","sourceRoot":"","sources":["../../../src/MockClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,qBAAa,UAAU;IAErB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;gBAEb,OAAO,EAAE,MAAM;IAQrB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5C,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/C,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjC,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAIlC,IAAI,CACR,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,UAAU,GACxB,OAAO,CAAC,eAAe,CAAC;IAKrB,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI3C,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC;IAIb,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAI5C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKtD,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM;IAIpC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU;CAQ7C"}
1
+ {"version":3,"file":"MockClient.d.ts","sourceRoot":"","sources":["../../../src/MockClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EACjB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,MAAM,EAAe,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,KAAK,IAAI,EAAa,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,KAAK,gBAAgB,EAAyB,MAAM,kBAAkB,CAAC;AAEhF,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,WAAW,CAAC,CAAkB;gBAE1B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;IAS5D,4DAA4D;IACtD,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAOrC,mEAAmE;IACnE,QAAQ,IAAI,MAAM,GAAG,SAAS;IAMxB,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOhC,SAAS,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAOrD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO5C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAOnE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAShD,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IASnD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpD,uDAAuD;IACjD,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAYjC,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,GAAG,MAAM,GACxB,OAAO,CAAC,eAAe,CAAC;IAarB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAO5C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC;IASV,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO9D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpD;;;OAGG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IASxD,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAO9B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAWxC,qEAAqE;IAC/D,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;IAO7C;;;OAGG;IACG,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IASpE,OAAO,CAAC,MAAM;YASA,WAAW;IAKzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,YAAY;CAGrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MockClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockClient.test.d.ts","sourceRoot":"","sources":["../../../src/MockClient.test.ts"],"names":[],"mappings":""}
@@ -1,6 +1,10 @@
1
+ export type { MockClientOptions } from "./MockClient";
1
2
  export { MockClient } from "./MockClient";
2
- export { CommandResponse } from "./model/CommandResponse";
3
- export { Device } from "./model/Device";
4
- export { Mock } from "./model/Mock";
5
- export { Session } from "./model/Session";
3
+ export type { AuthResponse, ConnectionState } from "./model/Auth";
4
+ export type { CommandResponse } from "./model/CommandResponse";
5
+ export { type Device, type DeviceApp, type DeviceConfig, deviceConfigCodec, type DeviceConnectivityType, } from "./model/Device";
6
+ export { type Mock, type MockConfig, mockConfigCodec } from "./model/Mock";
7
+ export type { Session } from "./model/Session";
8
+ export { type SessionExport, sessionExportCodec } from "./model/SessionExport";
9
+ export type { SpeculosInstance } from "./model/Speculos";
6
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EACL,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3E,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,KAAK,aAAa,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { Codec } from "purify-ts";
2
+ import { type Device } from "./Device";
3
+ /**
4
+ * Response of POST /auth: an opaque bearer token identifying a session and its
5
+ * expiry timestamp (epoch ms).
6
+ */
7
+ export interface AuthResponse {
8
+ readonly token: string;
9
+ readonly expires_at: number;
10
+ }
11
+ export declare const authResponseCodec: Codec<{
12
+ token: string;
13
+ expires_at: number;
14
+ }>;
15
+ /**
16
+ * State returned when connecting a device (POST /devices/:id/connect).
17
+ */
18
+ export interface ConnectionState {
19
+ readonly device: Device;
20
+ readonly connected: boolean;
21
+ }
22
+ export declare const connectionStateCodec: Codec<{
23
+ device: {
24
+ id: string;
25
+ name: string;
26
+ device_type: string;
27
+ connectivity_type: string;
28
+ firmware_version: string | undefined;
29
+ apps: {
30
+ name: string;
31
+ version: string;
32
+ }[] | undefined;
33
+ masks: number[] | undefined;
34
+ connected: boolean | undefined;
35
+ };
36
+ connected: boolean;
37
+ }>;
38
+ //# sourceMappingURL=Auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Auth.d.ts","sourceRoot":"","sources":["../../../../src/model/Auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,EAAkB,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,UAAU,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,iBAAiB;;;EAG5B,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;EAG/B,CAAC"}
@@ -1,8 +1,14 @@
1
- export type CommandResponseArgs = {
1
+ import { Codec } from "purify-ts";
2
+ /**
3
+ * The result of simulating an APDU exchange (POST /devices/:id/apdu).
4
+ *
5
+ * {@link CommandResponse.response} is the full response hex, data followed by the
6
+ * two-byte status word.
7
+ */
8
+ export interface CommandResponse {
2
9
  readonly response: string;
3
- };
4
- export declare class CommandResponse {
5
- readonly response: string;
6
- constructor({ response }: CommandResponseArgs);
7
10
  }
11
+ export declare const commandResponseCodec: Codec<{
12
+ response: string;
13
+ }>;
8
14
  //# sourceMappingURL=CommandResponse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommandResponse.d.ts","sourceRoot":"","sources":["../../../../src/model/CommandResponse.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,qBAAa,eAAe;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,EAAE,QAAQ,EAAE,EAAE,mBAAmB;CAG9C"}
1
+ {"version":3,"file":"CommandResponse.d.ts","sourceRoot":"","sources":["../../../../src/model/CommandResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAU,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,oBAAoB;;EAE/B,CAAC"}