fix: Switch to biome & vitest (#726)

This commit is contained in:
Nerivec
2025-03-23 21:30:14 +01:00
committed by GitHub
parent 44c5bbcc1c
commit 94b76a910a
48 changed files with 1762 additions and 4075 deletions
+9 -9
View File
@@ -1,10 +1,10 @@
import {getJson, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type ImagesJsonBuildPart = {
path: string; // .bin
offset: number;
type?: 'app' | 'storage';
type?: "app" | "storage";
ota?: string; // .ota
};
type ImagesJsonBuild = {
@@ -21,11 +21,11 @@ type ImagesJson = {
builds: ImagesJsonBuild[];
};
const NAME = 'GammaTroniques';
const NAME = "GammaTroniques";
// const LOG_PREFIX = `[${NAME}]`;
const BASE_URL = 'https://update.gammatroniques.fr/';
const MANIFEST_URL_PATH = `/manifest.json`;
const MODEL_IDS: [urlId: string, modelId: string][] = [['ticmeter', 'TICMeter']];
const BASE_URL = "https://update.gammatroniques.fr/";
const MANIFEST_URL_PATH = "/manifest.json";
const MODEL_IDS: [urlId: string, modelId: string][] = [["ticmeter", "TICMeter"]];
function isDifferent(newData: ImagesJson, cachedData?: ImagesJson): boolean {
return Boolean(process.env.IGNORE_CACHE) || !cachedData || cachedData.version !== newData.version;
@@ -62,14 +62,14 @@ export async function download(): Promise<void> {
writeCacheJson(cacheFileName, page);
const appUrl: ImagesJsonBuildPart | undefined = page.builds[0].parts.find((part) => part.type === 'app');
const appUrl: ImagesJsonBuildPart | undefined = page.builds[0].parts.find((part) => part.type === "app");
if (!appUrl || !appUrl.ota) {
console.error(`${logPrefix} No image found.`);
continue;
}
const firmwareFileName = appUrl.ota.split('/').pop()!;
const firmwareFileName = appUrl.ota.split("/").pop()!;
await processFirmwareImage(NAME, firmwareFileName, appUrl.ota, {modelId});
}
+3 -3
View File
@@ -1,7 +1,7 @@
import type {ExtraMetas} from '../types.js';
import type {ExtraMetas} from "../types.js";
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type ReleaseAssetJson = {
url: string;
+20 -20
View File
@@ -1,5 +1,5 @@
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type ImageJson = {
createdAt: string;
@@ -13,34 +13,34 @@ type ImageJson = {
};
type PageJson = {updates: ImageJson[]};
const NAME = 'Hue';
const BASE_URL = 'https://firmware.meethue.com/v1/checkupdate?version=0&deviceTypeId=';
const NAME = "Hue";
const BASE_URL = "https://firmware.meethue.com/v1/checkupdate?version=0&deviceTypeId=";
const DEVICE_TYPE_IDS: string[] = [
'100b-111',
'100b-112',
"100b-111",
"100b-112",
// '100b-113',
'100b-114',
'100b-115',
"100b-114",
"100b-115",
// '100b-116',
'100b-117',
'100b-118',
"100b-117",
"100b-118",
// '100b-119',
'100b-11a',
"100b-11a",
// '100b-11b',
// '100b-11c',
'100b-11d',
'100b-11e',
'100b-11f',
'100b-120',
"100b-11d",
"100b-11e",
"100b-11f",
"100b-120",
// '100b-121',
// '100b-122',
'100b-123',
"100b-123",
// '100b-124',
'100b-125',
"100b-125",
// '100b-126',
'100b-127',
"100b-127",
// '100b-128',
'100b-129',
"100b-129",
// '100b-12a',
// '100b-12b',
// '100b-12c',
@@ -98,7 +98,7 @@ export async function download(): Promise<void> {
continue;
}
const firmwareFileName = image.binaryUrl.split('/').pop()!;
const firmwareFileName = image.binaryUrl.split("/").pop()!;
await processFirmwareImage(NAME, firmwareFileName, image.binaryUrl, {releaseNotes: image.releaseNotes || undefined});
}
+9 -7
View File
@@ -1,5 +1,5 @@
import {getJson, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type GatewayImageJson = {
fw_binary_url: string;
@@ -16,7 +16,9 @@ type GatewayImageJson = {
};
type DeviceImageJson = {
fw_binary_url: string;
// biome-ignore lint/style/useNamingConvention: <explanation>
fw_file_version_LSB: number;
// biome-ignore lint/style/useNamingConvention: <explanation>
fw_file_version_MSB: number;
fw_filesize: number;
fw_image_type: number;
@@ -25,16 +27,16 @@ type DeviceImageJson = {
};
type ImagesJson = (GatewayImageJson | DeviceImageJson)[];
const NAME = 'IKEA';
const NAME = "IKEA";
const LOG_PREFIX = `[${NAME}]`;
const PRODUCTION_FIRMWARE_URL = 'http://fw.ota.homesmart.ikea.net/feed/version_info.json';
const PRODUCTION_FIRMWARE_URL = "http://fw.ota.homesmart.ikea.net/feed/version_info.json";
// const TEST_FIRMWARE_URL = 'http://fw.test.ota.homesmart.ikea.net/feed/version_info.json';
export const RELEASE_NOTES_URL = 'https://ww8.ikea.com/ikeahomesmart/releasenotes/releasenotes.html';
export const RELEASE_NOTES_URL = "https://ww8.ikea.com/ikeahomesmart/releasenotes/releasenotes.html";
function findInCache(image: DeviceImageJson, cachedData?: ImagesJson): DeviceImageJson | undefined {
// `fw_type` compare ensures always `DeviceImagesJson`
return cachedData?.find(
(d) => d.fw_type == image.fw_type && d.fw_image_type == image.fw_image_type && d.fw_manufacturer_id == image.fw_manufacturer_id,
(d) => d.fw_type === image.fw_type && d.fw_image_type === image.fw_image_type && d.fw_manufacturer_id === image.fw_manufacturer_id,
) as DeviceImageJson | undefined;
}
@@ -67,7 +69,7 @@ export async function download(): Promise<void> {
continue;
}
const firmwareFileName = image.fw_binary_url.split('/').pop()!;
const firmwareFileName = image.fw_binary_url.split("/").pop()!;
if (!isDifferent(image, findInCache(image, cachedData))) {
console.log(`[${NAME}:${firmwareFileName}] No change from last run.`);
+7 -7
View File
@@ -1,6 +1,6 @@
import {getJson, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {RELEASE_NOTES_URL} from './ikea.js';
import {getJson, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
import {RELEASE_NOTES_URL} from "./ikea.js";
type GatewayImageJson = {
fw_type: 3;
@@ -23,15 +23,15 @@ type DeviceImageJson = {
type ImagesJson = (GatewayImageJson | DeviceImageJson)[];
// same name as `ikea.ts` to keep everything in same folder
const NAME = 'IKEA';
const NAME = "IKEA";
const CACHE_FILENAME = `${NAME}_new`;
const LOG_PREFIX = `[${NAME}_new]`;
// requires cacerts/ikea_new.pem
const FIRMWARE_URL = 'https://fw.ota.homesmart.ikea.com/check/update/prod';
const FIRMWARE_URL = "https://fw.ota.homesmart.ikea.com/check/update/prod";
function findInCache(image: DeviceImageJson, cachedData?: ImagesJson): DeviceImageJson | undefined {
// `fw_type` compare ensures always `DeviceImagesJson`
return cachedData?.find((d) => d.fw_type == image.fw_type && d.fw_image_type == image.fw_image_type) as DeviceImageJson | undefined;
return cachedData?.find((d) => d.fw_type === image.fw_type && d.fw_image_type === image.fw_image_type) as DeviceImageJson | undefined;
}
function isDifferent(newData: DeviceImageJson, cachedData?: DeviceImageJson): boolean {
@@ -58,7 +58,7 @@ export async function download(): Promise<void> {
continue;
}
const firmwareFileName = image.fw_binary_url.split('/').pop()!;
const firmwareFileName = image.fw_binary_url.split("/").pop()!;
if (!isDifferent(image, findInCache(image, cachedData))) {
console.log(`[${NAME}:${firmwareFileName}] No change from last run.`);
+9 -9
View File
@@ -1,9 +1,9 @@
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type DeviceImageJson = {
version: string;
channel: 'beta' | 'production';
channel: "beta" | "production";
firmware: string;
manufacturer_id: number;
image_type: number;
@@ -12,15 +12,15 @@ type ModelsJson = {
[k: string]: DeviceImageJson[];
};
const NAME = 'Inovelli';
const NAME = "Inovelli";
const LOG_PREFIX = `[${NAME}]`;
const FIRMWARE_URL = 'https://files.inovelli.com/firmware/firmware.json';
const FIRMWARE_URL = "https://files.inovelli.com/firmware/firmware.json";
function sortByVersion(a: DeviceImageJson, b: DeviceImageJson): number {
const aRadix = a.version.match(/[a-fA-F]/) ? 16 : 10;
const bRadix = b.version.match(/[a-fA-F]/) ? 16 : 10;
const aVersion = parseInt(a.version, aRadix);
const bVersion = parseInt(b.version, bRadix);
const aVersion = Number.parseInt(a.version, aRadix);
const bVersion = Number.parseInt(b.version, bRadix);
return aVersion < bVersion ? -1 : aVersion > bVersion ? 1 : 0;
}
@@ -44,7 +44,7 @@ export async function download(): Promise<void> {
const cachedData = readCacheJson<ModelsJson>(NAME);
for (const model in models) {
if (model == '') {
if (model === "") {
// ignore empty key (bug)
continue;
}
@@ -55,7 +55,7 @@ export async function download(): Promise<void> {
continue;
}
const firmwareFileName = image.firmware.split('/').pop()!;
const firmwareFileName = image.firmware.split("/").pop()!;
if (cachedData && !isDifferent(image, getLatestImage(cachedData[model], sortByVersion))) {
console.log(`[${NAME}:${firmwareFileName}] No change from last run.`);
+9 -10
View File
@@ -1,5 +1,5 @@
import {getJson, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type ImageJson = {
vendor: string;
@@ -13,12 +13,12 @@ type ImageJson = {
version: string;
date: string;
images: {
'zigbee.ota': {
"zigbee.ota": {
url: string;
hash: string;
filesize: number;
};
'zigbee.bin': {
"zigbee.bin": {
url: string;
hash: string;
filesize: number;
@@ -29,12 +29,12 @@ type ImageJson = {
};
};
const NAME = 'JetHome';
const NAME = "JetHome";
const LOG_PREFIX = `[${NAME}]`;
const BASE_URL = 'https://fw.jethome.ru';
const BASE_URL = "https://fw.jethome.ru";
const DEVICE_URL = `${BASE_URL}/api/devices/`;
const MODEL_IDS = ['WS7'];
const MODEL_IDS = ["WS7"];
function getCacheFileName(modelId: string): string {
return `${NAME}_${modelId}`;
@@ -62,14 +62,14 @@ export async function download(): Promise<void> {
// XXX: this is assumed to always be present even for devices that support OTA but without images yet available?
if (image?.latest_firmware?.release?.images) {
const firmware = image.latest_firmware.release.images['zigbee.ota'];
const firmware = image.latest_firmware.release.images["zigbee.ota"];
if (!firmware) {
continue;
}
const firmwareUrl = BASE_URL + firmware.url;
const firmwareFileName = firmwareUrl.split('/').pop()!;
const firmwareFileName = firmwareUrl.split("/").pop()!;
const cacheFileName = getCacheFileName(modelId);
if (!isDifferent(image, readCacheJson(cacheFileName))) {
@@ -85,7 +85,6 @@ export async function download(): Promise<void> {
});
} else {
console.error(`${LOG_PREFIX} No image data for ${modelId}.`);
continue;
}
}
}
+7 -7
View File
@@ -1,5 +1,5 @@
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage, ProcessFirmwareImageStatus} from '../process_firmware_image.js';
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js";
import {ProcessFirmwareImageStatus, processFirmwareImage} from "../process_firmware_image.js";
type FirmwareJson = {
blob: null;
@@ -34,12 +34,12 @@ type ImagesJson = {
};
type GroupedImagesJson = Record<string, FirmwareJson[]>;
const NAME = 'LEDVANCE';
const NAME = "LEDVANCE";
const LOG_PREFIX = `[${NAME}]`;
const FIRMWARE_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/';
const FIRMWARE_URL = "https://api.update.ledvance.com/v1/zigbee/firmwares/";
// const UPDATE_CHECK_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/newer';
// const UPDATE_CHECK_PARAMS = `?company=${manufCode}&product=${imageType}&version=0.0.0`;
const UPDATE_DOWNLOAD_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/download';
const UPDATE_DOWNLOAD_URL = "https://api.update.ledvance.com/v1/zigbee/firmwares/download";
/** XXX: getting 429 after a few downloads, force more throttling. Seems to trigger after around ~20 requests. */
const FETCH_FAILED_THROTTLE_MS = 60000;
const FETCH_FAILED_RETRIES = 3;
@@ -98,7 +98,7 @@ export async function download(): Promise<void> {
// const fileVersion = parseInt(fileVersionMatch[1], 16);
const firmwareUrl = `${UPDATE_DOWNLOAD_URL}?company=${firmware.identity.company}&product=${firmware.identity.product}&version=${getVersionString(firmware)}`;
const firmwareFileName = firmware.fullName.split('/').pop()!;
const firmwareFileName = firmware.fullName.split("/").pop()!;
if (cachedDataByProduct && !isDifferent(firmware, getLatestImage(cachedDataByProduct[product], sortByReleased))) {
console.log(`[${NAME}:${firmwareFileName}] No change from last run.`);
@@ -112,7 +112,7 @@ export async function download(): Promise<void> {
releaseNotes: firmware.releaseNotes,
});
if (status === ProcessFirmwareImageStatus.REQUEST_FAILED) {
if (status === ProcessFirmwareImageStatus.RequestFailed) {
await new Promise((resolve) => setTimeout(resolve, FETCH_FAILED_THROTTLE_MS));
} else {
break;
+4 -4
View File
@@ -1,9 +1,9 @@
import * as github from './github.js';
import * as github from "./github.js";
const NAME = 'LiXee';
const FIRMWARE_URL = 'https://api.github.com/repos/fairecasoimeme/Zlinky_TIC/releases';
const NAME = "LiXee";
const FIRMWARE_URL = "https://api.github.com/repos/fairecasoimeme/Zlinky_TIC/releases";
/** @see https://github.com/fairecasoimeme/Zlinky_TIC?tab=readme-ov-file#route-or-limited-route-from-v7 */
const FIRMWARE_EXT = '.ota';
const FIRMWARE_EXT = ".ota";
const FIRMWARE_LIMITED = `limited${FIRMWARE_EXT}`;
export async function writeCache(): Promise<void> {
+7 -7
View File
@@ -1,5 +1,5 @@
import {getJson, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getJson, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type ImageJson = {
model: string;
@@ -10,12 +10,12 @@ type ImagesJson = {
versions: ImageJson[];
};
const NAME = 'SalusControls';
const NAME = "SalusControls";
const LOG_PREFIX = `[${NAME}]`;
const FIRMWARE_URL = 'https://eu.salusconnect.io/demo/default/status/firmware?timestamp=0';
const FIRMWARE_URL = "https://eu.salusconnect.io/demo/default/status/firmware?timestamp=0";
function findInCache(image: ImageJson, cachedData?: ImagesJson): ImageJson | undefined {
return cachedData?.versions?.find((d) => d.model == image.model);
return cachedData?.versions?.find((d) => d.model === image.model);
}
function isDifferent(newData: ImageJson, cachedData?: ImageJson): boolean {
@@ -38,14 +38,14 @@ export async function download(): Promise<void> {
for (const image of images.versions) {
const archiveUrl = image.url; //.replace(/^http:\/\//, 'https://');
const archiveFileName = archiveUrl.split('/').pop()!;
const archiveFileName = archiveUrl.split("/").pop()!;
if (!isDifferent(image, findInCache(image, cachedData))) {
console.log(`[${NAME}:${archiveFileName}] No change from last run.`);
continue;
}
await processFirmwareImage(NAME, archiveFileName, archiveUrl, {manufacturerName: [NAME]}, true, (fileName) => fileName.endsWith('.ota'));
await processFirmwareImage(NAME, archiveFileName, archiveUrl, {manufacturerName: [NAME]}, true, (fileName) => fileName.endsWith(".ota"));
}
writeCacheJson(NAME, images);
+11 -11
View File
@@ -1,7 +1,7 @@
import url from 'url';
import url from "node:url";
import {getLatestImage, getText, readCacheJson, writeCacheJson} from '../common.js';
import {processFirmwareImage} from '../process_firmware_image.js';
import {getLatestImage, getText, readCacheJson, writeCacheJson} from "../common.js";
import {processFirmwareImage} from "../process_firmware_image.js";
type Image = {
fileName: string;
@@ -14,14 +14,14 @@ type GroupedImages = {
[k: string]: Image[];
};
const NAME = 'Ubisys';
const NAME = "Ubisys";
const LOG_PREFIX = `[${NAME}]`;
const FIRMWARE_HTML_URL = 'http://fwu.ubisys.de/smarthome/OTA/release/index';
const FIRMWARE_HTML_URL = "http://fwu.ubisys.de/smarthome/OTA/release/index";
function groupByImageType(arr: Image[]): GroupedImages {
return arr.reduce<GroupedImages>((acc, cur) => {
acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : '')] = [
...(acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : '')] || []),
acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : "")] = [
...(acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : "")] || []),
cur,
];
return acc;
@@ -37,7 +37,7 @@ function isDifferent(newData: Image, cachedData?: Image): boolean {
}
function parseText(pageText: string): Image[] {
const lines = pageText.split('\n');
const lines = pageText.split("\n");
const images: Image[] = [];
for (const line of lines) {
@@ -48,9 +48,9 @@ function parseText(pageText: string): Image[] {
images.push({
fileName: imageMatch[0],
imageType: imageMatch[1],
hardwareVersionMin: parseInt(imageMatch[2], 16),
hardwareVersionMax: parseInt(imageMatch[3], 16),
fileVersion: parseInt(imageMatch[4], 16),
hardwareVersionMin: Number.parseInt(imageMatch[2], 16),
hardwareVersionMax: Number.parseInt(imageMatch[3], 16),
fileVersion: Number.parseInt(imageMatch[4], 16),
});
}
}
+5 -5
View File
@@ -1,13 +1,13 @@
import * as github from './github.js';
import * as github from "./github.js";
const NAME = 'xyzroe';
const FIRMWARE_URL = 'https://api.github.com/repos/xyzroe/ZigUSB_C6/releases';
const FIRMWARE_EXT = '.ota';
const NAME = "xyzroe";
const FIRMWARE_URL = "https://api.github.com/repos/xyzroe/ZigUSB_C6/releases";
const FIRMWARE_EXT = ".ota";
export async function writeCache(): Promise<void> {
await github.writeCache(NAME, FIRMWARE_URL);
}
export async function download(): Promise<void> {
await github.download(NAME, FIRMWARE_URL, [(a): boolean => a.name.endsWith(FIRMWARE_EXT)], {modelId: 'ZigUSB_C6'});
await github.download(NAME, FIRMWARE_URL, [(a): boolean => a.name.endsWith(FIRMWARE_EXT)], {modelId: "ZigUSB_C6"});
}