@homebridge-plugins/homebridge-updater 3.0.7

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 (85) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +117 -0
  3. package/config.schema.json +257 -0
  4. package/dist/Platform.HAP.d.ts +16 -0
  5. package/dist/Platform.HAP.d.ts.map +1 -0
  6. package/dist/Platform.HAP.js +77 -0
  7. package/dist/Platform.HAP.js.map +1 -0
  8. package/dist/Platform.Matter.d.ts +7 -0
  9. package/dist/Platform.Matter.d.ts.map +1 -0
  10. package/dist/Platform.Matter.js +21 -0
  11. package/dist/Platform.Matter.js.map +1 -0
  12. package/dist/configMigration.d.ts +4 -0
  13. package/dist/configMigration.d.ts.map +1 -0
  14. package/dist/configMigration.js +45 -0
  15. package/dist/configMigration.js.map +1 -0
  16. package/dist/configMigration.test.d.ts +2 -0
  17. package/dist/configMigration.test.d.ts.map +1 -0
  18. package/dist/configMigration.test.js +23 -0
  19. package/dist/configMigration.test.js.map +1 -0
  20. package/dist/configTypes.d.ts +24 -0
  21. package/dist/configTypes.d.ts.map +1 -0
  22. package/dist/configTypes.js +2 -0
  23. package/dist/configTypes.js.map +1 -0
  24. package/dist/configTypes.test.d.ts +2 -0
  25. package/dist/configTypes.test.d.ts.map +1 -0
  26. package/dist/configTypes.test.js +108 -0
  27. package/dist/configTypes.test.js.map +1 -0
  28. package/dist/failureSensor.d.ts +17 -0
  29. package/dist/failureSensor.d.ts.map +1 -0
  30. package/dist/failureSensor.js +36 -0
  31. package/dist/failureSensor.js.map +1 -0
  32. package/dist/homebridge-ui/public/index.html +230 -0
  33. package/dist/homebridge-ui/server.d.ts +2 -0
  34. package/dist/homebridge-ui/server.d.ts.map +1 -0
  35. package/dist/homebridge-ui/server.js +47 -0
  36. package/dist/homebridge-ui/server.js.map +1 -0
  37. package/dist/ignore-plugins.test.d.ts +2 -0
  38. package/dist/ignore-plugins.test.d.ts.map +1 -0
  39. package/dist/ignore-plugins.test.js +121 -0
  40. package/dist/ignore-plugins.test.js.map +1 -0
  41. package/dist/index.d.ts +4 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +12 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/index.test.d.ts +2 -0
  46. package/dist/index.test.d.ts.map +1 -0
  47. package/dist/index.test.js +8 -0
  48. package/dist/index.test.js.map +1 -0
  49. package/dist/schema.test.d.ts +2 -0
  50. package/dist/schema.test.d.ts.map +1 -0
  51. package/dist/schema.test.js +109 -0
  52. package/dist/schema.test.js.map +1 -0
  53. package/dist/sensorBase.d.ts +39 -0
  54. package/dist/sensorBase.d.ts.map +1 -0
  55. package/dist/sensorBase.js +309 -0
  56. package/dist/sensorBase.js.map +1 -0
  57. package/dist/settings.d.ts +11 -0
  58. package/dist/settings.d.ts.map +1 -0
  59. package/dist/settings.js +11 -0
  60. package/dist/settings.js.map +1 -0
  61. package/dist/ui-api.d.ts +40 -0
  62. package/dist/ui-api.d.ts.map +1 -0
  63. package/dist/ui-api.js +522 -0
  64. package/dist/ui-api.js.map +1 -0
  65. package/dist/updateCheckCore.d.ts +46 -0
  66. package/dist/updateCheckCore.d.ts.map +1 -0
  67. package/dist/updateCheckCore.js +433 -0
  68. package/dist/updateCheckCore.js.map +1 -0
  69. package/dist/updateSensor.d.ts +21 -0
  70. package/dist/updateSensor.d.ts.map +1 -0
  71. package/dist/updateSensor.js +75 -0
  72. package/dist/updateSensor.js.map +1 -0
  73. package/dist/updateSensor.test.d.ts +2 -0
  74. package/dist/updateSensor.test.d.ts.map +1 -0
  75. package/dist/updateSensor.test.js +133 -0
  76. package/dist/updateSensor.test.js.map +1 -0
  77. package/dist/utils.d.ts +22 -0
  78. package/dist/utils.d.ts.map +1 -0
  79. package/dist/utils.js +75 -0
  80. package/dist/utils.js.map +1 -0
  81. package/dist/utils.test.d.ts +2 -0
  82. package/dist/utils.test.d.ts.map +1 -0
  83. package/dist/utils.test.js +126 -0
  84. package/dist/utils.test.js.map +1 -0
  85. package/package.json +96 -0
@@ -0,0 +1,133 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ /**
3
+ * Regression test for: update checks not running after Homebridge restart
4
+ *
5
+ * When Homebridge restarts, cached accessories are restored via `configureAccessory`
6
+ * before `didFinishLaunching` fires. The previous implementation returned early in
7
+ * `addUpdateSensor` when `registered` was already true, which prevented the initial
8
+ * check and scheduled cron jobs from being started.
9
+ */
10
+ describe('updateSensor cached accessory restore', () => {
11
+ it('should start update checks even when the accessory is restored from cache', async () => {
12
+ // Arrange: track calls to startScheduledChecks and doCheck (via checkUi)
13
+ const checkUiCalls = [];
14
+ const startScheduledChecksCalls = [];
15
+ // Minimal mock for UpdateCheckCore
16
+ const mockUpdateCore = {
17
+ initialCheckDelay: 0,
18
+ checkUi: vi.fn().mockResolvedValue(0),
19
+ startScheduledChecks: vi.fn((_cb) => {
20
+ startScheduledChecksCalls.push(1);
21
+ }),
22
+ getLastAutoUpdateFailed: vi.fn().mockReturnValue(false),
23
+ };
24
+ // Minimal mock for a HAP sensor
25
+ const mockSensor = {
26
+ configure: vi.fn(),
27
+ setState: vi.fn(),
28
+ };
29
+ // Minimal mock for the Homebridge API (HAP path, no Matter)
30
+ const mockAccessory = {
31
+ UUID: 'test-uuid',
32
+ displayName: 'Plugin Update Check',
33
+ on: vi.fn(),
34
+ };
35
+ const mockApi = {
36
+ matter: undefined,
37
+ hap: {
38
+ uuid: {
39
+ generate: vi.fn().mockReturnValue('test-uuid'),
40
+ },
41
+ },
42
+ platformAccessory: vi.fn().mockReturnValue(mockAccessory),
43
+ registerPlatformAccessories: vi.fn(),
44
+ user: { storagePath: vi.fn().mockReturnValue('/tmp') },
45
+ on: vi.fn(),
46
+ };
47
+ // Build the UpdateSensor object directly by manipulating internal state
48
+ // to simulate the cached accessory scenario without needing to import the full class
49
+ // (which requires a real Homebridge environment).
50
+ //
51
+ // Instead, we test the *logic* extracted from addUpdateSensor:
52
+ // The fix ensures that checks are started whether or not the accessory was cached.
53
+ let registered = false;
54
+ // Simulate configureAccessory being called (cached accessory restore)
55
+ function configureAccessory(_accessory) {
56
+ mockSensor.configure(_accessory);
57
+ registered = true;
58
+ }
59
+ // Fixed addUpdateSensor: only skips accessory creation, always starts checks
60
+ function addUpdateSensor() {
61
+ if (!registered) {
62
+ // Would create and register the accessory here
63
+ mockSensor.configure(mockAccessory);
64
+ registered = true;
65
+ }
66
+ // Always start checks
67
+ setTimeout(() => {
68
+ mockUpdateCore.checkUi().then((updates) => {
69
+ checkUiCalls.push(updates);
70
+ mockSensor.setState(!!updates);
71
+ });
72
+ }, mockUpdateCore.initialCheckDelay * 1000);
73
+ mockUpdateCore.startScheduledChecks(() => {
74
+ mockUpdateCore.checkUi();
75
+ });
76
+ }
77
+ // Simulate Homebridge restart: cached accessory is restored first
78
+ configureAccessory(mockAccessory);
79
+ expect(registered).toBe(true);
80
+ // Then addUpdateSensor fires on didFinishLaunching
81
+ addUpdateSensor();
82
+ // The accessory should NOT be reconfigured (already was via restore)
83
+ expect(mockSensor.configure).toHaveBeenCalledTimes(1);
84
+ // Scheduled checks MUST be started
85
+ expect(startScheduledChecksCalls).toHaveLength(1);
86
+ expect(mockUpdateCore.startScheduledChecks).toHaveBeenCalledTimes(1);
87
+ // Wait for setTimeout(0) to fire
88
+ await new Promise(resolve => setTimeout(resolve, 10));
89
+ // The initial check must have run
90
+ expect(mockUpdateCore.checkUi).toHaveBeenCalled();
91
+ expect(checkUiCalls).toHaveLength(1);
92
+ });
93
+ it('should NOT start checks twice when addUpdateSensor is called on first launch (no cached accessory)', async () => {
94
+ const startScheduledChecksCalls = [];
95
+ const configureCalls = [];
96
+ const mockUpdateCore = {
97
+ initialCheckDelay: 0,
98
+ checkUi: vi.fn().mockResolvedValue(1),
99
+ startScheduledChecks: vi.fn((_cb) => {
100
+ startScheduledChecksCalls.push(1);
101
+ }),
102
+ getLastAutoUpdateFailed: vi.fn().mockReturnValue(false),
103
+ };
104
+ const mockSensor = {
105
+ configure: vi.fn((_acc) => configureCalls.push(1)),
106
+ setState: vi.fn(),
107
+ };
108
+ const mockAccessory = {
109
+ UUID: 'test-uuid',
110
+ displayName: 'Plugin Update Check',
111
+ };
112
+ let registered = false;
113
+ // Fixed addUpdateSensor (no prior configureAccessory call)
114
+ function addUpdateSensor() {
115
+ if (!registered) {
116
+ mockSensor.configure(mockAccessory);
117
+ registered = true;
118
+ }
119
+ setTimeout(() => {
120
+ mockUpdateCore.checkUi();
121
+ }, mockUpdateCore.initialCheckDelay * 1000);
122
+ mockUpdateCore.startScheduledChecks(() => {
123
+ mockUpdateCore.checkUi();
124
+ });
125
+ }
126
+ // First launch: no cached accessory; addUpdateSensor creates it
127
+ addUpdateSensor();
128
+ expect(registered).toBe(true);
129
+ expect(configureCalls).toHaveLength(1);
130
+ expect(startScheduledChecksCalls).toHaveLength(1);
131
+ });
132
+ });
133
+ //# sourceMappingURL=updateSensor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateSensor.test.js","sourceRoot":"","sources":["../src/updateSensor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { PlatformConfig } from 'homebridge';
2
+ /**
3
+ * Returns true if the failure sensor should be registered and active.
4
+ *
5
+ * The failure sensor is disabled when:
6
+ * - `failureSensorType` is explicitly set to `"none"`, OR
7
+ * - none of the auto-update options (autoUpdateNode, autoUpdateHomebridge,
8
+ * autoUpdateHomebridgeUI, autoUpdatePlugins, autoUpdateNpm) are enabled, because without
9
+ * auto-updates there can never be an auto-update failure to report.
10
+ */
11
+ export declare function isFailureSensorEnabled(config: PlatformConfig): boolean;
12
+ /**
13
+ * Factory function that creates a platform proxy constructor.
14
+ * Selects between HAP and Matter platform implementations at runtime
15
+ * based on whether Homebridge Matter support is available and enabled.
16
+ *
17
+ * @param HAPPlatform The HAP platform class constructor.
18
+ * @param MatterPlatform The Matter platform class constructor.
19
+ * @returns A proxy class that delegates to the correct platform implementation.
20
+ */
21
+ export declare function createPlatformProxy(HAPPlatform: any, MatterPlatform: any): any;
22
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAIhD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAMtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,GAAG,GAAG,CAoD9E"}
package/dist/utils.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Returns true if the failure sensor should be registered and active.
3
+ *
4
+ * The failure sensor is disabled when:
5
+ * - `failureSensorType` is explicitly set to `"none"`, OR
6
+ * - none of the auto-update options (autoUpdateNode, autoUpdateHomebridge,
7
+ * autoUpdateHomebridgeUI, autoUpdatePlugins, autoUpdateNpm) are enabled, because without
8
+ * auto-updates there can never be an auto-update failure to report.
9
+ */
10
+ export function isFailureSensorEnabled(config) {
11
+ const cfg = config;
12
+ if (cfg.failureSensorType === 'none') {
13
+ return false;
14
+ }
15
+ return !!(cfg.autoUpdateNode || cfg.autoUpdateHomebridge || cfg.autoUpdateHomebridgeUI || cfg.autoUpdatePlugins || cfg.autoUpdateNpm);
16
+ }
17
+ /**
18
+ * Factory function that creates a platform proxy constructor.
19
+ * Selects between HAP and Matter platform implementations at runtime
20
+ * based on whether Homebridge Matter support is available and enabled.
21
+ *
22
+ * @param HAPPlatform The HAP platform class constructor.
23
+ * @param MatterPlatform The Matter platform class constructor.
24
+ * @returns A proxy class that delegates to the correct platform implementation.
25
+ */
26
+ export function createPlatformProxy(HAPPlatform, MatterPlatform) {
27
+ return class PluginUpdatePlatformProxy {
28
+ /** The instantiated platform implementation (HAP or Matter) */
29
+ impl;
30
+ /**
31
+ * Constructs the proxy and instantiates the correct platform implementation.
32
+ * @param log Logger instance
33
+ * @param config Platform config
34
+ * @param api Homebridge API instance
35
+ * @returns The instantiated platform implementation
36
+ */
37
+ constructor(log, config, api) {
38
+ const enableMatter = config.enableMatter ?? true;
39
+ const hasMatterApi = !!api?.matter;
40
+ const matterAvailable = typeof api?.isMatterAvailable === 'function' ? !!api.isMatterAvailable() : hasMatterApi;
41
+ const matterEnabled = typeof api?.isMatterEnabled === 'function' ? !!api.isMatterEnabled() : hasMatterApi;
42
+ if (enableMatter && MatterPlatform && hasMatterApi && matterAvailable && matterEnabled) {
43
+ log?.debug?.('[Protocol] Using Matter platform implementation');
44
+ this.impl = new MatterPlatform(log, config, api);
45
+ return;
46
+ }
47
+ if (enableMatter) {
48
+ const reasons = [];
49
+ if (!MatterPlatform) {
50
+ reasons.push('Matter platform class unavailable');
51
+ }
52
+ if (!hasMatterApi) {
53
+ reasons.push('api.matter missing');
54
+ }
55
+ if (!matterAvailable) {
56
+ reasons.push('Matter not available');
57
+ }
58
+ if (!matterEnabled) {
59
+ reasons.push('Matter not enabled');
60
+ }
61
+ const reasonText = reasons.length ? reasons.join(', ') : 'unknown reason';
62
+ log?.debug?.(`[Protocol] Falling back to HAP: ${reasonText}`);
63
+ }
64
+ else {
65
+ log?.debug?.('[Protocol] Using HAP platform implementation');
66
+ }
67
+ // Fallback to HAP
68
+ this.impl = new HAPPlatform(log, config, api);
69
+ }
70
+ configureAccessory(...args) {
71
+ return this.impl?.configureAccessory?.(...args);
72
+ }
73
+ };
74
+ }
75
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAsB;IAC3D,MAAM,GAAG,GAAG,MAAoC,CAAA;IAChD,IAAI,GAAG,CAAC,iBAAiB,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,oBAAoB,IAAI,GAAG,CAAC,sBAAsB,IAAI,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC,aAAa,CAAC,CAAA;AACvI,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAgB,EAAE,cAAmB;IACvE,OAAO,MAAM,yBAAyB;QACpC,+DAA+D;QACvD,IAAI,CAAK;QAEjB;;;;;;WAMG;QACH,YAAY,GAAQ,EAAE,MAAsB,EAAE,GAAQ;YACpD,MAAM,YAAY,GAAI,MAAc,CAAC,YAAY,IAAI,IAAI,CAAA;YACzD,MAAM,YAAY,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,CAAA;YAClC,MAAM,eAAe,GAAG,OAAO,GAAG,EAAE,iBAAiB,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,YAAY,CAAA;YAC/G,MAAM,aAAa,GAAG,OAAO,GAAG,EAAE,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,YAAY,CAAA;YAEzG,IAAI,YAAY,IAAI,cAAc,IAAI,YAAY,IAAI,eAAe,IAAI,aAAa,EAAE,CAAC;gBACvF,GAAG,EAAE,KAAK,EAAE,CAAC,iDAAiD,CAAC,CAAA;gBAC/D,IAAI,CAAC,IAAI,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;gBAChD,OAAM;YACR,CAAC;YAED,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,OAAO,GAAa,EAAE,CAAA;gBAC5B,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAA;gBACnD,CAAC;gBACD,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;gBACpC,CAAC;gBACD,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;gBACtC,CAAC;gBACD,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;gBACpC,CAAC;gBACD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAA;gBACzE,GAAG,EAAE,KAAK,EAAE,CAAC,mCAAmC,UAAU,EAAE,CAAC,CAAA;YAC/D,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,KAAK,EAAE,CAAC,8CAA8C,CAAC,CAAA;YAC9D,CAAC;YAED,kBAAkB;YAClB,IAAI,CAAC,IAAI,GAAG,IAAI,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;QAC/C,CAAC;QAED,kBAAkB,CAAC,GAAG,IAAW;YAC/B,OAAO,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;QACjD,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,126 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createPlatformProxy, isFailureSensorEnabled } from './utils.js';
3
+ describe('isFailureSensorEnabled', () => {
4
+ it('should return false when failureSensorType is "none"', () => {
5
+ expect(isFailureSensorEnabled({ failureSensorType: 'none', autoUpdateHomebridge: true })).toBe(false);
6
+ });
7
+ it('should return false when no auto-update option is enabled', () => {
8
+ expect(isFailureSensorEnabled({})).toBe(false);
9
+ expect(isFailureSensorEnabled({ autoUpdateHomebridge: false, autoUpdateHomebridgeUI: false, autoUpdatePlugins: false, autoUpdateNode: false, autoUpdateNpm: false })).toBe(false);
10
+ });
11
+ it('should return true when at least one auto-update option is enabled', () => {
12
+ expect(isFailureSensorEnabled({ autoUpdateHomebridge: true })).toBe(true);
13
+ expect(isFailureSensorEnabled({ autoUpdateHomebridgeUI: true })).toBe(true);
14
+ expect(isFailureSensorEnabled({ autoUpdatePlugins: true })).toBe(true);
15
+ expect(isFailureSensorEnabled({ autoUpdateNode: true })).toBe(true);
16
+ expect(isFailureSensorEnabled({ autoUpdateNpm: true })).toBe(true);
17
+ });
18
+ it('should return false when failureSensorType is "none" even if auto-updates are enabled', () => {
19
+ const config = {
20
+ failureSensorType: 'none',
21
+ autoUpdateHomebridge: true,
22
+ autoUpdateHomebridgeUI: true,
23
+ autoUpdatePlugins: true,
24
+ autoUpdateNode: true,
25
+ autoUpdateNpm: true,
26
+ };
27
+ expect(isFailureSensorEnabled(config)).toBe(false);
28
+ });
29
+ it('should return true when failureSensorType is a valid sensor and auto-update is enabled', () => {
30
+ expect(isFailureSensorEnabled({ failureSensorType: 'motion', autoUpdateHomebridge: true })).toBe(true);
31
+ expect(isFailureSensorEnabled({ failureSensorType: 'contact', autoUpdatePlugins: true })).toBe(true);
32
+ });
33
+ });
34
+ describe('createPlatformProxy', () => {
35
+ it('should fall back to HAP platform when Matter is not available', () => {
36
+ const hapConstructed = [];
37
+ const matterConstructed = [];
38
+ class MockHAPPlatform {
39
+ constructor(log, config, api) {
40
+ hapConstructed.push({ log, config, api });
41
+ }
42
+ }
43
+ class MockMatterPlatform {
44
+ constructor(log, config, api) {
45
+ matterConstructed.push({ log, config, api });
46
+ }
47
+ }
48
+ const ProxyCtor = createPlatformProxy(MockHAPPlatform, MockMatterPlatform);
49
+ // api without Matter support
50
+ const api = {};
51
+ new ProxyCtor('log', { enableMatter: true }, api);
52
+ expect(hapConstructed).toHaveLength(1);
53
+ expect(matterConstructed).toHaveLength(0);
54
+ });
55
+ it('should use Matter platform when Matter is available and enabled', () => {
56
+ const hapConstructed = [];
57
+ const matterConstructed = [];
58
+ class MockHAPPlatform {
59
+ constructor(log, config, api) {
60
+ hapConstructed.push({ log, config, api });
61
+ }
62
+ }
63
+ class MockMatterPlatform {
64
+ constructor(log, config, api) {
65
+ matterConstructed.push({ log, config, api });
66
+ }
67
+ }
68
+ const ProxyCtor = createPlatformProxy(MockHAPPlatform, MockMatterPlatform);
69
+ // api with Matter support available and enabled
70
+ const api = {
71
+ matter: {},
72
+ isMatterAvailable: () => true,
73
+ isMatterEnabled: () => true,
74
+ };
75
+ new ProxyCtor('log', { enableMatter: true }, api);
76
+ expect(matterConstructed).toHaveLength(1);
77
+ expect(hapConstructed).toHaveLength(0);
78
+ });
79
+ it('should fall back to HAP when enableMatter is false', () => {
80
+ const hapConstructed = [];
81
+ const matterConstructed = [];
82
+ class MockHAPPlatform {
83
+ constructor(log, config, api) {
84
+ hapConstructed.push({ log, config, api });
85
+ }
86
+ }
87
+ class MockMatterPlatform {
88
+ constructor(log, config, api) {
89
+ matterConstructed.push({ log, config, api });
90
+ }
91
+ }
92
+ const ProxyCtor = createPlatformProxy(MockHAPPlatform, MockMatterPlatform);
93
+ // Matter available but disabled in config
94
+ const api = {
95
+ matter: {},
96
+ isMatterAvailable: () => true,
97
+ isMatterEnabled: () => true,
98
+ };
99
+ new ProxyCtor('log', { enableMatter: false }, api);
100
+ expect(hapConstructed).toHaveLength(1);
101
+ expect(matterConstructed).toHaveLength(0);
102
+ });
103
+ it('should use Matter when isMatter* APIs are unavailable but matter API exists', () => {
104
+ const hapConstructed = [];
105
+ const matterConstructed = [];
106
+ class MockHAPPlatform {
107
+ constructor(log, config, api) {
108
+ hapConstructed.push({ log, config, api });
109
+ }
110
+ }
111
+ class MockMatterPlatform {
112
+ constructor(log, config, api) {
113
+ matterConstructed.push({ log, config, api });
114
+ }
115
+ }
116
+ const ProxyCtor = createPlatformProxy(MockHAPPlatform, MockMatterPlatform);
117
+ // API shape used in some Homebridge versions/plugins where isMatter* may not exist.
118
+ const api = {
119
+ matter: {},
120
+ };
121
+ new ProxyCtor('log', { enableMatter: true }, api);
122
+ expect(matterConstructed).toHaveLength(1);
123
+ expect(hapConstructed).toHaveLength(0);
124
+ });
125
+ });
126
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../src/utils.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@homebridge-plugins/homebridge-updater",
3
+ "displayName": "Homebridge Updater",
4
+ "type": "module",
5
+ "version": "3.0.7",
6
+ "description": "A Homebridge plugin for checking for updates to Homebridge and plugins",
7
+ "author": "David Maher",
8
+ "license": "BSD-2-Clause",
9
+ "funding": [
10
+ {
11
+ "type": "kofi",
12
+ "url": "https://ko-fi.com/sunookitsune"
13
+ },
14
+ {
15
+ "type": "paypal",
16
+ "url": "https://paypal.me/sunoo"
17
+ },
18
+ {
19
+ "type": "github",
20
+ "url": "https://github.com/Sunoo"
21
+ },
22
+ {
23
+ "type": "liberapay",
24
+ "url": "https://liberapay.com/Sunoo"
25
+ }
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "homepage": "https://github.com/homebridge-plugins/homebridge-updater#readme",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/homebridge-plugins/homebridge-updater.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/homebridge-plugins/homebridge-updater/issues"
37
+ },
38
+ "keywords": [
39
+ "homebridge-plugin",
40
+ "plugin",
41
+ "update",
42
+ "updates",
43
+ "upgrade",
44
+ "upgrades",
45
+ "version",
46
+ "versions"
47
+ ],
48
+ "main": "dist/index.js",
49
+ "files": [
50
+ "LICENSE",
51
+ "README.md",
52
+ "config.schema.json",
53
+ "dist/**/*",
54
+ "package.json"
55
+ ],
56
+ "engines": {
57
+ "homebridge": "^1.11.4 || ^2.0.0-beta.111",
58
+ "node": "^22 || ^24"
59
+ },
60
+ "scripts": {
61
+ "check": "npm install && npm outdated",
62
+ "lint": "eslint src/**/*.ts",
63
+ "lint:fix": "eslint src/**/*.ts --fix",
64
+ "watch": "npm run build && npm run plugin-ui && npm link && nodemon",
65
+ "plugin-ui": "rsync ./src/homebridge-ui/public/index.html ./dist/homebridge-ui/public/",
66
+ "build": "npm run clean && tsc && npm run plugin-ui",
67
+ "prepublishOnly": "npm run lint && npm run build && npm run plugin-ui && npm run docs && npm run docs:lint",
68
+ "postpublish": "npm run clean && npm ci",
69
+ "clean": "shx rm -rf ./dist",
70
+ "test": "vitest run",
71
+ "test:watch": "vitest watch",
72
+ "test-coverage": "npm run test -- --coverage",
73
+ "docs": "typedoc",
74
+ "docs:lint": "typedoc --emit none --treatWarningsAsErrors"
75
+ },
76
+ "dependencies": {
77
+ "@homebridge/plugin-ui-utils": "^2.2.3",
78
+ "cacheable-lookup": "^7.0.0",
79
+ "croner": "^10.0.1",
80
+ "jsonwebtoken": "^9.0.3"
81
+ },
82
+ "devDependencies": {
83
+ "@antfu/eslint-config": "^8.2.0",
84
+ "@types/debug": "^4.1.13",
85
+ "@types/node": "^25.6.0",
86
+ "@vitest/coverage-v8": "^4.1.5",
87
+ "eslint": "^10.3.0",
88
+ "eslint-plugin-format": "^2.0.1",
89
+ "homebridge": "^2.0.0-beta.111",
90
+ "homebridge-config-ui-x": "^5.22.0",
91
+ "nodemon": "^3.1.14",
92
+ "shx": "^0.4.0",
93
+ "typedoc": "^0.28.19",
94
+ "vitest": "^4.1.5"
95
+ }
96
+ }