@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,24 @@
1
+ import type { PlatformIdentifier, PlatformName } from 'homebridge';
2
+ export interface PluginUpdatePlatformConfig {
3
+ autoUpdateNode?: boolean;
4
+ checkNodeUpdates?: boolean;
5
+ autoUpdateNpm?: boolean;
6
+ checkNpmUpdates?: boolean;
7
+ name: string;
8
+ platform: PlatformName | PlatformIdentifier;
9
+ sensorType?: string;
10
+ checkHomebridgeUpdates?: boolean;
11
+ checkHomebridgeUIUpdates?: boolean;
12
+ checkPluginUpdates?: boolean;
13
+ checkDockerUpdates?: boolean;
14
+ initialCheckDelay?: number;
15
+ autoUpdateHomebridge?: boolean;
16
+ autoUpdateHomebridgeUI?: boolean;
17
+ autoUpdatePlugins?: boolean;
18
+ allowDirectNpmUpdates?: boolean;
19
+ autoRestartAfterUpdates?: boolean;
20
+ failureSensorType?: string;
21
+ respectDisabledPlugins?: boolean;
22
+ enableMatter?: boolean;
23
+ }
24
+ //# sourceMappingURL=configTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configTypes.d.ts","sourceRoot":"","sources":["../src/configTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAElE,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,YAAY,GAAG,kBAAkB,CAAA;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,wBAAwB,CAAC,EAAE,OAAO,CAAA;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configTypes.js","sourceRoot":"","sources":["../src/configTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configTypes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configTypes.test.d.ts","sourceRoot":"","sources":["../src/configTypes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ describe('pluginUpdatePlatformConfig', () => {
3
+ it('should allow valid platform name and identifier', () => {
4
+ const config = {
5
+ name: 'Example Platform',
6
+ platform: 'ExamplePlatform',
7
+ };
8
+ expect(config.name).toBe('Example Platform');
9
+ expect(config.platform).toBe('ExamplePlatform');
10
+ });
11
+ it('should allow optional sensorType property', () => {
12
+ const config = {
13
+ name: 'Example Platform',
14
+ platform: 'ExamplePlatform',
15
+ sensorType: 'temperature',
16
+ };
17
+ expect(config.sensorType).toBe('temperature');
18
+ });
19
+ it('should allow optional initialCheckDelay property', () => {
20
+ const config = {
21
+ name: 'Example Platform',
22
+ platform: 'ExamplePlatform',
23
+ initialCheckDelay: 30,
24
+ };
25
+ expect(config.initialCheckDelay).toBe(30);
26
+ });
27
+ it('should allow all properties to be set', () => {
28
+ const config = {
29
+ name: 'Example Platform',
30
+ platform: 'ExamplePlatform',
31
+ sensorType: 'humidity',
32
+ checkHomebridgeUpdates: true,
33
+ checkHomebridgeUIUpdates: true,
34
+ checkPluginUpdates: true,
35
+ checkDockerUpdates: true,
36
+ checkNpmUpdates: true,
37
+ initialCheckDelay: 15,
38
+ autoUpdateNpm: false,
39
+ autoUpdateHomebridge: true,
40
+ autoUpdateHomebridgeUI: false,
41
+ autoUpdatePlugins: true,
42
+ allowDirectNpmUpdates: false,
43
+ };
44
+ expect(config.platform).toBe('ExamplePlatform');
45
+ expect(config.sensorType).toBe('humidity');
46
+ expect(config.checkHomebridgeUpdates).toBe(true);
47
+ expect(config.checkHomebridgeUIUpdates).toBe(true);
48
+ expect(config.checkPluginUpdates).toBe(true);
49
+ expect(config.checkDockerUpdates).toBe(true);
50
+ expect(config.checkNpmUpdates).toBe(true);
51
+ expect(config.initialCheckDelay).toBe(15);
52
+ expect(config.autoUpdateNpm).toBe(false);
53
+ expect(config.autoUpdateHomebridge).toBe(true);
54
+ expect(config.autoUpdateHomebridgeUI).toBe(false);
55
+ expect(config.autoUpdatePlugins).toBe(true);
56
+ expect(config.allowDirectNpmUpdates).toBe(false);
57
+ });
58
+ it('should allow auto-update properties to be set independently', () => {
59
+ const config = {
60
+ name: 'Example Platform',
61
+ platform: 'ExamplePlatform',
62
+ autoUpdateHomebridge: true,
63
+ autoUpdateHomebridgeUI: false,
64
+ autoUpdatePlugins: true,
65
+ autoUpdateNpm: false,
66
+ };
67
+ expect(config.name).toBe('Example Platform');
68
+ expect(config.autoUpdateHomebridge).toBe(true);
69
+ expect(config.autoUpdateHomebridgeUI).toBe(false);
70
+ expect(config.autoUpdatePlugins).toBe(true);
71
+ expect(config.autoUpdateNpm).toBe(false);
72
+ });
73
+ it('should allow npm update properties to be set independently', () => {
74
+ const config = {
75
+ name: 'Example Platform',
76
+ platform: 'ExamplePlatform',
77
+ checkNpmUpdates: true,
78
+ autoUpdateNpm: true,
79
+ };
80
+ expect(config.checkNpmUpdates).toBe(true);
81
+ expect(config.autoUpdateNpm).toBe(true);
82
+ });
83
+ it('should allow allowDirectNpmUpdates property to be set', () => {
84
+ const config = {
85
+ name: 'Example Platform',
86
+ platform: 'ExamplePlatform',
87
+ allowDirectNpmUpdates: true,
88
+ };
89
+ expect(config.allowDirectNpmUpdates).toBe(true);
90
+ });
91
+ it('should allow autoRestartAfterUpdates property to be set', () => {
92
+ const config = {
93
+ name: 'Example Platform',
94
+ platform: 'ExamplePlatform',
95
+ autoRestartAfterUpdates: true,
96
+ };
97
+ expect(config.autoRestartAfterUpdates).toBe(true);
98
+ });
99
+ it('should allow enableMatter property to be set', () => {
100
+ const config = {
101
+ name: 'Example Platform',
102
+ platform: 'ExamplePlatform',
103
+ enableMatter: false,
104
+ };
105
+ expect(config.enableMatter).toBe(false);
106
+ });
107
+ });
108
+ //# sourceMappingURL=configTypes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configTypes.test.js","sourceRoot":"","sources":["../src/configTypes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { API, Logging, PlatformAccessory } from 'homebridge';
2
+ /**
3
+ * Manages a failure sensor for automatic update operations.
4
+ * This sensor is triggered when automatic updates fail.
5
+ */
6
+ export declare class FailureSensor {
7
+ private readonly log;
8
+ private readonly protocolSensor;
9
+ constructor(log: Logging, api: API, sensorType?: string, protocol?: 'hap' | 'matter');
10
+ configure(accessory: PlatformAccessory): void;
11
+ /**
12
+ * Set the failure sensor state
13
+ * @param failed - true if failure detected, false for normal operation
14
+ */
15
+ setState(failed: boolean): void;
16
+ }
17
+ //# sourceMappingURL=failureSensor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failureSensor.d.ts","sourceRoot":"","sources":["../src/failureSensor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAMjE;;;GAGG;AAEH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;gBAEnC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,KAAK,GAAG,QAAgB;IAW3F,SAAS,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAQ7C;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;CAIhC"}
@@ -0,0 +1,36 @@
1
+ import { HAPSensor, MatterSensor } from './sensorBase.js';
2
+ /**
3
+ * Manages a failure sensor for automatic update operations.
4
+ * This sensor is triggered when automatic updates fail.
5
+ */
6
+ export class FailureSensor {
7
+ log;
8
+ protocolSensor;
9
+ constructor(log, api, sensorType, protocol = 'hap') {
10
+ this.log = log;
11
+ const options = { log, api, sensorType };
12
+ // Choose protocol implementation
13
+ if (protocol === 'matter') {
14
+ this.protocolSensor = new MatterSensor(options);
15
+ }
16
+ else {
17
+ this.protocolSensor = new HAPSensor(options);
18
+ }
19
+ }
20
+ configure(accessory) {
21
+ this.protocolSensor.configure(accessory);
22
+ // Only set initial state immediately for HAP, not Matter
23
+ if (this.protocolSensor instanceof HAPSensor) {
24
+ this.setState(false);
25
+ }
26
+ }
27
+ /**
28
+ * Set the failure sensor state
29
+ * @param failed - true if failure detected, false for normal operation
30
+ */
31
+ setState(failed) {
32
+ this.protocolSensor.setState(failed);
33
+ this.log.debug(`[FailureSensor] Set to ${failed ? 'triggered' : 'normal'} state`);
34
+ }
35
+ }
36
+ //# sourceMappingURL=failureSensor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failureSensor.js","sourceRoot":"","sources":["../src/failureSensor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEzD;;;GAGG;AAEH,MAAM,OAAO,aAAa;IACP,GAAG,CAAS;IACZ,cAAc,CAAgB;IAE/C,YAAY,GAAY,EAAE,GAAQ,EAAE,UAAmB,EAAE,WAA6B,KAAK;QACzF,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,MAAM,OAAO,GAAkB,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,CAAA;QACvD,iCAAiC;QACjC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,cAAc,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAED,SAAS,CAAC,SAA4B;QACpC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QACxC,yDAAyD;QACzD,IAAI,IAAI,CAAC,cAAc,YAAY,SAAS,EAAE,CAAC;YAC7C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,MAAe;QACtB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,QAAQ,CAAC,CAAA;IACnF,CAAC;CACF"}
@@ -0,0 +1,230 @@
1
+ <p class="text-center">
2
+ <img
3
+ src="https://raw.githubusercontent.com/homebridge/branding/latest/logos/homebridge-color-round.svg"
4
+ alt="homebridge-updater logo" style="width: 25%" />
5
+ </p>
6
+ <div id="pageIntro" style="display: none">
7
+ <p class="lead text-center">Thank you for installing <strong>homebridge-updater</strong></p>
8
+ <div class="text-center">
9
+ <button type="button" class="btn btn-primary" id="introLink">Continue &rarr;</button>
10
+ </div>
11
+ </div>
12
+ <div id="menuWrapper" class="btn-group w-100 mb-0" role="group" aria-label="UI Menu" style="display: none">
13
+ <button type="button" class="btn btn-primary" id="menuSettings">Settings</button>
14
+ <button type="button" class="btn btn-primary" id="menuDevices">Devices</button>
15
+ <button type="button" class="btn btn-primary mr-0" id="menuHome">Support</button>
16
+ </div>
17
+ <div id="disabledBanner" class="alert alert-secondary mb-0 mt-3" role="alert" style="display: none">
18
+ Plugin is currently disabled
19
+ <button id="disabledEnable" type="button" class="btn btn-link p-0 m-0 float-right">Enable</button>
20
+ </div>
21
+ <div id="pageDevices" class="mt-4" style="display: none">
22
+ <div id="deviceInfo">
23
+ <form>
24
+ <div class="form-group">
25
+ <select class="form-control" id="deviceSelect"></select>
26
+ </div>
27
+ </form>
28
+ <table class="table w-100" id="deviceTable" style="display: none">
29
+ <thead>
30
+ <tr class="table-active">
31
+ <th scope="col" style="width: 40%">Device Name</th>
32
+ <th scope="col" style="width: 60%" id="displayName"></th>
33
+ </tr>
34
+ </thead>
35
+ <tbody>
36
+ <tr>
37
+ <th scope="row">Serial Number</th>
38
+ <td id="serialNumber"></td>
39
+ </tr>
40
+ <tr>
41
+ <th scope="row">Model</th>
42
+ <td id="model"></td>
43
+ </tr>
44
+ <tr>
45
+ <th scope="row">Firmware Version</th>
46
+ <td id="firmwareRevision"></td>
47
+ </tr>
48
+ </tbody>
49
+ </table>
50
+ </div>
51
+ </div>
52
+ <div id="pageSupport" class="mt-4" style="display: none">
53
+ <p class="text-center lead">Thank you for using <strong>homebridge-updater</strong></p>
54
+ <p class="text-center">The links below will take you to our GitHub wiki</p>
55
+ <h5>Setup</h5>
56
+ <ul>
57
+ <li>
58
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki" target="_blank">Wiki Home</a>
59
+ </li>
60
+ <li>
61
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Configuration"
62
+ target="_blank">Configuration</a>
63
+ </li>
64
+ <li>
65
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Beta-Version"
66
+ target="_blank">Beta
67
+ Version</a>
68
+ </li>
69
+ <li>
70
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Node-Version"
71
+ target="_blank">Node
72
+ Version</a>
73
+ </li>
74
+ <li>
75
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Uninstallation"
76
+ target="_blank">Uninstallation</a>
77
+ </li>
78
+ </ul>
79
+ <h5>Features</h5>
80
+ <ul>
81
+ <li>
82
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Supported-Devices"
83
+ target="_blank">Supported Devices</a>
84
+ </li>
85
+ <li>
86
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/wiki/Fan-Modes" target="_blank">Fan
87
+ Modes</a>
88
+ </li>
89
+ </ul>
90
+ <h5>Help/About</h5>
91
+ <ul>
92
+ <li>
93
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/issues/new/choose"
94
+ target="_blank">Support
95
+ Request</a>
96
+ </li>
97
+ <li>
98
+ <a href="https://github.com/homebridge-plugins/homebridge-updater/blob/latest/CHANGELOG.md"
99
+ target="_blank">Changelog</a>
100
+ </li>
101
+ <li>
102
+ <a href="https://github.com/Sunoo" target="_blank">About Me</a>
103
+ </li>
104
+ </ul>
105
+ </div>
106
+ <script>
107
+ (async () => {
108
+ try {
109
+ const currentConfig = await homebridge.getPluginConfig();
110
+ showIntro = () => {
111
+ const introLink = document.getElementById('introLink');
112
+ introLink.addEventListener('click', () => {
113
+ homebridge.showSpinner();
114
+ document.getElementById('pageIntro').style.display = 'none';
115
+ document.getElementById('menuWrapper').style.display = 'inline-flex';
116
+ showSettings();
117
+ homebridge.hideSpinner();
118
+ });
119
+ document.getElementById('menuWrapper').style.display = 'none';
120
+ document.getElementById('pageIntro').style.display = 'block';
121
+ };
122
+ showDevices = async () => {
123
+ homebridge.showSpinner();
124
+ homebridge.hideSchemaForm();
125
+ document.getElementById('menuHome').classList.remove('btn-elegant');
126
+ document.getElementById('menuHome').classList.add('btn-primary');
127
+ document.getElementById('menuDevices').classList.add('btn-elegant');
128
+ document.getElementById('menuDevices').classList.remove('btn-primary');
129
+ document.getElementById('menuSettings').classList.remove('btn-elegant');
130
+ document.getElementById('menuSettings').classList.add('btn-primary');
131
+ document.getElementById('pageSupport').style.display = 'none';
132
+ document.getElementById('pageDevices').style.display = 'block';
133
+ const cachedAccessories =
134
+ typeof homebridge.getCachedAccessories === 'function'
135
+ ? await homebridge.getCachedAccessories()
136
+ : await homebridge.request('/getCachedAccessories');
137
+ if (cachedAccessories.length > 0) {
138
+ cachedAccessories.sort((a, b) => {
139
+ return a.displayName.toLowerCase() > b.displayName.toLowerCase() ? 1 : b.displayName.toLowerCase() > a.displayName.toLowerCase() ? -1 : 0;
140
+ });
141
+ }
142
+ const deviceSelect = document.getElementById('deviceSelect');
143
+ deviceSelect.innerHTML = '';
144
+ cachedAccessories.forEach((a) => {
145
+ const option = document.createElement('option');
146
+ option.text = a.displayName;
147
+ option.value = a.UUID;
148
+ deviceSelect.add(option);
149
+ });
150
+ showDeviceInfo = async (UUID) => {
151
+ homebridge.showSpinner();
152
+ const thisAcc = cachedAccessories.find((x) => x.UUID === UUID);
153
+ const context = thisAcc.context;
154
+ document.getElementById('displayName').innerHTML = thisAcc.displayName;
155
+ document.getElementById('serialNumber').innerHTML = context.serialNumber;
156
+ document.getElementById('model').innerHTML = context.model;
157
+ document.getElementById('firmwareRevision').innerHTML = context.firmwareRevision || 'N/A';
158
+ document.getElementById('deviceTable').style.display = 'inline-table';
159
+ homebridge.hideSpinner();
160
+ };
161
+ deviceSelect.addEventListener('change', (event) => showDeviceInfo(event.target.value));
162
+ if (cachedAccessories.length > 0) {
163
+ showDeviceInfo(cachedAccessories[0].UUID);
164
+ } else {
165
+ const option = document.createElement('option');
166
+ option.text = 'No Devices';
167
+ deviceSelect.add(option);
168
+ deviceSelect.disabled = true;
169
+ }
170
+ homebridge.hideSpinner();
171
+ };
172
+ showSupport = () => {
173
+ homebridge.showSpinner();
174
+ homebridge.hideSchemaForm();
175
+ document.getElementById('menuHome').classList.add('btn-elegant');
176
+ document.getElementById('menuHome').classList.remove('btn-primary');
177
+ document.getElementById('menuDevices').classList.remove('btn-elegant');
178
+ document.getElementById('menuDevices').classList.add('btn-primary');
179
+ document.getElementById('menuSettings').classList.remove('btn-elegant');
180
+ document.getElementById('menuSettings').classList.add('btn-primary');
181
+ document.getElementById('pageSupport').style.display = 'block';
182
+ document.getElementById('pageDevices').style.display = 'none';
183
+ homebridge.hideSpinner();
184
+ };
185
+ showSettings = () => {
186
+ homebridge.showSpinner();
187
+ document.getElementById('menuHome').classList.remove('btn-elegant');
188
+ document.getElementById('menuHome').classList.add('btn-primary');
189
+ document.getElementById('menuDevices').classList.remove('btn-elegant');
190
+ document.getElementById('menuDevices').classList.add('btn-primary');
191
+ document.getElementById('menuSettings').classList.add('btn-elegant');
192
+ document.getElementById('menuSettings').classList.remove('btn-primary');
193
+ document.getElementById('pageSupport').style.display = 'none';
194
+ document.getElementById('pageDevices').style.display = 'none';
195
+ homebridge.showSchemaForm();
196
+ homebridge.hideSpinner();
197
+ };
198
+ showDisabledBanner = () => {
199
+ document.getElementById('disabledBanner').style.display = 'block';
200
+ };
201
+ enablePlugin = async () => {
202
+ homebridge.showSpinner();
203
+ document.getElementById('disabledBanner').style.display = 'none';
204
+ currentConfig[0].disablePlugin = false;
205
+ await homebridge.updatePluginConfig(currentConfig);
206
+ await homebridge.savePluginConfig();
207
+ homebridge.hideSpinner();
208
+ };
209
+ menuHome.addEventListener('click', () => showSupport());
210
+ menuDevices.addEventListener('click', () => showDevices());
211
+ menuSettings.addEventListener('click', () => showSettings());
212
+ disabledEnable.addEventListener('click', () => enablePlugin());
213
+ if (currentConfig.length) {
214
+ document.getElementById('menuWrapper').style.display = 'inline-flex';
215
+ showSettings();
216
+ if (currentConfig[0].disablePlugin) {
217
+ showDisabledBanner();
218
+ }
219
+ } else {
220
+ currentConfig.push({ name: 'PluginUpdate' });
221
+ await homebridge.updatePluginConfig(currentConfig);
222
+ showIntro();
223
+ }
224
+ } catch (err) {
225
+ homebridge.toast.error(err.message, 'Error');
226
+ } finally {
227
+ homebridge.hideSpinner();
228
+ }
229
+ })();
230
+ </script>
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import fs from 'node:fs';
2
+ /* Copyright(C) 2021-2024, David Maher (https://github.com/sunoo). All rights reserved.
3
+ *
4
+ * server.ts: homebridge-updater.
5
+ */
6
+ import { HomebridgePluginUiServer } from '@homebridge/plugin-ui-utils';
7
+ class PluginUiServer extends HomebridgePluginUiServer {
8
+ constructor() {
9
+ super();
10
+ /*
11
+ A native method getCachedAccessories() was introduced in config-ui-x v4.37.0
12
+ The following is for users who have a lower version of config-ui-x
13
+ */
14
+ this.onRequest('getCachedAccessories', () => {
15
+ try {
16
+ const plugin = '@homebridge-plugins/homebridge-updater';
17
+ const devicesToReturn = [];
18
+ // The path and file of the cached accessories
19
+ const accFile = `${this.homebridgeStoragePath}/accessories/cachedAccessories`;
20
+ // Check the file exists
21
+ if (fs.existsSync(accFile)) {
22
+ // read the cached accessories file
23
+ const cachedAccessories = JSON.parse(fs.readFileSync(accFile, 'utf8'));
24
+ cachedAccessories.forEach((accessory) => {
25
+ // Check the accessory is from this plugin
26
+ if (accessory.plugin === plugin) {
27
+ // Add the cached accessory to the array
28
+ devicesToReturn.push(accessory.accessory);
29
+ }
30
+ });
31
+ }
32
+ // Return the array
33
+ return devicesToReturn;
34
+ }
35
+ catch {
36
+ // Just return an empty accessory list in case of any errors
37
+ return [];
38
+ }
39
+ });
40
+ this.ready();
41
+ }
42
+ }
43
+ function startPluginUiServer() {
44
+ return new PluginUiServer();
45
+ }
46
+ startPluginUiServer();
47
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/homebridge-ui/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AAExB;;;GAGG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AAEtE,MAAM,cAAe,SAAQ,wBAAwB;IACnD;QACE,KAAK,EAAE,CAAA;QACP;;;UAGE;QACF,IAAI,CAAC,SAAS,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC1C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,wCAAwC,CAAA;gBACvD,MAAM,eAAe,GAAG,EAAE,CAAA;gBAE1B,8CAA8C;gBAC9C,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,qBAAqB,gCAAgC,CAAA;gBAE7E,wBAAwB;gBACxB,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,mCAAmC;oBACnC,MAAM,iBAAiB,GAAU,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;oBAE7E,iBAAiB,CAAC,OAAO,CAAC,CAAC,SAAc,EAAE,EAAE;wBAC3C,0CAA0C;wBAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;4BAChC,wCAAwC;4BACxC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,SAAkB,CAAC,CAAA;wBACpD,CAAC;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC;gBACD,mBAAmB;gBACnB,OAAO,eAAe,CAAA;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;gBAC5D,OAAO,EAAE,CAAA;YACX,CAAC;QACH,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;CACF;AAED,SAAS,mBAAmB;IAC1B,OAAO,IAAI,cAAc,EAAE,CAAA;AAC7B,CAAC;AAED,mBAAmB,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ignore-plugins.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore-plugins.test.d.ts","sourceRoot":"","sources":["../src/ignore-plugins.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,121 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ // Test for the plugin filtering logic
3
+ describe('plugin Update Filtering', () => {
4
+ it('should filter plugins correctly based on ignore list', () => {
5
+ // Mock plugin data similar to what would come from the API
6
+ const mockPlugins = [
7
+ {
8
+ name: 'homebridge-plugin-1',
9
+ installedVersion: '1.0.0',
10
+ latestVersion: '1.1.0',
11
+ updateAvailable: true,
12
+ },
13
+ {
14
+ name: 'homebridge-plugin-2',
15
+ installedVersion: '2.0.0',
16
+ latestVersion: '2.1.0',
17
+ updateAvailable: true,
18
+ },
19
+ {
20
+ name: 'homebridge-config-ui-x',
21
+ installedVersion: '4.0.0',
22
+ latestVersion: '4.1.0',
23
+ updateAvailable: true,
24
+ },
25
+ {
26
+ name: 'homebridge-plugin-3',
27
+ installedVersion: '3.0.0',
28
+ latestVersion: '3.1.0',
29
+ updateAvailable: true,
30
+ },
31
+ ];
32
+ const ignoredPlugins = ['homebridge-plugin-2', 'homebridge-plugin-3'];
33
+ // Test the filtering logic that would be used in checkUi()
34
+ const filteredPlugins = mockPlugins.filter(plugin => plugin.name !== 'homebridge-config-ui-x'
35
+ && !ignoredPlugins.includes(plugin.name));
36
+ expect(filteredPlugins).toHaveLength(1);
37
+ expect(filteredPlugins[0].name).toBe('homebridge-plugin-1');
38
+ });
39
+ it('should include all plugins when ignore list is empty', () => {
40
+ const mockPlugins = [
41
+ {
42
+ name: 'homebridge-plugin-1',
43
+ installedVersion: '1.0.0',
44
+ latestVersion: '1.1.0',
45
+ updateAvailable: true,
46
+ },
47
+ {
48
+ name: 'homebridge-plugin-2',
49
+ installedVersion: '2.0.0',
50
+ latestVersion: '2.1.0',
51
+ updateAvailable: true,
52
+ },
53
+ ];
54
+ const ignoredPlugins = [];
55
+ const filteredPlugins = mockPlugins.filter(plugin => plugin.name !== 'homebridge-config-ui-x'
56
+ && !ignoredPlugins.includes(plugin.name));
57
+ expect(filteredPlugins).toHaveLength(2);
58
+ expect(filteredPlugins.map(p => p.name)).toEqual(['homebridge-plugin-1', 'homebridge-plugin-2']);
59
+ });
60
+ it('should correctly identify ignored plugins with updates', () => {
61
+ const mockPlugins = [
62
+ {
63
+ name: 'homebridge-plugin-1',
64
+ installedVersion: '1.0.0',
65
+ latestVersion: '1.1.0',
66
+ updateAvailable: true,
67
+ },
68
+ {
69
+ name: 'homebridge-plugin-ignored',
70
+ installedVersion: '2.0.0',
71
+ latestVersion: '2.1.0',
72
+ updateAvailable: true,
73
+ },
74
+ {
75
+ name: 'homebridge-plugin-no-update',
76
+ installedVersion: '3.0.0',
77
+ latestVersion: '3.0.0',
78
+ updateAvailable: false,
79
+ },
80
+ ];
81
+ const ignoredPlugins = ['homebridge-plugin-ignored'];
82
+ // Test identifying ignored plugins with available updates
83
+ const ignoredWithUpdates = mockPlugins.filter(plugin => ignoredPlugins.includes(plugin.name) && plugin.updateAvailable);
84
+ expect(ignoredWithUpdates).toHaveLength(1);
85
+ expect(ignoredWithUpdates[0].name).toBe('homebridge-plugin-ignored');
86
+ });
87
+ it('should filter homebridge-config-ui-x when in ignore list', () => {
88
+ const mockPlugins = [
89
+ {
90
+ name: 'homebridge-config-ui-x',
91
+ installedVersion: '4.0.0',
92
+ latestVersion: '4.1.0',
93
+ updateAvailable: true,
94
+ },
95
+ ];
96
+ const ignoredPlugins = ['homebridge-config-ui-x'];
97
+ // Test filtering homebridge-config-ui-x updates when ignored
98
+ const shouldFilterUI = ignoredPlugins.includes('homebridge-config-ui-x');
99
+ expect(shouldFilterUI).toBe(true);
100
+ // Simulate what would happen in the checkUi() method
101
+ const uiPlugin = mockPlugins.find(plugin => plugin.name === 'homebridge-config-ui-x');
102
+ const shouldAddUpdate = uiPlugin && uiPlugin.updateAvailable && !shouldFilterUI;
103
+ expect(shouldAddUpdate).toBe(false);
104
+ });
105
+ it('should filter homebridge core updates when in ignore list', () => {
106
+ const mockHomebridge = {
107
+ name: 'homebridge',
108
+ installedVersion: '1.0.0',
109
+ latestVersion: '1.1.0',
110
+ updateAvailable: true,
111
+ };
112
+ const ignoredPlugins = ['homebridge'];
113
+ // Test filtering homebridge core updates when ignored
114
+ const shouldFilterHomebridge = ignoredPlugins.includes('homebridge');
115
+ expect(shouldFilterHomebridge).toBe(true);
116
+ // Simulate what would happen in the checkUi() method
117
+ const shouldAddUpdate = mockHomebridge.updateAvailable && !shouldFilterHomebridge;
118
+ expect(shouldAddUpdate).toBe(false);
119
+ });
120
+ });
121
+ //# sourceMappingURL=ignore-plugins.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore-plugins.test.js","sourceRoot":"","sources":["../src/ignore-plugins.test.ts"],"names":[],"mappings":"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"}