@zwave-js/config 15.1.1 → 15.1.2
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/build/cjs/ConfigManager.d.ts +1 -1
- package/build/cjs/ConfigManager.js.map +1 -1
- package/build/cjs/JsonTemplate.d.ts +1 -1
- package/build/cjs/JsonTemplate.js +12 -13
- package/build/cjs/JsonTemplate.js.map +3 -3
- package/build/cjs/Logger_safe.d.ts +1 -1
- package/build/cjs/Logger_safe.js.map +1 -1
- package/build/cjs/Manufacturers.d.ts +1 -1
- package/build/cjs/Manufacturers.js.map +1 -1
- package/build/cjs/_version.d.ts +1 -1
- package/build/cjs/_version.js +1 -1
- package/build/cjs/_version.js.map +1 -1
- package/build/cjs/devices/AssociationConfig.d.ts +1 -1
- package/build/cjs/devices/AssociationConfig.js +2 -2
- package/build/cjs/devices/AssociationConfig.js.map +2 -2
- package/build/cjs/devices/CompatConfig.d.ts +2 -2
- package/build/cjs/devices/CompatConfig.js +13 -13
- package/build/cjs/devices/CompatConfig.js.map +3 -3
- package/build/cjs/devices/ConditionalItem.d.ts +1 -1
- package/build/cjs/devices/ConditionalItem.js +5 -5
- package/build/cjs/devices/ConditionalItem.js.map +3 -3
- package/build/cjs/devices/DeviceConfig.d.ts +1 -1
- package/build/cjs/devices/DeviceConfig.js +1 -2
- package/build/cjs/devices/DeviceConfig.js.map +3 -3
- package/build/cjs/devices/DeviceMetadata.d.ts +1 -1
- package/build/cjs/devices/DeviceMetadata.js +2 -2
- package/build/cjs/devices/DeviceMetadata.js.map +2 -2
- package/build/cjs/devices/EndpointConfig.d.ts +1 -1
- package/build/cjs/devices/EndpointConfig.js.map +1 -1
- package/build/cjs/devices/ParamInformation.d.ts +1 -1
- package/build/cjs/devices/ParamInformation.js +4 -4
- package/build/cjs/devices/ParamInformation.js.map +2 -2
- package/build/cjs/traits.d.ts +1 -1
- package/build/cjs/utils.d.ts +1 -1
- package/build/cjs/utils.js.map +1 -1
- package/build/cjs/utils_safe.d.ts +1 -1
- package/build/cjs/utils_safe.js +6 -6
- package/build/cjs/utils_safe.js.map +2 -2
- package/build/esm/ConfigManager.d.ts +1 -1
- package/build/esm/ConfigManager.d.ts.map +1 -1
- package/build/esm/JsonTemplate.d.ts +1 -1
- package/build/esm/JsonTemplate.d.ts.map +1 -1
- package/build/esm/JsonTemplate.js +2 -3
- package/build/esm/JsonTemplate.js.map +1 -1
- package/build/esm/Logger_safe.d.ts +1 -1
- package/build/esm/Logger_safe.d.ts.map +1 -1
- package/build/esm/Manufacturers.d.ts +1 -1
- package/build/esm/Manufacturers.d.ts.map +1 -1
- package/build/esm/_version.d.ts +1 -1
- package/build/esm/_version.js +1 -1
- package/build/esm/devices/AssociationConfig.d.ts +1 -1
- package/build/esm/devices/AssociationConfig.d.ts.map +1 -1
- package/build/esm/devices/AssociationConfig.js +1 -1
- package/build/esm/devices/AssociationConfig.js.map +1 -1
- package/build/esm/devices/CompatConfig.d.ts +2 -2
- package/build/esm/devices/CompatConfig.d.ts.map +1 -1
- package/build/esm/devices/CompatConfig.js +2 -2
- package/build/esm/devices/CompatConfig.js.map +1 -1
- package/build/esm/devices/ConditionalItem.d.ts +1 -1
- package/build/esm/devices/ConditionalItem.d.ts.map +1 -1
- package/build/esm/devices/ConditionalItem.js +2 -2
- package/build/esm/devices/ConditionalItem.js.map +1 -1
- package/build/esm/devices/DeviceConfig.d.ts +1 -1
- package/build/esm/devices/DeviceConfig.d.ts.map +1 -1
- package/build/esm/devices/DeviceConfig.js +1 -2
- package/build/esm/devices/DeviceConfig.js.map +1 -1
- package/build/esm/devices/DeviceMetadata.d.ts +1 -1
- package/build/esm/devices/DeviceMetadata.d.ts.map +1 -1
- package/build/esm/devices/DeviceMetadata.js +1 -1
- package/build/esm/devices/DeviceMetadata.js.map +1 -1
- package/build/esm/devices/EndpointConfig.d.ts +1 -1
- package/build/esm/devices/EndpointConfig.d.ts.map +1 -1
- package/build/esm/devices/ParamInformation.d.ts +1 -1
- package/build/esm/devices/ParamInformation.d.ts.map +1 -1
- package/build/esm/devices/ParamInformation.js +1 -1
- package/build/esm/devices/ParamInformation.js.map +1 -1
- package/build/esm/traits.d.ts +1 -1
- package/build/esm/traits.d.ts.map +1 -1
- package/build/esm/utils.d.ts +1 -1
- package/build/esm/utils.d.ts.map +1 -1
- package/build/esm/utils_safe.d.ts +1 -1
- package/build/esm/utils_safe.d.ts.map +1 -1
- package/build/esm/utils_safe.js +1 -1
- package/build/esm/utils_safe.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/devices/CompatConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\ttype CommandClassInfo,\n\ttype CommandClasses,\n\ttype ValueID,\n\tgetCCName,\n\tstripUndefined,\n} from \"@zwave-js/core/safe\";\nimport { type JSONObject, pick } from \"@zwave-js/shared/safe\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport { throwInvalidConfig, tryParseCCId } from \"../utils_safe.js\";\nimport { type ConditionalItem, conditionApplies } from \"./ConditionalItem.js\";\nimport type { DeviceID } from \"./shared.js\";\n\nexport class ConditionalCompatConfig implements ConditionalItem<CompatConfig> {\n\tprivate valueIdRegex = /^\\$value\\$\\[.+\\]$/;\n\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tthis.condition = definition.$if;\n\n\t\tif (definition.queryOnWakeup != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.queryOnWakeup)\n\t\t\t\t|| !definition.queryOnWakeup.every(\n\t\t\t\t\t(cmd: unknown) =>\n\t\t\t\t\t\tisArray(cmd)\n\t\t\t\t\t\t&& cmd.length >= 2\n\t\t\t\t\t\t&& typeof cmd[0] === \"string\"\n\t\t\t\t\t\t&& typeof cmd[1] === \"string\"\n\t\t\t\t\t\t&& cmd\n\t\t\t\t\t\t\t.slice(2)\n\t\t\t\t\t\t\t.every(\n\t\t\t\t\t\t\t\t(arg) =>\n\t\t\t\t\t\t\t\t\ttypeof arg === \"string\"\n\t\t\t\t\t\t\t\t\t|| typeof arg === \"number\"\n\t\t\t\t\t\t\t\t\t|| typeof arg === \"boolean\",\n\t\t\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option queryOnWakeup`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Parse \"smart\" values into partial Value IDs\n\t\t\tthis.queryOnWakeup = (definition.queryOnWakeup as any[][]).map(\n\t\t\t\t(cmd) =>\n\t\t\t\t\tcmd.map((arg) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof arg === \"string\"\n\t\t\t\t\t\t\t&& this.valueIdRegex.test(arg)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst tuple = JSON.parse(\n\t\t\t\t\t\t\t\targ.slice(\"$value$\".length),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tproperty: tuple[0],\n\t\t\t\t\t\t\t\tpropertyKey: tuple[1],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn arg;\n\t\t\t\t\t}),\n\t\t\t) as any;\n\t\t}\n\n\t\tif (definition.disableAutoRefresh != undefined) {\n\t\t\tif (definition.disableAutoRefresh !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableAutoRefresh must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableAutoRefresh = definition.disableAutoRefresh;\n\t\t}\n\n\t\tif (definition.disableCallbackFunctionTypeCheck != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.disableCallbackFunctionTypeCheck)\n\t\t\t\t|| !definition.disableCallbackFunctionTypeCheck.every(\n\t\t\t\t\t(d: any) => typeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nwhen present, compat option disableCallbackFunctionTypeCheck msut be an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.disableCallbackFunctionTypeCheck =\n\t\t\t\tdefinition.disableCallbackFunctionTypeCheck;\n\t\t}\n\n\t\tif (definition.disableStrictEntryControlDataValidation != undefined) {\n\t\t\tif (definition.disableStrictEntryControlDataValidation !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableStrictEntryControlDataValidation must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableStrictEntryControlDataValidation =\n\t\t\t\tdefinition.disableStrictEntryControlDataValidation;\n\t\t}\n\n\t\tif (definition.disableStrictMeasurementValidation != undefined) {\n\t\t\tif (definition.disableStrictMeasurementValidation !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableStrictMeasurementValidation must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableStrictMeasurementValidation =\n\t\t\t\tdefinition.disableStrictMeasurementValidation;\n\t\t}\n\n\t\tif (definition.encodeCCsUsingTargetVersion != undefined) {\n\t\t\tif (definition.encodeCCsUsingTargetVersion !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option encodeCCsUsingTargetVersion must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.encodeCCsUsingTargetVersion =\n\t\t\t\tdefinition.encodeCCsUsingTargetVersion;\n\t\t}\n\n\t\tif (definition.forceNotificationIdleReset != undefined) {\n\t\t\tif (definition.forceNotificationIdleReset !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceNotificationIdleReset must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.forceNotificationIdleReset =\n\t\t\t\tdefinition.forceNotificationIdleReset;\n\t\t}\n\n\t\tif (definition.forceSceneControllerGroupCount != undefined) {\n\t\t\tif (typeof definition.forceSceneControllerGroupCount !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceSceneControllerGroupCount must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.forceSceneControllerGroupCount < 0\n\t\t\t\t|| definition.forceSceneControllerGroupCount > 255\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceSceneControllerGroupCount must be between 0 and 255!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.forceSceneControllerGroupCount =\n\t\t\t\tdefinition.forceSceneControllerGroupCount;\n\t\t}\n\n\t\tif (definition.mapBasicReport != undefined) {\n\t\t\tif (!isBasicReportMapping(definition.mapBasicReport)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapBasicReport contains an invalid value`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapBasicReport = definition.mapBasicReport;\n\t\t}\n\n\t\tif (definition.mapBasicSet != undefined) {\n\t\t\tif (!isBasicSetMapping(definition.mapBasicSet)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapBasicSet contains an invalid value`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapBasicSet = definition.mapBasicSet;\n\t\t}\n\n\t\tif (definition.preserveRootApplicationCCValueIDs != undefined) {\n\t\t\tif (definition.preserveRootApplicationCCValueIDs !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option preserveRootApplicationCCValueIDs`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.preserveRootApplicationCCValueIDs =\n\t\t\t\tdefinition.preserveRootApplicationCCValueIDs;\n\t\t}\n\n\t\tif (definition.preserveEndpoints != undefined) {\n\t\t\tif (\n\t\t\t\tdefinition.preserveEndpoints !== \"*\"\n\t\t\t\t&& !(\n\t\t\t\t\tisArray(definition.preserveEndpoints)\n\t\t\t\t\t&& definition.preserveEndpoints.every(\n\t\t\t\t\t\t(d: any) =>\n\t\t\t\t\t\t\ttypeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option preserveEndpoints must be \"*\" or an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.preserveEndpoints = definition.preserveEndpoints;\n\t\t}\n\n\t\tif (definition.removeEndpoints != undefined) {\n\t\t\tif (\n\t\t\t\tdefinition.removeEndpoints !== \"*\"\n\t\t\t\t&& !(\n\t\t\t\t\tisArray(definition.removeEndpoints)\n\t\t\t\t\t&& definition.removeEndpoints.every(\n\t\t\t\t\t\t(d: any) =>\n\t\t\t\t\t\t\ttypeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option removeEndpoints must be \"*\" or an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.removeEndpoints = definition.removeEndpoints;\n\t\t}\n\n\t\tif (definition.skipConfigurationNameQuery != undefined) {\n\t\t\tif (definition.skipConfigurationNameQuery !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option skipConfigurationNameQuery`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.skipConfigurationNameQuery =\n\t\t\t\tdefinition.skipConfigurationNameQuery;\n\t\t}\n\n\t\tif (definition.skipConfigurationInfoQuery != undefined) {\n\t\t\tif (definition.skipConfigurationInfoQuery !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option skipConfigurationInfoQuery`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.skipConfigurationInfoQuery =\n\t\t\t\tdefinition.skipConfigurationInfoQuery;\n\t\t}\n\n\t\tif (definition.treatMultilevelSwitchSetAsEvent != undefined) {\n\t\t\tif (definition.treatMultilevelSwitchSetAsEvent !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option treatMultilevelSwitchSetAsEvent`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatMultilevelSwitchSetAsEvent =\n\t\t\t\tdefinition.treatMultilevelSwitchSetAsEvent;\n\t\t}\n\n\t\tif (definition.treatSetAsReport != undefined) {\n\t\t\tif (\n\t\t\t\t!(isArray(definition.treatSetAsReport)\n\t\t\t\t\t&& definition.treatSetAsReport.every(\n\t\t\t\t\t\t(d: any) => typeof d === \"string\",\n\t\t\t\t\t))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option treatSetAsReport must be an array of strings`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatSetAsReport = new Set(definition.treatSetAsReport);\n\t\t}\n\n\t\tif (definition.treatDestinationEndpointAsSource != undefined) {\n\t\t\tif (definition.treatDestinationEndpointAsSource !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option treatDestinationEndpointAsSource`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatDestinationEndpointAsSource =\n\t\t\t\tdefinition.treatDestinationEndpointAsSource;\n\t\t}\n\n\t\tif (definition.useUTCInTimeParametersCC != undefined) {\n\t\t\tif (definition.useUTCInTimeParametersCC !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option useUTCInTimeParametersCC must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.useUTCInTimeParametersCC = definition.useUTCInTimeParametersCC;\n\t\t}\n\n\t\tif (definition.manualValueRefreshDelayMs != undefined) {\n\t\t\tif (typeof definition.manualValueRefreshDelayMs !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option manualValueRefreshDelayMs must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.manualValueRefreshDelayMs % 1 !== 0\n\t\t\t\t|| definition.manualValueRefreshDelayMs < 0\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option manualValueRefreshDelayMs must be a non-negative integer!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.manualValueRefreshDelayMs =\n\t\t\t\tdefinition.manualValueRefreshDelayMs;\n\t\t}\n\n\t\tif (definition.reportTimeout != undefined) {\n\t\t\tif (typeof definition.reportTimeout !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option reportTimeout must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.reportTimeout % 1 !== 0\n\t\t\t\t|| definition.reportTimeout < 1000\n\t\t\t\t|| definition.reportTimeout > 10000\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option reportTimeout must be an integer between 1000 and 10000!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.reportTimeout = definition.reportTimeout;\n\t\t}\n\n\t\tif (definition.mapRootReportsToEndpoint != undefined) {\n\t\t\tif (typeof definition.mapRootReportsToEndpoint !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapRootReportsToEndpoint must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.mapRootReportsToEndpoint % 1 !== 0\n\t\t\t\t|| definition.mapRootReportsToEndpoint < 1\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapRootReportsToEndpoint must be a positive integer!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapRootReportsToEndpoint = definition.mapRootReportsToEndpoint;\n\t\t}\n\n\t\tif (definition.overrideFloatEncoding != undefined) {\n\t\t\tif (!isObject(definition.overrideFloatEncoding)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option overrideFloatEncoding`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.overrideFloatEncoding = {};\n\t\t\tif (\"precision\" in definition.overrideFloatEncoding) {\n\t\t\t\tif (\n\t\t\t\t\ttypeof definition.overrideFloatEncoding.precision\n\t\t\t\t\t\t!= \"number\"\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.precision must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdefinition.overrideFloatEncoding.precision % 1 !== 0\n\t\t\t\t\t|| definition.overrideFloatEncoding.precision < 0\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.precision must be a positive integer!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.overrideFloatEncoding.precision =\n\t\t\t\t\tdefinition.overrideFloatEncoding.precision;\n\t\t\t}\n\t\t\tif (\"size\" in definition.overrideFloatEncoding) {\n\t\t\t\tif (typeof definition.overrideFloatEncoding.size != \"number\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.size must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdefinition.overrideFloatEncoding.size % 1 !== 0\n\t\t\t\t\t|| definition.overrideFloatEncoding.size < 1\n\t\t\t\t\t|| definition.overrideFloatEncoding.size > 4\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.size must be an integer between 1 and 4!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.overrideFloatEncoding.size =\n\t\t\t\t\tdefinition.overrideFloatEncoding.size;\n\t\t\t}\n\n\t\t\tif (Object.keys(this.overrideFloatEncoding).length === 0) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option overrideFloatEncoding: size and/or precision must be specified!`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.commandClasses != undefined) {\n\t\t\tif (!isObject(definition.commandClasses)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (definition.commandClasses.add != undefined) {\n\t\t\t\tif (!isObject(definition.commandClasses.add)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses.add`,\n\t\t\t\t\t);\n\t\t\t\t} else if (\n\t\t\t\t\t!Object.values(definition.commandClasses.add).every((v) =>\n\t\t\t\t\t\tisObject(v)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nAll values in compat option commandClasses.add must be objects`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst addCCs = new Map<CommandClasses, CompatAddCC>();\n\t\t\t\tfor (\n\t\t\t\t\tconst [key, info] of Object.entries(\n\t\t\t\t\t\tdefinition.commandClasses.add,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// Parse the key into a CC ID\n\t\t\t\t\tconst cc = tryParseCCId(key);\n\t\t\t\t\tif (cc == undefined) {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option commandClasses.add!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\taddCCs.set(cc, new CompatAddCC(filename, info as any));\n\t\t\t\t}\n\t\t\t\tthis.addCCs = addCCs;\n\t\t\t}\n\n\t\t\tif (definition.commandClasses.remove != undefined) {\n\t\t\t\tif (!isObject(definition.commandClasses.remove)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses.remove`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst removeCCs = new Map<\n\t\t\t\t\tCommandClasses,\n\t\t\t\t\t\"*\" | readonly number[]\n\t\t\t\t>();\n\t\t\t\tfor (\n\t\t\t\t\tconst [key, info] of Object.entries(\n\t\t\t\t\t\tdefinition.commandClasses.remove,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// Parse the key into a CC ID\n\t\t\t\t\tconst cc = tryParseCCId(key);\n\t\t\t\t\tif (cc == undefined) {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option commandClasses.remove!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (isObject(info) && \"endpoints\" in info) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tinfo.endpoints === \"*\"\n\t\t\t\t\t\t\t|| (isArray(info.endpoints)\n\t\t\t\t\t\t\t\t&& info.endpoints.every(\n\t\t\t\t\t\t\t\t\t(i) => typeof i === \"number\",\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tremoveCCs.set(cc, info.endpoints as any);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t\t`config/devices/${filename}:\nCompat option commandClasses.remove has an invalid \"endpoints\" property. Only \"*\" and numeric arrays are allowed!`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nAll values in compat option commandClasses.remove must be objects with an \"endpoints\" property!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.removeCCs = removeCCs;\n\t\t\t}\n\t\t}\n\n\t\tif (definition.alarmMapping != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.alarmMapping)\n\t\t\t\t|| !definition.alarmMapping.every((m: any) => isObject(m))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option alarmMapping must be an array where all items are objects!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.alarmMapping = (definition.alarmMapping as any[]).map(\n\t\t\t\t(m, i) => new CompatMapAlarm(filename, m, i + 1),\n\t\t\t);\n\t\t}\n\n\t\tif (definition.overrideQueries != undefined) {\n\t\t\tif (!isObject(definition.overrideQueries)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideQueries must be an object!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.overrideQueries = new CompatOverrideQueries(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.overrideQueries,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly alarmMapping?: readonly CompatMapAlarm[];\n\tpublic readonly addCCs?: ReadonlyMap<CommandClasses, CompatAddCC>;\n\tpublic readonly removeCCs?: ReadonlyMap<\n\t\tCommandClasses,\n\t\t\"*\" | readonly number[]\n\t>;\n\tpublic readonly disableAutoRefresh?: boolean;\n\tpublic readonly disableStrictEntryControlDataValidation?: boolean;\n\tpublic readonly disableStrictMeasurementValidation?: boolean;\n\tpublic readonly disableCallbackFunctionTypeCheck?: number[];\n\tpublic readonly encodeCCsUsingTargetVersion?: boolean;\n\tpublic readonly forceNotificationIdleReset?: boolean;\n\tpublic readonly forceSceneControllerGroupCount?: number;\n\tpublic readonly manualValueRefreshDelayMs?: number;\n\tpublic readonly mapRootReportsToEndpoint?: number;\n\tpublic readonly mapBasicReport?: BasicReportMapping;\n\tpublic readonly mapBasicSet?: BasicSetMapping;\n\tpublic readonly overrideFloatEncoding?: {\n\t\tsize?: number;\n\t\tprecision?: number;\n\t};\n\tpublic readonly overrideQueries?: CompatOverrideQueries;\n\tpublic readonly preserveRootApplicationCCValueIDs?: boolean;\n\tpublic readonly preserveEndpoints?: \"*\" | readonly number[];\n\tpublic readonly removeEndpoints?: \"*\" | readonly number[];\n\tpublic readonly reportTimeout?: number;\n\tpublic readonly skipConfigurationNameQuery?: boolean;\n\tpublic readonly skipConfigurationInfoQuery?: boolean;\n\tpublic readonly treatMultilevelSwitchSetAsEvent?: boolean;\n\tpublic readonly treatSetAsReport?: ReadonlySet<string>;\n\tpublic readonly treatDestinationEndpointAsSource?: boolean;\n\tpublic readonly useUTCInTimeParametersCC?: boolean;\n\tpublic readonly queryOnWakeup?: readonly [\n\t\tstring,\n\t\tstring,\n\t\t...(\n\t\t\t| string\n\t\t\t| number\n\t\t\t| boolean\n\t\t\t| Pick<ValueID, \"property\" | \"propertyKey\">\n\t\t)[],\n\t][];\n\n\tpublic readonly condition?: string | undefined;\n\n\tpublic evaluateCondition(deviceId?: DeviceID): CompatConfig | undefined {\n\t\tif (!conditionApplies(this, deviceId)) return;\n\t\tconst ret = pick(this, [\n\t\t\t\"alarmMapping\",\n\t\t\t\"addCCs\",\n\t\t\t\"removeCCs\",\n\t\t\t\"disableAutoRefresh\",\n\t\t\t\"disableCallbackFunctionTypeCheck\",\n\t\t\t\"disableStrictEntryControlDataValidation\",\n\t\t\t\"disableStrictMeasurementValidation\",\n\t\t\t\"encodeCCsUsingTargetVersion\",\n\t\t\t\"forceNotificationIdleReset\",\n\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\"manualValueRefreshDelayMs\",\n\t\t\t\"mapBasicReport\",\n\t\t\t\"mapBasicSet\",\n\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\"overrideFloatEncoding\",\n\t\t\t\"overrideQueries\",\n\t\t\t\"reportTimeout\",\n\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\"preserveEndpoints\",\n\t\t\t\"removeEndpoints\",\n\t\t\t\"skipConfigurationNameQuery\",\n\t\t\t\"skipConfigurationInfoQuery\",\n\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\"treatSetAsReport\",\n\t\t\t\"treatDestinationEndpointAsSource\",\n\t\t\t\"useUTCInTimeParametersCC\",\n\t\t\t\"queryOnWakeup\",\n\t\t]);\n\t\treturn stripUndefined(ret) as CompatConfig;\n\t}\n}\n\nexport type CompatConfig = Omit<\n\tConditionalCompatConfig,\n\t\"condition\" | \"evaluateCondition\"\n>;\n\nexport class CompatAddCC {\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tconst endpoints = new Map<number, Partial<CommandClassInfo>>();\n\t\tconst parseEndpointInfo = (endpoint: number, info: JSONObject) => {\n\t\t\tconst parsed: Partial<CommandClassInfo> = {};\n\t\t\tif (info.isSupported != undefined) {\n\t\t\t\tif (typeof info.isSupported !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty isSupported in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.isSupported = info.isSupported;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.isControlled != undefined) {\n\t\t\t\tif (typeof info.isControlled !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty isControlled in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.isControlled = info.isControlled;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.secure != undefined) {\n\t\t\t\tif (typeof info.secure !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty secure in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.secure = info.secure;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.version != undefined) {\n\t\t\t\tif (typeof info.version !== \"number\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty version in compat option commandClasses.add, endpoint ${endpoint} must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.version = info.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tendpoints.set(endpoint, parsed);\n\t\t};\n\t\t// Parse root endpoint info if given\n\t\tif (\n\t\t\tdefinition.isSupported != undefined\n\t\t\t|| definition.isControlled != undefined\n\t\t\t|| definition.version != undefined\n\t\t\t|| definition.secure != undefined\n\t\t) {\n\t\t\t// We have info for the root endpoint\n\t\t\tparseEndpointInfo(0, definition);\n\t\t}\n\t\t// Parse all other endpoints\n\t\tif (isObject(definition.endpoints)) {\n\t\t\tif (\n\t\t\t\t!Object.keys(definition.endpoints).every((k) => /^\\d+$/.test(k))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ninvalid endpoint index in compat option commandClasses.add`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tfor (const [ep, info] of Object.entries(definition.endpoints)) {\n\t\t\t\t\tparseEndpointInfo(parseInt(ep), info as any);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.endpoints = endpoints;\n\t}\n\n\tpublic readonly endpoints: ReadonlyMap<number, Partial<CommandClassInfo>>;\n}\n\nexport interface CompatMapAlarmFrom {\n\talarmType: number;\n\talarmLevel?: number;\n}\n\nexport interface CompatMapAlarmTo {\n\tnotificationType: number;\n\tnotificationEvent: number;\n\teventParameters?: Record<string, number | \"alarmLevel\">;\n}\n\nexport class CompatMapAlarm {\n\tpublic constructor(\n\t\tfilename: string,\n\t\tdefinition: JSONObject,\n\t\tindex: number,\n\t) {\n\t\tif (!isObject(definition.from)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"devices\",\n\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"from\" must be an object!`,\n\t\t\t);\n\t\t} else {\n\t\t\tif (typeof definition.from.alarmType !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"from.alarmType\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdefinition.from.alarmLevel != undefined\n\t\t\t\t&& typeof definition.from.alarmLevel !== \"number\"\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: if property \"from.alarmLevel\" is given, it must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (!isObject(definition.to)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"devices\",\n\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to\" must be an object!`,\n\t\t\t);\n\t\t} else {\n\t\t\tif (typeof definition.to.notificationType !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.notificationType\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof definition.to.notificationEvent !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.notificationEvent\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (definition.to.eventParameters != undefined) {\n\t\t\t\tif (!isObject(definition.to.eventParameters)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.eventParameters\" must be an object!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tfor (\n\t\t\t\t\t\tconst [key, val] of Object.entries(\n\t\t\t\t\t\t\tdefinition.to.eventParameters,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (typeof val !== \"number\" && val !== \"alarmLevel\") {\n\t\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.eventParameters.${key}\" must be a number or the literal \"alarmLevel\"!`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.from = pick(definition.from, [\"alarmType\", \"alarmLevel\"]);\n\t\tthis.to = pick(definition.to, [\n\t\t\t\"notificationType\",\n\t\t\t\"notificationEvent\",\n\t\t\t\"eventParameters\",\n\t\t]);\n\t}\n\n\tpublic readonly from: CompatMapAlarmFrom;\n\tpublic readonly to: CompatMapAlarmTo;\n}\n\nexport class CompatOverrideQueries {\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tconst overrides = new Map();\n\n\t\tconst parseOverride = (\n\t\t\tcc: CommandClasses,\n\t\t\tinfo: JSONObject,\n\t\t): CompatOverrideQuery => {\n\t\t\tif (typeof info.method !== \"string\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"method\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be a string!`,\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tinfo.matchArgs != undefined\n\t\t\t\t&& !isArray(info.matchArgs)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"matchArgs\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an array!`,\n\t\t\t\t);\n\t\t\t} else if (!(\"result\" in info)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"result\" is missing in in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t}!`,\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tinfo.endpoint != undefined\n\t\t\t\t&& typeof info.endpoint !== \"number\"\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"endpoint\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be a number!`,\n\t\t\t\t);\n\t\t\t} else if (info.persistValues && !isObject(info.persistValues)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"persistValues\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an object!`,\n\t\t\t\t);\n\t\t\t} else if (info.extendMetadata && !isObject(info.extendMetadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"extendMetadata\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an object!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tendpoint: info.endpoint,\n\t\t\t\tmethod: info.method,\n\t\t\t\tmatchArgs: info.matchArgs,\n\t\t\t\tresult: info.result,\n\t\t\t\tpersistValues: info.persistValues,\n\t\t\t\textendMetadata: info.extendMetadata,\n\t\t\t};\n\t\t};\n\n\t\tfor (const [key, value] of Object.entries(definition)) {\n\t\t\t// Parse the key into a CC ID\n\t\t\tconst cc = tryParseCCId(key);\n\t\t\tif (cc == undefined) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option overrideQueries!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet overrideDefinitions: any;\n\t\t\tif (isObject(value)) {\n\t\t\t\toverrideDefinitions = [value];\n\t\t\t} else if (!isArray(value)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"${key}\" in compat option overrideQueries must be a single override object or an array thereof!`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\toverrideDefinitions = value;\n\t\t\t}\n\n\t\t\toverrides.set(\n\t\t\t\tcc,\n\t\t\t\toverrideDefinitions.map((info: any) => parseOverride(cc, info)),\n\t\t\t);\n\t\t}\n\n\t\tthis.overrides = overrides;\n\t}\n\n\t// CC -> endpoint -> queries\n\tprivate readonly overrides: ReadonlyMap<\n\t\tCommandClasses,\n\t\tCompatOverrideQuery[]\n\t>;\n\n\tpublic hasOverride(ccId: CommandClasses): boolean {\n\t\treturn this.overrides.has(ccId);\n\t}\n\n\tpublic matchOverride(\n\t\tcc: CommandClasses,\n\t\tendpointIndex: number,\n\t\tmethod: string,\n\t\targs: any[],\n\t):\n\t\t| Pick<\n\t\t\tCompatOverrideQuery,\n\t\t\t\"result\" | \"persistValues\" | \"extendMetadata\"\n\t\t>\n\t\t| undefined\n\t{\n\t\tconst queries = this.overrides.get(cc);\n\t\tif (!queries) return undefined;\n\t\tfor (const query of queries) {\n\t\t\tif ((query.endpoint ?? 0) !== endpointIndex) continue;\n\t\t\tif (query.method !== method) continue;\n\t\t\tif (query.matchArgs) {\n\t\t\t\tif (query.matchArgs.length !== args.length) continue;\n\t\t\t\tif (!query.matchArgs.every((arg, i) => arg === args[i])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn pick(query, [\"result\", \"persistValues\", \"extendMetadata\"]);\n\t\t}\n\t}\n}\n\nexport interface CompatOverrideQuery {\n\t/** Which endpoint this override is for */\n\tendpoint?: number;\n\t/** For which API method this override is defined */\n\tmethod: string;\n\t/**\n\t * An array of method arguments that needs to match for this override to apply.\n\t * If `undefined`, no matching is performed.\n\t */\n\tmatchArgs?: any[];\n\t/** The result to return from the API call */\n\tresult: any;\n\t/**\n\t * An optional dictionary of values that will be persisted in the cache.\n\t * The keys are properties of the `...CCValues` objects that belong to this CC.\n\t */\n\tpersistValues?: Record<string, any>;\n\t/**\n\t * An optional dictionary of value metadata that will be persisted in the cache.\n\t * The keys are properties of the `...CCValues` objects that belong to this CC.\n\t * The given metadata will be merged with statically defined value metadata.\n\t */\n\textendMetadata?: Record<string, any>;\n}\n\nconst basicReportMappings = [\n\tfalse,\n\t\"auto\",\n\t\"Binary Sensor\",\n] as const;\n\n/**\n * Defines how to handle a received Basic CC Report:\n * - \"auto\": map it to a different CC based on the device type, with fallback to `false`\n * - false: treat the report verbatim without mapping\n * - \"Binary Sensor\": treat it as a Binary Sensor CC Report, regardless of device type\n */\nexport type BasicReportMapping = typeof basicReportMappings[number];\n\nfunction isBasicReportMapping(v: unknown): v is BasicReportMapping {\n\treturn basicReportMappings.includes(v as any);\n}\n\nconst basicSetMappings = [\n\t\"event\",\n\t\"report\",\n\t\"auto\",\n\t\"Binary Sensor\",\n] as const;\n\n/**\n * Defines how to handle a received Basic CC Set:\n * - \"event\": emit an event for the special `event` CC value\n * - \"report\": treat it as as a Basic CC Report (default)\n * - \"auto\": map it to a different CC based on the device type, with fallback to Basic CC report\n * - \"Binary Sensor\": treat it as a Binary Sensor CC Report, regardless of device type\n */\nexport type BasicSetMapping = typeof basicSetMappings[number];\n\nfunction isBasicSetMapping(v: unknown): v is BasicSetMapping {\n\treturn basicSetMappings.includes(v as any);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": [
|
|
4
|
+
"sourcesContent": ["import {\n\ttype CommandClassInfo,\n\ttype CommandClasses,\n\ttype ValueID,\n\tgetCCName,\n\tstripUndefined,\n} from \"@zwave-js/core\";\nimport { type JSONObject, pick } from \"@zwave-js/shared\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport { throwInvalidConfig, tryParseCCId } from \"../utils_safe.js\";\nimport { type ConditionalItem, conditionApplies } from \"./ConditionalItem.js\";\nimport type { DeviceID } from \"./shared.js\";\n\nexport class ConditionalCompatConfig implements ConditionalItem<CompatConfig> {\n\tprivate valueIdRegex = /^\\$value\\$\\[.+\\]$/;\n\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tthis.condition = definition.$if;\n\n\t\tif (definition.queryOnWakeup != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.queryOnWakeup)\n\t\t\t\t|| !definition.queryOnWakeup.every(\n\t\t\t\t\t(cmd: unknown) =>\n\t\t\t\t\t\tisArray(cmd)\n\t\t\t\t\t\t&& cmd.length >= 2\n\t\t\t\t\t\t&& typeof cmd[0] === \"string\"\n\t\t\t\t\t\t&& typeof cmd[1] === \"string\"\n\t\t\t\t\t\t&& cmd\n\t\t\t\t\t\t\t.slice(2)\n\t\t\t\t\t\t\t.every(\n\t\t\t\t\t\t\t\t(arg) =>\n\t\t\t\t\t\t\t\t\ttypeof arg === \"string\"\n\t\t\t\t\t\t\t\t\t|| typeof arg === \"number\"\n\t\t\t\t\t\t\t\t\t|| typeof arg === \"boolean\",\n\t\t\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option queryOnWakeup`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Parse \"smart\" values into partial Value IDs\n\t\t\tthis.queryOnWakeup = (definition.queryOnWakeup as any[][]).map(\n\t\t\t\t(cmd) =>\n\t\t\t\t\tcmd.map((arg) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof arg === \"string\"\n\t\t\t\t\t\t\t&& this.valueIdRegex.test(arg)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst tuple = JSON.parse(\n\t\t\t\t\t\t\t\targ.slice(\"$value$\".length),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tproperty: tuple[0],\n\t\t\t\t\t\t\t\tpropertyKey: tuple[1],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn arg;\n\t\t\t\t\t}),\n\t\t\t) as any;\n\t\t}\n\n\t\tif (definition.disableAutoRefresh != undefined) {\n\t\t\tif (definition.disableAutoRefresh !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableAutoRefresh must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableAutoRefresh = definition.disableAutoRefresh;\n\t\t}\n\n\t\tif (definition.disableCallbackFunctionTypeCheck != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.disableCallbackFunctionTypeCheck)\n\t\t\t\t|| !definition.disableCallbackFunctionTypeCheck.every(\n\t\t\t\t\t(d: any) => typeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nwhen present, compat option disableCallbackFunctionTypeCheck msut be an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.disableCallbackFunctionTypeCheck =\n\t\t\t\tdefinition.disableCallbackFunctionTypeCheck;\n\t\t}\n\n\t\tif (definition.disableStrictEntryControlDataValidation != undefined) {\n\t\t\tif (definition.disableStrictEntryControlDataValidation !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableStrictEntryControlDataValidation must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableStrictEntryControlDataValidation =\n\t\t\t\tdefinition.disableStrictEntryControlDataValidation;\n\t\t}\n\n\t\tif (definition.disableStrictMeasurementValidation != undefined) {\n\t\t\tif (definition.disableStrictMeasurementValidation !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option disableStrictMeasurementValidation must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.disableStrictMeasurementValidation =\n\t\t\t\tdefinition.disableStrictMeasurementValidation;\n\t\t}\n\n\t\tif (definition.encodeCCsUsingTargetVersion != undefined) {\n\t\t\tif (definition.encodeCCsUsingTargetVersion !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option encodeCCsUsingTargetVersion must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.encodeCCsUsingTargetVersion =\n\t\t\t\tdefinition.encodeCCsUsingTargetVersion;\n\t\t}\n\n\t\tif (definition.forceNotificationIdleReset != undefined) {\n\t\t\tif (definition.forceNotificationIdleReset !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceNotificationIdleReset must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.forceNotificationIdleReset =\n\t\t\t\tdefinition.forceNotificationIdleReset;\n\t\t}\n\n\t\tif (definition.forceSceneControllerGroupCount != undefined) {\n\t\t\tif (typeof definition.forceSceneControllerGroupCount !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceSceneControllerGroupCount must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.forceSceneControllerGroupCount < 0\n\t\t\t\t|| definition.forceSceneControllerGroupCount > 255\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option forceSceneControllerGroupCount must be between 0 and 255!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.forceSceneControllerGroupCount =\n\t\t\t\tdefinition.forceSceneControllerGroupCount;\n\t\t}\n\n\t\tif (definition.mapBasicReport != undefined) {\n\t\t\tif (!isBasicReportMapping(definition.mapBasicReport)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapBasicReport contains an invalid value`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapBasicReport = definition.mapBasicReport;\n\t\t}\n\n\t\tif (definition.mapBasicSet != undefined) {\n\t\t\tif (!isBasicSetMapping(definition.mapBasicSet)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapBasicSet contains an invalid value`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapBasicSet = definition.mapBasicSet;\n\t\t}\n\n\t\tif (definition.preserveRootApplicationCCValueIDs != undefined) {\n\t\t\tif (definition.preserveRootApplicationCCValueIDs !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option preserveRootApplicationCCValueIDs`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.preserveRootApplicationCCValueIDs =\n\t\t\t\tdefinition.preserveRootApplicationCCValueIDs;\n\t\t}\n\n\t\tif (definition.preserveEndpoints != undefined) {\n\t\t\tif (\n\t\t\t\tdefinition.preserveEndpoints !== \"*\"\n\t\t\t\t&& !(\n\t\t\t\t\tisArray(definition.preserveEndpoints)\n\t\t\t\t\t&& definition.preserveEndpoints.every(\n\t\t\t\t\t\t(d: any) =>\n\t\t\t\t\t\t\ttypeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option preserveEndpoints must be \"*\" or an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.preserveEndpoints = definition.preserveEndpoints;\n\t\t}\n\n\t\tif (definition.removeEndpoints != undefined) {\n\t\t\tif (\n\t\t\t\tdefinition.removeEndpoints !== \"*\"\n\t\t\t\t&& !(\n\t\t\t\t\tisArray(definition.removeEndpoints)\n\t\t\t\t\t&& definition.removeEndpoints.every(\n\t\t\t\t\t\t(d: any) =>\n\t\t\t\t\t\t\ttypeof d === \"number\" && d % 1 === 0 && d > 0,\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option removeEndpoints must be \"*\" or an array of positive integers`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.removeEndpoints = definition.removeEndpoints;\n\t\t}\n\n\t\tif (definition.skipConfigurationNameQuery != undefined) {\n\t\t\tif (definition.skipConfigurationNameQuery !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option skipConfigurationNameQuery`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.skipConfigurationNameQuery =\n\t\t\t\tdefinition.skipConfigurationNameQuery;\n\t\t}\n\n\t\tif (definition.skipConfigurationInfoQuery != undefined) {\n\t\t\tif (definition.skipConfigurationInfoQuery !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option skipConfigurationInfoQuery`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.skipConfigurationInfoQuery =\n\t\t\t\tdefinition.skipConfigurationInfoQuery;\n\t\t}\n\n\t\tif (definition.treatMultilevelSwitchSetAsEvent != undefined) {\n\t\t\tif (definition.treatMultilevelSwitchSetAsEvent !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option treatMultilevelSwitchSetAsEvent`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatMultilevelSwitchSetAsEvent =\n\t\t\t\tdefinition.treatMultilevelSwitchSetAsEvent;\n\t\t}\n\n\t\tif (definition.treatSetAsReport != undefined) {\n\t\t\tif (\n\t\t\t\t!(isArray(definition.treatSetAsReport)\n\t\t\t\t\t&& definition.treatSetAsReport.every(\n\t\t\t\t\t\t(d: any) => typeof d === \"string\",\n\t\t\t\t\t))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option treatSetAsReport must be an array of strings`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatSetAsReport = new Set(definition.treatSetAsReport);\n\t\t}\n\n\t\tif (definition.treatDestinationEndpointAsSource != undefined) {\n\t\t\tif (definition.treatDestinationEndpointAsSource !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option treatDestinationEndpointAsSource`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.treatDestinationEndpointAsSource =\n\t\t\t\tdefinition.treatDestinationEndpointAsSource;\n\t\t}\n\n\t\tif (definition.useUTCInTimeParametersCC != undefined) {\n\t\t\tif (definition.useUTCInTimeParametersCC !== true) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option useUTCInTimeParametersCC must be true or omitted`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.useUTCInTimeParametersCC = definition.useUTCInTimeParametersCC;\n\t\t}\n\n\t\tif (definition.manualValueRefreshDelayMs != undefined) {\n\t\t\tif (typeof definition.manualValueRefreshDelayMs !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option manualValueRefreshDelayMs must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.manualValueRefreshDelayMs % 1 !== 0\n\t\t\t\t|| definition.manualValueRefreshDelayMs < 0\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option manualValueRefreshDelayMs must be a non-negative integer!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.manualValueRefreshDelayMs =\n\t\t\t\tdefinition.manualValueRefreshDelayMs;\n\t\t}\n\n\t\tif (definition.reportTimeout != undefined) {\n\t\t\tif (typeof definition.reportTimeout !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option reportTimeout must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.reportTimeout % 1 !== 0\n\t\t\t\t|| definition.reportTimeout < 1000\n\t\t\t\t|| definition.reportTimeout > 10000\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option reportTimeout must be an integer between 1000 and 10000!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.reportTimeout = definition.reportTimeout;\n\t\t}\n\n\t\tif (definition.mapRootReportsToEndpoint != undefined) {\n\t\t\tif (typeof definition.mapRootReportsToEndpoint !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapRootReportsToEndpoint must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdefinition.mapRootReportsToEndpoint % 1 !== 0\n\t\t\t\t|| definition.mapRootReportsToEndpoint < 1\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option mapRootReportsToEndpoint must be a positive integer!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.mapRootReportsToEndpoint = definition.mapRootReportsToEndpoint;\n\t\t}\n\n\t\tif (definition.overrideFloatEncoding != undefined) {\n\t\t\tif (!isObject(definition.overrideFloatEncoding)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option overrideFloatEncoding`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.overrideFloatEncoding = {};\n\t\t\tif (\"precision\" in definition.overrideFloatEncoding) {\n\t\t\t\tif (\n\t\t\t\t\ttypeof definition.overrideFloatEncoding.precision\n\t\t\t\t\t\t!= \"number\"\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.precision must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdefinition.overrideFloatEncoding.precision % 1 !== 0\n\t\t\t\t\t|| definition.overrideFloatEncoding.precision < 0\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.precision must be a positive integer!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.overrideFloatEncoding.precision =\n\t\t\t\t\tdefinition.overrideFloatEncoding.precision;\n\t\t\t}\n\t\t\tif (\"size\" in definition.overrideFloatEncoding) {\n\t\t\t\tif (typeof definition.overrideFloatEncoding.size != \"number\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.size must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tdefinition.overrideFloatEncoding.size % 1 !== 0\n\t\t\t\t\t|| definition.overrideFloatEncoding.size < 1\n\t\t\t\t\t|| definition.overrideFloatEncoding.size > 4\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideFloatEncoding.size must be an integer between 1 and 4!`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.overrideFloatEncoding.size =\n\t\t\t\t\tdefinition.overrideFloatEncoding.size;\n\t\t\t}\n\n\t\t\tif (Object.keys(this.overrideFloatEncoding).length === 0) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option overrideFloatEncoding: size and/or precision must be specified!`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.commandClasses != undefined) {\n\t\t\tif (!isObject(definition.commandClasses)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (definition.commandClasses.add != undefined) {\n\t\t\t\tif (!isObject(definition.commandClasses.add)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses.add`,\n\t\t\t\t\t);\n\t\t\t\t} else if (\n\t\t\t\t\t!Object.values(definition.commandClasses.add).every((v) =>\n\t\t\t\t\t\tisObject(v)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nAll values in compat option commandClasses.add must be objects`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst addCCs = new Map<CommandClasses, CompatAddCC>();\n\t\t\t\tfor (\n\t\t\t\t\tconst [key, info] of Object.entries(\n\t\t\t\t\t\tdefinition.commandClasses.add,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// Parse the key into a CC ID\n\t\t\t\t\tconst cc = tryParseCCId(key);\n\t\t\t\t\tif (cc == undefined) {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option commandClasses.add!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\taddCCs.set(cc, new CompatAddCC(filename, info as any));\n\t\t\t\t}\n\t\t\t\tthis.addCCs = addCCs;\n\t\t\t}\n\n\t\t\tif (definition.commandClasses.remove != undefined) {\n\t\t\t\tif (!isObject(definition.commandClasses.remove)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option commandClasses.remove`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst removeCCs = new Map<\n\t\t\t\t\tCommandClasses,\n\t\t\t\t\t\"*\" | readonly number[]\n\t\t\t\t>();\n\t\t\t\tfor (\n\t\t\t\t\tconst [key, info] of Object.entries(\n\t\t\t\t\t\tdefinition.commandClasses.remove,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// Parse the key into a CC ID\n\t\t\t\t\tconst cc = tryParseCCId(key);\n\t\t\t\t\tif (cc == undefined) {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option commandClasses.remove!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (isObject(info) && \"endpoints\" in info) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tinfo.endpoints === \"*\"\n\t\t\t\t\t\t\t|| (isArray(info.endpoints)\n\t\t\t\t\t\t\t\t&& info.endpoints.every(\n\t\t\t\t\t\t\t\t\t(i) => typeof i === \"number\",\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tremoveCCs.set(cc, info.endpoints as any);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t\t`config/devices/${filename}:\nCompat option commandClasses.remove has an invalid \"endpoints\" property. Only \"*\" and numeric arrays are allowed!`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t`config/devices/${filename}:\nAll values in compat option commandClasses.remove must be objects with an \"endpoints\" property!`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.removeCCs = removeCCs;\n\t\t\t}\n\t\t}\n\n\t\tif (definition.alarmMapping != undefined) {\n\t\t\tif (\n\t\t\t\t!isArray(definition.alarmMapping)\n\t\t\t\t|| !definition.alarmMapping.every((m: any) => isObject(m))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option alarmMapping must be an array where all items are objects!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.alarmMapping = (definition.alarmMapping as any[]).map(\n\t\t\t\t(m, i) => new CompatMapAlarm(filename, m, i + 1),\n\t\t\t);\n\t\t}\n\n\t\tif (definition.overrideQueries != undefined) {\n\t\t\tif (!isObject(definition.overrideQueries)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ncompat option overrideQueries must be an object!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.overrideQueries = new CompatOverrideQueries(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.overrideQueries,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly alarmMapping?: readonly CompatMapAlarm[];\n\tpublic readonly addCCs?: ReadonlyMap<CommandClasses, CompatAddCC>;\n\tpublic readonly removeCCs?: ReadonlyMap<\n\t\tCommandClasses,\n\t\t\"*\" | readonly number[]\n\t>;\n\tpublic readonly disableAutoRefresh?: boolean;\n\tpublic readonly disableStrictEntryControlDataValidation?: boolean;\n\tpublic readonly disableStrictMeasurementValidation?: boolean;\n\tpublic readonly disableCallbackFunctionTypeCheck?: number[];\n\tpublic readonly encodeCCsUsingTargetVersion?: boolean;\n\tpublic readonly forceNotificationIdleReset?: boolean;\n\tpublic readonly forceSceneControllerGroupCount?: number;\n\tpublic readonly manualValueRefreshDelayMs?: number;\n\tpublic readonly mapRootReportsToEndpoint?: number;\n\tpublic readonly mapBasicReport?: BasicReportMapping;\n\tpublic readonly mapBasicSet?: BasicSetMapping;\n\tpublic readonly overrideFloatEncoding?: {\n\t\tsize?: number;\n\t\tprecision?: number;\n\t};\n\tpublic readonly overrideQueries?: CompatOverrideQueries;\n\tpublic readonly preserveRootApplicationCCValueIDs?: boolean;\n\tpublic readonly preserveEndpoints?: \"*\" | readonly number[];\n\tpublic readonly removeEndpoints?: \"*\" | readonly number[];\n\tpublic readonly reportTimeout?: number;\n\tpublic readonly skipConfigurationNameQuery?: boolean;\n\tpublic readonly skipConfigurationInfoQuery?: boolean;\n\tpublic readonly treatMultilevelSwitchSetAsEvent?: boolean;\n\tpublic readonly treatSetAsReport?: ReadonlySet<string>;\n\tpublic readonly treatDestinationEndpointAsSource?: boolean;\n\tpublic readonly useUTCInTimeParametersCC?: boolean;\n\tpublic readonly queryOnWakeup?: readonly [\n\t\tstring,\n\t\tstring,\n\t\t...(\n\t\t\t| string\n\t\t\t| number\n\t\t\t| boolean\n\t\t\t| Pick<ValueID, \"property\" | \"propertyKey\">\n\t\t)[],\n\t][];\n\n\tpublic readonly condition?: string | undefined;\n\n\tpublic evaluateCondition(deviceId?: DeviceID): CompatConfig | undefined {\n\t\tif (!conditionApplies(this, deviceId)) return;\n\t\tconst ret = pick(this, [\n\t\t\t\"alarmMapping\",\n\t\t\t\"addCCs\",\n\t\t\t\"removeCCs\",\n\t\t\t\"disableAutoRefresh\",\n\t\t\t\"disableCallbackFunctionTypeCheck\",\n\t\t\t\"disableStrictEntryControlDataValidation\",\n\t\t\t\"disableStrictMeasurementValidation\",\n\t\t\t\"encodeCCsUsingTargetVersion\",\n\t\t\t\"forceNotificationIdleReset\",\n\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\"manualValueRefreshDelayMs\",\n\t\t\t\"mapBasicReport\",\n\t\t\t\"mapBasicSet\",\n\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\"overrideFloatEncoding\",\n\t\t\t\"overrideQueries\",\n\t\t\t\"reportTimeout\",\n\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\"preserveEndpoints\",\n\t\t\t\"removeEndpoints\",\n\t\t\t\"skipConfigurationNameQuery\",\n\t\t\t\"skipConfigurationInfoQuery\",\n\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\"treatSetAsReport\",\n\t\t\t\"treatDestinationEndpointAsSource\",\n\t\t\t\"useUTCInTimeParametersCC\",\n\t\t\t\"queryOnWakeup\",\n\t\t]);\n\t\treturn stripUndefined(ret) as CompatConfig;\n\t}\n}\n\nexport type CompatConfig = Omit<\n\tConditionalCompatConfig,\n\t\"condition\" | \"evaluateCondition\"\n>;\n\nexport class CompatAddCC {\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tconst endpoints = new Map<number, Partial<CommandClassInfo>>();\n\t\tconst parseEndpointInfo = (endpoint: number, info: JSONObject) => {\n\t\t\tconst parsed: Partial<CommandClassInfo> = {};\n\t\t\tif (info.isSupported != undefined) {\n\t\t\t\tif (typeof info.isSupported !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty isSupported in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.isSupported = info.isSupported;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.isControlled != undefined) {\n\t\t\t\tif (typeof info.isControlled !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty isControlled in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.isControlled = info.isControlled;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.secure != undefined) {\n\t\t\t\tif (typeof info.secure !== \"boolean\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty secure in compat option commandClasses.add, endpoint ${endpoint} must be a boolean!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.secure = info.secure;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (info.version != undefined) {\n\t\t\t\tif (typeof info.version !== \"number\") {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nProperty version in compat option commandClasses.add, endpoint ${endpoint} must be a number!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tparsed.version = info.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tendpoints.set(endpoint, parsed);\n\t\t};\n\t\t// Parse root endpoint info if given\n\t\tif (\n\t\t\tdefinition.isSupported != undefined\n\t\t\t|| definition.isControlled != undefined\n\t\t\t|| definition.version != undefined\n\t\t\t|| definition.secure != undefined\n\t\t) {\n\t\t\t// We have info for the root endpoint\n\t\t\tparseEndpointInfo(0, definition);\n\t\t}\n\t\t// Parse all other endpoints\n\t\tif (isObject(definition.endpoints)) {\n\t\t\tif (\n\t\t\t\t!Object.keys(definition.endpoints).every((k) => /^\\d+$/.test(k))\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\ninvalid endpoint index in compat option commandClasses.add`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tfor (const [ep, info] of Object.entries(definition.endpoints)) {\n\t\t\t\t\tparseEndpointInfo(parseInt(ep), info as any);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.endpoints = endpoints;\n\t}\n\n\tpublic readonly endpoints: ReadonlyMap<number, Partial<CommandClassInfo>>;\n}\n\nexport interface CompatMapAlarmFrom {\n\talarmType: number;\n\talarmLevel?: number;\n}\n\nexport interface CompatMapAlarmTo {\n\tnotificationType: number;\n\tnotificationEvent: number;\n\teventParameters?: Record<string, number | \"alarmLevel\">;\n}\n\nexport class CompatMapAlarm {\n\tpublic constructor(\n\t\tfilename: string,\n\t\tdefinition: JSONObject,\n\t\tindex: number,\n\t) {\n\t\tif (!isObject(definition.from)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"devices\",\n\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"from\" must be an object!`,\n\t\t\t);\n\t\t} else {\n\t\t\tif (typeof definition.from.alarmType !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"from.alarmType\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdefinition.from.alarmLevel != undefined\n\t\t\t\t&& typeof definition.from.alarmLevel !== \"number\"\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: if property \"from.alarmLevel\" is given, it must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (!isObject(definition.to)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"devices\",\n\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to\" must be an object!`,\n\t\t\t);\n\t\t} else {\n\t\t\tif (typeof definition.to.notificationType !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.notificationType\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof definition.to.notificationEvent !== \"number\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.notificationEvent\" must be a number!`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (definition.to.eventParameters != undefined) {\n\t\t\t\tif (!isObject(definition.to.eventParameters)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.eventParameters\" must be an object!`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tfor (\n\t\t\t\t\t\tconst [key, val] of Object.entries(\n\t\t\t\t\t\t\tdefinition.to.eventParameters,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (typeof val !== \"number\" && val !== \"alarmLevel\") {\n\t\t\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t\t\t\"devices\",\n\t\t\t\t\t\t\t\t`config/devices/${filename}:\nerror in compat option alarmMapping, mapping #${index}: property \"to.eventParameters.${key}\" must be a number or the literal \"alarmLevel\"!`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.from = pick(definition.from, [\"alarmType\", \"alarmLevel\"]);\n\t\tthis.to = pick(definition.to, [\n\t\t\t\"notificationType\",\n\t\t\t\"notificationEvent\",\n\t\t\t\"eventParameters\",\n\t\t]);\n\t}\n\n\tpublic readonly from: CompatMapAlarmFrom;\n\tpublic readonly to: CompatMapAlarmTo;\n}\n\nexport class CompatOverrideQueries {\n\tpublic constructor(filename: string, definition: JSONObject) {\n\t\tconst overrides = new Map();\n\n\t\tconst parseOverride = (\n\t\t\tcc: CommandClasses,\n\t\t\tinfo: JSONObject,\n\t\t): CompatOverrideQuery => {\n\t\t\tif (typeof info.method !== \"string\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"method\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be a string!`,\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tinfo.matchArgs != undefined\n\t\t\t\t&& !isArray(info.matchArgs)\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"matchArgs\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an array!`,\n\t\t\t\t);\n\t\t\t} else if (!(\"result\" in info)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"result\" is missing in in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t}!`,\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tinfo.endpoint != undefined\n\t\t\t\t&& typeof info.endpoint !== \"number\"\n\t\t\t) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"endpoint\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be a number!`,\n\t\t\t\t);\n\t\t\t} else if (info.persistValues && !isObject(info.persistValues)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"persistValues\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an object!`,\n\t\t\t\t);\n\t\t\t} else if (info.extendMetadata && !isObject(info.extendMetadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"extendMetadata\" in compat option overrideQueries, CC ${\n\t\t\t\t\t\tgetCCName(\n\t\t\t\t\t\t\tcc,\n\t\t\t\t\t\t)\n\t\t\t\t\t} must be an object!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tendpoint: info.endpoint,\n\t\t\t\tmethod: info.method,\n\t\t\t\tmatchArgs: info.matchArgs,\n\t\t\t\tresult: info.result,\n\t\t\t\tpersistValues: info.persistValues,\n\t\t\t\textendMetadata: info.extendMetadata,\n\t\t\t};\n\t\t};\n\n\t\tfor (const [key, value] of Object.entries(definition)) {\n\t\t\t// Parse the key into a CC ID\n\t\t\tconst cc = tryParseCCId(key);\n\t\t\tif (cc == undefined) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nInvalid Command Class \"${key}\" specified in compat option overrideQueries!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet overrideDefinitions: any;\n\t\t\tif (isObject(value)) {\n\t\t\t\toverrideDefinitions = [value];\n\t\t\t} else if (!isArray(value)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"devices\",\n\t\t\t\t\t`config/devices/${filename}:\nProperty \"${key}\" in compat option overrideQueries must be a single override object or an array thereof!`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\toverrideDefinitions = value;\n\t\t\t}\n\n\t\t\toverrides.set(\n\t\t\t\tcc,\n\t\t\t\toverrideDefinitions.map((info: any) => parseOverride(cc, info)),\n\t\t\t);\n\t\t}\n\n\t\tthis.overrides = overrides;\n\t}\n\n\t// CC -> endpoint -> queries\n\tprivate readonly overrides: ReadonlyMap<\n\t\tCommandClasses,\n\t\tCompatOverrideQuery[]\n\t>;\n\n\tpublic hasOverride(ccId: CommandClasses): boolean {\n\t\treturn this.overrides.has(ccId);\n\t}\n\n\tpublic matchOverride(\n\t\tcc: CommandClasses,\n\t\tendpointIndex: number,\n\t\tmethod: string,\n\t\targs: any[],\n\t):\n\t\t| Pick<\n\t\t\tCompatOverrideQuery,\n\t\t\t\"result\" | \"persistValues\" | \"extendMetadata\"\n\t\t>\n\t\t| undefined\n\t{\n\t\tconst queries = this.overrides.get(cc);\n\t\tif (!queries) return undefined;\n\t\tfor (const query of queries) {\n\t\t\tif ((query.endpoint ?? 0) !== endpointIndex) continue;\n\t\t\tif (query.method !== method) continue;\n\t\t\tif (query.matchArgs) {\n\t\t\t\tif (query.matchArgs.length !== args.length) continue;\n\t\t\t\tif (!query.matchArgs.every((arg, i) => arg === args[i])) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn pick(query, [\"result\", \"persistValues\", \"extendMetadata\"]);\n\t\t}\n\t}\n}\n\nexport interface CompatOverrideQuery {\n\t/** Which endpoint this override is for */\n\tendpoint?: number;\n\t/** For which API method this override is defined */\n\tmethod: string;\n\t/**\n\t * An array of method arguments that needs to match for this override to apply.\n\t * If `undefined`, no matching is performed.\n\t */\n\tmatchArgs?: any[];\n\t/** The result to return from the API call */\n\tresult: any;\n\t/**\n\t * An optional dictionary of values that will be persisted in the cache.\n\t * The keys are properties of the `...CCValues` objects that belong to this CC.\n\t */\n\tpersistValues?: Record<string, any>;\n\t/**\n\t * An optional dictionary of value metadata that will be persisted in the cache.\n\t * The keys are properties of the `...CCValues` objects that belong to this CC.\n\t * The given metadata will be merged with statically defined value metadata.\n\t */\n\textendMetadata?: Record<string, any>;\n}\n\nconst basicReportMappings = [\n\tfalse,\n\t\"auto\",\n\t\"Binary Sensor\",\n] as const;\n\n/**\n * Defines how to handle a received Basic CC Report:\n * - \"auto\": map it to a different CC based on the device type, with fallback to `false`\n * - false: treat the report verbatim without mapping\n * - \"Binary Sensor\": treat it as a Binary Sensor CC Report, regardless of device type\n */\nexport type BasicReportMapping = typeof basicReportMappings[number];\n\nfunction isBasicReportMapping(v: unknown): v is BasicReportMapping {\n\treturn basicReportMappings.includes(v as any);\n}\n\nconst basicSetMappings = [\n\t\"event\",\n\t\"report\",\n\t\"auto\",\n\t\"Binary Sensor\",\n] as const;\n\n/**\n * Defines how to handle a received Basic CC Set:\n * - \"event\": emit an event for the special `event` CC value\n * - \"report\": treat it as as a Basic CC Report (default)\n * - \"auto\": map it to a different CC based on the device type, with fallback to Basic CC report\n * - \"Binary Sensor\": treat it as a Binary Sensor CC Report, regardless of device type\n */\nexport type BasicSetMapping = typeof basicSetMappings[number];\n\nfunction isBasicSetMapping(v: unknown): v is BasicSetMapping {\n\treturn basicSetMappings.includes(v as any);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
|
@@ -25,8 +25,8 @@ __export(ConditionalItem_exports, {
|
|
|
25
25
|
validateCondition: () => validateCondition
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(ConditionalItem_exports);
|
|
28
|
-
var
|
|
29
|
-
var
|
|
28
|
+
var import_core = require("@zwave-js/core");
|
|
29
|
+
var import_shared = require("@zwave-js/shared");
|
|
30
30
|
var import_typeguards = require("alcalzone-shared/typeguards");
|
|
31
31
|
var import_Logic = require("../Logic.js");
|
|
32
32
|
var import_utils_safe = require("../utils_safe.js");
|
|
@@ -49,7 +49,7 @@ function conditionApplies(self, deviceId) {
|
|
|
49
49
|
try {
|
|
50
50
|
return !!(0, import_Logic.evaluate)(self.condition, deviceId);
|
|
51
51
|
} catch {
|
|
52
|
-
throw new
|
|
52
|
+
throw new import_core.ZWaveError(`Invalid condition "${self.condition}"!`, import_core.ZWaveErrorCodes.Config_Invalid);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
__name(conditionApplies, "conditionApplies");
|
|
@@ -84,8 +84,8 @@ function evaluateDeep(obj, deviceId, preserveArray = false) {
|
|
|
84
84
|
}
|
|
85
85
|
if (ret.size > 0)
|
|
86
86
|
return ret;
|
|
87
|
-
} else if (obj instanceof
|
|
88
|
-
const ret = new
|
|
87
|
+
} else if (obj instanceof import_shared.ObjectKeyMap) {
|
|
88
|
+
const ret = new import_shared.ObjectKeyMap();
|
|
89
89
|
for (const [key, val] of obj) {
|
|
90
90
|
const evaluated = evaluateDeep(val, deviceId, false);
|
|
91
91
|
if (evaluated != void 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/devices/ConditionalItem.ts"],
|
|
4
|
-
"sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,kBAA4C;AAC5C,
|
|
6
|
-
"names": [
|
|
4
|
+
"sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core\";\nimport { ObjectKeyMap } from \"@zwave-js/shared\";\nimport { isArray } from \"alcalzone-shared/typeguards\";\nimport { evaluate } from \"../Logic.js\";\nimport { throwInvalidConfig } from \"../utils_safe.js\";\nimport type { DeviceID } from \"./shared.js\";\n\n/** A conditional config item */\nexport interface ConditionalItem<T> {\n\treadonly condition?: string;\n\tevaluateCondition(deviceId?: DeviceID): T | undefined;\n}\n\nexport function isConditionalItem<T>(val: any): val is ConditionalItem<T> {\n\t// Conditional items must be objects or classes\n\tif (typeof val !== \"object\" || val == undefined) return false;\n\t// Conditional items may have a string-valued condition\n\tif (\n\t\ttypeof val.condition !== \"string\"\n\t\t&& typeof val.condition !== \"undefined\"\n\t) {\n\t\treturn false;\n\t}\n\t// Conditional items must have an evaluateCondition method\n\tif (typeof val.evaluateCondition !== \"function\") return false;\n\treturn true;\n}\n\n/** Checks if a given condition applies for the given device ID */\nexport function conditionApplies<T>(\n\tself: ConditionalItem<T>,\n\tdeviceId: DeviceID | undefined,\n): boolean {\n\t// No condition? Always applies\n\tif (!self.condition) return true;\n\t// No device ID? Always applies\n\tif (!deviceId) return true;\n\n\ttry {\n\t\treturn !!evaluate(self.condition, deviceId);\n\t} catch {\n\t\tthrow new ZWaveError(\n\t\t\t`Invalid condition \"${self.condition}\"!`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n}\n\nexport function validateCondition(\n\tfilename: string,\n\tdefinition: Record<string, any>,\n\terrorPrefix: string,\n): void {\n\tif (definition.$if != undefined && typeof definition.$if !== \"string\") {\n\t\tthrowInvalidConfig(\n\t\t\t\"devices\",\n\t\t\t`packages/config/config/devices/${filename}:\n${errorPrefix} invalid $if condition`,\n\t\t);\n\t}\n}\n\nexport type EvaluateDeepReturnType<\n\tT,\n\tPreserveArray extends boolean = false,\n> = T extends undefined ? undefined\n\t: T extends ConditionalItem<infer R>[]\n\t\t? [PreserveArray] extends [true] ? R[]\n\t\t: R\n\t: T extends ConditionalItem<infer R> ? R\n\t: T extends ObjectKeyMap<infer K, infer V>\n\t\t? ObjectKeyMap<K, EvaluateDeepReturnType<V, false>>\n\t: T extends ReadonlyMap<infer K, infer V>\n\t\t? Map<K, EvaluateDeepReturnType<V, false>>\n\t: T extends Map<infer K, infer V> ? Map<K, EvaluateDeepReturnType<V, false>>\n\t: T extends unknown[] ? [PreserveArray] extends [true] ? T\n\t\t: T[number]\n\t: T;\n\nexport function evaluateDeep<T, PA extends boolean>(\n\tobj: T,\n\tdeviceId?: DeviceID,\n\tpreserveArray?: PA,\n): EvaluateDeepReturnType<T, PA>;\n\n/**\n * Recursively evaluates the given conditional item. By default, arrays are collapsed to the first applicable item.\n */\nexport function evaluateDeep(\n\tobj: unknown,\n\tdeviceId?: DeviceID,\n\tpreserveArray: boolean = false,\n): unknown {\n\tif (obj == undefined) {\n\t\treturn obj;\n\t} else if (isArray(obj)) {\n\t\tif (preserveArray) {\n\t\t\t// Evaluate all array entries and return the ones that passed\n\t\t\treturn obj\n\t\t\t\t.map((item) => evaluateDeep(item, deviceId, true))\n\t\t\t\t.filter((o) => o != undefined);\n\t\t} else {\n\t\t\t// Return the first matching array entry\n\t\t\tfor (const item of obj) {\n\t\t\t\tconst evaluated = evaluateDeep(item, deviceId, false);\n\t\t\t\tif (evaluated != undefined) return evaluated;\n\t\t\t}\n\t\t}\n\t} else if (obj instanceof Map) {\n\t\tconst ret = new Map();\n\t\tfor (const [key, val] of obj) {\n\t\t\t// In maps only take the first possible value for each entry\n\t\t\tconst evaluated = evaluateDeep(val, deviceId, false);\n\n\t\t\tif (evaluated != undefined) {\n\t\t\t\tret.set(key, evaluated);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (ret.size > 0) return ret;\n\t} else if (obj instanceof ObjectKeyMap) {\n\t\tconst ret = new ObjectKeyMap();\n\t\tfor (const [key, val] of obj) {\n\t\t\t// In maps only take the first possible value for each entry\n\t\t\tconst evaluated = evaluateDeep(val, deviceId, false);\n\n\t\t\tif (evaluated != undefined) {\n\t\t\t\tret.set(key, evaluated);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (ret.size > 0) return ret;\n\t} else if (isConditionalItem(obj)) {\n\t\t// Evaluate the condition for simple items\n\t\treturn obj.evaluateCondition(deviceId);\n\t} else {\n\t\t// Simply return non-conditional items\n\t\treturn obj;\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,kBAA4C;AAC5C,oBAA6B;AAC7B,wBAAwB;AACxB,mBAAyB;AACzB,wBAAmC;AAS7B,SAAU,kBAAqB,KAAQ;AAE5C,MAAI,OAAO,QAAQ,YAAY,OAAO;AAAW,WAAO;AAExD,MACC,OAAO,IAAI,cAAc,YACtB,OAAO,IAAI,cAAc,aAC3B;AACD,WAAO;EACR;AAEA,MAAI,OAAO,IAAI,sBAAsB;AAAY,WAAO;AACxD,SAAO;AACR;AAbgB;AAgBV,SAAU,iBACf,MACA,UAA8B;AAG9B,MAAI,CAAC,KAAK;AAAW,WAAO;AAE5B,MAAI,CAAC;AAAU,WAAO;AAEtB,MAAI;AACH,WAAO,CAAC,KAAC,uBAAS,KAAK,WAAW,QAAQ;EAC3C,QAAQ;AACP,UAAM,IAAI,uBACT,sBAAsB,KAAK,SAAS,MACpC,4BAAgB,cAAc;EAEhC;AACD;AAjBgB;AAmBV,SAAU,kBACf,UACA,YACA,aAAmB;AAEnB,MAAI,WAAW,OAAO,UAAa,OAAO,WAAW,QAAQ,UAAU;AACtE,8CACC,WACA,kCAAkC,QAAQ;EAC3C,WAAW,wBAAwB;EAEpC;AACD;AAZgB;AAwCV,SAAU,aACf,KACA,UACA,gBAAyB,OAAK;AAE9B,MAAI,OAAO,QAAW;AACrB,WAAO;EACR,eAAW,2BAAQ,GAAG,GAAG;AACxB,QAAI,eAAe;AAElB,aAAO,IACL,IAAI,CAAC,SAAS,aAAa,MAAM,UAAU,IAAI,CAAC,EAChD,OAAO,CAAC,MAAM,KAAK,MAAS;IAC/B,OAAO;AAEN,iBAAW,QAAQ,KAAK;AACvB,cAAM,YAAY,aAAa,MAAM,UAAU,KAAK;AACpD,YAAI,aAAa;AAAW,iBAAO;MACpC;IACD;EACD,WAAW,eAAe,KAAK;AAC9B,UAAM,MAAM,oBAAI,IAAG;AACnB,eAAW,CAAC,KAAK,GAAG,KAAK,KAAK;AAE7B,YAAM,YAAY,aAAa,KAAK,UAAU,KAAK;AAEnD,UAAI,aAAa,QAAW;AAC3B,YAAI,IAAI,KAAK,SAAS;AACtB;MACD;IACD;AACA,QAAI,IAAI,OAAO;AAAG,aAAO;EAC1B,WAAW,eAAe,4BAAc;AACvC,UAAM,MAAM,IAAI,2BAAY;AAC5B,eAAW,CAAC,KAAK,GAAG,KAAK,KAAK;AAE7B,YAAM,YAAY,aAAa,KAAK,UAAU,KAAK;AAEnD,UAAI,aAAa,QAAW;AAC3B,YAAI,IAAI,KAAK,SAAS;AACtB;MACD;IACD;AACA,QAAI,IAAI,OAAO;AAAG,aAAO;EAC1B,WAAW,kBAAkB,GAAG,GAAG;AAElC,WAAO,IAAI,kBAAkB,QAAQ;EACtC,OAAO;AAEN,WAAO;EACR;AACD;AAnDgB;",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type JSONObject } from "@zwave-js/shared";
|
|
2
|
-
import {
|
|
2
|
+
import type { ReadFile, ReadFileSystemInfo } from "@zwave-js/shared/bindings";
|
|
3
3
|
import { type AssociationConfig, ConditionalAssociationConfig } from "./AssociationConfig.js";
|
|
4
4
|
import { type CompatConfig, ConditionalCompatConfig } from "./CompatConfig.js";
|
|
5
5
|
import { type ConditionalPrimitive } from "./ConditionalPrimitive.js";
|
|
@@ -39,7 +39,6 @@ __export(DeviceConfig_exports, {
|
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(DeviceConfig_exports);
|
|
41
41
|
var import_core = require("@zwave-js/core");
|
|
42
|
-
var import_core2 = require("@zwave-js/core");
|
|
43
42
|
var import_shared = require("@zwave-js/shared");
|
|
44
43
|
var import_typeguards = require("alcalzone-shared/typeguards");
|
|
45
44
|
var import_json5 = __toESM(require("json5"), 1);
|
|
@@ -503,7 +502,7 @@ class DeviceConfig {
|
|
|
503
502
|
*/
|
|
504
503
|
getHash(algorithm = "sha-256") {
|
|
505
504
|
const buffer = this.getHashable();
|
|
506
|
-
return (0,
|
|
505
|
+
return (0, import_core.digest)(algorithm, buffer);
|
|
507
506
|
}
|
|
508
507
|
}
|
|
509
508
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/devices/DeviceConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core\";\nimport { digest } from \"@zwave-js/core\";\nimport {\n\tBytes,\n\ttype JSONObject,\n\tenumFilesRecursive,\n\tformatId,\n\tgetenv,\n\tnum2hex,\n\tpadVersion,\n\tpathExists,\n\tpick,\n\treadTextFile,\n\tstringify,\n\twriteTextFile,\n} from \"@zwave-js/shared\";\nimport {\n\ttype ReadFile,\n\ttype ReadFileSystemInfo,\n\ttype WriteFile,\n} from \"@zwave-js/shared/bindings\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport path from \"pathe\";\nimport semverGt from \"semver/functions/gt.js\";\nimport { clearTemplateCache, readJsonWithTemplate } from \"../JsonTemplate.js\";\nimport type { ConfigLogger } from \"../Logger.js\";\nimport { configDir } from \"../utils.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"../utils_safe.js\";\nimport {\n\ttype AssociationConfig,\n\tConditionalAssociationConfig,\n} from \"./AssociationConfig.js\";\nimport { type CompatConfig, ConditionalCompatConfig } from \"./CompatConfig.js\";\nimport { evaluateDeep, validateCondition } from \"./ConditionalItem.js\";\nimport {\n\ttype ConditionalPrimitive,\n\tparseConditionalPrimitive,\n} from \"./ConditionalPrimitive.js\";\nimport {\n\tConditionalDeviceMetadata,\n\ttype DeviceMetadata,\n} from \"./DeviceMetadata.js\";\nimport {\n\tConditionalEndpointConfig,\n\ttype EndpointConfig,\n} from \"./EndpointConfig.js\";\nimport {\n\ttype ConditionalParamInfoMap,\n\ttype ParamInfoMap,\n\ttype ParamInformation,\n\tparseConditionalParamInformationMap,\n} from \"./ParamInformation.js\";\nimport type { DeviceID, FirmwareVersionRange } from \"./shared.js\";\n\nexport interface DeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport interface FulltextDeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tmanufacturer: string;\n\tlabel: string;\n\tdescription: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport const embeddedDevicesDir = path.join(configDir, \"devices\");\nconst fulltextIndexPath = path.join(embeddedDevicesDir, \"fulltext_index.json\");\n\nexport function getDevicesPaths(configDir: string): {\n\tdevicesDir: string;\n\tindexPath: string;\n} {\n\tconst devicesDir = path.join(configDir, \"devices\");\n\tconst indexPath = path.join(devicesDir, \"index.json\");\n\treturn { devicesDir, indexPath };\n}\n\nexport type DeviceConfigIndex = DeviceConfigIndexEntry[];\nexport type FulltextDeviceConfigIndex = FulltextDeviceConfigIndexEntry[];\n\nasync function hasChangedDeviceFiles(\n\tfs: ReadFileSystemInfo,\n\tdevicesRoot: string,\n\tdir: string,\n\tlastChange: Date,\n): Promise<boolean> {\n\t// Check if there are any files BUT index.json that were changed\n\t// or directories that were modified\n\tconst filesAndDirs = await fs.readDir(dir);\n\tfor (const f of filesAndDirs) {\n\t\tconst fullPath = path.join(dir, f);\n\n\t\tconst stat = await fs.stat(fullPath);\n\t\tif (\n\t\t\t(dir !== devicesRoot || f !== \"index.json\")\n\t\t\t&& (stat.isFile() || stat.isDirectory())\n\t\t\t&& stat.mtime > lastChange\n\t\t) {\n\t\t\treturn true;\n\t\t} else if (stat.isDirectory()) {\n\t\t\t// we need to go deeper!\n\t\t\tif (\n\t\t\t\tawait hasChangedDeviceFiles(\n\t\t\t\t\tfs,\n\t\t\t\t\tdevicesRoot,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tlastChange,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Read all device config files from a given directory and return them as index entries.\n * Does not update the index itself.\n */\nasync function generateIndex<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdevicesDir: string,\n\tisEmbedded: boolean,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string; rootDir?: string })[]> {\n\tconst index: (T & { filename: string; rootDir?: string })[] = [];\n\n\tclearTemplateCache();\n\tconst configFiles = await enumFilesRecursive(\n\t\tfs,\n\t\tdevicesDir,\n\t\t(file) =>\n\t\t\tfile.endsWith(\".json\")\n\t\t\t&& !file.endsWith(\"index.json\")\n\t\t\t&& !file.includes(\"/templates/\")\n\t\t\t&& !file.includes(\"\\\\templates\\\\\"),\n\t);\n\n\t// Add the embedded devices dir as a fallback if necessary\n\tconst fallbackDirs = devicesDir !== embeddedDevicesDir\n\t\t? [embeddedDevicesDir]\n\t\t: undefined;\n\n\tfor (const file of configFiles) {\n\t\tconst relativePath = path\n\t\t\t.relative(devicesDir, file)\n\t\t\t.replaceAll(\"\\\\\", \"/\");\n\t\t// Try parsing the file\n\t\ttry {\n\t\t\tconst config = await DeviceConfig.from(\n\t\t\t\tfs,\n\t\t\t\tfile,\n\t\t\t\tisEmbedded,\n\t\t\t\t{\n\t\t\t\t\trootDir: devicesDir,\n\t\t\t\t\tfallbackDirs,\n\t\t\t\t\trelative: true,\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Add the file to the index\n\t\t\tindex.push(\n\t\t\t\t...extractIndexEntries(config).map((entry) => {\n\t\t\t\t\tconst ret: T & { filename: string; rootDir?: string } = {\n\t\t\t\t\t\t...entry,\n\t\t\t\t\t\tfilename: relativePath,\n\t\t\t\t\t};\n\t\t\t\t\t// Only add the root dir to the index if necessary\n\t\t\t\t\tif (devicesDir !== embeddedDevicesDir) {\n\t\t\t\t\t\tret.rootDir = devicesDir;\n\t\t\t\t\t}\n\t\t\t\t\treturn ret;\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tconst message = `Error parsing config file ${relativePath}: ${\n\t\t\t\t(e as Error).message\n\t\t\t}`;\n\t\t\t// Crash hard during tests, just print an error when in production systems.\n\t\t\t// A user could have changed a config file\n\t\t\tif (process.env.NODE_ENV === \"test\" || !!getenv(\"CI\")) {\n\t\t\t\tthrow new ZWaveError(message, ZWaveErrorCodes.Config_Invalid);\n\t\t\t} else {\n\t\t\t\tlogger?.print(message, \"error\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn index;\n}\n\nasync function loadDeviceIndexShared<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tdevicesDir: string,\n\tindexPath: string,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string })[]> {\n\t// The index file needs to be regenerated if it does not exist\n\tlet needsUpdate = !(await pathExists(fs, indexPath));\n\tlet index: (T & { filename: string })[] | undefined;\n\tlet mtimeIndex: Date | undefined;\n\t// ...or if cannot be parsed\n\tif (!needsUpdate) {\n\t\ttry {\n\t\t\tconst fileContents = await readTextFile(fs, indexPath, \"utf8\");\n\t\t\tindex = JSON5.parse(fileContents);\n\t\t\tmtimeIndex = (await fs.stat(indexPath)).mtime;\n\t\t} catch {\n\t\t\tlogger?.print(\n\t\t\t\t\"Error while parsing index file - regenerating...\",\n\t\t\t\t\"warn\",\n\t\t\t);\n\t\t\tneedsUpdate = true;\n\t\t} finally {\n\t\t\tif (!index) {\n\t\t\t\tlogger?.print(\n\t\t\t\t\t\"Index file was malformed - regenerating...\",\n\t\t\t\t\t\"warn\",\n\t\t\t\t);\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ...or if there were any changes in the file system\n\tif (!needsUpdate) {\n\t\tneedsUpdate = await hasChangedDeviceFiles(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\tdevicesDir,\n\t\t\tmtimeIndex!,\n\t\t);\n\t\tif (needsUpdate) {\n\t\t\tlogger?.print(\n\t\t\t\t\"Device configuration files on disk changed - regenerating index...\",\n\t\t\t\t\"verbose\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (needsUpdate) {\n\t\t// Read all files from disk and generate an index\n\t\tindex = await generateIndex(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\ttrue,\n\t\t\textractIndexEntries,\n\t\t\tlogger,\n\t\t);\n\t\t// Save the index to disk\n\t\ttry {\n\t\t\tawait writeTextFile(\n\t\t\t\tfs,\n\t\t\t\tpath.join(indexPath),\n\t\t\t\t`// This file is auto-generated. DO NOT edit it by hand if you don't know what you're doing!\"\n${stringify(index, \"\\t\")}\n`,\n\t\t\t\t\"utf8\",\n\t\t\t);\n\t\t\tlogger?.print(\"Device index regenerated\", \"verbose\");\n\t\t} catch (e) {\n\t\t\tlogger?.print(\n\t\t\t\t`Writing the device index to disk failed: ${\n\t\t\t\t\t(e as Error).message\n\t\t\t\t}`,\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn index!;\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function generatePriorityDeviceIndex(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdeviceConfigPriorityDir: string,\n\tlogger?: ConfigLogger,\n): Promise<DeviceConfigIndex> {\n\treturn (\n\t\tawait generateIndex(\n\t\t\tfs,\n\t\t\tdeviceConfigPriorityDir,\n\t\t\tfalse,\n\t\t\t(config) =>\n\t\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\t\tmanufacturerId: formatId(\n\t\t\t\t\t\tconfig.manufacturerId.toString(16),\n\t\t\t\t\t),\n\t\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\t\tlabel: config.label,\n\t\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\t\trootDir: deviceConfigPriorityDir,\n\t\t\t\t})),\n\t\t\tlogger,\n\t\t)\n\t).map(({ filename, ...entry }) => ({\n\t\t...entry,\n\t\t// The generated index makes the filenames relative to the given directory\n\t\t// but we need them to be absolute\n\t\tfilename: path.join(deviceConfigPriorityDir, filename),\n\t}));\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n\texternalConfigDir?: string,\n): Promise<DeviceConfigIndex> {\n\tconst { devicesDir, indexPath } = getDevicesPaths(\n\t\texternalConfigDir || configDir,\n\t);\n\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tdevicesDir,\n\t\tindexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\n/**\n * @internal\n * Loads the full text index file to quickly search the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadFulltextDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n): Promise<FulltextDeviceConfigIndex> {\n\t// This method is not meant to operate with the external device index!\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tembeddedDevicesDir,\n\t\tfulltextIndexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tdescription: config.description,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\trootDir: embeddedDevicesDir,\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\nfunction isHexKeyWith4Digits(val: any): val is string {\n\treturn typeof val === \"string\" && hexKeyRegex4Digits.test(val);\n}\n\nconst firmwareVersionRegex = /^\\d{1,3}\\.\\d{1,3}(\\.\\d{1,3})?$/;\nfunction isFirmwareVersion(val: any): val is string {\n\treturn (\n\t\ttypeof val === \"string\"\n\t\t&& firmwareVersionRegex.test(val)\n\t\t&& val\n\t\t\t.split(\".\")\n\t\t\t.map((str) => parseInt(str, 10))\n\t\t\t.every((num) => num >= 0 && num <= 255)\n\t);\n}\n\n/** This class represents a device config entry whose conditional settings have not been evaluated yet */\nexport class ConditionalDeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t},\n\t): Promise<ConditionalDeviceConfig> {\n\t\tconst { relative, rootDir } = options;\n\n\t\tconst relativePath = relative\n\t\t\t? path.relative(rootDir, filename).replaceAll(\"\\\\\", \"/\")\n\t\t\t: filename;\n\t\tconst json = await readJsonWithTemplate(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\t[\n\t\t\t\toptions.rootDir,\n\t\t\t\t...(options.fallbackDirs ?? []),\n\t\t\t],\n\t\t);\n\t\treturn new ConditionalDeviceConfig(relativePath, isEmbedded, json);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tdefinition: JSONObject,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\n\t\tif (!isHexKeyWith4Digits(definition.manufacturerId)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nmanufacturer id must be a lowercase hexadecimal number with 4 digits`,\n\t\t\t);\n\t\t}\n\t\tthis.manufacturerId = parseInt(definition.manufacturerId, 16);\n\n\t\tfor (const prop of [\"manufacturer\", \"label\", \"description\"] as const) {\n\t\t\tthis[prop] = parseConditionalPrimitive(\n\t\t\t\tfilename,\n\t\t\t\t\"string\",\n\t\t\t\tprop,\n\t\t\t\tdefinition[prop],\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!isArray(definition.devices)\n\t\t\t|| !(definition.devices as any[]).every(\n\t\t\t\t(dev: unknown) =>\n\t\t\t\t\tisObject(dev)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productType)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productId),\n\t\t\t)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\ndevices is malformed (not an object or type/id that is not a lowercase 4-digit hex key)`,\n\t\t\t);\n\t\t}\n\t\tthis.devices = (definition.devices as any[]).map(\n\t\t\t({ productType, productId }) => ({\n\t\t\t\tproductType: parseInt(productType, 16),\n\t\t\t\tproductId: parseInt(productId, 16),\n\t\t\t}),\n\t\t);\n\n\t\tif (\n\t\t\t!isObject(definition.firmwareVersion)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.min)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.max)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion is malformed or invalid. Must be x.y or x.y.z where x, y, and z are integers between 0 and 255`,\n\t\t\t);\n\t\t} else {\n\t\t\tconst { min, max } = definition.firmwareVersion;\n\t\t\tif (semverGt(padVersion(min), padVersion(max))) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion.min ${min} must not be greater than firmwareVersion.max ${max}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.firmwareVersion = { min, max };\n\t\t}\n\n\t\tif (\n\t\t\tdefinition.preferred != undefined\n\t\t\t&& definition.preferred !== true\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\npreferred must be true or omitted`,\n\t\t\t);\n\t\t}\n\t\tthis.preferred = !!definition.preferred;\n\n\t\tif (definition.endpoints != undefined) {\n\t\t\tconst endpoints = new Map<number, ConditionalEndpointConfig>();\n\t\t\tif (!isObject(definition.endpoints)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nendpoints is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, ep] of Object.entries(definition.endpoints)) {\n\t\t\t\tif (!/^\\d+$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric endpoint index \"${key}\" in endpoints`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst epIndex = parseInt(key, 10);\n\t\t\t\tendpoints.set(\n\t\t\t\t\tepIndex,\n\t\t\t\t\tnew ConditionalEndpointConfig(this, epIndex, ep as any),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.endpoints = endpoints;\n\t\t}\n\n\t\tif (definition.associations != undefined) {\n\t\t\tconst associations = new Map<\n\t\t\t\tnumber,\n\t\t\t\tConditionalAssociationConfig\n\t\t\t>();\n\t\t\tif (!isObject(definition.associations)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nassociations is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (\n\t\t\t\tconst [key, assocDefinition] of Object.entries(\n\t\t\t\t\tdefinition.associations,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tif (!/^[1-9][0-9]*$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric group id \"${key}\" in associations`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst keyNum = parseInt(key, 10);\n\t\t\t\tassociations.set(\n\t\t\t\t\tkeyNum,\n\t\t\t\t\tnew ConditionalAssociationConfig(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tkeyNum,\n\t\t\t\t\t\tassocDefinition as any,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.associations = associations;\n\t\t}\n\n\t\tif (definition.paramInformation != undefined) {\n\t\t\tthis.paramInformation = parseConditionalParamInformationMap(\n\t\t\t\tdefinition,\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\n\t\tif (definition.proprietary != undefined) {\n\t\t\tif (!isObject(definition.proprietary)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nproprietary is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.proprietary = definition.proprietary;\n\t\t}\n\n\t\tif (definition.compat != undefined) {\n\t\t\tif (\n\t\t\t\tisArray(definition.compat)\n\t\t\t\t&& definition.compat.every((item: any) => isObject(item))\n\t\t\t) {\n\t\t\t\t// Make sure all conditions are valid\n\t\t\t\tfor (const entry of definition.compat) {\n\t\t\t\t\tvalidateCondition(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\t`At least one entry of compat contains an`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.compat = definition.compat.map(\n\t\t\t\t\t(item: any) => new ConditionalCompatConfig(filename, item),\n\t\t\t\t);\n\t\t\t} else if (isObject(definition.compat)) {\n\t\t\t\tthis.compat = new ConditionalCompatConfig(\n\t\t\t\t\tfilename,\n\t\t\t\t\tdefinition.compat,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\ncompat must be an object or any array of conditional objects`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.metadata != undefined) {\n\t\t\tif (!isObject(definition.metadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nmetadata is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.metadata = new ConditionalDeviceMetadata(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.metadata,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly filename: string;\n\n\tpublic readonly manufacturer!: ConditionalPrimitive<string>;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label!: ConditionalPrimitive<string>;\n\tpublic readonly description!: ConditionalPrimitive<string>;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, ConditionalEndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<\n\t\tnumber,\n\t\tConditionalAssociationConfig\n\t>;\n\tpublic readonly paramInformation?: ConditionalParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?:\n\t\t| ConditionalCompatConfig\n\t\t| ConditionalCompatConfig[];\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: ConditionalDeviceMetadata;\n\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\n\tpublic evaluate(deviceId?: DeviceID): DeviceConfig {\n\t\treturn new DeviceConfig(\n\t\t\tthis.filename,\n\t\t\tthis.isEmbedded,\n\t\t\tevaluateDeep(this.manufacturer, deviceId),\n\t\t\tthis.manufacturerId,\n\t\t\tevaluateDeep(this.label, deviceId),\n\t\t\tevaluateDeep(this.description, deviceId),\n\t\t\tthis.devices,\n\t\t\tthis.firmwareVersion,\n\t\t\tthis.preferred,\n\t\t\tevaluateDeep(this.endpoints, deviceId),\n\t\t\tevaluateDeep(this.associations, deviceId),\n\t\t\tevaluateDeep(this.paramInformation, deviceId),\n\t\t\tthis.proprietary,\n\t\t\tevaluateDeep(this.compat, deviceId),\n\t\t\tevaluateDeep(this.metadata, deviceId),\n\t\t);\n\t}\n}\n\nexport class DeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t\tdeviceId?: DeviceID;\n\t\t},\n\t): Promise<DeviceConfig> {\n\t\tconst ret = await ConditionalDeviceConfig.from(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\tisEmbedded,\n\t\t\toptions,\n\t\t);\n\t\treturn ret.evaluate(options.deviceId);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tmanufacturer: string,\n\t\tmanufacturerId: number,\n\t\tlabel: string,\n\t\tdescription: string,\n\t\tdevices: readonly {\n\t\t\tproductType: number;\n\t\t\tproductId: number;\n\t\t}[],\n\t\tfirmwareVersion: FirmwareVersionRange,\n\t\tpreferred: boolean,\n\t\tendpoints?: ReadonlyMap<number, EndpointConfig>,\n\t\tassociations?: ReadonlyMap<number, AssociationConfig>,\n\t\tparamInformation?: ParamInfoMap,\n\t\tproprietary?: Record<string, unknown>,\n\t\tcompat?: CompatConfig,\n\t\tmetadata?: DeviceMetadata,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\t\tthis.manufacturer = manufacturer;\n\t\tthis.manufacturerId = manufacturerId;\n\t\tthis.label = label;\n\t\tthis.description = description;\n\t\tthis.devices = devices;\n\t\tthis.firmwareVersion = firmwareVersion;\n\t\tthis.preferred = preferred;\n\t\tthis.endpoints = endpoints;\n\t\tthis.associations = associations;\n\t\tthis.paramInformation = paramInformation;\n\t\tthis.proprietary = proprietary;\n\t\tthis.compat = compat;\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic readonly filename: string;\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\tpublic readonly manufacturer: string;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label: string;\n\tpublic readonly description: string;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, EndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<number, AssociationConfig>;\n\tpublic readonly paramInformation?: ParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?: CompatConfig;\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: DeviceMetadata;\n\n\t/** Returns the association config for a given endpoint */\n\tpublic getAssociationConfigForEndpoint(\n\t\tendpointIndex: number,\n\t\tgroup: number,\n\t): AssociationConfig | undefined {\n\t\tif (endpointIndex === 0) {\n\t\t\t// The root endpoint's associations may be configured separately or as part of \"endpoints\"\n\t\t\treturn (\n\t\t\t\tthis.associations?.get(group)\n\t\t\t\t\t?? this.endpoints?.get(0)?.associations?.get(group)\n\t\t\t);\n\t\t} else {\n\t\t\t// The other endpoints can only have a configuration as part of \"endpoints\"\n\t\t\treturn this.endpoints?.get(endpointIndex)?.associations?.get(group);\n\t\t}\n\t}\n\n\tprivate getHashable(): Uint8Array {\n\t\t// We only need to compare the information that is persisted elsewhere:\n\t\t// - config parameters\n\t\t// - functional association settings\n\t\t// - CC-related compat flags\n\n\t\tlet hashable: Record<string, any> = {\n\t\t\t// endpoints: {\n\t\t\t// \tassociations: {},\n\t\t\t// \tparamInformation: []\n\t\t\t// },\n\t\t\t// proprietary: {},\n\t\t\t// compat: {},\n\t\t};\n\n\t\tconst sortObject = (obj: Record<string, any>) => {\n\t\t\tconst ret: Record<string, any> = {};\n\t\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\t\tret[key] = obj[key];\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\n\t\tconst cloneAssociationConfig = (a: AssociationConfig) => {\n\t\t\treturn sortObject(\n\t\t\t\tpick(a, [\"maxNodes\", \"multiChannel\", \"isLifeline\"]),\n\t\t\t);\n\t\t};\n\t\tconst cloneAssociationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ReadonlyMap<number, AssociationConfig> | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\ttarget.associations = {};\n\t\t\tfor (const [key, value] of map) {\n\t\t\t\ttarget.associations[key] = cloneAssociationConfig(value);\n\t\t\t}\n\t\t\ttarget.associations = sortObject(target.associations);\n\t\t};\n\n\t\tconst cloneParamInformationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ParamInfoMap | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\tconst getParamKey = (param: ParamInformation) =>\n\t\t\t\t`${param.parameterNumber}${\n\t\t\t\t\tparam.valueBitMask ? `[${num2hex(param.valueBitMask)}]` : \"\"\n\t\t\t\t}`;\n\t\t\ttarget.paramInformation = [...map.values()].sort((a, b) =>\n\t\t\t\tgetParamKey(a).localeCompare(getParamKey(b))\n\t\t\t);\n\t\t};\n\n\t\t// Clone associations and param information on the root (ep 0) and endpoints\n\t\t{\n\t\t\tlet ep0: Record<string, any> = {};\n\t\t\tcloneAssociationMap(ep0, this.associations);\n\t\t\tcloneParamInformationMap(ep0, this.paramInformation);\n\t\t\tep0 = sortObject(ep0);\n\n\t\t\tif (Object.keys(ep0).length > 0) {\n\t\t\t\thashable.endpoints ??= {};\n\t\t\t\thashable.endpoints[0] = ep0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.endpoints) {\n\t\t\tfor (const [index, endpoint] of this.endpoints) {\n\t\t\t\tlet ep: Record<string, any> = {};\n\n\t\t\t\tcloneAssociationMap(ep, endpoint.associations);\n\t\t\t\tcloneParamInformationMap(ep, endpoint.paramInformation);\n\n\t\t\t\tep = sortObject(ep);\n\n\t\t\t\tif (Object.keys(ep).length > 0) {\n\t\t\t\t\thashable.endpoints ??= {};\n\t\t\t\t\thashable.endpoints[index] = ep;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Clone proprietary config\n\t\tif (this.proprietary && Object.keys(this.proprietary).length > 0) {\n\t\t\thashable.proprietary = sortObject({ ...this.proprietary });\n\t\t}\n\n\t\t// Clone relevant compat flags\n\t\tif (this.compat) {\n\t\t\tlet c: Record<string, any> = {};\n\n\t\t\t// Copy some simple flags over\n\t\t\tfor (\n\t\t\t\tconst prop of [\n\t\t\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\t\t\"mapBasicSet\",\n\t\t\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\t\t\"preserveEndpoints\",\n\t\t\t\t\t\"removeEndpoints\",\n\t\t\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\t] as const\n\t\t\t) {\n\t\t\t\tif (this.compat[prop] != undefined) {\n\t\t\t\t\tc[prop] = this.compat[prop];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy other, more complex flags\n\t\t\tif (this.compat.overrideQueries) {\n\t\t\t\tc.overrideQueries = Object.fromEntries(\n\t\t\t\t\tthis.compat.overrideQueries[\"overrides\"],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.addCCs) {\n\t\t\t\tc.addCCs = Object.fromEntries(\n\t\t\t\t\t[...this.compat.addCCs].map(([ccId, def]) => [\n\t\t\t\t\t\tccId,\n\t\t\t\t\t\tObject.fromEntries(def.endpoints),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.removeCCs) {\n\t\t\t\tc.removeCCs = Object.fromEntries(this.compat.removeCCs);\n\t\t\t}\n\t\t\tif (this.compat.treatSetAsReport) {\n\t\t\t\tc.treatSetAsReport = [...this.compat.treatSetAsReport].sort();\n\t\t\t}\n\n\t\t\tc = sortObject(c);\n\t\t\tif (Object.keys(c).length > 0) {\n\t\t\t\thashable.compat = c;\n\t\t\t}\n\t\t}\n\n\t\thashable = sortObject(hashable);\n\n\t\treturn Bytes.from(JSON.stringify(hashable), \"utf8\");\n\t}\n\n\t/**\n\t * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.\n\t */\n\tpublic getHash(\n\t\talgorithm: \"md5\" | \"sha-256\" = \"sha-256\",\n\t): Promise<Uint8Array> {\n\t\t// Figure out what to hash\n\t\tconst buffer = this.getHashable();\n\n\t\t// And create a hash from it. This does not need to be cryptographically secure, just good enough to detect changes.\n\t\treturn digest(algorithm, buffer);\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import { ZWaveError, ZWaveErrorCodes, digest } from \"@zwave-js/core\";\nimport {\n\tBytes,\n\ttype JSONObject,\n\tenumFilesRecursive,\n\tformatId,\n\tgetenv,\n\tnum2hex,\n\tpadVersion,\n\tpathExists,\n\tpick,\n\treadTextFile,\n\tstringify,\n\twriteTextFile,\n} from \"@zwave-js/shared\";\nimport type {\n\tReadFile,\n\tReadFileSystemInfo,\n\tWriteFile,\n} from \"@zwave-js/shared/bindings\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport path from \"pathe\";\nimport semverGt from \"semver/functions/gt.js\";\nimport { clearTemplateCache, readJsonWithTemplate } from \"../JsonTemplate.js\";\nimport type { ConfigLogger } from \"../Logger.js\";\nimport { configDir } from \"../utils.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"../utils_safe.js\";\nimport {\n\ttype AssociationConfig,\n\tConditionalAssociationConfig,\n} from \"./AssociationConfig.js\";\nimport { type CompatConfig, ConditionalCompatConfig } from \"./CompatConfig.js\";\nimport { evaluateDeep, validateCondition } from \"./ConditionalItem.js\";\nimport {\n\ttype ConditionalPrimitive,\n\tparseConditionalPrimitive,\n} from \"./ConditionalPrimitive.js\";\nimport {\n\tConditionalDeviceMetadata,\n\ttype DeviceMetadata,\n} from \"./DeviceMetadata.js\";\nimport {\n\tConditionalEndpointConfig,\n\ttype EndpointConfig,\n} from \"./EndpointConfig.js\";\nimport {\n\ttype ConditionalParamInfoMap,\n\ttype ParamInfoMap,\n\ttype ParamInformation,\n\tparseConditionalParamInformationMap,\n} from \"./ParamInformation.js\";\nimport type { DeviceID, FirmwareVersionRange } from \"./shared.js\";\n\nexport interface DeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport interface FulltextDeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tmanufacturer: string;\n\tlabel: string;\n\tdescription: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport const embeddedDevicesDir = path.join(configDir, \"devices\");\nconst fulltextIndexPath = path.join(embeddedDevicesDir, \"fulltext_index.json\");\n\nexport function getDevicesPaths(configDir: string): {\n\tdevicesDir: string;\n\tindexPath: string;\n} {\n\tconst devicesDir = path.join(configDir, \"devices\");\n\tconst indexPath = path.join(devicesDir, \"index.json\");\n\treturn { devicesDir, indexPath };\n}\n\nexport type DeviceConfigIndex = DeviceConfigIndexEntry[];\nexport type FulltextDeviceConfigIndex = FulltextDeviceConfigIndexEntry[];\n\nasync function hasChangedDeviceFiles(\n\tfs: ReadFileSystemInfo,\n\tdevicesRoot: string,\n\tdir: string,\n\tlastChange: Date,\n): Promise<boolean> {\n\t// Check if there are any files BUT index.json that were changed\n\t// or directories that were modified\n\tconst filesAndDirs = await fs.readDir(dir);\n\tfor (const f of filesAndDirs) {\n\t\tconst fullPath = path.join(dir, f);\n\n\t\tconst stat = await fs.stat(fullPath);\n\t\tif (\n\t\t\t(dir !== devicesRoot || f !== \"index.json\")\n\t\t\t&& (stat.isFile() || stat.isDirectory())\n\t\t\t&& stat.mtime > lastChange\n\t\t) {\n\t\t\treturn true;\n\t\t} else if (stat.isDirectory()) {\n\t\t\t// we need to go deeper!\n\t\t\tif (\n\t\t\t\tawait hasChangedDeviceFiles(\n\t\t\t\t\tfs,\n\t\t\t\t\tdevicesRoot,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tlastChange,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Read all device config files from a given directory and return them as index entries.\n * Does not update the index itself.\n */\nasync function generateIndex<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdevicesDir: string,\n\tisEmbedded: boolean,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string; rootDir?: string })[]> {\n\tconst index: (T & { filename: string; rootDir?: string })[] = [];\n\n\tclearTemplateCache();\n\tconst configFiles = await enumFilesRecursive(\n\t\tfs,\n\t\tdevicesDir,\n\t\t(file) =>\n\t\t\tfile.endsWith(\".json\")\n\t\t\t&& !file.endsWith(\"index.json\")\n\t\t\t&& !file.includes(\"/templates/\")\n\t\t\t&& !file.includes(\"\\\\templates\\\\\"),\n\t);\n\n\t// Add the embedded devices dir as a fallback if necessary\n\tconst fallbackDirs = devicesDir !== embeddedDevicesDir\n\t\t? [embeddedDevicesDir]\n\t\t: undefined;\n\n\tfor (const file of configFiles) {\n\t\tconst relativePath = path\n\t\t\t.relative(devicesDir, file)\n\t\t\t.replaceAll(\"\\\\\", \"/\");\n\t\t// Try parsing the file\n\t\ttry {\n\t\t\tconst config = await DeviceConfig.from(\n\t\t\t\tfs,\n\t\t\t\tfile,\n\t\t\t\tisEmbedded,\n\t\t\t\t{\n\t\t\t\t\trootDir: devicesDir,\n\t\t\t\t\tfallbackDirs,\n\t\t\t\t\trelative: true,\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Add the file to the index\n\t\t\tindex.push(\n\t\t\t\t...extractIndexEntries(config).map((entry) => {\n\t\t\t\t\tconst ret: T & { filename: string; rootDir?: string } = {\n\t\t\t\t\t\t...entry,\n\t\t\t\t\t\tfilename: relativePath,\n\t\t\t\t\t};\n\t\t\t\t\t// Only add the root dir to the index if necessary\n\t\t\t\t\tif (devicesDir !== embeddedDevicesDir) {\n\t\t\t\t\t\tret.rootDir = devicesDir;\n\t\t\t\t\t}\n\t\t\t\t\treturn ret;\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tconst message = `Error parsing config file ${relativePath}: ${\n\t\t\t\t(e as Error).message\n\t\t\t}`;\n\t\t\t// Crash hard during tests, just print an error when in production systems.\n\t\t\t// A user could have changed a config file\n\t\t\tif (process.env.NODE_ENV === \"test\" || !!getenv(\"CI\")) {\n\t\t\t\tthrow new ZWaveError(message, ZWaveErrorCodes.Config_Invalid);\n\t\t\t} else {\n\t\t\t\tlogger?.print(message, \"error\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn index;\n}\n\nasync function loadDeviceIndexShared<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tdevicesDir: string,\n\tindexPath: string,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string })[]> {\n\t// The index file needs to be regenerated if it does not exist\n\tlet needsUpdate = !(await pathExists(fs, indexPath));\n\tlet index: (T & { filename: string })[] | undefined;\n\tlet mtimeIndex: Date | undefined;\n\t// ...or if cannot be parsed\n\tif (!needsUpdate) {\n\t\ttry {\n\t\t\tconst fileContents = await readTextFile(fs, indexPath, \"utf8\");\n\t\t\tindex = JSON5.parse(fileContents);\n\t\t\tmtimeIndex = (await fs.stat(indexPath)).mtime;\n\t\t} catch {\n\t\t\tlogger?.print(\n\t\t\t\t\"Error while parsing index file - regenerating...\",\n\t\t\t\t\"warn\",\n\t\t\t);\n\t\t\tneedsUpdate = true;\n\t\t} finally {\n\t\t\tif (!index) {\n\t\t\t\tlogger?.print(\n\t\t\t\t\t\"Index file was malformed - regenerating...\",\n\t\t\t\t\t\"warn\",\n\t\t\t\t);\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ...or if there were any changes in the file system\n\tif (!needsUpdate) {\n\t\tneedsUpdate = await hasChangedDeviceFiles(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\tdevicesDir,\n\t\t\tmtimeIndex!,\n\t\t);\n\t\tif (needsUpdate) {\n\t\t\tlogger?.print(\n\t\t\t\t\"Device configuration files on disk changed - regenerating index...\",\n\t\t\t\t\"verbose\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (needsUpdate) {\n\t\t// Read all files from disk and generate an index\n\t\tindex = await generateIndex(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\ttrue,\n\t\t\textractIndexEntries,\n\t\t\tlogger,\n\t\t);\n\t\t// Save the index to disk\n\t\ttry {\n\t\t\tawait writeTextFile(\n\t\t\t\tfs,\n\t\t\t\tpath.join(indexPath),\n\t\t\t\t`// This file is auto-generated. DO NOT edit it by hand if you don't know what you're doing!\"\n${stringify(index, \"\\t\")}\n`,\n\t\t\t\t\"utf8\",\n\t\t\t);\n\t\t\tlogger?.print(\"Device index regenerated\", \"verbose\");\n\t\t} catch (e) {\n\t\t\tlogger?.print(\n\t\t\t\t`Writing the device index to disk failed: ${\n\t\t\t\t\t(e as Error).message\n\t\t\t\t}`,\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn index!;\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function generatePriorityDeviceIndex(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdeviceConfigPriorityDir: string,\n\tlogger?: ConfigLogger,\n): Promise<DeviceConfigIndex> {\n\treturn (\n\t\tawait generateIndex(\n\t\t\tfs,\n\t\t\tdeviceConfigPriorityDir,\n\t\t\tfalse,\n\t\t\t(config) =>\n\t\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\t\tmanufacturerId: formatId(\n\t\t\t\t\t\tconfig.manufacturerId.toString(16),\n\t\t\t\t\t),\n\t\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\t\tlabel: config.label,\n\t\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\t\trootDir: deviceConfigPriorityDir,\n\t\t\t\t})),\n\t\t\tlogger,\n\t\t)\n\t).map(({ filename, ...entry }) => ({\n\t\t...entry,\n\t\t// The generated index makes the filenames relative to the given directory\n\t\t// but we need them to be absolute\n\t\tfilename: path.join(deviceConfigPriorityDir, filename),\n\t}));\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n\texternalConfigDir?: string,\n): Promise<DeviceConfigIndex> {\n\tconst { devicesDir, indexPath } = getDevicesPaths(\n\t\texternalConfigDir || configDir,\n\t);\n\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tdevicesDir,\n\t\tindexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\n/**\n * @internal\n * Loads the full text index file to quickly search the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadFulltextDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n): Promise<FulltextDeviceConfigIndex> {\n\t// This method is not meant to operate with the external device index!\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tembeddedDevicesDir,\n\t\tfulltextIndexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tdescription: config.description,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\trootDir: embeddedDevicesDir,\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\nfunction isHexKeyWith4Digits(val: any): val is string {\n\treturn typeof val === \"string\" && hexKeyRegex4Digits.test(val);\n}\n\nconst firmwareVersionRegex = /^\\d{1,3}\\.\\d{1,3}(\\.\\d{1,3})?$/;\nfunction isFirmwareVersion(val: any): val is string {\n\treturn (\n\t\ttypeof val === \"string\"\n\t\t&& firmwareVersionRegex.test(val)\n\t\t&& val\n\t\t\t.split(\".\")\n\t\t\t.map((str) => parseInt(str, 10))\n\t\t\t.every((num) => num >= 0 && num <= 255)\n\t);\n}\n\n/** This class represents a device config entry whose conditional settings have not been evaluated yet */\nexport class ConditionalDeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t},\n\t): Promise<ConditionalDeviceConfig> {\n\t\tconst { relative, rootDir } = options;\n\n\t\tconst relativePath = relative\n\t\t\t? path.relative(rootDir, filename).replaceAll(\"\\\\\", \"/\")\n\t\t\t: filename;\n\t\tconst json = await readJsonWithTemplate(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\t[\n\t\t\t\toptions.rootDir,\n\t\t\t\t...(options.fallbackDirs ?? []),\n\t\t\t],\n\t\t);\n\t\treturn new ConditionalDeviceConfig(relativePath, isEmbedded, json);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tdefinition: JSONObject,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\n\t\tif (!isHexKeyWith4Digits(definition.manufacturerId)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nmanufacturer id must be a lowercase hexadecimal number with 4 digits`,\n\t\t\t);\n\t\t}\n\t\tthis.manufacturerId = parseInt(definition.manufacturerId, 16);\n\n\t\tfor (const prop of [\"manufacturer\", \"label\", \"description\"] as const) {\n\t\t\tthis[prop] = parseConditionalPrimitive(\n\t\t\t\tfilename,\n\t\t\t\t\"string\",\n\t\t\t\tprop,\n\t\t\t\tdefinition[prop],\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!isArray(definition.devices)\n\t\t\t|| !(definition.devices as any[]).every(\n\t\t\t\t(dev: unknown) =>\n\t\t\t\t\tisObject(dev)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productType)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productId),\n\t\t\t)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\ndevices is malformed (not an object or type/id that is not a lowercase 4-digit hex key)`,\n\t\t\t);\n\t\t}\n\t\tthis.devices = (definition.devices as any[]).map(\n\t\t\t({ productType, productId }) => ({\n\t\t\t\tproductType: parseInt(productType, 16),\n\t\t\t\tproductId: parseInt(productId, 16),\n\t\t\t}),\n\t\t);\n\n\t\tif (\n\t\t\t!isObject(definition.firmwareVersion)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.min)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.max)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion is malformed or invalid. Must be x.y or x.y.z where x, y, and z are integers between 0 and 255`,\n\t\t\t);\n\t\t} else {\n\t\t\tconst { min, max } = definition.firmwareVersion;\n\t\t\tif (semverGt(padVersion(min), padVersion(max))) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion.min ${min} must not be greater than firmwareVersion.max ${max}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.firmwareVersion = { min, max };\n\t\t}\n\n\t\tif (\n\t\t\tdefinition.preferred != undefined\n\t\t\t&& definition.preferred !== true\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\npreferred must be true or omitted`,\n\t\t\t);\n\t\t}\n\t\tthis.preferred = !!definition.preferred;\n\n\t\tif (definition.endpoints != undefined) {\n\t\t\tconst endpoints = new Map<number, ConditionalEndpointConfig>();\n\t\t\tif (!isObject(definition.endpoints)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nendpoints is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, ep] of Object.entries(definition.endpoints)) {\n\t\t\t\tif (!/^\\d+$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric endpoint index \"${key}\" in endpoints`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst epIndex = parseInt(key, 10);\n\t\t\t\tendpoints.set(\n\t\t\t\t\tepIndex,\n\t\t\t\t\tnew ConditionalEndpointConfig(this, epIndex, ep as any),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.endpoints = endpoints;\n\t\t}\n\n\t\tif (definition.associations != undefined) {\n\t\t\tconst associations = new Map<\n\t\t\t\tnumber,\n\t\t\t\tConditionalAssociationConfig\n\t\t\t>();\n\t\t\tif (!isObject(definition.associations)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nassociations is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (\n\t\t\t\tconst [key, assocDefinition] of Object.entries(\n\t\t\t\t\tdefinition.associations,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tif (!/^[1-9][0-9]*$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric group id \"${key}\" in associations`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst keyNum = parseInt(key, 10);\n\t\t\t\tassociations.set(\n\t\t\t\t\tkeyNum,\n\t\t\t\t\tnew ConditionalAssociationConfig(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tkeyNum,\n\t\t\t\t\t\tassocDefinition as any,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.associations = associations;\n\t\t}\n\n\t\tif (definition.paramInformation != undefined) {\n\t\t\tthis.paramInformation = parseConditionalParamInformationMap(\n\t\t\t\tdefinition,\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\n\t\tif (definition.proprietary != undefined) {\n\t\t\tif (!isObject(definition.proprietary)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nproprietary is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.proprietary = definition.proprietary;\n\t\t}\n\n\t\tif (definition.compat != undefined) {\n\t\t\tif (\n\t\t\t\tisArray(definition.compat)\n\t\t\t\t&& definition.compat.every((item: any) => isObject(item))\n\t\t\t) {\n\t\t\t\t// Make sure all conditions are valid\n\t\t\t\tfor (const entry of definition.compat) {\n\t\t\t\t\tvalidateCondition(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\t`At least one entry of compat contains an`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.compat = definition.compat.map(\n\t\t\t\t\t(item: any) => new ConditionalCompatConfig(filename, item),\n\t\t\t\t);\n\t\t\t} else if (isObject(definition.compat)) {\n\t\t\t\tthis.compat = new ConditionalCompatConfig(\n\t\t\t\t\tfilename,\n\t\t\t\t\tdefinition.compat,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\ncompat must be an object or any array of conditional objects`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.metadata != undefined) {\n\t\t\tif (!isObject(definition.metadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nmetadata is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.metadata = new ConditionalDeviceMetadata(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.metadata,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly filename: string;\n\n\tpublic readonly manufacturer!: ConditionalPrimitive<string>;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label!: ConditionalPrimitive<string>;\n\tpublic readonly description!: ConditionalPrimitive<string>;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, ConditionalEndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<\n\t\tnumber,\n\t\tConditionalAssociationConfig\n\t>;\n\tpublic readonly paramInformation?: ConditionalParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?:\n\t\t| ConditionalCompatConfig\n\t\t| ConditionalCompatConfig[];\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: ConditionalDeviceMetadata;\n\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\n\tpublic evaluate(deviceId?: DeviceID): DeviceConfig {\n\t\treturn new DeviceConfig(\n\t\t\tthis.filename,\n\t\t\tthis.isEmbedded,\n\t\t\tevaluateDeep(this.manufacturer, deviceId),\n\t\t\tthis.manufacturerId,\n\t\t\tevaluateDeep(this.label, deviceId),\n\t\t\tevaluateDeep(this.description, deviceId),\n\t\t\tthis.devices,\n\t\t\tthis.firmwareVersion,\n\t\t\tthis.preferred,\n\t\t\tevaluateDeep(this.endpoints, deviceId),\n\t\t\tevaluateDeep(this.associations, deviceId),\n\t\t\tevaluateDeep(this.paramInformation, deviceId),\n\t\t\tthis.proprietary,\n\t\t\tevaluateDeep(this.compat, deviceId),\n\t\t\tevaluateDeep(this.metadata, deviceId),\n\t\t);\n\t}\n}\n\nexport class DeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t\tdeviceId?: DeviceID;\n\t\t},\n\t): Promise<DeviceConfig> {\n\t\tconst ret = await ConditionalDeviceConfig.from(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\tisEmbedded,\n\t\t\toptions,\n\t\t);\n\t\treturn ret.evaluate(options.deviceId);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tmanufacturer: string,\n\t\tmanufacturerId: number,\n\t\tlabel: string,\n\t\tdescription: string,\n\t\tdevices: readonly {\n\t\t\tproductType: number;\n\t\t\tproductId: number;\n\t\t}[],\n\t\tfirmwareVersion: FirmwareVersionRange,\n\t\tpreferred: boolean,\n\t\tendpoints?: ReadonlyMap<number, EndpointConfig>,\n\t\tassociations?: ReadonlyMap<number, AssociationConfig>,\n\t\tparamInformation?: ParamInfoMap,\n\t\tproprietary?: Record<string, unknown>,\n\t\tcompat?: CompatConfig,\n\t\tmetadata?: DeviceMetadata,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\t\tthis.manufacturer = manufacturer;\n\t\tthis.manufacturerId = manufacturerId;\n\t\tthis.label = label;\n\t\tthis.description = description;\n\t\tthis.devices = devices;\n\t\tthis.firmwareVersion = firmwareVersion;\n\t\tthis.preferred = preferred;\n\t\tthis.endpoints = endpoints;\n\t\tthis.associations = associations;\n\t\tthis.paramInformation = paramInformation;\n\t\tthis.proprietary = proprietary;\n\t\tthis.compat = compat;\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic readonly filename: string;\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\tpublic readonly manufacturer: string;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label: string;\n\tpublic readonly description: string;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, EndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<number, AssociationConfig>;\n\tpublic readonly paramInformation?: ParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?: CompatConfig;\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: DeviceMetadata;\n\n\t/** Returns the association config for a given endpoint */\n\tpublic getAssociationConfigForEndpoint(\n\t\tendpointIndex: number,\n\t\tgroup: number,\n\t): AssociationConfig | undefined {\n\t\tif (endpointIndex === 0) {\n\t\t\t// The root endpoint's associations may be configured separately or as part of \"endpoints\"\n\t\t\treturn (\n\t\t\t\tthis.associations?.get(group)\n\t\t\t\t\t?? this.endpoints?.get(0)?.associations?.get(group)\n\t\t\t);\n\t\t} else {\n\t\t\t// The other endpoints can only have a configuration as part of \"endpoints\"\n\t\t\treturn this.endpoints?.get(endpointIndex)?.associations?.get(group);\n\t\t}\n\t}\n\n\tprivate getHashable(): Uint8Array {\n\t\t// We only need to compare the information that is persisted elsewhere:\n\t\t// - config parameters\n\t\t// - functional association settings\n\t\t// - CC-related compat flags\n\n\t\tlet hashable: Record<string, any> = {\n\t\t\t// endpoints: {\n\t\t\t// \tassociations: {},\n\t\t\t// \tparamInformation: []\n\t\t\t// },\n\t\t\t// proprietary: {},\n\t\t\t// compat: {},\n\t\t};\n\n\t\tconst sortObject = (obj: Record<string, any>) => {\n\t\t\tconst ret: Record<string, any> = {};\n\t\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\t\tret[key] = obj[key];\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\n\t\tconst cloneAssociationConfig = (a: AssociationConfig) => {\n\t\t\treturn sortObject(\n\t\t\t\tpick(a, [\"maxNodes\", \"multiChannel\", \"isLifeline\"]),\n\t\t\t);\n\t\t};\n\t\tconst cloneAssociationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ReadonlyMap<number, AssociationConfig> | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\ttarget.associations = {};\n\t\t\tfor (const [key, value] of map) {\n\t\t\t\ttarget.associations[key] = cloneAssociationConfig(value);\n\t\t\t}\n\t\t\ttarget.associations = sortObject(target.associations);\n\t\t};\n\n\t\tconst cloneParamInformationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ParamInfoMap | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\tconst getParamKey = (param: ParamInformation) =>\n\t\t\t\t`${param.parameterNumber}${\n\t\t\t\t\tparam.valueBitMask ? `[${num2hex(param.valueBitMask)}]` : \"\"\n\t\t\t\t}`;\n\t\t\ttarget.paramInformation = [...map.values()].sort((a, b) =>\n\t\t\t\tgetParamKey(a).localeCompare(getParamKey(b))\n\t\t\t);\n\t\t};\n\n\t\t// Clone associations and param information on the root (ep 0) and endpoints\n\t\t{\n\t\t\tlet ep0: Record<string, any> = {};\n\t\t\tcloneAssociationMap(ep0, this.associations);\n\t\t\tcloneParamInformationMap(ep0, this.paramInformation);\n\t\t\tep0 = sortObject(ep0);\n\n\t\t\tif (Object.keys(ep0).length > 0) {\n\t\t\t\thashable.endpoints ??= {};\n\t\t\t\thashable.endpoints[0] = ep0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.endpoints) {\n\t\t\tfor (const [index, endpoint] of this.endpoints) {\n\t\t\t\tlet ep: Record<string, any> = {};\n\n\t\t\t\tcloneAssociationMap(ep, endpoint.associations);\n\t\t\t\tcloneParamInformationMap(ep, endpoint.paramInformation);\n\n\t\t\t\tep = sortObject(ep);\n\n\t\t\t\tif (Object.keys(ep).length > 0) {\n\t\t\t\t\thashable.endpoints ??= {};\n\t\t\t\t\thashable.endpoints[index] = ep;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Clone proprietary config\n\t\tif (this.proprietary && Object.keys(this.proprietary).length > 0) {\n\t\t\thashable.proprietary = sortObject({ ...this.proprietary });\n\t\t}\n\n\t\t// Clone relevant compat flags\n\t\tif (this.compat) {\n\t\t\tlet c: Record<string, any> = {};\n\n\t\t\t// Copy some simple flags over\n\t\t\tfor (\n\t\t\t\tconst prop of [\n\t\t\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\t\t\"mapBasicSet\",\n\t\t\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\t\t\"preserveEndpoints\",\n\t\t\t\t\t\"removeEndpoints\",\n\t\t\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\t] as const\n\t\t\t) {\n\t\t\t\tif (this.compat[prop] != undefined) {\n\t\t\t\t\tc[prop] = this.compat[prop];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy other, more complex flags\n\t\t\tif (this.compat.overrideQueries) {\n\t\t\t\tc.overrideQueries = Object.fromEntries(\n\t\t\t\t\tthis.compat.overrideQueries[\"overrides\"],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.addCCs) {\n\t\t\t\tc.addCCs = Object.fromEntries(\n\t\t\t\t\t[...this.compat.addCCs].map(([ccId, def]) => [\n\t\t\t\t\t\tccId,\n\t\t\t\t\t\tObject.fromEntries(def.endpoints),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.removeCCs) {\n\t\t\t\tc.removeCCs = Object.fromEntries(this.compat.removeCCs);\n\t\t\t}\n\t\t\tif (this.compat.treatSetAsReport) {\n\t\t\t\tc.treatSetAsReport = [...this.compat.treatSetAsReport].sort();\n\t\t\t}\n\n\t\t\tc = sortObject(c);\n\t\t\tif (Object.keys(c).length > 0) {\n\t\t\t\thashable.compat = c;\n\t\t\t}\n\t\t}\n\n\t\thashable = sortObject(hashable);\n\n\t\treturn Bytes.from(JSON.stringify(hashable), \"utf8\");\n\t}\n\n\t/**\n\t * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.\n\t */\n\tpublic getHash(\n\t\talgorithm: \"md5\" | \"sha-256\" = \"sha-256\",\n\t): Promise<Uint8Array> {\n\t\t// Figure out what to hash\n\t\tconst buffer = this.getHashable();\n\n\t\t// And create a hash from it. This does not need to be cryptographically secure, just good enough to detect changes.\n\t\treturn digest(algorithm, buffer);\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path", "configDir", "JSON5", "semverGt"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type JSONObject } from "@zwave-js/shared
|
|
1
|
+
import { type JSONObject } from "@zwave-js/shared";
|
|
2
2
|
import { type ConditionalItem } from "./ConditionalItem.js";
|
|
3
3
|
import { type ConditionalPrimitive } from "./ConditionalPrimitive.js";
|
|
4
4
|
import type { DeviceID } from "./shared.js";
|
|
@@ -23,7 +23,7 @@ __export(DeviceMetadata_exports, {
|
|
|
23
23
|
ConditionalDeviceMetadata: () => ConditionalDeviceMetadata
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(DeviceMetadata_exports);
|
|
26
|
-
var
|
|
26
|
+
var import_shared = require("@zwave-js/shared");
|
|
27
27
|
var import_typeguards = require("alcalzone-shared/typeguards");
|
|
28
28
|
var import_utils_safe = require("../utils_safe.js");
|
|
29
29
|
var import_ConditionalItem = require("./ConditionalItem.js");
|
|
@@ -108,7 +108,7 @@ class ConditionalDeviceComment {
|
|
|
108
108
|
evaluateCondition(deviceId) {
|
|
109
109
|
if (!(0, import_ConditionalItem.conditionApplies)(this, deviceId))
|
|
110
110
|
return;
|
|
111
|
-
return (0,
|
|
111
|
+
return (0, import_shared.pick)(this, ["level", "text"]);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
// Annotate the CommonJS export names for ESM import in node:
|