diff --git a/package-lock.json b/package-lock.json index 1a5da6c..6a0c655 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "@types/jest": "^28.1.6", "@types/node": "^12.20.11", "@types/node-fetch": "^2.6.2", + "@types/semver": "^7.3.13", "@types/w3c-web-serial": "^1.0.2", "@typescript-eslint/eslint-plugin": "^4.22.0", "@typescript-eslint/parser": "^4.22.0", @@ -43,6 +44,7 @@ "rollup-plugin-polyfill-node": "^0.10.1", "rollup-plugin-visualizer": "^5.7.1", "semantic-release": "^19.0.2", + "semver": "^7.3.8", "typescript": "^4.2.4", "wds": "^0.12.0" }, @@ -3343,6 +3345,12 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -13953,9 +13961,9 @@ } }, "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -17879,6 +17887,12 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -25615,9 +25629,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" diff --git a/package.json b/package.json index 8ec77a2..ed2aaca 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "@types/jest": "^28.1.6", "@types/node": "^12.20.11", "@types/node-fetch": "^2.6.2", + "@types/semver": "^7.3.13", "@types/w3c-web-serial": "^1.0.2", "@typescript-eslint/eslint-plugin": "^4.22.0", "@typescript-eslint/parser": "^4.22.0", @@ -101,6 +102,7 @@ "rollup-plugin-polyfill-node": "^0.10.1", "rollup-plugin-visualizer": "^5.7.1", "semantic-release": "^19.0.2", + "semver": "^7.3.8", "typescript": "^4.2.4", "wds": "^0.12.0" }, diff --git a/src/PirateMidiDevice.ts b/src/PirateMidiDevice.ts index 2a8c624..9ed204d 100644 --- a/src/PirateMidiDevice.ts +++ b/src/PirateMidiDevice.ts @@ -1,3 +1,4 @@ +import semver from 'semver'; import { BankSettings, Command, DeviceInfo, GlobalSettings } from './types'; import { BaseDevice } from './BaseDevice'; import { deviceDescriptors } from './data/deviceDescriptors'; @@ -7,6 +8,8 @@ import { WebSerialPort } from './serial/WebSerialPort'; import { EventEmitter } from 'events'; import { DevicePortMock } from './mock/DevicePortMock'; +export const MINIMUM_FIRMWARE_VERSION = '1.1.3'; + export class PirateMidiDevice extends EventEmitter { deviceInfo?: DeviceInfo; baseDevice: BaseDevice; @@ -30,6 +33,14 @@ export class PirateMidiDevice extends EventEmitter { return deviceDescriptors[this.deviceInfo.deviceModel]; } + getIsSupported(): boolean { + if (!this.deviceInfo) throw new Error('No device info available'); + return semver.gte( + this.deviceInfo.firmwareVersion, + MINIMUM_FIRMWARE_VERSION + ); + } + validateBankNumber(bank: number): void { const { numberBanks } = this.getDeviceDescription(); if (typeof bank !== 'number') diff --git a/src/index.browser.ts b/src/index.browser.ts index 7687c16..520ea58 100644 --- a/src/index.browser.ts +++ b/src/index.browser.ts @@ -1,4 +1,4 @@ -import { PirateMidiDevice } from './PirateMidiDevice'; +import { MINIMUM_FIRMWARE_VERSION, PirateMidiDevice } from './PirateMidiDevice'; import { WebSerialPort } from './serial/WebSerialPort'; import { GetDevices } from './types'; @@ -25,5 +25,10 @@ export const getDevices: GetDevices = async () => { // Populate deviceInfo immediately to reduce friction await device.updateDeviceInfo(); + if (!device.getIsSupported()) + throw new Error( + `Minimum firmware version ${MINIMUM_FIRMWARE_VERSION} is required` + ); + return [device]; }; diff --git a/src/index.ts b/src/index.ts index eaa14ed..de19812 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { PirateMidiDevice } from './PirateMidiDevice'; +import { MINIMUM_FIRMWARE_VERSION, PirateMidiDevice } from './PirateMidiDevice'; import { NodeSerialPort } from './serial/NodeSerialPort'; import { GetDevices } from './types'; @@ -24,6 +24,11 @@ export const getDevices: GetDevices = async () => { // Populate deviceInfo immediately to reduce friction await device.updateDeviceInfo(); + if (!device.getIsSupported()) + throw new Error( + `Minimum firmware version ${MINIMUM_FIRMWARE_VERSION} is required` + ); + return device; }) );