@switchbot/homebridge-switchbot 5.0.0-beta.10 → 5.0.0-beta.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;yBAOrB,KAAK,GAAG,KAAG,IAAI;AAA/B,wBAgCC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;yBAOrB,KAAK,GAAG,KAAG,IAAI;AAA/B,wBAiEC"}
package/dist/index.js CHANGED
@@ -3,35 +3,68 @@ import { SwitchBotMatterPlatform } from './platform-matter.js';
3
3
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
4
4
  // Register our platform with homebridge.
5
5
  export default (api) => {
6
- // Call the instance method on the runtime `api` object (optional chaining in case
7
- // older homebridge doesn't provide it). Treat undefined as false.
8
- const isMatter = (() => {
6
+ // Register a single proxy platform class. Homebridge will instantiate this class
7
+ // with (log, config, api) and we delegate to the appropriate actual platform
8
+ // implementation (HAP or Matter) based on runtime detection. This avoids
9
+ // registering two platforms and possible conflicts.
10
+ // Compact helper to determine if Matter should be used.
11
+ const detectMatter = (apiObj) => {
9
12
  try {
10
- const maybeFnOrProp = api.isMatterEnabled;
11
- if (typeof maybeFnOrProp === 'function') {
12
- return Boolean(maybeFnOrProp.call(api));
13
+ const maybe = apiObj.isMatterEnabled;
14
+ if (typeof maybe === 'function') {
15
+ return Boolean(maybe.call(apiObj));
13
16
  }
14
- if (typeof maybeFnOrProp !== 'undefined') {
15
- return Boolean(maybeFnOrProp);
17
+ if (typeof maybe !== 'undefined') {
18
+ return Boolean(maybe);
16
19
  }
17
- // Some Homebridge beta versions expose Matter info on an internal server object
18
- const server = api.server ?? api.homebridgeServer ?? api.homebridge_server;
19
- const serverFn = server?.isMatterEnabled;
20
- if (typeof serverFn === 'function') {
21
- return Boolean(serverFn.call(server));
20
+ const server = apiObj.server ?? apiObj.homebridgeServer ?? apiObj.homebridge_server;
21
+ const serverMaybe = server?.isMatterEnabled;
22
+ if (typeof serverMaybe === 'function') {
23
+ return Boolean(serverMaybe.call(server));
22
24
  }
23
25
  if (typeof server?.isMatterEnabled !== 'undefined') {
24
26
  return Boolean(server.isMatterEnabled);
25
27
  }
26
28
  }
27
29
  catch (e) {
28
- // ignore and fall through to false
30
+ // ignore
29
31
  }
30
32
  return false;
31
- })();
32
- const log = api.logger ?? api.log ?? console;
33
- log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.`);
34
- // If Matter is enabled register the Matter platform, otherwise use HAP platform.
35
- api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, isMatter ? SwitchBotMatterPlatform : SwitchBotHAPPlatform);
33
+ };
34
+ class SwitchBotPlatformProxy {
35
+ log;
36
+ config;
37
+ api;
38
+ delegate;
39
+ constructor(log, config, api) {
40
+ this.log = log;
41
+ this.config = config;
42
+ this.api = api;
43
+ const isMatter = detectMatter(this.api);
44
+ this.log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.`);
45
+ const PlatformCtor = isMatter ? SwitchBotMatterPlatform : SwitchBotHAPPlatform;
46
+ this.delegate = new PlatformCtor(this.log, this.config, this.api);
47
+ }
48
+ // Homebridge lifecycle hooks we expect to be called — delegate if available.
49
+ configureAccessory(accessory) {
50
+ if (typeof this.delegate.configureAccessory === 'function') {
51
+ return this.delegate.configureAccessory(accessory);
52
+ }
53
+ }
54
+ configureMatterAccessory(accessory) {
55
+ if (typeof this.delegate.configureMatterAccessory === 'function') {
56
+ return this.delegate.configureMatterAccessory(accessory);
57
+ }
58
+ }
59
+ // Expose common properties via getters for external access
60
+ get accessories() {
61
+ return this.delegate?.accessories;
62
+ }
63
+ get matterAccessories() {
64
+ return this.delegate?.matterAccessories;
65
+ }
66
+ }
67
+ // Register the proxy class with Homebridge. Homebridge will call `new SwitchBotPlatformProxy(log, config, api)`
68
+ api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, SwitchBotPlatformProxy);
36
69
  };
37
70
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE1D,yCAAyC;AACzC,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAChC,kFAAkF;IAClF,kEAAkE;IAClE,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,aAAa,GAAI,GAAW,CAAC,eAAe,CAAA;YAClD,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;gBACxC,OAAO,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YACzC,CAAC;YACD,IAAI,OAAO,aAAa,KAAK,WAAW,EAAE,CAAC;gBACzC,OAAO,OAAO,CAAC,aAAa,CAAC,CAAA;YAC/B,CAAC;YAED,gFAAgF;YAChF,MAAM,MAAM,GAAI,GAAW,CAAC,MAAM,IAAK,GAAW,CAAC,gBAAgB,IAAK,GAAW,CAAC,iBAAiB,CAAA;YACrG,MAAM,QAAQ,GAAG,MAAM,EAAE,eAAe,CAAA;YACxC,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACnC,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;YACvC,CAAC;YACD,IAAI,OAAO,MAAM,EAAE,eAAe,KAAK,WAAW,EAAE,CAAC;gBACnD,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;YACxC,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,mCAAmC;QACrC,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,EAAE,CAAA;IAEJ,MAAM,GAAG,GAAI,GAAW,CAAC,MAAM,IAAK,GAAW,CAAC,GAAG,IAAI,OAAO,CAAA;IAC9D,GAAG,CAAC,IAAI,EAAE,CAAC,+CAA+C,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAA;IAC9F,iFAAiF;IACjF,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAA;AAC7G,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
2
  import registerPlatform from './index.js';
3
- import { SwitchBotHAPPlatform } from './platform-hap.js';
4
3
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
5
4
  describe('index.ts', () => {
6
5
  it('should register the platform with homebridge', () => {
@@ -8,7 +7,13 @@ describe('index.ts', () => {
8
7
  registerPlatform: vi.fn(),
9
8
  };
10
9
  registerPlatform(api);
11
- expect(api.registerPlatform).toHaveBeenCalledWith(PLUGIN_NAME, PLATFORM_NAME, SwitchBotHAPPlatform);
10
+ // The platform registration now uses a runtime proxy/delegate constructor so
11
+ // assert the call happened and the third argument is a constructor function.
12
+ expect(api.registerPlatform).toHaveBeenCalled();
13
+ const callArgs = api.registerPlatform.mock.calls[0];
14
+ expect(callArgs[0]).toBe(PLUGIN_NAME);
15
+ expect(callArgs[1]).toBe(PLATFORM_NAME);
16
+ expect(typeof callArgs[2]).toBe('function');
12
17
  });
13
18
  });
14
19
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,OAAO,gBAAgB,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE1D,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,GAAG,GAAG;YACV,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;SACR,CAAA;QAEnB,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAErB,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,WAAW,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAA;IACrG,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,OAAO,gBAAgB,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE1D,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,GAAG,GAAG;YACV,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;SACR,CAAA;QAEnB,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAErB,6EAA6E;QAC7E,6EAA6E;QAC7E,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,gBAAgB,EAAE,CAAA;QAC/C,MAAM,QAAQ,GAAI,GAAG,CAAC,gBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC5D,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACrC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACvC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/d9357d0d3a0bb3a054d3a2b194f242455cf84373/src/index.ts#L12">index.ts:12</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/d434012d13896acbd607c731d16d64844d232082/src/index.ts#L12">index.ts:12</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@switchbot/homebridge-switchbot",
3
3
  "displayName": "SwitchBot",
4
4
  "type": "module",
5
- "version": "5.0.0-beta.10",
5
+ "version": "5.0.0-beta.11",
6
6
  "description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.",
7
7
  "author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
8
8
  "contributors": [
package/src/index.test.ts CHANGED
@@ -3,7 +3,6 @@ import type { API } from 'homebridge'
3
3
  import { describe, expect, it, vi } from 'vitest'
4
4
 
5
5
  import registerPlatform from './index.js'
6
- import { SwitchBotHAPPlatform } from './platform-hap.js'
7
6
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
8
7
 
9
8
  describe('index.ts', () => {
@@ -14,6 +13,12 @@ describe('index.ts', () => {
14
13
 
15
14
  registerPlatform(api)
16
15
 
17
- expect(api.registerPlatform).toHaveBeenCalledWith(PLUGIN_NAME, PLATFORM_NAME, SwitchBotHAPPlatform)
16
+ // The platform registration now uses a runtime proxy/delegate constructor so
17
+ // assert the call happened and the third argument is a constructor function.
18
+ expect(api.registerPlatform).toHaveBeenCalled()
19
+ const callArgs = (api.registerPlatform as any).mock.calls[0]
20
+ expect(callArgs[0]).toBe(PLUGIN_NAME)
21
+ expect(callArgs[1]).toBe(PLATFORM_NAME)
22
+ expect(typeof callArgs[2]).toBe('function')
18
23
  })
19
24
  })
package/src/index.ts CHANGED
@@ -10,35 +10,68 @@ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
10
10
 
11
11
  // Register our platform with homebridge.
12
12
  export default (api: API): void => {
13
- // Call the instance method on the runtime `api` object (optional chaining in case
14
- // older homebridge doesn't provide it). Treat undefined as false.
15
- const isMatter = (() => {
13
+ // Register a single proxy platform class. Homebridge will instantiate this class
14
+ // with (log, config, api) and we delegate to the appropriate actual platform
15
+ // implementation (HAP or Matter) based on runtime detection. This avoids
16
+ // registering two platforms and possible conflicts.
17
+ // Compact helper to determine if Matter should be used.
18
+ const detectMatter = (apiObj: API): boolean => {
16
19
  try {
17
- const maybeFnOrProp = (api as any).isMatterEnabled
18
- if (typeof maybeFnOrProp === 'function') {
19
- return Boolean(maybeFnOrProp.call(api))
20
+ const maybe = (apiObj as any).isMatterEnabled
21
+ if (typeof maybe === 'function') {
22
+ return Boolean(maybe.call(apiObj))
20
23
  }
21
- if (typeof maybeFnOrProp !== 'undefined') {
22
- return Boolean(maybeFnOrProp)
24
+ if (typeof maybe !== 'undefined') {
25
+ return Boolean(maybe)
23
26
  }
24
27
 
25
- // Some Homebridge beta versions expose Matter info on an internal server object
26
- const server = (api as any).server ?? (api as any).homebridgeServer ?? (api as any).homebridge_server
27
- const serverFn = server?.isMatterEnabled
28
- if (typeof serverFn === 'function') {
29
- return Boolean(serverFn.call(server))
28
+ const server = (apiObj as any).server ?? (apiObj as any).homebridgeServer ?? (apiObj as any).homebridge_server
29
+ const serverMaybe = server?.isMatterEnabled
30
+ if (typeof serverMaybe === 'function') {
31
+ return Boolean(serverMaybe.call(server))
30
32
  }
31
33
  if (typeof server?.isMatterEnabled !== 'undefined') {
32
34
  return Boolean(server.isMatterEnabled)
33
35
  }
34
36
  } catch (e) {
35
- // ignore and fall through to false
37
+ // ignore
36
38
  }
37
39
  return false
38
- })()
40
+ }
39
41
 
40
- const log = (api as any).logger ?? (api as any).log ?? console
41
- log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.`)
42
- // If Matter is enabled register the Matter platform, otherwise use HAP platform.
43
- api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, isMatter ? SwitchBotMatterPlatform : SwitchBotHAPPlatform)
42
+ class SwitchBotPlatformProxy {
43
+ private delegate: any
44
+
45
+ constructor(public readonly log: any, public readonly config: any, public readonly api: API) {
46
+ const isMatter = detectMatter(this.api)
47
+ this.log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.`)
48
+ const PlatformCtor = isMatter ? SwitchBotMatterPlatform : SwitchBotHAPPlatform
49
+ this.delegate = new PlatformCtor(this.log, this.config, this.api)
50
+ }
51
+
52
+ // Homebridge lifecycle hooks we expect to be called — delegate if available.
53
+ configureAccessory(accessory: any): void {
54
+ if (typeof this.delegate.configureAccessory === 'function') {
55
+ return this.delegate.configureAccessory(accessory)
56
+ }
57
+ }
58
+
59
+ configureMatterAccessory?(accessory: any): void {
60
+ if (typeof this.delegate.configureMatterAccessory === 'function') {
61
+ return this.delegate.configureMatterAccessory(accessory)
62
+ }
63
+ }
64
+
65
+ // Expose common properties via getters for external access
66
+ get accessories(): any {
67
+ return this.delegate?.accessories
68
+ }
69
+
70
+ get matterAccessories(): any {
71
+ return this.delegate?.matterAccessories
72
+ }
73
+ }
74
+
75
+ // Register the proxy class with Homebridge. Homebridge will call `new SwitchBotPlatformProxy(log, config, api)`
76
+ api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, SwitchBotPlatformProxy as any)
44
77
  }