@zwave-js/config 14.0.0 → 14.1.0

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.
Files changed (43) hide show
  1. package/build/cjs/JsonTemplate.js +1 -1
  2. package/build/cjs/JsonTemplate.js.map +2 -2
  3. package/build/cjs/Manufacturers.js +1 -1
  4. package/build/cjs/Manufacturers.js.map +1 -1
  5. package/build/cjs/_version.d.ts +1 -1
  6. package/build/cjs/_version.js +1 -1
  7. package/build/cjs/_version.js.map +1 -1
  8. package/build/cjs/devices/CompatConfig.js +1 -1
  9. package/build/cjs/devices/CompatConfig.js.map +1 -1
  10. package/build/cjs/devices/ConditionalItem.js +1 -1
  11. package/build/cjs/devices/ConditionalItem.js.map +1 -1
  12. package/build/cjs/devices/ConditionalPrimitive.js +1 -1
  13. package/build/cjs/devices/ConditionalPrimitive.js.map +1 -1
  14. package/build/cjs/devices/DeviceConfig.js +1 -1
  15. package/build/cjs/devices/DeviceConfig.js.map +1 -1
  16. package/build/cjs/devices/DeviceMetadata.js +1 -1
  17. package/build/cjs/devices/DeviceMetadata.js.map +1 -1
  18. package/build/cjs/devices/EndpointConfig.js +1 -1
  19. package/build/cjs/devices/EndpointConfig.js.map +1 -1
  20. package/build/cjs/devices/ParamInformation.js +1 -1
  21. package/build/cjs/devices/ParamInformation.js.map +1 -1
  22. package/build/cjs/utils.js.map +1 -1
  23. package/build/esm/JsonTemplate.js +1 -1
  24. package/build/esm/JsonTemplate.js.map +1 -1
  25. package/build/esm/Manufacturers.js +1 -1
  26. package/build/esm/Manufacturers.js.map +1 -1
  27. package/build/esm/_version.d.ts +1 -1
  28. package/build/esm/_version.js +1 -1
  29. package/build/esm/devices/CompatConfig.js +1 -1
  30. package/build/esm/devices/CompatConfig.js.map +1 -1
  31. package/build/esm/devices/ConditionalItem.js +1 -1
  32. package/build/esm/devices/ConditionalItem.js.map +1 -1
  33. package/build/esm/devices/ConditionalPrimitive.js +1 -1
  34. package/build/esm/devices/ConditionalPrimitive.js.map +1 -1
  35. package/build/esm/devices/DeviceConfig.js +1 -1
  36. package/build/esm/devices/DeviceConfig.js.map +1 -1
  37. package/build/esm/devices/DeviceMetadata.js +1 -1
  38. package/build/esm/devices/DeviceMetadata.js.map +1 -1
  39. package/build/esm/devices/EndpointConfig.js +1 -1
  40. package/build/esm/devices/EndpointConfig.js.map +1 -1
  41. package/build/esm/devices/ParamInformation.js +1 -1
  42. package/build/esm/devices/ParamInformation.js.map +1 -1
  43. package/package.json +6 -6
@@ -35,7 +35,7 @@ module.exports = __toCommonJS(JsonTemplate_exports);
35
35
  var import_safe = require("@zwave-js/core/safe");
36
36
  var import_shared = require("@zwave-js/shared");
37
37
  var import_safe2 = require("@zwave-js/shared/safe");
38
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
38
+ var import_typeguards = require("alcalzone-shared/typeguards");
39
39
  var import_json5 = __toESM(require("json5"), 1);
40
40
  var import_promises = __toESM(require("node:fs/promises"), 1);
41
41
  var path = __toESM(require("node:path"), 1);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/JsonTemplate.ts"],
4
- "sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core/safe\";\nimport { pathExists } from \"@zwave-js/shared\";\nimport { getErrorMessage } from \"@zwave-js/shared/safe\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards/index.js\";\nimport JSON5 from \"json5\";\nimport fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nconst IMPORT_KEY = \"$import\";\nconst importSpecifierRegex =\n\t/^(?<filename>(?:~\\/)?[\\w\\d\\/\\\\\\._-]+\\.json)?(?:#(?<selector>[\\w\\d\\/\\._-]+(?:\\[0x[0-9a-fA-F]+\\])?))?$/i;\n\ntype FileCache = Map<string, Record<string, unknown>>;\n\n// The template cache is used to speed up cases where the same files get parsed multiple times,\n// e.g. during config file linting. It should be cleared whenever the files need to be loaded fresh\n// from disk, like when creating an index\nconst templateCache: FileCache = new Map();\nexport function clearTemplateCache(): void {\n\ttemplateCache.clear();\n}\n\n/** Parses a JSON file with $import keys and replaces them with the selected objects */\nexport async function readJsonWithTemplate(\n\tfilename: string,\n\trootDirs?: string | string[],\n): Promise<Record<string, unknown>> {\n\tif (!(await pathExists(filename))) {\n\t\tthrow new ZWaveError(\n\t\t\t`Could not open config file ${filename}: not found!`,\n\t\t\tZWaveErrorCodes.Config_NotFound,\n\t\t);\n\t}\n\n\tif (typeof rootDirs === \"string\") rootDirs = [rootDirs];\n\n\t// Try to use the cached versions of the template files to speed up the loading\n\tconst fileCache = new Map(templateCache);\n\tconst ret = await readJsonWithTemplateInternal(\n\t\tfilename,\n\t\tundefined,\n\t\t[],\n\t\tfileCache,\n\t\trootDirs,\n\t);\n\n\t// Only remember the cached templates, not the individual files to save RAM\n\tfor (const [filename, cached] of fileCache) {\n\t\tif (/[\\\\/]templates[\\\\/]/.test(filename)) {\n\t\t\ttemplateCache.set(filename, cached);\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nfunction assertImportSpecifier(\n\tval: unknown,\n\tsource?: string,\n): asserts val is string {\n\tif (typeof val !== \"string\") {\n\t\tthrow new ZWaveError(\n\t\t\t`Invalid import specifier ${String(val)}!${\n\t\t\t\tsource != undefined ? ` Source: ${source}` : \"\"\n\t\t\t}`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\tif (!importSpecifierRegex.test(val)) {\n\t\tthrow new ZWaveError(\n\t\t\t`Import specifier \"${val}\" is invalid!${\n\t\t\t\tsource != undefined ? ` Source: ${source}` : \"\"\n\t\t\t}`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n}\n\nfunction getImportSpecifier(filename: string, selector?: string): string {\n\tlet ret = filename;\n\tif (selector) ret += `#${selector}`;\n\treturn ret;\n}\n\nfunction select(\n\tobj: Record<string, unknown>,\n\tselector: string,\n): Record<string, unknown> {\n\tlet ret: Record<string, unknown> = obj;\n\tconst selectorParts = selector.split(\"/\").filter((s) => !!s);\n\tfor (const part of selectorParts) {\n\t\t// Special case for paramInformation selectors to select params by #\n\t\tif (isArray(ret)) {\n\t\t\tconst item = ret.find(\n\t\t\t\t(r) => isObject(r) && \"#\" in r && r[\"#\"] === part,\n\t\t\t);\n\t\t\tif (item != undefined) {\n\t\t\t\t// Don't copy the param number\n\t\t\t\tconst { [\"#\"]: _, ...rest } = item as any;\n\t\t\t\tret = rest;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// By default select the object property\n\t\tret = (ret as any)[part];\n\t}\n\tif (!isObject(ret)) {\n\t\tthrow new ZWaveError(\n\t\t\t`The import target \"${selector}\" is not an object!`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\treturn ret;\n}\n\nfunction getImportStack(\n\tvisited: string[],\n\tselector: string | undefined,\n): string {\n\tconst source = [...visited, selector ? `#${selector}` : undefined]\n\t\t.reverse()\n\t\t.filter((s) => !!s) as string[];\n\tif (source.length > 0) {\n\t\treturn `\\nImport stack: ${source.map((s) => `\\n in ${s}`).join(\"\")}`;\n\t}\n\treturn \"\";\n}\n\nasync function readJsonWithTemplateInternal(\n\tfilename: string,\n\tselector: string | undefined,\n\tvisited: string[],\n\tfileCache: FileCache,\n\trootDirs?: string[],\n): Promise<Record<string, unknown>> {\n\tfilename = path.normalize(filename);\n\n\t// If we're limited by one or more root directories, make sure the file is inside one of those\n\tif (rootDirs) {\n\t\tconst outsideAllRootDirs = rootDirs.every((rootDir) => {\n\t\t\tconst relativeToRoot = path.relative(rootDir, filename);\n\t\t\treturn relativeToRoot.startsWith(\"..\");\n\t\t});\n\n\t\tif (outsideAllRootDirs) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`Tried to import config file \"${filename}\" from outside all root directories: ${\n\t\t\t\t\trootDirs\n\t\t\t\t\t\t.map((d) => `\\n\u00B7 ${d}`)\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t}\n${getImportStack(visited, selector)}`,\n\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst specifier = getImportSpecifier(filename, selector);\n\tif (visited.includes(specifier)) {\n\t\tconst msg = `Circular $import in config files: ${\n\t\t\t[\n\t\t\t\t...visited,\n\t\t\t\tspecifier,\n\t\t\t].join(\" -> \")\n\t\t}\\n`;\n\t\t// process.stderr.write(msg + \"\\n\");\n\t\tthrow new ZWaveError(msg, ZWaveErrorCodes.Config_CircularImport);\n\t}\n\n\tlet json: Record<string, unknown>;\n\tif (fileCache.has(filename)) {\n\t\tjson = fileCache.get(filename)!;\n\t} else {\n\t\ttry {\n\t\t\tconst fileContent = await fs.readFile(filename, \"utf8\");\n\t\t\tjson = JSON5.parse(fileContent);\n\t\t\tfileCache.set(filename, json);\n\t\t} catch (e) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`Could not parse config file ${filename}: ${\n\t\t\t\t\tgetErrorMessage(\n\t\t\t\t\t\te,\n\t\t\t\t\t)\n\t\t\t\t}${getImportStack(visited, selector)}`,\n\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t);\n\t\t}\n\t}\n\t// Resolve the JSON imports for (a subset) of the file and return the compound file\n\treturn resolveJsonImports(\n\t\tselector ? select(json, selector) : json,\n\t\tfilename,\n\t\t[...visited, specifier],\n\t\tfileCache,\n\t\trootDirs,\n\t);\n}\n\n/** Replaces all `$import` properties in a JSON object with object spreads of the referenced file/property */\nasync function resolveJsonImports(\n\tjson: Record<string, unknown>,\n\tfilename: string,\n\tvisited: string[],\n\tfileCache: FileCache,\n\trootDirs?: string[],\n): Promise<Record<string, unknown>> {\n\tconst ret: Record<string, unknown> = {};\n\t// Loop through all properties and copy them to the resulting object\n\tfor (const [prop, val] of Object.entries(json)) {\n\t\tif (prop === IMPORT_KEY) {\n\t\t\t// This is an import statement. Make sure we're working with a string\n\t\t\tassertImportSpecifier(val, visited.join(\" -> \"));\n\t\t\tconst { filename: importFilename, selector } = importSpecifierRegex\n\t\t\t\t.exec(val)!.groups!;\n\n\t\t\t// Resolve the correct import path\n\t\t\tlet newFilename: string | undefined;\n\t\t\tif (importFilename) {\n\t\t\t\tif (importFilename.startsWith(\"~/\")) {\n\t\t\t\t\t// This is a special import specifier that is relative to the root directory\n\t\t\t\t\t// Try to find at least one root directory that contains the referenced file\n\t\t\t\t\tif (rootDirs) {\n\t\t\t\t\t\tfor (const rootDir of rootDirs) {\n\t\t\t\t\t\t\tnewFilename = path.join(\n\t\t\t\t\t\t\t\trootDir,\n\t\t\t\t\t\t\t\timportFilename.slice(2),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (await pathExists(newFilename)) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Try the next\n\t\t\t\t\t\t\t\tnewFilename = undefined!;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!newFilename) {\n\t\t\t\t\t\t\tthrow new ZWaveError(\n\t\t\t\t\t\t\t\t`Could not find the referenced file ${\n\t\t\t\t\t\t\t\t\timportFilename.slice(\n\t\t\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t} in any of the root directories: ${\n\t\t\t\t\t\t\t\t\trootDirs\n\t\t\t\t\t\t\t\t\t\t.map((d) => `\\n\u00B7 ${d}`)\n\t\t\t\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t\t\t\t}\\n${\n\t\t\t\t\t\t\t\t\tgetImportStack(\n\t\t\t\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t\t\tZWaveErrorCodes.Config_Invalid,\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\tthrow new ZWaveError(\n\t\t\t\t\t\t\t`An $import specifier cannot start with ~/ when no root directory is defined!${\n\t\t\t\t\t\t\t\tgetImportStack(\n\t\t\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewFilename = path.join(\n\t\t\t\t\t\tpath.dirname(filename),\n\t\t\t\t\t\timportFilename,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnewFilename = filename;\n\t\t\t}\n\n\t\t\t// const importFilename = path.join(path.dirname(filename), val);\n\t\t\tconst imported = await readJsonWithTemplateInternal(\n\t\t\t\tnewFilename,\n\t\t\t\tselector,\n\t\t\t\tvisited,\n\t\t\t\tfileCache,\n\t\t\t\trootDirs,\n\t\t\t);\n\t\t\tObject.assign(ret, imported);\n\t\t} else if (isObject(val)) {\n\t\t\t// We're looking at an object, recurse into it\n\t\t\tret[prop] = await resolveJsonImports(\n\t\t\t\tval,\n\t\t\t\tfilename,\n\t\t\t\tvisited,\n\t\t\t\tfileCache,\n\t\t\t\trootDirs,\n\t\t\t);\n\t\t} else if (isArray(val)) {\n\t\t\t// We're looking at an array, check if there are objects we need to recurse into\n\t\t\tconst vals: unknown[] = [];\n\t\t\tfor (const v of val) {\n\t\t\t\tif (isObject(v)) {\n\t\t\t\t\tvals.push(\n\t\t\t\t\t\tawait resolveJsonImports(\n\t\t\t\t\t\t\tv,\n\t\t\t\t\t\t\tfilename,\n\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\tfileCache,\n\t\t\t\t\t\t\trootDirs,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tvals.push(v);\n\t\t\t\t}\n\t\t\t}\n\t\t\tret[prop] = vals;\n\t\t} else {\n\t\t\tret[prop] = val;\n\t\t}\n\t}\n\treturn ret;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core/safe\";\nimport { pathExists } from \"@zwave-js/shared\";\nimport { getErrorMessage } from \"@zwave-js/shared/safe\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nconst IMPORT_KEY = \"$import\";\nconst importSpecifierRegex =\n\t/^(?<filename>(?:~\\/)?[\\w\\d\\/\\\\\\._-]+\\.json)?(?:#(?<selector>[\\w\\d\\/\\._-]+(?:\\[0x[0-9a-fA-F]+\\])?))?$/i;\n\ntype FileCache = Map<string, Record<string, unknown>>;\n\n// The template cache is used to speed up cases where the same files get parsed multiple times,\n// e.g. during config file linting. It should be cleared whenever the files need to be loaded fresh\n// from disk, like when creating an index\nconst templateCache: FileCache = new Map();\nexport function clearTemplateCache(): void {\n\ttemplateCache.clear();\n}\n\n/** Parses a JSON file with $import keys and replaces them with the selected objects */\nexport async function readJsonWithTemplate(\n\tfilename: string,\n\trootDirs?: string | string[],\n): Promise<Record<string, unknown>> {\n\tif (!(await pathExists(filename))) {\n\t\tthrow new ZWaveError(\n\t\t\t`Could not open config file ${filename}: not found!`,\n\t\t\tZWaveErrorCodes.Config_NotFound,\n\t\t);\n\t}\n\n\tif (typeof rootDirs === \"string\") rootDirs = [rootDirs];\n\n\t// Try to use the cached versions of the template files to speed up the loading\n\tconst fileCache = new Map(templateCache);\n\tconst ret = await readJsonWithTemplateInternal(\n\t\tfilename,\n\t\tundefined,\n\t\t[],\n\t\tfileCache,\n\t\trootDirs,\n\t);\n\n\t// Only remember the cached templates, not the individual files to save RAM\n\tfor (const [filename, cached] of fileCache) {\n\t\tif (/[\\\\/]templates[\\\\/]/.test(filename)) {\n\t\t\ttemplateCache.set(filename, cached);\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nfunction assertImportSpecifier(\n\tval: unknown,\n\tsource?: string,\n): asserts val is string {\n\tif (typeof val !== \"string\") {\n\t\tthrow new ZWaveError(\n\t\t\t`Invalid import specifier ${String(val)}!${\n\t\t\t\tsource != undefined ? ` Source: ${source}` : \"\"\n\t\t\t}`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\tif (!importSpecifierRegex.test(val)) {\n\t\tthrow new ZWaveError(\n\t\t\t`Import specifier \"${val}\" is invalid!${\n\t\t\t\tsource != undefined ? ` Source: ${source}` : \"\"\n\t\t\t}`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n}\n\nfunction getImportSpecifier(filename: string, selector?: string): string {\n\tlet ret = filename;\n\tif (selector) ret += `#${selector}`;\n\treturn ret;\n}\n\nfunction select(\n\tobj: Record<string, unknown>,\n\tselector: string,\n): Record<string, unknown> {\n\tlet ret: Record<string, unknown> = obj;\n\tconst selectorParts = selector.split(\"/\").filter((s) => !!s);\n\tfor (const part of selectorParts) {\n\t\t// Special case for paramInformation selectors to select params by #\n\t\tif (isArray(ret)) {\n\t\t\tconst item = (ret as any).find(\n\t\t\t\t(r: any) => isObject(r) && \"#\" in r && r[\"#\"] === part,\n\t\t\t);\n\t\t\tif (item != undefined) {\n\t\t\t\t// Don't copy the param number\n\t\t\t\tconst { [\"#\"]: _, ...rest } = item;\n\t\t\t\tret = rest;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\t// By default select the object property\n\t\tret = (ret as any)[part];\n\t}\n\tif (!isObject(ret)) {\n\t\tthrow new ZWaveError(\n\t\t\t`The import target \"${selector}\" is not an object!`,\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\treturn ret;\n}\n\nfunction getImportStack(\n\tvisited: string[],\n\tselector: string | undefined,\n): string {\n\tconst source = [...visited, selector ? `#${selector}` : undefined]\n\t\t.reverse()\n\t\t.filter((s) => !!s) as string[];\n\tif (source.length > 0) {\n\t\treturn `\\nImport stack: ${source.map((s) => `\\n in ${s}`).join(\"\")}`;\n\t}\n\treturn \"\";\n}\n\nasync function readJsonWithTemplateInternal(\n\tfilename: string,\n\tselector: string | undefined,\n\tvisited: string[],\n\tfileCache: FileCache,\n\trootDirs?: string[],\n): Promise<Record<string, unknown>> {\n\tfilename = path.normalize(filename);\n\n\t// If we're limited by one or more root directories, make sure the file is inside one of those\n\tif (rootDirs) {\n\t\tconst outsideAllRootDirs = rootDirs.every((rootDir) => {\n\t\t\tconst relativeToRoot = path.relative(rootDir, filename);\n\t\t\treturn relativeToRoot.startsWith(\"..\");\n\t\t});\n\n\t\tif (outsideAllRootDirs) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`Tried to import config file \"${filename}\" from outside all root directories: ${\n\t\t\t\t\trootDirs\n\t\t\t\t\t\t.map((d) => `\\n\u00B7 ${d}`)\n\t\t\t\t\t\t.join(\"\")\n\t\t\t\t}\n${getImportStack(visited, selector)}`,\n\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst specifier = getImportSpecifier(filename, selector);\n\tif (visited.includes(specifier)) {\n\t\tconst msg = `Circular $import in config files: ${\n\t\t\t[\n\t\t\t\t...visited,\n\t\t\t\tspecifier,\n\t\t\t].join(\" -> \")\n\t\t}\\n`;\n\t\t// process.stderr.write(msg + \"\\n\");\n\t\tthrow new ZWaveError(msg, ZWaveErrorCodes.Config_CircularImport);\n\t}\n\n\tlet json: Record<string, unknown>;\n\tif (fileCache.has(filename)) {\n\t\tjson = fileCache.get(filename)!;\n\t} else {\n\t\ttry {\n\t\t\tconst fileContent = await fs.readFile(filename, \"utf8\");\n\t\t\tjson = JSON5.parse(fileContent);\n\t\t\tfileCache.set(filename, json);\n\t\t} catch (e) {\n\t\t\tthrow new ZWaveError(\n\t\t\t\t`Could not parse config file ${filename}: ${\n\t\t\t\t\tgetErrorMessage(\n\t\t\t\t\t\te,\n\t\t\t\t\t)\n\t\t\t\t}${getImportStack(visited, selector)}`,\n\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t);\n\t\t}\n\t}\n\t// Resolve the JSON imports for (a subset) of the file and return the compound file\n\treturn resolveJsonImports(\n\t\tselector ? select(json, selector) : json,\n\t\tfilename,\n\t\t[...visited, specifier],\n\t\tfileCache,\n\t\trootDirs,\n\t);\n}\n\n/** Replaces all `$import` properties in a JSON object with object spreads of the referenced file/property */\nasync function resolveJsonImports(\n\tjson: Record<string, unknown>,\n\tfilename: string,\n\tvisited: string[],\n\tfileCache: FileCache,\n\trootDirs?: string[],\n): Promise<Record<string, unknown>> {\n\tconst ret: Record<string, unknown> = {};\n\t// Loop through all properties and copy them to the resulting object\n\tfor (const [prop, val] of Object.entries(json)) {\n\t\tif (prop === IMPORT_KEY) {\n\t\t\t// This is an import statement. Make sure we're working with a string\n\t\t\tassertImportSpecifier(val, visited.join(\" -> \"));\n\t\t\tconst { filename: importFilename, selector } = importSpecifierRegex\n\t\t\t\t.exec(val)!.groups!;\n\n\t\t\t// Resolve the correct import path\n\t\t\tlet newFilename: string | undefined;\n\t\t\tif (importFilename) {\n\t\t\t\tif (importFilename.startsWith(\"~/\")) {\n\t\t\t\t\t// This is a special import specifier that is relative to the root directory\n\t\t\t\t\t// Try to find at least one root directory that contains the referenced file\n\t\t\t\t\tif (rootDirs) {\n\t\t\t\t\t\tfor (const rootDir of rootDirs) {\n\t\t\t\t\t\t\tnewFilename = path.join(\n\t\t\t\t\t\t\t\trootDir,\n\t\t\t\t\t\t\t\timportFilename.slice(2),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (await pathExists(newFilename)) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Try the next\n\t\t\t\t\t\t\t\tnewFilename = undefined!;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!newFilename) {\n\t\t\t\t\t\t\tthrow new ZWaveError(\n\t\t\t\t\t\t\t\t`Could not find the referenced file ${\n\t\t\t\t\t\t\t\t\timportFilename.slice(\n\t\t\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t} in any of the root directories: ${\n\t\t\t\t\t\t\t\t\trootDirs\n\t\t\t\t\t\t\t\t\t\t.map((d) => `\\n\u00B7 ${d}`)\n\t\t\t\t\t\t\t\t\t\t.join(\"\")\n\t\t\t\t\t\t\t\t}\\n${\n\t\t\t\t\t\t\t\t\tgetImportStack(\n\t\t\t\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t\t\tZWaveErrorCodes.Config_Invalid,\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\tthrow new ZWaveError(\n\t\t\t\t\t\t\t`An $import specifier cannot start with ~/ when no root directory is defined!${\n\t\t\t\t\t\t\t\tgetImportStack(\n\t\t\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\t\t\tselector,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}`,\n\t\t\t\t\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewFilename = path.join(\n\t\t\t\t\t\tpath.dirname(filename),\n\t\t\t\t\t\timportFilename,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnewFilename = filename;\n\t\t\t}\n\n\t\t\t// const importFilename = path.join(path.dirname(filename), val);\n\t\t\tconst imported = await readJsonWithTemplateInternal(\n\t\t\t\tnewFilename,\n\t\t\t\tselector,\n\t\t\t\tvisited,\n\t\t\t\tfileCache,\n\t\t\t\trootDirs,\n\t\t\t);\n\t\t\tObject.assign(ret, imported);\n\t\t} else if (isObject(val)) {\n\t\t\t// We're looking at an object, recurse into it\n\t\t\tret[prop] = await resolveJsonImports(\n\t\t\t\tval,\n\t\t\t\tfilename,\n\t\t\t\tvisited,\n\t\t\t\tfileCache,\n\t\t\t\trootDirs,\n\t\t\t);\n\t\t} else if (isArray(val)) {\n\t\t\t// We're looking at an array, check if there are objects we need to recurse into\n\t\t\tconst vals: unknown[] = [];\n\t\t\tfor (const v of val) {\n\t\t\t\tif (isObject(v)) {\n\t\t\t\t\tvals.push(\n\t\t\t\t\t\tawait resolveJsonImports(\n\t\t\t\t\t\t\tv,\n\t\t\t\t\t\t\tfilename,\n\t\t\t\t\t\t\tvisited,\n\t\t\t\t\t\t\tfileCache,\n\t\t\t\t\t\t\trootDirs,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tvals.push(v);\n\t\t\t\t}\n\t\t\t}\n\t\t\tret[prop] = vals;\n\t\t} else {\n\t\t\tret[prop] = val;\n\t\t}\n\t}\n\treturn ret;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_safe", "filename", "fs", "JSON5"]
7
7
  }
@@ -34,7 +34,7 @@ __export(Manufacturers_exports, {
34
34
  module.exports = __toCommonJS(Manufacturers_exports);
35
35
  var import_core = require("@zwave-js/core");
36
36
  var import_shared = require("@zwave-js/shared");
37
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
37
+ var import_typeguards = require("alcalzone-shared/typeguards");
38
38
  var import_json5 = __toESM(require("json5"), 1);
39
39
  var import_promises = __toESM(require("node:fs/promises"), 1);
40
40
  var import_node_path = __toESM(require("node:path"), 1);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/Manufacturers.ts"],
4
- "sourcesContent": ["import { ZWaveError, ZWaveErrorCodes, isZWaveError } from \"@zwave-js/core\";\nimport { formatId, pathExists, stringify } from \"@zwave-js/shared\";\nimport { isObject } from \"alcalzone-shared/typeguards/index.js\";\nimport JSON5 from \"json5\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { configDir } from \"./utils.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"./utils_safe.js\";\n\nexport type ManufacturersMap = Map<number, string>;\n\n/** @internal */\nexport async function loadManufacturersInternal(\n\texternalConfigDir?: string,\n): Promise<ManufacturersMap> {\n\tconst configPath = path.join(\n\t\texternalConfigDir || configDir,\n\t\t\"manufacturers.json\",\n\t);\n\n\tif (!(await pathExists(configPath))) {\n\t\tthrow new ZWaveError(\n\t\t\t\"The manufacturer config file does not exist!\",\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\ttry {\n\t\tconst fileContents = await fs.readFile(configPath, \"utf8\");\n\t\tconst definition = JSON5.parse(fileContents);\n\t\tif (!isObject(definition)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"manufacturers\",\n\t\t\t\t`the database is not an object!`,\n\t\t\t);\n\t\t}\n\n\t\tconst manufacturers = new Map();\n\t\tfor (const [id, name] of Object.entries(definition)) {\n\t\t\tif (!hexKeyRegex4Digits.test(id)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"manufacturers\",\n\t\t\t\t\t`found invalid key ${id} at the root level. Manufacturer IDs must be hexadecimal lowercase.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof name !== \"string\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"manufacturers\",\n\t\t\t\t\t`Key ${id} has a non-string manufacturer name`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst idNum = parseInt(id.slice(2), 16);\n\t\t\tmanufacturers.set(idNum, name);\n\t\t}\n\n\t\treturn manufacturers;\n\t} catch (e) {\n\t\tif (isZWaveError(e) || ((e as any).code === \"ENOENT\")) {\n\t\t\tthrow e;\n\t\t} else {\n\t\t\tthrowInvalidConfig(\"manufacturers\");\n\t\t}\n\t}\n}\n\n/**\n * Write current manufacturers map to json\n */\nexport async function saveManufacturersInternal(\n\tmanufacturers: ManufacturersMap,\n): Promise<void> {\n\tconst data: Record<string, string> = {};\n\n\tconst orderedMap = new Map(\n\t\t[...manufacturers].sort((a, b) => (a[0] > b[0] ? 1 : -1)),\n\t);\n\n\tfor (const [id, name] of orderedMap) {\n\t\tdata[formatId(id)] = name;\n\t}\n\n\tconst configPath = path.join(configDir, \"manufacturers.json\");\n\tawait fs.writeFile(configPath, stringify(data, \"\\t\") + \"\\n\");\n}\n"],
4
+ "sourcesContent": ["import { ZWaveError, ZWaveErrorCodes, isZWaveError } from \"@zwave-js/core\";\nimport { formatId, pathExists, stringify } from \"@zwave-js/shared\";\nimport { isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { configDir } from \"./utils.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"./utils_safe.js\";\n\nexport type ManufacturersMap = Map<number, string>;\n\n/** @internal */\nexport async function loadManufacturersInternal(\n\texternalConfigDir?: string,\n): Promise<ManufacturersMap> {\n\tconst configPath = path.join(\n\t\texternalConfigDir || configDir,\n\t\t\"manufacturers.json\",\n\t);\n\n\tif (!(await pathExists(configPath))) {\n\t\tthrow new ZWaveError(\n\t\t\t\"The manufacturer config file does not exist!\",\n\t\t\tZWaveErrorCodes.Config_Invalid,\n\t\t);\n\t}\n\ttry {\n\t\tconst fileContents = await fs.readFile(configPath, \"utf8\");\n\t\tconst definition = JSON5.parse(fileContents);\n\t\tif (!isObject(definition)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t\"manufacturers\",\n\t\t\t\t`the database is not an object!`,\n\t\t\t);\n\t\t}\n\n\t\tconst manufacturers = new Map();\n\t\tfor (const [id, name] of Object.entries(definition)) {\n\t\t\tif (!hexKeyRegex4Digits.test(id)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"manufacturers\",\n\t\t\t\t\t`found invalid key ${id} at the root level. Manufacturer IDs must be hexadecimal lowercase.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (typeof name !== \"string\") {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\"manufacturers\",\n\t\t\t\t\t`Key ${id} has a non-string manufacturer name`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst idNum = parseInt(id.slice(2), 16);\n\t\t\tmanufacturers.set(idNum, name);\n\t\t}\n\n\t\treturn manufacturers;\n\t} catch (e) {\n\t\tif (isZWaveError(e) || ((e as any).code === \"ENOENT\")) {\n\t\t\tthrow e;\n\t\t} else {\n\t\t\tthrowInvalidConfig(\"manufacturers\");\n\t\t}\n\t}\n}\n\n/**\n * Write current manufacturers map to json\n */\nexport async function saveManufacturersInternal(\n\tmanufacturers: ManufacturersMap,\n): Promise<void> {\n\tconst data: Record<string, string> = {};\n\n\tconst orderedMap = new Map(\n\t\t[...manufacturers].sort((a, b) => (a[0] > b[0] ? 1 : -1)),\n\t);\n\n\tfor (const [id, name] of orderedMap) {\n\t\tdata[formatId(id)] = name;\n\t}\n\n\tconst configPath = path.join(configDir, \"manufacturers.json\");\n\tawait fs.writeFile(configPath, stringify(data, \"\\t\") + \"\\n\");\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;AAAA,kBAA0D;AAC1D,oBAAgD;AAChD,wBAAyB;AACzB,mBAAkB;AAClB,sBAAe;AACf,uBAAiB;AACjB,mBAA0B;AAC1B,wBAAuD;AAKvD,eAAsB,0BACrB,mBAA0B;AAE1B,QAAM,aAAa,iBAAAA,QAAK,KACvB,qBAAqB,wBACrB,oBAAoB;AAGrB,MAAI,CAAE,UAAM,0BAAW,UAAU,GAAI;AACpC,UAAM,IAAI,uBACT,gDACA,4BAAgB,cAAc;EAEhC;AACA,MAAI;AACH,UAAM,eAAe,MAAM,gBAAAC,QAAG,SAAS,YAAY,MAAM;AACzD,UAAM,aAAa,aAAAC,QAAM,MAAM,YAAY;AAC3C,QAAI,KAAC,4BAAS,UAAU,GAAG;AAC1B,gDACC,iBACA,gCAAgC;IAElC;AAEA,UAAM,gBAAgB,oBAAI,IAAG;AAC7B,eAAW,CAAC,IAAI,IAAI,KAAK,OAAO,QAAQ,UAAU,GAAG;AACpD,UAAI,CAAC,qCAAmB,KAAK,EAAE,GAAG;AACjC,kDACC,iBACA,qBAAqB,EAAE,qEAAqE;MAE9F;AACA,UAAI,OAAO,SAAS,UAAU;AAC7B,kDACC,iBACA,OAAO,EAAE,qCAAqC;MAEhD;AACA,YAAM,QAAQ,SAAS,GAAG,MAAM,CAAC,GAAG,EAAE;AACtC,oBAAc,IAAI,OAAO,IAAI;IAC9B;AAEA,WAAO;EACR,SAAS,GAAG;AACX,YAAI,0BAAa,CAAC,KAAO,EAAU,SAAS,UAAW;AACtD,YAAM;IACP,OAAO;AACN,gDAAmB,eAAe;IACnC;EACD;AACD;AAKA,eAAsB,0BACrB,eAA+B;AAE/B,QAAM,OAA+B,CAAA;AAErC,QAAM,aAAa,IAAI,IACtB,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,GAAG,MAAO,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,EAAG,CAAC;AAG1D,aAAW,CAAC,IAAI,IAAI,KAAK,YAAY;AACpC,aAAK,wBAAS,EAAE,CAAC,IAAI;EACtB;AAEA,QAAM,aAAa,iBAAAF,QAAK,KAAK,wBAAW,oBAAoB;AAC5D,QAAM,gBAAAC,QAAG,UAAU,gBAAY,yBAAU,MAAM,GAAI,IAAI,IAAI;AAC5D;",
6
6
  "names": ["path", "fs", "JSON5"]
7
7
  }
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "14.0.0";
1
+ export declare const PACKAGE_VERSION = "14.1.0";
2
2
  //# sourceMappingURL=_version.d.ts.map
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  PACKAGE_VERSION: () => PACKAGE_VERSION
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const PACKAGE_VERSION = "14.0.0";
24
+ const PACKAGE_VERSION = "14.1.0";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  PACKAGE_VERSION
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/_version.ts"],
4
- "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"14.0.0\";\n"],
4
+ "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"14.1.0\";\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AACO,MAAM,kBAAkB;",
6
6
  "names": []
7
7
  }
@@ -26,7 +26,7 @@ __export(CompatConfig_exports, {
26
26
  module.exports = __toCommonJS(CompatConfig_exports);
27
27
  var import_safe = require("@zwave-js/core/safe");
28
28
  var import_safe2 = require("@zwave-js/shared/safe");
29
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
29
+ var import_typeguards = require("alcalzone-shared/typeguards");
30
30
  var import_utils_safe = require("../utils_safe.js");
31
31
  var import_ConditionalItem = require("./ConditionalItem.js");
32
32
  class ConditionalCompatConfig {
@@ -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/index.js\";\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"],
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
5
  "mappings": "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",
6
6
  "names": ["import_safe"]
7
7
  }
@@ -26,7 +26,7 @@ __export(ConditionalItem_exports, {
26
26
  module.exports = __toCommonJS(ConditionalItem_exports);
27
27
  var import_safe = require("@zwave-js/core/safe");
28
28
  var import_safe2 = require("@zwave-js/shared/safe");
29
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
29
+ var import_typeguards = require("alcalzone-shared/typeguards");
30
30
  var import_Logic = require("../Logic.js");
31
31
  var import_utils_safe = require("../utils_safe.js");
32
32
  function isConditionalItem(val) {
@@ -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/safe\";\nimport { ObjectKeyMap } from \"@zwave-js/shared/safe\";\nimport { isArray } from \"alcalzone-shared/typeguards/index.js\";\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"],
4
+ "sourcesContent": ["import { ZWaveError, ZWaveErrorCodes } from \"@zwave-js/core/safe\";\nimport { ObjectKeyMap } from \"@zwave-js/shared/safe\";\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
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;AAAA,kBAA4C;AAC5C,IAAAA,eAA6B;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;AAGM,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;AAEM,SAAU,kBACf,UACA,YACA,aAAmB;AAEnB,MAAI,WAAW,OAAO,UAAa,OAAO,WAAW,QAAQ,UAAU;AACtE,8CACC,WACA,kCAAkC,QAAQ;EAC3C,WAAW,wBAAwB;EAEpC;AACD;AA4BM,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,2BAAc;AACvC,UAAM,MAAM,IAAI,0BAAY;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;",
6
6
  "names": ["import_safe"]
7
7
  }
@@ -22,7 +22,7 @@ __export(ConditionalPrimitive_exports, {
22
22
  parseConditionalPrimitive: () => parseConditionalPrimitive
23
23
  });
24
24
  module.exports = __toCommonJS(ConditionalPrimitive_exports);
25
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
25
+ var import_typeguards = require("alcalzone-shared/typeguards");
26
26
  var import_utils_safe = require("../utils_safe.js");
27
27
  var import_ConditionalItem = require("./ConditionalItem.js");
28
28
  function parseConditionalPrimitive(filename, valueType, propertyName, definition, errorMessagePrefix = "") {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/devices/ConditionalPrimitive.ts"],
4
- "sourcesContent": ["import { isArray, isObject } from \"alcalzone-shared/typeguards/index.js\";\nimport { throwInvalidConfig } from \"../utils_safe.js\";\nimport { type ConditionalItem, conditionApplies } from \"./ConditionalItem.js\";\nimport type { DeviceID } from \"./shared.js\";\n\ntype ToPrimitive<T extends string> = T extends \"string\" ? string\n\t: T extends \"number\" ? number\n\t: T extends \"boolean\" ? boolean\n\t: never;\n\nexport function parseConditionalPrimitive<\n\tT extends \"string\" | \"number\" | \"boolean\",\n>(\n\tfilename: string,\n\tvalueType: T,\n\tpropertyName: string,\n\tdefinition: any,\n\terrorMessagePrefix: string = \"\",\n): ConditionalPrimitive<ToPrimitive<T>> {\n\tif (\n\t\tisArray(definition)\n\t\t&& (definition as any[]).every(\n\t\t\t(i, index, dfn) =>\n\t\t\t\t// In arrays, only the last item may be non-conditional\n\t\t\t\t(isObject(i) && typeof i.value === valueType)\n\t\t\t\t|| (index === dfn.length - 1 && typeof i === valueType),\n\t\t)\n\t) {\n\t\treturn definition.map((d: any) =>\n\t\t\ttypeof d === valueType\n\t\t\t\t? new ConditionalPrimitiveVariant<ToPrimitive<T>>(d)\n\t\t\t\t: new ConditionalPrimitiveVariant<ToPrimitive<T>>(\n\t\t\t\t\td.value,\n\t\t\t\t\ttypeof d.$if === \"string\" ? d.$if : undefined,\n\t\t\t\t)\n\t\t);\n\t} else if (typeof definition === valueType) {\n\t\treturn definition;\n\t} else {\n\t\tthrowInvalidConfig(\n\t\t\t`device`,\n\t\t\t`packages/config/config/devices/${filename}:\n${errorMessagePrefix}${propertyName} must be a ${valueType} or an array of conditional ${valueType} entries`,\n\t\t);\n\t}\n}\n\nexport type ConditionalPrimitive<T extends number | string | boolean> =\n\t| T\n\t| ConditionalPrimitiveVariant<T>[];\n\nexport class ConditionalPrimitiveVariant<T extends number | string | boolean>\n\timplements ConditionalItem<T>\n{\n\tpublic constructor(\n\t\tpublic readonly value: T,\n\t\tpublic readonly condition?: string,\n\t) {}\n\n\tpublic evaluateCondition(deviceId?: DeviceID): T | undefined {\n\t\tif (!conditionApplies(this, deviceId)) return;\n\t\treturn this.value;\n\t}\n}\n"],
4
+ "sourcesContent": ["import { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport { throwInvalidConfig } from \"../utils_safe.js\";\nimport { type ConditionalItem, conditionApplies } from \"./ConditionalItem.js\";\nimport type { DeviceID } from \"./shared.js\";\n\ntype ToPrimitive<T extends string> = T extends \"string\" ? string\n\t: T extends \"number\" ? number\n\t: T extends \"boolean\" ? boolean\n\t: never;\n\nexport function parseConditionalPrimitive<\n\tT extends \"string\" | \"number\" | \"boolean\",\n>(\n\tfilename: string,\n\tvalueType: T,\n\tpropertyName: string,\n\tdefinition: any,\n\terrorMessagePrefix: string = \"\",\n): ConditionalPrimitive<ToPrimitive<T>> {\n\tif (\n\t\tisArray(definition)\n\t\t&& (definition as any[]).every(\n\t\t\t(i, index, dfn) =>\n\t\t\t\t// In arrays, only the last item may be non-conditional\n\t\t\t\t(isObject(i) && typeof i.value === valueType)\n\t\t\t\t|| (index === dfn.length - 1 && typeof i === valueType),\n\t\t)\n\t) {\n\t\treturn definition.map((d: any) =>\n\t\t\ttypeof d === valueType\n\t\t\t\t? new ConditionalPrimitiveVariant<ToPrimitive<T>>(d)\n\t\t\t\t: new ConditionalPrimitiveVariant<ToPrimitive<T>>(\n\t\t\t\t\td.value,\n\t\t\t\t\ttypeof d.$if === \"string\" ? d.$if : undefined,\n\t\t\t\t)\n\t\t);\n\t} else if (typeof definition === valueType) {\n\t\treturn definition;\n\t} else {\n\t\tthrowInvalidConfig(\n\t\t\t`device`,\n\t\t\t`packages/config/config/devices/${filename}:\n${errorMessagePrefix}${propertyName} must be a ${valueType} or an array of conditional ${valueType} entries`,\n\t\t);\n\t}\n}\n\nexport type ConditionalPrimitive<T extends number | string | boolean> =\n\t| T\n\t| ConditionalPrimitiveVariant<T>[];\n\nexport class ConditionalPrimitiveVariant<T extends number | string | boolean>\n\timplements ConditionalItem<T>\n{\n\tpublic constructor(\n\t\tpublic readonly value: T,\n\t\tpublic readonly condition?: string,\n\t) {}\n\n\tpublic evaluateCondition(deviceId?: DeviceID): T | undefined {\n\t\tif (!conditionApplies(this, deviceId)) return;\n\t\treturn this.value;\n\t}\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;AAAA,wBAAkC;AAClC,wBAAmC;AACnC,6BAAuD;AAQjD,SAAU,0BAGf,UACA,WACA,cACA,YACA,qBAA6B,IAAE;AAE/B,UACC,2BAAQ,UAAU,KACd,WAAqB,MACxB,CAAC,GAAG,OAAO;;QAET,4BAAS,CAAC,KAAK,OAAO,EAAE,UAAU,aAC/B,UAAU,IAAI,SAAS,KAAK,OAAO,MAAM;GAAU,GAExD;AACD,WAAO,WAAW,IAAI,CAAC,MACtB,OAAO,MAAM,YACV,IAAI,4BAA4C,CAAC,IACjD,IAAI,4BACL,EAAE,OACF,OAAO,EAAE,QAAQ,WAAW,EAAE,MAAM,MAAS,CAC7C;EAEJ,WAAW,OAAO,eAAe,WAAW;AAC3C,WAAO;EACR,OAAO;AACN,8CACC,UACA,kCAAkC,QAAQ;EAC3C,kBAAkB,GAAG,YAAY,cAAc,SAAS,+BAA+B,SAAS,UAAU;EAE3G;AACD;AAMM,MAAO,4BAA2B;EAItB;EACA;EAFjB,YACiB,OACA,WAAkB;AADlB,SAAA,QAAA;AACA,SAAA,YAAA;EACd;EAEI,kBAAkB,UAAmB;AAC3C,QAAI,KAAC,yCAAiB,MAAM,QAAQ;AAAG;AACvC,WAAO,KAAK;EACb;;",
6
6
  "names": []
7
7
  }
@@ -39,7 +39,7 @@ __export(DeviceConfig_exports, {
39
39
  module.exports = __toCommonJS(DeviceConfig_exports);
40
40
  var import_core = require("@zwave-js/core");
41
41
  var import_shared = require("@zwave-js/shared");
42
- var import_typeguards = require("alcalzone-shared/typeguards/index.js");
42
+ var import_typeguards = require("alcalzone-shared/typeguards");
43
43
  var import_json5 = __toESM(require("json5"), 1);
44
44
  var import_node_crypto = require("node:crypto");
45
45
  var import_promises = __toESM(require("node:fs/promises"), 1);