From 0dad5fa035f2ee7a31ef5cf7bc19f4dab0b06d0f Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 19 Jul 2026 19:48:03 -0400 Subject: [PATCH] test(desktop): add temporary backend verification harness Adds a throwaway App.vue that exercises enumerate/open_device/list_dir/ close_device over Tauri 2 IPC and logs addDevice/removeDevice/progress events. open_device, list_dir, and close_device are wrapped with a 10s client-side timeout each so a hang or Busy response from the CX II's known firmware issue can't block the other calls from reporting; enumerate only reads USB descriptors and is left untimed. Installs @tauri-apps/plugin-dialog and @tauri-apps/plugin-shell per the task-7 brief's Step 1. Manual GUI verification against a connected device (brief Steps 3-4) is out of scope here and left to the user; download_file/sha256 cross-check is intentionally omitted since any libnspire transfer against this CX II is known to hang. Replaced by the real UI in Plan B. --- desktop/package.json | 12 ++- desktop/src/App.vue | 223 ++++++++++++++----------------------------- package-lock.json | 61 +++++------- 3 files changed, 105 insertions(+), 191 deletions(-) diff --git a/desktop/package.json b/desktop/package.json index 30a3f19..cc29464 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -10,15 +10,17 @@ "tauri": "tauri" }, "dependencies": { - "vue": "^3.5.13", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-opener": "^2" + "@tauri-apps/api": "^2.11.1", + "@tauri-apps/plugin-dialog": "^2.7.2", + "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-shell": "^2.3.5", + "vue": "^3.5.13" }, "devDependencies": { + "@tauri-apps/cli": "^2", "@vitejs/plugin-vue": "^5.2.1", "typescript": "~5.6.2", "vite": "^6.0.3", - "vue-tsc": "^2.1.10", - "@tauri-apps/cli": "^2" + "vue-tsc": "^2.1.10" } } diff --git a/desktop/src/App.vue b/desktop/src/App.vue index b209212..d3079ea 100644 --- a/desktop/src/App.vue +++ b/desktop/src/App.vue @@ -1,160 +1,81 @@ - - - - \ No newline at end of file +async function run() { + log.value = ''; + + // enumerate only reads USB descriptors, no device transfer — it never + // hangs, so it gets no timeout and always reports before anything else runs. + const enumerateResult = await step('enumerate', () => invoke('enumerate')); + if (!enumerateResult.ok) return; + + const devices = enumerateResult.result; + if (!devices.length) { + add('NO DEVICES FOUND'); + return; + } + + const { busNumber, address } = devices[0]; + add(`opening ${busNumber}:${address}`); + + // The remaining commands perform real libnspire transfers and are the + // ones known to hang or return Busy on this machine's CX II firmware. + await step('open_device', () => invoke('open_device', { busNumber, address }), TRANSFER_TIMEOUT_MS); + await step('list_dir /', () => invoke('list_dir', { busNumber, address, path: '/' }), TRANSFER_TIMEOUT_MS); + await step('close_device', () => invoke('close_device', { busNumber, address }), TRANSFER_TIMEOUT_MS); +} + diff --git a/package-lock.json b/package-lock.json index 711cc45..3012b0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,10 @@ "name": "n-link", "version": "0.1.0", "dependencies": { - "@tauri-apps/api": "^2", + "@tauri-apps/api": "^2.11.1", + "@tauri-apps/plugin-dialog": "^2.7.2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-shell": "^2.3.5", "vue": "^3.5.13" }, "devDependencies": { @@ -4550,7 +4552,6 @@ "version": "2.18.1", "resolved": "https://registry.npmjs.org/@nuxt/types/-/types-2.18.1.tgz", "integrity": "sha512-PpReoV9oHCnSpB9WqemTUWmlH1kqFHC3Xe5LH904VvCl/3xLO2nGYcrHeZCMV5hXNWsDUyqDnd/2cQHmeqj5lA==", - "dev": true, "dependencies": { "@types/babel__core": "7.20.5", "@types/compression": "1.7.5", @@ -5685,6 +5686,14 @@ "node": ">= 10" } }, + "node_modules/@tauri-apps/plugin-dialog": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.7.2.tgz", + "integrity": "sha512-pX0IGm1I3I6wc+zeKYcq1GSqogK6okCNX5fOdaNU5ab1AjGS6l1E5wFNjEb7meg7ZFSp0JUs+0jQGQNyOvLrsg==", + "dependencies": { + "@tauri-apps/api": "^2.11.0" + } + }, "node_modules/@tauri-apps/plugin-opener": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz", @@ -5693,11 +5702,18 @@ "@tauri-apps/api": "^2.11.0" } }, + "node_modules/@tauri-apps/plugin-shell": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.3.5.tgz", + "integrity": "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg==", + "dependencies": { + "@tauri-apps/api": "^2.10.1" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -5710,7 +5726,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -5719,7 +5734,6 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -5729,7 +5743,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, "dependencies": { "@babel/types": "^7.28.2" } @@ -5738,7 +5751,6 @@ "version": "1.19.6", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -5748,7 +5760,6 @@ "version": "1.7.5", "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", - "dev": true, "dependencies": { "@types/express": "*" } @@ -5757,7 +5768,6 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -5778,7 +5788,6 @@ "version": "1.8.3", "resolved": "https://registry.npmjs.org/@types/etag/-/etag-1.8.3.tgz", "integrity": "sha512-QYHv9Yeh1ZYSMPQOoxY4XC4F1r+xRUiAriB303F4G6uBsT3KKX60DjiogvVv+2VISVDuJhcIzMdbjT+Bm938QQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -5787,7 +5796,6 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", @@ -5798,7 +5806,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.2.tgz", "integrity": "sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -5810,7 +5817,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*" @@ -5820,7 +5826,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/file-loader/-/file-loader-5.0.4.tgz", "integrity": "sha512-aB4X92oi5D2nIGI8/kolnJ47btRM2MQjQS4eJgA/VnCD12x0+kP5v7b5beVQWKHLOcquwUXvv6aMt8PmMy9uug==", - "dev": true, "dependencies": { "@types/webpack": "^4" } @@ -5834,14 +5839,12 @@ "node_modules/@types/html-minifier-terser": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-7.0.2.tgz", - "integrity": "sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==", - "dev": true + "integrity": "sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==" }, "node_modules/@types/http-errors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -5857,8 +5860,7 @@ "node_modules/@types/less": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.6.tgz", - "integrity": "sha512-PecSzorDGdabF57OBeQO/xFbAkYWo88g4Xvnsx7LRwqLC17I7OoKtA3bQB9uXkY6UkMWCOsA8HSVpaoitscdXw==", - "dev": true + "integrity": "sha512-PecSzorDGdabF57OBeQO/xFbAkYWo88g4Xvnsx7LRwqLC17I7OoKtA3bQB9uXkY6UkMWCOsA8HSVpaoitscdXw==" }, "node_modules/@types/node": { "version": "16.18.126", @@ -5875,7 +5877,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/@types/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz", "integrity": "sha512-n134DdmRVXTy0KKbgg3A/G02r2XJKJicYzbJYhdIO8rdYdzoMv6GNHjog2Oq1ttaCOhsYcPIA6Sn7eFxEGCM1A==", - "dev": true, "dependencies": { "@types/webpack": "^4" } @@ -5888,26 +5889,22 @@ "node_modules/@types/pug": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", - "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", - "dev": true + "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==" }, "node_modules/@types/qs": { "version": "6.15.1", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", - "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", - "dev": true + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -5916,7 +5913,6 @@ "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -5937,7 +5933,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-4.2.1.tgz", "integrity": "sha512-x688KsgQKJF8PPfv4qSvHQztdZNHLlWJdolN9/ptAGimHVy3rY+vHdfglQDFh1Z39h7eMWOd6fQ7ke3PKQcdyA==", - "dev": true, "dependencies": { "@types/webpack": "^4", "terser": "^4.6.13" @@ -5974,7 +5969,6 @@ "version": "3.9.5", "resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.5.tgz", "integrity": "sha512-QlyDyX7rsOIJHASzXWlih8DT9fR+XCG9cwIV/4pKrtScdHv4XFshdEf/7iiqLqG0lzWcoBdzG8ylMHQ5XLNixw==", - "dev": true, "dependencies": { "@types/webpack": "^4" } @@ -5983,7 +5977,6 @@ "version": "2.25.5", "resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.5.tgz", "integrity": "sha512-/eRWWMgZteNzl17qLCRdRmtKPZuWy984b11Igz9+BAU5a99Hc2AJinnMohMPVahGRSHby4XwsnjlgIt9m0Ce3g==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/webpack": "^4" @@ -8399,8 +8392,7 @@ "node_modules/consola": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "dev": true + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, "node_modules/console-browserify": { "version": "1.2.0", @@ -20367,7 +20359,6 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver"