@ledgerhq/device-management-kit-devtools-ui 0.0.0-develop-20260630003344 → 0.0.0-develop-20260702003423
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build/src/Dashboard.d.ts.map +1 -1
- package/lib/build/src/Dashboard.js +5 -1
- package/lib/build/src/Dashboard.js.map +1 -1
- package/lib/build/src/components/DashboardNavigationBar.d.ts +1 -0
- package/lib/build/src/components/DashboardNavigationBar.d.ts.map +1 -1
- package/lib/build/src/components/DashboardNavigationBar.js +2 -1
- package/lib/build/src/components/DashboardNavigationBar.js.map +1 -1
- package/lib/build/src/hooks/connectorMessageHandlers.d.ts +2 -2
- package/lib/build/src/hooks/connectorMessageHandlers.d.ts.map +1 -1
- package/lib/build/src/hooks/connectorMessageHandlers.js +30 -2
- package/lib/build/src/hooks/connectorMessageHandlers.js.map +1 -1
- package/lib/build/src/hooks/useConnectorMessages.d.ts +15 -0
- package/lib/build/src/hooks/useConnectorMessages.d.ts.map +1 -1
- package/lib/build/src/hooks/useConnectorMessages.js +23 -5
- package/lib/build/src/hooks/useConnectorMessages.js.map +1 -1
- package/lib/build/src/screens/logger/mapConnectorMessageToLogData.d.ts +1 -4
- package/lib/build/src/screens/logger/mapConnectorMessageToLogData.d.ts.map +1 -1
- package/lib/build/src/screens/logger/mapConnectorMessageToLogData.js +2 -6
- package/lib/build/src/screens/logger/mapConnectorMessageToLogData.js.map +1 -1
- package/lib/build/src/screens/mock-capture/deviceConfigFromSession.d.ts +16 -0
- package/lib/build/src/screens/mock-capture/deviceConfigFromSession.d.ts.map +1 -0
- package/lib/build/src/screens/mock-capture/deviceConfigFromSession.js +52 -0
- package/lib/build/src/screens/mock-capture/deviceConfigFromSession.js.map +1 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.d.ts +36 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.d.ts.map +1 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.js +79 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.js.map +1 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.test.d.ts +2 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.test.d.ts.map +1 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.test.js +125 -0
- package/lib/build/src/screens/mock-capture/generateSessionExport.test.js.map +1 -0
- package/lib/build/src/screens/mock-capture/index.d.ts +23 -0
- package/lib/build/src/screens/mock-capture/index.d.ts.map +1 -0
- package/lib/build/src/screens/mock-capture/index.js +281 -0
- package/lib/build/src/screens/mock-capture/index.js.map +1 -0
- package/lib/build/tsconfig.build.tsbuildinfo +1 -1
- package/lib/cjs/package.json +2 -1
- package/lib/cjs/src/Dashboard.js +3 -3
- package/lib/cjs/src/Dashboard.js.map +3 -3
- package/lib/cjs/src/components/DashboardNavigationBar.js +8 -8
- package/lib/cjs/src/components/DashboardNavigationBar.js.map +2 -2
- package/lib/cjs/src/hooks/connectorMessageHandlers.js +1 -1
- package/lib/cjs/src/hooks/connectorMessageHandlers.js.map +3 -3
- package/lib/cjs/src/hooks/useConnectorMessages.js +1 -1
- package/lib/cjs/src/hooks/useConnectorMessages.js.map +3 -3
- package/lib/cjs/src/screens/logger/mapConnectorMessageToLogData.js +1 -1
- package/lib/cjs/src/screens/logger/mapConnectorMessageToLogData.js.map +3 -3
- package/lib/cjs/src/screens/mock-capture/deviceConfigFromSession.js +2 -0
- package/lib/cjs/src/screens/mock-capture/deviceConfigFromSession.js.map +7 -0
- package/lib/cjs/src/screens/mock-capture/generateSessionExport.js +2 -0
- package/lib/cjs/src/screens/mock-capture/generateSessionExport.js.map +7 -0
- package/lib/cjs/src/screens/mock-capture/generateSessionExport.test.js +2 -0
- package/lib/cjs/src/screens/mock-capture/generateSessionExport.test.js.map +7 -0
- package/lib/cjs/src/screens/mock-capture/index.js +109 -0
- package/lib/cjs/src/screens/mock-capture/index.js.map +7 -0
- package/lib/esm/package.json +2 -1
- package/lib/esm/src/Dashboard.js +3 -3
- package/lib/esm/src/Dashboard.js.map +3 -3
- package/lib/esm/src/components/DashboardNavigationBar.js +8 -8
- package/lib/esm/src/components/DashboardNavigationBar.js.map +2 -2
- package/lib/esm/src/hooks/connectorMessageHandlers.js +1 -1
- package/lib/esm/src/hooks/connectorMessageHandlers.js.map +3 -3
- package/lib/esm/src/hooks/useConnectorMessages.js +1 -1
- package/lib/esm/src/hooks/useConnectorMessages.js.map +3 -3
- package/lib/esm/src/screens/logger/mapConnectorMessageToLogData.js +1 -1
- package/lib/esm/src/screens/logger/mapConnectorMessageToLogData.js.map +3 -3
- package/lib/esm/src/screens/mock-capture/deviceConfigFromSession.js +2 -0
- package/lib/esm/src/screens/mock-capture/deviceConfigFromSession.js.map +7 -0
- package/lib/esm/src/screens/mock-capture/generateSessionExport.js +2 -0
- package/lib/esm/src/screens/mock-capture/generateSessionExport.js.map +7 -0
- package/lib/esm/src/screens/mock-capture/generateSessionExport.test.js +2 -0
- package/lib/esm/src/screens/mock-capture/generateSessionExport.test.js.map +7 -0
- package/lib/esm/src/screens/mock-capture/index.js +109 -0
- package/lib/esm/src/screens/mock-capture/index.js.map +7 -0
- package/package.json +9 -8
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";var ae=Object.create;var S=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var pe=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var ue=(o,i)=>{for(var d in i)S(o,d,{get:i[d],enumerable:!0})},K=(o,i,d,b)=>{if(i&&typeof i=="object"||typeof i=="function")for(let l of de(i))!le.call(o,l)&&l!==d&&S(o,l,{get:()=>i[l],enumerable:!(b=ce(i,l))||b.enumerable});return o};var ge=(o,i,d)=>(d=o!=null?ae(pe(o)):{},K(i||!o||!o.__esModule?S(d,"default",{value:o,enumerable:!0}):d,o)),fe=o=>K(S({},"__esModule",{value:!0}),o);var Se={};ue(Se,{MockCapture:()=>we});module.exports=fe(Se);var n=require("react"),Q=require("@ledgerhq/device-mockserver-client"),a=ge(require("styled-components")),W=require("../../shared/NotConnectedMessage"),O=require("./deviceConfigFromSession"),Y=require("./generateSessionExport"),e=require("react/jsx-runtime");const me="http://127.0.0.1:8080",he=`import { DevToolsLogger } from "@ledgerhq/device-management-kit-devtools-core";
|
|
2
|
+
|
|
3
|
+
const dmk = new DeviceManagementKitBuilder()
|
|
4
|
+
.addLogger(new DevToolsLogger(connector))
|
|
5
|
+
.build();`,xe=a.default.div`
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: 16px;
|
|
9
|
+
padding: 16px 24px;
|
|
10
|
+
overflow: auto;
|
|
11
|
+
height: 100%;
|
|
12
|
+
`,P=a.default.div`
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
gap: 8px;
|
|
16
|
+
padding: 12px;
|
|
17
|
+
border: 1px solid #e0e0e0;
|
|
18
|
+
border-radius: 6px;
|
|
19
|
+
background: #fff;
|
|
20
|
+
`,L=a.default.div`
|
|
21
|
+
font-size: 13px;
|
|
22
|
+
font-weight: 600;
|
|
23
|
+
color: #333;
|
|
24
|
+
`,C=a.default.div`
|
|
25
|
+
display: flex;
|
|
26
|
+
gap: 8px;
|
|
27
|
+
align-items: center;
|
|
28
|
+
flex-wrap: wrap;
|
|
29
|
+
`,j=a.default.label`
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: 4px;
|
|
33
|
+
font-size: 12px;
|
|
34
|
+
color: #666;
|
|
35
|
+
flex: 1;
|
|
36
|
+
min-width: 140px;
|
|
37
|
+
`,H=a.default.input`
|
|
38
|
+
padding: 6px 8px;
|
|
39
|
+
border: 1px solid #ddd;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
font-size: 12px;
|
|
42
|
+
|
|
43
|
+
&:focus {
|
|
44
|
+
outline: none;
|
|
45
|
+
border-color: #2196f3;
|
|
46
|
+
}
|
|
47
|
+
`,v=a.default.button`
|
|
48
|
+
padding: 6px 12px;
|
|
49
|
+
border: none;
|
|
50
|
+
border-radius: 4px;
|
|
51
|
+
color: white;
|
|
52
|
+
font-size: 12px;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
transition: all 0.15s ease;
|
|
55
|
+
background: ${({$variant:o})=>o==="danger"?"#e53935":o==="neutral"?"#757575":"#2196f3"};
|
|
56
|
+
|
|
57
|
+
&:hover:not(:disabled) {
|
|
58
|
+
opacity: 0.9;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&:disabled {
|
|
62
|
+
opacity: 0.5;
|
|
63
|
+
cursor: not-allowed;
|
|
64
|
+
}
|
|
65
|
+
`,q=a.default.span`
|
|
66
|
+
display: inline-block;
|
|
67
|
+
width: 10px;
|
|
68
|
+
height: 10px;
|
|
69
|
+
border-radius: 50%;
|
|
70
|
+
margin-right: 6px;
|
|
71
|
+
background: ${({$active:o})=>o?"#fff":"#bbb"};
|
|
72
|
+
`,ve=a.default.span`
|
|
73
|
+
font-size: 12px;
|
|
74
|
+
color: #555;
|
|
75
|
+
`,be=a.default.textarea`
|
|
76
|
+
margin: 0;
|
|
77
|
+
padding: 12px;
|
|
78
|
+
background: #1e1e1e;
|
|
79
|
+
color: #d4d4d4;
|
|
80
|
+
border: none;
|
|
81
|
+
border-radius: 4px;
|
|
82
|
+
font-size: 12px;
|
|
83
|
+
font-family: monospace;
|
|
84
|
+
min-height: 240px;
|
|
85
|
+
max-height: 480px;
|
|
86
|
+
overflow: auto;
|
|
87
|
+
white-space: pre;
|
|
88
|
+
resize: vertical;
|
|
89
|
+
|
|
90
|
+
&:focus {
|
|
91
|
+
outline: none;
|
|
92
|
+
box-shadow: 0 0 0 1px #2196f3;
|
|
93
|
+
}
|
|
94
|
+
`,X=a.default.div`
|
|
95
|
+
font-size: 12px;
|
|
96
|
+
padding: 8px;
|
|
97
|
+
border-radius: 4px;
|
|
98
|
+
background: ${({$error:o})=>o?"#ffebee":"#e8f5e9"};
|
|
99
|
+
border: 1px solid ${({$error:o})=>o?"#ffcdd2":"#c8e6c9"};
|
|
100
|
+
color: ${({$error:o})=>o?"#c62828":"#2e7d32"};
|
|
101
|
+
`,ke=a.default.label`
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 6px;
|
|
105
|
+
font-size: 12px;
|
|
106
|
+
color: #666;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
`,we=({apduExchanges:o,isRecording:i,isConnected:d,startRecording:b,stopRecording:l,clearRecorded:T,sessionStates:k,connectedDevices:U})=>{const[y,Z]=(0,n.useState)(!1),[M,ee]=(0,n.useState)(me),[x,oe]=(0,n.useState)(""),[J,z]=(0,n.useState)(!1),[D,R]=(0,n.useState)(null),[B,F]=(0,n.useState)(new Map),[_,G]=(0,n.useState)(new Map);(0,n.useEffect)(()=>{for(const[t,r]of k.entries()){const s=(0,O.deviceConfigFromSession)(r);if(s.apps&&s.apps.length>0){const p=s.apps;F(c=>{const g=c.get(t)??[],f=[...g];for(const m of p)f.some(A=>A.name===m.name&&A.version===m.version)||f.push(m);return f.length===g.length?c:new Map(c).set(t,f)})}if(s.firmware_version){const p=s.firmware_version;G(c=>c.get(t)?c:new Map(c).set(t,p))}}},[k]);const te=(0,n.useCallback)(()=>{T(),F(new Map),G(new Map)},[T]),I=(0,n.useMemo)(()=>{const t=new Map;for(const r of o){const s=r.sessionId??"",p=t.get(s)??[];p.push(r),t.set(s,p)}return[...t.entries()].map(([r,s])=>{const p=r?k.get(r):void 0,c=r?U.find(ie=>ie.sessionId===r)?.type:void 0,g=(0,O.deviceConfigFromSession)(p,c),f=_.get(r),m=B.get(r);return{device:{...g,name:g.name||"Mocked device",...f?{firmware_version:f}:{},...m&&m.length>0?{apps:m}:{}},exchanges:s}})},[o,k,U,B,_]),E=(0,n.useMemo)(()=>(0,Y.generateMultiDeviceSessionExport)(I,{includeHandshake:y}),[I,y]),ne=E.devices.reduce((t,r)=>t+(r.mocks?.length??0),0),h=(0,n.useMemo)(()=>JSON.stringify(E,null,2),[E]),[u,N]=(0,n.useState)(h),V=(0,n.useRef)(h);(0,n.useEffect)(()=>{h!==V.current&&(V.current=h,N(h))},[h]);const w=(0,n.useMemo)(()=>{try{return JSON.parse(u),null}catch(t){return t instanceof Error?t.message:"Invalid JSON"}},[u]),re=(0,n.useCallback)(()=>{const t=new Blob([u],{type:"application/json"}),r=URL.createObjectURL(t),s=document.createElement("a");s.href=r,s.download=`mock-session-${new Date().toISOString()}.json`,s.click(),URL.revokeObjectURL(r)},[u]),se=(0,n.useCallback)(async()=>{z(!0),R(null);try{const t=JSON.parse(u),r=new Q.MockClient(M,x?{token:x}:{});x||await r.authenticate();const s=await r.importSession(t),p=s.devices.reduce((c,g)=>c+(g.mocks?.length??0),0);R({error:!1,message:`Imported ${s.devices.length} device(s) with ${p} mock(s) to the mock server.`})}catch(t){R({error:!0,message:t instanceof Error?t.message:"Failed to push session"})}finally{z(!1)}},[M,x,u]);if(!d)return(0,e.jsx)(W.NotConnectedMessage,{title:"Logger not connected",description:(0,e.jsxs)(e.Fragment,{children:["Mock capture reads APDU exchanges from the DMK logs. Add"," ",(0,e.jsx)("code",{children:"DevToolsLogger"})," to your DMK builder to start capturing:"]}),codeExample:he});const $=o.length>0;return(0,e.jsxs)(xe,{children:[(0,e.jsxs)(P,{children:[(0,e.jsx)(L,{children:"Recording"}),(0,e.jsxs)(C,{children:[i?(0,e.jsxs)(v,{$variant:"danger",onClick:l,children:[(0,e.jsx)(q,{$active:!0}),"Stop"]}):(0,e.jsxs)(v,{$variant:"primary",onClick:b,children:[(0,e.jsx)(q,{$active:!1}),"Record"]}),(0,e.jsx)(v,{$variant:"neutral",onClick:te,disabled:!$,children:"Clear"}),(0,e.jsxs)(ve,{children:[o.length," exchange(s) captured, ",ne," mock(s) derived"]})]}),(0,e.jsxs)(ke,{children:[(0,e.jsx)("input",{type:"checkbox",checked:y,onChange:t=>Z(t.target.checked)}),"Include handshake APDUs (GetOsVersion / GetAppAndVersion)"]})]}),(0,e.jsxs)(P,{children:[(0,e.jsx)(L,{children:"Generated session export"}),(0,e.jsx)(C,{children:(0,e.jsx)(v,{onClick:re,disabled:!$||!!w,children:"Download JSON"})}),(0,e.jsx)(be,{value:u,spellCheck:!1,onChange:t=>N(t.target.value)}),w&&(0,e.jsxs)(X,{$error:!0,children:["Invalid JSON: ",w]})]}),(0,e.jsxs)(P,{children:[(0,e.jsx)(L,{children:"Push to mock server"}),(0,e.jsxs)(C,{children:[(0,e.jsxs)(j,{children:["Server URL",(0,e.jsx)(H,{value:M,onChange:t=>ee(t.target.value)})]}),(0,e.jsxs)(j,{children:["Session token",(0,e.jsx)(H,{value:x,placeholder:"auto-provisioned if empty",onChange:t=>oe(t.target.value)})]})]}),(0,e.jsx)(C,{children:(0,e.jsx)(v,{onClick:se,disabled:!$||J||!!w,children:J?"Pushing...":"Push to mock server"})}),D&&(0,e.jsx)(X,{$error:D.error,children:D.message})]})]})};0&&(module.exports={MockCapture});
|
|
109
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/screens/mock-capture/index.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * @file Mock Capture screen\n *\n * Records APDU exchanges captured passively from the host app DMK logs,\n * derives mock-server mocks from them, and lets the user download the\n * resulting session export or push it directly to a running mock server.\n */\n\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport {\n type ConnectedDevice,\n type DeviceSessionState,\n} from \"@ledgerhq/device-management-kit\";\nimport {\n type DeviceApp,\n MockClient,\n type SessionExport,\n} from \"@ledgerhq/device-mockserver-client\";\nimport styled from \"styled-components\";\n\nimport { type ApduExchange } from \"../../hooks/useConnectorMessages\";\nimport { NotConnectedMessage } from \"../../shared/NotConnectedMessage\";\nimport { deviceConfigFromSession } from \"./deviceConfigFromSession\";\nimport {\n type DeviceCaptureGroup,\n generateMultiDeviceSessionExport,\n} from \"./generateSessionExport\";\n\nconst DEFAULT_MOCK_SERVER_URL = \"http://127.0.0.1:8080\";\n\nconst MOCK_CAPTURE_CODE_EXAMPLE = `import { DevToolsLogger } from \"@ledgerhq/device-management-kit-devtools-core\";\n\nconst dmk = new DeviceManagementKitBuilder()\n .addLogger(new DevToolsLogger(connector))\n .build();`;\n\nconst Container = styled.div`\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 16px 24px;\n overflow: auto;\n height: 100%;\n`;\n\nconst Section = styled.div`\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n background: #fff;\n`;\n\nconst SectionTitle = styled.div`\n font-size: 13px;\n font-weight: 600;\n color: #333;\n`;\n\nconst Row = styled.div`\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n`;\n\nconst Field = styled.label`\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 12px;\n color: #666;\n flex: 1;\n min-width: 140px;\n`;\n\nconst Input = styled.input`\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n`;\n\nconst Button = styled.button<{ $variant?: \"primary\" | \"danger\" | \"neutral\" }>`\n padding: 6px 12px;\n border: none;\n border-radius: 4px;\n color: white;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s ease;\n background: ${({ $variant }) =>\n $variant === \"danger\"\n ? \"#e53935\"\n : $variant === \"neutral\"\n ? \"#757575\"\n : \"#2196f3\"};\n\n &:hover:not(:disabled) {\n opacity: 0.9;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n`;\n\nconst RecordingDot = styled.span<{ $active: boolean }>`\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n margin-right: 6px;\n background: ${({ $active }) => ($active ? \"#fff\" : \"#bbb\")};\n`;\n\nconst Stat = styled.span`\n font-size: 12px;\n color: #555;\n`;\n\nconst JsonEditor = styled.textarea`\n margin: 0;\n padding: 12px;\n background: #1e1e1e;\n color: #d4d4d4;\n border: none;\n border-radius: 4px;\n font-size: 12px;\n font-family: monospace;\n min-height: 240px;\n max-height: 480px;\n overflow: auto;\n white-space: pre;\n resize: vertical;\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 1px #2196f3;\n }\n`;\n\nconst StatusMessage = styled.div<{ $error: boolean }>`\n font-size: 12px;\n padding: 8px;\n border-radius: 4px;\n background: ${({ $error }) => ($error ? \"#ffebee\" : \"#e8f5e9\")};\n border: 1px solid ${({ $error }) => ($error ? \"#ffcdd2\" : \"#c8e6c9\")};\n color: ${({ $error }) => ($error ? \"#c62828\" : \"#2e7d32\")};\n`;\n\nconst Checkbox = styled.label`\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: #666;\n cursor: pointer;\n`;\n\ntype MockCaptureProps = {\n apduExchanges: ApduExchange[];\n isRecording: boolean;\n isConnected: boolean;\n startRecording: () => void;\n stopRecording: () => void;\n clearRecorded: () => void;\n sessionStates: Map<string, DeviceSessionState>;\n connectedDevices: ConnectedDevice[];\n};\n\ntype PushStatus = { error: boolean; message: string } | null;\n\nexport const MockCapture: React.FC<MockCaptureProps> = ({\n apduExchanges,\n isRecording,\n isConnected,\n startRecording,\n stopRecording,\n clearRecorded,\n sessionStates,\n connectedDevices,\n}) => {\n const [includeHandshake, setIncludeHandshake] = useState(false);\n const [serverUrl, setServerUrl] = useState(DEFAULT_MOCK_SERVER_URL);\n const [sessionToken, setSessionToken] = useState(\"\");\n const [isPushing, setIsPushing] = useState(false);\n const [pushStatus, setPushStatus] = useState<PushStatus>(null);\n const [detectedApps, setDetectedApps] = useState<Map<string, DeviceApp[]>>(\n new Map(),\n );\n const [detectedFirmwareVersions, setDetectedFirmwareVersions] = useState<\n Map<string, string>\n >(new Map());\n\n useEffect(() => {\n for (const [sessionId, state] of sessionStates.entries()) {\n const config = deviceConfigFromSession(state);\n if (config.apps && config.apps.length > 0) {\n const seenApps = config.apps;\n setDetectedApps((prev) => {\n const current = prev.get(sessionId) ?? [];\n const merged = [...current];\n for (const app of seenApps) {\n if (\n !merged.some(\n (a) => a.name === app.name && a.version === app.version,\n )\n ) {\n merged.push(app);\n }\n }\n if (merged.length === current.length) return prev;\n return new Map(prev).set(sessionId, merged);\n });\n }\n if (config.firmware_version) {\n const firmwareVersion = config.firmware_version;\n setDetectedFirmwareVersions((prev) => {\n if (prev.get(sessionId)) return prev;\n return new Map(prev).set(sessionId, firmwareVersion);\n });\n }\n }\n }, [sessionStates]);\n\n const handleClear = useCallback(() => {\n clearRecorded();\n setDetectedApps(new Map());\n setDetectedFirmwareVersions(new Map());\n }, [clearRecorded]);\n\n // Group exchanges by the session (device) that performed them, preserving\n // first-seen order, so each connected device gets its own export entry.\n const captureGroups = useMemo<DeviceCaptureGroup[]>(() => {\n const exchangesBySession = new Map<string, ApduExchange[]>();\n for (const exchange of apduExchanges) {\n const sessionId = exchange.sessionId ?? \"\";\n const list = exchangesBySession.get(sessionId) ?? [];\n list.push(exchange);\n exchangesBySession.set(sessionId, list);\n }\n\n return [...exchangesBySession.entries()].map(([sessionId, exchanges]) => {\n const state = sessionId ? sessionStates.get(sessionId) : undefined;\n const connectivityType = sessionId\n ? connectedDevices.find((device) => device.sessionId === sessionId)\n ?.type\n : undefined;\n const base = deviceConfigFromSession(state, connectivityType);\n const firmwareVersion = detectedFirmwareVersions.get(sessionId);\n const apps = detectedApps.get(sessionId);\n const device = {\n ...base,\n name: base.name || \"Mocked device\",\n ...(firmwareVersion ? { firmware_version: firmwareVersion } : {}),\n ...(apps && apps.length > 0 ? { apps } : {}),\n };\n return { device, exchanges };\n });\n }, [\n apduExchanges,\n sessionStates,\n connectedDevices,\n detectedApps,\n detectedFirmwareVersions,\n ]);\n\n const sessionExport = useMemo(\n () => generateMultiDeviceSessionExport(captureGroups, { includeHandshake }),\n [captureGroups, includeHandshake],\n );\n\n const mockCount = sessionExport.devices.reduce(\n (total, device) => total + (device.mocks?.length ?? 0),\n 0,\n );\n\n const generatedJson = useMemo(\n () => JSON.stringify(sessionExport, null, 2),\n [sessionExport],\n );\n\n // Editable JSON, kept in sync with the generated export until it changes\n // (e.g. new exchanges captured or the handshake toggle flipped), at which\n // point the editor is refreshed with the regenerated export.\n const [editedJson, setEditedJson] = useState(generatedJson);\n const lastGeneratedRef = useRef(generatedJson);\n useEffect(() => {\n if (generatedJson !== lastGeneratedRef.current) {\n lastGeneratedRef.current = generatedJson;\n setEditedJson(generatedJson);\n }\n }, [generatedJson]);\n\n const jsonError = useMemo(() => {\n try {\n JSON.parse(editedJson);\n return null;\n } catch (error) {\n return error instanceof Error ? error.message : \"Invalid JSON\";\n }\n }, [editedJson]);\n\n const downloadJson = useCallback(() => {\n const blob = new Blob([editedJson], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `mock-session-${new Date().toISOString()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }, [editedJson]);\n\n const pushToServer = useCallback(async () => {\n setIsPushing(true);\n setPushStatus(null);\n try {\n const parsedExport = JSON.parse(editedJson) as SessionExport;\n const client = new MockClient(\n serverUrl,\n sessionToken ? { token: sessionToken } : {},\n );\n if (!sessionToken) {\n await client.authenticate();\n }\n const result = await client.importSession(parsedExport);\n const importedMocks = result.devices.reduce(\n (total, device) => total + (device.mocks?.length ?? 0),\n 0,\n );\n setPushStatus({\n error: false,\n message: `Imported ${result.devices.length} device(s) with ${importedMocks} mock(s) to the mock server.`,\n });\n } catch (error) {\n setPushStatus({\n error: true,\n message:\n error instanceof Error ? error.message : \"Failed to push session\",\n });\n } finally {\n setIsPushing(false);\n }\n }, [serverUrl, sessionToken, editedJson]);\n\n if (!isConnected) {\n return (\n <NotConnectedMessage\n title=\"Logger not connected\"\n description={\n <>\n Mock capture reads APDU exchanges from the DMK logs. Add{\" \"}\n <code>DevToolsLogger</code> to your DMK builder to start capturing:\n </>\n }\n codeExample={MOCK_CAPTURE_CODE_EXAMPLE}\n />\n );\n }\n\n const hasExchanges = apduExchanges.length > 0;\n\n return (\n <Container>\n <Section>\n <SectionTitle>Recording</SectionTitle>\n <Row>\n {isRecording ? (\n <Button $variant=\"danger\" onClick={stopRecording}>\n <RecordingDot $active />\n Stop\n </Button>\n ) : (\n <Button $variant=\"primary\" onClick={startRecording}>\n <RecordingDot $active={false} />\n Record\n </Button>\n )}\n <Button\n $variant=\"neutral\"\n onClick={handleClear}\n disabled={!hasExchanges}\n >\n Clear\n </Button>\n <Stat>\n {apduExchanges.length} exchange(s) captured, {mockCount} mock(s)\n derived\n </Stat>\n </Row>\n <Checkbox>\n <input\n type=\"checkbox\"\n checked={includeHandshake}\n onChange={(e) => setIncludeHandshake(e.target.checked)}\n />\n Include handshake APDUs (GetOsVersion / GetAppAndVersion)\n </Checkbox>\n </Section>\n\n <Section>\n <SectionTitle>Generated session export</SectionTitle>\n <Row>\n <Button\n onClick={downloadJson}\n disabled={!hasExchanges || !!jsonError}\n >\n Download JSON\n </Button>\n </Row>\n <JsonEditor\n value={editedJson}\n spellCheck={false}\n onChange={(e) => setEditedJson(e.target.value)}\n />\n {jsonError && (\n <StatusMessage $error>Invalid JSON: {jsonError}</StatusMessage>\n )}\n </Section>\n\n <Section>\n <SectionTitle>Push to mock server</SectionTitle>\n <Row>\n <Field>\n Server URL\n <Input\n value={serverUrl}\n onChange={(e) => setServerUrl(e.target.value)}\n />\n </Field>\n <Field>\n Session token\n <Input\n value={sessionToken}\n placeholder=\"auto-provisioned if empty\"\n onChange={(e) => setSessionToken(e.target.value)}\n />\n </Field>\n </Row>\n <Row>\n <Button\n onClick={pushToServer}\n disabled={!hasExchanges || isPushing || !!jsonError}\n >\n {isPushing ? \"Pushing...\" : \"Push to mock server\"}\n </Button>\n </Row>\n {pushStatus && (\n <StatusMessage $error={pushStatus.error}>\n {pushStatus.message}\n </StatusMessage>\n )}\n </Section>\n </Container>\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["mock_capture_exports", "__export", "MockCapture", "__toCommonJS", "import_react", "import_device_mockserver_client", "import_styled_components", "import_NotConnectedMessage", "import_deviceConfigFromSession", "import_generateSessionExport", "import_jsx_runtime", "DEFAULT_MOCK_SERVER_URL", "MOCK_CAPTURE_CODE_EXAMPLE", "Container", "styled", "Section", "SectionTitle", "Row", "Field", "Input", "Button", "$variant", "RecordingDot", "$active", "Stat", "JsonEditor", "StatusMessage", "$error", "Checkbox", "apduExchanges", "isRecording", "isConnected", "startRecording", "stopRecording", "clearRecorded", "sessionStates", "connectedDevices", "includeHandshake", "setIncludeHandshake", "serverUrl", "setServerUrl", "sessionToken", "setSessionToken", "isPushing", "setIsPushing", "pushStatus", "setPushStatus", "detectedApps", "setDetectedApps", "detectedFirmwareVersions", "setDetectedFirmwareVersions", "sessionId", "state", "config", "seenApps", "prev", "current", "merged", "app", "a", "firmwareVersion", "handleClear", "captureGroups", "exchangesBySession", "exchange", "list", "exchanges", "connectivityType", "device", "base", "apps", "sessionExport", "mockCount", "total", "generatedJson", "editedJson", "setEditedJson", "lastGeneratedRef", "jsonError", "error", "downloadJson", "blob", "url", "pushToServer", "parsedExport", "client", "result", "importedMocks", "hasExchanges", "e"]
|
|
7
|
+
}
|
package/lib/esm/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
+
"@ledgerhq/device-mockserver-client": "workspace:*",
|
|
3
4
|
"@ledgerhq/react-ui": "catalog:",
|
|
4
5
|
"@tanstack/react-table": "8.20.5",
|
|
5
6
|
"@tanstack/react-virtual": "3.10.8",
|
|
@@ -69,5 +70,5 @@
|
|
|
69
70
|
"watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
|
|
70
71
|
},
|
|
71
72
|
"types": "lib/index.d.ts",
|
|
72
|
-
"version": "0.0.0-develop-
|
|
73
|
+
"version": "0.0.0-develop-20260702003423"
|
|
73
74
|
}
|
package/lib/esm/src/Dashboard.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{useState as
|
|
1
|
+
import{useState as u}from"react";import{StyleProvider as W}from"@ledgerhq/react-ui/styles/index";import m from"styled-components";import{DashboardFooter as q}from"./components/DashboardFooter";import{DashboardNavigationBar as G,DashboardScreen as o}from"./components/DashboardNavigationBar";import{DebugDrawer as J}from"./components/DebugDrawer";import{SplitView as v}from"./components/SplitView";import{useConnectorMessages as K}from"./hooks/useConnectorMessages";import{Inspector as Q}from"./screens/inspector";import{Logger as U}from"./screens/logger";import{MockCapture as X}from"./screens/mock-capture";import{ErrorBoundary as Y}from"./ErrorBoundary";import{jsx as e,jsxs as j}from"react/jsx-runtime";const Z=m.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
height: 100vh;
|
|
5
5
|
overflow: hidden;
|
|
6
|
-
`,
|
|
6
|
+
`,_=m.div`
|
|
7
7
|
display: flex;
|
|
8
8
|
flex-direction: column;
|
|
9
9
|
flex: 1;
|
|
10
10
|
overflow: hidden;
|
|
11
|
-
|
|
11
|
+
`,$=({connector:s})=>{const{receivedMessages:f,sentMessages:D,logs:h,connectedDevices:c,sessionStates:a,discoveredDevices:C,isListening:b,isActivelyDiscovering:S,isLoggerConnected:n,isInspectorConnected:d,providerValue:R,apduResponses:x,apduExchanges:y,isRecordingExchanges:L,sendMessage:g,clearLogs:E,startRecordingExchanges:M,stopRecordingExchanges:P,clearRecordedExchanges:A,startListening:w,stopListening:B,startDiscovering:I,stopDiscovering:O,connectDevice:V,getProvider:k,setProvider:z,sendApdu:F}=K(s),[p,H]=u(o.logs),[t,l]=u(!1),r=e(U,{logs:h,clearLogs:E,isConnected:n}),i=e(Q,{devices:c,sessionStates:a,discoveredDevices:C,isListening:b,isActivelyDiscovering:S,sendMessage:g,isConnected:d,startListening:w,stopListening:B,startDiscovering:I,stopDiscovering:O,connectDevice:V,providerValue:R,getProvider:k,setProvider:z,sendApdu:F,apduResponses:x}),N=e(X,{apduExchanges:y,isRecording:L,isConnected:n,startRecording:M,stopRecording:P,clearRecorded:A,sessionStates:a,connectedDevices:c}),T=(()=>{switch(p){case o.logs:return r;case o.inspector:return i;case o.mockCapture:return N;case o.splitHorizontal:return e(v,{direction:"horizontal",first:r,second:i});case o.splitVertical:return e(v,{direction:"vertical",first:r,second:i});default:return r}})();return j(Z,{children:[e(G,{currentScreen:p,onScreenChange:H,isLoggerConnected:n,isInspectorConnected:d}),e(_,{children:T}),e(q,{isDebugOpen:t,onToggleDebug:()=>l(!t)}),e(J,{isOpen:t,onClose:()=>l(!1),sentMessages:D,receivedMessages:f,sendMessage:g})]})};function ue({connector:s}){return e(Y,{children:e(W,{selectedPalette:"light",children:e($,{connector:s})})})}export{ue as DashboardWithErrorBoundary};
|
|
12
12
|
//# sourceMappingURL=Dashboard.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/Dashboard.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useState } from \"react\";\nimport { type Connector } from \"@ledgerhq/device-management-kit-devtools-core\";\nimport { StyleProvider } from \"@ledgerhq/react-ui/styles/index\";\nimport styled from \"styled-components\";\n\nimport { DashboardFooter } from \"./components/DashboardFooter\";\nimport {\n DashboardNavigationBar,\n DashboardScreen,\n} from \"./components/DashboardNavigationBar\";\nimport { DebugDrawer } from \"./components/DebugDrawer\";\nimport { SplitView } from \"./components/SplitView\";\nimport { useConnectorMessages } from \"./hooks/useConnectorMessages\";\nimport { Inspector } from \"./screens/inspector\";\nimport { Logger } from \"./screens/logger\";\nimport { ErrorBoundary } from \"./ErrorBoundary\";\n\nconst DashboardContainer = styled.div`\n display: flex;\n flex-direction: column;\n height: 100vh;\n overflow: hidden;\n`;\n\nconst ContentArea = styled.div`\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n`;\n\nconst Dashboard: React.FC<{ connector: Connector }> = ({ connector }) => {\n const {\n receivedMessages,\n sentMessages,\n logs,\n connectedDevices,\n sessionStates,\n discoveredDevices,\n isListening,\n isActivelyDiscovering,\n isLoggerConnected,\n isInspectorConnected,\n providerValue,\n apduResponses,\n sendMessage,\n clearLogs,\n startListening,\n stopListening,\n startDiscovering,\n stopDiscovering,\n connectDevice,\n getProvider,\n setProvider,\n sendApdu,\n } = useConnectorMessages(connector);\n\n const [currentScreen, setCurrentScreen] = useState<DashboardScreen>(\n DashboardScreen.logs,\n );\n const [isDebugOpen, setIsDebugOpen] = useState(false);\n\n const logger = (\n <Logger logs={logs} clearLogs={clearLogs} isConnected={isLoggerConnected} />\n );\n\n const inspector = (\n <Inspector\n devices={connectedDevices}\n sessionStates={sessionStates}\n discoveredDevices={discoveredDevices}\n isListening={isListening}\n isActivelyDiscovering={isActivelyDiscovering}\n sendMessage={sendMessage}\n isConnected={isInspectorConnected}\n startListening={startListening}\n stopListening={stopListening}\n startDiscovering={startDiscovering}\n stopDiscovering={stopDiscovering}\n connectDevice={connectDevice}\n providerValue={providerValue}\n getProvider={getProvider}\n setProvider={setProvider}\n sendApdu={sendApdu}\n apduResponses={apduResponses}\n />\n );\n\n const content = (() => {\n switch (currentScreen) {\n case DashboardScreen.logs:\n return logger;\n case DashboardScreen.inspector:\n return inspector;\n case DashboardScreen.splitHorizontal:\n return (\n <SplitView direction=\"horizontal\" first={logger} second={inspector} />\n );\n case DashboardScreen.splitVertical:\n return (\n <SplitView direction=\"vertical\" first={logger} second={inspector} />\n );\n default:\n return logger;\n }\n })();\n\n return (\n <DashboardContainer>\n <DashboardNavigationBar\n currentScreen={currentScreen}\n onScreenChange={setCurrentScreen}\n isLoggerConnected={isLoggerConnected}\n isInspectorConnected={isInspectorConnected}\n />\n <ContentArea>{content}</ContentArea>\n <DashboardFooter\n isDebugOpen={isDebugOpen}\n onToggleDebug={() => setIsDebugOpen(!isDebugOpen)}\n />\n <DebugDrawer\n isOpen={isDebugOpen}\n onClose={() => setIsDebugOpen(false)}\n sentMessages={sentMessages}\n receivedMessages={receivedMessages}\n sendMessage={sendMessage}\n />\n </DashboardContainer>\n );\n};\n\nexport function DashboardWithErrorBoundary({\n connector,\n}: {\n connector: Connector;\n}) {\n return (\n <ErrorBoundary>\n <StyleProvider selectedPalette=\"light\">\n <Dashboard connector={connector} />\n </StyleProvider>\n </ErrorBoundary>\n );\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAgB,YAAAA,MAAgB,QAEhC,OAAS,iBAAAC,MAAqB,kCAC9B,OAAOC,MAAY,oBAEnB,OAAS,mBAAAC,MAAuB,+BAChC,OACE,0BAAAC,EACA,mBAAAC,MACK,sCACP,OAAS,eAAAC,MAAmB,2BAC5B,OAAS,aAAAC,MAAiB,yBAC1B,OAAS,wBAAAC,MAA4B,+BACrC,OAAS,aAAAC,MAAiB,sBAC1B,OAAS,UAAAC,MAAc,mBACvB,OAAS,iBAAAC,MAAqB,
|
|
6
|
-
"names": ["useState", "StyleProvider", "styled", "DashboardFooter", "DashboardNavigationBar", "DashboardScreen", "DebugDrawer", "SplitView", "useConnectorMessages", "Inspector", "Logger", "ErrorBoundary", "jsx", "jsxs", "DashboardContainer", "ContentArea", "Dashboard", "connector", "receivedMessages", "sentMessages", "logs", "connectedDevices", "sessionStates", "discoveredDevices", "isListening", "isActivelyDiscovering", "isLoggerConnected", "isInspectorConnected", "providerValue", "apduResponses", "sendMessage", "clearLogs", "startListening", "stopListening", "startDiscovering", "stopDiscovering", "connectDevice", "getProvider", "setProvider", "sendApdu", "currentScreen", "setCurrentScreen", "isDebugOpen", "setIsDebugOpen", "logger", "inspector", "content", "DashboardWithErrorBoundary"]
|
|
4
|
+
"sourcesContent": ["import React, { useState } from \"react\";\nimport { type Connector } from \"@ledgerhq/device-management-kit-devtools-core\";\nimport { StyleProvider } from \"@ledgerhq/react-ui/styles/index\";\nimport styled from \"styled-components\";\n\nimport { DashboardFooter } from \"./components/DashboardFooter\";\nimport {\n DashboardNavigationBar,\n DashboardScreen,\n} from \"./components/DashboardNavigationBar\";\nimport { DebugDrawer } from \"./components/DebugDrawer\";\nimport { SplitView } from \"./components/SplitView\";\nimport { useConnectorMessages } from \"./hooks/useConnectorMessages\";\nimport { Inspector } from \"./screens/inspector\";\nimport { Logger } from \"./screens/logger\";\nimport { MockCapture } from \"./screens/mock-capture\";\nimport { ErrorBoundary } from \"./ErrorBoundary\";\n\nconst DashboardContainer = styled.div`\n display: flex;\n flex-direction: column;\n height: 100vh;\n overflow: hidden;\n`;\n\nconst ContentArea = styled.div`\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n`;\n\nconst Dashboard: React.FC<{ connector: Connector }> = ({ connector }) => {\n const {\n receivedMessages,\n sentMessages,\n logs,\n connectedDevices,\n sessionStates,\n discoveredDevices,\n isListening,\n isActivelyDiscovering,\n isLoggerConnected,\n isInspectorConnected,\n providerValue,\n apduResponses,\n apduExchanges,\n isRecordingExchanges,\n sendMessage,\n clearLogs,\n startRecordingExchanges,\n stopRecordingExchanges,\n clearRecordedExchanges,\n startListening,\n stopListening,\n startDiscovering,\n stopDiscovering,\n connectDevice,\n getProvider,\n setProvider,\n sendApdu,\n } = useConnectorMessages(connector);\n\n const [currentScreen, setCurrentScreen] = useState<DashboardScreen>(\n DashboardScreen.logs,\n );\n const [isDebugOpen, setIsDebugOpen] = useState(false);\n\n const logger = (\n <Logger logs={logs} clearLogs={clearLogs} isConnected={isLoggerConnected} />\n );\n\n const inspector = (\n <Inspector\n devices={connectedDevices}\n sessionStates={sessionStates}\n discoveredDevices={discoveredDevices}\n isListening={isListening}\n isActivelyDiscovering={isActivelyDiscovering}\n sendMessage={sendMessage}\n isConnected={isInspectorConnected}\n startListening={startListening}\n stopListening={stopListening}\n startDiscovering={startDiscovering}\n stopDiscovering={stopDiscovering}\n connectDevice={connectDevice}\n providerValue={providerValue}\n getProvider={getProvider}\n setProvider={setProvider}\n sendApdu={sendApdu}\n apduResponses={apduResponses}\n />\n );\n\n const mockCapture = (\n <MockCapture\n apduExchanges={apduExchanges}\n isRecording={isRecordingExchanges}\n isConnected={isLoggerConnected}\n startRecording={startRecordingExchanges}\n stopRecording={stopRecordingExchanges}\n clearRecorded={clearRecordedExchanges}\n sessionStates={sessionStates}\n connectedDevices={connectedDevices}\n />\n );\n\n const content = (() => {\n switch (currentScreen) {\n case DashboardScreen.logs:\n return logger;\n case DashboardScreen.inspector:\n return inspector;\n case DashboardScreen.mockCapture:\n return mockCapture;\n case DashboardScreen.splitHorizontal:\n return (\n <SplitView direction=\"horizontal\" first={logger} second={inspector} />\n );\n case DashboardScreen.splitVertical:\n return (\n <SplitView direction=\"vertical\" first={logger} second={inspector} />\n );\n default:\n return logger;\n }\n })();\n\n return (\n <DashboardContainer>\n <DashboardNavigationBar\n currentScreen={currentScreen}\n onScreenChange={setCurrentScreen}\n isLoggerConnected={isLoggerConnected}\n isInspectorConnected={isInspectorConnected}\n />\n <ContentArea>{content}</ContentArea>\n <DashboardFooter\n isDebugOpen={isDebugOpen}\n onToggleDebug={() => setIsDebugOpen(!isDebugOpen)}\n />\n <DebugDrawer\n isOpen={isDebugOpen}\n onClose={() => setIsDebugOpen(false)}\n sentMessages={sentMessages}\n receivedMessages={receivedMessages}\n sendMessage={sendMessage}\n />\n </DashboardContainer>\n );\n};\n\nexport function DashboardWithErrorBoundary({\n connector,\n}: {\n connector: Connector;\n}) {\n return (\n <ErrorBoundary>\n <StyleProvider selectedPalette=\"light\">\n <Dashboard connector={connector} />\n </StyleProvider>\n </ErrorBoundary>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["useState", "StyleProvider", "styled", "DashboardFooter", "DashboardNavigationBar", "DashboardScreen", "DebugDrawer", "SplitView", "useConnectorMessages", "Inspector", "Logger", "MockCapture", "ErrorBoundary", "jsx", "jsxs", "DashboardContainer", "ContentArea", "Dashboard", "connector", "receivedMessages", "sentMessages", "logs", "connectedDevices", "sessionStates", "discoveredDevices", "isListening", "isActivelyDiscovering", "isLoggerConnected", "isInspectorConnected", "providerValue", "apduResponses", "apduExchanges", "isRecordingExchanges", "sendMessage", "clearLogs", "startRecordingExchanges", "stopRecordingExchanges", "clearRecordedExchanges", "startListening", "stopListening", "startDiscovering", "stopDiscovering", "connectDevice", "getProvider", "setProvider", "sendApdu", "currentScreen", "setCurrentScreen", "isDebugOpen", "setIsDebugOpen", "logger", "inspector", "mockCapture", "content", "DashboardWithErrorBoundary"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"styled-components";import{jsx as t,jsxs as i}from"react/jsx-runtime";var b=(
|
|
1
|
+
import e from"styled-components";import{jsx as t,jsxs as i}from"react/jsx-runtime";var b=(a=>(a.logs="logs",a.inspector="inspector",a.mockCapture="mockCapture",a.splitHorizontal="splitHorizontal",a.splitVertical="splitVertical",a))(b||{});const h=e.div`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: row;
|
|
4
4
|
align-items: center;
|
|
@@ -7,17 +7,17 @@ import e from"styled-components";import{jsx as t,jsxs as i}from"react/jsx-runtim
|
|
|
7
7
|
background: #f8f8f8;
|
|
8
8
|
border-bottom: 1px solid #e0e0e0;
|
|
9
9
|
flex-shrink: 0;
|
|
10
|
-
`,
|
|
10
|
+
`,d=e.div`
|
|
11
11
|
display: flex;
|
|
12
12
|
flex-direction: row;
|
|
13
13
|
align-items: center;
|
|
14
14
|
gap: 4px;
|
|
15
|
-
`,
|
|
15
|
+
`,x=e.div`
|
|
16
16
|
width: 1px;
|
|
17
17
|
height: 24px;
|
|
18
18
|
background: #ddd;
|
|
19
19
|
margin: 0 8px;
|
|
20
|
-
`,
|
|
20
|
+
`,l=e.button`
|
|
21
21
|
padding: 6px 12px;
|
|
22
22
|
border: 1px solid ${({$isActive:o})=>o?"#2196F3":"#ddd"};
|
|
23
23
|
border-radius: 4px;
|
|
@@ -33,7 +33,7 @@ import e from"styled-components";import{jsx as t,jsxs as i}from"react/jsx-runtim
|
|
|
33
33
|
background: ${({$isActive:o})=>o?"#e3f2fd":"#f5f5f5"};
|
|
34
34
|
border-color: ${({$isActive:o})=>o?"#2196F3":"#bbb"};
|
|
35
35
|
}
|
|
36
|
-
`,
|
|
36
|
+
`,p=e.button`
|
|
37
37
|
padding: 6px 8px;
|
|
38
38
|
border: 1px solid ${({$isActive:o})=>o?"#2196F3":"#ddd"};
|
|
39
39
|
border-radius: 4px;
|
|
@@ -49,16 +49,16 @@ import e from"styled-components";import{jsx as t,jsxs as i}from"react/jsx-runtim
|
|
|
49
49
|
background: ${({$isActive:o})=>o?"#e3f2fd":"#f5f5f5"};
|
|
50
50
|
border-color: ${({$isActive:o})=>o?"#2196F3":"#bbb"};
|
|
51
51
|
}
|
|
52
|
-
`,
|
|
52
|
+
`,c=e.span`
|
|
53
53
|
display: inline-block;
|
|
54
54
|
width: 8px;
|
|
55
55
|
height: 8px;
|
|
56
56
|
border-radius: 50%;
|
|
57
57
|
background: ${({$connected:o})=>o?"#4CAF50":"#ff9800"};
|
|
58
58
|
margin-right: 6px;
|
|
59
|
-
`,
|
|
59
|
+
`,g=e.span`
|
|
60
60
|
font-size: 12px;
|
|
61
61
|
color: #666;
|
|
62
62
|
margin-right: 4px;
|
|
63
|
-
`,f=()=>i("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor",children:[t("rect",{x:"2",y:"2",width:"12",height:"5",rx:"1",opacity:"0.6"}),t("rect",{x:"2",y:"9",width:"12",height:"5",rx:"1"})]}),v=()=>i("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor",children:[t("rect",{x:"2",y:"2",width:"5",height:"12",rx:"1",opacity:"0.6"}),t("rect",{x:"9",y:"2",width:"5",height:"12",rx:"1"})]}),$=({currentScreen:o,onScreenChange:r,isLoggerConnected:
|
|
63
|
+
`,f=()=>i("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor",children:[t("rect",{x:"2",y:"2",width:"12",height:"5",rx:"1",opacity:"0.6"}),t("rect",{x:"2",y:"9",width:"12",height:"5",rx:"1"})]}),v=()=>i("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"currentColor",children:[t("rect",{x:"2",y:"2",width:"5",height:"12",rx:"1",opacity:"0.6"}),t("rect",{x:"9",y:"2",width:"5",height:"12",rx:"1"})]}),$=({currentScreen:o,onScreenChange:r,isLoggerConnected:n,isInspectorConnected:s})=>i(h,{children:[i(d,{children:[i(l,{$isActive:o==="logs",$isConnected:n,onClick:()=>r("logs"),children:[t(c,{$connected:n}),"Logger"]}),i(l,{$isActive:o==="inspector",$isConnected:s,onClick:()=>r("inspector"),children:[t(c,{$connected:s}),"Inspector"]}),i(l,{$isActive:o==="mockCapture",$isConnected:n,onClick:()=>r("mockCapture"),children:[t(c,{$connected:n}),"Mock Capture"]})]}),t(x,{}),i(d,{children:[t(g,{children:"Split:"}),t(p,{$isActive:o==="splitHorizontal",onClick:()=>r("splitHorizontal"),title:"Split Horizontal (top/bottom)",children:t(f,{})}),t(p,{$isActive:o==="splitVertical",onClick:()=>r("splitVertical"),title:"Split Vertical (left/right)",children:t(v,{})})]})]});export{$ as DashboardNavigationBar,b as DashboardScreen};
|
|
64
64
|
//# sourceMappingURL=DashboardNavigationBar.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/DashboardNavigationBar.tsx"],
|
|
4
|
-
"sourcesContent": ["import React from \"react\";\nimport styled from \"styled-components\";\n\nexport enum DashboardScreen {\n logs = \"logs\",\n inspector = \"inspector\",\n splitHorizontal = \"splitHorizontal\",\n splitVertical = \"splitVertical\",\n}\n\nconst NavContainer = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f8f8f8;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n`;\n\nconst NavGroup = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 4px;\n`;\n\nconst Divider = styled.div`\n width: 1px;\n height: 24px;\n background: #ddd;\n margin: 0 8px;\n`;\n\nconst NavButton = styled.button<{\n $isActive?: boolean;\n $isConnected?: boolean;\n}>`\n padding: 6px 12px;\n border: 1px solid ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#ddd\")};\n border-radius: 4px;\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"white\")};\n color: ${({ $isActive }) => ($isActive ? \"#1976d2\" : \"#333\")};\n font-weight: ${({ $isActive }) => ($isActive ? \"600\" : \"normal\")};\n font-size: 13px;\n cursor: pointer;\n opacity: ${({ $isConnected }) => ($isConnected === false ? 0.5 : 1)};\n transition: all 0.15s ease;\n\n &:hover {\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"#f5f5f5\")};\n border-color: ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#bbb\")};\n }\n`;\n\nconst SplitButton = styled.button<{ $isActive?: boolean }>`\n padding: 6px 8px;\n border: 1px solid ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#ddd\")};\n border-radius: 4px;\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"white\")};\n color: ${({ $isActive }) => ($isActive ? \"#1976d2\" : \"#666\")};\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"#f5f5f5\")};\n border-color: ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#bbb\")};\n }\n`;\n\nconst ConnectionIndicator = styled.span<{ $connected: boolean }>`\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: ${({ $connected }) => ($connected ? \"#4CAF50\" : \"#ff9800\")};\n margin-right: 6px;\n`;\n\nconst SplitLabel = styled.span`\n font-size: 12px;\n color: #666;\n margin-right: 4px;\n`;\n\n// Simple SVG icons for split buttons\nconst SplitHorizontalIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"2\" y=\"2\" width=\"12\" height=\"5\" rx=\"1\" opacity=\"0.6\" />\n <rect x=\"2\" y=\"9\" width=\"12\" height=\"5\" rx=\"1\" />\n </svg>\n);\n\nconst SplitVerticalIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"2\" y=\"2\" width=\"5\" height=\"12\" rx=\"1\" opacity=\"0.6\" />\n <rect x=\"9\" y=\"2\" width=\"5\" height=\"12\" rx=\"1\" />\n </svg>\n);\n\ntype DashboardNavigationBarProps = {\n currentScreen: DashboardScreen;\n onScreenChange: (screen: DashboardScreen) => void;\n isLoggerConnected: boolean;\n isInspectorConnected: boolean;\n};\n\nexport const DashboardNavigationBar: React.FC<DashboardNavigationBarProps> = ({\n currentScreen,\n onScreenChange,\n isLoggerConnected,\n isInspectorConnected,\n}) => {\n return (\n <NavContainer>\n {/* Main view buttons */}\n <NavGroup>\n <NavButton\n $isActive={currentScreen === DashboardScreen.logs}\n $isConnected={isLoggerConnected}\n onClick={() => onScreenChange(DashboardScreen.logs)}\n >\n <ConnectionIndicator $connected={isLoggerConnected} />\n Logger\n </NavButton>\n <NavButton\n $isActive={currentScreen === DashboardScreen.inspector}\n $isConnected={isInspectorConnected}\n onClick={() => onScreenChange(DashboardScreen.inspector)}\n >\n <ConnectionIndicator $connected={isInspectorConnected} />\n Inspector\n </NavButton>\n </NavGroup>\n\n <Divider />\n\n {/* Split view buttons */}\n <NavGroup>\n <SplitLabel>Split:</SplitLabel>\n <SplitButton\n $isActive={currentScreen === DashboardScreen.splitHorizontal}\n onClick={() => onScreenChange(DashboardScreen.splitHorizontal)}\n title=\"Split Horizontal (top/bottom)\"\n >\n <SplitHorizontalIcon />\n </SplitButton>\n <SplitButton\n $isActive={currentScreen === DashboardScreen.splitVertical}\n onClick={() => onScreenChange(DashboardScreen.splitVertical)}\n title=\"Split Vertical (left/right)\"\n >\n <SplitVerticalIcon />\n </SplitButton>\n </NavGroup>\n </NavContainer>\n );\n};\n"],
|
|
5
|
-
"mappings": "AACA,OAAOA,MAAY,
|
|
4
|
+
"sourcesContent": ["import React from \"react\";\nimport styled from \"styled-components\";\n\nexport enum DashboardScreen {\n logs = \"logs\",\n inspector = \"inspector\",\n mockCapture = \"mockCapture\",\n splitHorizontal = \"splitHorizontal\",\n splitVertical = \"splitVertical\",\n}\n\nconst NavContainer = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f8f8f8;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n`;\n\nconst NavGroup = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 4px;\n`;\n\nconst Divider = styled.div`\n width: 1px;\n height: 24px;\n background: #ddd;\n margin: 0 8px;\n`;\n\nconst NavButton = styled.button<{\n $isActive?: boolean;\n $isConnected?: boolean;\n}>`\n padding: 6px 12px;\n border: 1px solid ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#ddd\")};\n border-radius: 4px;\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"white\")};\n color: ${({ $isActive }) => ($isActive ? \"#1976d2\" : \"#333\")};\n font-weight: ${({ $isActive }) => ($isActive ? \"600\" : \"normal\")};\n font-size: 13px;\n cursor: pointer;\n opacity: ${({ $isConnected }) => ($isConnected === false ? 0.5 : 1)};\n transition: all 0.15s ease;\n\n &:hover {\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"#f5f5f5\")};\n border-color: ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#bbb\")};\n }\n`;\n\nconst SplitButton = styled.button<{ $isActive?: boolean }>`\n padding: 6px 8px;\n border: 1px solid ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#ddd\")};\n border-radius: 4px;\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"white\")};\n color: ${({ $isActive }) => ($isActive ? \"#1976d2\" : \"#666\")};\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${({ $isActive }) => ($isActive ? \"#e3f2fd\" : \"#f5f5f5\")};\n border-color: ${({ $isActive }) => ($isActive ? \"#2196F3\" : \"#bbb\")};\n }\n`;\n\nconst ConnectionIndicator = styled.span<{ $connected: boolean }>`\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: ${({ $connected }) => ($connected ? \"#4CAF50\" : \"#ff9800\")};\n margin-right: 6px;\n`;\n\nconst SplitLabel = styled.span`\n font-size: 12px;\n color: #666;\n margin-right: 4px;\n`;\n\n// Simple SVG icons for split buttons\nconst SplitHorizontalIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"2\" y=\"2\" width=\"12\" height=\"5\" rx=\"1\" opacity=\"0.6\" />\n <rect x=\"2\" y=\"9\" width=\"12\" height=\"5\" rx=\"1\" />\n </svg>\n);\n\nconst SplitVerticalIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"2\" y=\"2\" width=\"5\" height=\"12\" rx=\"1\" opacity=\"0.6\" />\n <rect x=\"9\" y=\"2\" width=\"5\" height=\"12\" rx=\"1\" />\n </svg>\n);\n\ntype DashboardNavigationBarProps = {\n currentScreen: DashboardScreen;\n onScreenChange: (screen: DashboardScreen) => void;\n isLoggerConnected: boolean;\n isInspectorConnected: boolean;\n};\n\nexport const DashboardNavigationBar: React.FC<DashboardNavigationBarProps> = ({\n currentScreen,\n onScreenChange,\n isLoggerConnected,\n isInspectorConnected,\n}) => {\n return (\n <NavContainer>\n {/* Main view buttons */}\n <NavGroup>\n <NavButton\n $isActive={currentScreen === DashboardScreen.logs}\n $isConnected={isLoggerConnected}\n onClick={() => onScreenChange(DashboardScreen.logs)}\n >\n <ConnectionIndicator $connected={isLoggerConnected} />\n Logger\n </NavButton>\n <NavButton\n $isActive={currentScreen === DashboardScreen.inspector}\n $isConnected={isInspectorConnected}\n onClick={() => onScreenChange(DashboardScreen.inspector)}\n >\n <ConnectionIndicator $connected={isInspectorConnected} />\n Inspector\n </NavButton>\n <NavButton\n $isActive={currentScreen === DashboardScreen.mockCapture}\n $isConnected={isLoggerConnected}\n onClick={() => onScreenChange(DashboardScreen.mockCapture)}\n >\n <ConnectionIndicator $connected={isLoggerConnected} />\n Mock Capture\n </NavButton>\n </NavGroup>\n\n <Divider />\n\n {/* Split view buttons */}\n <NavGroup>\n <SplitLabel>Split:</SplitLabel>\n <SplitButton\n $isActive={currentScreen === DashboardScreen.splitHorizontal}\n onClick={() => onScreenChange(DashboardScreen.splitHorizontal)}\n title=\"Split Horizontal (top/bottom)\"\n >\n <SplitHorizontalIcon />\n </SplitButton>\n <SplitButton\n $isActive={currentScreen === DashboardScreen.splitVertical}\n onClick={() => onScreenChange(DashboardScreen.splitVertical)}\n title=\"Split Vertical (left/right)\"\n >\n <SplitVerticalIcon />\n </SplitButton>\n </NavGroup>\n </NavContainer>\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["styled", "jsx", "jsxs", "DashboardScreen", "NavContainer", "NavGroup", "Divider", "NavButton", "$isActive", "$isConnected", "SplitButton", "ConnectionIndicator", "$connected", "SplitLabel", "SplitHorizontalIcon", "SplitVerticalIcon", "DashboardNavigationBar", "currentScreen", "onScreenChange", "isLoggerConnected", "isInspectorConnected"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{mapConnectorMessageToLogData as
|
|
1
|
+
import{mapConnectorMessageToLogData as i}from"../screens/logger/mapConnectorMessageToLogData";const c="apdu-exchange";function p(o){const t=o.payload;return typeof t!="object"||t===null||Array.isArray(t)||t.type!==c||typeof t.apdu!="string"||typeof t.response!="string"?null:{sessionId:typeof t.sessionId=="string"?t.sessionId:void 0,apdu:t.apdu,response:t.response,timestamp:o.timestamp}}function l(o,t){try{const{module:e}=JSON.parse(o);t(s=>new Set([...s,e]))}catch(e){console.error("Failed to parse moduleConnected payload",e)}}function u(o,t,e,s){const a=i(o);if(a!==null){if(t(n=>[...n,a]),s){const n=p(a);n!==null&&e(r=>[...r,n])}return!0}return!1}function S(o,t){try{const e=JSON.parse(o);t(e)}catch(e){console.error("Failed to parse connectedDevicesUpdate payload",e)}}function v(o,t){try{const{sessionId:e,state:s}=JSON.parse(o);t(a=>new Map(a).set(e,s))}catch(e){console.error("Failed to parse deviceSessionStateUpdate payload",e)}}function D(o,t){try{const e=JSON.parse(o);t(e)}catch(e){console.error("Failed to parse discoveredDevicesUpdate payload",e)}}function y(o,t){try{const{provider:e}=JSON.parse(o);t(e)}catch(e){console.error("Failed to parse providerValue payload",e)}}function h(o,t){try{const e=JSON.parse(o);t(s=>new Map(s).set(e.requestId,e))}catch(e){console.error("Failed to parse apduResponse payload",e)}}export{h as handleApduResponse,S as handleConnectedDevicesUpdate,v as handleDeviceSessionStateUpdate,D as handleDiscoveredDevicesUpdate,u as handleLogMessage,l as handleModuleConnected,y as handleProviderValue};
|
|
2
2
|
//# sourceMappingURL=connectorMessageHandlers.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/hooks/connectorMessageHandlers.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Dispatch, SetStateAction } from \"react\";\nimport {\n type ConnectedDevice,\n type DeviceSessionState,\n type DiscoveredDevice,\n} from \"@ledgerhq/device-management-kit\";\nimport { type DevToolsModule } from \"@ledgerhq/device-management-kit-devtools-core\";\n\nimport { mapConnectorMessageToLogData } from \"../screens/logger/mapConnectorMessageToLogData\";\nimport { type LogData } from \"../screens/logger/types\";\nimport { type ApduResponse } from \"./useConnectorMessages\";\n\n/**\n * Handle module connected handshake message.\n */\nexport function handleModuleConnected(\n payload: string,\n setConnectedModules: Dispatch<SetStateAction<Set<DevToolsModule>>>,\n): void {\n try {\n const { module } = JSON.parse(payload) as { module: DevToolsModule };\n setConnectedModules((prev) => new Set([...prev, module]));\n } catch (e) {\n console.error(\"Failed to parse moduleConnected payload\", e);\n }\n}\n\n/**\n * Handle log message. Returns true if message was a log, false otherwise.\n */\nexport function handleLogMessage(\n
|
|
5
|
-
"mappings": "AAQA,OAAS,gCAAAA,MAAoC,
|
|
6
|
-
"names": ["mapConnectorMessageToLogData", "handleModuleConnected", "payload", "setConnectedModules", "module", "prev", "handleLogMessage", "
|
|
4
|
+
"sourcesContent": ["import type { Dispatch, SetStateAction } from \"react\";\nimport {\n type ConnectedDevice,\n type DeviceSessionState,\n type DiscoveredDevice,\n} from \"@ledgerhq/device-management-kit\";\nimport { type DevToolsModule } from \"@ledgerhq/device-management-kit-devtools-core\";\n\nimport { mapConnectorMessageToLogData } from \"../screens/logger/mapConnectorMessageToLogData\";\nimport { type LogData } from \"../screens/logger/types\";\nimport { type ApduExchange, type ApduResponse } from \"./useConnectorMessages\";\n\nconst APDU_EXCHANGE_LOG = \"apdu-exchange\";\n\n/**\n * Extracts a structured APDU exchange from a log message, if the log carries\n * the `apdu-exchange` payload emitted by DMK. Returns null otherwise.\n */\nfunction tryExtractApduExchange(logData: LogData): ApduExchange | null {\n const data = logData.payload;\n if (\n typeof data !== \"object\" ||\n data === null ||\n Array.isArray(data) ||\n data[\"type\"] !== APDU_EXCHANGE_LOG ||\n typeof data[\"apdu\"] !== \"string\" ||\n typeof data[\"response\"] !== \"string\"\n ) {\n return null;\n }\n return {\n sessionId:\n typeof data[\"sessionId\"] === \"string\" ? data[\"sessionId\"] : undefined,\n apdu: data[\"apdu\"],\n response: data[\"response\"],\n timestamp: logData.timestamp,\n };\n}\n\n/**\n * Handle module connected handshake message.\n */\nexport function handleModuleConnected(\n payload: string,\n setConnectedModules: Dispatch<SetStateAction<Set<DevToolsModule>>>,\n): void {\n try {\n const { module } = JSON.parse(payload) as { module: DevToolsModule };\n setConnectedModules((prev) => new Set([...prev, module]));\n } catch (e) {\n console.error(\"Failed to parse moduleConnected payload\", e);\n }\n}\n\n/**\n * Handle log message. Returns true if message was a log, false otherwise.\n */\nexport function handleLogMessage(\n payload: string,\n setLogs: Dispatch<SetStateAction<LogData[]>>,\n setApduExchanges: Dispatch<SetStateAction<ApduExchange[]>>,\n isRecordingExchanges: boolean,\n): boolean {\n const logData = mapConnectorMessageToLogData(payload);\n if (logData !== null) {\n setLogs((prev) => [...prev, logData]);\n if (isRecordingExchanges) {\n const exchange = tryExtractApduExchange(logData);\n if (exchange !== null) {\n setApduExchanges((prev) => [...prev, exchange]);\n }\n }\n return true;\n }\n return false;\n}\n\n/**\n * Handle connected devices update message.\n */\nexport function handleConnectedDevicesUpdate(\n payload: string,\n setConnectedDevices: Dispatch<SetStateAction<ConnectedDevice[]>>,\n): void {\n try {\n const devices = JSON.parse(payload) as ConnectedDevice[];\n setConnectedDevices(devices);\n } catch (e) {\n console.error(\"Failed to parse connectedDevicesUpdate payload\", e);\n }\n}\n\n/**\n * Handle device session state update message.\n */\nexport function handleDeviceSessionStateUpdate(\n payload: string,\n setSessionStates: Dispatch<SetStateAction<Map<string, DeviceSessionState>>>,\n): void {\n try {\n const { sessionId, state } = JSON.parse(payload) as {\n sessionId: string;\n state: DeviceSessionState;\n };\n setSessionStates((prev) => new Map(prev).set(sessionId, state));\n } catch (e) {\n console.error(\"Failed to parse deviceSessionStateUpdate payload\", e);\n }\n}\n\n/**\n * Handle discovered devices update message.\n */\nexport function handleDiscoveredDevicesUpdate(\n payload: string,\n setDiscoveredDevices: Dispatch<SetStateAction<DiscoveredDevice[]>>,\n): void {\n try {\n const devices = JSON.parse(payload) as DiscoveredDevice[];\n setDiscoveredDevices(devices);\n } catch (e) {\n console.error(\"Failed to parse discoveredDevicesUpdate payload\", e);\n }\n}\n\n/**\n * Handle provider value response message.\n */\nexport function handleProviderValue(\n payload: string,\n setProviderValue: Dispatch<SetStateAction<number | null>>,\n): void {\n try {\n const { provider } = JSON.parse(payload) as { provider: number };\n setProviderValue(provider);\n } catch (e) {\n console.error(\"Failed to parse providerValue payload\", e);\n }\n}\n\n/**\n * Handle APDU response message.\n */\nexport function handleApduResponse(\n payload: string,\n setApduResponses: Dispatch<SetStateAction<Map<string, ApduResponse>>>,\n): void {\n try {\n const response = JSON.parse(payload) as ApduResponse;\n setApduResponses((prev) => new Map(prev).set(response.requestId, response));\n } catch (e) {\n console.error(\"Failed to parse apduResponse payload\", e);\n }\n}\n"],
|
|
5
|
+
"mappings": "AAQA,OAAS,gCAAAA,MAAoC,iDAI7C,MAAMC,EAAoB,gBAM1B,SAASC,EAAuBC,EAAuC,CACrE,MAAMC,EAAOD,EAAQ,QACrB,OACE,OAAOC,GAAS,UAChBA,IAAS,MACT,MAAM,QAAQA,CAAI,GAClBA,EAAK,OAAYH,GACjB,OAAOG,EAAK,MAAY,UACxB,OAAOA,EAAK,UAAgB,SAErB,KAEF,CACL,UACE,OAAOA,EAAK,WAAiB,SAAWA,EAAK,UAAe,OAC9D,KAAMA,EAAK,KACX,SAAUA,EAAK,SACf,UAAWD,EAAQ,SACrB,CACF,CAKO,SAASE,EACdC,EACAC,EACM,CACN,GAAI,CACF,KAAM,CAAE,OAAAC,CAAO,EAAI,KAAK,MAAMF,CAAO,EACrCC,EAAqBE,GAAS,IAAI,IAAI,CAAC,GAAGA,EAAMD,CAAM,CAAC,CAAC,CAC1D,OAAS,EAAG,CACV,QAAQ,MAAM,0CAA2C,CAAC,CAC5D,CACF,CAKO,SAASE,EACdJ,EACAK,EACAC,EACAC,EACS,CACT,MAAMV,EAAUH,EAA6BM,CAAO,EACpD,GAAIH,IAAY,KAAM,CAEpB,GADAQ,EAASF,GAAS,CAAC,GAAGA,EAAMN,CAAO,CAAC,EAChCU,EAAsB,CACxB,MAAMC,EAAWZ,EAAuBC,CAAO,EAC3CW,IAAa,MACfF,EAAkBH,GAAS,CAAC,GAAGA,EAAMK,CAAQ,CAAC,CAElD,CACA,MAAO,EACT,CACA,MAAO,EACT,CAKO,SAASC,EACdT,EACAU,EACM,CACN,GAAI,CACF,MAAMC,EAAU,KAAK,MAAMX,CAAO,EAClCU,EAAoBC,CAAO,CAC7B,OAAS,EAAG,CACV,QAAQ,MAAM,iDAAkD,CAAC,CACnE,CACF,CAKO,SAASC,EACdZ,EACAa,EACM,CACN,GAAI,CACF,KAAM,CAAE,UAAAC,EAAW,MAAAC,CAAM,EAAI,KAAK,MAAMf,CAAO,EAI/Ca,EAAkBV,GAAS,IAAI,IAAIA,CAAI,EAAE,IAAIW,EAAWC,CAAK,CAAC,CAChE,OAAS,EAAG,CACV,QAAQ,MAAM,mDAAoD,CAAC,CACrE,CACF,CAKO,SAASC,EACdhB,EACAiB,EACM,CACN,GAAI,CACF,MAAMN,EAAU,KAAK,MAAMX,CAAO,EAClCiB,EAAqBN,CAAO,CAC9B,OAAS,EAAG,CACV,QAAQ,MAAM,kDAAmD,CAAC,CACpE,CACF,CAKO,SAASO,EACdlB,EACAmB,EACM,CACN,GAAI,CACF,KAAM,CAAE,SAAAC,CAAS,EAAI,KAAK,MAAMpB,CAAO,EACvCmB,EAAiBC,CAAQ,CAC3B,OAAS,EAAG,CACV,QAAQ,MAAM,wCAAyC,CAAC,CAC1D,CACF,CAKO,SAASC,EACdrB,EACAsB,EACM,CACN,GAAI,CACF,MAAMC,EAAW,KAAK,MAAMvB,CAAO,EACnCsB,EAAkBnB,GAAS,IAAI,IAAIA,CAAI,EAAE,IAAIoB,EAAS,UAAWA,CAAQ,CAAC,CAC5E,OAAS,EAAG,CACV,QAAQ,MAAM,uCAAwC,CAAC,CACzD,CACF",
|
|
6
|
+
"names": ["mapConnectorMessageToLogData", "APDU_EXCHANGE_LOG", "tryExtractApduExchange", "logData", "data", "handleModuleConnected", "payload", "setConnectedModules", "module", "prev", "handleLogMessage", "setLogs", "setApduExchanges", "isRecordingExchanges", "exchange", "handleConnectedDevicesUpdate", "setConnectedDevices", "devices", "handleDeviceSessionStateUpdate", "setSessionStates", "sessionId", "state", "handleDiscoveredDevicesUpdate", "setDiscoveredDevices", "handleProviderValue", "setProviderValue", "provider", "handleApduResponse", "setApduResponses", "response"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useCallback as
|
|
1
|
+
import{useCallback as o,useEffect as X,useMemo as g,useRef as Z,useState as e}from"react";import{DEVTOOLS_MODULES as M,INSPECTOR_MESSAGE_TYPES as a,LOGGER_MESSAGE_TYPES as $,MODULE_CONNECTED_MESSAGE_TYPE as ee}from"@ledgerhq/device-management-kit-devtools-core";import{createApduCommands as se,createDiscoveryCommands as ne,createProviderCommands as oe}from"./commandDispatcher";import{handleApduResponse as te,handleConnectedDevicesUpdate as ie,handleDeviceSessionStateUpdate as ce,handleDiscoveredDevicesUpdate as re,handleLogMessage as ae,handleModuleConnected as de,handleProviderValue as ge}from"./connectorMessageHandlers";function Ee(i){const[S,R]=e([]),[h,A]=e([]),[L,u]=e([]),[v,b]=e(new Set),[f,x]=e([]),[P,_]=e(new Map),[I,c]=e([]),[T,D]=e(!1),[O,E]=e(!1),[V,U]=e(null),[k,G]=e(new Map),[N,l]=e([]),[y,m]=e(!1),p=Z(!1),t=g(()=>({...i,sendMessage:(d,r)=>{i.sendMessage(d,r),A(s=>[...s,{type:d,payload:r}])}}),[i]);X(()=>{const{unsubscribe:d}=i.listenToMessages((r,s)=>{switch(R(W=>[...W,{type:r,payload:s}]),r){case ee:de(s,b);break;case a.CONNECTED_DEVICES_UPDATE:ie(s,x);break;case a.DEVICE_SESSION_STATE_UPDATE:ce(s,_);break;case a.DISCOVERED_DEVICES_UPDATE:re(s,c);break;case a.PROVIDER_VALUE:ge(s,U);break;case a.APDU_RESPONSE:te(s,G);break;case $.ADD_LOG:ae(s,u,l,p.current);break}});return d},[i]);const n=g(()=>ne(t),[t]),C=g(()=>oe(t),[t]),w=g(()=>se(t),[t]),Y=o(()=>{D(!0),c([]),n.startListeningCommand()},[n]),q=o(()=>{D(!1),c([]),n.stopListeningCommand()},[n]),H=o(()=>{E(!0),c([]),n.startDiscoveringCommand()},[n]),K=o(()=>{E(!1),c([]),n.stopDiscoveringCommand()},[n]),j=o(()=>{u([])},[]),z=o(()=>{p.current=!0,m(!0)},[]),B=o(()=>{p.current=!1,m(!1)},[]),F=o(()=>{l([])},[]),J=v.has(M.LOGGER),Q=v.has(M.DMK_INSPECTOR);return{receivedMessages:S,sentMessages:h,logs:L,connectedModules:v,connectedDevices:f,sessionStates:P,discoveredDevices:I,isListening:T,isActivelyDiscovering:O,isLoggerConnected:J,isInspectorConnected:Q,providerValue:V,apduResponses:k,apduExchanges:N,isRecordingExchanges:y,sendMessage:t.sendMessage,clearLogs:j,startRecordingExchanges:z,stopRecordingExchanges:B,clearRecordedExchanges:F,startListening:Y,stopListening:q,startDiscovering:H,stopDiscovering:K,connectDevice:n.connectDeviceCommand,getProvider:C.getProviderCommand,setProvider:C.setProviderCommand,sendApdu:w.sendApduCommand}}export{Ee as useConnectorMessages};
|
|
2
2
|
//# sourceMappingURL=useConnectorMessages.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/hooks/useConnectorMessages.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @file useConnectorMessages hook\n *\n * Central hook for managing DevTools connector state and actions.\n * Handles all communication between the Dashboard UI and the client app\n * via the connector (WebSocket or Rozenite).\n */\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n type ConnectedDevice,\n type DeviceSessionState,\n type DiscoveredDevice,\n} from \"@ledgerhq/device-management-kit\";\nimport {\n type Connector,\n DEVTOOLS_MODULES,\n type DevToolsModule,\n INSPECTOR_MESSAGE_TYPES,\n MODULE_CONNECTED_MESSAGE_TYPE,\n} from \"@ledgerhq/device-management-kit-devtools-core\";\n\nimport { type Message } from \"../PluginEvents\";\nimport { type LogData } from \"../screens/logger/types\";\nimport {\n createApduCommands,\n createDiscoveryCommands,\n createProviderCommands,\n} from \"./commandDispatcher\";\nimport {\n handleApduResponse,\n handleConnectedDevicesUpdate,\n handleDeviceSessionStateUpdate,\n handleDiscoveredDevicesUpdate,\n handleLogMessage,\n handleModuleConnected,\n handleProviderValue,\n} from \"./connectorMessageHandlers\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ApduResponse = {\n requestId: string;\n success: boolean;\n statusCode?: number[];\n data?: number[];\n error?: string;\n};\n\nexport type ConnectorMessagesState = {\n receivedMessages: Message[];\n sentMessages: Message[];\n logs: LogData[];\n connectedModules: Set<DevToolsModule>;\n connectedDevices: ConnectedDevice[];\n sessionStates: Map<string, DeviceSessionState>;\n discoveredDevices: DiscoveredDevice[];\n isListening: boolean;\n isActivelyDiscovering: boolean;\n isLoggerConnected: boolean;\n isInspectorConnected: boolean;\n providerValue: number | null;\n apduResponses: Map<string, ApduResponse>;\n sendMessage: (type: string, payload: string) => void;\n clearLogs: () => void;\n startListening: () => void;\n stopListening: () => void;\n startDiscovering: () => void;\n stopDiscovering: () => void;\n connectDevice: (\n deviceId: string,\n sessionRefresherOptions?: {\n isRefresherDisabled: boolean;\n pollingInterval?: number;\n },\n ) => void;\n getProvider: () => void;\n setProvider: (value: number) => void;\n sendApdu: (sessionId: string, apduHex: string) => string;\n};\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Central hook for managing DevTools connector state and communication.\n *\n * This hook:\n * - Listens to messages from the connector and dispatches them to handlers\n * - Tracks all sent/received messages for debugging\n * - Manages device discovery, sessions, and DMK configuration state\n * - Provides action functions to send commands to the inspector module\n *\n * @param connector - The connector instance (WebSocket or Rozenite)\n * @returns State and actions for the Dashboard UI\n */\nexport function useConnectorMessages(\n connector: Connector,\n): ConnectorMessagesState {\n // === State ===\n const [receivedMessages, setReceivedMessages] = useState<Message[]>([]);\n const [sentMessages, setSentMessages] = useState<Message[]>([]);\n const [logs, setLogs] = useState<LogData[]>([]);\n const [connectedModules, setConnectedModules] = useState<Set<DevToolsModule>>(\n new Set(),\n );\n const [connectedDevices, setConnectedDevices] = useState<ConnectedDevice[]>(\n [],\n );\n const [sessionStates, setSessionStates] = useState<\n Map<string, DeviceSessionState>\n >(new Map());\n const [discoveredDevices, setDiscoveredDevices] = useState<\n DiscoveredDevice[]\n >([]);\n const [isListening, setIsListening] = useState(false);\n const [isActivelyDiscovering, setIsActivelyDiscovering] = useState(false);\n const [providerValue, setProviderValue] = useState<number | null>(null);\n const [apduResponses, setApduResponses] = useState<Map<string, ApduResponse>>(\n new Map(),\n );\n\n // === Tracked Connector (keeps all sent messages in state) ===\n const trackedConnector: Connector = useMemo(\n () => ({\n ...connector,\n sendMessage: (type: string, payload: string) => {\n connector.sendMessage(type, payload);\n setSentMessages((prev) => [...prev, { type, payload }]);\n },\n }),\n [connector],\n );\n\n // === Message Listener ===\n useEffect(() => {\n const { unsubscribe } = connector.listenToMessages((type, payload) => {\n setReceivedMessages((prev) => [...prev, { type, payload }]);\n\n switch (type) {\n case MODULE_CONNECTED_MESSAGE_TYPE:\n handleModuleConnected(payload, setConnectedModules);\n break;\n case INSPECTOR_MESSAGE_TYPES.CONNECTED_DEVICES_UPDATE:\n handleConnectedDevicesUpdate(payload, setConnectedDevices);\n break;\n case INSPECTOR_MESSAGE_TYPES.DEVICE_SESSION_STATE_UPDATE:\n handleDeviceSessionStateUpdate(payload, setSessionStates);\n break;\n case INSPECTOR_MESSAGE_TYPES.DISCOVERED_DEVICES_UPDATE:\n handleDiscoveredDevicesUpdate(payload, setDiscoveredDevices);\n break;\n case INSPECTOR_MESSAGE_TYPES.PROVIDER_VALUE:\n handleProviderValue(payload, setProviderValue);\n break;\n case INSPECTOR_MESSAGE_TYPES.APDU_RESPONSE:\n handleApduResponse(payload, setApduResponses);\n break;\n
|
|
5
|
-
"mappings": "AAQA,OAAS,eAAAA,EAAa,aAAAC,EAAW,WAAAC,EAAS,YAAAC,MAAgB,
|
|
6
|
-
"names": ["useCallback", "useEffect", "useMemo", "useState", "DEVTOOLS_MODULES", "INSPECTOR_MESSAGE_TYPES", "MODULE_CONNECTED_MESSAGE_TYPE", "createApduCommands", "createDiscoveryCommands", "createProviderCommands", "handleApduResponse", "handleConnectedDevicesUpdate", "handleDeviceSessionStateUpdate", "handleDiscoveredDevicesUpdate", "handleLogMessage", "handleModuleConnected", "handleProviderValue", "useConnectorMessages", "connector", "receivedMessages", "setReceivedMessages", "sentMessages", "setSentMessages", "logs", "setLogs", "connectedModules", "setConnectedModules", "connectedDevices", "setConnectedDevices", "sessionStates", "setSessionStates", "discoveredDevices", "setDiscoveredDevices", "isListening", "setIsListening", "isActivelyDiscovering", "setIsActivelyDiscovering", "providerValue", "setProviderValue", "apduResponses", "setApduResponses", "trackedConnector", "type", "payload", "prev", "unsubscribe", "discoveryCommands", "providerCommands", "apduCommands", "startListening", "stopListening", "startDiscovering", "stopDiscovering", "clearLogs", "isLoggerConnected", "isInspectorConnected"]
|
|
4
|
+
"sourcesContent": ["/**\n * @file useConnectorMessages hook\n *\n * Central hook for managing DevTools connector state and actions.\n * Handles all communication between the Dashboard UI and the client app\n * via the connector (WebSocket or Rozenite).\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n type ConnectedDevice,\n type DeviceSessionState,\n type DiscoveredDevice,\n} from \"@ledgerhq/device-management-kit\";\nimport {\n type Connector,\n DEVTOOLS_MODULES,\n type DevToolsModule,\n INSPECTOR_MESSAGE_TYPES,\n LOGGER_MESSAGE_TYPES,\n MODULE_CONNECTED_MESSAGE_TYPE,\n} from \"@ledgerhq/device-management-kit-devtools-core\";\n\nimport { type Message } from \"../PluginEvents\";\nimport { type LogData } from \"../screens/logger/types\";\nimport {\n createApduCommands,\n createDiscoveryCommands,\n createProviderCommands,\n} from \"./commandDispatcher\";\nimport {\n handleApduResponse,\n handleConnectedDevicesUpdate,\n handleDeviceSessionStateUpdate,\n handleDiscoveredDevicesUpdate,\n handleLogMessage,\n handleModuleConnected,\n handleProviderValue,\n} from \"./connectorMessageHandlers\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ApduResponse = {\n requestId: string;\n success: boolean;\n statusCode?: number[];\n data?: number[];\n error?: string;\n};\n\n/**\n * A single APDU exchange (request + response) captured passively from the DMK\n * logs of the host app. Used to derive mock-server mocks.\n */\nexport type ApduExchange = {\n sessionId?: string;\n apdu: string;\n response: string;\n timestamp: string;\n};\n\nexport type ConnectorMessagesState = {\n receivedMessages: Message[];\n sentMessages: Message[];\n logs: LogData[];\n connectedModules: Set<DevToolsModule>;\n connectedDevices: ConnectedDevice[];\n sessionStates: Map<string, DeviceSessionState>;\n discoveredDevices: DiscoveredDevice[];\n isListening: boolean;\n isActivelyDiscovering: boolean;\n isLoggerConnected: boolean;\n isInspectorConnected: boolean;\n providerValue: number | null;\n apduResponses: Map<string, ApduResponse>;\n apduExchanges: ApduExchange[];\n isRecordingExchanges: boolean;\n sendMessage: (type: string, payload: string) => void;\n clearLogs: () => void;\n startRecordingExchanges: () => void;\n stopRecordingExchanges: () => void;\n clearRecordedExchanges: () => void;\n startListening: () => void;\n stopListening: () => void;\n startDiscovering: () => void;\n stopDiscovering: () => void;\n connectDevice: (\n deviceId: string,\n sessionRefresherOptions?: {\n isRefresherDisabled: boolean;\n pollingInterval?: number;\n },\n ) => void;\n getProvider: () => void;\n setProvider: (value: number) => void;\n sendApdu: (sessionId: string, apduHex: string) => string;\n};\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Central hook for managing DevTools connector state and communication.\n *\n * This hook:\n * - Listens to messages from the connector and dispatches them to handlers\n * - Tracks all sent/received messages for debugging\n * - Manages device discovery, sessions, and DMK configuration state\n * - Provides action functions to send commands to the inspector module\n *\n * @param connector - The connector instance (WebSocket or Rozenite)\n * @returns State and actions for the Dashboard UI\n */\nexport function useConnectorMessages(\n connector: Connector,\n): ConnectorMessagesState {\n // === State ===\n const [receivedMessages, setReceivedMessages] = useState<Message[]>([]);\n const [sentMessages, setSentMessages] = useState<Message[]>([]);\n const [logs, setLogs] = useState<LogData[]>([]);\n const [connectedModules, setConnectedModules] = useState<Set<DevToolsModule>>(\n new Set(),\n );\n const [connectedDevices, setConnectedDevices] = useState<ConnectedDevice[]>(\n [],\n );\n const [sessionStates, setSessionStates] = useState<\n Map<string, DeviceSessionState>\n >(new Map());\n const [discoveredDevices, setDiscoveredDevices] = useState<\n DiscoveredDevice[]\n >([]);\n const [isListening, setIsListening] = useState(false);\n const [isActivelyDiscovering, setIsActivelyDiscovering] = useState(false);\n const [providerValue, setProviderValue] = useState<number | null>(null);\n const [apduResponses, setApduResponses] = useState<Map<string, ApduResponse>>(\n new Map(),\n );\n const [apduExchanges, setApduExchanges] = useState<ApduExchange[]>([]);\n const [isRecordingExchanges, setIsRecordingExchanges] = useState(false);\n const isRecordingExchangesRef = useRef(false);\n\n // === Tracked Connector (keeps all sent messages in state) ===\n const trackedConnector: Connector = useMemo(\n () => ({\n ...connector,\n sendMessage: (type: string, payload: string) => {\n connector.sendMessage(type, payload);\n setSentMessages((prev) => [...prev, { type, payload }]);\n },\n }),\n [connector],\n );\n\n // === Message Listener ===\n useEffect(() => {\n const { unsubscribe } = connector.listenToMessages((type, payload) => {\n setReceivedMessages((prev) => [...prev, { type, payload }]);\n\n switch (type) {\n case MODULE_CONNECTED_MESSAGE_TYPE:\n handleModuleConnected(payload, setConnectedModules);\n break;\n case INSPECTOR_MESSAGE_TYPES.CONNECTED_DEVICES_UPDATE:\n handleConnectedDevicesUpdate(payload, setConnectedDevices);\n break;\n case INSPECTOR_MESSAGE_TYPES.DEVICE_SESSION_STATE_UPDATE:\n handleDeviceSessionStateUpdate(payload, setSessionStates);\n break;\n case INSPECTOR_MESSAGE_TYPES.DISCOVERED_DEVICES_UPDATE:\n handleDiscoveredDevicesUpdate(payload, setDiscoveredDevices);\n break;\n case INSPECTOR_MESSAGE_TYPES.PROVIDER_VALUE:\n handleProviderValue(payload, setProviderValue);\n break;\n case INSPECTOR_MESSAGE_TYPES.APDU_RESPONSE:\n handleApduResponse(payload, setApduResponses);\n break;\n case LOGGER_MESSAGE_TYPES.ADD_LOG:\n handleLogMessage(\n payload,\n setLogs,\n setApduExchanges,\n isRecordingExchangesRef.current,\n );\n break;\n }\n });\n return unsubscribe;\n }, [connector]);\n\n // === Commands (using tracked connector to log all sent messages) ===\n const discoveryCommands = useMemo(\n () => createDiscoveryCommands(trackedConnector),\n [trackedConnector],\n );\n const providerCommands = useMemo(\n () => createProviderCommands(trackedConnector),\n [trackedConnector],\n );\n const apduCommands = useMemo(\n () => createApduCommands(trackedConnector),\n [trackedConnector],\n );\n\n // === Wrapped Commands (with local state updates) ===\n const startListening = useCallback(() => {\n setIsListening(true);\n setDiscoveredDevices([]);\n discoveryCommands.startListeningCommand();\n }, [discoveryCommands]);\n\n const stopListening = useCallback(() => {\n setIsListening(false);\n setDiscoveredDevices([]);\n discoveryCommands.stopListeningCommand();\n }, [discoveryCommands]);\n\n const startDiscovering = useCallback(() => {\n setIsActivelyDiscovering(true);\n setDiscoveredDevices([]);\n discoveryCommands.startDiscoveringCommand();\n }, [discoveryCommands]);\n\n const stopDiscovering = useCallback(() => {\n setIsActivelyDiscovering(false);\n setDiscoveredDevices([]);\n discoveryCommands.stopDiscoveringCommand();\n }, [discoveryCommands]);\n\n const clearLogs = useCallback(() => {\n setLogs([]);\n }, []);\n\n const startRecordingExchanges = useCallback(() => {\n isRecordingExchangesRef.current = true;\n setIsRecordingExchanges(true);\n }, []);\n\n const stopRecordingExchanges = useCallback(() => {\n isRecordingExchangesRef.current = false;\n setIsRecordingExchanges(false);\n }, []);\n\n const clearRecordedExchanges = useCallback(() => {\n setApduExchanges([]);\n }, []);\n\n // === Derived State ===\n const isLoggerConnected = connectedModules.has(DEVTOOLS_MODULES.LOGGER);\n const isInspectorConnected = connectedModules.has(\n DEVTOOLS_MODULES.DMK_INSPECTOR,\n );\n\n return {\n // State\n receivedMessages,\n sentMessages,\n logs,\n connectedModules,\n connectedDevices,\n sessionStates,\n discoveredDevices,\n isListening,\n isActivelyDiscovering,\n isLoggerConnected,\n isInspectorConnected,\n providerValue,\n apduResponses,\n apduExchanges,\n isRecordingExchanges,\n // Actions\n sendMessage: trackedConnector.sendMessage,\n clearLogs,\n startRecordingExchanges,\n stopRecordingExchanges,\n clearRecordedExchanges,\n startListening,\n stopListening,\n startDiscovering,\n stopDiscovering,\n connectDevice: discoveryCommands.connectDeviceCommand,\n getProvider: providerCommands.getProviderCommand,\n setProvider: providerCommands.setProviderCommand,\n sendApdu: apduCommands.sendApduCommand,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["useCallback", "useEffect", "useMemo", "useRef", "useState", "DEVTOOLS_MODULES", "INSPECTOR_MESSAGE_TYPES", "LOGGER_MESSAGE_TYPES", "MODULE_CONNECTED_MESSAGE_TYPE", "createApduCommands", "createDiscoveryCommands", "createProviderCommands", "handleApduResponse", "handleConnectedDevicesUpdate", "handleDeviceSessionStateUpdate", "handleDiscoveredDevicesUpdate", "handleLogMessage", "handleModuleConnected", "handleProviderValue", "useConnectorMessages", "connector", "receivedMessages", "setReceivedMessages", "sentMessages", "setSentMessages", "logs", "setLogs", "connectedModules", "setConnectedModules", "connectedDevices", "setConnectedDevices", "sessionStates", "setSessionStates", "discoveredDevices", "setDiscoveredDevices", "isListening", "setIsListening", "isActivelyDiscovering", "setIsActivelyDiscovering", "providerValue", "setProviderValue", "apduResponses", "setApduResponses", "apduExchanges", "setApduExchanges", "isRecordingExchanges", "setIsRecordingExchanges", "isRecordingExchangesRef", "trackedConnector", "type", "payload", "prev", "unsubscribe", "discoveryCommands", "providerCommands", "apduCommands", "startListening", "stopListening", "startDiscovering", "stopDiscovering", "clearLogs", "startRecordingExchanges", "stopRecordingExchanges", "clearRecordedExchanges", "isLoggerConnected", "isInspectorConnected"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
function r(a){const{timestamp:t,tag:s,verbosity:e,message:n,payloadJSON:o}=JSON.parse(a);return{timestamp:t,tag:s,verbosity:e,message:n,payloadJSON:o,payload:JSON.parse(o)}}export{r as mapConnectorMessageToLogData};
|
|
2
2
|
//# sourceMappingURL=mapConnectorMessageToLogData.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/screens/logger/mapConnectorMessageToLogData.ts"],
|
|
4
|
-
"sourcesContent": ["import
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import type { DevToolsLog, LogData } from \"./types\";\n\nexport function mapConnectorMessageToLogData(payload: string): LogData | null {\n const { timestamp, tag, verbosity, message, payloadJSON } = JSON.parse(\n payload,\n ) as DevToolsLog;\n return {\n timestamp,\n tag,\n verbosity,\n message,\n payloadJSON,\n // TODO: fix this type\n payload: JSON.parse(payloadJSON) as string | Record<string, unknown>,\n };\n}\n"],
|
|
5
|
+
"mappings": "AAEO,SAASA,EAA6BC,EAAiC,CAC5E,KAAM,CAAE,UAAAC,EAAW,IAAAC,EAAK,UAAAC,EAAW,QAAAC,EAAS,YAAAC,CAAY,EAAI,KAAK,MAC/DL,CACF,EACA,MAAO,CACL,UAAAC,EACA,IAAAC,EACA,UAAAC,EACA,QAAAC,EACA,YAAAC,EAEA,QAAS,KAAK,MAAMA,CAAW,CACjC,CACF",
|
|
6
|
+
"names": ["mapConnectorMessageToLogData", "payload", "timestamp", "tag", "verbosity", "message", "payloadJSON"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{DeviceSessionStateType as c,StaticDeviceModelDataSource as t}from"@ledgerhq/device-management-kit";const r="BOLOS",p=new t;function v(e){return"firmwareVersion"in e&&e.firmwareVersion?.os?e.firmwareVersion.os:"currentApp"in e&&e.currentApp?.name===r?e.currentApp.version:""}function f(e,i){if(!e)return{};const o=v(e),n={name:p.getDeviceModel({id:e.deviceModelId}).productName,device_type:e.deviceModelId,...i?{connectivity_type:i}:{},firmware_version:o};return e.sessionStateType===c.Connected?n:{...n,...e.currentApp&&e.currentApp.name!==r?{apps:[{name:e.currentApp.name,version:e.currentApp.version}]}:{}}}export{f as deviceConfigFromSession};
|
|
2
|
+
//# sourceMappingURL=deviceConfigFromSession.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/screens/mock-capture/deviceConfigFromSession.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n type ConnectedDevice,\n type DeviceSessionState,\n DeviceSessionStateType,\n StaticDeviceModelDataSource,\n} from \"@ledgerhq/device-management-kit\";\nimport { type DeviceConfig } from \"@ledgerhq/device-mockserver-client\";\n\ntype ConnectivityType = ConnectedDevice[\"type\"];\n\nconst DASHBOARD_APP_NAME = \"BOLOS\";\nconst deviceModelDataSource = new StaticDeviceModelDataSource();\n\nfunction firmwareVersionFromState(state: DeviceSessionState): string {\n if (\"firmwareVersion\" in state && state.firmwareVersion?.os) {\n return state.firmwareVersion.os;\n }\n if (\"currentApp\" in state && state.currentApp?.name === DASHBOARD_APP_NAME) {\n return state.currentApp.version;\n }\n return \"\";\n}\n\n/**\n * Builds a partial mock-server device config from a DMK device session state.\n *\n * The mock server's `device_type` values match the `DeviceModelId` enum values\n * (e.g. \"nanoX\", \"stax\"), so the model id is used directly. The `name` is the\n * commercial model name (e.g. \"Flex\", \"Gen 5\"). The optional `connectivityType`\n * (\"USB\" / \"BLE\") comes from the connected device. The `firmware_version` (SE\n * version) is always present, defaulting to an empty string until the session\n * is ready. The running app is only available once the session is ready.\n */\nexport function deviceConfigFromSession(\n state?: DeviceSessionState,\n connectivityType?: ConnectivityType,\n): Partial<DeviceConfig> {\n if (!state) {\n return {};\n }\n\n const firmwareVersion = firmwareVersionFromState(state);\n const deviceModel = deviceModelDataSource.getDeviceModel({\n id: state.deviceModelId,\n });\n\n const base: Partial<DeviceConfig> = {\n name: deviceModel.productName,\n device_type: state.deviceModelId,\n ...(connectivityType ? { connectivity_type: connectivityType } : {}),\n firmware_version: firmwareVersion,\n };\n\n if (state.sessionStateType === DeviceSessionStateType.Connected) {\n return base;\n }\n\n return {\n ...base,\n // The dashboard (BOLOS) is not an installed app, so it is never listed.\n ...(state.currentApp && state.currentApp.name !== DASHBOARD_APP_NAME\n ? {\n apps: [\n { name: state.currentApp.name, version: state.currentApp.version },\n ],\n }\n : {}),\n };\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAGE,0BAAAA,EACA,+BAAAC,MACK,kCAKP,MAAMC,EAAqB,QACrBC,EAAwB,IAAIF,EAElC,SAASG,EAAyBC,EAAmC,CACnE,MAAI,oBAAqBA,GAASA,EAAM,iBAAiB,GAChDA,EAAM,gBAAgB,GAE3B,eAAgBA,GAASA,EAAM,YAAY,OAASH,EAC/CG,EAAM,WAAW,QAEnB,EACT,CAYO,SAASC,EACdD,EACAE,EACuB,CACvB,GAAI,CAACF,EACH,MAAO,CAAC,EAGV,MAAMG,EAAkBJ,EAAyBC,CAAK,EAKhDI,EAA8B,CAClC,KALkBN,EAAsB,eAAe,CACvD,GAAIE,EAAM,aACZ,CAAC,EAGmB,YAClB,YAAaA,EAAM,cACnB,GAAIE,EAAmB,CAAE,kBAAmBA,CAAiB,EAAI,CAAC,EAClE,iBAAkBC,CACpB,EAEA,OAAIH,EAAM,mBAAqBL,EAAuB,UAC7CS,EAGF,CACL,GAAGA,EAEH,GAAIJ,EAAM,YAAcA,EAAM,WAAW,OAASH,EAC9C,CACE,KAAM,CACJ,CAAE,KAAMG,EAAM,WAAW,KAAM,QAASA,EAAM,WAAW,OAAQ,CACnE,CACF,EACA,CAAC,CACP,CACF",
|
|
6
|
+
"names": ["DeviceSessionStateType", "StaticDeviceModelDataSource", "DASHBOARD_APP_NAME", "deviceModelDataSource", "firmwareVersionFromState", "state", "deviceConfigFromSession", "connectivityType", "firmwareVersion", "base"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const a=["e0010000","b0010000"];function c(e){return a.some(o=>e.startsWith(o))}function p(e){return e.every(n=>n===e[0])?e.slice(0,1):e}function u(e,o){const n=new Map;for(const i of e){const t=i.apdu.toLowerCase();if(!o&&c(t))continue;const s=n.get(t)??[];s.push(i.response.toLowerCase()),n.set(t,s)}return[...n.entries()].map(([i,t])=>({prefix:i,responses:p(t)}))}function r(e,o,n){const i=u(o,n),{name:t,...s}=e;return{...t!==void 0?{name:t}:{},...s,mocks:i}}function d(e,o={},n={}){return{devices:[r(o,e,n.includeHandshake??!1)]}}function f(e,o={}){const n=o.includeHandshake??!1;return{devices:e.map(({device:i,exchanges:t})=>r(i,t,n))}}export{f as generateMultiDeviceSessionExport,d as generateSessionExport};
|
|
2
|
+
//# sourceMappingURL=generateSessionExport.js.map
|