@switchbot/openapi-cli 3.2.1 → 3.2.2

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 (332) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +57349 -170
  3. package/package.json +9 -5
  4. package/dist/api/client.d.ts +0 -31
  5. package/dist/api/client.js +0 -236
  6. package/dist/api/client.js.map +0 -1
  7. package/dist/auth.d.ts +0 -1
  8. package/dist/auth.js +0 -21
  9. package/dist/auth.js.map +0 -1
  10. package/dist/commands/agent-bootstrap.d.ts +0 -10
  11. package/dist/commands/agent-bootstrap.js +0 -200
  12. package/dist/commands/agent-bootstrap.js.map +0 -1
  13. package/dist/commands/auth.d.ts +0 -18
  14. package/dist/commands/auth.js +0 -355
  15. package/dist/commands/auth.js.map +0 -1
  16. package/dist/commands/batch.d.ts +0 -2
  17. package/dist/commands/batch.js +0 -414
  18. package/dist/commands/batch.js.map +0 -1
  19. package/dist/commands/cache.d.ts +0 -2
  20. package/dist/commands/cache.js +0 -127
  21. package/dist/commands/cache.js.map +0 -1
  22. package/dist/commands/capabilities.d.ts +0 -31
  23. package/dist/commands/capabilities.js +0 -383
  24. package/dist/commands/capabilities.js.map +0 -1
  25. package/dist/commands/catalog.d.ts +0 -2
  26. package/dist/commands/catalog.js +0 -360
  27. package/dist/commands/catalog.js.map +0 -1
  28. package/dist/commands/completion.d.ts +0 -2
  29. package/dist/commands/completion.js +0 -386
  30. package/dist/commands/completion.js.map +0 -1
  31. package/dist/commands/config.d.ts +0 -21
  32. package/dist/commands/config.js +0 -377
  33. package/dist/commands/config.js.map +0 -1
  34. package/dist/commands/daemon.d.ts +0 -2
  35. package/dist/commands/daemon.js +0 -411
  36. package/dist/commands/daemon.js.map +0 -1
  37. package/dist/commands/device-meta.d.ts +0 -2
  38. package/dist/commands/device-meta.js +0 -160
  39. package/dist/commands/device-meta.js.map +0 -1
  40. package/dist/commands/devices.d.ts +0 -2
  41. package/dist/commands/devices.js +0 -949
  42. package/dist/commands/devices.js.map +0 -1
  43. package/dist/commands/doctor.d.ts +0 -3
  44. package/dist/commands/doctor.js +0 -1016
  45. package/dist/commands/doctor.js.map +0 -1
  46. package/dist/commands/events.d.ts +0 -31
  47. package/dist/commands/events.js +0 -564
  48. package/dist/commands/events.js.map +0 -1
  49. package/dist/commands/expand.d.ts +0 -2
  50. package/dist/commands/expand.js +0 -131
  51. package/dist/commands/expand.js.map +0 -1
  52. package/dist/commands/explain.d.ts +0 -2
  53. package/dist/commands/explain.js +0 -140
  54. package/dist/commands/explain.js.map +0 -1
  55. package/dist/commands/health.d.ts +0 -8
  56. package/dist/commands/health.js +0 -114
  57. package/dist/commands/health.js.map +0 -1
  58. package/dist/commands/history.d.ts +0 -2
  59. package/dist/commands/history.js +0 -321
  60. package/dist/commands/history.js.map +0 -1
  61. package/dist/commands/identity.d.ts +0 -45
  62. package/dist/commands/identity.js +0 -60
  63. package/dist/commands/identity.js.map +0 -1
  64. package/dist/commands/install.d.ts +0 -20
  65. package/dist/commands/install.js +0 -247
  66. package/dist/commands/install.js.map +0 -1
  67. package/dist/commands/mcp.d.ts +0 -14
  68. package/dist/commands/mcp.js +0 -2018
  69. package/dist/commands/mcp.js.map +0 -1
  70. package/dist/commands/plan.d.ts +0 -51
  71. package/dist/commands/plan.js +0 -654
  72. package/dist/commands/plan.js.map +0 -1
  73. package/dist/commands/policy.d.ts +0 -24
  74. package/dist/commands/policy.js +0 -587
  75. package/dist/commands/policy.js.map +0 -1
  76. package/dist/commands/quota.d.ts +0 -2
  77. package/dist/commands/quota.js +0 -79
  78. package/dist/commands/quota.js.map +0 -1
  79. package/dist/commands/rules.d.ts +0 -2
  80. package/dist/commands/rules.js +0 -876
  81. package/dist/commands/rules.js.map +0 -1
  82. package/dist/commands/scenes.d.ts +0 -2
  83. package/dist/commands/scenes.js +0 -265
  84. package/dist/commands/scenes.js.map +0 -1
  85. package/dist/commands/schema.d.ts +0 -2
  86. package/dist/commands/schema.js +0 -185
  87. package/dist/commands/schema.js.map +0 -1
  88. package/dist/commands/status-sync.d.ts +0 -2
  89. package/dist/commands/status-sync.js +0 -132
  90. package/dist/commands/status-sync.js.map +0 -1
  91. package/dist/commands/uninstall.d.ts +0 -20
  92. package/dist/commands/uninstall.js +0 -238
  93. package/dist/commands/uninstall.js.map +0 -1
  94. package/dist/commands/upgrade-check.d.ts +0 -2
  95. package/dist/commands/upgrade-check.js +0 -107
  96. package/dist/commands/upgrade-check.js.map +0 -1
  97. package/dist/commands/watch.d.ts +0 -2
  98. package/dist/commands/watch.js +0 -195
  99. package/dist/commands/watch.js.map +0 -1
  100. package/dist/commands/webhook.d.ts +0 -2
  101. package/dist/commands/webhook.js +0 -183
  102. package/dist/commands/webhook.js.map +0 -1
  103. package/dist/config.d.ts +0 -57
  104. package/dist/config.js +0 -259
  105. package/dist/config.js.map +0 -1
  106. package/dist/credentials/backends/file.d.ts +0 -18
  107. package/dist/credentials/backends/file.js +0 -102
  108. package/dist/credentials/backends/file.js.map +0 -1
  109. package/dist/credentials/backends/linux.d.ts +0 -16
  110. package/dist/credentials/backends/linux.js +0 -130
  111. package/dist/credentials/backends/linux.js.map +0 -1
  112. package/dist/credentials/backends/macos.d.ts +0 -18
  113. package/dist/credentials/backends/macos.js +0 -130
  114. package/dist/credentials/backends/macos.js.map +0 -1
  115. package/dist/credentials/backends/windows.d.ts +0 -23
  116. package/dist/credentials/backends/windows.js +0 -216
  117. package/dist/credentials/backends/windows.js.map +0 -1
  118. package/dist/credentials/keychain.d.ts +0 -83
  119. package/dist/credentials/keychain.js +0 -89
  120. package/dist/credentials/keychain.js.map +0 -1
  121. package/dist/credentials/prime.d.ts +0 -32
  122. package/dist/credentials/prime.js +0 -53
  123. package/dist/credentials/prime.js.map +0 -1
  124. package/dist/devices/cache.d.ts +0 -79
  125. package/dist/devices/cache.js +0 -294
  126. package/dist/devices/cache.js.map +0 -1
  127. package/dist/devices/catalog.d.ts +0 -138
  128. package/dist/devices/catalog.js +0 -768
  129. package/dist/devices/catalog.js.map +0 -1
  130. package/dist/devices/device-meta.d.ts +0 -15
  131. package/dist/devices/device-meta.js +0 -57
  132. package/dist/devices/device-meta.js.map +0 -1
  133. package/dist/devices/history-agg.d.ts +0 -37
  134. package/dist/devices/history-agg.js +0 -139
  135. package/dist/devices/history-agg.js.map +0 -1
  136. package/dist/devices/history-query.d.ts +0 -45
  137. package/dist/devices/history-query.js +0 -182
  138. package/dist/devices/history-query.js.map +0 -1
  139. package/dist/devices/param-validator.d.ts +0 -40
  140. package/dist/devices/param-validator.js +0 -434
  141. package/dist/devices/param-validator.js.map +0 -1
  142. package/dist/devices/resources.d.ts +0 -74
  143. package/dist/devices/resources.js +0 -271
  144. package/dist/devices/resources.js.map +0 -1
  145. package/dist/index.d.ts +0 -1
  146. package/dist/index.js.map +0 -1
  147. package/dist/install/default-steps.d.ts +0 -66
  148. package/dist/install/default-steps.js +0 -258
  149. package/dist/install/default-steps.js.map +0 -1
  150. package/dist/install/preflight.d.ts +0 -60
  151. package/dist/install/preflight.js +0 -213
  152. package/dist/install/preflight.js.map +0 -1
  153. package/dist/install/steps.d.ts +0 -61
  154. package/dist/install/steps.js +0 -68
  155. package/dist/install/steps.js.map +0 -1
  156. package/dist/lib/command-keywords.d.ts +0 -5
  157. package/dist/lib/command-keywords.js +0 -18
  158. package/dist/lib/command-keywords.js.map +0 -1
  159. package/dist/lib/daemon-state.d.ts +0 -24
  160. package/dist/lib/daemon-state.js +0 -47
  161. package/dist/lib/daemon-state.js.map +0 -1
  162. package/dist/lib/destructive-mode.d.ts +0 -2
  163. package/dist/lib/destructive-mode.js +0 -13
  164. package/dist/lib/destructive-mode.js.map +0 -1
  165. package/dist/lib/devices.d.ts +0 -151
  166. package/dist/lib/devices.js +0 -383
  167. package/dist/lib/devices.js.map +0 -1
  168. package/dist/lib/idempotency.d.ts +0 -46
  169. package/dist/lib/idempotency.js +0 -107
  170. package/dist/lib/idempotency.js.map +0 -1
  171. package/dist/lib/plan-store.d.ts +0 -19
  172. package/dist/lib/plan-store.js +0 -69
  173. package/dist/lib/plan-store.js.map +0 -1
  174. package/dist/lib/request-context.d.ts +0 -7
  175. package/dist/lib/request-context.js +0 -13
  176. package/dist/lib/request-context.js.map +0 -1
  177. package/dist/lib/scenes.d.ts +0 -7
  178. package/dist/lib/scenes.js +0 -11
  179. package/dist/lib/scenes.js.map +0 -1
  180. package/dist/logger.d.ts +0 -4
  181. package/dist/logger.js +0 -17
  182. package/dist/logger.js.map +0 -1
  183. package/dist/mcp/device-history.d.ts +0 -36
  184. package/dist/mcp/device-history.js +0 -146
  185. package/dist/mcp/device-history.js.map +0 -1
  186. package/dist/mcp/events-subscription.d.ts +0 -45
  187. package/dist/mcp/events-subscription.js +0 -214
  188. package/dist/mcp/events-subscription.js.map +0 -1
  189. package/dist/mqtt/client.d.ts +0 -25
  190. package/dist/mqtt/client.js +0 -181
  191. package/dist/mqtt/client.js.map +0 -1
  192. package/dist/mqtt/credential.d.ts +0 -16
  193. package/dist/mqtt/credential.js +0 -31
  194. package/dist/mqtt/credential.js.map +0 -1
  195. package/dist/policy/add-rule.d.ts +0 -21
  196. package/dist/policy/add-rule.js +0 -125
  197. package/dist/policy/add-rule.js.map +0 -1
  198. package/dist/policy/diff.d.ts +0 -21
  199. package/dist/policy/diff.js +0 -92
  200. package/dist/policy/diff.js.map +0 -1
  201. package/dist/policy/format.d.ts +0 -6
  202. package/dist/policy/format.js +0 -58
  203. package/dist/policy/format.js.map +0 -1
  204. package/dist/policy/load.d.ts +0 -32
  205. package/dist/policy/load.js +0 -62
  206. package/dist/policy/load.js.map +0 -1
  207. package/dist/policy/migrate.d.ts +0 -21
  208. package/dist/policy/migrate.js +0 -68
  209. package/dist/policy/migrate.js.map +0 -1
  210. package/dist/policy/schema.d.ts +0 -5
  211. package/dist/policy/schema.js +0 -19
  212. package/dist/policy/schema.js.map +0 -1
  213. package/dist/policy/validate.d.ts +0 -19
  214. package/dist/policy/validate.js +0 -263
  215. package/dist/policy/validate.js.map +0 -1
  216. package/dist/rules/action.d.ts +0 -65
  217. package/dist/rules/action.js +0 -217
  218. package/dist/rules/action.js.map +0 -1
  219. package/dist/rules/audit-query.d.ts +0 -51
  220. package/dist/rules/audit-query.js +0 -90
  221. package/dist/rules/audit-query.js.map +0 -1
  222. package/dist/rules/conflict-analyzer.d.ts +0 -57
  223. package/dist/rules/conflict-analyzer.js +0 -215
  224. package/dist/rules/conflict-analyzer.js.map +0 -1
  225. package/dist/rules/cron-scheduler.d.ts +0 -62
  226. package/dist/rules/cron-scheduler.js +0 -187
  227. package/dist/rules/cron-scheduler.js.map +0 -1
  228. package/dist/rules/destructive.d.ts +0 -20
  229. package/dist/rules/destructive.js +0 -53
  230. package/dist/rules/destructive.js.map +0 -1
  231. package/dist/rules/engine.d.ts +0 -193
  232. package/dist/rules/engine.js +0 -758
  233. package/dist/rules/engine.js.map +0 -1
  234. package/dist/rules/matcher.d.ts +0 -56
  235. package/dist/rules/matcher.js +0 -231
  236. package/dist/rules/matcher.js.map +0 -1
  237. package/dist/rules/pid-file.d.ts +0 -43
  238. package/dist/rules/pid-file.js +0 -96
  239. package/dist/rules/pid-file.js.map +0 -1
  240. package/dist/rules/quiet-hours.d.ts +0 -26
  241. package/dist/rules/quiet-hours.js +0 -46
  242. package/dist/rules/quiet-hours.js.map +0 -1
  243. package/dist/rules/suggest.d.ts +0 -20
  244. package/dist/rules/suggest.js +0 -96
  245. package/dist/rules/suggest.js.map +0 -1
  246. package/dist/rules/throttle.d.ts +0 -61
  247. package/dist/rules/throttle.js +0 -117
  248. package/dist/rules/throttle.js.map +0 -1
  249. package/dist/rules/types.d.ts +0 -117
  250. package/dist/rules/types.js +0 -35
  251. package/dist/rules/types.js.map +0 -1
  252. package/dist/rules/webhook-listener.d.ts +0 -63
  253. package/dist/rules/webhook-listener.js +0 -224
  254. package/dist/rules/webhook-listener.js.map +0 -1
  255. package/dist/rules/webhook-token.d.ts +0 -50
  256. package/dist/rules/webhook-token.js +0 -91
  257. package/dist/rules/webhook-token.js.map +0 -1
  258. package/dist/schema/field-aliases.d.ts +0 -34
  259. package/dist/schema/field-aliases.js +0 -132
  260. package/dist/schema/field-aliases.js.map +0 -1
  261. package/dist/sinks/dispatcher.d.ts +0 -7
  262. package/dist/sinks/dispatcher.js +0 -13
  263. package/dist/sinks/dispatcher.js.map +0 -1
  264. package/dist/sinks/file.d.ts +0 -6
  265. package/dist/sinks/file.js +0 -20
  266. package/dist/sinks/file.js.map +0 -1
  267. package/dist/sinks/format.d.ts +0 -20
  268. package/dist/sinks/format.js +0 -57
  269. package/dist/sinks/format.js.map +0 -1
  270. package/dist/sinks/homeassistant.d.ts +0 -18
  271. package/dist/sinks/homeassistant.js +0 -45
  272. package/dist/sinks/homeassistant.js.map +0 -1
  273. package/dist/sinks/openclaw.d.ts +0 -13
  274. package/dist/sinks/openclaw.js +0 -34
  275. package/dist/sinks/openclaw.js.map +0 -1
  276. package/dist/sinks/stdout.d.ts +0 -4
  277. package/dist/sinks/stdout.js +0 -6
  278. package/dist/sinks/stdout.js.map +0 -1
  279. package/dist/sinks/telegram.d.ts +0 -11
  280. package/dist/sinks/telegram.js +0 -29
  281. package/dist/sinks/telegram.js.map +0 -1
  282. package/dist/sinks/types.d.ts +0 -13
  283. package/dist/sinks/types.js +0 -2
  284. package/dist/sinks/types.js.map +0 -1
  285. package/dist/sinks/webhook.d.ts +0 -6
  286. package/dist/sinks/webhook.js +0 -23
  287. package/dist/sinks/webhook.js.map +0 -1
  288. package/dist/status-sync/manager.d.ts +0 -48
  289. package/dist/status-sync/manager.js +0 -269
  290. package/dist/status-sync/manager.js.map +0 -1
  291. package/dist/utils/arg-parsers.d.ts +0 -16
  292. package/dist/utils/arg-parsers.js +0 -67
  293. package/dist/utils/arg-parsers.js.map +0 -1
  294. package/dist/utils/audit.d.ts +0 -69
  295. package/dist/utils/audit.js +0 -122
  296. package/dist/utils/audit.js.map +0 -1
  297. package/dist/utils/filter.d.ts +0 -81
  298. package/dist/utils/filter.js +0 -190
  299. package/dist/utils/filter.js.map +0 -1
  300. package/dist/utils/flags.d.ts +0 -72
  301. package/dist/utils/flags.js +0 -187
  302. package/dist/utils/flags.js.map +0 -1
  303. package/dist/utils/format.d.ts +0 -9
  304. package/dist/utils/format.js +0 -118
  305. package/dist/utils/format.js.map +0 -1
  306. package/dist/utils/health.d.ts +0 -48
  307. package/dist/utils/health.js +0 -102
  308. package/dist/utils/health.js.map +0 -1
  309. package/dist/utils/help-json.d.ts +0 -39
  310. package/dist/utils/help-json.js +0 -55
  311. package/dist/utils/help-json.js.map +0 -1
  312. package/dist/utils/name-resolver.d.ts +0 -26
  313. package/dist/utils/name-resolver.js +0 -138
  314. package/dist/utils/name-resolver.js.map +0 -1
  315. package/dist/utils/output.d.ts +0 -73
  316. package/dist/utils/output.js +0 -405
  317. package/dist/utils/output.js.map +0 -1
  318. package/dist/utils/quota.d.ts +0 -61
  319. package/dist/utils/quota.js +0 -228
  320. package/dist/utils/quota.js.map +0 -1
  321. package/dist/utils/redact.d.ts +0 -23
  322. package/dist/utils/redact.js +0 -69
  323. package/dist/utils/redact.js.map +0 -1
  324. package/dist/utils/retry.d.ts +0 -72
  325. package/dist/utils/retry.js +0 -141
  326. package/dist/utils/retry.js.map +0 -1
  327. package/dist/utils/string.d.ts +0 -2
  328. package/dist/utils/string.js +0 -23
  329. package/dist/utils/string.js.map +0 -1
  330. package/dist/version.d.ts +0 -2
  331. package/dist/version.js +0 -5
  332. package/dist/version.js.map +0 -1
@@ -1,53 +0,0 @@
1
- /**
2
- * Destructive command parsing — single source of truth shared between the
3
- * policy validator post-hook (rejects destructive commands inside
4
- * `automation.rules[].then[].command`) and the runtime executor (second-
5
- * line guard that refuses to shell out even if validation was bypassed).
6
- */
7
- export const DESTRUCTIVE_COMMANDS = [
8
- 'lock',
9
- 'unlock',
10
- 'deleteWebhook',
11
- 'deleteScene',
12
- 'factoryReset',
13
- ];
14
- /**
15
- * Parse the verb out of a rule action command string. The expected form
16
- * mirrors what the engine will eventually build: `devices command <id> <verb> [args...]`.
17
- * We also accept scene shorthands (`scenes run <id>`, `webhooks delete <id>`).
18
- *
19
- * Returns null for anything we cannot confidently attribute to a known verb
20
- * slot — the validator treats null as "probably fine, let the engine's own
21
- * guard handle it if it's not."
22
- */
23
- export function extractVerb(cmd) {
24
- const trimmed = cmd.trim();
25
- if (!trimmed)
26
- return null;
27
- const tokens = trimmed.split(/\s+/);
28
- // `devices command <id> <verb> [args]`
29
- if (tokens[0] === 'devices' && tokens[1] === 'command' && tokens.length >= 4) {
30
- return tokens[3];
31
- }
32
- // `webhooks delete <id>` → verb is "deleteWebhook"
33
- if (tokens[0] === 'webhooks' && tokens[1] === 'delete')
34
- return 'deleteWebhook';
35
- // `scenes delete <id>` → verb is "deleteScene"
36
- if (tokens[0] === 'scenes' && tokens[1] === 'delete')
37
- return 'deleteScene';
38
- return null;
39
- }
40
- export function isDestructiveCommand(cmd) {
41
- const verb = extractVerb(cmd);
42
- if (!verb)
43
- return false;
44
- return DESTRUCTIVE_COMMANDS.includes(verb);
45
- }
46
- export function destructiveVerbOf(cmd) {
47
- const verb = extractVerb(cmd);
48
- if (verb && DESTRUCTIVE_COMMANDS.includes(verb)) {
49
- return verb;
50
- }
51
- return null;
52
- }
53
- //# sourceMappingURL=destructive.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"destructive.js","sourceRoot":"","sources":["../../src/rules/destructive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,QAAQ;IACR,eAAe;IACf,aAAa;IACb,cAAc;CACN,CAAC;AAIX;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEpC,uCAAuC;IACvC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IACD,mDAAmD;IACnD,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,eAAe,CAAC;IAC/E,+CAA+C;IAC/C,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC;IAC3E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,OAAQ,oBAA0C,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,IAAI,IAAK,oBAA0C,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvE,OAAO,IAA0B,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,193 +0,0 @@
1
- /**
2
- * Rules engine runtime — orchestrates trigger subscription, matcher
3
- * pipeline, throttle gate, and action executor.
4
- *
5
- * v0.2 PoC scope:
6
- * - Loads an `automation` block from a policy file.
7
- * - Subscribes to a single MQTT client; routes every shadow message
8
- * through `matchesMqttTrigger` → `evaluateConditions` → throttle →
9
- * `executeRuleAction`.
10
- * - Cron + webhook triggers are **recognised but not wired** — they
11
- * surface in the static lint as `unsupported` so users know the
12
- * feature is pending (E1/E2 fill it in without a schema change).
13
- * - Exposes `start()`, `stop()`, `getStats()` for the rules run
14
- * subcommand.
15
- *
16
- * Not responsible for: loading the policy file, validating it, talking
17
- * to the SwitchBot REST API (that's `executeCommand`), or writing
18
- * audit lines (that's each module's local responsibility).
19
- */
20
- import type { AxiosInstance } from 'axios';
21
- import type { SwitchBotMqttClient } from '../mqtt/client.js';
22
- import type { MqttCredential } from '../mqtt/credential.js';
23
- import { type DeviceStatusFetcher } from './matcher.js';
24
- import { type AutomationBlock, type EngineEvent, type Rule } from './types.js';
25
- export interface LintIssue {
26
- rule: string;
27
- severity: 'error' | 'warning';
28
- code: string;
29
- message: string;
30
- }
31
- export interface LintResult {
32
- rules: Array<{
33
- name: string;
34
- enabled: boolean;
35
- status: 'ok' | 'error' | 'unsupported' | 'disabled';
36
- issues: LintIssue[];
37
- }>;
38
- valid: boolean;
39
- unsupportedCount: number;
40
- }
41
- export declare function lintRules(automation: AutomationBlock | null | undefined): LintResult;
42
- export interface RulesEngineOptions {
43
- automation: AutomationBlock | null | undefined;
44
- aliases: Record<string, string>;
45
- /** Pre-connected MQTT client — owned by the caller. */
46
- mqttClient: SwitchBotMqttClient;
47
- /** Credential exposed so we know the default shadow topic to subscribe to. */
48
- mqttCredential: MqttCredential;
49
- /** Optional HTTP client for executeCommand — omit in tests. */
50
- httpClient?: AxiosInstance;
51
- /** When true, treat every rule as dry_run regardless of policy. */
52
- globalDryRun?: boolean;
53
- /** Max firings before the engine self-stops — test / demo only. */
54
- maxFirings?: number;
55
- /** Suppress live API calls. Used by tests that don't want to mock axios. */
56
- skipApiCall?: boolean;
57
- /** Side channel for unit tests — drop every processed event here. */
58
- onFire?: (entry: EngineFireEntry) => void;
59
- /**
60
- * Webhook bearer token. Required when any rule uses a webhook
61
- * trigger; the listener will refuse to start otherwise.
62
- */
63
- webhookToken?: string;
64
- /** Webhook listener port (default 18790). Set 0 to auto-allocate. */
65
- webhookPort?: number;
66
- /** Webhook listener host (default 127.0.0.1). */
67
- webhookHost?: string;
68
- /**
69
- * Override how device_state conditions fetch live status. Primarily a
70
- * test seam — production callers should leave it unset so the engine
71
- * goes through the normal `fetchDeviceStatus` path with the shared
72
- * axios client.
73
- */
74
- statusFetcher?: DeviceStatusFetcher;
75
- }
76
- export interface EngineFireEntry {
77
- ruleName: string;
78
- fireId: string;
79
- /** Final disposition of the fire. */
80
- status: 'fired' | 'dry' | 'throttled' | 'conditions-failed' | 'unsupported' | 'blocked';
81
- deviceId?: string;
82
- reason?: string;
83
- }
84
- export interface EngineStats {
85
- started: boolean;
86
- rulesLoaded: number;
87
- rulesActive: number;
88
- eventsProcessed: number;
89
- fires: number;
90
- dryFires: number;
91
- throttled: number;
92
- conditionsFailed: number;
93
- }
94
- export declare class RulesEngine {
95
- private readonly opts;
96
- private rules;
97
- private aliases;
98
- private readonly throttle;
99
- /** hysteresis / requires_stable_for: tracks when each (rule::device) trigger was first seen. */
100
- private hysteresisFirstSeen;
101
- private unsubscribeMessage;
102
- private unsubscribeState;
103
- private cronScheduler;
104
- private webhookListener;
105
- private started;
106
- private stopped;
107
- /**
108
- * Sequential dispatch queue. Two MQTT messages arriving in the same
109
- * tick would otherwise race inside the throttle check — each sees an
110
- * empty lastFireAt map because neither has recorded yet. Serialising
111
- * keeps the semantics of `max_per` honest.
112
- */
113
- private pendingChain;
114
- private stats;
115
- constructor(opts: RulesEngineOptions);
116
- getStats(): EngineStats;
117
- getRules(): readonly Rule[];
118
- /**
119
- * Subscribes to MQTT and begins the pipeline. Throws if the policy
120
- * block is missing `enabled: true` or if lint finds errors (e.g.
121
- * destructive command in a rule action).
122
- */
123
- start(): Promise<void>;
124
- stop(): Promise<void>;
125
- /**
126
- * Hot-reload the running engine with a fresh automation block and
127
- * alias map — typically triggered by SIGHUP or by the `rules reload`
128
- * subcommand writing the reload sentinel file.
129
- *
130
- * Semantics:
131
- * - Rejects (and keeps the old ruleset) when the new automation is
132
- * disabled or fails lint. The engine never silently degrades.
133
- * - Diffs cron registrations by `rule.name` + `schedule`: unchanged
134
- * entries keep their armed timer, changed/removed entries are
135
- * unregistered, new entries are registered and armed.
136
- * - Hands the fresh webhook rule list to the live listener (keeps
137
- * the bound port / open connections). If the reload removes every
138
- * webhook rule the listener is torn down; if it adds the first
139
- * webhook rule we refuse — spinning up a new listener mid-run
140
- * would silently change the security surface.
141
- * - `ThrottleGate` state is retained for surviving rule names and
142
- * dropped for removed ones. A rule that was throttled before the
143
- * reload stays throttled after it (same name = same window), but
144
- * a renamed rule resets.
145
- */
146
- reload(nextAutomation: AutomationBlock | null | undefined, nextAliases?: Record<string, string>): Promise<{
147
- changed: boolean;
148
- errors: string[];
149
- warnings: string[];
150
- }>;
151
- /**
152
- * Expose the MQTT pipeline for direct invocation from tests — feeds a
153
- * synthetic payload through the same matcher/throttle/action chain.
154
- */
155
- ingestMqttForTest(payload: unknown): Promise<void>;
156
- /**
157
- * Dispatch a pre-built EngineEvent through all matching MQTT rules.
158
- * Used by tests that need full control over the event timestamp (e.g.
159
- * hysteresis tests that advance time manually).
160
- */
161
- ingestEventForTest(event: EngineEvent): Promise<void>;
162
- /**
163
- * Fire a cron rule directly without needing the scheduler/timers.
164
- * Used by tests that want to exercise the dispatch pipeline without
165
- * depending on fake timers or croner's internals.
166
- */
167
- ingestCronForTest(rule: Rule, when?: Date): Promise<void>;
168
- /**
169
- * Fire a webhook rule directly without standing up the HTTP listener.
170
- */
171
- ingestWebhookForTest(rule: Rule, body?: string, when?: Date): Promise<void>;
172
- /** Returns the bound webhook port when the listener is active. */
173
- getWebhookPort(): number | null;
174
- /** Read-only peek at cron schedule state — for `rules list` extras. */
175
- getCronSchedule(ruleName: string): {
176
- schedule: string;
177
- nextAt: Date | null;
178
- } | null;
179
- /** Test helper — resolves after all queued dispatches complete. */
180
- drainForTest(): Promise<void>;
181
- /**
182
- * Append a task to the dispatch queue; callers get back a promise that
183
- * resolves when their task finishes (errors are swallowed — we never
184
- * want the queue itself to die because one rule threw). Returning a
185
- * promise lets awaited callsites (ingestMqttForTest) observe completion.
186
- */
187
- private enqueue;
188
- private onMqttMessage;
189
- private onCronFire;
190
- private onWebhookFire;
191
- private firesTotal;
192
- private dispatchRule;
193
- }