@switchbot/openapi-cli 1.1.0 → 1.3.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 (105) hide show
  1. package/README.md +174 -18
  2. package/dist/api/client.d.ts +7 -1
  3. package/dist/api/client.js +44 -8
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/commands/batch.d.ts +2 -0
  6. package/dist/commands/batch.js +252 -0
  7. package/dist/commands/batch.js.map +1 -0
  8. package/dist/commands/cache.d.ts +2 -0
  9. package/dist/commands/cache.js +108 -0
  10. package/dist/commands/cache.js.map +1 -0
  11. package/dist/commands/capabilities.d.ts +2 -0
  12. package/dist/commands/capabilities.js +91 -0
  13. package/dist/commands/capabilities.js.map +1 -0
  14. package/dist/commands/catalog.d.ts +2 -0
  15. package/dist/commands/catalog.js +291 -0
  16. package/dist/commands/catalog.js.map +1 -0
  17. package/dist/commands/config.js +123 -10
  18. package/dist/commands/config.js.map +1 -1
  19. package/dist/commands/device-meta.d.ts +2 -0
  20. package/dist/commands/device-meta.js +142 -0
  21. package/dist/commands/device-meta.js.map +1 -0
  22. package/dist/commands/devices.js +272 -152
  23. package/dist/commands/devices.js.map +1 -1
  24. package/dist/commands/doctor.d.ts +2 -0
  25. package/dist/commands/doctor.js +147 -0
  26. package/dist/commands/doctor.js.map +1 -0
  27. package/dist/commands/events.d.ts +15 -0
  28. package/dist/commands/events.js +188 -0
  29. package/dist/commands/events.js.map +1 -0
  30. package/dist/commands/expand.d.ts +2 -0
  31. package/dist/commands/expand.js +192 -0
  32. package/dist/commands/expand.js.map +1 -0
  33. package/dist/commands/explain.d.ts +2 -0
  34. package/dist/commands/explain.js +137 -0
  35. package/dist/commands/explain.js.map +1 -0
  36. package/dist/commands/history.d.ts +2 -0
  37. package/dist/commands/history.js +104 -0
  38. package/dist/commands/history.js.map +1 -0
  39. package/dist/commands/mcp.d.ts +4 -0
  40. package/dist/commands/mcp.js +386 -0
  41. package/dist/commands/mcp.js.map +1 -0
  42. package/dist/commands/plan.d.ts +38 -0
  43. package/dist/commands/plan.js +356 -0
  44. package/dist/commands/plan.js.map +1 -0
  45. package/dist/commands/quota.d.ts +2 -0
  46. package/dist/commands/quota.js +77 -0
  47. package/dist/commands/quota.js.map +1 -0
  48. package/dist/commands/scenes.js +19 -13
  49. package/dist/commands/scenes.js.map +1 -1
  50. package/dist/commands/schema.d.ts +2 -0
  51. package/dist/commands/schema.js +77 -0
  52. package/dist/commands/schema.js.map +1 -0
  53. package/dist/commands/watch.d.ts +2 -0
  54. package/dist/commands/watch.js +161 -0
  55. package/dist/commands/watch.js.map +1 -0
  56. package/dist/commands/webhook.js +37 -22
  57. package/dist/commands/webhook.js.map +1 -1
  58. package/dist/config.d.ts +11 -0
  59. package/dist/config.js +32 -6
  60. package/dist/config.js.map +1 -1
  61. package/dist/devices/cache.d.ts +50 -0
  62. package/dist/devices/cache.js +152 -1
  63. package/dist/devices/cache.js.map +1 -1
  64. package/dist/devices/catalog.d.ts +49 -0
  65. package/dist/devices/catalog.js +362 -92
  66. package/dist/devices/catalog.js.map +1 -1
  67. package/dist/devices/device-meta.d.ts +15 -0
  68. package/dist/devices/device-meta.js +52 -0
  69. package/dist/devices/device-meta.js.map +1 -0
  70. package/dist/index.js +31 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/lib/devices.d.ts +144 -0
  73. package/dist/lib/devices.js +329 -0
  74. package/dist/lib/devices.js.map +1 -0
  75. package/dist/lib/scenes.d.ts +7 -0
  76. package/dist/lib/scenes.js +11 -0
  77. package/dist/lib/scenes.js.map +1 -0
  78. package/dist/utils/audit.d.ts +13 -0
  79. package/dist/utils/audit.js +43 -0
  80. package/dist/utils/audit.js.map +1 -0
  81. package/dist/utils/filter.d.ts +45 -0
  82. package/dist/utils/filter.js +96 -0
  83. package/dist/utils/filter.js.map +1 -0
  84. package/dist/utils/flags.d.ts +42 -0
  85. package/dist/utils/flags.js +108 -0
  86. package/dist/utils/flags.js.map +1 -1
  87. package/dist/utils/format.d.ts +9 -0
  88. package/dist/utils/format.js +109 -0
  89. package/dist/utils/format.js.map +1 -0
  90. package/dist/utils/name-resolver.d.ts +17 -0
  91. package/dist/utils/name-resolver.js +78 -0
  92. package/dist/utils/name-resolver.js.map +1 -0
  93. package/dist/utils/output.d.ts +18 -0
  94. package/dist/utils/output.js +66 -6
  95. package/dist/utils/output.js.map +1 -1
  96. package/dist/utils/quota.d.ts +48 -0
  97. package/dist/utils/quota.js +144 -0
  98. package/dist/utils/quota.js.map +1 -0
  99. package/dist/utils/retry.d.ts +23 -0
  100. package/dist/utils/retry.js +60 -0
  101. package/dist/utils/retry.js.map +1 -0
  102. package/dist/utils/string.d.ts +2 -0
  103. package/dist/utils/string.js +23 -0
  104. package/dist/utils/string.js.map +1 -0
  105. package/package.json +4 -1
@@ -0,0 +1,329 @@
1
+ import { createClient } from '../api/client.js';
2
+ import { findCatalogEntry, suggestedActions, getEffectiveCatalog, } from '../devices/catalog.js';
3
+ import { getCachedDevice, updateCacheFromDeviceList, loadCache, isListCacheFresh, getCachedStatus, setCachedStatus, } from '../devices/cache.js';
4
+ import { getCacheMode } from '../utils/flags.js';
5
+ import { writeAudit } from '../utils/audit.js';
6
+ import { isDryRun } from '../utils/flags.js';
7
+ export class DeviceNotFoundError extends Error {
8
+ deviceId;
9
+ constructor(deviceId) {
10
+ super(`No device with id "${deviceId}" found on this account.`);
11
+ this.deviceId = deviceId;
12
+ this.name = 'DeviceNotFoundError';
13
+ }
14
+ }
15
+ export class CommandValidationError extends Error {
16
+ kind;
17
+ hint;
18
+ constructor(message, kind, hint) {
19
+ super(message);
20
+ this.kind = kind;
21
+ this.hint = hint;
22
+ this.name = 'CommandValidationError';
23
+ }
24
+ }
25
+ /** Fetch the full device + IR remote inventory and refresh the local cache. */
26
+ export async function fetchDeviceList(client) {
27
+ // TTL-gated read: when the on-disk cache is younger than the configured
28
+ // list TTL, skip the API call and synthesize a DeviceListBody from the
29
+ // metadata cache.
30
+ const mode = getCacheMode();
31
+ if (mode.listTtlMs > 0 && isListCacheFresh(mode.listTtlMs)) {
32
+ const cached = loadCache();
33
+ if (cached) {
34
+ const deviceList = [];
35
+ const infraredRemoteList = [];
36
+ for (const [deviceId, entry] of Object.entries(cached.devices)) {
37
+ if (entry.category === 'physical') {
38
+ deviceList.push({
39
+ deviceId,
40
+ deviceName: entry.name,
41
+ deviceType: entry.type,
42
+ enableCloudService: entry.enableCloudService ?? true,
43
+ hubDeviceId: entry.hubDeviceId ?? '',
44
+ roomID: entry.roomID,
45
+ roomName: entry.roomName,
46
+ familyName: entry.familyName,
47
+ controlType: entry.controlType,
48
+ });
49
+ }
50
+ else {
51
+ infraredRemoteList.push({
52
+ deviceId,
53
+ deviceName: entry.name,
54
+ remoteType: entry.type,
55
+ hubDeviceId: entry.hubDeviceId ?? '',
56
+ controlType: entry.controlType,
57
+ });
58
+ }
59
+ }
60
+ return { deviceList, infraredRemoteList };
61
+ }
62
+ }
63
+ const c = client ?? createClient();
64
+ const res = await c.get('/v1.1/devices');
65
+ updateCacheFromDeviceList(res.data.body);
66
+ return res.data.body;
67
+ }
68
+ /** Fetch live status for a single physical device. IR remotes have no status channel. */
69
+ export async function fetchDeviceStatus(deviceId, client) {
70
+ const mode = getCacheMode();
71
+ if (mode.statusTtlMs > 0) {
72
+ const cached = getCachedStatus(deviceId, mode.statusTtlMs);
73
+ if (cached)
74
+ return cached;
75
+ }
76
+ const c = client ?? createClient();
77
+ const res = await c.get(`/v1.1/devices/${deviceId}/status`);
78
+ if (mode.statusTtlMs > 0) {
79
+ setCachedStatus(deviceId, res.data.body);
80
+ }
81
+ return res.data.body;
82
+ }
83
+ /**
84
+ * Execute a command on a device. `parameter` is the fully-parsed value already
85
+ * (JSON-object when applicable), not a raw CLI string — callers should parse
86
+ * upstream if needed.
87
+ */
88
+ export async function executeCommand(deviceId, cmd, parameter, commandType, client) {
89
+ const c = client ?? createClient();
90
+ const body = {
91
+ command: cmd,
92
+ parameter: parameter ?? 'default',
93
+ commandType,
94
+ };
95
+ const baseAudit = {
96
+ t: new Date().toISOString(),
97
+ kind: 'command',
98
+ deviceId,
99
+ command: cmd,
100
+ parameter,
101
+ commandType,
102
+ dryRun: isDryRun(),
103
+ };
104
+ try {
105
+ const res = await c.post(`/v1.1/devices/${deviceId}/commands`, body);
106
+ writeAudit({ ...baseAudit, result: 'ok' });
107
+ return res.data.body;
108
+ }
109
+ catch (err) {
110
+ // Dry-run intercepts throw DryRunSignal — still log the intent.
111
+ if (err instanceof Error && err.name === 'DryRunSignal') {
112
+ writeAudit({ ...baseAudit, result: 'ok' });
113
+ }
114
+ else {
115
+ writeAudit({
116
+ ...baseAudit,
117
+ result: 'error',
118
+ error: err instanceof Error ? err.message : String(err),
119
+ });
120
+ }
121
+ throw err;
122
+ }
123
+ }
124
+ /**
125
+ * Validate a command against the locally-cached device → catalog mapping.
126
+ * Returns `{ ok: true }` when validation passes or is skipped (unknown device,
127
+ * custom IR button, etc.); returns `{ ok: false, error }` when the caller
128
+ * should refuse the call.
129
+ */
130
+ export function validateCommand(deviceId, cmd, parameter, commandType) {
131
+ if (commandType === 'customize')
132
+ return { ok: true };
133
+ const cached = getCachedDevice(deviceId);
134
+ if (!cached)
135
+ return { ok: true };
136
+ const match = findCatalogEntry(cached.type);
137
+ if (!match || Array.isArray(match))
138
+ return { ok: true };
139
+ const builtinCommands = match.commands.filter((c) => c.commandType !== 'customize');
140
+ if (builtinCommands.length === 0)
141
+ return { ok: true };
142
+ const spec = builtinCommands.find((c) => c.command === cmd);
143
+ if (!spec) {
144
+ const unique = [...new Set(builtinCommands.map((c) => c.command))];
145
+ return {
146
+ ok: false,
147
+ error: new CommandValidationError(`"${cmd}" is not a supported command for ${cached.name} (${cached.type}).`, 'unknown-command', `Supported commands: ${unique.join(', ')}`),
148
+ };
149
+ }
150
+ const noParamExpected = spec.parameter === '—';
151
+ const userProvidedParam = parameter !== undefined && parameter !== 'default';
152
+ if (noParamExpected && userProvidedParam) {
153
+ return {
154
+ ok: false,
155
+ error: new CommandValidationError(`"${cmd}" takes no parameter, but one was provided: "${parameter}".`, 'unexpected-parameter', `Try: switchbot devices command ${deviceId} ${cmd}`),
156
+ };
157
+ }
158
+ return { ok: true };
159
+ }
160
+ /**
161
+ * Inspect catalog annotations to decide whether a command is destructive,
162
+ * i.e. has hard-to-reverse real-world effects and should require an explicit
163
+ * confirmation from an agent / operator before execution. Customize commands
164
+ * are considered non-destructive here — they're user-defined IR buttons
165
+ * whose behavior the catalog can't know about.
166
+ */
167
+ export function isDestructiveCommand(deviceType, cmd, commandType) {
168
+ if (commandType === 'customize')
169
+ return false;
170
+ if (!deviceType)
171
+ return false;
172
+ const match = findCatalogEntry(deviceType);
173
+ if (!match || Array.isArray(match))
174
+ return false;
175
+ const spec = match.commands.find((c) => c.command === cmd);
176
+ return Boolean(spec?.destructive);
177
+ }
178
+ /** Return the destructiveReason for a command, or null if not destructive / not found. */
179
+ export function getDestructiveReason(deviceType, cmd, commandType) {
180
+ if (commandType === 'customize')
181
+ return null;
182
+ if (!deviceType)
183
+ return null;
184
+ const match = findCatalogEntry(deviceType);
185
+ if (!match || Array.isArray(match))
186
+ return null;
187
+ const spec = match.commands.find((c) => c.command === cmd);
188
+ return spec?.destructiveReason ?? null;
189
+ }
190
+ /**
191
+ * Describe a device by id: metadata + catalog entry (if known) +
192
+ * optional live status. Throws `DeviceNotFoundError` when the id is unknown.
193
+ */
194
+ export async function describeDevice(deviceId, options = {}, client) {
195
+ const body = await fetchDeviceList(client);
196
+ const { deviceList, infraredRemoteList } = body;
197
+ const physical = deviceList.find((d) => d.deviceId === deviceId);
198
+ const ir = infraredRemoteList.find((d) => d.deviceId === deviceId);
199
+ if (!physical && !ir)
200
+ throw new DeviceNotFoundError(deviceId);
201
+ const typeName = physical ? (physical.deviceType ?? '') : ir.remoteType;
202
+ const match = typeName ? findCatalogEntry(typeName) : null;
203
+ const catalogEntry = !match || Array.isArray(match) ? null : match;
204
+ let liveStatus;
205
+ if (options.live && physical) {
206
+ try {
207
+ liveStatus = await fetchDeviceStatus(deviceId, client);
208
+ }
209
+ catch (err) {
210
+ liveStatus = { error: err instanceof Error ? err.message : String(err) };
211
+ }
212
+ }
213
+ const source = catalogEntry
214
+ ? liveStatus
215
+ ? 'catalog+live'
216
+ : 'catalog'
217
+ : liveStatus
218
+ ? 'live'
219
+ : 'none';
220
+ const capabilities = catalogEntry
221
+ ? {
222
+ role: catalogEntry.role ?? null,
223
+ readOnly: catalogEntry.readOnly ?? false,
224
+ commands: catalogEntry.commands,
225
+ statusFields: catalogEntry.statusFields ?? [],
226
+ ...(liveStatus !== undefined ? { liveStatus } : {}),
227
+ }
228
+ : liveStatus !== undefined
229
+ ? { liveStatus }
230
+ : null;
231
+ return {
232
+ device: (physical ?? ir),
233
+ isPhysical: Boolean(physical),
234
+ typeName,
235
+ controlType: physical?.controlType ?? ir?.controlType ?? null,
236
+ catalog: catalogEntry,
237
+ capabilities,
238
+ source,
239
+ suggestedActions: catalogEntry ? suggestedActions(catalogEntry) : [],
240
+ inheritedLocation: ir ? buildHubLocationMap(deviceList).get(ir.hubDeviceId) : undefined,
241
+ };
242
+ }
243
+ /** Build a map from hubDeviceId → room/family/roomID for IR-remote inheritance. */
244
+ export function buildHubLocationMap(deviceList) {
245
+ const map = new Map();
246
+ for (const d of deviceList) {
247
+ if (!d.deviceId)
248
+ continue;
249
+ map.set(d.deviceId, {
250
+ family: d.familyName ?? undefined,
251
+ room: d.roomName ?? undefined,
252
+ roomID: d.roomID ?? undefined,
253
+ });
254
+ }
255
+ return map;
256
+ }
257
+ /**
258
+ * Search the local catalog by type name / alias. Returns up to `limit`
259
+ * entries whose type or alias contains the query (case-insensitive).
260
+ * Intended for MCP's `search_catalog` tool — not for dispatching commands.
261
+ */
262
+ export function searchCatalog(query, limit = 20) {
263
+ const catalog = getEffectiveCatalog();
264
+ const q = query.trim().toLowerCase();
265
+ if (!q)
266
+ return catalog.slice(0, limit);
267
+ const hits = [];
268
+ for (const entry of catalog) {
269
+ const haystack = [entry.type, ...(entry.aliases ?? [])].map((s) => s.toLowerCase());
270
+ if (haystack.some((h) => h.includes(q))) {
271
+ hits.push(entry);
272
+ if (hits.length >= limit)
273
+ break;
274
+ }
275
+ }
276
+ return hits;
277
+ }
278
+ /** Convert a DescribeResult to the shape validated by the MCP outputSchema. */
279
+ export function toMcpDescribeShape(r) {
280
+ const d = r.device;
281
+ return {
282
+ device: {
283
+ deviceId: d.deviceId,
284
+ deviceName: d.deviceName,
285
+ ...(d.deviceType !== undefined ? { deviceType: d.deviceType } : {}),
286
+ ...('enableCloudService' in d ? { enableCloudService: d.enableCloudService } : {}),
287
+ ...(d.hubDeviceId !== undefined ? { hubDeviceId: d.hubDeviceId } : {}),
288
+ ...(d.roomID !== undefined ? { roomID: d.roomID } : {}),
289
+ ...(d.roomName !== undefined ? { roomName: d.roomName } : {}),
290
+ ...(d.familyName !== undefined ? { familyName: d.familyName } : {}),
291
+ ...(d.controlType !== undefined ? { controlType: d.controlType } : {}),
292
+ ...('remoteType' in d && d.remoteType !== undefined ? { remoteType: d.remoteType } : {}),
293
+ },
294
+ isPhysical: r.isPhysical,
295
+ typeName: r.typeName,
296
+ controlType: r.controlType,
297
+ source: r.source,
298
+ capabilities: r.capabilities,
299
+ suggestedActions: r.suggestedActions,
300
+ ...(r.inheritedLocation !== undefined
301
+ ? { inheritedLocation: { family: r.inheritedLocation.family, room: r.inheritedLocation.room } }
302
+ : {}),
303
+ };
304
+ }
305
+ /** Shapes the device list body for the MCP list_devices outputSchema. */
306
+ export function toMcpDeviceListShape(d) {
307
+ return {
308
+ deviceId: d.deviceId,
309
+ deviceName: d.deviceName,
310
+ deviceType: d.deviceType,
311
+ enableCloudService: d.enableCloudService,
312
+ hubDeviceId: d.hubDeviceId,
313
+ roomID: d.roomID,
314
+ roomName: d.roomName,
315
+ familyName: d.familyName,
316
+ controlType: d.controlType,
317
+ };
318
+ }
319
+ /** Shapes an infrared remote for the MCP list_devices outputSchema. */
320
+ export function toMcpIrDeviceShape(d) {
321
+ return {
322
+ deviceId: d.deviceId,
323
+ deviceName: d.deviceName,
324
+ remoteType: d.remoteType,
325
+ hubDeviceId: d.hubDeviceId,
326
+ controlType: d.controlType,
327
+ };
328
+ }
329
+ //# sourceMappingURL=devices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/lib/devices.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ export interface Scene {
3
+ sceneId: string;
4
+ sceneName: string;
5
+ }
6
+ export declare function fetchScenes(client?: AxiosInstance): Promise<Scene[]>;
7
+ export declare function executeScene(sceneId: string, client?: AxiosInstance): Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { createClient } from '../api/client.js';
2
+ export async function fetchScenes(client) {
3
+ const c = client ?? createClient();
4
+ const res = await c.get('/v1.1/scenes');
5
+ return res.data.body;
6
+ }
7
+ export async function executeScene(sceneId, client) {
8
+ const c = client ?? createClient();
9
+ await c.post(`/v1.1/scenes/${sceneId}/execute`);
10
+ }
11
+ //# sourceMappingURL=scenes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenes.js","sourceRoot":"","sources":["../../src/lib/scenes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAOhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAsB;IACtD,MAAM,CAAC,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,CAAoB,cAAc,CAAC,CAAC;IAC3D,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,MAAsB;IACxE,MAAM,CAAC,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACnC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,OAAO,UAAU,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface AuditEntry {
2
+ t: string;
3
+ kind: 'command';
4
+ deviceId: string;
5
+ command: string;
6
+ parameter: unknown;
7
+ commandType: 'command' | 'customize';
8
+ dryRun: boolean;
9
+ result?: 'ok' | 'error';
10
+ error?: string;
11
+ }
12
+ export declare function writeAudit(entry: AuditEntry): void;
13
+ export declare function readAudit(file: string): AuditEntry[];
@@ -0,0 +1,43 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { getAuditLog } from './flags.js';
4
+ function resolveAuditPath() {
5
+ const flag = getAuditLog();
6
+ if (flag === null)
7
+ return null;
8
+ return path.resolve(flag);
9
+ }
10
+ export function writeAudit(entry) {
11
+ const file = resolveAuditPath();
12
+ if (!file)
13
+ return;
14
+ const dir = path.dirname(file);
15
+ try {
16
+ if (!fs.existsSync(dir)) {
17
+ fs.mkdirSync(dir, { recursive: true });
18
+ }
19
+ fs.appendFileSync(file, JSON.stringify(entry) + '\n');
20
+ }
21
+ catch {
22
+ // Best-effort — never let audit failures break the actual command.
23
+ }
24
+ }
25
+ export function readAudit(file) {
26
+ if (!fs.existsSync(file))
27
+ return [];
28
+ const raw = fs.readFileSync(file, 'utf-8');
29
+ const out = [];
30
+ for (const line of raw.split(/\r?\n/)) {
31
+ const trimmed = line.trim();
32
+ if (!trimmed)
33
+ continue;
34
+ try {
35
+ out.push(JSON.parse(trimmed));
36
+ }
37
+ catch {
38
+ // skip malformed lines
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/utils/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAczC,SAAS,gBAAgB;IACvB,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;IACrE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { Device, InfraredDevice } from '../lib/devices.js';
2
+ /**
3
+ * A parsed filter clause. Each clause is an (op, key, value) triple that runs
4
+ * against a candidate device. All clauses from a single expression are AND-ed.
5
+ */
6
+ export interface FilterClause {
7
+ key: 'type' | 'family' | 'room' | 'category';
8
+ op: '=' | '~=';
9
+ value: string;
10
+ }
11
+ export declare class FilterSyntaxError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ /**
15
+ * Parse a filter expression like "type=Bot,family=Home" into discrete clauses.
16
+ *
17
+ * Grammar:
18
+ * expr := clause ("," clause)*
19
+ * clause := KEY OP VALUE
20
+ * KEY := type | family | room | category
21
+ * OP := "=" | "~="
22
+ * VALUE := any non-empty string (no comma — split at the clause boundary)
23
+ *
24
+ * Whitespace around keys / values is trimmed. Empty expressions return [].
25
+ */
26
+ export declare function parseFilter(expr: string | undefined): FilterClause[];
27
+ interface FilterableDevice {
28
+ deviceId: string;
29
+ type: string;
30
+ family?: string;
31
+ room?: string;
32
+ category: 'physical' | 'ir';
33
+ }
34
+ /**
35
+ * Apply the parsed clauses to a mixed list of physical devices + IR remotes.
36
+ * Returns the deviceIds of the entries that satisfy every clause.
37
+ *
38
+ * `hubLocation` (optional) allows family/room filters to match IR remotes by
39
+ * the Hub-inherited location.
40
+ */
41
+ export declare function applyFilter(clauses: FilterClause[], deviceList: Device[], infraredRemoteList: InfraredDevice[], hubLocation?: Map<string, {
42
+ family?: string;
43
+ room?: string;
44
+ }>): FilterableDevice[];
45
+ export {};
@@ -0,0 +1,96 @@
1
+ export class FilterSyntaxError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = 'FilterSyntaxError';
5
+ }
6
+ }
7
+ const VALID_KEYS = ['type', 'family', 'room', 'category'];
8
+ /**
9
+ * Parse a filter expression like "type=Bot,family=Home" into discrete clauses.
10
+ *
11
+ * Grammar:
12
+ * expr := clause ("," clause)*
13
+ * clause := KEY OP VALUE
14
+ * KEY := type | family | room | category
15
+ * OP := "=" | "~="
16
+ * VALUE := any non-empty string (no comma — split at the clause boundary)
17
+ *
18
+ * Whitespace around keys / values is trimmed. Empty expressions return [].
19
+ */
20
+ export function parseFilter(expr) {
21
+ if (!expr)
22
+ return [];
23
+ const parts = expr.split(',').map((p) => p.trim()).filter((p) => p.length > 0);
24
+ const clauses = [];
25
+ for (const part of parts) {
26
+ const m = /^([a-zA-Z_]+)\s*(~=|=)\s*(.+)$/.exec(part);
27
+ if (!m) {
28
+ throw new FilterSyntaxError(`Invalid filter clause "${part}" — expected "<key>=<value>" or "<key>~=<pattern>"`);
29
+ }
30
+ const key = m[1];
31
+ const op = m[2];
32
+ const value = m[3].trim();
33
+ if (!VALID_KEYS.includes(key)) {
34
+ throw new FilterSyntaxError(`Unknown filter key "${key}" — supported: ${VALID_KEYS.join(', ')}`);
35
+ }
36
+ if (!value) {
37
+ throw new FilterSyntaxError(`Empty value for filter clause "${part}"`);
38
+ }
39
+ clauses.push({ key, op, value });
40
+ }
41
+ return clauses;
42
+ }
43
+ /** Normalize a physical / IR device entry to the shape the filter matcher expects. */
44
+ function toFilterable(d, isPhysical, hubLocation) {
45
+ if (isPhysical) {
46
+ const p = d;
47
+ return {
48
+ deviceId: p.deviceId,
49
+ type: p.deviceType ?? '',
50
+ family: p.familyName ?? undefined,
51
+ room: p.roomName ?? undefined,
52
+ category: 'physical',
53
+ };
54
+ }
55
+ const ir = d;
56
+ const inherited = hubLocation?.get(ir.hubDeviceId);
57
+ return {
58
+ deviceId: ir.deviceId,
59
+ type: ir.remoteType ?? '',
60
+ family: inherited?.family,
61
+ room: inherited?.room,
62
+ category: 'ir',
63
+ };
64
+ }
65
+ function matches(d, clause) {
66
+ const candidate = clause.key === 'type'
67
+ ? d.type
68
+ : clause.key === 'family'
69
+ ? d.family
70
+ : clause.key === 'room'
71
+ ? d.room
72
+ : d.category;
73
+ if (candidate === undefined)
74
+ return false;
75
+ if (clause.op === '=')
76
+ return candidate.toLowerCase() === clause.value.toLowerCase();
77
+ // '~=' — case-insensitive substring match on the candidate.
78
+ return candidate.toLowerCase().includes(clause.value.toLowerCase());
79
+ }
80
+ /**
81
+ * Apply the parsed clauses to a mixed list of physical devices + IR remotes.
82
+ * Returns the deviceIds of the entries that satisfy every clause.
83
+ *
84
+ * `hubLocation` (optional) allows family/room filters to match IR remotes by
85
+ * the Hub-inherited location.
86
+ */
87
+ export function applyFilter(clauses, deviceList, infraredRemoteList, hubLocation) {
88
+ const candidates = [
89
+ ...deviceList.map((d) => toFilterable(d, true)),
90
+ ...infraredRemoteList.map((d) => toFilterable(d, false, hubLocation)),
91
+ ];
92
+ if (clauses.length === 0)
93
+ return candidates;
94
+ return candidates.filter((c) => clauses.every((clause) => matches(c, clause)));
95
+ }
96
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/utils/filter.ts"],"names":[],"mappings":"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"}
@@ -8,3 +8,45 @@ export declare function isDryRun(): boolean;
8
8
  export declare function getTimeout(): number;
9
9
  /** Override for the credentials file path. */
10
10
  export declare function getConfigPath(): string | undefined;
11
+ /** Named profile → ~/.switchbot/profiles/<name>.json. */
12
+ export declare function getProfile(): string | undefined;
13
+ /**
14
+ * Audit log path. `--audit-log <path>` enables JSONL append on every mutating
15
+ * command; default path is ~/.switchbot/audit.log when `--audit-log` is given
16
+ * without a value. Returns null when the flag is absent.
17
+ */
18
+ export declare function getAuditLog(): string | null;
19
+ /**
20
+ * Max 429 retries before surfacing the error. Default 3. `--no-retry`
21
+ * disables retries entirely; `--retry-on-429 <n>` overrides the count.
22
+ */
23
+ export declare function getRetryOn429(): number;
24
+ /** Backoff strategy for 429 retries. Default 'exponential'. */
25
+ export declare function getBackoffStrategy(): 'linear' | 'exponential';
26
+ /**
27
+ * Whether local quota counting is disabled. Quota counting is best-effort
28
+ * (see src/utils/quota.ts) — this lets scripts opt out entirely when even
29
+ * best-effort file I/O is unwelcome.
30
+ */
31
+ export declare function isQuotaDisabled(): boolean;
32
+ /**
33
+ * Cache TTL controls. Values:
34
+ * - `--no-cache` → disable cache for all reads
35
+ * - `--cache off` → same as `--no-cache`
36
+ * - `--cache auto` (default) → list cache on (1h), status cache off
37
+ * - `--cache 5m` | `--cache 1h` → enable both stores with the given TTL
38
+ * - numeric millisecond values are also accepted
39
+ */
40
+ export interface CacheMode {
41
+ /** TTL for the device-list cache, in ms. 0/undefined = off. */
42
+ listTtlMs: number;
43
+ /** TTL for the device-status cache, in ms. 0/undefined = off. */
44
+ statusTtlMs: number;
45
+ }
46
+ declare function parseDurationToMs(v: string): number | null;
47
+ export { parseDurationToMs };
48
+ /** The --format flag value, or undefined when absent. */
49
+ export declare function getFormat(): string | undefined;
50
+ /** Comma-separated --fields value, split into an array. */
51
+ export declare function getFields(): string[] | undefined;
52
+ export declare function getCacheMode(): CacheMode;