@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
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2021-2024, David Maher
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # homebridge-updater
2
+
3
+ [![npm](https://img.shields.io/npm/v/@homebridge-plugins/homebridge-updater) ![npm](https://img.shields.io/npm/dt/@homebridge-plugins/homebridge-updater)](https://www.npmjs.com/package/@homebridge-plugins/homebridge-updater) [![verified-by-homebridge](https://badgen.net/badge/homebridge/verified/purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
4
+
5
+ A [Homebridge](https://github.com/nfarina/homebridge) plugin that reports update availability as sensors and can optionally run automatic updates.
6
+
7
+ ## Features
8
+
9
+ - Works with both HomeKit Accessory Protocol (HAP) and Matter at runtime
10
+ - Exposes an update availability sensor
11
+ - Exposes an optional failure sensor for automatic update/restart failures
12
+ - Checks for updates to Node.js (LTS), Homebridge, Homebridge UI, plugins, and Docker images
13
+ - Supports optional auto-updates for Node.js, Homebridge, Homebridge UI, and plugins
14
+ - Intentionally does not auto-update Docker containers (check-only)
15
+
16
+ ## Installation
17
+
18
+ 1. Install Homebridge using the [official instructions](https://github.com/homebridge/homebridge/wiki).
19
+ 2. Install this plugin using: `sudo npm install -g @homebridge-plugins/homebridge-updater`.
20
+ 3. Update your configuration file. See sample config.json snippet below.
21
+
22
+ ### Configuration
23
+
24
+ Configuration sample:
25
+
26
+ ```json
27
+ "platforms": [
28
+ {
29
+ "platform": "HomebridgeUpdater",
30
+ "name": "Plugin Update",
31
+ "sensorType": "contact",
32
+ "failureSensorType": "motion",
33
+ "checkNodeUpdates": true,
34
+ "checkNpmUpdates": true,
35
+ "checkHomebridgeUpdates": true,
36
+ "checkHomebridgeUIUpdates": true,
37
+ "checkPluginUpdates": true,
38
+ "checkDockerUpdates": false,
39
+ "initialCheckDelay": 10,
40
+ "autoUpdateNode": false,
41
+ "autoUpdateNpm": false,
42
+ "autoUpdateHomebridge": false,
43
+ "autoUpdateHomebridgeUI": false,
44
+ "autoUpdatePlugins": false,
45
+ "allowDirectNpmUpdates": false,
46
+ "autoRestartAfterUpdates": false,
47
+ "respectDisabledPlugins": true,
48
+ "enableMatter": true
49
+ }
50
+ ]
51
+ ```
52
+
53
+ #### Fields
54
+
55
+ All sensor type options are:
56
+
57
+ - `motion`
58
+ - `contact`
59
+ - `occupancy`
60
+ - `humidity`
61
+ - `light`
62
+ - `air`
63
+ - `leak`
64
+ - `smoke`
65
+ - `dioxide`
66
+ - `monoxide`
67
+
68
+ `failureSensorType` also supports `none` to disable the failure sensor.
69
+
70
+ | Field | Description | Default |
71
+ | --- | --- | --- |
72
+ | `platform` | Must always be `HomebridgeUpdater` | Required |
73
+ | `name` | Accessory name shown in Home app | `Plugin Update` |
74
+ | `sensorType` | Sensor type for the main update sensor | `motion` |
75
+ | `failureSensorType` | Sensor type for auto-update failure status, or `none` to disable | `motion` |
76
+ | `checkNodeUpdates` | Check for newer Node.js LTS versions | `false` |
77
+ | `checkNpmUpdates` | Check for newer npm versions when npm is installed | `false` |
78
+ | `checkHomebridgeUpdates` | Check for Homebridge server updates | `true` |
79
+ | `checkHomebridgeUIUpdates` | Check for Homebridge Config UI updates | `true` |
80
+ | `checkPluginUpdates` | Check for installed plugin updates | `true` |
81
+ | `checkDockerUpdates` | Check for newer Docker image versions when running in Docker | `false` |
82
+ | `initialCheckDelay` | Delay in seconds before the first check after startup | `10` |
83
+ | `autoUpdateNode` | Automatically run Node.js updates using `hb-service update-node` when supported | `false` |
84
+ | `autoUpdateNpm` | Automatically update npm when a newer version is available | `false` |
85
+ | `autoUpdateHomebridge` | Automatically update Homebridge | `false` |
86
+ | `autoUpdateHomebridgeUI` | Automatically update Homebridge Config UI | `false` |
87
+ | `autoUpdatePlugins` | Automatically update plugins | `false` |
88
+ | `allowDirectNpmUpdates` | Allow direct npm update commands when UI API is unavailable | `false` |
89
+ | `autoRestartAfterUpdates` | Restart Homebridge after successful auto-updates | `false` |
90
+ | `respectDisabledPlugins` | Respect hidden update notifications configured in Homebridge UI | `true` |
91
+ | `enableMatter` | Enable Matter support when available in Homebridge | `true` |
92
+
93
+ ## How It Works
94
+
95
+ - The plugin checks selected update sources on a schedule.
96
+ - If any enabled source has updates, the main sensor is set to active.
97
+ - If automatic updates are enabled and an update/restart fails, the failure sensor is set to active.
98
+ - If no auto-update options are enabled, the failure sensor is automatically not exposed.
99
+
100
+ ## Automatic Updates
101
+
102
+ When automatic updates are enabled, the plugin will:
103
+
104
+ 1. Attempt to create a backup before updates when Homebridge UI is available.
105
+ 2. Perform configured updates (Node.js, Homebridge, Homebridge UI, plugins).
106
+ 3. Optionally restart Homebridge if `autoRestartAfterUpdates` is enabled.
107
+ 4. Surface failures through the failure sensor.
108
+
109
+ Automatic updates are disabled by default. Enable them only if your environment has appropriate permissions and you are comfortable with unattended updates.
110
+
111
+ If Homebridge UI is not configured, automatic updates require `allowDirectNpmUpdates: true`.
112
+
113
+ If npm is not installed in your environment, npm checks and npm auto-update are skipped safely.
114
+
115
+ ## Docker Notes
116
+
117
+ Docker update checks are notification-only. The plugin does not attempt in-container self-updates by design, to avoid interrupting or corrupting the running container.
@@ -0,0 +1,257 @@
1
+ {
2
+ "pluginAlias": "HomebridgeUpdater",
3
+ "pluginType": "platform",
4
+ "singular": true,
5
+ "customUi": true,
6
+ "customUiPath": "./dist/homebridge-ui",
7
+ "headerDisplay": "A Homebridge plugin for checking for updates to Homebridge and plugins.",
8
+ "footerDisplay": "Raise [Issues](https://github.com/homebridge-plugins/homebridge-updater/issues) or submit [Pull Requests](https://github.com/homebridge-plugins/homebridge-updater/pulls) on [Project Page](https://github.com/homebridge-plugins/homebridge-updater).",
9
+ "schema": {
10
+ "type": "object",
11
+ "properties": {
12
+ "name": {
13
+ "title": "Name",
14
+ "type": "string",
15
+ "default": "Plugin Update",
16
+ "description": "A unique name for the accessory. It will be used as the accessory name in HomeKit. Can only contain letters, numbers, spaces, hyphens, and underscores. Periods and other special characters are not allowed as they can cause HomeKit pairing issues.",
17
+ "pattern": "^[a-zA-Z0-9\\s_-]+$",
18
+ "minLength": 1,
19
+ "maxLength": 64
20
+ },
21
+ "sensorType": {
22
+ "title": "Sensor Type",
23
+ "type": "string",
24
+ "default": "motion",
25
+ "description": "What type of sensor will be exposed to HomeKit.",
26
+ "oneOf": [
27
+ {
28
+ "title": "Motion Sensor",
29
+ "enum": ["motion"]
30
+ },
31
+ {
32
+ "title": "Contact Sensor",
33
+ "enum": ["contact"]
34
+ },
35
+ {
36
+ "title": "Occupancy Sensor",
37
+ "enum": ["occupancy"]
38
+ },
39
+ {
40
+ "title": "Humidity Sensor",
41
+ "enum": ["humidity"]
42
+ },
43
+ {
44
+ "title": "Light Sensor",
45
+ "enum": ["light"]
46
+ },
47
+ {
48
+ "title": "Air Quality Sensor",
49
+ "enum": ["air"]
50
+ },
51
+ {
52
+ "title": "Leak Sensor",
53
+ "enum": ["leak"]
54
+ },
55
+ {
56
+ "title": "Smoke Sensor",
57
+ "enum": ["smoke"]
58
+ },
59
+ {
60
+ "title": "Carbon Dioxide Sensor",
61
+ "enum": ["dioxide"]
62
+ },
63
+ {
64
+ "title": "Carbon Monoxide Sensor",
65
+ "enum": ["monoxide"]
66
+ }
67
+ ]
68
+ },
69
+ "failureSensorType": {
70
+ "title": "Failure Sensor Type",
71
+ "type": "string",
72
+ "default": "motion",
73
+ "description": "What type of sensor will be used for update/restart failure notifications (only shown when auto-updates are enabled).",
74
+ "oneOf": [
75
+ {
76
+ "title": "Motion Sensor",
77
+ "enum": ["motion"]
78
+ },
79
+ {
80
+ "title": "Contact Sensor",
81
+ "enum": ["contact"]
82
+ },
83
+ {
84
+ "title": "Occupancy Sensor",
85
+ "enum": ["occupancy"]
86
+ },
87
+ {
88
+ "title": "Humidity Sensor",
89
+ "enum": ["humidity"]
90
+ },
91
+ {
92
+ "title": "Light Sensor",
93
+ "enum": ["light"]
94
+ },
95
+ {
96
+ "title": "Air Quality Sensor",
97
+ "enum": ["air"]
98
+ },
99
+ {
100
+ "title": "Leak Sensor",
101
+ "enum": ["leak"]
102
+ },
103
+ {
104
+ "title": "Smoke Sensor",
105
+ "enum": ["smoke"]
106
+ },
107
+ {
108
+ "title": "Carbon Dioxide Sensor",
109
+ "enum": ["dioxide"]
110
+ },
111
+ {
112
+ "title": "Carbon Monoxide Sensor",
113
+ "enum": ["monoxide"]
114
+ },
115
+ {
116
+ "title": "None (Disabled)",
117
+ "enum": ["none"]
118
+ }
119
+ ]
120
+ },
121
+ "enableMatter": {
122
+ "title": "Enable Matter support",
123
+ "type": "boolean",
124
+ "description": "Enable Homebridge Matter support when running on Homebridge v2.0 or later with Matter enabled.",
125
+ "default": true
126
+ },
127
+ "initialCheckDelay": {
128
+ "title": "Initial Check Delay (seconds)",
129
+ "type": "integer",
130
+ "description": "Delay in seconds before performing the initial update check after startup",
131
+ "default": 10,
132
+ "minimum": 0,
133
+ "maximum": 300
134
+ },
135
+ "checkNodeUpdates": {
136
+ "title": "Check for Node.js updates",
137
+ "type": "boolean",
138
+ "description": "Check if a newer LTS version of Node.js is available.",
139
+ "default": false
140
+ },
141
+ "checkNpmUpdates": {
142
+ "title": "Check for npm updates",
143
+ "type": "boolean",
144
+ "description": "Check if a newer npm version is available. Ignored when npm is not installed.",
145
+ "default": false
146
+ },
147
+ "checkHomebridgeUpdates": {
148
+ "title": "Check for Homebridge updates",
149
+ "type": "boolean",
150
+ "description": "Check if an update is available for the Homebridge server",
151
+ "default": true
152
+ },
153
+ "checkHomebridgeUIUpdates": {
154
+ "title": "Check for Homebridge Config UI updates",
155
+ "type": "boolean",
156
+ "description": "Check if an update is available for the Homebridge UI",
157
+ "default": true
158
+ },
159
+ "checkPluginUpdates": {
160
+ "title": "Check for plugin updates",
161
+ "type": "boolean",
162
+ "description": "Check if updates are available for any installed plugins",
163
+ "default": true
164
+ },
165
+ "checkDockerUpdates": {
166
+ "title": "Check for Docker image updates",
167
+ "type": "boolean",
168
+ "description": "Check if Docker image updates are available (ignored if not running in Docker container)"
169
+ },
170
+ "respectDisabledPlugins": {
171
+ "title": "Respect disabled plugin update notifications",
172
+ "type": "boolean",
173
+ "description": "When enabled, respects the 'Hide update notifications for this plugin' setting from homebridge-config-ui-x. Plugins marked to hide updates will not trigger notifications.",
174
+ "default": true
175
+ },
176
+ "autoUpdateNode": {
177
+ "title": "Auto-update Node.js",
178
+ "type": "boolean",
179
+ "description": "Automatically update Node.js using hb-service update-node when a new LTS version is available and supported.",
180
+ "default": false
181
+ },
182
+ "autoUpdateNpm": {
183
+ "title": "Auto-update npm",
184
+ "type": "boolean",
185
+ "description": "Automatically update npm when a newer version is available. Ignored when npm is not installed.",
186
+ "default": false
187
+ },
188
+ "autoUpdateHomebridge": {
189
+ "title": "Auto-update Homebridge",
190
+ "type": "boolean",
191
+ "description": "Automatically install Homebridge updates when available (requires homebridge-config-ui-x and sufficient npm privileges)",
192
+ "default": false
193
+ },
194
+ "autoUpdateHomebridgeUI": {
195
+ "title": "Auto-update Homebridge Config UI",
196
+ "type": "boolean",
197
+ "description": "Automatically install Homebridge Config UI updates when available (requires homebridge-config-ui-x and sufficient npm privileges)",
198
+ "default": false
199
+ },
200
+ "autoUpdatePlugins": {
201
+ "title": "Auto-update plugins",
202
+ "type": "boolean",
203
+ "description": "Automatically install plugin updates when available (requires homebridge-config-ui-x and sufficient npm privileges)",
204
+ "default": false
205
+ },
206
+ "allowDirectNpmUpdates": {
207
+ "title": "Allow direct npm updates",
208
+ "type": "boolean",
209
+ "description": "Allow automatic updates using direct npm commands even when homebridge-config-ui-x is not available (requires sufficient npm privileges)",
210
+ "default": false
211
+ },
212
+ "autoRestartAfterUpdates": {
213
+ "title": "Auto-restart after updates",
214
+ "type": "boolean",
215
+ "description": "Automatically restart Homebridge after successful automatic updates to apply changes",
216
+ "default": false
217
+ },
218
+ "uiNotice": {
219
+ "title": "",
220
+ "description": "Note: This feature may require updating Homebridge UI to a newer version. It is recommended to update to the latest version.",
221
+ "type": "object",
222
+ "properties": {}
223
+ }
224
+ },
225
+ "required": ["name", "sensorType"]
226
+ },
227
+ "layout": [
228
+ "name",
229
+ "sensorType",
230
+ "failureSensorType",
231
+ {
232
+ "type": "fieldset",
233
+ "title": "Advanced Settings",
234
+ "expandable": true,
235
+ "expanded": false,
236
+ "items": [
237
+ "enableMatter",
238
+ "initialCheckDelay",
239
+ "checkNodeUpdates",
240
+ "checkNpmUpdates",
241
+ "checkHomebridgeUpdates",
242
+ "checkHomebridgeUIUpdates",
243
+ "checkPluginUpdates",
244
+ "checkDockerUpdates",
245
+ "respectDisabledPlugins",
246
+ "autoUpdateNode",
247
+ "autoUpdateNpm",
248
+ "autoUpdateHomebridge",
249
+ "autoUpdateHomebridgeUI",
250
+ "autoUpdatePlugins",
251
+ "allowDirectNpmUpdates",
252
+ "autoRestartAfterUpdates",
253
+ "uiNotice"
254
+ ]
255
+ }
256
+ ]
257
+ }
@@ -0,0 +1,16 @@
1
+ import type { API, DynamicPlatformPlugin, Logging, PlatformConfig } from 'homebridge';
2
+ export declare class PluginUpdatePlatform implements DynamicPlatformPlugin {
3
+ private readonly log;
4
+ private readonly config;
5
+ private readonly api;
6
+ private updateSensor;
7
+ private failureSensor;
8
+ private readonly updateSensorUuid;
9
+ private readonly failureSensorUuid;
10
+ private failureSensorRegistered;
11
+ private cachedFailureAccessory?;
12
+ constructor(log: Logging, config: PlatformConfig, api: API);
13
+ private addFailureSensor;
14
+ configureAccessory(accessory: any): void;
15
+ }
16
+ //# sourceMappingURL=Platform.HAP.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Platform.HAP.d.ts","sourceRoot":"","sources":["../src/Platform.HAP.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,qBAAqB,EAAE,OAAO,EAAqB,cAAc,EAAE,MAAM,YAAY,CAAA;AAOxG,qBAAa,oBAAqB,YAAW,qBAAqB;IAChE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAK;IACzB,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAC1C,OAAO,CAAC,uBAAuB,CAAQ;IACvC,OAAO,CAAC,sBAAsB,CAAC,CAAmB;gBAEtC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG;IAe1D,OAAO,CAAC,gBAAgB;IAuBxB,kBAAkB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;CA4BzC"}
@@ -0,0 +1,77 @@
1
+ import { FailureSensor } from './failureSensor.js';
2
+ import { FAILURE_SENSOR_UUID_KEY, PLATFORM_NAME, PLUGIN_NAME, UPDATE_SENSOR_UUID_KEY } from './settings.js';
3
+ import { UpdateSensor } from './updateSensor.js';
4
+ import { isFailureSensorEnabled } from './utils.js';
5
+ export class PluginUpdatePlatform {
6
+ log;
7
+ config;
8
+ api;
9
+ updateSensor;
10
+ failureSensor;
11
+ updateSensorUuid;
12
+ failureSensorUuid;
13
+ failureSensorRegistered = false;
14
+ cachedFailureAccessory;
15
+ constructor(log, config, api) {
16
+ this.log = log;
17
+ this.config = config;
18
+ this.api = api;
19
+ this.updateSensorUuid = api.hap.uuid.generate(UPDATE_SENSOR_UUID_KEY);
20
+ this.failureSensorUuid = api.hap.uuid.generate(FAILURE_SENSOR_UUID_KEY);
21
+ this.failureSensor = new FailureSensor(log, api, config.failureSensorType || config.sensorType, 'hap');
22
+ this.updateSensor = new UpdateSensor(log, config, api, {
23
+ protocol: 'hap',
24
+ onFailureStateChange: isFailureSensorEnabled(config) ? (failed) => this.failureSensor.setState(failed) : undefined,
25
+ });
26
+ // Register the failure sensor accessory
27
+ api.on('didFinishLaunching', this.addFailureSensor.bind(this));
28
+ }
29
+ addFailureSensor() {
30
+ // If the failure sensor has been disabled, remove any previously cached accessory
31
+ if (!isFailureSensorEnabled(this.config)) {
32
+ if (this.cachedFailureAccessory) {
33
+ this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [this.cachedFailureAccessory]);
34
+ this.cachedFailureAccessory = undefined;
35
+ this.log.info('Removed cached failure sensor accessory (failure sensor is disabled)');
36
+ }
37
+ return;
38
+ }
39
+ if (this.failureSensorRegistered) {
40
+ return;
41
+ }
42
+ const Accessory = this.api.platformAccessory;
43
+ const failureAccessory = new Accessory('Plugin Update Failure', this.failureSensorUuid);
44
+ this.failureSensor.configure(failureAccessory);
45
+ this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [failureAccessory]);
46
+ this.failureSensorRegistered = true;
47
+ }
48
+ // Handle cached accessories: restore event and delegate configuration
49
+ configureAccessory(accessory) {
50
+ if (accessory && typeof accessory.on === 'function') {
51
+ accessory.on('identify', () => {
52
+ if (this.updateSensor && this.updateSensor.log) {
53
+ this.updateSensor.log(`${accessory.displayName} identify requested!`);
54
+ }
55
+ });
56
+ }
57
+ // Restore for update sensor
58
+ if (accessory.UUID === this.updateSensorUuid) {
59
+ this.updateSensor.configureAccessory(accessory);
60
+ return;
61
+ }
62
+ // Restore for failure sensor
63
+ if (accessory.UUID === this.failureSensorUuid) {
64
+ if (!isFailureSensorEnabled(this.config)) {
65
+ // Sensor is disabled — keep track of the cached accessory so it can be
66
+ // unregistered once `didFinishLaunching` fires.
67
+ this.cachedFailureAccessory = accessory;
68
+ return;
69
+ }
70
+ this.failureSensor.configure(accessory);
71
+ this.failureSensorRegistered = true;
72
+ return;
73
+ }
74
+ this.log.warn(`Ignoring unknown cached accessory: ${accessory.displayName}`);
75
+ }
76
+ }
77
+ //# sourceMappingURL=Platform.HAP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Platform.HAP.js","sourceRoot":"","sources":["../src/Platform.HAP.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { API, Logging, PlatformConfig } from 'homebridge';
2
+ export declare class PluginUpdateMatterPlatform {
3
+ private updateSensor;
4
+ private failureSensor;
5
+ constructor(log: Logging, config: PlatformConfig, api: API);
6
+ }
7
+ //# sourceMappingURL=Platform.Matter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Platform.Matter.d.ts","sourceRoot":"","sources":["../src/Platform.Matter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAM9D,qBAAa,0BAA0B;IACrC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,aAAa,CAAe;gBAExB,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG;CAa3D"}
@@ -0,0 +1,21 @@
1
+ import { FailureSensor } from './failureSensor.js';
2
+ import { UpdateSensor } from './updateSensor.js';
3
+ import { isFailureSensorEnabled } from './utils.js';
4
+ export class PluginUpdateMatterPlatform {
5
+ updateSensor;
6
+ failureSensor;
7
+ constructor(log, config, api) {
8
+ this.failureSensor = new FailureSensor(log, api, config.failureSensorType || config.sensorType, 'matter');
9
+ this.updateSensor = new UpdateSensor(log, config, api, {
10
+ protocol: 'matter',
11
+ onFailureStateChange: isFailureSensorEnabled(config) ? (failed) => this.failureSensor.setState(failed) : undefined,
12
+ });
13
+ // Register the failure sensor as a separate Matter device only when enabled
14
+ if (isFailureSensorEnabled(config)) {
15
+ const deviceName = config.name || 'Plugin Update Check';
16
+ const failureDeviceName = `${deviceName} Failure`;
17
+ this.failureSensor.configure({ displayName: failureDeviceName });
18
+ }
19
+ }
20
+ }
21
+ //# sourceMappingURL=Platform.Matter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Platform.Matter.js","sourceRoot":"","sources":["../src/Platform.Matter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,OAAO,0BAA0B;IAC7B,YAAY,CAAc;IAC1B,aAAa,CAAe;IAEpC,YAAY,GAAY,EAAE,MAAsB,EAAE,GAAQ;QACxD,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACzG,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;YACrD,QAAQ,EAAE,QAAQ;YAClB,oBAAoB,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;SACnH,CAAC,CAAA;QACF,4EAA4E;QAC5E,IAAI,sBAAsB,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,UAAU,GAAI,MAAc,CAAC,IAAI,IAAI,qBAAqB,CAAA;YAChE,MAAM,iBAAiB,GAAG,GAAG,UAAU,UAAU,CAAA;YACjD,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAS,CAAC,CAAA;QACzE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import type { API } from 'homebridge';
2
+ export declare function migratePlatformAliasInPluginConfigs(configs: Array<Record<string, unknown>>): number;
3
+ export declare function migrateLegacyPlatformAlias(api: API): Promise<void>;
4
+ //# sourceMappingURL=configMigration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configMigration.d.ts","sourceRoot":"","sources":["../src/configMigration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AAOrC,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAcnG;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BxE"}
@@ -0,0 +1,45 @@
1
+ import { PLUGIN_NAME, PLATFORM_NAME } from './settings.js';
2
+ import { UiApi } from './ui-api.js';
3
+ const LEGACY_PLATFORM_NAME = 'PluginUpdate';
4
+ export function migratePlatformAliasInPluginConfigs(configs) {
5
+ if (!Array.isArray(configs)) {
6
+ return 0;
7
+ }
8
+ let updated = 0;
9
+ for (const platformConfig of configs) {
10
+ if (platformConfig?.platform === LEGACY_PLATFORM_NAME) {
11
+ platformConfig.platform = PLATFORM_NAME;
12
+ updated++;
13
+ }
14
+ }
15
+ return updated;
16
+ }
17
+ export async function migrateLegacyPlatformAlias(api) {
18
+ const hbStoragePath = api.user?.storagePath?.();
19
+ if (!hbStoragePath) {
20
+ return;
21
+ }
22
+ const silentLog = {
23
+ info: () => { },
24
+ warn: () => { },
25
+ error: () => { },
26
+ debug: () => { },
27
+ };
28
+ try {
29
+ const uiApi = new UiApi(hbStoragePath, silentLog);
30
+ if (!uiApi.isConfigured()) {
31
+ return;
32
+ }
33
+ const pluginConfigs = await uiApi.getPluginConfig(PLUGIN_NAME);
34
+ const updated = migratePlatformAliasInPluginConfigs(pluginConfigs);
35
+ if (!updated) {
36
+ return;
37
+ }
38
+ await uiApi.updatePluginConfig(PLUGIN_NAME, pluginConfigs);
39
+ await uiApi.savePluginConfig(PLUGIN_NAME);
40
+ }
41
+ catch {
42
+ // Ignore migration errors so plugin startup is never blocked.
43
+ }
44
+ }
45
+ //# sourceMappingURL=configMigration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configMigration.js","sourceRoot":"","sources":["../src/configMigration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC,MAAM,oBAAoB,GAAG,cAAc,CAAA;AAE3C,MAAM,UAAU,mCAAmC,CAAC,OAAuC;IACzF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAA;IACV,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,cAAc,IAAI,OAAO,EAAE,CAAC;QACrC,IAAI,cAAc,EAAE,QAAQ,KAAK,oBAAoB,EAAE,CAAC;YACtD,cAAc,CAAC,QAAQ,GAAG,aAAa,CAAA;YACvC,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,GAAQ;IACvD,MAAM,aAAa,GAAI,GAAG,CAAC,IAAY,EAAE,WAAW,EAAE,EAAE,CAAA;IACxD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAM;IACR,CAAC;IAED,MAAM,SAAS,GAAG;QAChB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;QACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;QACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;QACf,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;KAChB,CAAA;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,aAAa,EAAE,SAAgB,CAAC,CAAA;QACxD,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC;YAC1B,OAAM;QACR,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;QAC9D,MAAM,OAAO,GAAG,mCAAmC,CAAC,aAAa,CAAC,CAAA;QAClE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAM;QACR,CAAC;QAED,MAAM,KAAK,CAAC,kBAAkB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;QAC1D,MAAM,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configMigration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configMigration.test.d.ts","sourceRoot":"","sources":["../src/configMigration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { migratePlatformAliasInPluginConfigs } from './configMigration.js';
3
+ describe('config migration', () => {
4
+ it('should migrate legacy platform alias in plugin config entries', () => {
5
+ const pluginConfigs = [
6
+ { platform: 'PluginUpdate', name: 'Legacy Updater' },
7
+ { platform: 'OtherPlugin', name: 'Other' },
8
+ ];
9
+ const updated = migratePlatformAliasInPluginConfigs(pluginConfigs);
10
+ expect(updated).toBe(1);
11
+ expect(pluginConfigs[0].platform).toBe('HomebridgeUpdater');
12
+ expect(pluginConfigs[1].platform).toBe('OtherPlugin');
13
+ });
14
+ it('should keep entries unchanged when no legacy alias exists', () => {
15
+ const pluginConfigs = [
16
+ { platform: 'HomebridgeUpdater', name: 'Updater' },
17
+ ];
18
+ const updated = migratePlatformAliasInPluginConfigs(pluginConfigs);
19
+ expect(updated).toBe(0);
20
+ expect(pluginConfigs[0].platform).toBe('HomebridgeUpdater');
21
+ });
22
+ });
23
+ //# sourceMappingURL=configMigration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configMigration.test.js","sourceRoot":"","sources":["../src/configMigration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,mCAAmC,EAAE,MAAM,sBAAsB,CAAA;AAE1E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,aAAa,GAAmC;YACpD,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,gBAAgB,EAAE;YACpD,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;SAC3C,CAAA;QAED,MAAM,OAAO,GAAG,mCAAmC,CAAC,aAAa,CAAC,CAAA;QAElE,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QAC3D,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,aAAa,GAAmC;YACpD,EAAE,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE;SACnD,CAAA;QAED,MAAM,OAAO,GAAG,mCAAmC,CAAC,aAAa,CAAC,CAAA;QAElE,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}