@nubisco/openbridge 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/__tests__/homekit-service-type.test.d.ts +2 -0
  4. package/dist/__tests__/homekit-service-type.test.d.ts.map +1 -0
  5. package/dist/__tests__/homekit-service-type.test.js +239 -0
  6. package/dist/__tests__/homekit-service-type.test.js.map +1 -0
  7. package/dist/__tests__/homekit-visibility.test.d.ts +2 -0
  8. package/dist/__tests__/homekit-visibility.test.d.ts.map +1 -0
  9. package/dist/__tests__/homekit-visibility.test.js +157 -0
  10. package/dist/__tests__/homekit-visibility.test.js.map +1 -0
  11. package/dist/__tests__/server.test.d.ts +2 -0
  12. package/dist/__tests__/server.test.d.ts.map +1 -0
  13. package/dist/__tests__/server.test.js +837 -0
  14. package/dist/__tests__/server.test.js.map +1 -0
  15. package/dist/__tests__/timeseries.test.d.ts +2 -0
  16. package/dist/__tests__/timeseries.test.d.ts.map +1 -0
  17. package/dist/__tests__/timeseries.test.js +216 -0
  18. package/dist/__tests__/timeseries.test.js.map +1 -0
  19. package/dist/auth.d.ts +23 -0
  20. package/dist/auth.d.ts.map +1 -0
  21. package/dist/auth.js +171 -0
  22. package/dist/auth.js.map +1 -0
  23. package/dist/daemon.d.ts +57 -0
  24. package/dist/daemon.d.ts.map +1 -0
  25. package/dist/daemon.js +636 -0
  26. package/dist/daemon.js.map +1 -0
  27. package/dist/homekit-service-type.d.ts +82 -0
  28. package/dist/homekit-service-type.d.ts.map +1 -0
  29. package/dist/homekit-service-type.js +184 -0
  30. package/dist/homekit-service-type.js.map +1 -0
  31. package/dist/homekit-visibility.d.ts +79 -0
  32. package/dist/homekit-visibility.d.ts.map +1 -0
  33. package/dist/homekit-visibility.js +164 -0
  34. package/dist/homekit-visibility.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +62 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/metrics.d.ts +17 -0
  40. package/dist/metrics.d.ts.map +1 -0
  41. package/dist/metrics.js +52 -0
  42. package/dist/metrics.js.map +1 -0
  43. package/dist/platform-client.d.ts +42 -0
  44. package/dist/platform-client.d.ts.map +1 -0
  45. package/dist/platform-client.js +92 -0
  46. package/dist/platform-client.js.map +1 -0
  47. package/dist/server.d.ts +30 -0
  48. package/dist/server.d.ts.map +1 -0
  49. package/dist/server.js +1744 -0
  50. package/dist/server.js.map +1 -0
  51. package/dist/timeseries.d.ts +134 -0
  52. package/dist/timeseries.d.ts.map +1 -0
  53. package/dist/timeseries.js +378 -0
  54. package/dist/timeseries.js.map +1 -0
  55. package/dist/version.d.ts +4 -0
  56. package/dist/version.d.ts.map +1 -0
  57. package/dist/version.js +28 -0
  58. package/dist/version.js.map +1 -0
  59. package/package.json +79 -0
  60. package/scripts/entrypoint.sh +82 -0
  61. package/scripts/fix-node-pty.mjs +22 -0
  62. package/ui-dist/android-chrome-192x192.png +0 -0
  63. package/ui-dist/android-chrome-512x512.png +0 -0
  64. package/ui-dist/apple-touch-icon.png +0 -0
  65. package/ui-dist/assets/index-Q0sxZHIR.css +32 -0
  66. package/ui-dist/assets/index-ZZYyAzBo.js +106 -0
  67. package/ui-dist/favicon-16x16.png +0 -0
  68. package/ui-dist/favicon-32x32.png +0 -0
  69. package/ui-dist/favicon.ico +0 -0
  70. package/ui-dist/fonts/MesloLGLDZNerdFontMono-Bold.woff2 +0 -0
  71. package/ui-dist/fonts/MesloLGLDZNerdFontMono-BoldItalic.woff2 +0 -0
  72. package/ui-dist/fonts/MesloLGLDZNerdFontMono-Italic.woff2 +0 -0
  73. package/ui-dist/fonts/MesloLGLDZNerdFontMono-Regular.woff2 +0 -0
  74. package/ui-dist/index.html +18 -0
  75. package/ui-dist/logo.svg +30 -0
  76. package/ui-dist/nubisco-logo.svg +120 -0
  77. package/ui-dist/site.webmanifest +19 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nubisco Lda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,306 @@
1
+ <div align="center">
2
+
3
+ <br />
4
+
5
+ <img src="apps/docs/docs/public/logo.svg" alt="OpenBridge" width="96" />
6
+
7
+ <br />
8
+
9
+ # OpenBridge
10
+
11
+ **Local-first home automation bridge for developers. Plugin-based, TypeScript-first, Homebridge-compatible.**
12
+
13
+ [![CI](https://github.com/nubisco/openbridge/actions/workflows/ci.yml/badge.svg)](https://github.com/nubisco/openbridge/actions/workflows/ci.yml)
14
+ [![GitHub release](https://img.shields.io/github/v/release/nubisco/openbridge)](https://github.com/nubisco/openbridge/releases)
15
+ [![npm](https://img.shields.io/npm/v/%40nubisco%2Fopenbridge)](https://www.npmjs.com/package/@nubisco/openbridge)
16
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-339933)](https://nodejs.org/)
17
+ [![pnpm](https://img.shields.io/badge/pnpm-9-f69220)](https://pnpm.io/)
18
+ [![license](https://img.shields.io/github/license/nubisco/openbridge)](LICENSE)
19
+ [![CLA](https://img.shields.io/badge/CLA-required-0A7F5A)](docs/CLA-INDIVIDUAL.md)
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ ## Table of Contents
26
+
27
+ - [Why OpenBridge?](#why-openbridge)
28
+ - [Features](#features)
29
+ - [Quick Start](#quick-start)
30
+ - [Development](#development)
31
+ - [Writing a Plugin](#writing-a-plugin)
32
+ - [Configuration](#configuration)
33
+ - [HTTP API](#http-api)
34
+ - [Monorepo Structure](#monorepo-structure)
35
+ - [License](#license)
36
+
37
+ ---
38
+
39
+ ## Why OpenBridge?
40
+
41
+ Homebridge works, but it was designed for a different era. OpenBridge is built from scratch with a developer-first philosophy:
42
+
43
+ - **No cloud, no accounts**: the HAP bridge is published directly on your local network
44
+ - **Clean plugin SDK**: `setup / start / stop` lifecycle, one exported object, full TypeScript types
45
+ - **Drop-in Homebridge compatibility**: existing `platform` plugins work with zero modification
46
+ - **Built-in dashboard**: Vue 3 UI included; no separate install needed
47
+ - **Full HTTP API**: everything the UI does, your scripts can do too
48
+ - **MIT licensed**: no paid tiers, no telemetry, no gatekeeping
49
+
50
+ ---
51
+
52
+ ## Features
53
+
54
+ - Plugin lifecycle management (load, start, stop, reload)
55
+ - HAP bridge via hap-nodejs: exposes accessories to Apple Home
56
+ - Homebridge platform plugin compatibility shim
57
+ - Vue 3 dashboard: accessories, plugins, logs, config editor, terminal
58
+ - REST API + WebSocket streams for logs and metrics
59
+ - Zod-validated JSON config
60
+ - Structured logger with in-memory buffer
61
+
62
+ ---
63
+
64
+ ## Quick Start
65
+
66
+ **Requirements:** Node.js 20 or newer.
67
+
68
+ ### Install from npm
69
+
70
+ ```bash
71
+ npm install -g @nubisco/openbridge
72
+ openbridge
73
+ ```
74
+
75
+ Open **http://localhost:8582**: the dashboard is bundled in the package and loads immediately.
76
+
77
+ ```bash
78
+ openbridge --help # usage
79
+ openbridge --port 9000 # run on a different port
80
+ ```
81
+
82
+ State lives in `~/.openbridge` (config, plugins, HomeKit pairing). Override it with `OPENBRIDGE_HOME`.
83
+
84
+ ### Install from source
85
+
86
+ **Requirements:** Node.js 20+, pnpm 9+, roughly 1 GB of free disk (`node_modules` lands around 720 MB).
87
+
88
+ ```bash
89
+ # Install dependencies
90
+ pnpm install
91
+
92
+ # Build the runtime packages and the dashboard
93
+ pnpm build
94
+
95
+ # Start the daemon
96
+ node apps/daemon/dist/index.js
97
+ ```
98
+
99
+ Open **http://localhost:8582**: the dashboard loads immediately.
100
+
101
+ ### Platform notes
102
+
103
+ - **Alpine / musl** is a supported target, on x64 and arm64. The only native
104
+ dependency, `node-pty`, is optional: without it everything runs normally and
105
+ only the dashboard's interactive shell pane is disabled. `npm install -g @nubisco/openbridge`
106
+ will try to build it and silently carry on if no compiler is present.
107
+ To enable the shell pane on Alpine, install `build-base python3 linux-headers`
108
+ before installing OpenBridge.
109
+ - **Building the docs site needs memory.** `pnpm build` covers the runtime
110
+ packages and the dashboard only. The VitePress docs site is built separately
111
+ with `pnpm build:docs` and needs more than 1 GB of RAM, so it is kept out of
112
+ the default build to keep OpenBridge installable on small SBCs.
113
+
114
+ ---
115
+
116
+ ## Development
117
+
118
+ ```bash
119
+ # Build all packages once
120
+ pnpm build
121
+
122
+ # Start the daemon in watch mode (terminal 1)
123
+ pnpm --filter @nubisco/openbridge dev
124
+
125
+ # Start the UI dev server with HMR (terminal 2)
126
+ pnpm --filter @nubisco/openbridge-ui dev
127
+ # → UI at http://localhost:5174 (proxies /api and /ws to daemon on :8582)
128
+ ```
129
+
130
+ To rebuild individual packages during development:
131
+
132
+ ```bash
133
+ pnpm --filter @nubisco/openbridge-core dev # watch mode
134
+ pnpm --filter @nubisco/openbridge-logger dev
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Writing a Plugin
140
+
141
+ ```typescript
142
+ import { definePlugin } from '@nubisco/openbridge-sdk'
143
+
144
+ export default definePlugin({
145
+ manifest: {
146
+ name: 'my-plugin',
147
+ version: '1.0.0',
148
+ description: 'Does something useful',
149
+ },
150
+
151
+ async setup(ctx) {
152
+ ctx.log.info('Setup: runs once at load time')
153
+ },
154
+
155
+ async start(ctx) {
156
+ ctx.log.info('Start: begin plugin operation')
157
+ // ctx.config has values from config.json
158
+ },
159
+
160
+ async stop(ctx) {
161
+ ctx.log.info('Stop: clean up resources')
162
+ },
163
+ })
164
+ ```
165
+
166
+ For a full guide, see the [Plugin Development docs](apps/docs/docs/guide/creating-a-plugin.md).
167
+
168
+ ---
169
+
170
+ ## Configuration
171
+
172
+ Default config path: `~/.openbridge/config.json`
173
+
174
+ ```json
175
+ {
176
+ "bridge": {
177
+ "name": "My OpenBridge",
178
+ "port": 8582,
179
+ "logLevel": "info"
180
+ },
181
+ "plugins": [
182
+ {
183
+ "name": "my-plugin",
184
+ "enabled": true,
185
+ "config": {
186
+ "interval": 5000
187
+ }
188
+ }
189
+ ]
190
+ }
191
+ ```
192
+
193
+ See [Configuration Reference](apps/docs/docs/guide/config-reference.md) for all options.
194
+
195
+ ---
196
+
197
+ ## HTTP API
198
+
199
+ The daemon exposes a REST API on port 8582:
200
+
201
+ | Method | Path | Description |
202
+ | ------ | -------------------------- | ---------------------------------------- |
203
+ | GET | `/api/health` | Daemon status, version, and capabilities |
204
+ | GET | `/api/plugins` | List all loaded plugins |
205
+ | GET | `/api/plugins/:id` | Get a single plugin |
206
+ | POST | `/api/plugins/:id/start` | Start a plugin |
207
+ | POST | `/api/plugins/:id/stop` | Stop a plugin |
208
+ | GET | `/api/accessories` | List all HAP accessories |
209
+ | GET | `/api/logs?plugin=&limit=` | Retrieve log entries |
210
+ | WS | `/ws/logs` | Stream live logs |
211
+ | WS | `/ws/shell` | Interactive terminal (requires node-pty) |
212
+
213
+ `GET /api/health` reports which optional features are present:
214
+
215
+ ```json
216
+ { "status": "ok", "version": "0.29.0", "capabilities": { "shell": true, "ui": true } }
217
+ ```
218
+
219
+ `capabilities.shell` is `false` when the optional `node-pty` dependency is not
220
+ installed; the interactive terminal is then unavailable and nothing else is affected.
221
+
222
+ Full reference: [HTTP API docs](apps/docs/docs/guide/api-reference.md).
223
+
224
+ ---
225
+
226
+ ## Monorepo Structure
227
+
228
+ ```
229
+ openbridge/
230
+ apps/
231
+ daemon/ Node.js runtime: plugin loader + Fastify HTTP API + HAP bridge
232
+ (published to npm as `@nubisco/openbridge`, dashboard bundled in)
233
+ ui/ Vue 3 dashboard: accessories, plugins, logs, config, terminal
234
+ cli/ Standalone CLI scaffold (not published; the daemon provides `openbridge`)
235
+ docs/ VitePress documentation site
236
+ packages/
237
+ core/ Plugin types, registry, lifecycle, loader
238
+ logger/ Structured logging with in-memory buffer + WebSocket
239
+ config/ Zod-validated JSON config
240
+ sdk/ definePlugin() helper for plugin authors
241
+ compatibility-homebridge/ Homebridge platform plugin adapter
242
+ ```
243
+
244
+ ### Published packages
245
+
246
+ Everything below is released together, under one version, from a single git tag.
247
+
248
+ | npm package | Source |
249
+ | ---------------------------------------------- | ----------------------------------- |
250
+ | `@nubisco/openbridge` | `apps/daemon` |
251
+ | `@nubisco/openbridge-core` | `packages/core` |
252
+ | `@nubisco/openbridge-logger` | `packages/logger` |
253
+ | `@nubisco/openbridge-config` | `packages/config` |
254
+ | `@nubisco/openbridge-sdk` | `packages/sdk` |
255
+ | `@nubisco/openbridge-compatibility-homebridge` | `packages/compatibility-homebridge` |
256
+
257
+ ### Releasing
258
+
259
+ Releases are automated and should not be run by hand.
260
+
261
+ 1. Merging to `master` runs semantic-release, which bumps the version, writes the
262
+ CHANGELOG entry, commits and pushes a `vX.Y.Z` tag.
263
+ 2. That tag triggers [`npm-publish.yml`](.github/workflows/npm-publish.yml), which
264
+ builds, packs each package with `pnpm pack` and publishes the tarballs to npm.
265
+
266
+ Authentication uses **npm trusted publishing** (OIDC), so there is no npm token
267
+ stored in the repository. Each package has this workflow registered as a trusted
268
+ publisher on npmjs.com, and npm accepts publishes only from it. Provenance
269
+ attestations are generated automatically, so every release is cryptographically
270
+ attested to the commit and workflow run it was built from, and CI fails the release
271
+ if an attestation is missing.
272
+
273
+ To inspect exactly what would be published, without publishing anything:
274
+
275
+ ```bash
276
+ pnpm pack:check
277
+ ```
278
+
279
+ That builds, stages the tarballs and asserts each one carries `dist`, a README and
280
+ a LICENSE, and that no `workspace:*` range survived into the published manifest.
281
+
282
+ ---
283
+
284
+ ## Contributing
285
+
286
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. All contributions are made under the [Individual CLA](docs/CLA-INDIVIDUAL.md).
287
+
288
+ ---
289
+
290
+ ## Security
291
+
292
+ To report a vulnerability, please use [GitHub Security Advisories](https://github.com/nubisco/openbridge/security/advisories/new) rather than opening a public issue. See [SECURITY.md](.github/SECURITY.md) for the full policy.
293
+
294
+ ---
295
+
296
+ ## Support this project
297
+
298
+ If OpenBridge is useful to you, consider [sponsoring the maintainer](https://github.com/sponsors/joseporto).
299
+
300
+ ---
301
+
302
+ ## License
303
+
304
+ MIT: see [LICENSE](LICENSE).
305
+
306
+ Part of the [Nubisco](https://nubisco.io) ecosystem.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=homekit-service-type.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"homekit-service-type.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/homekit-service-type.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,239 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtempSync, rmSync, readFileSync, existsSync } from 'fs';
3
+ import { tmpdir } from 'os';
4
+ import { join } from 'path';
5
+ import { HomeKitServiceTypes, CONVERTIBLE_SERVICES, isConvertible } from '../homekit-service-type.js';
6
+ import { HomeKitVisibility } from '../homekit-visibility.js';
7
+ let dir;
8
+ let path;
9
+ beforeEach(() => {
10
+ dir = mkdtempSync(join(tmpdir(), 'ob-hkst-'));
11
+ path = join(dir, 'homekit-service-types.json');
12
+ });
13
+ afterEach(() => {
14
+ rmSync(dir, { recursive: true, force: true });
15
+ });
16
+ const SWITCH = CONVERTIBLE_SERVICES.switch.uuid;
17
+ const LIGHT = CONVERTIBLE_SERVICES.light.uuid;
18
+ const ON = '00000025-0000-1000-8000-0026BB765291';
19
+ const THERMOSTAT = '0000004A-0000-1000-8000-0026BB765291';
20
+ /**
21
+ * Minimal stand-ins for the hap-nodejs surface the swap touches: a
22
+ * characteristic that records writes and notifies `change` listeners, and a
23
+ * service holding one.
24
+ */
25
+ function fakeCharacteristic(uuid, value = false) {
26
+ const listeners = [];
27
+ return {
28
+ UUID: uuid,
29
+ value,
30
+ sets: [],
31
+ getHandler: null,
32
+ setHandler: null,
33
+ setValue(v) {
34
+ this.sets.push(v);
35
+ this.value = v;
36
+ return this;
37
+ },
38
+ updateValue(v) {
39
+ this.value = v;
40
+ return this;
41
+ },
42
+ on(event, cb) {
43
+ if (event === 'change')
44
+ listeners.push(cb);
45
+ return this;
46
+ },
47
+ onGet(cb) {
48
+ this.getHandler = cb;
49
+ return this;
50
+ },
51
+ onSet(cb) {
52
+ this.setHandler = cb;
53
+ return this;
54
+ },
55
+ emitChange(newValue) {
56
+ this.value = newValue;
57
+ listeners.forEach((cb) => cb({ newValue }));
58
+ },
59
+ };
60
+ }
61
+ function fakeService(uuid, displayName, charUuid = ON) {
62
+ const characteristics = [fakeCharacteristic(charUuid)];
63
+ return {
64
+ UUID: uuid,
65
+ displayName,
66
+ subtype: undefined,
67
+ characteristics,
68
+ getCharacteristic() {
69
+ return characteristics[0];
70
+ },
71
+ };
72
+ }
73
+ function fakeAccessory(uuid, services) {
74
+ return {
75
+ UUID: uuid,
76
+ displayName: uuid,
77
+ category: 8,
78
+ services,
79
+ addService(svc) {
80
+ this.services.push(svc);
81
+ return svc;
82
+ },
83
+ removeService(svc) {
84
+ this.services = this.services.filter((s) => s !== svc);
85
+ },
86
+ };
87
+ }
88
+ /** hap-nodejs stand-in exposing just Service.<Name> and Characteristic.On. */
89
+ function fakeHap() {
90
+ class Svc {
91
+ UUID;
92
+ displayName;
93
+ subtype;
94
+ characteristics;
95
+ constructor(uuid, displayName, subtype) {
96
+ this.UUID = uuid;
97
+ this.displayName = displayName;
98
+ this.subtype = subtype;
99
+ this.characteristics = [fakeCharacteristic(ON)];
100
+ }
101
+ getCharacteristic() {
102
+ return this.characteristics[0];
103
+ }
104
+ }
105
+ return {
106
+ Characteristic: { On: { UUID: ON } },
107
+ Service: {
108
+ Lightbulb: class extends Svc {
109
+ constructor(name, subtype) {
110
+ super(LIGHT, name, subtype);
111
+ }
112
+ },
113
+ Switch: class extends Svc {
114
+ constructor(name, subtype) {
115
+ super(SWITCH, name, subtype);
116
+ }
117
+ },
118
+ },
119
+ };
120
+ }
121
+ describe('convertibility', () => {
122
+ it('accepts the On-based service family', () => {
123
+ for (const def of Object.values(CONVERTIBLE_SERVICES)) {
124
+ expect(isConvertible(def.uuid)).toBe(true);
125
+ }
126
+ });
127
+ it('rejects services that are not built on On', () => {
128
+ // A thermostat has no On characteristic, so presenting it as a lightbulb
129
+ // would silently drop everything that makes it a thermostat.
130
+ expect(isConvertible(THERMOSTAT)).toBe(false);
131
+ });
132
+ });
133
+ describe('persistence', () => {
134
+ it('round trips an override across instances', () => {
135
+ const a = new HomeKitServiceTypes(path);
136
+ a.set('pool', SWITCH, 'light');
137
+ expect(existsSync(path)).toBe(true);
138
+ expect(new HomeKitServiceTypes(path).get('pool', SWITCH)).toBe('light');
139
+ });
140
+ it('clearing an override removes the entry rather than storing a null', () => {
141
+ const s = new HomeKitServiceTypes(path);
142
+ s.set('pool', SWITCH, 'light');
143
+ s.set('pool', SWITCH, null);
144
+ expect(s.get('pool', SWITCH)).toBeNull();
145
+ expect(JSON.parse(readFileSync(path, 'utf8'))).toEqual({});
146
+ });
147
+ it('treats selecting the service’s own type as clearing it', () => {
148
+ const s = new HomeKitServiceTypes(path);
149
+ s.set('pool', SWITCH, 'switch');
150
+ expect(s.get('pool', SWITCH)).toBeNull();
151
+ });
152
+ it('survives a corrupt store by falling back to plugin defaults', () => {
153
+ const s = new HomeKitServiceTypes(join(dir, 'missing.json'));
154
+ expect(s.all()).toEqual({});
155
+ });
156
+ });
157
+ describe('applying an override', () => {
158
+ it('presents a Switch as a Lightbulb and re-categorises the accessory', () => {
159
+ const s = new HomeKitServiceTypes(path, fakeHap());
160
+ s.set('pool', SWITCH, 'light');
161
+ const acc = fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]);
162
+ s.apply(acc);
163
+ expect(acc.services).toHaveLength(1);
164
+ expect(acc.services[0].UUID).toBe(LIGHT);
165
+ expect(acc.services[0].displayName).toBe('Pool Light');
166
+ expect(acc.category).toBe(CONVERTIBLE_SERVICES.light.category);
167
+ });
168
+ it('forwards HomeKit writes to the original characteristic, so the plugin still acts on them', async () => {
169
+ const s = new HomeKitServiceTypes(path, fakeHap());
170
+ s.set('pool', SWITCH, 'light');
171
+ const original = fakeService(SWITCH, 'Pool Light');
172
+ const originalOn = original.characteristics[0];
173
+ const acc = fakeAccessory('pool', [original]);
174
+ s.apply(acc);
175
+ await acc.services[0].getCharacteristic().setHandler(true);
176
+ expect(originalOn.sets).toEqual([true]);
177
+ });
178
+ it('mirrors plugin-side updates onto the replacement service', () => {
179
+ const s = new HomeKitServiceTypes(path, fakeHap());
180
+ s.set('pool', SWITCH, 'light');
181
+ const original = fakeService(SWITCH, 'Pool Light');
182
+ const acc = fakeAccessory('pool', [original]);
183
+ s.apply(acc);
184
+ original.characteristics[0].emitChange(true);
185
+ expect(acc.services[0].getCharacteristic().value).toBe(true);
186
+ });
187
+ it('leaves non-convertible services alone', () => {
188
+ const s = new HomeKitServiceTypes(path, fakeHap());
189
+ // Written directly: set() would accept this, but apply() must refuse it.
190
+ s.set('thermo', THERMOSTAT, 'light');
191
+ const acc = fakeAccessory('thermo', [fakeService(THERMOSTAT, 'Heating', 'other')]);
192
+ s.apply(acc);
193
+ expect(acc.services[0].UUID).toBe(THERMOSTAT);
194
+ expect(acc.category).toBe(8);
195
+ });
196
+ it('leaves accessories with no override untouched', () => {
197
+ const s = new HomeKitServiceTypes(path, fakeHap());
198
+ const acc = fakeAccessory('other', [fakeService(SWITCH, 'Garden Tap')]);
199
+ s.apply(acc);
200
+ expect(acc.services[0].UUID).toBe(SWITCH);
201
+ });
202
+ });
203
+ describe('bridge integration', () => {
204
+ it('applies overrides on the way to the bridge, before HomeKit sees the accessory', () => {
205
+ const types = new HomeKitServiceTypes(path, fakeHap());
206
+ types.set('pool', SWITCH, 'light');
207
+ const bridge = {
208
+ added: [],
209
+ addBridgedAccessory(acc) {
210
+ this.added.push(acc);
211
+ return acc;
212
+ },
213
+ removeBridgedAccessory() { },
214
+ };
215
+ const wrapped = new HomeKitVisibility(join(dir, 'hidden.json'), null, types).wrapBridge(bridge);
216
+ wrapped.addBridgedAccessory(fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]));
217
+ expect(bridge.added[0].services[0].UUID).toBe(LIGHT);
218
+ });
219
+ it('does not bother re-typing an accessory that is hidden anyway', () => {
220
+ const types = new HomeKitServiceTypes(path, fakeHap());
221
+ types.set('pool', SWITCH, 'light');
222
+ const hiddenPath = join(dir, 'hidden.json');
223
+ const visibility = new HomeKitVisibility(hiddenPath, null, types);
224
+ visibility.setVisible('pool', false);
225
+ const bridge = {
226
+ added: [],
227
+ addBridgedAccessory(acc) {
228
+ this.added.push(acc);
229
+ return acc;
230
+ },
231
+ removeBridgedAccessory() { },
232
+ };
233
+ const acc = fakeAccessory('pool', [fakeService(SWITCH, 'Pool Light')]);
234
+ visibility.wrapBridge(bridge).addBridgedAccessory(acc);
235
+ expect(bridge.added).toHaveLength(0);
236
+ expect(acc.services[0].UUID).toBe(SWITCH);
237
+ });
238
+ });
239
+ //# sourceMappingURL=homekit-service-type.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"homekit-service-type.test.js","sourceRoot":"","sources":["../../src/__tests__/homekit-service-type.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=homekit-visibility.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"homekit-visibility.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/homekit-visibility.test.ts"],"names":[],"mappings":""}