homey-lib 2.46.0 → 2.47.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.
@@ -504,6 +504,7 @@ export interface FlowCard {
504
504
  | {
505
505
  [k: string]: unknown;
506
506
  };
507
+ items?: "variable" | "flow_or_advanced_flow" | "user";
507
508
  [k: string]: unknown;
508
509
  }
509
510
  | {
@@ -333,6 +333,14 @@
333
333
  "type": "object"
334
334
  }
335
335
  ]
336
+ },
337
+ "items": {
338
+ "type": "string",
339
+ "enum": [
340
+ "variable",
341
+ "flow_or_advanced_flow",
342
+ "user"
343
+ ]
336
344
  }
337
345
  }
338
346
  },
package/lib/App/index.js CHANGED
@@ -386,32 +386,29 @@ class App {
386
386
  // validate `appJson.drivers[].capabilitiesOptions`
387
387
  if (driver.capabilitiesOptions) {
388
388
  for (const [capabilityId, capabilityOptions] of Object.entries(driver.capabilitiesOptions)) {
389
- // Merge canonical + extra values for target_power_mode - canonical always present, extras appended
390
- if (Capability.isInstanceOfId(capabilityId, 'target_power_mode')) {
389
+ // Validate target_power_mode values - check canonical IDs present, no reserved prefixes
390
+ if (Capability.isInstanceOfId(capabilityId, 'target_power_mode') && Array.isArray(capabilityOptions.values)) {
391
391
  const canonicalValues = Capability.getCapability('target_power_mode').values;
392
- const providedValues = Array.isArray(capabilityOptions.values) ? capabilityOptions.values : [];
393
392
 
394
- const seenIds = new Set(canonicalValues.map(canonical => canonical.id));
395
- const extraValues = [];
396
-
397
- for (const value of providedValues) {
398
- if (!value || typeof value !== 'object' || typeof value.id !== 'string') continue;
399
- if (seenIds.has(value.id)) continue;
400
- seenIds.add(value.id);
401
- extraValues.push(value);
393
+ for (const canonical of canonicalValues) {
394
+ const provided = capabilityOptions.values.find(v => v && typeof v === 'object' && v.id === canonical.id);
395
+ if (!provided) {
396
+ throw new Error(`drivers.${driver.id}.capabilitiesOptions.${capabilityId}.values must include canonical value "${canonical.id}"`);
397
+ }
402
398
  }
403
399
 
404
- const RESERVED_PREFIXES = ['homey_', 'device_'];
400
+ const canonicalIds = new Set(canonicalValues.map(v => v.id));
401
+ const extraValues = capabilityOptions.values.filter(v => v && typeof v === 'object' && typeof v.id === 'string' && !canonicalIds.has(v.id));
402
+
403
+ const RESERVED_PREFIXES = ['homey_'];
405
404
  const reservedValues = extraValues.filter(value =>
406
405
  RESERVED_PREFIXES.some(prefix => value.id.startsWith(prefix))
407
406
  );
408
407
 
409
408
  if (reservedValues.length) {
410
409
  const ids = reservedValues.map(value => value.id).join(', ');
411
- throw new Error(`drivers.${driver.id}.capabilitiesOptions.${capabilityId} custom values cannot use reserved prefixes "homey_" or "device_": ${ids}`);
410
+ throw new Error(`drivers.${driver.id}.capabilitiesOptions.${capabilityId}.values custom values cannot use reserved prefix "homey_": ${ids}`);
412
411
  }
413
-
414
- capabilityOptions.values = [...canonicalValues, ...extraValues];
415
412
  }
416
413
 
417
414
  // validate target_power exclude range must include 0
@@ -698,7 +695,11 @@ class App {
698
695
  const seenFiles = new Set();
699
696
 
700
697
  for (const [fileIndex, file] of Object.entries(update.files)) {
701
- const relativeFilePath = Util.getOTAFilePath({ appPath: '', driverId: driver.id, fileName: file.name });
698
+ if (basename(file.name) !== file.name) {
699
+ throw new Error(`drivers.${driver.id}.firmwareUpdates.updates[${updateIndex}].files[${fileIndex}] cannot include (sub)directories in the file name`);
700
+ }
701
+
702
+ const relativeFilePath = Util.getOTAFilePath({ driverId: driver.id, fileName: file.name });
702
703
  await this._ensureFileExistsCaseSensitive(relativeFilePath);
703
704
  const filePath = join(this._path, relativeFilePath);
704
705
  const isIntegrityValid = await Util.validateIntegrity(filePath, file.integrity);
package/lib/Util/file.js CHANGED
@@ -73,7 +73,7 @@ async function getIntegrity(filePath, hashName = 'sha256') {
73
73
  }
74
74
 
75
75
  function getOTAFilePath({ appPath, driverId, fileName }) {
76
- return path.join(appPath, 'drivers', driverId, 'assets', 'firmware', fileName);
76
+ return path.join(appPath || '', 'drivers', driverId, 'assets', 'firmware', fileName);
77
77
  }
78
78
 
79
79
  module.exports = {
package/lib/Util/index.js CHANGED
@@ -73,7 +73,7 @@ class Util {
73
73
  * Returns the expected file path for an OTA file based on app path, driver ID and file name.
74
74
  * NOTE: This method is only available in Node.js environments.
75
75
  * @param {object} options - File path options.
76
- * @param {string} options.appPath - Absolute path to the app.
76
+ * @param {string} [options.appPath] - Absolute path to the app. If not provided, the path is relative to the app root.
77
77
  * @param {string} options.driverId - Driver ID.
78
78
  * @param {string} options.fileName - OTA file name.
79
79
  * @returns {string} Resolves with the expected file path.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homey-lib",
3
- "version": "2.46.0",
3
+ "version": "2.47.0",
4
4
  "description": "Shared Library for Homey",
5
5
  "types": "types/index.d.ts",
6
6
  "main": "index.js",
@@ -504,6 +504,7 @@ export interface FlowCard {
504
504
  | {
505
505
  [k: string]: unknown;
506
506
  };
507
+ items?: "variable" | "flow_or_advanced_flow" | "user";
507
508
  [k: string]: unknown;
508
509
  }
509
510
  | {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/App/index.js"],"names":[],"mappings":";AA8EA;IACE,2CAAqD;IACrD,2CAAmD;IAsyBnD;;;OAGG;IACH,sCAHW,WAAW,GACT,IAAI,CAOhB;IA4PD;;;;;OAKG;IACH,4CALW,MAAM,QACN;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,aAClB,MAAM,GACJ,IAAI,CAkChB;IAiBD;;;OAGG;IACH,wBAHW,MAAM,GACJ,OAAO,CAQnB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAInB;IAED;;OAEG;IACH,wBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnC;IAED;;OAEG;IACH,yBAFa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAcnD;IAED;;OAEG;IACH,wBAFa,MAAM,EAAE,CAIpB;IAED;;OAEG;IACH,qBAFa,MAAM,EAAE,CAKpB;IAED;;;OAGG;IACH,4BAHW,MAAM,GACJ,MAAM,CAuBlB;IAED;;;;OAIG;IACH,0BAJW,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,WAC1C,WAAW,GACT,MAAM,GAAG,IAAI,CAyDzB;IApvCD;;OAEG;IACH,kBAFW,MAAM,EAQhB;IALC,cAAiB;IAOnB;;;OAGG;IACH,eAHc,OAAO,EAAA,GACR,IAAI,CAKhB;IAED;;;OAGG;IACH,6BAHW;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3D,OAAO,CAAC,IAAI,CAAC,CA4wBzB;IAtwBC,gBAAmB;IAmxBrB;;;;OAIG;IACH,uCAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UACvB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GACZ,IAAI,CAwBhB;IAED;;;;OAIG;IACH,8BAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,WAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACxC,IAAI,CAuBhB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CAY7B;IAED;;;OAGG;IACH,yCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAOzB;IAED;;;OAGG;IACH,mCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAe5B;IAED;;;;;OAKG;IACH,2BALW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,QAChC,KAAK,GAAG,QAAQ,cAChB,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;OAEG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;;OAMG;IACH,wBANW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aACvB,MAAM,WACN,WAAW,mCACX;QAAE,YAAY,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAC/C,IAAI,CA+EhB;IA0CD;;;;OAIG;IACH,qBAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAU3B;CAwJF;;;;mBAtyCa,OAAO,yBAAyB,EAAE,GAAG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/App/index.js"],"names":[],"mappings":";AA8EA;IACE,2CAAqD;IACrD,2CAAmD;IAuyBnD;;;OAGG;IACH,sCAHW,WAAW,GACT,IAAI,CAOhB;IA4PD;;;;;OAKG;IACH,4CALW,MAAM,QACN;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,aAClB,MAAM,GACJ,IAAI,CAkChB;IAiBD;;;OAGG;IACH,wBAHW,MAAM,GACJ,OAAO,CAQnB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAInB;IAED;;OAEG;IACH,wBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnC;IAED;;OAEG;IACH,yBAFa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAcnD;IAED;;OAEG;IACH,wBAFa,MAAM,EAAE,CAIpB;IAED;;OAEG;IACH,qBAFa,MAAM,EAAE,CAKpB;IAED;;;OAGG;IACH,4BAHW,MAAM,GACJ,MAAM,CAuBlB;IAED;;;;OAIG;IACH,0BAJW,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,WAC1C,WAAW,GACT,MAAM,GAAG,IAAI,CAyDzB;IArvCD;;OAEG;IACH,kBAFW,MAAM,EAQhB;IALC,cAAiB;IAOnB;;;OAGG;IACH,eAHc,OAAO,EAAA,GACR,IAAI,CAKhB;IAED;;;OAGG;IACH,6BAHW;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3D,OAAO,CAAC,IAAI,CAAC,CA6wBzB;IAvwBC,gBAAmB;IAoxBrB;;;;OAIG;IACH,uCAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UACvB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GACZ,IAAI,CAwBhB;IAED;;;;OAIG;IACH,8BAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,WAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACxC,IAAI,CAuBhB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CAY7B;IAED;;;OAGG;IACH,yCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAOzB;IAED;;;OAGG;IACH,mCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAe5B;IAED;;;;;OAKG;IACH,2BALW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,QAChC,KAAK,GAAG,QAAQ,cAChB,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;OAEG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;;OAMG;IACH,wBANW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aACvB,MAAM,WACN,WAAW,mCACX;QAAE,YAAY,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAC/C,IAAI,CA+EhB;IA0CD;;;;OAIG;IACH,qBAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAU3B;CAwJF;;;;mBAvyCa,OAAO,yBAAyB,EAAE,GAAG"}
@@ -54,13 +54,13 @@ declare class Util {
54
54
  * Returns the expected file path for an OTA file based on app path, driver ID and file name.
55
55
  * NOTE: This method is only available in Node.js environments.
56
56
  * @param {object} options - File path options.
57
- * @param {string} options.appPath - Absolute path to the app.
57
+ * @param {string} [options.appPath] - Absolute path to the app. If not provided, the path is relative to the app root.
58
58
  * @param {string} options.driverId - Driver ID.
59
59
  * @param {string} options.fileName - OTA file name.
60
60
  * @returns {string} Resolves with the expected file path.
61
61
  */
62
62
  static getOTAFilePath({ appPath, driverId, fileName }: {
63
- appPath: string;
63
+ appPath?: string;
64
64
  driverId: string;
65
65
  fileName: string;
66
66
  }): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/Util/index.js"],"names":[],"mappings":";AAKA;IAEE;;;OAGG;IACH,yCAHW,MAAM,GACJ,MAAM,EAAE,CAIpB;IAED;;;;OAIG;IACH,gDAJW,MAAM,kBACN,MAAM,EAAE,GACN,MAAM,EAAE,CAKpB;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAI3B;IAED;;;;;;OAMG;IACH,mCAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;;OAKG;IACH,sCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;;OASG;IACH,wCANG;QAAwB,QAAQ,EAAxB,MAAM;QACW,gBAAgB,GAAjC,MAAM;QACW,WAAW,GAA5B,MAAM;QACW,SAAS,GAA1B,MAAM;KACd,GAAU,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;OAQG;IACH,uDALG;QAAwB,OAAO,EAAvB,MAAM;QACU,QAAQ,EAAxB,MAAM;QACU,QAAQ,EAAxB,MAAM;KACd,GAAU,MAAM,CAIlB;CAEF;;;;;;;gCAOU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/Util/index.js"],"names":[],"mappings":";AAKA;IAEE;;;OAGG;IACH,yCAHW,MAAM,GACJ,MAAM,EAAE,CAIpB;IAED;;;;OAIG;IACH,gDAJW,MAAM,kBACN,MAAM,EAAE,GACN,MAAM,EAAE,CAKpB;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAI3B;IAED;;;;;;OAMG;IACH,mCAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;;OAKG;IACH,sCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;;OASG;IACH,wCANG;QAAwB,QAAQ,EAAxB,MAAM;QACW,gBAAgB,GAAjC,MAAM;QACW,WAAW,GAA5B,MAAM;QACW,SAAS,GAA1B,MAAM;KACd,GAAU,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;OAQG;IACH,uDALG;QAAyB,OAAO,GAAxB,MAAM;QACU,QAAQ,EAAxB,MAAM;QACU,QAAQ,EAAxB,MAAM;KACd,GAAU,MAAM,CAIlB;CAEF;;;;;;;gCAOU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC"}