@smarthome.exchange/integrations 1.0.0 → 2.0.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 (294) hide show
  1. package/changelog.md +49 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/core/classes.configstore.d.ts +2 -0
  4. package/dist_ts/core/classes.configstore.js +84 -27
  5. package/dist_ts/core/classes.nativehomeadmission.d.ts +19 -0
  6. package/dist_ts/core/classes.nativehomeadmission.js +84 -0
  7. package/dist_ts/core/classes.nativeintegrationowner.d.ts +79 -0
  8. package/dist_ts/core/classes.nativeintegrationowner.js +269 -0
  9. package/dist_ts/core/index.d.ts +2 -0
  10. package/dist_ts/core/index.js +3 -1
  11. package/dist_ts/core/types.d.ts +14 -0
  12. package/dist_ts/integrations/braviatv/braviatv.classes.client.d.ts +23 -72
  13. package/dist_ts/integrations/braviatv/braviatv.classes.client.js +265 -625
  14. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.d.ts +7 -7
  15. package/dist_ts/integrations/braviatv/braviatv.classes.configflow.js +51 -68
  16. package/dist_ts/integrations/braviatv/braviatv.classes.integration.d.ts +8 -11
  17. package/dist_ts/integrations/braviatv/braviatv.classes.integration.js +186 -135
  18. package/dist_ts/integrations/braviatv/braviatv.discovery.js +12 -11
  19. package/dist_ts/integrations/braviatv/braviatv.mapper.d.ts +6 -14
  20. package/dist_ts/integrations/braviatv/braviatv.mapper.js +37 -131
  21. package/dist_ts/integrations/braviatv/braviatv.types.d.ts +55 -133
  22. package/dist_ts/integrations/braviatv/braviatv.validation.d.ts +7 -0
  23. package/dist_ts/integrations/braviatv/braviatv.validation.js +72 -0
  24. package/dist_ts/integrations/broadlink/broadlink.actions.d.ts +2 -0
  25. package/dist_ts/integrations/broadlink/broadlink.actions.js +36 -0
  26. package/dist_ts/integrations/broadlink/broadlink.classes.client.d.ts +21 -19
  27. package/dist_ts/integrations/broadlink/broadlink.classes.client.js +185 -124
  28. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.d.ts +5 -4
  29. package/dist_ts/integrations/broadlink/broadlink.classes.configflow.js +64 -83
  30. package/dist_ts/integrations/broadlink/broadlink.classes.integration.d.ts +16 -19
  31. package/dist_ts/integrations/broadlink/broadlink.classes.integration.js +114 -59
  32. package/dist_ts/integrations/broadlink/broadlink.mapper.d.ts +3 -2
  33. package/dist_ts/integrations/broadlink/broadlink.mapper.js +2 -1
  34. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.d.ts +10 -0
  35. package/dist_ts/integrations/broadlink/broadlink.selected.mapper.js +41 -0
  36. package/dist_ts/integrations/broadlink/broadlink.types.d.ts +43 -7
  37. package/dist_ts/integrations/broadlink/broadlink.validation.d.ts +7 -0
  38. package/dist_ts/integrations/broadlink/broadlink.validation.js +63 -0
  39. package/dist_ts/integrations/daikin/daikin.classes.client.d.ts +10 -52
  40. package/dist_ts/integrations/daikin/daikin.classes.client.js +55 -614
  41. package/dist_ts/integrations/daikin/daikin.classes.configflow.d.ts +8 -12
  42. package/dist_ts/integrations/daikin/daikin.classes.configflow.js +77 -138
  43. package/dist_ts/integrations/daikin/daikin.classes.integration.d.ts +7 -24
  44. package/dist_ts/integrations/daikin/daikin.classes.integration.js +175 -67
  45. package/dist_ts/integrations/daikin/daikin.discovery.d.ts +11 -24
  46. package/dist_ts/integrations/daikin/daikin.discovery.js +98 -305
  47. package/dist_ts/integrations/daikin/daikin.mapper.d.ts +6 -7
  48. package/dist_ts/integrations/daikin/daikin.mapper.js +95 -155
  49. package/dist_ts/integrations/daikin/daikin.types.d.ts +24 -44
  50. package/dist_ts/integrations/daikin/daikin.types.js +1 -1
  51. package/dist_ts/integrations/daikin/daikin.validation.d.ts +5 -0
  52. package/dist_ts/integrations/daikin/daikin.validation.js +53 -0
  53. package/dist_ts/integrations/denonavr/denonavr.classes.client.d.ts +31 -40
  54. package/dist_ts/integrations/denonavr/denonavr.classes.client.js +149 -404
  55. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.d.ts +7 -2
  56. package/dist_ts/integrations/denonavr/denonavr.classes.configflow.js +44 -36
  57. package/dist_ts/integrations/denonavr/denonavr.classes.integration.d.ts +6 -11
  58. package/dist_ts/integrations/denonavr/denonavr.classes.integration.js +192 -113
  59. package/dist_ts/integrations/denonavr/denonavr.discovery.d.ts +10 -18
  60. package/dist_ts/integrations/denonavr/denonavr.discovery.js +71 -193
  61. package/dist_ts/integrations/denonavr/denonavr.mapper.d.ts +5 -13
  62. package/dist_ts/integrations/denonavr/denonavr.mapper.js +35 -159
  63. package/dist_ts/integrations/denonavr/denonavr.types.d.ts +55 -90
  64. package/dist_ts/integrations/denonavr/denonavr.validation.d.ts +10 -0
  65. package/dist_ts/integrations/denonavr/denonavr.validation.js +86 -0
  66. package/dist_ts/integrations/kodi/kodi.classes.client.d.ts +11 -45
  67. package/dist_ts/integrations/kodi/kodi.classes.client.js +84 -310
  68. package/dist_ts/integrations/kodi/kodi.classes.configflow.d.ts +9 -8
  69. package/dist_ts/integrations/kodi/kodi.classes.configflow.js +53 -48
  70. package/dist_ts/integrations/kodi/kodi.classes.integration.d.ts +11 -11
  71. package/dist_ts/integrations/kodi/kodi.classes.integration.js +114 -171
  72. package/dist_ts/integrations/kodi/kodi.discovery.js +53 -29
  73. package/dist_ts/integrations/kodi/kodi.mapper.d.ts +7 -2
  74. package/dist_ts/integrations/kodi/kodi.mapper.js +48 -10
  75. package/dist_ts/integrations/kodi/kodi.types.d.ts +32 -28
  76. package/dist_ts/integrations/kodi/kodi.validation.d.ts +9 -0
  77. package/dist_ts/integrations/kodi/kodi.validation.js +62 -0
  78. package/dist_ts/integrations/modbus/modbus.classes.client.d.ts +15 -61
  79. package/dist_ts/integrations/modbus/modbus.classes.client.js +117 -776
  80. package/dist_ts/integrations/modbus/modbus.classes.configflow.d.ts +9 -5
  81. package/dist_ts/integrations/modbus/modbus.classes.configflow.js +70 -38
  82. package/dist_ts/integrations/modbus/modbus.classes.integration.d.ts +6 -17
  83. package/dist_ts/integrations/modbus/modbus.classes.integration.js +133 -57
  84. package/dist_ts/integrations/modbus/modbus.discovery.d.ts +5 -8
  85. package/dist_ts/integrations/modbus/modbus.discovery.js +38 -93
  86. package/dist_ts/integrations/modbus/modbus.mapper.d.ts +8 -32
  87. package/dist_ts/integrations/modbus/modbus.mapper.js +71 -431
  88. package/dist_ts/integrations/modbus/modbus.types.d.ts +82 -332
  89. package/dist_ts/integrations/modbus/modbus.validation.d.ts +10 -0
  90. package/dist_ts/integrations/modbus/modbus.validation.js +128 -0
  91. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.d.ts +12 -34
  92. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.client.js +143 -231
  93. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.d.ts +6 -1
  94. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.configflow.js +105 -18
  95. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.d.ts +8 -8
  96. package/dist_ts/integrations/nanoleaf/nanoleaf.classes.integration.js +141 -155
  97. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.d.ts +9 -0
  98. package/dist_ts/integrations/nanoleaf/nanoleaf.credentials.js +35 -0
  99. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.d.ts +6 -18
  100. package/dist_ts/integrations/nanoleaf/nanoleaf.mapper.js +45 -220
  101. package/dist_ts/integrations/nanoleaf/nanoleaf.types.d.ts +33 -147
  102. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.d.ts +6 -0
  103. package/dist_ts/integrations/nanoleaf/nanoleaf.validation.js +82 -0
  104. package/dist_ts/integrations/onkyo/onkyo.classes.client.d.ts +15 -20
  105. package/dist_ts/integrations/onkyo/onkyo.classes.client.js +161 -404
  106. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.d.ts +9 -4
  107. package/dist_ts/integrations/onkyo/onkyo.classes.configflow.js +51 -6
  108. package/dist_ts/integrations/onkyo/onkyo.classes.integration.d.ts +22 -6
  109. package/dist_ts/integrations/onkyo/onkyo.classes.integration.js +144 -11
  110. package/dist_ts/integrations/onkyo/onkyo.discovery.d.ts +6 -1
  111. package/dist_ts/integrations/onkyo/onkyo.discovery.js +40 -4
  112. package/dist_ts/integrations/onkyo/onkyo.mapper.d.ts +7 -8
  113. package/dist_ts/integrations/onkyo/onkyo.mapper.js +45 -12
  114. package/dist_ts/integrations/onkyo/onkyo.types.d.ts +58 -8
  115. package/dist_ts/integrations/onkyo/onkyo.types.js +13 -102
  116. package/dist_ts/integrations/onkyo/onkyo.validation.d.ts +16 -0
  117. package/dist_ts/integrations/onkyo/onkyo.validation.js +77 -0
  118. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.d.ts +25 -25
  119. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.client.js +116 -360
  120. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.d.ts +11 -3
  121. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.js +76 -6
  122. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.d.ts +26 -4
  123. package/dist_ts/integrations/panasonic_viera/panasonic_viera.classes.integration.js +142 -9
  124. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.d.ts +2 -1
  125. package/dist_ts/integrations/panasonic_viera/panasonic_viera.discovery.js +31 -4
  126. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.d.ts +9 -9
  127. package/dist_ts/integrations/panasonic_viera/panasonic_viera.mapper.js +31 -149
  128. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.d.ts +51 -11
  129. package/dist_ts/integrations/panasonic_viera/panasonic_viera.types.js +22 -87
  130. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.d.ts +6 -0
  131. package/dist_ts/integrations/panasonic_viera/panasonic_viera.validation.js +56 -0
  132. package/dist_ts/integrations/pioneer/pioneer.classes.client.d.ts +31 -16
  133. package/dist_ts/integrations/pioneer/pioneer.classes.client.js +167 -409
  134. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.d.ts +10 -3
  135. package/dist_ts/integrations/pioneer/pioneer.classes.configflow.js +66 -6
  136. package/dist_ts/integrations/pioneer/pioneer.classes.integration.d.ts +13 -5
  137. package/dist_ts/integrations/pioneer/pioneer.classes.integration.js +239 -11
  138. package/dist_ts/integrations/pioneer/pioneer.discovery.d.ts +14 -1
  139. package/dist_ts/integrations/pioneer/pioneer.discovery.js +51 -4
  140. package/dist_ts/integrations/pioneer/pioneer.mapper.d.ts +14 -8
  141. package/dist_ts/integrations/pioneer/pioneer.mapper.js +54 -12
  142. package/dist_ts/integrations/pioneer/pioneer.types.d.ts +79 -12
  143. package/dist_ts/integrations/pioneer/pioneer.types.js +12 -76
  144. package/dist_ts/integrations/pioneer/pioneer.validation.d.ts +10 -0
  145. package/dist_ts/integrations/pioneer/pioneer.validation.js +85 -0
  146. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.d.ts +13 -36
  147. package/dist_ts/integrations/soundtouch/soundtouch.classes.client.js +179 -502
  148. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.d.ts +6 -1
  149. package/dist_ts/integrations/soundtouch/soundtouch.classes.configflow.js +50 -40
  150. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.d.ts +14 -15
  151. package/dist_ts/integrations/soundtouch/soundtouch.classes.integration.js +108 -128
  152. package/dist_ts/integrations/soundtouch/soundtouch.discovery.d.ts +2 -20
  153. package/dist_ts/integrations/soundtouch/soundtouch.discovery.js +23 -113
  154. package/dist_ts/integrations/soundtouch/soundtouch.mapper.d.ts +3 -12
  155. package/dist_ts/integrations/soundtouch/soundtouch.mapper.js +35 -189
  156. package/dist_ts/integrations/soundtouch/soundtouch.types.d.ts +57 -142
  157. package/dist_ts/integrations/soundtouch/soundtouch.types.js +18 -3
  158. package/dist_ts/integrations/soundtouch/soundtouch.validation.d.ts +22 -0
  159. package/dist_ts/integrations/soundtouch/soundtouch.validation.js +65 -0
  160. package/dist_ts/integrations/wiz/index.d.ts +1 -0
  161. package/dist_ts/integrations/wiz/index.js +2 -1
  162. package/dist_ts/integrations/wiz/wiz.classes.client.d.ts +14 -28
  163. package/dist_ts/integrations/wiz/wiz.classes.client.js +93 -229
  164. package/dist_ts/integrations/wiz/wiz.classes.configflow.d.ts +6 -4
  165. package/dist_ts/integrations/wiz/wiz.classes.configflow.js +38 -67
  166. package/dist_ts/integrations/wiz/wiz.classes.integration.d.ts +10 -21
  167. package/dist_ts/integrations/wiz/wiz.classes.integration.js +204 -44
  168. package/dist_ts/integrations/wiz/wiz.discovery.d.ts +10 -31
  169. package/dist_ts/integrations/wiz/wiz.discovery.js +48 -249
  170. package/dist_ts/integrations/wiz/wiz.mapper.d.ts +7 -51
  171. package/dist_ts/integrations/wiz/wiz.mapper.js +82 -668
  172. package/dist_ts/integrations/wiz/wiz.types.d.ts +34 -208
  173. package/dist_ts/integrations/wiz/wiz.validation.d.ts +8 -0
  174. package/dist_ts/integrations/wiz/wiz.validation.js +72 -0
  175. package/dist_ts/integrations/yamaha/index.d.ts +1 -0
  176. package/dist_ts/integrations/yamaha/index.js +2 -1
  177. package/dist_ts/integrations/yamaha/yamaha.classes.client.d.ts +30 -4
  178. package/dist_ts/integrations/yamaha/yamaha.classes.client.js +162 -6
  179. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.d.ts +10 -3
  180. package/dist_ts/integrations/yamaha/yamaha.classes.configflow.js +106 -6
  181. package/dist_ts/integrations/yamaha/yamaha.classes.integration.d.ts +22 -4
  182. package/dist_ts/integrations/yamaha/yamaha.classes.integration.js +243 -8
  183. package/dist_ts/integrations/yamaha/yamaha.discovery.d.ts +13 -1
  184. package/dist_ts/integrations/yamaha/yamaha.discovery.js +57 -4
  185. package/dist_ts/integrations/yamaha/yamaha.mapper.d.ts +16 -8
  186. package/dist_ts/integrations/yamaha/yamaha.mapper.js +58 -12
  187. package/dist_ts/integrations/yamaha/yamaha.types.d.ts +73 -6
  188. package/dist_ts/integrations/yamaha/yamaha.types.js +8 -94
  189. package/dist_ts/integrations/yamaha/yamaha.validation.d.ts +12 -0
  190. package/dist_ts/integrations/yamaha/yamaha.validation.js +89 -0
  191. package/package.json +3 -3
  192. package/readme.md +514 -2
  193. package/ts/00_commitinfo_data.ts +1 -1
  194. package/ts/core/classes.configstore.ts +84 -27
  195. package/ts/core/classes.nativehomeadmission.ts +96 -0
  196. package/ts/core/classes.nativeintegrationowner.ts +297 -0
  197. package/ts/core/index.ts +2 -0
  198. package/ts/core/types.ts +16 -0
  199. package/ts/integrations/braviatv/braviatv.classes.client.ts +245 -709
  200. package/ts/integrations/braviatv/braviatv.classes.configflow.ts +47 -76
  201. package/ts/integrations/braviatv/braviatv.classes.integration.ts +167 -147
  202. package/ts/integrations/braviatv/braviatv.discovery.ts +11 -10
  203. package/ts/integrations/braviatv/braviatv.mapper.ts +39 -142
  204. package/ts/integrations/braviatv/braviatv.types.ts +53 -173
  205. package/ts/integrations/braviatv/braviatv.validation.ts +68 -0
  206. package/ts/integrations/broadlink/broadlink.actions.ts +31 -0
  207. package/ts/integrations/broadlink/broadlink.classes.client.ts +170 -144
  208. package/ts/integrations/broadlink/broadlink.classes.configflow.ts +59 -89
  209. package/ts/integrations/broadlink/broadlink.classes.integration.ts +110 -64
  210. package/ts/integrations/broadlink/broadlink.mapper.ts +5 -4
  211. package/ts/integrations/broadlink/broadlink.selected.mapper.ts +46 -0
  212. package/ts/integrations/broadlink/broadlink.types.ts +48 -8
  213. package/ts/integrations/broadlink/broadlink.validation.ts +66 -0
  214. package/ts/integrations/daikin/daikin.classes.client.ts +52 -661
  215. package/ts/integrations/daikin/daikin.classes.configflow.ts +72 -152
  216. package/ts/integrations/daikin/daikin.classes.integration.ts +166 -71
  217. package/ts/integrations/daikin/daikin.discovery.ts +94 -346
  218. package/ts/integrations/daikin/daikin.mapper.ts +83 -166
  219. package/ts/integrations/daikin/daikin.types.ts +27 -48
  220. package/ts/integrations/daikin/daikin.validation.ts +51 -0
  221. package/ts/integrations/daikin/readme.md +83 -0
  222. package/ts/integrations/denonavr/denonavr.classes.client.ts +132 -421
  223. package/ts/integrations/denonavr/denonavr.classes.configflow.ts +44 -37
  224. package/ts/integrations/denonavr/denonavr.classes.integration.ts +171 -117
  225. package/ts/integrations/denonavr/denonavr.discovery.ts +67 -220
  226. package/ts/integrations/denonavr/denonavr.mapper.ts +36 -182
  227. package/ts/integrations/denonavr/denonavr.types.ts +48 -111
  228. package/ts/integrations/denonavr/denonavr.validation.ts +87 -0
  229. package/ts/integrations/kodi/kodi.classes.client.ts +72 -352
  230. package/ts/integrations/kodi/kodi.classes.configflow.ts +52 -55
  231. package/ts/integrations/kodi/kodi.classes.integration.ts +97 -178
  232. package/ts/integrations/kodi/kodi.discovery.ts +49 -28
  233. package/ts/integrations/kodi/kodi.mapper.ts +52 -10
  234. package/ts/integrations/kodi/kodi.types.ts +33 -58
  235. package/ts/integrations/kodi/kodi.validation.ts +60 -0
  236. package/ts/integrations/modbus/modbus.classes.client.ts +100 -842
  237. package/ts/integrations/modbus/modbus.classes.configflow.ts +70 -41
  238. package/ts/integrations/modbus/modbus.classes.integration.ts +115 -60
  239. package/ts/integrations/modbus/modbus.discovery.ts +38 -106
  240. package/ts/integrations/modbus/modbus.mapper.ts +64 -467
  241. package/ts/integrations/modbus/modbus.types.ts +64 -381
  242. package/ts/integrations/modbus/modbus.validation.ts +119 -0
  243. package/ts/integrations/nanoleaf/nanoleaf.classes.client.ts +115 -249
  244. package/ts/integrations/nanoleaf/nanoleaf.classes.configflow.ts +90 -19
  245. package/ts/integrations/nanoleaf/nanoleaf.classes.integration.ts +130 -181
  246. package/ts/integrations/nanoleaf/nanoleaf.credentials.ts +39 -0
  247. package/ts/integrations/nanoleaf/nanoleaf.mapper.ts +47 -260
  248. package/ts/integrations/nanoleaf/nanoleaf.types.ts +29 -147
  249. package/ts/integrations/nanoleaf/nanoleaf.validation.ts +77 -0
  250. package/ts/integrations/onkyo/onkyo.classes.client.ts +148 -457
  251. package/ts/integrations/onkyo/onkyo.classes.configflow.ts +52 -6
  252. package/ts/integrations/onkyo/onkyo.classes.integration.ts +121 -12
  253. package/ts/integrations/onkyo/onkyo.discovery.ts +41 -3
  254. package/ts/integrations/onkyo/onkyo.mapper.ts +46 -19
  255. package/ts/integrations/onkyo/onkyo.types.ts +55 -110
  256. package/ts/integrations/onkyo/onkyo.validation.ts +85 -0
  257. package/ts/integrations/onkyo/readme.md +126 -0
  258. package/ts/integrations/panasonic_viera/panasonic_viera.classes.client.ts +101 -398
  259. package/ts/integrations/panasonic_viera/panasonic_viera.classes.configflow.ts +69 -5
  260. package/ts/integrations/panasonic_viera/panasonic_viera.classes.integration.ts +141 -9
  261. package/ts/integrations/panasonic_viera/panasonic_viera.discovery.ts +32 -3
  262. package/ts/integrations/panasonic_viera/panasonic_viera.mapper.ts +34 -161
  263. package/ts/integrations/panasonic_viera/panasonic_viera.types.ts +52 -96
  264. package/ts/integrations/panasonic_viera/panasonic_viera.validation.ts +56 -0
  265. package/ts/integrations/pioneer/pioneer.classes.client.ts +132 -428
  266. package/ts/integrations/pioneer/pioneer.classes.configflow.ts +67 -5
  267. package/ts/integrations/pioneer/pioneer.classes.integration.ts +225 -11
  268. package/ts/integrations/pioneer/pioneer.discovery.ts +45 -3
  269. package/ts/integrations/pioneer/pioneer.mapper.ts +57 -13
  270. package/ts/integrations/pioneer/pioneer.types.ts +87 -85
  271. package/ts/integrations/pioneer/pioneer.validation.ts +84 -0
  272. package/ts/integrations/soundtouch/soundtouch.classes.client.ts +152 -571
  273. package/ts/integrations/soundtouch/soundtouch.classes.configflow.ts +47 -42
  274. package/ts/integrations/soundtouch/soundtouch.classes.integration.ts +95 -150
  275. package/ts/integrations/soundtouch/soundtouch.discovery.ts +21 -133
  276. package/ts/integrations/soundtouch/soundtouch.mapper.ts +36 -207
  277. package/ts/integrations/soundtouch/soundtouch.types.ts +50 -195
  278. package/ts/integrations/soundtouch/soundtouch.validation.ts +60 -0
  279. package/ts/integrations/wiz/index.ts +1 -0
  280. package/ts/integrations/wiz/wiz.classes.client.ts +84 -254
  281. package/ts/integrations/wiz/wiz.classes.configflow.ts +39 -70
  282. package/ts/integrations/wiz/wiz.classes.integration.ts +189 -45
  283. package/ts/integrations/wiz/wiz.discovery.ts +48 -291
  284. package/ts/integrations/wiz/wiz.mapper.ts +81 -754
  285. package/ts/integrations/wiz/wiz.types.ts +24 -224
  286. package/ts/integrations/wiz/wiz.validation.ts +73 -0
  287. package/ts/integrations/yamaha/index.ts +1 -0
  288. package/ts/integrations/yamaha/yamaha.classes.client.ts +150 -6
  289. package/ts/integrations/yamaha/yamaha.classes.configflow.ts +100 -5
  290. package/ts/integrations/yamaha/yamaha.classes.integration.ts +236 -8
  291. package/ts/integrations/yamaha/yamaha.discovery.ts +52 -3
  292. package/ts/integrations/yamaha/yamaha.mapper.ts +65 -13
  293. package/ts/integrations/yamaha/yamaha.types.ts +77 -97
  294. package/ts/integrations/yamaha/yamaha.validation.ts +86 -0
@@ -1,323 +1,97 @@
1
- const defaultPort = 8080;
2
- const defaultWsPort = 9090;
3
- const defaultTimeoutMs = 5000;
4
- const playerProperties = ['time', 'totaltime', 'speed', 'live', 'percentage', 'playlistid', 'position', 'repeat', 'shuffled'];
5
- const itemProperties = ['title', 'file', 'uniqueid', 'thumbnail', 'artist', 'albumartist', 'showtitle', 'album', 'season', 'episode', 'streamdetails'];
6
- export class KodiJsonRpcError extends Error {
7
- method;
8
- code;
9
- data;
10
- constructor(method, code, messageArg, data) {
11
- super(`Kodi JSON-RPC ${method} failed${typeof code === 'number' ? ` (${code})` : ''}: ${messageArg}`);
12
- this.method = method;
13
- this.code = code;
14
- this.data = data;
15
- this.name = 'KodiJsonRpcError';
16
- }
17
- }
1
+ import * as plugins from '../../plugins.js';
2
+ import { NativeHomeAdmission } from '../../core/classes.nativehomeadmission.js';
3
+ import { kodiKeys, kodiRecord, kodiSignal, normalizeKodiConfig } from './kodi.validation.js';
4
+ /** Consumer lifecycle and home projection; the foundation owns all protocol work. */
18
5
  export class KodiClient {
19
- config;
20
- requestId = 1;
21
- constructor(config) {
22
- this.config = config;
23
- }
24
- async getSnapshot() {
25
- if (this.config.snapshot) {
26
- return this.normalizeSnapshot(this.cloneSnapshot(this.config.snapshot));
27
- }
28
- if (!this.config.host) {
29
- return this.normalizeSnapshot({
30
- deviceInfo: this.deviceInfoFromConfig(),
31
- players: [],
32
- online: false,
33
- updatedAt: new Date().toISOString(),
34
- });
35
- }
36
- const [application, players] = await Promise.all([
37
- this.getApplicationProperties().catch(() => undefined),
38
- this.getActivePlayers(),
39
- ]);
40
- const player = players[0];
41
- const [playerPropertiesResult, item] = player ? await Promise.all([
42
- this.getPlayerProperties(player.playerid).catch(() => undefined),
43
- this.getPlayerItem(player.playerid).catch(() => undefined),
44
- ]) : [undefined, undefined];
45
- return this.normalizeSnapshot({
46
- deviceInfo: {
47
- ...this.deviceInfoFromConfig(),
48
- name: this.config.name || this.config.deviceInfo?.name || application?.name || this.config.host,
49
- version: this.versionString(application),
50
- },
51
- application,
52
- players,
53
- player,
54
- playerProperties: playerPropertiesResult,
55
- item,
56
- online: true,
57
- updatedAt: new Date().toISOString(),
58
- });
59
- }
60
- async ping() {
61
- const result = await this.callMethod('JSONRPC.Ping');
62
- return result === 'pong';
63
- }
64
- async getApplicationProperties() {
65
- return this.callMethod('Application.GetProperties', {
66
- properties: ['name', 'version', 'volume', 'muted'],
67
- });
68
- }
69
- async getActivePlayers() {
70
- return this.callMethod('Player.GetActivePlayers');
71
- }
72
- async getPlayerProperties(playerIdArg) {
73
- return this.callMethod('Player.GetProperties', {
74
- playerid: playerIdArg,
75
- properties: playerProperties,
76
- });
77
- }
78
- async getPlayerItem(playerIdArg) {
79
- const result = await this.callMethod('Player.GetItem', {
80
- playerid: playerIdArg,
81
- properties: itemProperties,
82
- });
83
- return result.item;
84
- }
85
- async setVolumeLevel(volumeLevelArg) {
86
- return this.callMethod('Application.SetVolume', {
87
- volume: Math.max(0, Math.min(100, Math.round(volumeLevelArg * 100))),
6
+ #config;
7
+ #context;
8
+ #protocol;
9
+ #lifetime = new AbortController();
10
+ #parentSignal;
11
+ #onParentAbort;
12
+ #operations = new Set();
13
+ #closed = false;
14
+ #healthy = false;
15
+ #closePromise;
16
+ constructor(config, context, options = {}) {
17
+ this.#config = normalizeKodiConfig(config);
18
+ this.#context = new NativeHomeAdmission('kodi').admit(context, this.#config.homeId);
19
+ const value = kodiRecord(options, 'client options');
20
+ kodiKeys(value, ['getBasicCredentials']);
21
+ this.#parentSignal = this.#context.abortSignal;
22
+ if (value.getBasicCredentials !== undefined && typeof value.getBasicCredentials !== 'function')
23
+ throw new TypeError('Kodi Basic provider must be a function.');
24
+ this.#parentSignal?.throwIfAborted();
25
+ this.#protocol = new plugins.ecobridgeDeviceManager.KodiProtocol({
26
+ origin: this.#config.origin, expectedApplicationName: this.#config.expectedApplicationName,
27
+ expectedApplicationMajor: this.#config.expectedApplicationMajor, allowUnencryptedHttp: true,
28
+ control: this.#config.control, timeoutMs: this.#config.timeoutMs,
29
+ maxQueuedOperations: this.#config.maxQueuedOperations, maxResponseBytes: this.#config.maxResponseBytes,
30
+ getBasicCredentials: value.getBasicCredentials,
88
31
  });
89
- }
90
- async stepVolume(directionArg) {
91
- return this.callMethod('Application.SetVolume', { volume: directionArg });
92
- }
93
- async setMuted(mutedArg) {
94
- return this.callMethod('Application.SetMute', { mute: mutedArg });
95
- }
96
- async playPause() {
97
- return this.playState('toggle');
98
- }
99
- async play() {
100
- return this.playState(true);
101
- }
102
- async pause() {
103
- return this.playState(false);
104
- }
105
- async stop() {
106
- return this.callMethod('Player.Stop', { playerid: await this.activePlayerId() });
107
- }
108
- async nextTrack() {
109
- return this.callMethod('Player.GoTo', { playerid: await this.activePlayerId(), to: 'next' });
110
- }
111
- async previousTrack() {
112
- return this.callMethod('Player.GoTo', { playerid: await this.activePlayerId(), to: 'previous' });
113
- }
114
- async seek(positionSecondsArg) {
115
- return this.callMethod('Player.Seek', {
116
- playerid: await this.activePlayerId(),
117
- value: { time: this.secondsToTime(positionSecondsArg) },
118
- });
119
- }
120
- async playMedia(mediaTypeArg, mediaIdArg) {
121
- return this.callMethod('Player.Open', { item: this.mediaItem(mediaTypeArg, mediaIdArg) });
122
- }
123
- async clearPlaylist(playlistIdArg = 0) {
124
- return this.callMethod('Playlist.Clear', { playlistid: playlistIdArg });
125
- }
126
- async addToPlaylist(mediaTypeArg, mediaIdArg, playlistIdArg = 0) {
127
- return this.callMethod('Playlist.Add', {
128
- playlistid: playlistIdArg,
129
- item: this.playlistItem(mediaTypeArg, mediaIdArg),
130
- });
131
- }
132
- async showNotification(titleArg, messageArg, iconArg = 'info', displayTimeMsArg = 10000) {
133
- return this.callMethod('GUI.ShowNotification', {
134
- title: titleArg,
135
- message: messageArg,
136
- image: iconArg,
137
- displaytime: Math.max(1500, Math.round(displayTimeMsArg)),
32
+ this.#onParentAbort = () => { void this.destroy().catch(() => { }); };
33
+ this.#parentSignal?.addEventListener('abort', this.#onParentAbort, { once: true });
34
+ if (this.#parentSignal?.aborted)
35
+ this.#onParentAbort();
36
+ }
37
+ isHealthy() { return this.#healthy && !this.#closed && !this.#protocol.isClosed; }
38
+ getSnapshot(signal) {
39
+ return this.run(async (signal) => this.project(await this.#protocol.readSnapshot({ signal })), signal);
40
+ }
41
+ setVolume(volume, signal) {
42
+ return this.run((signal) => this.#protocol.setVolume(volume, { signal }), signal);
43
+ }
44
+ setMuted(muted, signal) {
45
+ return this.run((signal) => this.#protocol.setMuted(muted, { signal }), signal);
46
+ }
47
+ destroy() {
48
+ if (this.#closePromise)
49
+ return this.#closePromise;
50
+ this.#closed = true;
51
+ this.#healthy = false;
52
+ this.#closePromise = Promise.resolve().then(async () => {
53
+ const [protocolCleanup] = await Promise.allSettled([this.#protocol.close(), ...this.#operations]);
54
+ // Operation failures belong to their callers; this close still joins every projection.
55
+ if (protocolCleanup.status === 'rejected')
56
+ throw protocolCleanup.reason;
138
57
  });
58
+ this.#parentSignal?.removeEventListener('abort', this.#onParentAbort);
59
+ this.#lifetime.abort(new Error('Kodi client is closed.'));
60
+ return this.#closePromise;
139
61
  }
140
- async input(commandArg) {
141
- const method = this.inputMethod(commandArg);
142
- return this.callMethod(method);
143
- }
144
- async quit() {
145
- return this.callMethod('Application.Quit');
62
+ project(state) {
63
+ return Object.freeze({ ...state, homeId: this.#context.homeId, name: this.#config.name ?? state.applicationName, online: true });
146
64
  }
147
- async callMethod(methodArg, paramsArg) {
148
- if (!this.config.host) {
149
- throw new Error('Kodi host is required when snapshot data is not provided.');
65
+ run(work, callerSignal) {
66
+ if (this.#closed || this.#protocol.isClosed)
67
+ return Promise.reject(new plugins.ecobridgeDeviceManager.KodiProtocolError('closed', 'Kodi client is terminally closed.'));
68
+ let signal;
69
+ try {
70
+ kodiSignal(callerSignal);
71
+ if (callerSignal?.aborted)
72
+ throw new plugins.ecobridgeDeviceManager.KodiProtocolError('cancelled', 'Kodi operation was cancelled before admission.');
73
+ signal = AbortSignal.any([this.#lifetime.signal, ...(callerSignal ? [callerSignal] : [])]);
150
74
  }
151
- const request = {
152
- jsonrpc: '2.0',
153
- method: methodArg,
154
- id: this.requestId++,
155
- };
156
- if (paramsArg !== undefined) {
157
- request.params = paramsArg;
75
+ catch (error) {
76
+ return Promise.reject(error);
158
77
  }
159
- const abortController = new AbortController();
160
- const timeout = setTimeout(() => abortController.abort(), this.config.timeoutMs || defaultTimeoutMs);
78
+ let operation;
161
79
  try {
162
- const response = await globalThis.fetch(this.jsonRpcUrl(), {
163
- method: 'POST',
164
- headers: this.headers(),
165
- body: JSON.stringify(request),
166
- signal: abortController.signal,
80
+ operation = work(signal).then((result) => {
81
+ this.#healthy = !this.#closed && !signal.aborted && !this.#protocol.isClosed;
82
+ return result;
83
+ }, (error) => {
84
+ this.#healthy = false;
85
+ throw error;
167
86
  });
168
- const text = await response.text();
169
- if (!response.ok) {
170
- throw new Error(`Kodi request ${methodArg} failed with HTTP ${response.status}: ${text}`);
171
- }
172
- const payload = JSON.parse(text);
173
- if (payload.error) {
174
- throw new KodiJsonRpcError(methodArg, payload.error.code, payload.error.message || 'Unknown JSON-RPC error', payload.error.data);
175
- }
176
- return payload.result;
177
- }
178
- finally {
179
- clearTimeout(timeout);
180
- }
181
- }
182
- async destroy() { }
183
- async playState(playArg) {
184
- return this.callMethod('Player.PlayPause', {
185
- playerid: await this.activePlayerId(),
186
- play: playArg,
187
- });
188
- }
189
- async activePlayerId() {
190
- const snapshot = await this.getSnapshot();
191
- const playerId = snapshot.player?.playerid ?? snapshot.players[0]?.playerid;
192
- if (typeof playerId !== 'number') {
193
- throw new Error('Kodi has no active player.');
194
- }
195
- return playerId;
196
- }
197
- mediaItem(mediaTypeArg, mediaIdArg) {
198
- const type = mediaTypeArg.toLowerCase();
199
- if (type === 'playlist') {
200
- return { playlistid: Number(mediaIdArg) };
201
- }
202
- if (type === 'channel') {
203
- return { channelid: Number(mediaIdArg) };
204
- }
205
- if (type === 'directory') {
206
- return { path: String(mediaIdArg), recursive: true };
207
- }
208
- if (type === 'movie') {
209
- return { movieid: Number(mediaIdArg) };
210
- }
211
- if (type === 'episode') {
212
- return { episodeid: Number(mediaIdArg) };
213
- }
214
- if (type === 'season') {
215
- return { seasonid: Number(mediaIdArg) };
216
- }
217
- if (type === 'tvshow') {
218
- return { tvshowid: Number(mediaIdArg) };
219
- }
220
- if (type === 'album') {
221
- return { albumid: Number(mediaIdArg) };
222
- }
223
- if (type === 'artist') {
224
- return { artistid: Number(mediaIdArg) };
225
87
  }
226
- if (type === 'song' || type === 'track') {
227
- return { songid: Number(mediaIdArg) };
228
- }
229
- return { file: String(mediaIdArg) };
230
- }
231
- playlistItem(mediaTypeArg, mediaIdArg) {
232
- const type = mediaTypeArg.toLowerCase();
233
- if (type === 'album') {
234
- return { albumid: Number(mediaIdArg) };
235
- }
236
- if (type === 'artist') {
237
- return { artistid: Number(mediaIdArg) };
238
- }
239
- if (type === 'song' || type === 'track') {
240
- return { songid: Number(mediaIdArg) };
241
- }
242
- return this.mediaItem(type, mediaIdArg);
243
- }
244
- secondsToTime(secondsArg) {
245
- const safeSeconds = Math.max(0, Math.floor(secondsArg));
246
- return {
247
- hours: Math.floor(safeSeconds / 3600),
248
- minutes: Math.floor((safeSeconds % 3600) / 60),
249
- seconds: safeSeconds % 60,
250
- milliseconds: Math.max(0, Math.round((secondsArg - Math.floor(secondsArg)) * 1000)),
251
- };
252
- }
253
- inputMethod(commandArg) {
254
- const normalized = commandArg.replace(/[_\s-]+/g, '').toLowerCase();
255
- const methods = {
256
- up: 'Input.Up',
257
- down: 'Input.Down',
258
- left: 'Input.Left',
259
- right: 'Input.Right',
260
- select: 'Input.Select',
261
- ok: 'Input.Select',
262
- enter: 'Input.Select',
263
- back: 'Input.Back',
264
- home: 'Input.Home',
265
- info: 'Input.Info',
266
- contextmenu: 'Input.ContextMenu',
267
- };
268
- return methods[normalized] || (commandArg.includes('.') ? commandArg : `Input.${commandArg}`);
269
- }
270
- normalizeSnapshot(snapshotArg) {
271
- const deviceInfo = {
272
- ...this.deviceInfoFromConfig(),
273
- ...snapshotArg.deviceInfo,
274
- };
275
- if (!deviceInfo.name) {
276
- deviceInfo.name = snapshotArg.application?.name || this.config.name || this.config.host || 'Kodi';
277
- }
278
- if (!deviceInfo.version) {
279
- deviceInfo.version = this.versionString(snapshotArg.application);
280
- }
281
- return {
282
- ...snapshotArg,
283
- deviceInfo,
284
- players: snapshotArg.players || [],
285
- player: snapshotArg.player || snapshotArg.players?.[0],
286
- online: snapshotArg.online,
287
- };
288
- }
289
- deviceInfoFromConfig() {
290
- return {
291
- ...this.config.deviceInfo,
292
- id: this.config.deviceInfo?.id || this.config.uniqueId,
293
- uuid: this.config.deviceInfo?.uuid || this.config.uniqueId,
294
- name: this.config.deviceInfo?.name || this.config.name,
295
- host: this.config.deviceInfo?.host || this.config.host,
296
- port: this.config.deviceInfo?.port || this.config.port || defaultPort,
297
- wsPort: this.config.deviceInfo?.wsPort || this.config.wsPort || defaultWsPort,
298
- manufacturer: this.config.deviceInfo?.manufacturer || 'Kodi',
299
- };
300
- }
301
- versionString(applicationArg) {
302
- const version = applicationArg?.version;
303
- if (!version || typeof version.major !== 'number') {
304
- return undefined;
305
- }
306
- return `${version.major}.${typeof version.minor === 'number' ? version.minor : 0}${version.revision ? `-${version.revision}` : ''}`;
307
- }
308
- cloneSnapshot(snapshotArg) {
309
- return JSON.parse(JSON.stringify(snapshotArg));
310
- }
311
- jsonRpcUrl() {
312
- const protocol = this.config.ssl ? 'https' : 'http';
313
- return `${protocol}://${this.config.host}:${this.config.port || defaultPort}/jsonrpc`;
314
- }
315
- headers() {
316
- const headers = { 'content-type': 'application/json' };
317
- if (this.config.username !== undefined && this.config.password !== undefined) {
318
- headers.authorization = `Basic ${globalThis.btoa(`${this.config.username}:${this.config.password}`)}`;
88
+ catch (error) {
89
+ return Promise.reject(error);
319
90
  }
320
- return headers;
91
+ this.#operations.add(operation);
92
+ const settled = () => { this.#operations.delete(operation); };
93
+ void operation.then(settled, settled);
94
+ return operation;
321
95
  }
322
96
  }
323
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia29kaS5jbGFzc2VzLmNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2ludGVncmF0aW9ucy9rb2RpL2tvZGkuY2xhc3Nlcy5jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZ0JBLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQztBQUN6QixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUM7QUFDM0IsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUFFOUIsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDOUgsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFFdkosTUFBTSxPQUFPLGdCQUFpQixTQUFRLEtBQUs7SUFDYixNQUFNO0lBQTBCLElBQUk7SUFBMEQsSUFBSTtJQUE5SCxZQUE0QixNQUFjLEVBQWtCLElBQXdCLEVBQUUsVUFBa0IsRUFBa0IsSUFBYztRQUN0SSxLQUFLLENBQUMsaUJBQWlCLE1BQU0sVUFBVSxPQUFPLElBQUksS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxVQUFVLEVBQUUsQ0FBQyxDQUFDO3NCQUQ1RSxNQUFNO29CQUEwQixJQUFJO29CQUEwRCxJQUFJO1FBRTVILElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLFVBQVU7SUFHUSxNQUFNO0lBRjNCLFNBQVMsR0FBRyxDQUFDLENBQUM7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QUFJLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUM1QyxDQUFDO1FBQ0QsSUFBSSxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsSUFBSSxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7WUFDekIsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3ZELENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUNyQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ3pDLENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN2QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQzNDLENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN0QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQzFDLENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN0QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQzFDLENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUNyQixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ3pDLENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN0QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFV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
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia29kaS5jbGFzc2VzLmNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2ludGVncmF0aW9ucy9rb2RpL2tvZGkuY2xhc3Nlcy5jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsbUJBQW1CLEVBQWdDLE1BQU0sMkNBQTJDLENBQUM7QUFFOUcsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFN0YscUZBQXFGO0FBQ3JGLE1BQU0sT0FBTyxVQUFVO0lBQ1osT0FBTyxDQUF3QjtJQUMvQixRQUFRLENBQTBCO0lBQ2xDLFNBQVMsQ0FBOEM7SUFDdkQsU0FBUyxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7SUFDbEMsYUFBYSxDQUFlO0lBQzVCLGNBQWMsQ0FBYTtJQUMzQixXQUFXLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7SUFDbkQsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNoQixRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLGFBQWEsQ0FBaUI7SUFFOUIsWUFBbUIsTUFBbUIsRUFBRSxPQUEwQixFQUFFLE9BQU8sR0FBdUIsRUFBRTtRQUNsRyxJQUFJLENBQUMsT0FBTyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEYsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BELFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztRQUMvQyxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsS0FBSyxTQUFTLElBQUksT0FBTyxLQUFLLENBQUMsbUJBQW1CLEtBQUssVUFBVTtZQUFFLE1BQU0sSUFBSSxTQUFTLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUMvSixJQUFJLENBQUMsYUFBYSxFQUFFLGNBQWMsRUFBRSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxPQUFPLENBQUMsc0JBQXNCLENBQUMsWUFBWSxDQUFDO1lBQy9ELE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLHVCQUF1QjtZQUMxRix3QkFBd0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLHdCQUF3QixFQUFFLG9CQUFvQixFQUFFLElBQUk7WUFDM0YsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVM7WUFDaEUsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtZQUN0RyxtQkFBbUIsRUFBRSxLQUFLLENBQUMsbUJBQWdFO1NBQzVGLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxjQUFjLEdBQUcsR0FBRyxFQUFFLEdBQUcsS0FBSyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxhQUFhLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNuRixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsT0FBTztZQUFFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN6RCxDQUFDO0lBRU0sU0FBUyxLQUFjLE9BQU8sSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFM0YsV0FBVyxDQUFDLE1BQW9CO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDekcsQ0FBQztJQUVNLFNBQVMsQ0FBQyxNQUFjLEVBQUUsTUFBb0I7UUFDbkQsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3BGLENBQUM7SUFFTSxRQUFRLENBQUMsS0FBYyxFQUFFLE1BQW9CO1FBQ2xELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNsRixDQUFDO0lBRU0sT0FBTztRQUNaLElBQUksSUFBSSxDQUFDLGFBQWE7WUFBRSxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDbEQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDdEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ3JELE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDbEcsdUZBQXVGO1lBQ3ZGLElBQUksZUFBZSxDQUFDLE1BQU0sS0FBSyxVQUFVO2dCQUFFLE1BQU0sZUFBZSxDQUFDLE1BQU0sQ0FBQztRQUMxRSxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxhQUFhLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN0RSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUM7UUFDMUQsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTyxPQUFPLENBQUMsS0FBbUQ7UUFDakUsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ25JLENBQUM7SUFFTyxHQUFHLENBQVUsSUFBK0MsRUFBRSxZQUEwQjtRQUM5RixJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRO1lBQUUsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksT0FBTyxDQUFDLHNCQUFzQixDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxtQ0FBbUMsQ0FBQyxDQUFDLENBQUM7UUFDeEssSUFBSSxNQUFtQixDQUFDO1FBQ3hCLElBQUksQ0FBQztZQUNILFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN6QixJQUFJLFlBQVksRUFBRSxPQUFPO2dCQUFFLE1BQU0sSUFBSSxPQUFPLENBQUMsc0JBQXNCLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLGdEQUFnRCxDQUFDLENBQUM7WUFDckosTUFBTSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0YsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFBQyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFBQyxDQUFDO1FBQ2pELElBQUksU0FBMkIsQ0FBQztRQUNoQyxJQUFJLENBQUM7WUFBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUM3QyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztnQkFDN0UsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxFQUFFLENBQUMsS0FBYyxFQUFFLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUMsQ0FBQyxDQUFDO1FBQUMsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFBQyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sT0FBTyxHQUFHLEdBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BFLEtBQUssU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDdEMsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztDQUNGIn0=
@@ -1,10 +1,11 @@
1
- import type { IConfigFlow, IConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
2
- import type { IKodiConfig } from './kodi.types.js';
1
+ import type { IConfigFlow, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
2
+ import { NativeIntegrationOwner } from '../../core/classes.nativeintegrationowner.js';
3
+ import type { IKodiConfig, IKodiConfigFlowContext } from './kodi.types.js';
4
+ /** Captures selected configuration. Setup separately owns live readiness admission. */
3
5
  export declare class KodiConfigFlow implements IConfigFlow<IKodiConfig> {
4
- start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IKodiConfig>>;
5
- private stringValue;
6
- private numberValue;
7
- private booleanValue;
8
- private numberMetadata;
9
- private booleanMetadata;
6
+ #private;
7
+ constructor(owner?: NativeIntegrationOwner);
8
+ destroy(): Promise<void>;
9
+ retryCleanup(): Promise<void>;
10
+ start(input: IDiscoveryCandidate, context: IKodiConfigFlowContext): Promise<IConfigFlowStep<IKodiConfig>>;
10
11
  }
@@ -1,55 +1,60 @@
1
- const defaultPort = 8080;
2
- const defaultWsPort = 9090;
3
- const defaultTimeoutMs = 5000;
1
+ import * as plugins from '../../plugins.js';
2
+ import { NativeIntegrationOwner } from '../../core/classes.nativeintegrationowner.js';
3
+ import { KodiClient } from './kodi.classes.client.js';
4
+ import { kodiInteger, kodiKeys, kodiRecord, kodiText, normalizeKodiConfig } from './kodi.validation.js';
5
+ /** Captures selected configuration. Setup separately owns live readiness admission. */
4
6
  export class KodiConfigFlow {
5
- async start(candidateArg, contextArg) {
6
- void contextArg;
7
+ #scope;
8
+ constructor(owner = new NativeIntegrationOwner('kodi')) {
9
+ this.#scope = owner.createFlowScope();
10
+ }
11
+ destroy() { return this.#scope.close(); }
12
+ retryCleanup() { return this.#scope.retryCleanup(); }
13
+ async start(input, context) {
14
+ const candidate = kodiRecord(input, 'config candidate');
15
+ const host = kodiText(candidate.host, 'selected candidate host', 128);
16
+ const port = kodiInteger(candidate.port === undefined ? 8080 : candidate.port, 1, 65535, 'candidate port');
17
+ const origin = plugins.ecobridgeDeviceManager.validateKodiOrigin(`http://${host}:${port}`);
18
+ const captured = this.#scope.admit(context);
7
19
  return {
8
- kind: 'form',
9
- title: 'Connect Kodi',
10
- description: 'Configure the local Kodi JSON-RPC endpoint.',
20
+ kind: 'form', title: 'Connect selected Kodi application',
21
+ description: 'Specify the expected application name and major for the host-selected home. Accept plaintext HTTP explicitly. Controls default to disabled; enabling them requires endpoint trust and an integer volume ceiling. Live readiness is checked during setup.',
11
22
  fields: [
12
- { name: 'host', label: 'Host', type: 'text', required: true },
13
- { name: 'port', label: 'HTTP JSON-RPC port', type: 'number' },
14
- { name: 'ssl', label: 'Use HTTPS', type: 'boolean' },
15
- { name: 'wsPort', label: 'WebSocket port', type: 'number' },
16
- { name: 'username', label: 'Username', type: 'text' },
17
- { name: 'password', label: 'Password', type: 'password' },
18
- { name: 'name', label: 'Name', type: 'text' },
23
+ { name: 'expectedApplicationName', label: 'Exact application name', type: 'text', required: true },
24
+ { name: 'expectedApplicationMajor', label: 'Application major version', type: 'number', required: true },
25
+ { name: 'allowUnencryptedHttp', label: 'Accept plaintext HTTP', type: 'boolean', required: true },
26
+ { name: 'allowControls', label: 'Enable application volume and mute controls', type: 'boolean' },
27
+ { name: 'trustSelectedEndpoint', label: 'Trust this selected endpoint for controls', type: 'boolean' },
28
+ { name: 'maximumVolume', label: 'Maximum integer application volume (0–100)', type: 'number' },
29
+ { name: 'name', label: 'Display name', type: 'text' },
19
30
  ],
20
- submit: async (valuesArg) => ({
21
- kind: 'done',
22
- title: 'Kodi configured',
23
- config: {
24
- host: this.stringValue(valuesArg.host) || candidateArg.host || '',
25
- port: this.numberValue(valuesArg.port) || candidateArg.port || defaultPort,
26
- wsPort: this.numberValue(valuesArg.wsPort) || this.numberMetadata(candidateArg, 'wsPort') || defaultWsPort,
27
- ssl: this.booleanValue(valuesArg.ssl) ?? this.booleanMetadata(candidateArg, 'ssl') ?? false,
28
- username: this.stringValue(valuesArg.username),
29
- password: this.stringValue(valuesArg.password),
30
- name: this.stringValue(valuesArg.name) || candidateArg.name,
31
- uniqueId: candidateArg.id,
32
- timeoutMs: defaultTimeoutMs,
33
- },
34
- }),
31
+ submit: async (input) => {
32
+ try {
33
+ const values = kodiRecord(input, 'config-flow values');
34
+ return await this.#scope.run(captured, captured.homeId, async (lease) => {
35
+ kodiKeys(values, ['homeId', 'expectedApplicationName', 'expectedApplicationMajor', 'allowUnencryptedHttp', 'allowControls', 'trustSelectedEndpoint', 'maximumVolume', 'name', 'timeoutMs', 'maxQueuedOperations', 'maxResponseBytes']);
36
+ if (values.homeId !== undefined && values.homeId !== lease.context.homeId)
37
+ throw new TypeError('Kodi form home differs from the host-selected home.');
38
+ if (values.allowControls !== undefined && typeof values.allowControls !== 'boolean')
39
+ throw new TypeError('Kodi controls require an explicit boolean opt-in.');
40
+ if (values.allowControls !== true && (values.trustSelectedEndpoint === true || values.maximumVolume !== undefined))
41
+ throw new TypeError('Kodi owner control policy requires an explicit controls opt-in.');
42
+ const config = normalizeKodiConfig({ homeId: lease.context.homeId, origin,
43
+ expectedApplicationName: values.expectedApplicationName, expectedApplicationMajor: values.expectedApplicationMajor,
44
+ allowUnencryptedHttp: values.allowUnencryptedHttp,
45
+ control: values.allowControls === true ? { trustSelectedEndpoint: values.trustSelectedEndpoint, maximumVolume: values.maximumVolume } : undefined,
46
+ name: values.name, timeoutMs: values.timeoutMs, maxQueuedOperations: values.maxQueuedOperations, maxResponseBytes: values.maxResponseBytes });
47
+ // Construction delegates endpoint validation without opening a connection.
48
+ const client = new KodiClient(config, { ...lease.context, abortSignal: lease.signal });
49
+ lease.own(() => client.destroy());
50
+ return { kind: 'done', title: 'Kodi configuration captured', config };
51
+ });
52
+ }
53
+ catch (error) {
54
+ return { kind: 'error', error: error instanceof Error ? error.message : 'Kodi configuration was refused.' };
55
+ }
56
+ },
35
57
  };
36
58
  }
37
- stringValue(valueArg) {
38
- return typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim() : undefined;
39
- }
40
- numberValue(valueArg) {
41
- return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : undefined;
42
- }
43
- booleanValue(valueArg) {
44
- return typeof valueArg === 'boolean' ? valueArg : undefined;
45
- }
46
- numberMetadata(candidateArg, keyArg) {
47
- const value = candidateArg.metadata?.[keyArg];
48
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
49
- }
50
- booleanMetadata(candidateArg, keyArg) {
51
- const value = candidateArg.metadata?.[keyArg];
52
- return typeof value === 'boolean' ? value : undefined;
53
- }
54
59
  }
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia29kaS5jbGFzc2VzLmNvbmZpZ2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9pbnRlZ3JhdGlvbnMva29kaS9rb2RpLmNsYXNzZXMuY29uZmlnZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUM7QUFDekIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDO0FBQzNCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBRTlCLE1BQU0sT0FBTyxjQUFjO0lBQ2xCLEtBQUssQ0FBQyxLQUFLLENBQUMsWUFBaUMsRUFBRSxVQUE4QjtRQUNsRixLQUFLLFVBQVUsQ0FBQztRQUNoQixPQUFPO1lBQ0wsSUFBSSxFQUFFLE1BQU07WUFDWixLQUFLLEVBQUUsY0FBYztZQUNyQixXQUFXLEVBQUUsNkNBQTZDO1lBQzFELE1BQU0sRUFBRTtnQkFDTixFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBQzdELEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtnQkFDN0QsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtnQkFDcEQsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO2dCQUMzRCxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFO2dCQUNyRCxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO2dCQUN6RCxFQUFFLElBQUks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
60
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia29kaS5jbGFzc2VzLmNvbmZpZ2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9pbnRlZ3JhdGlvbnMva29kaS9rb2RpLmNsYXNzZXMuY29uZmlnZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sRUFBRSxzQkFBc0IsRUFBK0IsTUFBTSw4Q0FBOEMsQ0FBQztBQUNuSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFdEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXhHLHVGQUF1RjtBQUN2RixNQUFNLE9BQU8sY0FBYztJQUNoQixNQUFNLENBQXlCO0lBQ3hDLFlBQW1CLEtBQUssR0FBMkIsSUFBSSxzQkFBc0IsQ0FBQyxNQUFNLENBQUM7UUFDbkYsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVNLE9BQU8sS0FBb0IsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RCxZQUFZLEtBQW9CLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFcEUsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUEwQixFQUFFLE9BQStCO1FBQzVFLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUN4RCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN0RSxNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksS0FBSyxTQUFT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