@switchbot/openapi-cli 3.1.1 → 3.2.1

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 (333) hide show
  1. package/README.md +3 -3
  2. package/dist/api/client.d.ts +31 -0
  3. package/dist/api/client.js +1 -0
  4. package/dist/api/client.js.map +1 -0
  5. package/dist/auth.d.ts +1 -0
  6. package/dist/auth.js +1 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/commands/agent-bootstrap.d.ts +10 -0
  9. package/dist/commands/agent-bootstrap.js +23 -5
  10. package/dist/commands/agent-bootstrap.js.map +1 -0
  11. package/dist/commands/auth.d.ts +18 -0
  12. package/dist/commands/auth.js +1 -0
  13. package/dist/commands/auth.js.map +1 -0
  14. package/dist/commands/batch.d.ts +2 -0
  15. package/dist/commands/batch.js +1 -0
  16. package/dist/commands/batch.js.map +1 -0
  17. package/dist/commands/cache.d.ts +2 -0
  18. package/dist/commands/cache.js +1 -0
  19. package/dist/commands/cache.js.map +1 -0
  20. package/dist/commands/capabilities.d.ts +31 -0
  21. package/dist/commands/capabilities.js +5 -7
  22. package/dist/commands/capabilities.js.map +1 -0
  23. package/dist/commands/catalog.d.ts +2 -0
  24. package/dist/commands/catalog.js +1 -0
  25. package/dist/commands/catalog.js.map +1 -0
  26. package/dist/commands/completion.d.ts +2 -0
  27. package/dist/commands/completion.js +1 -0
  28. package/dist/commands/completion.js.map +1 -0
  29. package/dist/commands/config.d.ts +21 -0
  30. package/dist/commands/config.js +1 -0
  31. package/dist/commands/config.js.map +1 -0
  32. package/dist/commands/daemon.d.ts +2 -0
  33. package/dist/commands/daemon.js +1 -0
  34. package/dist/commands/daemon.js.map +1 -0
  35. package/dist/commands/device-meta.d.ts +2 -0
  36. package/dist/commands/device-meta.js +1 -0
  37. package/dist/commands/device-meta.js.map +1 -0
  38. package/dist/commands/devices.d.ts +2 -0
  39. package/dist/commands/devices.js +1 -0
  40. package/dist/commands/devices.js.map +1 -0
  41. package/dist/commands/doctor.d.ts +3 -0
  42. package/dist/commands/doctor.js +1 -0
  43. package/dist/commands/doctor.js.map +1 -0
  44. package/dist/commands/events.d.ts +31 -0
  45. package/dist/commands/events.js +1 -0
  46. package/dist/commands/events.js.map +1 -0
  47. package/dist/commands/expand.d.ts +2 -0
  48. package/dist/commands/expand.js +1 -0
  49. package/dist/commands/expand.js.map +1 -0
  50. package/dist/commands/explain.d.ts +2 -0
  51. package/dist/commands/explain.js +1 -0
  52. package/dist/commands/explain.js.map +1 -0
  53. package/dist/commands/health.d.ts +8 -0
  54. package/dist/commands/health.js +1 -0
  55. package/dist/commands/health.js.map +1 -0
  56. package/dist/commands/history.d.ts +2 -0
  57. package/dist/commands/history.js +1 -0
  58. package/dist/commands/history.js.map +1 -0
  59. package/dist/commands/identity.d.ts +45 -0
  60. package/dist/commands/identity.js +1 -0
  61. package/dist/commands/identity.js.map +1 -0
  62. package/dist/commands/install.d.ts +20 -0
  63. package/dist/commands/install.js +1 -0
  64. package/dist/commands/install.js.map +1 -0
  65. package/dist/commands/mcp.d.ts +14 -0
  66. package/dist/commands/mcp.js +1 -0
  67. package/dist/commands/mcp.js.map +1 -0
  68. package/dist/commands/plan.d.ts +51 -0
  69. package/dist/commands/plan.js +1 -0
  70. package/dist/commands/plan.js.map +1 -0
  71. package/dist/commands/policy.d.ts +24 -0
  72. package/dist/commands/policy.js +1 -0
  73. package/dist/commands/policy.js.map +1 -0
  74. package/dist/commands/quota.d.ts +2 -0
  75. package/dist/commands/quota.js +1 -0
  76. package/dist/commands/quota.js.map +1 -0
  77. package/dist/commands/rules.d.ts +2 -0
  78. package/dist/commands/rules.js +1 -0
  79. package/dist/commands/rules.js.map +1 -0
  80. package/dist/commands/scenes.d.ts +2 -0
  81. package/dist/commands/scenes.js +1 -0
  82. package/dist/commands/scenes.js.map +1 -0
  83. package/dist/commands/schema.d.ts +2 -0
  84. package/dist/commands/schema.js +10 -2
  85. package/dist/commands/schema.js.map +1 -0
  86. package/dist/commands/status-sync.d.ts +2 -0
  87. package/dist/commands/status-sync.js +1 -0
  88. package/dist/commands/status-sync.js.map +1 -0
  89. package/dist/commands/uninstall.d.ts +20 -0
  90. package/dist/commands/uninstall.js +1 -0
  91. package/dist/commands/uninstall.js.map +1 -0
  92. package/dist/commands/upgrade-check.d.ts +2 -0
  93. package/dist/commands/upgrade-check.js +3 -3
  94. package/dist/commands/upgrade-check.js.map +1 -0
  95. package/dist/commands/watch.d.ts +2 -0
  96. package/dist/commands/watch.js +1 -0
  97. package/dist/commands/watch.js.map +1 -0
  98. package/dist/commands/webhook.d.ts +2 -0
  99. package/dist/commands/webhook.js +1 -0
  100. package/dist/commands/webhook.js.map +1 -0
  101. package/dist/config.d.ts +57 -0
  102. package/dist/config.js +1 -0
  103. package/dist/config.js.map +1 -0
  104. package/dist/credentials/backends/file.d.ts +18 -0
  105. package/dist/credentials/backends/file.js +1 -0
  106. package/dist/credentials/backends/file.js.map +1 -0
  107. package/dist/credentials/backends/linux.d.ts +16 -0
  108. package/dist/credentials/backends/linux.js +1 -0
  109. package/dist/credentials/backends/linux.js.map +1 -0
  110. package/dist/credentials/backends/macos.d.ts +18 -0
  111. package/dist/credentials/backends/macos.js +1 -0
  112. package/dist/credentials/backends/macos.js.map +1 -0
  113. package/dist/credentials/backends/windows.d.ts +23 -0
  114. package/dist/credentials/backends/windows.js +1 -0
  115. package/dist/credentials/backends/windows.js.map +1 -0
  116. package/dist/credentials/keychain.d.ts +83 -0
  117. package/dist/credentials/keychain.js +1 -0
  118. package/dist/credentials/keychain.js.map +1 -0
  119. package/dist/credentials/prime.d.ts +32 -0
  120. package/dist/credentials/prime.js +1 -0
  121. package/dist/credentials/prime.js.map +1 -0
  122. package/dist/devices/cache.d.ts +79 -0
  123. package/dist/devices/cache.js +1 -0
  124. package/dist/devices/cache.js.map +1 -0
  125. package/dist/devices/catalog.d.ts +138 -0
  126. package/dist/devices/catalog.js +1 -0
  127. package/dist/devices/catalog.js.map +1 -0
  128. package/dist/devices/device-meta.d.ts +15 -0
  129. package/dist/devices/device-meta.js +1 -0
  130. package/dist/devices/device-meta.js.map +1 -0
  131. package/dist/devices/history-agg.d.ts +37 -0
  132. package/dist/devices/history-agg.js +1 -0
  133. package/dist/devices/history-agg.js.map +1 -0
  134. package/dist/devices/history-query.d.ts +45 -0
  135. package/dist/devices/history-query.js +1 -0
  136. package/dist/devices/history-query.js.map +1 -0
  137. package/dist/devices/param-validator.d.ts +40 -0
  138. package/dist/devices/param-validator.js +1 -0
  139. package/dist/devices/param-validator.js.map +1 -0
  140. package/dist/devices/resources.d.ts +74 -0
  141. package/dist/devices/resources.js +1 -0
  142. package/dist/devices/resources.js.map +1 -0
  143. package/dist/index.d.ts +1 -0
  144. package/dist/index.js +1 -1
  145. package/dist/index.js.map +1 -0
  146. package/dist/install/default-steps.d.ts +66 -0
  147. package/dist/install/default-steps.js +1 -0
  148. package/dist/install/default-steps.js.map +1 -0
  149. package/dist/install/preflight.d.ts +60 -0
  150. package/dist/install/preflight.js +1 -0
  151. package/dist/install/preflight.js.map +1 -0
  152. package/dist/install/steps.d.ts +61 -0
  153. package/dist/install/steps.js +1 -0
  154. package/dist/install/steps.js.map +1 -0
  155. package/dist/lib/command-keywords.d.ts +5 -0
  156. package/dist/lib/command-keywords.js +1 -0
  157. package/dist/lib/command-keywords.js.map +1 -0
  158. package/dist/lib/daemon-state.d.ts +24 -0
  159. package/dist/lib/daemon-state.js +1 -0
  160. package/dist/lib/daemon-state.js.map +1 -0
  161. package/dist/lib/destructive-mode.d.ts +2 -0
  162. package/dist/lib/destructive-mode.js +1 -0
  163. package/dist/lib/destructive-mode.js.map +1 -0
  164. package/dist/lib/devices.d.ts +151 -0
  165. package/dist/lib/devices.js +1 -0
  166. package/dist/lib/devices.js.map +1 -0
  167. package/dist/lib/idempotency.d.ts +46 -0
  168. package/dist/lib/idempotency.js +1 -0
  169. package/dist/lib/idempotency.js.map +1 -0
  170. package/dist/lib/plan-store.d.ts +19 -0
  171. package/dist/lib/plan-store.js +1 -0
  172. package/dist/lib/plan-store.js.map +1 -0
  173. package/dist/lib/request-context.d.ts +7 -0
  174. package/dist/lib/request-context.js +1 -0
  175. package/dist/lib/request-context.js.map +1 -0
  176. package/dist/lib/scenes.d.ts +7 -0
  177. package/dist/lib/scenes.js +1 -0
  178. package/dist/lib/scenes.js.map +1 -0
  179. package/dist/logger.d.ts +4 -0
  180. package/dist/logger.js +1 -0
  181. package/dist/logger.js.map +1 -0
  182. package/dist/mcp/device-history.d.ts +36 -0
  183. package/dist/mcp/device-history.js +1 -0
  184. package/dist/mcp/device-history.js.map +1 -0
  185. package/dist/mcp/events-subscription.d.ts +45 -0
  186. package/dist/mcp/events-subscription.js +1 -0
  187. package/dist/mcp/events-subscription.js.map +1 -0
  188. package/dist/mqtt/client.d.ts +25 -0
  189. package/dist/mqtt/client.js +1 -0
  190. package/dist/mqtt/client.js.map +1 -0
  191. package/dist/mqtt/credential.d.ts +16 -0
  192. package/dist/mqtt/credential.js +1 -0
  193. package/dist/mqtt/credential.js.map +1 -0
  194. package/dist/policy/add-rule.d.ts +21 -0
  195. package/dist/policy/add-rule.js +1 -0
  196. package/dist/policy/add-rule.js.map +1 -0
  197. package/dist/policy/diff.d.ts +21 -0
  198. package/dist/policy/diff.js +1 -0
  199. package/dist/policy/diff.js.map +1 -0
  200. package/dist/policy/format.d.ts +6 -0
  201. package/dist/policy/format.js +1 -0
  202. package/dist/policy/format.js.map +1 -0
  203. package/dist/policy/load.d.ts +32 -0
  204. package/dist/policy/load.js +1 -0
  205. package/dist/policy/load.js.map +1 -0
  206. package/dist/policy/migrate.d.ts +21 -0
  207. package/dist/policy/migrate.js +1 -0
  208. package/dist/policy/migrate.js.map +1 -0
  209. package/dist/policy/schema/v0.2.json +1 -1
  210. package/dist/policy/schema.d.ts +5 -0
  211. package/dist/policy/schema.js +1 -0
  212. package/dist/policy/schema.js.map +1 -0
  213. package/dist/policy/validate.d.ts +19 -0
  214. package/dist/policy/validate.js +1 -0
  215. package/dist/policy/validate.js.map +1 -0
  216. package/dist/rules/action.d.ts +65 -0
  217. package/dist/rules/action.js +1 -0
  218. package/dist/rules/action.js.map +1 -0
  219. package/dist/rules/audit-query.d.ts +51 -0
  220. package/dist/rules/audit-query.js +1 -0
  221. package/dist/rules/audit-query.js.map +1 -0
  222. package/dist/rules/conflict-analyzer.d.ts +57 -0
  223. package/dist/rules/conflict-analyzer.js +1 -0
  224. package/dist/rules/conflict-analyzer.js.map +1 -0
  225. package/dist/rules/cron-scheduler.d.ts +62 -0
  226. package/dist/rules/cron-scheduler.js +1 -0
  227. package/dist/rules/cron-scheduler.js.map +1 -0
  228. package/dist/rules/destructive.d.ts +20 -0
  229. package/dist/rules/destructive.js +1 -0
  230. package/dist/rules/destructive.js.map +1 -0
  231. package/dist/rules/engine.d.ts +193 -0
  232. package/dist/rules/engine.js +1 -0
  233. package/dist/rules/engine.js.map +1 -0
  234. package/dist/rules/matcher.d.ts +56 -0
  235. package/dist/rules/matcher.js +1 -0
  236. package/dist/rules/matcher.js.map +1 -0
  237. package/dist/rules/pid-file.d.ts +43 -0
  238. package/dist/rules/pid-file.js +1 -0
  239. package/dist/rules/pid-file.js.map +1 -0
  240. package/dist/rules/quiet-hours.d.ts +26 -0
  241. package/dist/rules/quiet-hours.js +1 -0
  242. package/dist/rules/quiet-hours.js.map +1 -0
  243. package/dist/rules/suggest.d.ts +20 -0
  244. package/dist/rules/suggest.js +1 -0
  245. package/dist/rules/suggest.js.map +1 -0
  246. package/dist/rules/throttle.d.ts +61 -0
  247. package/dist/rules/throttle.js +1 -0
  248. package/dist/rules/throttle.js.map +1 -0
  249. package/dist/rules/types.d.ts +117 -0
  250. package/dist/rules/types.js +1 -0
  251. package/dist/rules/types.js.map +1 -0
  252. package/dist/rules/webhook-listener.d.ts +63 -0
  253. package/dist/rules/webhook-listener.js +1 -0
  254. package/dist/rules/webhook-listener.js.map +1 -0
  255. package/dist/rules/webhook-token.d.ts +50 -0
  256. package/dist/rules/webhook-token.js +1 -0
  257. package/dist/rules/webhook-token.js.map +1 -0
  258. package/dist/schema/field-aliases.d.ts +34 -0
  259. package/dist/schema/field-aliases.js +1 -0
  260. package/dist/schema/field-aliases.js.map +1 -0
  261. package/dist/sinks/dispatcher.d.ts +7 -0
  262. package/dist/sinks/dispatcher.js +1 -0
  263. package/dist/sinks/dispatcher.js.map +1 -0
  264. package/dist/sinks/file.d.ts +6 -0
  265. package/dist/sinks/file.js +1 -0
  266. package/dist/sinks/file.js.map +1 -0
  267. package/dist/sinks/format.d.ts +20 -0
  268. package/dist/sinks/format.js +1 -0
  269. package/dist/sinks/format.js.map +1 -0
  270. package/dist/sinks/homeassistant.d.ts +18 -0
  271. package/dist/sinks/homeassistant.js +1 -0
  272. package/dist/sinks/homeassistant.js.map +1 -0
  273. package/dist/sinks/openclaw.d.ts +13 -0
  274. package/dist/sinks/openclaw.js +1 -0
  275. package/dist/sinks/openclaw.js.map +1 -0
  276. package/dist/sinks/stdout.d.ts +4 -0
  277. package/dist/sinks/stdout.js +1 -0
  278. package/dist/sinks/stdout.js.map +1 -0
  279. package/dist/sinks/telegram.d.ts +11 -0
  280. package/dist/sinks/telegram.js +1 -0
  281. package/dist/sinks/telegram.js.map +1 -0
  282. package/dist/sinks/types.d.ts +13 -0
  283. package/dist/sinks/types.js +1 -0
  284. package/dist/sinks/types.js.map +1 -0
  285. package/dist/sinks/webhook.d.ts +6 -0
  286. package/dist/sinks/webhook.js +1 -0
  287. package/dist/sinks/webhook.js.map +1 -0
  288. package/dist/status-sync/manager.d.ts +48 -0
  289. package/dist/status-sync/manager.js +1 -0
  290. package/dist/status-sync/manager.js.map +1 -0
  291. package/dist/utils/arg-parsers.d.ts +16 -0
  292. package/dist/utils/arg-parsers.js +1 -0
  293. package/dist/utils/arg-parsers.js.map +1 -0
  294. package/dist/utils/audit.d.ts +69 -0
  295. package/dist/utils/audit.js +1 -0
  296. package/dist/utils/audit.js.map +1 -0
  297. package/dist/utils/filter.d.ts +81 -0
  298. package/dist/utils/filter.js +1 -0
  299. package/dist/utils/filter.js.map +1 -0
  300. package/dist/utils/flags.d.ts +72 -0
  301. package/dist/utils/flags.js +1 -0
  302. package/dist/utils/flags.js.map +1 -0
  303. package/dist/utils/format.d.ts +9 -0
  304. package/dist/utils/format.js +1 -0
  305. package/dist/utils/format.js.map +1 -0
  306. package/dist/utils/health.d.ts +48 -0
  307. package/dist/utils/health.js +1 -0
  308. package/dist/utils/health.js.map +1 -0
  309. package/dist/utils/help-json.d.ts +39 -0
  310. package/dist/utils/help-json.js +1 -0
  311. package/dist/utils/help-json.js.map +1 -0
  312. package/dist/utils/name-resolver.d.ts +26 -0
  313. package/dist/utils/name-resolver.js +1 -0
  314. package/dist/utils/name-resolver.js.map +1 -0
  315. package/dist/utils/output.d.ts +73 -0
  316. package/dist/utils/output.js +1 -0
  317. package/dist/utils/output.js.map +1 -0
  318. package/dist/utils/quota.d.ts +61 -0
  319. package/dist/utils/quota.js +1 -0
  320. package/dist/utils/quota.js.map +1 -0
  321. package/dist/utils/redact.d.ts +23 -0
  322. package/dist/utils/redact.js +1 -0
  323. package/dist/utils/redact.js.map +1 -0
  324. package/dist/utils/retry.d.ts +72 -0
  325. package/dist/utils/retry.js +1 -0
  326. package/dist/utils/retry.js.map +1 -0
  327. package/dist/utils/string.d.ts +2 -0
  328. package/dist/utils/string.js +1 -0
  329. package/dist/utils/string.js.map +1 -0
  330. package/dist/version.d.ts +2 -0
  331. package/dist/version.js +1 -0
  332. package/dist/version.js.map +1 -0
  333. package/package.json +4 -3
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Cross-platform supervisor glue for `switchbot rules run`.
3
+ *
4
+ * The running engine registers a pid file and a reload sentinel under
5
+ * `~/.switchbot/`; the `switchbot rules reload` subcommand reads them
6
+ * to signal the live process:
7
+ *
8
+ * - Unix (SIGHUP supported): `process.kill(pid, 'SIGHUP')`.
9
+ * - Windows (no SIGHUP): write `~/.switchbot/rules.reload`. The engine
10
+ * polls this path and consumes it, so the same `rules reload`
11
+ * command works on every platform.
12
+ *
13
+ * The files are tiny (<100 bytes) and created with 0o600; cleanup is
14
+ * best-effort on exit so a crash leaves at most a stale pid the user
15
+ * can overwrite with a fresh `rules run`.
16
+ */
17
+ export interface PidFilePaths {
18
+ dir: string;
19
+ pidFile: string;
20
+ reloadFile: string;
21
+ }
22
+ export declare function getDefaultPidFilePaths(): PidFilePaths;
23
+ /** Write the current process pid. Creates parent dir with 0700 if needed. */
24
+ export declare function writePidFile(pidFile: string, pid?: number): void;
25
+ /** Return the pid persisted in the file, or null if absent / unparseable. */
26
+ export declare function readPidFile(pidFile: string): number | null;
27
+ /**
28
+ * Remove the pid file only when it still refers to the current process.
29
+ * A stale file from an earlier run is left alone so we don't accidentally
30
+ * clobber a new supervisor that already won the race.
31
+ */
32
+ export declare function clearPidFile(pidFile: string, pid?: number): void;
33
+ export declare function writeReloadSentinel(reloadFile: string): void;
34
+ export declare function consumeReloadSentinel(reloadFile: string): boolean;
35
+ /** Detect whether SIGHUP is usable on the current platform. */
36
+ export declare function sighupSupported(): boolean;
37
+ /**
38
+ * Check whether a pid is alive — used by `rules reload` to avoid
39
+ * signalling dead pids, which would otherwise leave the user wondering
40
+ * why nothing happened. Node's `process.kill(pid, 0)` throws `ESRCH`
41
+ * for dead pids and `EPERM` for pids we cannot signal (still alive).
42
+ */
43
+ export declare function isPidAlive(pid: number): boolean;
@@ -93,3 +93,4 @@ export function isPidAlive(pid) {
93
93
  return code === 'EPERM';
94
94
  }
95
95
  }
96
+ //# sourceMappingURL=pid-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pid-file.js","sourceRoot":"","sources":["../../src/rules/pid-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Time-window helpers shared by `time_between` conditions and (later)
3
+ * the top-level `quiet_hours` block. Both evaluate a local-clock HH:MM
4
+ * range that may cross midnight.
5
+ */
6
+ export interface TimeWindow {
7
+ start: string;
8
+ end: string;
9
+ }
10
+ /**
11
+ * `true` when `now` falls inside the window. If `start > end` the window
12
+ * is interpreted as overnight (e.g. 22:00 → 07:00 crosses midnight).
13
+ *
14
+ * Boundary semantics: start is inclusive, end is exclusive. A window of
15
+ * 09:00 → 09:00 therefore matches nothing — callers who want "always"
16
+ * should omit the condition entirely rather than fake it with equal
17
+ * times.
18
+ */
19
+ export declare function isWithin(window: TimeWindow, now: Date): boolean;
20
+ /** Convenience wrapper that accepts the schema's tuple shape. */
21
+ export declare function isWithinTuple(range: [string, string], now: Date): boolean;
22
+ /** Top-level quiet_hours block helper — same math, schema shape differs. */
23
+ export declare function isInQuietHours(qh: {
24
+ start?: string;
25
+ end?: string;
26
+ } | null | undefined, now: Date): boolean;
@@ -43,3 +43,4 @@ export function isInQuietHours(qh, now) {
43
43
  return false;
44
44
  return isWithin({ start: qh.start, end: qh.end }, now);
45
45
  }
46
+ //# sourceMappingURL=quiet-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quiet-hours.js","sourceRoot":"","sources":["../../src/rules/quiet-hours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,IAAI,GAAG,2BAA2B,CAAC;AAOzC,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,GAAG,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,SAAS,CAAC,CAAO;IACxB,OAAO,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;AAC5C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAkB,EAAE,GAAS;IACpD,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,KAAuB,EAAE,GAAS;IAC9D,OAAO,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAC5B,EAAuD,EACvD,GAAS;IAET,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Rule } from './types.js';
2
+ export interface SuggestRuleOptions {
3
+ intent: string;
4
+ trigger?: 'mqtt' | 'cron' | 'webhook';
5
+ devices?: Array<{
6
+ id: string;
7
+ name?: string;
8
+ type?: string;
9
+ }>;
10
+ event?: string;
11
+ schedule?: string;
12
+ days?: string[];
13
+ webhookPath?: string;
14
+ }
15
+ export interface SuggestRuleResult {
16
+ rule: Rule;
17
+ ruleYaml: string;
18
+ warnings: string[];
19
+ }
20
+ export declare function suggestRule(opts: SuggestRuleOptions): SuggestRuleResult;
@@ -93,3 +93,4 @@ export function suggestRule(opts) {
93
93
  const ruleYaml = yamlStringify(rule, { lineWidth: 0 });
94
94
  return { rule, ruleYaml, warnings };
95
95
  }
96
+ //# sourceMappingURL=suggest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest.js","sourceRoot":"","sources":["../../src/rules/suggest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Throttle gate — per-rule, optionally keyed by deviceId.
3
+ *
4
+ * Semantics:
5
+ * - `max_per: "10m"` → a rule may fire at most once every 10 minutes
6
+ * per (rule, deviceId) pair.
7
+ * - `dedupe_window: "5s"` → suppress fires whose key already fired
8
+ * within the window (collapses rapid sensor bursts into one action).
9
+ * - Fires that would violate the window are **suppressed** (not
10
+ * queued) and surface as `{ allowed: false, reason: 'throttled' }`.
11
+ * - When a rule has no `throttle` block, `ThrottleGate.check` returns
12
+ * `{ allowed: true }` immediately.
13
+ *
14
+ * The gate is in-memory only. Re-reads between processes (or after
15
+ * SIGHUP reload) start with a clean slate — a deliberate choice,
16
+ * because persisting throttle state would lock the engine into a
17
+ * schema that changes every time we add a trigger type.
18
+ */
19
+ export declare function parseMaxPerMs(expr: string): number;
20
+ export interface ThrottleCheckResult {
21
+ allowed: boolean;
22
+ /** Timestamp of the last fire that occupies the window, if any. */
23
+ lastFiredAt?: number;
24
+ /** When the window will reopen. */
25
+ nextAllowedAt?: number;
26
+ /** Whether this was blocked by the dedupe_window (vs max_per). */
27
+ dedupedBy?: 'dedupe_window' | 'max_per' | 'cooldown' | 'maxFiringsPerHour';
28
+ }
29
+ export interface MaxFiringsCheckResult {
30
+ allowed: boolean;
31
+ count: number;
32
+ max: number;
33
+ }
34
+ export declare class ThrottleGate {
35
+ private lastFireAt;
36
+ /** Sliding-window fire-time log for count-based maxFiringsPerHour. */
37
+ private fireTimes;
38
+ private keyOf;
39
+ /**
40
+ * Does **not** record the fire. Call `record()` after the action
41
+ * actually runs so that dry-run / throttled paths don't bump the
42
+ * window.
43
+ */
44
+ check(ruleName: string, windowMs: number | null, now: number, deviceId?: string, dedupeWindowMs?: number | null): ThrottleCheckResult;
45
+ record(ruleName: string, now: number, deviceId?: string): void;
46
+ /** Count-based check: has the rule fired >= maxCount times in the last windowMs? */
47
+ checkMaxFirings(ruleName: string, maxCount: number, windowMs: number, now: number, deviceId?: string): MaxFiringsCheckResult;
48
+ /** Record a count-based fire (call alongside record()). */
49
+ recordFire(ruleName: string, now: number, deviceId?: string): void;
50
+ /** Drop everything — used by engine.reload when a rule is removed. */
51
+ forget(ruleName: string): void;
52
+ /**
53
+ * Drop every window whose rule name isn't in the given set — used by
54
+ * `engine.reload` after a policy swap. Entries for names that survive
55
+ * the reload are preserved so unchanged rules don't get a free
56
+ * one-fire amnesty.
57
+ */
58
+ retainOnly(ruleNames: Set<string>): void;
59
+ /** Test helper — exposes the underlying size. */
60
+ size(): number;
61
+ }
@@ -114,3 +114,4 @@ export class ThrottleGate {
114
114
  return this.lastFireAt.size;
115
115
  }
116
116
  }
117
+ //# sourceMappingURL=throttle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/rules/throttle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Runtime TypeScript shapes for policy v0.2 rule objects.
3
+ *
4
+ * These are hand-mirrored from `src/policy/schema/v0.2.json` — the ajv
5
+ * validator is the source of truth for what a file may contain, this
6
+ * file is the source of truth for what the engine expects after load.
7
+ * When you edit one, edit the other in the same commit.
8
+ */
9
+ import type { DestructiveCommand } from './destructive.js';
10
+ export type TriggerSource = 'mqtt' | 'cron' | 'webhook';
11
+ export interface MqttTrigger {
12
+ source: 'mqtt';
13
+ /**
14
+ * Event name matched against the engine's event classifier. Known
15
+ * values today: `device.shadow` (catch-all), `motion.detected`,
16
+ * `motion.cleared`, `contact.opened`, `contact.closed`.
17
+ */
18
+ event: string;
19
+ /** Optional filter by deviceId or alias. */
20
+ device?: string;
21
+ }
22
+ export type DayOfWeek = 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';
23
+ export interface CronTrigger {
24
+ source: 'cron';
25
+ /** Standard 5-field cron (minute hour dom month dow), local tz. */
26
+ schedule: string;
27
+ /**
28
+ * Optional weekday filter applied AFTER the cron expression fires.
29
+ * When omitted, every firing passes. Values are matched
30
+ * case-insensitively against the local weekday name.
31
+ */
32
+ days?: DayOfWeek[];
33
+ }
34
+ export interface WebhookTrigger {
35
+ source: 'webhook';
36
+ /** Local HTTP path the rule engine listens on, e.g. `/kitchen/motion`. */
37
+ path: string;
38
+ }
39
+ export type Trigger = MqttTrigger | CronTrigger | WebhookTrigger;
40
+ export interface TimeBetweenCondition {
41
+ time_between: [string, string];
42
+ }
43
+ export interface DeviceStateCondition {
44
+ device: string;
45
+ field: string;
46
+ op: '==' | '!=' | '<' | '>' | '<=' | '>=';
47
+ value: unknown;
48
+ }
49
+ export interface AllCondition {
50
+ all: Condition[];
51
+ }
52
+ export interface AnyCondition {
53
+ any: Condition[];
54
+ }
55
+ export interface NotCondition {
56
+ not: Condition;
57
+ }
58
+ export type Condition = TimeBetweenCondition | DeviceStateCondition | AllCondition | AnyCondition | NotCondition;
59
+ export interface Action {
60
+ command: string;
61
+ device?: string;
62
+ args?: Record<string, unknown> | null;
63
+ on_error?: 'continue' | 'stop';
64
+ }
65
+ export interface Throttle {
66
+ max_per: string;
67
+ /** Deduplicate identical events arriving within this window after the last fire. */
68
+ dedupe_window?: string;
69
+ }
70
+ export interface Rule {
71
+ name: string;
72
+ enabled?: boolean;
73
+ when: Trigger;
74
+ conditions?: Condition[] | null;
75
+ then: Action[];
76
+ throttle?: Throttle | null;
77
+ dry_run?: boolean;
78
+ /** Shorthand cooldown — equivalent to throttle.max_per. Takes precedence when both are set. */
79
+ cooldown?: string;
80
+ /** Hysteresis guard — device state must remain stable for this duration before the rule fires. */
81
+ requires_stable_for?: string;
82
+ /** Alias for requires_stable_for with clearer semantics (takes precedence when both are set). */
83
+ hysteresis?: string;
84
+ /** Maximum times this rule may fire per rolling hour (count-based rate limit). */
85
+ maxFiringsPerHour?: number;
86
+ /** Skip the action if the device's last-known cached state already matches the desired command outcome. */
87
+ suppressIfAlreadyDesired?: boolean;
88
+ }
89
+ export interface AutomationBlock {
90
+ enabled?: boolean;
91
+ rules?: Rule[] | null;
92
+ }
93
+ /**
94
+ * Engine event — unified shape the matcher consumes regardless of
95
+ * trigger source.
96
+ */
97
+ export interface EngineEvent {
98
+ source: TriggerSource;
99
+ /** Classifier output for MQTT; schedule string for cron; path for webhook. */
100
+ event: string;
101
+ t: Date;
102
+ /** Resolved deviceId if the trigger carried one (MQTT). */
103
+ deviceId?: string;
104
+ /** Raw trigger payload for inspection / audit. */
105
+ payload?: unknown;
106
+ }
107
+ /** Guards used outside this file. */
108
+ export declare function isMqttTrigger(t: Trigger): t is MqttTrigger;
109
+ export declare function isCronTrigger(t: Trigger): t is CronTrigger;
110
+ export declare function isWebhookTrigger(t: Trigger): t is WebhookTrigger;
111
+ export declare function isTimeBetween(c: Condition): c is TimeBetweenCondition;
112
+ export declare function isDeviceState(c: Condition): c is DeviceStateCondition;
113
+ export declare function isAllCondition(c: Condition): c is AllCondition;
114
+ export declare function isAnyCondition(c: Condition): c is AnyCondition;
115
+ export declare function isNotCondition(c: Condition): c is NotCondition;
116
+ /** Re-export for consumers that want the single list without a second import. */
117
+ export type { DestructiveCommand };
@@ -32,3 +32,4 @@ export function isAnyCondition(c) {
32
32
  export function isNotCondition(c) {
33
33
  return c.not !== undefined && !Array.isArray(c.not);
34
34
  }
35
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuHH,qCAAqC;AACrC,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;AAC7B,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;AAC7B,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACzC,OAAO,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;AAChC,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,CAAY;IACxC,OAAO,KAAK,CAAC,OAAO,CAAE,CAA0B,CAAC,YAAY,CAAC,CAAC;AACjE,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,CAAY;IACxC,MAAM,CAAC,GAAG,CAAyB,CAAC;IACpC,OAAO,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC;AACjG,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,CAAY;IACzC,OAAO,KAAK,CAAC,OAAO,CAAE,CAAkB,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,CAAY;IACzC,OAAO,KAAK,CAAC,OAAO,CAAE,CAAkB,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,CAAY;IACzC,OAAQ,CAAkB,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,CAAkB,CAAC,GAAG,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Local HTTP listener that delivers webhook events to the rules engine.
3
+ *
4
+ * Scope (E2):
5
+ * - Binds to `127.0.0.1` only — the loopback interface keeps the
6
+ * listener off the network by default. The plan's integration story
7
+ * is that an agent or local script POSTs to this endpoint.
8
+ * - Default port is 18790 (phase-3 design doc choice); override with
9
+ * `--webhook-port <n>` in `switchbot rules run`. `--webhook-port 0`
10
+ * asks the OS for an ephemeral port — useful in tests.
11
+ * - Bearer-token auth on every request: `Authorization: Bearer <t>`.
12
+ * The expected token comes from `WebhookTokenStore`; unauthorized
13
+ * requests get a 401 with no body, no hint about which header
14
+ * failed, and an audit entry (`rule-webhook-rejected`).
15
+ * - Matches request path against registered webhook rules: only
16
+ * `POST /path/exactly/as/declared`. Unknown paths return 404.
17
+ *
18
+ * Non-goals:
19
+ * - No TLS; operators who expose this outside loopback are expected
20
+ * to sit behind a reverse proxy that terminates TLS.
21
+ * - No payload parsing beyond reading the body as a string — the
22
+ * engine passes the raw body through in the event payload.
23
+ */
24
+ import type { EngineEvent, Rule } from './types.js';
25
+ export declare const DEFAULT_WEBHOOK_PORT = 18790;
26
+ export interface WebhookDispatch {
27
+ (rule: Rule, event: EngineEvent): Promise<void>;
28
+ }
29
+ export interface WebhookListenerOptions {
30
+ rules: Rule[];
31
+ /** Bearer token used to authorize incoming requests. */
32
+ bearerToken: string;
33
+ /**
34
+ * Host interface to bind. Defaults to 127.0.0.1; tests can set this
35
+ * to '127.0.0.1' + port 0 for ephemeral allocation.
36
+ */
37
+ host?: string;
38
+ port?: number;
39
+ dispatch: WebhookDispatch;
40
+ /** Optional clock — tests inject a deterministic value. */
41
+ now?: () => Date;
42
+ }
43
+ export declare class WebhookListener {
44
+ private readonly opts;
45
+ private server;
46
+ private readonly pathIndex;
47
+ private actualPort;
48
+ constructor(opts: WebhookListenerOptions);
49
+ /** Start listening. Resolves once the server has bound a port. */
50
+ start(): Promise<void>;
51
+ stop(): Promise<void>;
52
+ getPort(): number | null;
53
+ listPaths(): string[];
54
+ /**
55
+ * Replace the current rule → path index. Used by `engine.reload`: the
56
+ * listener keeps its open port and accepted connections, but routes
57
+ * subsequent requests against the fresh policy.
58
+ */
59
+ updateRules(rules: Rule[]): void;
60
+ private handle;
61
+ private isAuthorized;
62
+ private now;
63
+ }
@@ -221,3 +221,4 @@ function readLimitedBody(req, max) {
221
221
  req.on('error', reject);
222
222
  });
223
223
  }
224
+ //# sourceMappingURL=webhook-listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-listener.js","sourceRoot":"","sources":["../../src/rules/webhook-listener.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Webhook bearer-token management for the rules engine.
3
+ *
4
+ * Responsibilities:
5
+ * - Resolve the bearer token the listener will accept. The order is
6
+ * env var (SWITCHBOT_WEBHOOK_TOKEN) → on-disk cache
7
+ * (~/.switchbot/webhook-token, chmod 0600) → generate a fresh
8
+ * 32-byte hex token and persist it.
9
+ * - Rotate the token on demand (`rules webhook-rotate-token` cli).
10
+ *
11
+ * Why not the OS keychain (F1 abstraction)? The webhook bearer is a
12
+ * single opaque string, whereas `CredentialStore` is shaped around the
13
+ * SwitchBot {token,secret} bundle. Fitting a one-field artifact into
14
+ * that contract bloats every profile; keeping it in a 0600 file gives
15
+ * the same protection the CLI has used for `~/.switchbot/config.json`.
16
+ * Promotion into the keychain is a future follow-up once the
17
+ * abstraction grows a generic single-value slot.
18
+ */
19
+ export interface WebhookTokenStoreOptions {
20
+ /** Override the resolved token path — tests use a tmpdir. */
21
+ filePath?: string;
22
+ /**
23
+ * Override the environment lookup. When set to `false` the env var is
24
+ * not consulted; useful for tests that want the file path exercised
25
+ * even though a token is set in the shell.
26
+ */
27
+ envLookup?: () => string | undefined;
28
+ }
29
+ export declare class WebhookTokenStore {
30
+ private readonly filePath;
31
+ private readonly envLookup;
32
+ constructor(opts?: WebhookTokenStoreOptions);
33
+ /**
34
+ * Return a bearer token, creating + persisting one if none exists yet.
35
+ * Env var wins when set; otherwise the on-disk token is read (and
36
+ * generated on first call).
37
+ */
38
+ getOrCreate(): string;
39
+ /**
40
+ * Read the persisted token, returning null when the file is absent
41
+ * or empty. Does NOT consult the env var — callers that want the
42
+ * env-aware path should use `getOrCreate()`.
43
+ */
44
+ readFromDisk(): string | null;
45
+ /** Write a new token, persisting with 0600 perms. */
46
+ rotate(): string;
47
+ getFilePath(): string;
48
+ private writeToDisk;
49
+ }
50
+ export declare function generateToken(): string;
@@ -88,3 +88,4 @@ export class WebhookTokenStore {
88
88
  export function generateToken() {
89
89
  return randomBytes(32).toString('hex');
90
90
  }
91
+ //# sourceMappingURL=webhook-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-token.js","sourceRoot":"","sources":["../../src/rules/webhook-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,SAAS,GAAG,yBAAyB,CAAC;AAC5C,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAahD,MAAM,OAAO,iBAAiB;IACX,QAAQ,CAAS;IACjB,SAAS,CAA2B;IAErD,YAAY,OAAiC,EAAE;QAC7C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;QACvE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;QAEhE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAE9B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,YAAY;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3D,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAClE,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,MAAM;QACJ,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,WAAW,CAAC,KAAa;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,oEAAoE;QACpE,gEAAgE;QAChE,wCAAwC;QACxC,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * User-facing aliases for canonical field names.
3
+ *
4
+ * Keys are canonical names (matching API response keys and CLI/schema output);
5
+ * values are lowercase alternatives a user may type for `--fields` or `--filter`.
6
+ *
7
+ * Conflict rules (do not add an alias that violates these — tests will fail):
8
+ * - `temp` is exclusive to `temperature` (NOT `colorTemperature`, `targetTemperature`).
9
+ * - `motion` is exclusive to `moveDetected`; `moving` uses `active` instead.
10
+ * - `mode` is exclusive to top-level `mode` (preset); device-specific modes go through `deviceMode`.
11
+ * - Reserved / too-generic words never appear as aliases: `auto`, `status`, `state`,
12
+ * `switch`, `type`, `on`, `off`.
13
+ * - Device-type words are never aliases: `lock`, `fan`.
14
+ */
15
+ export declare const FIELD_ALIASES: Record<string, readonly string[]>;
16
+ /**
17
+ * Resolve a user-typed field name to its canonical form against an allowed list.
18
+ *
19
+ * Matching is case-insensitive and trims surrounding whitespace. Direct matches
20
+ * win over alias matches. Throws UsageError if the input is empty or does not
21
+ * match any canonical / alias in the allowed list.
22
+ */
23
+ export declare function resolveField(input: string, allowedCanonical: readonly string[]): string;
24
+ /**
25
+ * Resolve every field in a list. Preserves order and the original UsageError
26
+ * from resolveField() on the first unknown input.
27
+ */
28
+ export declare function resolveFieldList(inputs: readonly string[], allowedCanonical: readonly string[]): string[];
29
+ export declare function listSupportedFieldInputs(allowedCanonical: readonly string[]): string[];
30
+ /**
31
+ * All canonical keys known to the alias registry. Use when no dynamic
32
+ * canonical list is available (e.g. `watch` before the first poll response).
33
+ */
34
+ export declare function listAllCanonical(): string[];
@@ -129,3 +129,4 @@ export function listSupportedFieldInputs(allowedCanonical) {
129
129
  export function listAllCanonical() {
130
130
  return Object.keys(FIELD_ALIASES);
131
131
  }
132
+ //# sourceMappingURL=field-aliases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-aliases.js","sourceRoot":"","sources":["../../src/schema/field-aliases.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Sink, MqttSinkEvent } from './types.js';
2
+ export declare class SinkDispatcher {
3
+ private sinks;
4
+ constructor(sinks: Sink[]);
5
+ dispatch(event: MqttSinkEvent): Promise<void>;
6
+ close(): Promise<void>;
7
+ }
@@ -10,3 +10,4 @@ export class SinkDispatcher {
10
10
  await Promise.allSettled(this.sinks.map((s) => s.close?.()));
11
11
  }
12
12
  }
13
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/sinks/dispatcher.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,cAAc;IACjB,KAAK,CAAS;IAEtB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QACjC,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { Sink, MqttSinkEvent } from './types.js';
2
+ export declare class FileSink implements Sink {
3
+ private filePath;
4
+ constructor(filePath: string);
5
+ write(event: MqttSinkEvent): Promise<void>;
6
+ }
@@ -17,3 +17,4 @@ export class FileSink {
17
17
  }
18
18
  }
19
19
  }
20
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/sinks/file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,OAAO,QAAQ;IACX,QAAQ,CAAS;IAEzB,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAoB;QAC9B,IAAI,CAAC;YACH,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACxF,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ export interface DeviceContext {
2
+ deviceMac?: string;
3
+ deviceType?: string;
4
+ temperature?: number;
5
+ humidity?: number;
6
+ power?: string;
7
+ battery?: number;
8
+ brightness?: string;
9
+ detectionState?: string;
10
+ openState?: string;
11
+ lockState?: string;
12
+ lightLevel?: number;
13
+ [key: string]: unknown;
14
+ }
15
+ export declare function formatEventText(context: DeviceContext): string;
16
+ export declare function parseSinkEvent(payload: unknown): {
17
+ deviceId: string;
18
+ deviceType: string;
19
+ text: string;
20
+ };
@@ -54,3 +54,4 @@ export function parseSinkEvent(payload) {
54
54
  text: formatEventText(context),
55
55
  };
56
56
  }
57
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/sinks/format.ts"],"names":[],"mappings":"AAeA,MAAM,KAAK,GAA2B;IACpC,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;IAClB,gBAAgB,EAAE,IAAI;IACtB,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IACtB,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,IAAI;IACnB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,IAAI;IACf,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF,SAAS,IAAI,CAAC,UAAkB;IAC9B,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC;IAC7C,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,GAAG,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IAExD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;IACnE,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;IAC3E,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;IAC3E,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC;IACrF,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;IAE7E,OAAO,GAAG,GAAG,gBAAgB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAK7C,MAAM,CAAC,GAAG,OAAqD,CAAC;IAChE,MAAM,OAAO,GAAI,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE,CAAmB,CAAC;IACtD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC;QAChD,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC;QACnD,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Sink, MqttSinkEvent } from './types.js';
2
+ export interface HomeAssistantSinkOptions {
3
+ url: string;
4
+ /** Long-lived access token — used when webhookId is not set */
5
+ token?: string;
6
+ /** Webhook ID — no auth required, takes priority over token */
7
+ webhookId?: string;
8
+ /** Event type for REST event API (default: switchbot_event) */
9
+ eventType?: string;
10
+ }
11
+ export declare class HomeAssistantSink implements Sink {
12
+ private url;
13
+ private token?;
14
+ private webhookId?;
15
+ private eventType;
16
+ constructor(opts: HomeAssistantSinkOptions);
17
+ write(event: MqttSinkEvent): Promise<void>;
18
+ }