@ledgerhq/device-transport-kit-web-hid 1.2.3 → 1.2.4

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.
@@ -1,2 +1,2 @@
1
- import{formatApduReceivedLog as c,formatApduSentLog as a,FramerUtils as u,OpeningConnectionError as v,SendApduTimeoutError as m}from"@ledgerhq/device-management-kit";import*as g from"@sentry/minimal";import{Left as p,Maybe as s,Nothing as h,Right as l}from"purify-ts";import{FRAME_SIZE as A}from"../data/WebHidConfig";import{WebHidSendReportError as y}from"../model/Errors";class E{dependencies;apduSender;apduReceiver;sendApduPromiseResolver;logger;constructor({dependencies:e,apduSenderFactory:n,apduReceiverFactory:d},r){const i=s.of(u.numberToByteArray(Math.floor(Math.random()*65535),2));this.logger=r("WebHidApduSender"),this.apduSender=n({frameSize:A,channel:i,padding:!0}),this.apduReceiver=d({channel:i}),this.sendApduPromiseResolver=h,this.dependencies=e,this.logger.info("\u{1F50C} Connected to device")}async sendApdu(e,n,d){let r;const i=new Promise(t=>{this.sendApduPromiseResolver=s.of((...o)=>(r&&clearTimeout(r),t(...o)))});for(const t of this.apduSender.getFrames(e))try{await this.dependencies.device.sendReport(0,new Uint8Array(t.getRawData()))}catch(o){return this.logger.info("Error sending frame",{data:{error:o}}),Promise.resolve(p(new y(o)))}return this.logger.debug(a(e)),d&&(r=setTimeout(()=>{this.logger.debug("[sendApdu] Abort timeout",{data:{abortTimeout:d}}),this.sendApduPromiseResolver.map(t=>t(p(new m("Abort timeout"))))},d)),i}receiveHidInputReport(e){const n=new Uint8Array(e.data.buffer);this.apduReceiver.handleFrame(n).map(r=>{r.map(i=>{this.logger.debug(c(i)),this.sendApduPromiseResolver.map(t=>t(l(i)))})}).mapLeft(r=>{this.sendApduPromiseResolver.map(i=>i(p(r)))})}getDependencies(){return this.dependencies}setDependencies(e){this.dependencies=e}async setupConnection(){try{this.dependencies.device.oninputreport=e=>this.receiveHidInputReport(e),await this.dependencies.device.open()}catch(e){if(e instanceof DOMException&&e.name==="InvalidStateError")this.logger.info("Device is already opened");else{const n=new v(e);throw this.logger.error("Error while opening device",{data:{error:e}}),g.captureException(n),e}}}closeConnection(){this.logger.info("\u{1F51A} Disconnect");try{this.dependencies.device.close()}catch(e){this.logger.error("Error while closing device",{data:{device:this.dependencies.device,error:e}})}}}export{E as WebHidApduSender};
1
+ import{formatApduReceivedLog as c,formatApduSentLog as a,FramerUtils as u,OpeningConnectionError as v,SendApduTimeoutError as m}from"@ledgerhq/device-management-kit";import*as g from"@sentry/minimal";import{Left as p,Maybe as s,Nothing as h,Right as l}from"purify-ts";import{FRAME_SIZE as A}from"../data/WebHidConfig";import{WebHidSendReportError as y}from"../model/Errors";class E{dependencies;apduSender;apduReceiver;sendApduPromiseResolver;logger;constructor({dependencies:e,apduSenderFactory:n,apduReceiverFactory:d},r){const i=s.of(u.numberToByteArray(Math.floor(Math.random()*65535),2));this.logger=r("WebHidApduSender"),this.apduSender=n({frameSize:A,channel:i,padding:!0}),this.apduReceiver=d({channel:i}),this.sendApduPromiseResolver=h,this.dependencies=e,this.logger.info("\u{1F50C} Connected to device")}async sendApdu(e,n,d){let r;const i=new Promise(t=>{this.sendApduPromiseResolver=s.of((...o)=>(r&&clearTimeout(r),t(...o)))});for(const t of this.apduSender.getFrames(e))try{await this.dependencies.device.sendReport(0,new Uint8Array(t.getRawData()))}catch(o){return this.logger.info("Error sending frame",{data:{error:o}}),Promise.resolve(p(new y(o)))}return this.logger.debug(a(e)),d&&(r=setTimeout(()=>{this.logger.debug("[sendApdu] Abort timeout",{data:{abortTimeout:d}}),this.sendApduPromiseResolver.map(t=>t(p(new m("Abort timeout"))))},d)),i}receiveHidInputReport(e){const n=new Uint8Array(e.data.buffer);this.apduReceiver.handleFrame(n).map(r=>{r.map(i=>{this.logger.debug(c(i)),this.sendApduPromiseResolver.map(t=>t(l(i)))})}).mapLeft(r=>{this.sendApduPromiseResolver.map(i=>i(p(r)))})}getDependencies(){return this.dependencies}setDependencies(e){this.dependencies=e}async setupConnection(){try{this.dependencies.device.oninputreport=e=>this.receiveHidInputReport(e),await this.dependencies.device.open()}catch(e){if(e instanceof DOMException&&e.name==="InvalidStateError")this.logger.info("Device is already opened");else{const n=new v(e);throw this.logger.error("Error while opening device",{data:{error:e}}),g.captureException(n),e}}}closeConnection(){this.logger.info("\u{1F51A} Disconnect"),this.dependencies.device.close().catch(e=>{this.logger.error("Error while closing device",{data:{device:this.dependencies.device,error:e}})})}}export{E as WebHidApduSender};
2
2
  //# sourceMappingURL=WebHidApduSender.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/api/transport/WebHidApduSender.ts"],
4
- "sourcesContent": ["import {\n type ApduReceiverService,\n type ApduReceiverServiceFactory,\n type ApduResponse,\n type ApduSenderService,\n type ApduSenderServiceFactory,\n type DeviceApduSender,\n type DmkError,\n formatApduReceivedLog,\n formatApduSentLog,\n FramerUtils,\n type LoggerPublisherService,\n OpeningConnectionError,\n SendApduTimeoutError,\n} from \"@ledgerhq/device-management-kit\";\nimport * as Sentry from \"@sentry/minimal\";\nimport { type Either, Left, Maybe, Nothing, Right } from \"purify-ts\";\n\nimport { FRAME_SIZE } from \"@api/data/WebHidConfig\";\nimport { WebHidSendReportError } from \"@api/model/Errors\";\n\nexport type WebHidApduSenderConstructorArgs = {\n dependencies: WebHidApduSenderDependencies;\n apduSenderFactory: ApduSenderServiceFactory;\n apduReceiverFactory: ApduReceiverServiceFactory;\n};\n\nexport type WebHidApduSenderDependencies = {\n device: HIDDevice;\n};\n\nexport class WebHidApduSender\n implements DeviceApduSender<WebHidApduSenderDependencies>\n{\n private dependencies: WebHidApduSenderDependencies;\n private readonly apduSender: ApduSenderService;\n private readonly apduReceiver: ApduReceiverService;\n private sendApduPromiseResolver: Maybe<\n (value: Either<DmkError, ApduResponse>) => void\n >;\n private readonly logger: LoggerPublisherService;\n\n constructor(\n {\n dependencies,\n apduSenderFactory,\n apduReceiverFactory,\n }: WebHidApduSenderConstructorArgs,\n loggerServiceFactory: (tag: string) => LoggerPublisherService,\n ) {\n const channel = Maybe.of(\n FramerUtils.numberToByteArray(Math.floor(Math.random() * 0xffff), 2),\n );\n this.logger = loggerServiceFactory(\"WebHidApduSender\");\n this.apduSender = apduSenderFactory({\n frameSize: FRAME_SIZE,\n channel,\n padding: true,\n });\n this.apduReceiver = apduReceiverFactory({ channel });\n this.sendApduPromiseResolver = Nothing;\n this.dependencies = dependencies;\n this.logger.info(\"\uD83D\uDD0C Connected to device\");\n }\n\n async sendApdu(\n apdu: Uint8Array,\n _triggersDisconnection?: boolean,\n abortTimeout?: number,\n ): Promise<Either<DmkError, ApduResponse>> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n\n const resultPromise = new Promise<Either<DmkError, ApduResponse>>(\n (resolve) => {\n this.sendApduPromiseResolver = Maybe.of((...args) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n return resolve(...args);\n });\n },\n );\n\n for (const frame of this.apduSender.getFrames(apdu)) {\n try {\n await this.dependencies.device.sendReport(\n 0,\n new Uint8Array(frame.getRawData()),\n );\n } catch (error) {\n this.logger.info(\"Error sending frame\", { data: { error } });\n return Promise.resolve(Left(new WebHidSendReportError(error)));\n }\n }\n this.logger.debug(formatApduSentLog(apdu));\n\n if (abortTimeout) {\n timeout = setTimeout(() => {\n this.logger.debug(\"[sendApdu] Abort timeout\", {\n data: { abortTimeout },\n });\n this.sendApduPromiseResolver.map((resolve) =>\n resolve(Left(new SendApduTimeoutError(\"Abort timeout\"))),\n );\n }, abortTimeout);\n }\n\n return resultPromise;\n }\n\n private receiveHidInputReport(event: HIDInputReportEvent) {\n const data = new Uint8Array(event.data.buffer);\n const maybeApduResponse = this.apduReceiver.handleFrame(data);\n\n maybeApduResponse\n .map((response) => {\n response.map((apduResponse) => {\n this.logger.debug(formatApduReceivedLog(apduResponse));\n this.sendApduPromiseResolver.map((resolve) =>\n resolve(Right(apduResponse)),\n );\n });\n })\n .mapLeft((error) => {\n this.sendApduPromiseResolver.map((resolve) => resolve(Left(error)));\n });\n }\n\n public getDependencies() {\n return this.dependencies;\n }\n\n public setDependencies(dependencies: WebHidApduSenderDependencies) {\n this.dependencies = dependencies;\n }\n\n public async setupConnection() {\n try {\n this.dependencies.device.oninputreport = (event) =>\n this.receiveHidInputReport(event);\n await this.dependencies.device.open();\n } catch (error) {\n if (error instanceof DOMException && error.name === \"InvalidStateError\") {\n this.logger.info(`Device is already opened`);\n } else {\n const connectionError = new OpeningConnectionError(error);\n this.logger.error(`Error while opening device`, {\n data: { error },\n });\n Sentry.captureException(connectionError);\n throw error;\n }\n }\n }\n\n public closeConnection() {\n this.logger.info(\"\uD83D\uDD1A Disconnect\");\n try {\n this.dependencies.device.close();\n } catch (error) {\n this.logger.error(\"Error while closing device\", {\n data: { device: this.dependencies.device, error },\n });\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type ApduReceiverService,\n type ApduReceiverServiceFactory,\n type ApduResponse,\n type ApduSenderService,\n type ApduSenderServiceFactory,\n type DeviceApduSender,\n type DmkError,\n formatApduReceivedLog,\n formatApduSentLog,\n FramerUtils,\n type LoggerPublisherService,\n OpeningConnectionError,\n SendApduTimeoutError,\n} from \"@ledgerhq/device-management-kit\";\nimport * as Sentry from \"@sentry/minimal\";\nimport { type Either, Left, Maybe, Nothing, Right } from \"purify-ts\";\n\nimport { FRAME_SIZE } from \"@api/data/WebHidConfig\";\nimport { WebHidSendReportError } from \"@api/model/Errors\";\n\nexport type WebHidApduSenderConstructorArgs = {\n dependencies: WebHidApduSenderDependencies;\n apduSenderFactory: ApduSenderServiceFactory;\n apduReceiverFactory: ApduReceiverServiceFactory;\n};\n\nexport type WebHidApduSenderDependencies = {\n device: HIDDevice;\n};\n\nexport class WebHidApduSender\n implements DeviceApduSender<WebHidApduSenderDependencies>\n{\n private dependencies: WebHidApduSenderDependencies;\n private readonly apduSender: ApduSenderService;\n private readonly apduReceiver: ApduReceiverService;\n private sendApduPromiseResolver: Maybe<\n (value: Either<DmkError, ApduResponse>) => void\n >;\n private readonly logger: LoggerPublisherService;\n\n constructor(\n {\n dependencies,\n apduSenderFactory,\n apduReceiverFactory,\n }: WebHidApduSenderConstructorArgs,\n loggerServiceFactory: (tag: string) => LoggerPublisherService,\n ) {\n const channel = Maybe.of(\n FramerUtils.numberToByteArray(Math.floor(Math.random() * 0xffff), 2),\n );\n this.logger = loggerServiceFactory(\"WebHidApduSender\");\n this.apduSender = apduSenderFactory({\n frameSize: FRAME_SIZE,\n channel,\n padding: true,\n });\n this.apduReceiver = apduReceiverFactory({ channel });\n this.sendApduPromiseResolver = Nothing;\n this.dependencies = dependencies;\n this.logger.info(\"\uD83D\uDD0C Connected to device\");\n }\n\n async sendApdu(\n apdu: Uint8Array,\n _triggersDisconnection?: boolean,\n abortTimeout?: number,\n ): Promise<Either<DmkError, ApduResponse>> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n\n const resultPromise = new Promise<Either<DmkError, ApduResponse>>(\n (resolve) => {\n this.sendApduPromiseResolver = Maybe.of((...args) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n return resolve(...args);\n });\n },\n );\n\n for (const frame of this.apduSender.getFrames(apdu)) {\n try {\n await this.dependencies.device.sendReport(\n 0,\n new Uint8Array(frame.getRawData()),\n );\n } catch (error) {\n this.logger.info(\"Error sending frame\", { data: { error } });\n return Promise.resolve(Left(new WebHidSendReportError(error)));\n }\n }\n this.logger.debug(formatApduSentLog(apdu));\n\n if (abortTimeout) {\n timeout = setTimeout(() => {\n this.logger.debug(\"[sendApdu] Abort timeout\", {\n data: { abortTimeout },\n });\n this.sendApduPromiseResolver.map((resolve) =>\n resolve(Left(new SendApduTimeoutError(\"Abort timeout\"))),\n );\n }, abortTimeout);\n }\n\n return resultPromise;\n }\n\n private receiveHidInputReport(event: HIDInputReportEvent) {\n const data = new Uint8Array(event.data.buffer);\n const maybeApduResponse = this.apduReceiver.handleFrame(data);\n\n maybeApduResponse\n .map((response) => {\n response.map((apduResponse) => {\n this.logger.debug(formatApduReceivedLog(apduResponse));\n this.sendApduPromiseResolver.map((resolve) =>\n resolve(Right(apduResponse)),\n );\n });\n })\n .mapLeft((error) => {\n this.sendApduPromiseResolver.map((resolve) => resolve(Left(error)));\n });\n }\n\n public getDependencies() {\n return this.dependencies;\n }\n\n public setDependencies(dependencies: WebHidApduSenderDependencies) {\n this.dependencies = dependencies;\n }\n\n public async setupConnection() {\n try {\n this.dependencies.device.oninputreport = (event) =>\n this.receiveHidInputReport(event);\n await this.dependencies.device.open();\n } catch (error) {\n if (error instanceof DOMException && error.name === \"InvalidStateError\") {\n this.logger.info(`Device is already opened`);\n } else {\n const connectionError = new OpeningConnectionError(error);\n this.logger.error(`Error while opening device`, {\n data: { error },\n });\n Sentry.captureException(connectionError);\n throw error;\n }\n }\n }\n\n public closeConnection() {\n this.logger.info(\"\uD83D\uDD1A Disconnect\");\n this.dependencies.device.close().catch((error) => {\n this.logger.error(\"Error while closing device\", {\n data: { device: this.dependencies.device, error },\n });\n });\n }\n}\n"],
5
+ "mappings": "AAAA,OAQE,yBAAAA,EACA,qBAAAC,EACA,eAAAC,EAEA,0BAAAC,EACA,wBAAAC,MACK,kCACP,UAAYC,MAAY,kBACxB,OAAsB,QAAAC,EAAM,SAAAC,EAAO,WAAAC,EAAS,SAAAC,MAAa,YAEzD,OAAS,cAAAC,MAAkB,yBAC3B,OAAS,yBAAAC,MAA6B,oBAY/B,MAAMC,CAEb,CACU,aACS,WACA,aACT,wBAGS,OAEjB,YACE,CACE,aAAAC,EACA,kBAAAC,EACA,oBAAAC,CACF,EACAC,EACA,CACA,MAAMC,EAAUV,EAAM,GACpBL,EAAY,kBAAkB,KAAK,MAAM,KAAK,OAAO,EAAI,KAAM,EAAG,CAAC,CACrE,EACA,KAAK,OAASc,EAAqB,kBAAkB,EACrD,KAAK,WAAaF,EAAkB,CAClC,UAAWJ,EACX,QAAAO,EACA,QAAS,EACX,CAAC,EACD,KAAK,aAAeF,EAAoB,CAAE,QAAAE,CAAQ,CAAC,EACnD,KAAK,wBAA0BT,EAC/B,KAAK,aAAeK,EACpB,KAAK,OAAO,KAAK,+BAAwB,CAC3C,CAEA,MAAM,SACJK,EACAC,EACAC,EACyC,CACzC,IAAIC,EAEJ,MAAMC,EAAgB,IAAI,QACvBC,GAAY,CACX,KAAK,wBAA0BhB,EAAM,GAAG,IAAIiB,KACtCH,GACF,aAAaA,CAAO,EAEfE,EAAQ,GAAGC,CAAI,EACvB,CACH,CACF,EAEA,UAAWC,KAAS,KAAK,WAAW,UAAUP,CAAI,EAChD,GAAI,CACF,MAAM,KAAK,aAAa,OAAO,WAC7B,EACA,IAAI,WAAWO,EAAM,WAAW,CAAC,CACnC,CACF,OAASC,EAAO,CACd,YAAK,OAAO,KAAK,sBAAuB,CAAE,KAAM,CAAE,MAAAA,CAAM,CAAE,CAAC,EACpD,QAAQ,QAAQpB,EAAK,IAAIK,EAAsBe,CAAK,CAAC,CAAC,CAC/D,CAEF,YAAK,OAAO,MAAMzB,EAAkBiB,CAAI,CAAC,EAErCE,IACFC,EAAU,WAAW,IAAM,CACzB,KAAK,OAAO,MAAM,2BAA4B,CAC5C,KAAM,CAAE,aAAAD,CAAa,CACvB,CAAC,EACD,KAAK,wBAAwB,IAAKG,GAChCA,EAAQjB,EAAK,IAAIF,EAAqB,eAAe,CAAC,CAAC,CACzD,CACF,EAAGgB,CAAY,GAGVE,CACT,CAEQ,sBAAsBK,EAA4B,CACxD,MAAMC,EAAO,IAAI,WAAWD,EAAM,KAAK,MAAM,EACnB,KAAK,aAAa,YAAYC,CAAI,EAGzD,IAAKC,GAAa,CACjBA,EAAS,IAAKC,GAAiB,CAC7B,KAAK,OAAO,MAAM9B,EAAsB8B,CAAY,CAAC,EACrD,KAAK,wBAAwB,IAAKP,GAChCA,EAAQd,EAAMqB,CAAY,CAAC,CAC7B,CACF,CAAC,CACH,CAAC,EACA,QAASJ,GAAU,CAClB,KAAK,wBAAwB,IAAKH,GAAYA,EAAQjB,EAAKoB,CAAK,CAAC,CAAC,CACpE,CAAC,CACL,CAEO,iBAAkB,CACvB,OAAO,KAAK,YACd,CAEO,gBAAgBb,EAA4C,CACjE,KAAK,aAAeA,CACtB,CAEA,MAAa,iBAAkB,CAC7B,GAAI,CACF,KAAK,aAAa,OAAO,cAAiBc,GACxC,KAAK,sBAAsBA,CAAK,EAClC,MAAM,KAAK,aAAa,OAAO,KAAK,CACtC,OAASD,EAAO,CACd,GAAIA,aAAiB,cAAgBA,EAAM,OAAS,oBAClD,KAAK,OAAO,KAAK,0BAA0B,MACtC,CACL,MAAMK,EAAkB,IAAI5B,EAAuBuB,CAAK,EACxD,WAAK,OAAO,MAAM,6BAA8B,CAC9C,KAAM,CAAE,MAAAA,CAAM,CAChB,CAAC,EACDrB,EAAO,iBAAiB0B,CAAe,EACjCL,CACR,CACF,CACF,CAEO,iBAAkB,CACvB,KAAK,OAAO,KAAK,sBAAe,EAChC,KAAK,aAAa,OAAO,MAAM,EAAE,MAAOA,GAAU,CAChD,KAAK,OAAO,MAAM,6BAA8B,CAC9C,KAAM,CAAE,OAAQ,KAAK,aAAa,OAAQ,MAAAA,CAAM,CAClD,CAAC,CACH,CAAC,CACH,CACF",
6
6
  "names": ["formatApduReceivedLog", "formatApduSentLog", "FramerUtils", "OpeningConnectionError", "SendApduTimeoutError", "Sentry", "Left", "Maybe", "Nothing", "Right", "FRAME_SIZE", "WebHidSendReportError", "WebHidApduSender", "dependencies", "apduSenderFactory", "apduReceiverFactory", "loggerServiceFactory", "channel", "apdu", "_triggersDisconnection", "abortTimeout", "timeout", "resultPromise", "resolve", "args", "frame", "error", "event", "data", "response", "apduResponse", "connectionError"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{SendApduTimeoutError as u}from"@ledgerhq/device-management-kit";import{Left as p,Maybe as l,Right as x}from"purify-ts";import{WebHidSendReportError as m}from"../model/Errors";import{WebHidApduSender as f}from"./WebHidApduSender";describe("WebHidApduSender",()=>{const c={getFrames:vi.fn()},i={handleFrame:vi.fn()},d={info:vi.fn(),debug:vi.fn(),error:vi.fn()},t={oninputreport:vi.fn(),open:vi.fn(),close:vi.fn(),sendReport:vi.fn()};let n;beforeEach(()=>{vi.clearAllMocks();const e=vi.fn().mockReturnValue(d),r=vi.fn().mockReturnValue(c),o=vi.fn().mockReturnValue(i);n=new f({dependencies:{device:t},apduSenderFactory:r,apduReceiverFactory:o},e)}),afterEach(()=>{vi.restoreAllMocks()}),it("should get dependencies",()=>{const e=n.getDependencies();expect(e).toEqual({device:t})}),it("should set dependencies",()=>{const e={oninputreport:null,open:vi.fn(),close:vi.fn(),sendReport:vi.fn()};n.setDependencies({device:e});const r=n.getDependencies();expect(r).toEqual({device:e})}),it("should setup connection",async()=>{await n.setupConnection(),expect(t.open).toHaveBeenCalled(),expect(t.oninputreport).toBeDefined()}),it("should handle setup connection error",async()=>{const e=new Error("Failed to open device");t.open=vi.fn().mockRejectedValue(e),expect(n.setupConnection()).rejects.toThrowError()}),it("should close connection",()=>{n.closeConnection(),expect(t.close).toHaveBeenCalled()}),it("should handle close connection error",()=>{const e=new Error("Failed to close device");t.close=vi.fn().mockImplementation(()=>{throw e}),n.closeConnection(),expect(d.error).toHaveBeenCalledWith("Error while closing device",{data:{device:t,error:e}})}),it("should send APDU successfully",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o={data:new Uint8Array([1,2]),statusCode:new Uint8Array([144,0])};c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),i.handleFrame.mockReturnValue(x(l.of(o))),await n.setupConnection();const a=n.sendApdu(e);t.oninputreport({data:{buffer:Buffer.from([])}});const s=await a;expect(t.sendReport).toHaveBeenCalled(),expect(s.isRight()).toBe(!0),expect(s.extract()).toEqual(o)}),it("should handle send APDU error",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o=new Error("Failed to send report");c.getFrames.mockReturnValue(r),t.sendReport.mockRejectedValue(o),await n.setupConnection();const a=await n.sendApdu(e);expect(a.isLeft()).toBe(!0),expect(a.extract()).toBeInstanceOf(m)}),it("should handle received response error",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o=new Error("Error while receiving APDU");c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),i.handleFrame.mockReturnValue(p(o)),await n.setupConnection();const a=n.sendApdu(e);t.oninputreport({data:{buffer:Buffer.from([])}});const s=await a;expect(t.sendReport).toHaveBeenCalled(),expect(s.isLeft()).toBe(!0),expect(s.extract()).toStrictEqual(o)}),it("should handle send APDU timeout",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}];c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),await n.setupConnection();const o=await n.sendApdu(e,!1,100);expect(o.isLeft()).toBe(!0),expect(o.extract()).toBeInstanceOf(u)})});
1
+ import{SendApduTimeoutError as u}from"@ledgerhq/device-management-kit";import{Left as p,Maybe as l,Right as x}from"purify-ts";import{WebHidSendReportError as v}from"../model/Errors";import{WebHidApduSender as f}from"./WebHidApduSender";describe("WebHidApduSender",()=>{const c={getFrames:vi.fn()},i={handleFrame:vi.fn()},d={info:vi.fn(),debug:vi.fn(),error:vi.fn()},t={oninputreport:vi.fn(),open:vi.fn(),close:vi.fn(),sendReport:vi.fn()};let n;beforeEach(()=>{vi.clearAllMocks(),t.close=vi.fn().mockResolvedValue(void 0);const e=vi.fn().mockReturnValue(d),r=vi.fn().mockReturnValue(c),o=vi.fn().mockReturnValue(i);n=new f({dependencies:{device:t},apduSenderFactory:r,apduReceiverFactory:o},e)}),afterEach(()=>{vi.restoreAllMocks()}),it("should get dependencies",()=>{const e=n.getDependencies();expect(e).toEqual({device:t})}),it("should set dependencies",()=>{const e={oninputreport:null,open:vi.fn(),close:vi.fn(),sendReport:vi.fn()};n.setDependencies({device:e});const r=n.getDependencies();expect(r).toEqual({device:e})}),it("should setup connection",async()=>{await n.setupConnection(),expect(t.open).toHaveBeenCalled(),expect(t.oninputreport).toBeDefined()}),it("GIVEN WebHID rejects open WHEN setting up the connection THEN it throws",async()=>{const e=new Error("Failed to open device");t.open=vi.fn().mockRejectedValue(e),await expect(n.setupConnection()).rejects.toThrowError()}),it("WHEN closing the connection THEN it closes the WebHID device",()=>{n.closeConnection(),expect(t.close).toHaveBeenCalled()}),it("GIVEN WebHID rejects close WHEN closing the connection THEN it logs the error",async()=>{const e=new Error("Failed to close device");t.close=vi.fn().mockRejectedValue(e),n.closeConnection(),await Promise.resolve(),expect(d.error).toHaveBeenCalledWith("Error while closing device",{data:{device:t,error:e}})}),it("should send APDU successfully",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o={data:new Uint8Array([1,2]),statusCode:new Uint8Array([144,0])};c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),i.handleFrame.mockReturnValue(x(l.of(o))),await n.setupConnection();const a=n.sendApdu(e);t.oninputreport({data:{buffer:Buffer.from([])}});const s=await a;expect(t.sendReport).toHaveBeenCalled(),expect(s.isRight()).toBe(!0),expect(s.extract()).toEqual(o)}),it("should handle send APDU error",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o=new Error("Failed to send report");c.getFrames.mockReturnValue(r),t.sendReport.mockRejectedValue(o),await n.setupConnection();const a=await n.sendApdu(e);expect(a.isLeft()).toBe(!0),expect(a.extract()).toBeInstanceOf(v)}),it("should handle received response error",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}],o=new Error("Error while receiving APDU");c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),i.handleFrame.mockReturnValue(p(o)),await n.setupConnection();const a=n.sendApdu(e);t.oninputreport({data:{buffer:Buffer.from([])}});const s=await a;expect(t.sendReport).toHaveBeenCalled(),expect(s.isLeft()).toBe(!0),expect(s.extract()).toStrictEqual(o)}),it("should handle send APDU timeout",async()=>{const e=new Uint8Array([0,1,2,3]),r=[{getRawData:()=>new Uint8Array([0,1])},{getRawData:()=>new Uint8Array([2,3])}];c.getFrames.mockReturnValue(r),t.sendReport.mockResolvedValue({}),await n.setupConnection();const o=await n.sendApdu(e,!1,100);expect(o.isLeft()).toBe(!0),expect(o.extract()).toBeInstanceOf(u)})});
2
2
  //# sourceMappingURL=WebHidApduSender.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/api/transport/WebHidApduSender.test.ts"],
4
- "sourcesContent": ["import {\n type ApduResponse,\n type LoggerPublisherService,\n SendApduTimeoutError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Maybe, Right } from \"purify-ts\";\n\nimport { WebHidSendReportError } from \"@api/model/Errors\";\n\nimport { WebHidApduSender } from \"./WebHidApduSender\";\n\ndescribe(\"WebHidApduSender\", () => {\n const mockApduSender = {\n getFrames: vi.fn(),\n };\n\n const mockApduReceiver = {\n handleFrame: vi.fn(),\n };\n\n const mockLogger = {\n info: vi.fn(),\n debug: vi.fn(),\n error: vi.fn(),\n };\n\n const mockDevice = {\n oninputreport: vi.fn(),\n open: vi.fn(),\n close: vi.fn(),\n sendReport: vi.fn(),\n };\n\n let webHidApduSender: WebHidApduSender;\n\n beforeEach(() => {\n vi.clearAllMocks();\n const mockLoggerFactory = vi\n .fn()\n .mockReturnValue(mockLogger as unknown as LoggerPublisherService);\n const mockApduSenderFactory = vi.fn().mockReturnValue(mockApduSender);\n const mockApduReceiverFactory = vi.fn().mockReturnValue(mockApduReceiver);\n webHidApduSender = new WebHidApduSender(\n {\n dependencies: { device: mockDevice as unknown as HIDDevice },\n apduSenderFactory: mockApduSenderFactory,\n apduReceiverFactory: mockApduReceiverFactory,\n },\n mockLoggerFactory,\n );\n });\n\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it(\"should get dependencies\", () => {\n const dependencies = webHidApduSender.getDependencies();\n expect(dependencies).toEqual({\n device: mockDevice as unknown as HIDDevice,\n });\n });\n\n it(\"should set dependencies\", () => {\n const newDevice: HIDDevice = {\n oninputreport: null,\n open: vi.fn(),\n close: vi.fn(),\n sendReport: vi.fn(),\n } as unknown as HIDDevice;\n webHidApduSender.setDependencies({ device: newDevice });\n const dependencies = webHidApduSender.getDependencies();\n expect(dependencies).toEqual({ device: newDevice });\n });\n\n it(\"should setup connection\", async () => {\n await webHidApduSender.setupConnection();\n expect(mockDevice.open).toHaveBeenCalled();\n expect(mockDevice.oninputreport).toBeDefined();\n });\n\n it(\"should handle setup connection error\", async () => {\n const error = new Error(\"Failed to open device\");\n mockDevice.open = vi.fn().mockRejectedValue(error);\n expect(webHidApduSender.setupConnection()).rejects.toThrowError();\n });\n\n it(\"should close connection\", () => {\n webHidApduSender.closeConnection();\n expect(mockDevice.close).toHaveBeenCalled();\n });\n\n it(\"should handle close connection error\", () => {\n const error = new Error(\"Failed to close device\");\n mockDevice.close = vi.fn().mockImplementation(() => {\n throw error;\n });\n webHidApduSender.closeConnection();\n expect(mockLogger.error).toHaveBeenCalledWith(\n \"Error while closing device\",\n {\n data: { device: mockDevice, error },\n },\n );\n });\n\n it(\"should send APDU successfully\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const apduResponse = {\n data: new Uint8Array([0x01, 0x02]),\n statusCode: new Uint8Array([0x90, 0x00]),\n } as ApduResponse;\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n mockApduReceiver.handleFrame.mockReturnValue(Right(Maybe.of(apduResponse)));\n\n // Setup connection\n await webHidApduSender.setupConnection();\n\n // Send APDU\n const promise = webHidApduSender.sendApdu(apdu);\n\n // Receive response\n mockDevice.oninputreport({ data: { buffer: Buffer.from([]) } });\n\n // Await response\n const result = await promise;\n expect(mockDevice.sendReport).toHaveBeenCalled();\n expect(result.isRight()).toBe(true);\n expect(result.extract()).toEqual(apduResponse);\n });\n\n it(\"should handle send APDU error\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const error = new Error(\"Failed to send report\");\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockRejectedValue(error);\n\n await webHidApduSender.setupConnection();\n const result = await webHidApduSender.sendApdu(apdu);\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toBeInstanceOf(WebHidSendReportError);\n });\n\n it(\"should handle received response error\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const apduError = new Error(\"Error while receiving APDU\");\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n mockApduReceiver.handleFrame.mockReturnValue(Left(apduError));\n\n // Setup connection\n await webHidApduSender.setupConnection();\n\n // Send APDU\n const promise = webHidApduSender.sendApdu(apdu);\n\n // Receive response\n mockDevice.oninputreport({ data: { buffer: Buffer.from([]) } });\n\n // Await response\n const result = await promise;\n expect(mockDevice.sendReport).toHaveBeenCalled();\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toStrictEqual(apduError);\n });\n\n it(\"should handle send APDU timeout\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n\n await webHidApduSender.setupConnection();\n const result = await webHidApduSender.sendApdu(apdu, false, 100);\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toBeInstanceOf(SendApduTimeoutError);\n });\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type ApduResponse,\n type LoggerPublisherService,\n SendApduTimeoutError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Maybe, Right } from \"purify-ts\";\n\nimport { WebHidSendReportError } from \"@api/model/Errors\";\n\nimport { WebHidApduSender } from \"./WebHidApduSender\";\n\ndescribe(\"WebHidApduSender\", () => {\n const mockApduSender = {\n getFrames: vi.fn(),\n };\n\n const mockApduReceiver = {\n handleFrame: vi.fn(),\n };\n\n const mockLogger = {\n info: vi.fn(),\n debug: vi.fn(),\n error: vi.fn(),\n };\n\n const mockDevice = {\n oninputreport: vi.fn(),\n open: vi.fn(),\n close: vi.fn(),\n sendReport: vi.fn(),\n };\n\n let webHidApduSender: WebHidApduSender;\n\n beforeEach(() => {\n vi.clearAllMocks();\n mockDevice.close = vi.fn().mockResolvedValue(undefined);\n const mockLoggerFactory = vi\n .fn()\n .mockReturnValue(mockLogger as unknown as LoggerPublisherService);\n const mockApduSenderFactory = vi.fn().mockReturnValue(mockApduSender);\n const mockApduReceiverFactory = vi.fn().mockReturnValue(mockApduReceiver);\n webHidApduSender = new WebHidApduSender(\n {\n dependencies: { device: mockDevice as unknown as HIDDevice },\n apduSenderFactory: mockApduSenderFactory,\n apduReceiverFactory: mockApduReceiverFactory,\n },\n mockLoggerFactory,\n );\n });\n\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it(\"should get dependencies\", () => {\n const dependencies = webHidApduSender.getDependencies();\n expect(dependencies).toEqual({\n device: mockDevice as unknown as HIDDevice,\n });\n });\n\n it(\"should set dependencies\", () => {\n const newDevice: HIDDevice = {\n oninputreport: null,\n open: vi.fn(),\n close: vi.fn(),\n sendReport: vi.fn(),\n } as unknown as HIDDevice;\n webHidApduSender.setDependencies({ device: newDevice });\n const dependencies = webHidApduSender.getDependencies();\n expect(dependencies).toEqual({ device: newDevice });\n });\n\n it(\"should setup connection\", async () => {\n await webHidApduSender.setupConnection();\n expect(mockDevice.open).toHaveBeenCalled();\n expect(mockDevice.oninputreport).toBeDefined();\n });\n\n it(\"GIVEN WebHID rejects open WHEN setting up the connection THEN it throws\", async () => {\n // GIVEN\n const error = new Error(\"Failed to open device\");\n mockDevice.open = vi.fn().mockRejectedValue(error);\n\n // WHEN / THEN\n await expect(webHidApduSender.setupConnection()).rejects.toThrowError();\n });\n\n it(\"WHEN closing the connection THEN it closes the WebHID device\", () => {\n // WHEN\n webHidApduSender.closeConnection();\n\n // THEN\n expect(mockDevice.close).toHaveBeenCalled();\n });\n\n it(\"GIVEN WebHID rejects close WHEN closing the connection THEN it logs the error\", async () => {\n // GIVEN\n const error = new Error(\"Failed to close device\");\n mockDevice.close = vi.fn().mockRejectedValue(error);\n\n // WHEN\n webHidApduSender.closeConnection();\n await Promise.resolve();\n\n // THEN\n expect(mockLogger.error).toHaveBeenCalledWith(\n \"Error while closing device\",\n {\n data: { device: mockDevice, error },\n },\n );\n });\n\n it(\"should send APDU successfully\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const apduResponse = {\n data: new Uint8Array([0x01, 0x02]),\n statusCode: new Uint8Array([0x90, 0x00]),\n } as ApduResponse;\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n mockApduReceiver.handleFrame.mockReturnValue(Right(Maybe.of(apduResponse)));\n\n // Setup connection\n await webHidApduSender.setupConnection();\n\n // Send APDU\n const promise = webHidApduSender.sendApdu(apdu);\n\n // Receive response\n mockDevice.oninputreport({ data: { buffer: Buffer.from([]) } });\n\n // Await response\n const result = await promise;\n expect(mockDevice.sendReport).toHaveBeenCalled();\n expect(result.isRight()).toBe(true);\n expect(result.extract()).toEqual(apduResponse);\n });\n\n it(\"should handle send APDU error\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const error = new Error(\"Failed to send report\");\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockRejectedValue(error);\n\n await webHidApduSender.setupConnection();\n const result = await webHidApduSender.sendApdu(apdu);\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toBeInstanceOf(WebHidSendReportError);\n });\n\n it(\"should handle received response error\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n const apduError = new Error(\"Error while receiving APDU\");\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n mockApduReceiver.handleFrame.mockReturnValue(Left(apduError));\n\n // Setup connection\n await webHidApduSender.setupConnection();\n\n // Send APDU\n const promise = webHidApduSender.sendApdu(apdu);\n\n // Receive response\n mockDevice.oninputreport({ data: { buffer: Buffer.from([]) } });\n\n // Await response\n const result = await promise;\n expect(mockDevice.sendReport).toHaveBeenCalled();\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toStrictEqual(apduError);\n });\n\n it(\"should handle send APDU timeout\", async () => {\n const apdu = new Uint8Array([0x00, 0x01, 0x02, 0x03]);\n const frames = [\n { getRawData: () => new Uint8Array([0x00, 0x01]) },\n { getRawData: () => new Uint8Array([0x02, 0x03]) },\n ];\n\n mockApduSender.getFrames.mockReturnValue(frames);\n mockDevice.sendReport.mockResolvedValue({});\n\n await webHidApduSender.setupConnection();\n const result = await webHidApduSender.sendApdu(apdu, false, 100);\n expect(result.isLeft()).toBe(true);\n expect(result.extract()).toBeInstanceOf(SendApduTimeoutError);\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["SendApduTimeoutError", "Left", "Maybe", "Right", "WebHidSendReportError", "WebHidApduSender", "mockApduSender", "mockApduReceiver", "mockLogger", "mockDevice", "webHidApduSender", "mockLoggerFactory", "mockApduSenderFactory", "mockApduReceiverFactory", "dependencies", "newDevice", "error", "apdu", "frames", "apduResponse", "promise", "result", "apduError"]
7
7
  }
@@ -53,5 +53,5 @@
53
53
  "watch:builds": "pnpm ldmk-tool watch --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json --platform web",
54
54
  "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
55
55
  },
56
- "version": "1.2.3"
56
+ "version": "1.2.4"
57
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebHidApduSender.d.ts","sourceRoot":"","sources":["../../../../src/api/transport/WebHidApduSender.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAEjB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EAIb,KAAK,sBAAsB,EAG5B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,KAAK,MAAM,EAA+B,MAAM,WAAW,CAAC;AAKrE,MAAM,MAAM,+BAA+B,GAAG;IAC5C,YAAY,EAAE,4BAA4B,CAAC;IAC3C,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,mBAAmB,EAAE,0BAA0B,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,qBAAa,gBACX,YAAW,gBAAgB,CAAC,4BAA4B,CAAC;IAEzD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,uBAAuB,CAE7B;IACF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAG9C,EACE,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,GACpB,EAAE,+BAA+B,EAClC,oBAAoB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB;IAiBzD,QAAQ,CACZ,IAAI,EAAE,UAAU,EAChB,sBAAsB,CAAC,EAAE,OAAO,EAChC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAyC1C,OAAO,CAAC,qBAAqB;IAkBtB,eAAe;IAIf,eAAe,CAAC,YAAY,EAAE,4BAA4B;IAIpD,eAAe;IAmBrB,eAAe;CAUvB"}
1
+ {"version":3,"file":"WebHidApduSender.d.ts","sourceRoot":"","sources":["../../../../src/api/transport/WebHidApduSender.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAEjB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EAIb,KAAK,sBAAsB,EAG5B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,KAAK,MAAM,EAA+B,MAAM,WAAW,CAAC;AAKrE,MAAM,MAAM,+BAA+B,GAAG;IAC5C,YAAY,EAAE,4BAA4B,CAAC;IAC3C,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,mBAAmB,EAAE,0BAA0B,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,qBAAa,gBACX,YAAW,gBAAgB,CAAC,4BAA4B,CAAC;IAEzD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,uBAAuB,CAE7B;IACF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAG9C,EACE,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,GACpB,EAAE,+BAA+B,EAClC,oBAAoB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB;IAiBzD,QAAQ,CACZ,IAAI,EAAE,UAAU,EAChB,sBAAsB,CAAC,EAAE,OAAO,EAChC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAyC1C,OAAO,CAAC,qBAAqB;IAkBtB,eAAe;IAIf,eAAe,CAAC,YAAY,EAAE,4BAA4B;IAIpD,eAAe;IAmBrB,eAAe;CAQvB"}