From e87a6f28e0cb9fa6ef3d80ea9e615edd88f6afd7 Mon Sep 17 00:00:00 2001 From: Dave Allie Date: Mon, 19 Jan 2026 21:32:15 +1100 Subject: [PATCH 1/4] Fix lint issues --- src/app/debug/page.tsx | 15 +++++++-------- src/app/page.tsx | 32 ++++++++++++++++---------------- src/esp/EspController.ts | 6 +++--- src/esp/useEspOperations.ts | 19 +++++++++++++------ src/utils/firmwareIdentifier.ts | 24 ++++++++++++++---------- 5 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/app/debug/page.tsx b/src/app/debug/page.tsx index a0514fb..aa0bab2 100644 --- a/src/app/debug/page.tsx +++ b/src/app/debug/page.tsx @@ -26,7 +26,6 @@ import OtaPartition, { OtaPartitionDetails } from '@/esp/OtaPartition'; import HexSpan from '@/components/HexSpan'; import HexViewer from '@/components/HexViewer'; import { downloadData } from '@/utils/download'; -import FileUpload, { FileUploadHandle } from '@/components/FileUpload'; import { FirmwareInfo } from '@/utils/firmwareIdentifier'; function OtadataDebug({ otaPartition }: { otaPartition: OtaPartition }) { @@ -220,6 +219,7 @@ function FirmwareIdentificationDebug({ case 'crosspoint': return 'blue'; case 'unknown': + default: return 'orange'; } }; @@ -272,9 +272,8 @@ function FirmwareIdentificationDebug({ } export default function Debug() { - const { actions, debugActions, stepData, isRunning } = useEspOperations(); + const { debugActions, stepData, isRunning } = useEspOperations(); const [debugOutputNode, setDebugOutputNode] = useState(null); - const appPartitionFileInput = React.useRef(null); return ( @@ -284,8 +283,8 @@ export default function Debug() {

These are few tools to help debugging / administering your Xtink - device. They're designed to be used by those who are - intentionally messing around with their device. + device. They’re designed to be used by those who are intentionally + messing around with their device.

Read otadata partition will read the raw data out of the{' '} @@ -303,8 +302,8 @@ export default function Debug() { otadata to switch the boot partition.

- Identify firmware in both partitions will read both app0 and - app1 partitions and automatically identify which firmware is + Identify firmware in both partitions will read both app0 + and app1 partitions and automatically identify which firmware is installed on each (Official English, Official Chinese, CrossPoint Community, or Custom).

@@ -414,4 +413,4 @@ export default function Debug() { ) : null}
); -} \ No newline at end of file +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 11a459a..bedc09c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -48,10 +48,10 @@ export default function Home() {

- I've tried to make this foolproof and while the likelihood - of unrecoverable things going wrong is extremely low, it's - never zero. So proceed with care and make sure to grab a backup - using Save full flash before flashing your device. + I’ve tried to make this foolproof and while the likelihood of + unrecoverable things going wrong is extremely low, it’s never + zero. So proceed with care and make sure to grab a backup using{' '} + Save full flash before flashing your device.

Once you start Write flash from file or{' '} @@ -75,10 +75,10 @@ export default function Home() { goes wrong.

- Save full flash will read your device's flash and save - it as flash.bin. This will take around 25 minutes to - complete. You can use that file (or someone else's) with{' '} - Write full flash from file to overwrite your device's + Save full flash will read your device’s flash and save it + as flash.bin. This will take around 25 minutes to + complete. You can use that file (or someone else’s) with{' '} + Write full flash from file to overwrite your device’s entire flash.

@@ -116,8 +116,8 @@ export default function Home() { OTA fast flash controls

- Before using this, I'd strongly recommend taking a backup of - your device using Save full flash above. + Before using this, I’d strongly recommend taking a backup of your + device using Save full flash above.

Flash English/Chinese firmware will download the firmware, @@ -208,9 +208,9 @@ export default function Home() { Change device language Before starting the process, it is recommended to change the device - language to English. To do this, select "Settings" icon, then - click "OK / Confirm" button and "OK / Confirm" again until English is shown. - Otherwise, the language will still be Chinese after flashing + language to English. To do this, select “Settings” icon, then click + “OK / Confirm” button and “OK / Confirm” again until English is + shown. Otherwise, the language will still be Chinese after flashing and you may not notice changes. @@ -221,9 +221,9 @@ export default function Home() { Device restart instructions Once you complete a write operation, you will need to restart your - device by pressing and releasing the small "Reset" button near the bottom - right, followed quickly by pressing and holding of the main power - button for about 3 seconds. + device by pressing and releasing the small “Reset” button near the + bottom right, followed quickly by pressing and holding of the main + power button for about 3 seconds. diff --git a/src/esp/EspController.ts b/src/esp/EspController.ts index 855fdf4..27db8b4 100644 --- a/src/esp/EspController.ts +++ b/src/esp/EspController.ts @@ -104,7 +104,7 @@ export default class EspController { return this.espLoader.readFlash(offset, 0x640000, onPacketReceived); } - async readAppPartitionForIdentification( + async readAppPartitionForIdentification( partitionLabel: 'app0' | 'app1', { readSize = 0x6400, // Default to 25KB (0x6400) for fast identification @@ -123,7 +123,7 @@ export default class EspController { // Optimized read for firmware identification with flexible read size and offset: // - Default (25KB / 0x6400): Fast path, covers 99% of cases // - Additional chunks: Specify offset multiples of 25KB until identification succeeds - // In testing, most firmwares are identified within the first 25KB read, so reading the entire + // In testing, most firmwares are identified within the first 25KB read, so reading the entire // partition is unnecessary in the majority of cases. const baseOffset = partitionLabel === 'app0' ? 0x10000 : 0x650000; @@ -183,4 +183,4 @@ export default class EspController { reportProgress, }); } -} \ No newline at end of file +} diff --git a/src/esp/useEspOperations.ts b/src/esp/useEspOperations.ts index a568824..eda15bf 100644 --- a/src/esp/useEspOperations.ts +++ b/src/esp/useEspOperations.ts @@ -23,10 +23,10 @@ export function useEspOperations() { const wrapWithRunning = (fn: (...a: Args) => Promise) => - async (...a: Args) => { - setIsRunning(true); - return fn(...a).finally(() => setIsRunning(false)); - }; + async (...a: Args) => { + setIsRunning(true); + return fn(...a).finally(() => setIsRunning(false)); + }; const flashRemoteFirmware = async ( getFirmware: () => Promise, @@ -416,6 +416,7 @@ export function useEspOperations() { let info: FirmwareInfo | undefined; for (let offset = 0; offset < maxReadSize; offset += chunkSize) { + // eslint-disable-next-line no-await-in-loop const chunk = await espController.readAppPartitionForIdentification( partitionLabel, { @@ -441,7 +442,13 @@ export function useEspOperations() { } } - return info ?? { type: 'unknown', version: 'unknown', displayName: 'Custom/Unknown Firmware' }; // Return the last identification result if not found + return ( + info ?? { + type: 'unknown', + version: 'unknown', + displayName: 'Custom/Unknown Firmware', + } + ); // Return the last identification result if not found }; const app0Info = await runStep('Read app0 partition', () => @@ -486,4 +493,4 @@ export function useEspOperations() { readAndIdentifyAllFirmware: wrapWithRunning(readAndIdentifyAllFirmware), }, }; -} \ No newline at end of file +} diff --git a/src/utils/firmwareIdentifier.ts b/src/utils/firmwareIdentifier.ts index 909148b..8edd0d6 100644 --- a/src/utils/firmwareIdentifier.ts +++ b/src/utils/firmwareIdentifier.ts @@ -19,9 +19,9 @@ function findString( return -1; } - for (let i = startOffset; i <= data.length - searchBytes.length; i++) { + for (let i = startOffset; i <= data.length - searchBytes.length; i += 1) { let match = true; - for (let j = 0; j < searchBytes.length; j++) { + for (let j = 0; j < searchBytes.length; j += 1) { if (data[i + j] !== searchBytes[j]) { match = false; break; @@ -73,7 +73,7 @@ function extractVersion(data: Uint8Array, searchLimit = 25000): string { // Try to find V-pattern versions (official firmware) // Pattern: [any byte] Date: Mon, 19 Jan 2026 21:32:47 +1100 Subject: [PATCH 2/4] Add pre-commit hook --- .husky/pre-commit | 1 + package.json | 11 +- yarn.lock | 271 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/package.json b/package.json index 3a5727e..20710a4 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "lint:fix": "yarn eslint --max-warnings 0 --cache --fix && yarn prettier --write .", "dev": "next dev", "build": "next build", - "start": "next start" + "start": "next start", + "prepare": "husky" }, "dependencies": { "@chakra-ui/react": "^3.31.0", @@ -44,9 +45,17 @@ "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.1", "globals": "^16.5.0", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "prettier": "^3.8.0", "typescript": "^5.9.3", "typescript-eslint": "^8.53.0" }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "yarn eslint --cache --fix --max-warnings 0 --no-warn-ignored", + "yarn prettier --write" + ] + }, "packageManager": "yarn@4.11.0" } diff --git a/yarn.lock b/yarn.lock index c2c99c9..b5d7770 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2438,6 +2438,22 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^7.0.0": + version: 7.2.0 + resolution: "ansi-escapes@npm:7.2.0" + dependencies: + environment: "npm:^1.0.0" + checksum: 10c0/b562fd995761fa12f33be316950ee58fda489e125d331bcd9131434969a2eb55dc14e9405f214dcf4697c9d67c576ba0baf6e8f3d52058bf9222c97560b220cb + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f + languageName: node + linkType: hard + "ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" @@ -2454,6 +2470,13 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^6.2.1": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -2760,6 +2783,25 @@ __metadata: languageName: node linkType: hard +"cli-cursor@npm:^5.0.0": + version: 5.0.0 + resolution: "cli-cursor@npm:5.0.0" + dependencies: + restore-cursor: "npm:^5.0.0" + checksum: 10c0/7ec62f69b79f6734ab209a3e4dbdc8af7422d44d360a7cb1efa8a0887bbe466a6e625650c466fe4359aee44dbe2dc0b6994b583d40a05d0808a5cb193641d220 + languageName: node + linkType: hard + +"cli-truncate@npm:^5.0.0": + version: 5.1.1 + resolution: "cli-truncate@npm:5.1.1" + dependencies: + slice-ansi: "npm:^7.1.0" + string-width: "npm:^8.0.0" + checksum: 10c0/3842920829a62f3e041ce39199050c42706c3c9c756a4efc8b86d464e102d1fa031d8b1b9b2e3bb36e1017c763558275472d031bdc884c1eff22a2f20e4f6b0a + languageName: node + linkType: hard + "client-only@npm:0.0.1": version: 0.0.1 resolution: "client-only@npm:0.0.1" @@ -2783,6 +2825,20 @@ __metadata: languageName: node linkType: hard +"colorette@npm:^2.0.20": + version: 2.0.20 + resolution: "colorette@npm:2.0.20" + checksum: 10c0/e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40 + languageName: node + linkType: hard + +"commander@npm:^14.0.2": + version: 14.0.2 + resolution: "commander@npm:14.0.2" + checksum: 10c0/245abd1349dbad5414cb6517b7b5c584895c02c4f7836ff5395f301192b8566f9796c82d7bd6c92d07eba8775fe4df86602fca5d86d8d10bcc2aded1e21c2aeb + languageName: node + linkType: hard + "comment-parser@npm:^1.4.1": version: 1.4.1 resolution: "comment-parser@npm:1.4.1" @@ -2983,6 +3039,13 @@ __metadata: languageName: node linkType: hard +"emoji-regex@npm:^10.3.0": + version: 10.6.0 + resolution: "emoji-regex@npm:10.6.0" + checksum: 10c0/1e4aa097bb007301c3b4b1913879ae27327fdc48e93eeefefe3b87e495eb33c5af155300be951b4349ff6ac084f4403dc9eff970acba7c1c572d89396a9a32d7 + languageName: node + linkType: hard + "emoji-regex@npm:^9.2.2": version: 9.2.2 resolution: "emoji-regex@npm:9.2.2" @@ -2990,6 +3053,13 @@ __metadata: languageName: node linkType: hard +"environment@npm:^1.0.0": + version: 1.1.0 + resolution: "environment@npm:1.1.0" + checksum: 10c0/fb26434b0b581ab397039e51ff3c92b34924a98b2039dcb47e41b7bca577b9dbf134a8eadb364415c74464b682e2d3afe1a4c0eb9873dc44ea814c5d3103331d + languageName: node + linkType: hard + "error-ex@npm:^1.3.1": version: 1.3.4 resolution: "error-ex@npm:1.3.4" @@ -3529,6 +3599,13 @@ __metadata: languageName: node linkType: hard +"eventemitter3@npm:^5.0.1": + version: 5.0.1 + resolution: "eventemitter3@npm:5.0.1" + checksum: 10c0/4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814 + languageName: node + linkType: hard + "expect@npm:^30.0.0": version: 30.2.0 resolution: "expect@npm:30.2.0" @@ -3686,6 +3763,13 @@ __metadata: languageName: node linkType: hard +"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.0, get-east-asian-width@npm:^1.3.1": + version: 1.4.0 + resolution: "get-east-asian-width@npm:1.4.0" + checksum: 10c0/4e481d418e5a32061c36fbb90d1b225a254cc5b2df5f0b25da215dcd335a3c111f0c2023ffda43140727a9cafb62dac41d022da82c08f31083ee89f714ee3b83 + languageName: node + linkType: hard + "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" @@ -3866,6 +3950,15 @@ __metadata: languageName: node linkType: hard +"husky@npm:^9.1.7": + version: 9.1.7 + resolution: "husky@npm:9.1.7" + bin: + husky: bin.js + checksum: 10c0/35bb110a71086c48906aa7cd3ed4913fb913823715359d65e32e0b964cb1e255593b0ae8014a5005c66a68e6fa66c38dcfa8056dbbdfb8b0187c0ffe7ee3a58f + languageName: node + linkType: hard + "ignore@npm:^5.2.0": version: 5.3.2 resolution: "ignore@npm:5.3.2" @@ -4020,6 +4113,15 @@ __metadata: languageName: node linkType: hard +"is-fullwidth-code-point@npm:^5.0.0": + version: 5.1.0 + resolution: "is-fullwidth-code-point@npm:5.1.0" + dependencies: + get-east-asian-width: "npm:^1.3.1" + checksum: 10c0/c1172c2e417fb73470c56c431851681591f6a17233603a9e6f94b7ba870b2e8a5266506490573b607fb1081318589372034aa436aec07b465c2029c0bc7f07a4 + languageName: node + linkType: hard + "is-generator-function@npm:^1.0.10": version: 1.1.2 resolution: "is-generator-function@npm:1.1.2" @@ -4376,6 +4478,37 @@ __metadata: languageName: node linkType: hard +"lint-staged@npm:^16.2.7": + version: 16.2.7 + resolution: "lint-staged@npm:16.2.7" + dependencies: + commander: "npm:^14.0.2" + listr2: "npm:^9.0.5" + micromatch: "npm:^4.0.8" + nano-spawn: "npm:^2.0.0" + pidtree: "npm:^0.6.0" + string-argv: "npm:^0.3.2" + yaml: "npm:^2.8.1" + bin: + lint-staged: bin/lint-staged.js + checksum: 10c0/9a677c21a8112d823ae5bc565ba2c9e7b803786f2a021c46827a55fe44ed59def96edb24fc99c06a2545cdbbf366022ad82addcb3bf60c712f3b98ef92069717 + languageName: node + linkType: hard + +"listr2@npm:^9.0.5": + version: 9.0.5 + resolution: "listr2@npm:9.0.5" + dependencies: + cli-truncate: "npm:^5.0.0" + colorette: "npm:^2.0.20" + eventemitter3: "npm:^5.0.1" + log-update: "npm:^6.1.0" + rfdc: "npm:^1.4.1" + wrap-ansi: "npm:^9.0.0" + checksum: 10c0/46448d1ba0addc9d71aeafd05bb8e86ded9641ccad930ac302c2bd2ad71580375604743e18586fcb8f11906edf98e8e17fca75ba0759947bf275d381f68e311d + languageName: node + linkType: hard + "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -4392,6 +4525,19 @@ __metadata: languageName: node linkType: hard +"log-update@npm:^6.1.0": + version: 6.1.0 + resolution: "log-update@npm:6.1.0" + dependencies: + ansi-escapes: "npm:^7.0.0" + cli-cursor: "npm:^5.0.0" + slice-ansi: "npm:^7.1.0" + strip-ansi: "npm:^7.1.0" + wrap-ansi: "npm:^9.0.0" + checksum: 10c0/4b350c0a83d7753fea34dcac6cd797d1dc9603291565de009baa4aa91c0447eab0d3815a05c8ec9ac04fdfffb43c82adcdb03ec1fceafd8518e1a8c1cff4ff89 + languageName: node + linkType: hard + "loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" @@ -4429,6 +4575,13 @@ __metadata: languageName: node linkType: hard +"mimic-function@npm:^5.0.0": + version: 5.0.1 + resolution: "mimic-function@npm:5.0.1" + checksum: 10c0/f3d9464dd1816ecf6bdf2aec6ba32c0728022039d992f178237d8e289b48764fee4131319e72eedd4f7f094e22ded0af836c3187a7edc4595d28dd74368fd81d + languageName: node + linkType: hard + "minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -4463,6 +4616,13 @@ __metadata: languageName: node linkType: hard +"nano-spawn@npm:^2.0.0": + version: 2.0.0 + resolution: "nano-spawn@npm:2.0.0" + checksum: 10c0/d00f9b5739f86e28cb732ffd774793e110810cded246b8393c75c4f22674af47f98ee37b19f022ada2d8c9425f800e841caa0662fbff4c0930a10e39339fb366 + languageName: node + linkType: hard + "nanoid@npm:^3.3.6": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -4636,6 +4796,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^7.0.0": + version: 7.0.0 + resolution: "onetime@npm:7.0.0" + dependencies: + mimic-function: "npm:^5.0.0" + checksum: 10c0/5cb9179d74b63f52a196a2e7037ba2b9a893245a5532d3f44360012005c9cadb60851d56716ebff18a6f47129dab7168022445df47c2aff3b276d92585ed1221 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -4763,6 +4932,15 @@ __metadata: languageName: node linkType: hard +"pidtree@npm:^0.6.0": + version: 0.6.0 + resolution: "pidtree@npm:0.6.0" + bin: + pidtree: bin/pidtree.js + checksum: 10c0/0829ec4e9209e230f74ebf4265f5ccc9ebfb488334b525cb13f86ff801dca44b362c41252cd43ae4d7653a10a5c6ab3be39d2c79064d6895e0d78dc50a5ed6e9 + languageName: node + linkType: hard + "possible-typed-array-names@npm:^1.0.0": version: 1.1.0 resolution: "possible-typed-array-names@npm:1.1.0" @@ -4998,6 +5176,23 @@ __metadata: languageName: node linkType: hard +"restore-cursor@npm:^5.0.0": + version: 5.1.0 + resolution: "restore-cursor@npm:5.1.0" + dependencies: + onetime: "npm:^7.0.0" + signal-exit: "npm:^4.1.0" + checksum: 10c0/c2ba89131eea791d1b25205bdfdc86699767e2b88dee2a590b1a6caa51737deac8bad0260a5ded2f7c074b7db2f3a626bcf1fcf3cdf35974cbeea5e2e6764f60 + languageName: node + linkType: hard + +"rfdc@npm:^1.4.1": + version: 1.4.1 + resolution: "rfdc@npm:1.4.1" + checksum: 10c0/4614e4292356cafade0b6031527eea9bc90f2372a22c012313be1dcc69a3b90c7338158b414539be863fa95bfcb2ddcd0587be696841af4e6679d85e62c060c7 + languageName: node + linkType: hard + "safe-array-concat@npm:^1.1.3": version: 1.1.3 resolution: "safe-array-concat@npm:1.1.3" @@ -5242,6 +5437,13 @@ __metadata: languageName: node linkType: hard +"signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -5249,6 +5451,16 @@ __metadata: languageName: node linkType: hard +"slice-ansi@npm:^7.1.0": + version: 7.1.2 + resolution: "slice-ansi@npm:7.1.2" + dependencies: + ansi-styles: "npm:^6.2.1" + is-fullwidth-code-point: "npm:^5.0.0" + checksum: 10c0/36742f2eb0c03e2e81a38ed14d13a64f7b732fe38c3faf96cce0599788a345011e840db35f1430ca606ea3f8db2abeb92a8d25c2753a819e3babaa10c2e289a2 + languageName: node + linkType: hard + "source-map-js@npm:^1.0.2": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" @@ -5289,6 +5501,34 @@ __metadata: languageName: node linkType: hard +"string-argv@npm:^0.3.2": + version: 0.3.2 + resolution: "string-argv@npm:0.3.2" + checksum: 10c0/75c02a83759ad1722e040b86823909d9a2fc75d15dd71ec4b537c3560746e33b5f5a07f7332d1e3f88319909f82190843aa2f0a0d8c8d591ec08e93d5b8dec82 + languageName: node + linkType: hard + +"string-width@npm:^7.0.0": + version: 7.2.0 + resolution: "string-width@npm:7.2.0" + dependencies: + emoji-regex: "npm:^10.3.0" + get-east-asian-width: "npm:^1.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 10c0/eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9 + languageName: node + linkType: hard + +"string-width@npm:^8.0.0": + version: 8.1.0 + resolution: "string-width@npm:8.1.0" + dependencies: + get-east-asian-width: "npm:^1.3.0" + strip-ansi: "npm:^7.1.0" + checksum: 10c0/749b5d0dab2532b4b6b801064230f4da850f57b3891287023117ab63a464ad79dd208f42f793458f48f3ad121fe2e1f01dd525ff27ead957ed9f205e27406593 + languageName: node + linkType: hard + "string.prototype.includes@npm:^2.0.1": version: 2.0.1 resolution: "string.prototype.includes@npm:2.0.1" @@ -5369,6 +5609,15 @@ __metadata: languageName: node linkType: hard +"strip-ansi@npm:^7.1.0": + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/0d6d7a023de33368fd042aab0bf48f4f4077abdfd60e5393e73c7c411e85e1b3a83507c11af2e656188511475776215df9ca589b4da2295c9455cc399ce1858b + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -5751,6 +6000,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^9.0.0": + version: 9.0.2 + resolution: "wrap-ansi@npm:9.0.2" + dependencies: + ansi-styles: "npm:^6.2.1" + string-width: "npm:^7.0.0" + strip-ansi: "npm:^7.1.0" + checksum: 10c0/3305839b9a0d6fb930cb63a52f34d3936013d8b0682ff3ec133c9826512620f213800ffa19ea22904876d5b7e9a3c1f40682f03597d986a4ca881fa7b033688c + languageName: node + linkType: hard + "xteink-flasher@workspace:.": version: 0.0.0-use.local resolution: "xteink-flasher@workspace:." @@ -5781,6 +6041,8 @@ __metadata: eslint-plugin-react-hooks: "npm:^7.0.1" esptool-js: "patch:esptool-js@npm%3A0.5.7#~/.yarn/patches/esptool-js-npm-0.5.7-bd6223d76a.patch" globals: "npm:^16.5.0" + husky: "npm:^9.1.7" + lint-staged: "npm:^16.2.7" next: "npm:16.1.3" next-themes: "npm:^0.4.6" prettier: "npm:^3.8.0" @@ -5807,6 +6069,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.8.1": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" + bin: + yaml: bin.mjs + checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 + languageName: node + linkType: hard + "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0" From 61f71547eb49d36314c7fdd9a7694ee6f1b559a9 Mon Sep 17 00:00:00 2001 From: Dave Allie Date: Mon, 19 Jan 2026 21:32:53 +1100 Subject: [PATCH 3/4] Lint in CI --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ .tool-versions | 1 + 2 files changed, 21 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .tool-versions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6435e2d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI +'on': + push: + branches: [master] + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .tool-versions + cache: yarn + + - name: Run linter + run: yarn lint diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..695dfec --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 24 From 20270e63055f463e8723572f0c241d4fca0cab35 Mon Sep 17 00:00:00 2001 From: Dave Allie Date: Mon, 19 Jan 2026 21:36:15 +1100 Subject: [PATCH 4/4] Install node modules in CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6435e2d..cdc5f94 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,5 +16,8 @@ jobs: node-version-file: .tool-versions cache: yarn + - name: Install Packages + run: yarn --immutable + - name: Run linter run: yarn lint