@switchbot/openapi-cli 3.2.1 → 3.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.
- package/README.md +3 -1
- package/dist/index.js +57419 -170
- package/package.json +9 -5
- package/dist/api/client.d.ts +0 -31
- package/dist/api/client.js +0 -236
- package/dist/api/client.js.map +0 -1
- package/dist/auth.d.ts +0 -1
- package/dist/auth.js +0 -21
- package/dist/auth.js.map +0 -1
- package/dist/commands/agent-bootstrap.d.ts +0 -10
- package/dist/commands/agent-bootstrap.js +0 -200
- package/dist/commands/agent-bootstrap.js.map +0 -1
- package/dist/commands/auth.d.ts +0 -18
- package/dist/commands/auth.js +0 -355
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/batch.d.ts +0 -2
- package/dist/commands/batch.js +0 -414
- package/dist/commands/batch.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -2
- package/dist/commands/cache.js +0 -127
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/capabilities.d.ts +0 -31
- package/dist/commands/capabilities.js +0 -383
- package/dist/commands/capabilities.js.map +0 -1
- package/dist/commands/catalog.d.ts +0 -2
- package/dist/commands/catalog.js +0 -360
- package/dist/commands/catalog.js.map +0 -1
- package/dist/commands/completion.d.ts +0 -2
- package/dist/commands/completion.js +0 -386
- package/dist/commands/completion.js.map +0 -1
- package/dist/commands/config.d.ts +0 -21
- package/dist/commands/config.js +0 -377
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/daemon.d.ts +0 -2
- package/dist/commands/daemon.js +0 -411
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/device-meta.d.ts +0 -2
- package/dist/commands/device-meta.js +0 -160
- package/dist/commands/device-meta.js.map +0 -1
- package/dist/commands/devices.d.ts +0 -2
- package/dist/commands/devices.js +0 -949
- package/dist/commands/devices.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -3
- package/dist/commands/doctor.js +0 -1016
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/events.d.ts +0 -31
- package/dist/commands/events.js +0 -564
- package/dist/commands/events.js.map +0 -1
- package/dist/commands/expand.d.ts +0 -2
- package/dist/commands/expand.js +0 -131
- package/dist/commands/expand.js.map +0 -1
- package/dist/commands/explain.d.ts +0 -2
- package/dist/commands/explain.js +0 -140
- package/dist/commands/explain.js.map +0 -1
- package/dist/commands/health.d.ts +0 -8
- package/dist/commands/health.js +0 -114
- package/dist/commands/health.js.map +0 -1
- package/dist/commands/history.d.ts +0 -2
- package/dist/commands/history.js +0 -321
- package/dist/commands/history.js.map +0 -1
- package/dist/commands/identity.d.ts +0 -45
- package/dist/commands/identity.js +0 -60
- package/dist/commands/identity.js.map +0 -1
- package/dist/commands/install.d.ts +0 -20
- package/dist/commands/install.js +0 -247
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -14
- package/dist/commands/mcp.js +0 -2018
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/plan.d.ts +0 -51
- package/dist/commands/plan.js +0 -654
- package/dist/commands/plan.js.map +0 -1
- package/dist/commands/policy.d.ts +0 -24
- package/dist/commands/policy.js +0 -587
- package/dist/commands/policy.js.map +0 -1
- package/dist/commands/quota.d.ts +0 -2
- package/dist/commands/quota.js +0 -79
- package/dist/commands/quota.js.map +0 -1
- package/dist/commands/rules.d.ts +0 -2
- package/dist/commands/rules.js +0 -876
- package/dist/commands/rules.js.map +0 -1
- package/dist/commands/scenes.d.ts +0 -2
- package/dist/commands/scenes.js +0 -265
- package/dist/commands/scenes.js.map +0 -1
- package/dist/commands/schema.d.ts +0 -2
- package/dist/commands/schema.js +0 -185
- package/dist/commands/schema.js.map +0 -1
- package/dist/commands/status-sync.d.ts +0 -2
- package/dist/commands/status-sync.js +0 -132
- package/dist/commands/status-sync.js.map +0 -1
- package/dist/commands/uninstall.d.ts +0 -20
- package/dist/commands/uninstall.js +0 -238
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/upgrade-check.d.ts +0 -2
- package/dist/commands/upgrade-check.js +0 -107
- package/dist/commands/upgrade-check.js.map +0 -1
- package/dist/commands/watch.d.ts +0 -2
- package/dist/commands/watch.js +0 -195
- package/dist/commands/watch.js.map +0 -1
- package/dist/commands/webhook.d.ts +0 -2
- package/dist/commands/webhook.js +0 -183
- package/dist/commands/webhook.js.map +0 -1
- package/dist/config.d.ts +0 -57
- package/dist/config.js +0 -259
- package/dist/config.js.map +0 -1
- package/dist/credentials/backends/file.d.ts +0 -18
- package/dist/credentials/backends/file.js +0 -102
- package/dist/credentials/backends/file.js.map +0 -1
- package/dist/credentials/backends/linux.d.ts +0 -16
- package/dist/credentials/backends/linux.js +0 -130
- package/dist/credentials/backends/linux.js.map +0 -1
- package/dist/credentials/backends/macos.d.ts +0 -18
- package/dist/credentials/backends/macos.js +0 -130
- package/dist/credentials/backends/macos.js.map +0 -1
- package/dist/credentials/backends/windows.d.ts +0 -23
- package/dist/credentials/backends/windows.js +0 -216
- package/dist/credentials/backends/windows.js.map +0 -1
- package/dist/credentials/keychain.d.ts +0 -83
- package/dist/credentials/keychain.js +0 -89
- package/dist/credentials/keychain.js.map +0 -1
- package/dist/credentials/prime.d.ts +0 -32
- package/dist/credentials/prime.js +0 -53
- package/dist/credentials/prime.js.map +0 -1
- package/dist/devices/cache.d.ts +0 -79
- package/dist/devices/cache.js +0 -294
- package/dist/devices/cache.js.map +0 -1
- package/dist/devices/catalog.d.ts +0 -138
- package/dist/devices/catalog.js +0 -768
- package/dist/devices/catalog.js.map +0 -1
- package/dist/devices/device-meta.d.ts +0 -15
- package/dist/devices/device-meta.js +0 -57
- package/dist/devices/device-meta.js.map +0 -1
- package/dist/devices/history-agg.d.ts +0 -37
- package/dist/devices/history-agg.js +0 -139
- package/dist/devices/history-agg.js.map +0 -1
- package/dist/devices/history-query.d.ts +0 -45
- package/dist/devices/history-query.js +0 -182
- package/dist/devices/history-query.js.map +0 -1
- package/dist/devices/param-validator.d.ts +0 -40
- package/dist/devices/param-validator.js +0 -434
- package/dist/devices/param-validator.js.map +0 -1
- package/dist/devices/resources.d.ts +0 -74
- package/dist/devices/resources.js +0 -271
- package/dist/devices/resources.js.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +0 -1
- package/dist/install/default-steps.d.ts +0 -66
- package/dist/install/default-steps.js +0 -258
- package/dist/install/default-steps.js.map +0 -1
- package/dist/install/preflight.d.ts +0 -60
- package/dist/install/preflight.js +0 -213
- package/dist/install/preflight.js.map +0 -1
- package/dist/install/steps.d.ts +0 -61
- package/dist/install/steps.js +0 -68
- package/dist/install/steps.js.map +0 -1
- package/dist/lib/command-keywords.d.ts +0 -5
- package/dist/lib/command-keywords.js +0 -18
- package/dist/lib/command-keywords.js.map +0 -1
- package/dist/lib/daemon-state.d.ts +0 -24
- package/dist/lib/daemon-state.js +0 -47
- package/dist/lib/daemon-state.js.map +0 -1
- package/dist/lib/destructive-mode.d.ts +0 -2
- package/dist/lib/destructive-mode.js +0 -13
- package/dist/lib/destructive-mode.js.map +0 -1
- package/dist/lib/devices.d.ts +0 -151
- package/dist/lib/devices.js +0 -383
- package/dist/lib/devices.js.map +0 -1
- package/dist/lib/idempotency.d.ts +0 -46
- package/dist/lib/idempotency.js +0 -107
- package/dist/lib/idempotency.js.map +0 -1
- package/dist/lib/plan-store.d.ts +0 -19
- package/dist/lib/plan-store.js +0 -69
- package/dist/lib/plan-store.js.map +0 -1
- package/dist/lib/request-context.d.ts +0 -7
- package/dist/lib/request-context.js +0 -13
- package/dist/lib/request-context.js.map +0 -1
- package/dist/lib/scenes.d.ts +0 -7
- package/dist/lib/scenes.js +0 -11
- package/dist/lib/scenes.js.map +0 -1
- package/dist/logger.d.ts +0 -4
- package/dist/logger.js +0 -17
- package/dist/logger.js.map +0 -1
- package/dist/mcp/device-history.d.ts +0 -36
- package/dist/mcp/device-history.js +0 -146
- package/dist/mcp/device-history.js.map +0 -1
- package/dist/mcp/events-subscription.d.ts +0 -45
- package/dist/mcp/events-subscription.js +0 -214
- package/dist/mcp/events-subscription.js.map +0 -1
- package/dist/mqtt/client.d.ts +0 -25
- package/dist/mqtt/client.js +0 -181
- package/dist/mqtt/client.js.map +0 -1
- package/dist/mqtt/credential.d.ts +0 -16
- package/dist/mqtt/credential.js +0 -31
- package/dist/mqtt/credential.js.map +0 -1
- package/dist/policy/add-rule.d.ts +0 -21
- package/dist/policy/add-rule.js +0 -125
- package/dist/policy/add-rule.js.map +0 -1
- package/dist/policy/diff.d.ts +0 -21
- package/dist/policy/diff.js +0 -92
- package/dist/policy/diff.js.map +0 -1
- package/dist/policy/format.d.ts +0 -6
- package/dist/policy/format.js +0 -58
- package/dist/policy/format.js.map +0 -1
- package/dist/policy/load.d.ts +0 -32
- package/dist/policy/load.js +0 -62
- package/dist/policy/load.js.map +0 -1
- package/dist/policy/migrate.d.ts +0 -21
- package/dist/policy/migrate.js +0 -68
- package/dist/policy/migrate.js.map +0 -1
- package/dist/policy/schema.d.ts +0 -5
- package/dist/policy/schema.js +0 -19
- package/dist/policy/schema.js.map +0 -1
- package/dist/policy/validate.d.ts +0 -19
- package/dist/policy/validate.js +0 -263
- package/dist/policy/validate.js.map +0 -1
- package/dist/rules/action.d.ts +0 -65
- package/dist/rules/action.js +0 -217
- package/dist/rules/action.js.map +0 -1
- package/dist/rules/audit-query.d.ts +0 -51
- package/dist/rules/audit-query.js +0 -90
- package/dist/rules/audit-query.js.map +0 -1
- package/dist/rules/conflict-analyzer.d.ts +0 -57
- package/dist/rules/conflict-analyzer.js +0 -215
- package/dist/rules/conflict-analyzer.js.map +0 -1
- package/dist/rules/cron-scheduler.d.ts +0 -62
- package/dist/rules/cron-scheduler.js +0 -187
- package/dist/rules/cron-scheduler.js.map +0 -1
- package/dist/rules/destructive.d.ts +0 -20
- package/dist/rules/destructive.js +0 -53
- package/dist/rules/destructive.js.map +0 -1
- package/dist/rules/engine.d.ts +0 -193
- package/dist/rules/engine.js +0 -758
- package/dist/rules/engine.js.map +0 -1
- package/dist/rules/matcher.d.ts +0 -56
- package/dist/rules/matcher.js +0 -231
- package/dist/rules/matcher.js.map +0 -1
- package/dist/rules/pid-file.d.ts +0 -43
- package/dist/rules/pid-file.js +0 -96
- package/dist/rules/pid-file.js.map +0 -1
- package/dist/rules/quiet-hours.d.ts +0 -26
- package/dist/rules/quiet-hours.js +0 -46
- package/dist/rules/quiet-hours.js.map +0 -1
- package/dist/rules/suggest.d.ts +0 -20
- package/dist/rules/suggest.js +0 -96
- package/dist/rules/suggest.js.map +0 -1
- package/dist/rules/throttle.d.ts +0 -61
- package/dist/rules/throttle.js +0 -117
- package/dist/rules/throttle.js.map +0 -1
- package/dist/rules/types.d.ts +0 -117
- package/dist/rules/types.js +0 -35
- package/dist/rules/types.js.map +0 -1
- package/dist/rules/webhook-listener.d.ts +0 -63
- package/dist/rules/webhook-listener.js +0 -224
- package/dist/rules/webhook-listener.js.map +0 -1
- package/dist/rules/webhook-token.d.ts +0 -50
- package/dist/rules/webhook-token.js +0 -91
- package/dist/rules/webhook-token.js.map +0 -1
- package/dist/schema/field-aliases.d.ts +0 -34
- package/dist/schema/field-aliases.js +0 -132
- package/dist/schema/field-aliases.js.map +0 -1
- package/dist/sinks/dispatcher.d.ts +0 -7
- package/dist/sinks/dispatcher.js +0 -13
- package/dist/sinks/dispatcher.js.map +0 -1
- package/dist/sinks/file.d.ts +0 -6
- package/dist/sinks/file.js +0 -20
- package/dist/sinks/file.js.map +0 -1
- package/dist/sinks/format.d.ts +0 -20
- package/dist/sinks/format.js +0 -57
- package/dist/sinks/format.js.map +0 -1
- package/dist/sinks/homeassistant.d.ts +0 -18
- package/dist/sinks/homeassistant.js +0 -45
- package/dist/sinks/homeassistant.js.map +0 -1
- package/dist/sinks/openclaw.d.ts +0 -13
- package/dist/sinks/openclaw.js +0 -34
- package/dist/sinks/openclaw.js.map +0 -1
- package/dist/sinks/stdout.d.ts +0 -4
- package/dist/sinks/stdout.js +0 -6
- package/dist/sinks/stdout.js.map +0 -1
- package/dist/sinks/telegram.d.ts +0 -11
- package/dist/sinks/telegram.js +0 -29
- package/dist/sinks/telegram.js.map +0 -1
- package/dist/sinks/types.d.ts +0 -13
- package/dist/sinks/types.js +0 -2
- package/dist/sinks/types.js.map +0 -1
- package/dist/sinks/webhook.d.ts +0 -6
- package/dist/sinks/webhook.js +0 -23
- package/dist/sinks/webhook.js.map +0 -1
- package/dist/status-sync/manager.d.ts +0 -48
- package/dist/status-sync/manager.js +0 -269
- package/dist/status-sync/manager.js.map +0 -1
- package/dist/utils/arg-parsers.d.ts +0 -16
- package/dist/utils/arg-parsers.js +0 -67
- package/dist/utils/arg-parsers.js.map +0 -1
- package/dist/utils/audit.d.ts +0 -69
- package/dist/utils/audit.js +0 -122
- package/dist/utils/audit.js.map +0 -1
- package/dist/utils/filter.d.ts +0 -81
- package/dist/utils/filter.js +0 -190
- package/dist/utils/filter.js.map +0 -1
- package/dist/utils/flags.d.ts +0 -72
- package/dist/utils/flags.js +0 -187
- package/dist/utils/flags.js.map +0 -1
- package/dist/utils/format.d.ts +0 -9
- package/dist/utils/format.js +0 -118
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/health.d.ts +0 -48
- package/dist/utils/health.js +0 -102
- package/dist/utils/health.js.map +0 -1
- package/dist/utils/help-json.d.ts +0 -39
- package/dist/utils/help-json.js +0 -55
- package/dist/utils/help-json.js.map +0 -1
- package/dist/utils/name-resolver.d.ts +0 -26
- package/dist/utils/name-resolver.js +0 -138
- package/dist/utils/name-resolver.js.map +0 -1
- package/dist/utils/output.d.ts +0 -73
- package/dist/utils/output.js +0 -405
- package/dist/utils/output.js.map +0 -1
- package/dist/utils/quota.d.ts +0 -61
- package/dist/utils/quota.js +0 -228
- package/dist/utils/quota.js.map +0 -1
- package/dist/utils/redact.d.ts +0 -23
- package/dist/utils/redact.js +0 -69
- package/dist/utils/redact.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -72
- package/dist/utils/retry.js +0 -141
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/string.d.ts +0 -2
- package/dist/utils/string.js +0 -23
- package/dist/utils/string.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -5
- package/dist/version.js.map +0 -1
package/dist/devices/cache.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
export interface CachedDevice {
|
|
2
|
-
type: string;
|
|
3
|
-
name: string;
|
|
4
|
-
category: 'physical' | 'ir';
|
|
5
|
-
hubDeviceId?: string;
|
|
6
|
-
enableCloudService?: boolean;
|
|
7
|
-
roomID?: string;
|
|
8
|
-
roomName?: string | null;
|
|
9
|
-
familyName?: string;
|
|
10
|
-
controlType?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface DeviceCache {
|
|
13
|
-
lastUpdated: string;
|
|
14
|
-
devices: Record<string, CachedDevice>;
|
|
15
|
-
}
|
|
16
|
-
export interface DeviceListBodyShape {
|
|
17
|
-
deviceList: Array<{
|
|
18
|
-
deviceId: string;
|
|
19
|
-
deviceName: string;
|
|
20
|
-
deviceType?: string;
|
|
21
|
-
hubDeviceId?: string;
|
|
22
|
-
enableCloudService?: boolean;
|
|
23
|
-
roomID?: string;
|
|
24
|
-
roomName?: string | null;
|
|
25
|
-
familyName?: string;
|
|
26
|
-
controlType?: string;
|
|
27
|
-
}>;
|
|
28
|
-
infraredRemoteList: Array<{
|
|
29
|
-
deviceId: string;
|
|
30
|
-
deviceName: string;
|
|
31
|
-
remoteType: string;
|
|
32
|
-
hubDeviceId?: string;
|
|
33
|
-
controlType?: string;
|
|
34
|
-
}>;
|
|
35
|
-
}
|
|
36
|
-
/** Force the next loadCache() call to re-read from disk. Used in tests. */
|
|
37
|
-
export declare function resetListCache(): void;
|
|
38
|
-
/** Force the next loadStatusCache() call to re-read from disk. Used in tests. */
|
|
39
|
-
export declare function resetStatusCache(): void;
|
|
40
|
-
export declare function loadCache(): DeviceCache | null;
|
|
41
|
-
export declare function getCachedDevice(deviceId: string): CachedDevice | null;
|
|
42
|
-
/** Build a deviceId -> type map from the metadata cache. */
|
|
43
|
-
export declare function getCachedTypeMap(deviceIds?: Iterable<string>): Map<string, string>;
|
|
44
|
-
export declare function updateCacheFromDeviceList(body: DeviceListBodyShape): void;
|
|
45
|
-
export declare function clearCache(): void;
|
|
46
|
-
/** Age of the on-disk list cache in ms, or null if there is no cache. */
|
|
47
|
-
export declare function listCacheAgeMs(now?: number): number | null;
|
|
48
|
-
/** True when the on-disk list cache is present and younger than `ttlMs`. */
|
|
49
|
-
export declare function isListCacheFresh(ttlMs: number, now?: number): boolean;
|
|
50
|
-
export interface CachedStatus {
|
|
51
|
-
fetchedAt: string;
|
|
52
|
-
body: Record<string, unknown>;
|
|
53
|
-
}
|
|
54
|
-
export interface StatusCache {
|
|
55
|
-
entries: Record<string, CachedStatus>;
|
|
56
|
-
}
|
|
57
|
-
export declare function loadStatusCache(): StatusCache;
|
|
58
|
-
/** Read a status entry; returns null when missing or older than `ttlMs`. */
|
|
59
|
-
export declare function getCachedStatus(deviceId: string, ttlMs: number, now?: number): Record<string, unknown> | null;
|
|
60
|
-
export declare function setCachedStatus(deviceId: string, body: Record<string, unknown>, now?: Date, ttlMsForGc?: number): void;
|
|
61
|
-
export declare function clearStatusCache(): void;
|
|
62
|
-
/** Summary for `switchbot cache show`. */
|
|
63
|
-
export interface CacheSummary {
|
|
64
|
-
list: {
|
|
65
|
-
path: string;
|
|
66
|
-
exists: boolean;
|
|
67
|
-
lastUpdated?: string;
|
|
68
|
-
ageMs?: number;
|
|
69
|
-
deviceCount?: number;
|
|
70
|
-
};
|
|
71
|
-
status: {
|
|
72
|
-
path: string;
|
|
73
|
-
exists: boolean;
|
|
74
|
-
entryCount: number;
|
|
75
|
-
oldestFetchedAt?: string;
|
|
76
|
-
newestFetchedAt?: string;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
export declare function describeCache(now?: number): CacheSummary;
|
package/dist/devices/cache.js
DELETED
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import { createHash } from 'node:crypto';
|
|
5
|
-
import { getConfigPath } from '../utils/flags.js';
|
|
6
|
-
import { getActiveProfile } from '../lib/request-context.js';
|
|
7
|
-
/**
|
|
8
|
-
* Returns the directory where cache files should be stored.
|
|
9
|
-
*
|
|
10
|
-
* - If a profile is active, scopes into a per-profile sub-directory so that
|
|
11
|
-
* rotating credentials or switching profiles never serves stale inventory
|
|
12
|
-
* from a prior session (Bug #37).
|
|
13
|
-
* - If no profile is active (unnamed / default), returns `baseDir` unchanged
|
|
14
|
-
* so the existing legacy path (~/.switchbot/devices.json) is preserved.
|
|
15
|
-
*
|
|
16
|
-
* Only called when `getConfigPath()` returns undefined — the --config-path
|
|
17
|
-
* override takes full precedence and bypasses this helper entirely.
|
|
18
|
-
*/
|
|
19
|
-
function scopedCacheDir(baseDir) {
|
|
20
|
-
const profile = getActiveProfile();
|
|
21
|
-
if (profile === undefined)
|
|
22
|
-
return baseDir;
|
|
23
|
-
const hash = createHash('sha256').update(profile).digest('hex').slice(0, 8);
|
|
24
|
-
const dir = path.join(baseDir, 'cache', hash);
|
|
25
|
-
if (!fs.existsSync(dir))
|
|
26
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
-
return dir;
|
|
28
|
-
}
|
|
29
|
-
/** GC cutoff for status entries: evict anything older than this. */
|
|
30
|
-
const DEFAULT_STATUS_GC_TTL_MS = 24 * 60 * 60 * 1000; // 24 h
|
|
31
|
-
function cacheFilePath() {
|
|
32
|
-
const override = getConfigPath();
|
|
33
|
-
const dir = override
|
|
34
|
-
? path.dirname(path.resolve(override))
|
|
35
|
-
: scopedCacheDir(path.join(os.homedir(), '.switchbot'));
|
|
36
|
-
return path.join(dir, 'devices.json');
|
|
37
|
-
}
|
|
38
|
-
// In-memory hot-cache keyed by active profile (or '__default__' for no profile).
|
|
39
|
-
// Using Maps instead of module-level singletons ensures that mcp serve, which
|
|
40
|
-
// rotates profiles per request via withRequestContext, never leaks inventory
|
|
41
|
-
// across profiles within the same process (Bug #37).
|
|
42
|
-
const _listCacheByProfile = new Map();
|
|
43
|
-
const _statusCacheByProfile = new Map();
|
|
44
|
-
function cacheKey() {
|
|
45
|
-
return getActiveProfile() ?? '__default__';
|
|
46
|
-
}
|
|
47
|
-
/** Force the next loadCache() call to re-read from disk. Used in tests. */
|
|
48
|
-
export function resetListCache() {
|
|
49
|
-
_listCacheByProfile.clear();
|
|
50
|
-
}
|
|
51
|
-
/** Force the next loadStatusCache() call to re-read from disk. Used in tests. */
|
|
52
|
-
export function resetStatusCache() {
|
|
53
|
-
_statusCacheByProfile.clear();
|
|
54
|
-
}
|
|
55
|
-
export function loadCache() {
|
|
56
|
-
const key = cacheKey();
|
|
57
|
-
if (_listCacheByProfile.has(key))
|
|
58
|
-
return _listCacheByProfile.get(key);
|
|
59
|
-
const file = cacheFilePath();
|
|
60
|
-
if (!fs.existsSync(file)) {
|
|
61
|
-
_listCacheByProfile.set(key, null);
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
const raw = fs.readFileSync(file, 'utf-8');
|
|
66
|
-
const cache = JSON.parse(raw);
|
|
67
|
-
if (!cache || typeof cache.devices !== 'object' || cache.devices === null) {
|
|
68
|
-
_listCacheByProfile.set(key, null);
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
_listCacheByProfile.set(key, cache);
|
|
72
|
-
return cache;
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
_listCacheByProfile.set(key, null);
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
export function getCachedDevice(deviceId) {
|
|
80
|
-
const cache = loadCache();
|
|
81
|
-
if (!cache)
|
|
82
|
-
return null;
|
|
83
|
-
return cache.devices[deviceId] ?? null;
|
|
84
|
-
}
|
|
85
|
-
/** Build a deviceId -> type map from the metadata cache. */
|
|
86
|
-
export function getCachedTypeMap(deviceIds) {
|
|
87
|
-
const cache = loadCache();
|
|
88
|
-
const out = new Map();
|
|
89
|
-
if (!cache)
|
|
90
|
-
return out;
|
|
91
|
-
if (deviceIds) {
|
|
92
|
-
for (const id of deviceIds) {
|
|
93
|
-
const entry = cache.devices[id];
|
|
94
|
-
if (entry?.type)
|
|
95
|
-
out.set(id, entry.type);
|
|
96
|
-
}
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
for (const [deviceId, entry] of Object.entries(cache.devices)) {
|
|
100
|
-
if (entry.type)
|
|
101
|
-
out.set(deviceId, entry.type);
|
|
102
|
-
}
|
|
103
|
-
return out;
|
|
104
|
-
}
|
|
105
|
-
export function updateCacheFromDeviceList(body) {
|
|
106
|
-
const devices = {};
|
|
107
|
-
for (const d of body.deviceList) {
|
|
108
|
-
if (!d.deviceId || !d.deviceType)
|
|
109
|
-
continue;
|
|
110
|
-
devices[d.deviceId] = {
|
|
111
|
-
type: d.deviceType,
|
|
112
|
-
name: d.deviceName,
|
|
113
|
-
category: 'physical',
|
|
114
|
-
hubDeviceId: d.hubDeviceId,
|
|
115
|
-
enableCloudService: d.enableCloudService,
|
|
116
|
-
roomID: d.roomID,
|
|
117
|
-
roomName: d.roomName,
|
|
118
|
-
familyName: d.familyName,
|
|
119
|
-
controlType: d.controlType,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
for (const d of body.infraredRemoteList) {
|
|
123
|
-
if (!d.deviceId)
|
|
124
|
-
continue;
|
|
125
|
-
devices[d.deviceId] = {
|
|
126
|
-
type: d.remoteType,
|
|
127
|
-
name: d.deviceName,
|
|
128
|
-
category: 'ir',
|
|
129
|
-
hubDeviceId: d.hubDeviceId,
|
|
130
|
-
controlType: d.controlType,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
const cache = {
|
|
134
|
-
lastUpdated: new Date().toISOString(),
|
|
135
|
-
devices,
|
|
136
|
-
};
|
|
137
|
-
try {
|
|
138
|
-
const file = cacheFilePath();
|
|
139
|
-
const dir = path.dirname(file);
|
|
140
|
-
if (!fs.existsSync(dir))
|
|
141
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
142
|
-
fs.writeFileSync(file, JSON.stringify(cache, null, 2), { mode: 0o600 });
|
|
143
|
-
_listCacheByProfile.set(cacheKey(), cache);
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// Cache write failures must not break the command that triggered them.
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
export function clearCache() {
|
|
150
|
-
const file = cacheFilePath();
|
|
151
|
-
if (fs.existsSync(file))
|
|
152
|
-
fs.unlinkSync(file);
|
|
153
|
-
_listCacheByProfile.set(cacheKey(), null);
|
|
154
|
-
}
|
|
155
|
-
// ---- Device list freshness -------------------------------------------------
|
|
156
|
-
/** Age of the on-disk list cache in ms, or null if there is no cache. */
|
|
157
|
-
export function listCacheAgeMs(now = Date.now()) {
|
|
158
|
-
const cache = loadCache();
|
|
159
|
-
if (!cache)
|
|
160
|
-
return null;
|
|
161
|
-
const ts = Date.parse(cache.lastUpdated);
|
|
162
|
-
if (!Number.isFinite(ts))
|
|
163
|
-
return null;
|
|
164
|
-
return Math.max(0, now - ts);
|
|
165
|
-
}
|
|
166
|
-
/** True when the on-disk list cache is present and younger than `ttlMs`. */
|
|
167
|
-
export function isListCacheFresh(ttlMs, now = Date.now()) {
|
|
168
|
-
if (!ttlMs || ttlMs <= 0)
|
|
169
|
-
return false;
|
|
170
|
-
const age = listCacheAgeMs(now);
|
|
171
|
-
return age !== null && age < ttlMs;
|
|
172
|
-
}
|
|
173
|
-
function statusCacheFilePath() {
|
|
174
|
-
const override = getConfigPath();
|
|
175
|
-
const dir = override
|
|
176
|
-
? path.dirname(path.resolve(override))
|
|
177
|
-
: scopedCacheDir(path.join(os.homedir(), '.switchbot'));
|
|
178
|
-
return path.join(dir, 'status.json');
|
|
179
|
-
}
|
|
180
|
-
export function loadStatusCache() {
|
|
181
|
-
const key = cacheKey();
|
|
182
|
-
if (_statusCacheByProfile.has(key))
|
|
183
|
-
return _statusCacheByProfile.get(key);
|
|
184
|
-
const file = statusCacheFilePath();
|
|
185
|
-
if (!fs.existsSync(file)) {
|
|
186
|
-
const empty = { entries: {} };
|
|
187
|
-
_statusCacheByProfile.set(key, empty);
|
|
188
|
-
return empty;
|
|
189
|
-
}
|
|
190
|
-
try {
|
|
191
|
-
const raw = fs.readFileSync(file, 'utf-8');
|
|
192
|
-
const parsed = JSON.parse(raw);
|
|
193
|
-
if (!parsed || typeof parsed.entries !== 'object' || parsed.entries === null) {
|
|
194
|
-
const empty = { entries: {} };
|
|
195
|
-
_statusCacheByProfile.set(key, empty);
|
|
196
|
-
return empty;
|
|
197
|
-
}
|
|
198
|
-
_statusCacheByProfile.set(key, parsed);
|
|
199
|
-
return parsed;
|
|
200
|
-
}
|
|
201
|
-
catch {
|
|
202
|
-
const empty = { entries: {} };
|
|
203
|
-
_statusCacheByProfile.set(key, empty);
|
|
204
|
-
return empty;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function saveStatusCache(cache) {
|
|
208
|
-
_statusCacheByProfile.set(cacheKey(), cache);
|
|
209
|
-
try {
|
|
210
|
-
const file = statusCacheFilePath();
|
|
211
|
-
const dir = path.dirname(file);
|
|
212
|
-
if (!fs.existsSync(dir))
|
|
213
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
214
|
-
fs.writeFileSync(file, JSON.stringify(cache, null, 2), { mode: 0o600 });
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
/* best-effort */
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/** Read a status entry; returns null when missing or older than `ttlMs`. */
|
|
221
|
-
export function getCachedStatus(deviceId, ttlMs, now = Date.now()) {
|
|
222
|
-
if (!ttlMs || ttlMs <= 0)
|
|
223
|
-
return null;
|
|
224
|
-
const cache = loadStatusCache();
|
|
225
|
-
const entry = cache.entries[deviceId];
|
|
226
|
-
if (!entry)
|
|
227
|
-
return null;
|
|
228
|
-
const ts = Date.parse(entry.fetchedAt);
|
|
229
|
-
if (!Number.isFinite(ts))
|
|
230
|
-
return null;
|
|
231
|
-
if (now - ts >= ttlMs)
|
|
232
|
-
return null;
|
|
233
|
-
return entry.body;
|
|
234
|
-
}
|
|
235
|
-
/** Evict status entries older than max(ttlMs × 10, 24 h) to bound file growth. */
|
|
236
|
-
function evictExpiredStatusEntries(cache, ttlMs, now = Date.now()) {
|
|
237
|
-
const cutoff = now - Math.max(ttlMs * 10, 24 * 60 * 60 * 1000);
|
|
238
|
-
for (const id of Object.keys(cache.entries)) {
|
|
239
|
-
const entry = cache.entries[id];
|
|
240
|
-
const ts = Date.parse(entry.fetchedAt);
|
|
241
|
-
if (!Number.isFinite(ts) || ts < cutoff)
|
|
242
|
-
delete cache.entries[id];
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
export function setCachedStatus(deviceId, body, now = new Date(), ttlMsForGc = DEFAULT_STATUS_GC_TTL_MS) {
|
|
246
|
-
const cache = loadStatusCache();
|
|
247
|
-
cache.entries[deviceId] = {
|
|
248
|
-
fetchedAt: now.toISOString(),
|
|
249
|
-
body,
|
|
250
|
-
};
|
|
251
|
-
evictExpiredStatusEntries(cache, ttlMsForGc, now.getTime());
|
|
252
|
-
saveStatusCache(cache);
|
|
253
|
-
}
|
|
254
|
-
export function clearStatusCache() {
|
|
255
|
-
const file = statusCacheFilePath();
|
|
256
|
-
if (fs.existsSync(file))
|
|
257
|
-
fs.unlinkSync(file);
|
|
258
|
-
_statusCacheByProfile.set(cacheKey(), { entries: {} });
|
|
259
|
-
}
|
|
260
|
-
export function describeCache(now = Date.now()) {
|
|
261
|
-
const listFile = cacheFilePath();
|
|
262
|
-
const listCache = loadCache();
|
|
263
|
-
const listExists = fs.existsSync(listFile);
|
|
264
|
-
const list = {
|
|
265
|
-
path: listFile,
|
|
266
|
-
exists: listExists,
|
|
267
|
-
};
|
|
268
|
-
if (listCache) {
|
|
269
|
-
list.lastUpdated = listCache.lastUpdated;
|
|
270
|
-
const ts = Date.parse(listCache.lastUpdated);
|
|
271
|
-
if (Number.isFinite(ts))
|
|
272
|
-
list.ageMs = Math.max(0, now - ts);
|
|
273
|
-
list.deviceCount = Object.keys(listCache.devices).length;
|
|
274
|
-
}
|
|
275
|
-
const statusFile = statusCacheFilePath();
|
|
276
|
-
const statusExists = fs.existsSync(statusFile);
|
|
277
|
-
const statusCache = loadStatusCache();
|
|
278
|
-
const entries = Object.values(statusCache.entries);
|
|
279
|
-
const status = {
|
|
280
|
-
path: statusFile,
|
|
281
|
-
exists: statusExists,
|
|
282
|
-
entryCount: entries.length,
|
|
283
|
-
};
|
|
284
|
-
if (entries.length > 0) {
|
|
285
|
-
const sorted = entries
|
|
286
|
-
.map((e) => e.fetchedAt)
|
|
287
|
-
.filter((s) => typeof s === 'string')
|
|
288
|
-
.sort();
|
|
289
|
-
status.oldestFetchedAt = sorted[0];
|
|
290
|
-
status.newestFetchedAt = sorted[sorted.length - 1];
|
|
291
|
-
}
|
|
292
|
-
return { list, status };
|
|
293
|
-
}
|
|
294
|
-
//# sourceMappingURL=cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/devices/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oEAAoE;AACpE,MAAM,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO;AAwC7D,SAAS,aAAa;IACpB,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ;QAClB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AACxC,CAAC;AAED,iFAAiF;AACjF,8EAA8E;AAC9E,6EAA6E;AAC7E,qDAAqD;AACrD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA8B,CAAC;AAClE,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAuB,CAAC;AAE7D,SAAS,QAAQ;IACf,OAAO,gBAAgB,EAAE,IAAI,aAAa,CAAC;AAC7C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc;IAC5B,mBAAmB,CAAC,KAAK,EAAE,CAAC;AAC9B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,gBAAgB;IAC9B,qBAAqB,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IACvE,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1E,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,gBAAgB,CAAC,SAA4B;IAC3D,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IAEvB,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,KAAK,EAAE,IAAI;gBAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,IAAI,KAAK,CAAC,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAyB;IACjE,MAAM,OAAO,GAAiC,EAAE,CAAC;IAEjD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU;YAAE,SAAS;QAC3C,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG;YACpB,IAAI,EAAE,CAAC,CAAC,UAAU;YAClB,IAAI,EAAE,CAAC,CAAC,UAAU;YAClB,QAAQ,EAAE,UAAU;YACpB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,kBAAkB,EAAE,CAAC,CAAC,kBAAkB;YACxC,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,CAAC,QAAQ;YAAE,SAAS;QAC1B,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG;YACpB,IAAI,EAAE,CAAC,CAAC,UAAU;YAClB,IAAI,EAAE,CAAC,CAAC,UAAU;YAClB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAgB;QACzB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,OAAO;KACR,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxE,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7C,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,+EAA+E;AAE/E,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC7C,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC9D,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC;AACrC,CAAC;AAqBD,SAAS,mBAAmB;IAC1B,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ;QAClB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IAC3E,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC9B,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QAC9C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7E,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC9B,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACtC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC9B,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAkB;IACzC,qBAAqB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,KAAa,EACb,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAEhB,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,GAAG,GAAG,EAAE,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB,CAAC;AAED,kFAAkF;AAClF,SAAS,yBAAyB,CAAC,KAAkB,EAAE,KAAa,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACpF,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/D,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,MAAM;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAA6B,EAC7B,GAAG,GAAG,IAAI,IAAI,EAAE,EAChB,UAAU,GAAG,wBAAwB;IAErC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG;QACxB,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;QAC5B,IAAI;KACL,CAAC;IACF,yBAAyB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5D,eAAe,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7C,qBAAqB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;AACzD,CAAC;AAoBD,MAAM,UAAU,aAAa,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC5C,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAyB;QACjC,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,UAAU;KACnB,CAAC;IACF,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAC3D,CAAC;IAED,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAC;IACzC,MAAM,YAAY,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,MAAM,GAA2B;QACrC,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE,OAAO,CAAC,MAAM;KAC3B,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,OAAO;aACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;aACvB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;aACjD,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static catalog of SwitchBot device types, control commands and status fields.
|
|
3
|
-
* Sourced from https://github.com/OpenWonderLabs/SwitchBotAPI — keep in sync
|
|
4
|
-
* when the upstream API adds new device types.
|
|
5
|
-
*
|
|
6
|
-
* Field conventions:
|
|
7
|
-
* - CommandSpec.idempotent: repeat-safe — calling it N times ends in the
|
|
8
|
-
* same state as calling it once (turnOn, setBrightness 50). Agents can
|
|
9
|
-
* retry these freely. Counter-examples: toggle, press, volumeAdd.
|
|
10
|
-
* - CommandSpec.safetyTier: explicit action safety classification. See
|
|
11
|
-
* SafetyTier for the 5-tier enum. Built-in entries set this on the
|
|
12
|
-
* destructive tier; other tiers are derived (see deriveSafetyTier).
|
|
13
|
-
* - DeviceCatalogEntry.role: functional grouping for filter/search
|
|
14
|
-
* ("all lighting", "all security"). Does not affect API behavior.
|
|
15
|
-
* - DeviceCatalogEntry.readOnly: the device has no control commands; it
|
|
16
|
-
* can only be queried via 'devices status'.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* Catalog shape version. Bump when any of the exported interfaces
|
|
20
|
-
* (CommandSpec / DeviceCatalogEntry / SafetyTier) gain/lose/rename a
|
|
21
|
-
* load-bearing field. The agent-bootstrap payload's schemaVersion must
|
|
22
|
-
* stay pinned to this value; `doctor` fails the `catalog-schema` check
|
|
23
|
-
* when they drift.
|
|
24
|
-
*/
|
|
25
|
-
export declare const CATALOG_SCHEMA_VERSION = "1.0";
|
|
26
|
-
/**
|
|
27
|
-
* Safety classification for catalog commands.
|
|
28
|
-
*
|
|
29
|
-
* - 'read' —— Read-only query (status fetch). Reserved for v2.8+
|
|
30
|
-
* `statusQueries` expansion; no command uses it today.
|
|
31
|
-
* - 'mutation' —— Causes a state change but is reversible/idempotent
|
|
32
|
-
* (turnOn/Off, setBrightness, setPosition).
|
|
33
|
-
* - 'ir-fire-forget' —— IR command (no reply/ack) or customize IR button.
|
|
34
|
-
* Fire-and-forget; reversibility depends on device.
|
|
35
|
-
* - 'destructive' —— Hard or unsafe to reverse; physical-world side effects
|
|
36
|
-
* (unlock, garage open, deleteKey). Needs confirmation.
|
|
37
|
-
* - 'maintenance' —— Factory reset / firmware update / deep calibrate.
|
|
38
|
-
* Reserved; the SwitchBot API exposes no such endpoint
|
|
39
|
-
* today, so no command uses it.
|
|
40
|
-
*/
|
|
41
|
-
export type SafetyTier = 'read' | 'mutation' | 'ir-fire-forget' | 'destructive' | 'maintenance';
|
|
42
|
-
export interface CommandSpec {
|
|
43
|
-
command: string;
|
|
44
|
-
parameter: string;
|
|
45
|
-
description: string;
|
|
46
|
-
commandType?: 'command' | 'customize';
|
|
47
|
-
idempotent?: boolean;
|
|
48
|
-
/**
|
|
49
|
-
* Explicit safety tier. When omitted, deriveSafetyTier() infers:
|
|
50
|
-
* commandType: 'customize' or entry.category === 'ir' → 'ir-fire-forget'
|
|
51
|
-
* otherwise → 'mutation'
|
|
52
|
-
*/
|
|
53
|
-
safetyTier?: SafetyTier;
|
|
54
|
-
/** One sentence explaining *why* this command needs caution — used in guard errors. */
|
|
55
|
-
safetyReason?: string;
|
|
56
|
-
exampleParams?: string[];
|
|
57
|
-
}
|
|
58
|
-
/** Coarse functional role — helpful for cross-type selection in agents. */
|
|
59
|
-
export type DeviceRole = 'lighting' | 'climate' | 'security' | 'media' | 'sensor' | 'cleaning' | 'curtain' | 'fan' | 'power' | 'hub' | 'other';
|
|
60
|
-
export interface DeviceCatalogEntry {
|
|
61
|
-
type: string;
|
|
62
|
-
category: 'physical' | 'ir';
|
|
63
|
-
description?: string;
|
|
64
|
-
aliases?: string[];
|
|
65
|
-
commands: CommandSpec[];
|
|
66
|
-
statusFields?: string[];
|
|
67
|
-
/**
|
|
68
|
-
* P11: strongly-typed read-only queries powering the 'read' safety tier.
|
|
69
|
-
* When omitted, deriveStatusQueries() produces equivalent entries from
|
|
70
|
-
* `statusFields`. Use this to override descriptions or attach examples.
|
|
71
|
-
*/
|
|
72
|
-
statusQueries?: ReadOnlyQuerySpec[];
|
|
73
|
-
role?: DeviceRole;
|
|
74
|
-
readOnly?: boolean;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* P11: a single read-only query against a device. `endpoint: 'status'` is
|
|
78
|
-
* the normal /devices/{id}/status call; 'keys' reads lock keypad entries;
|
|
79
|
-
* 'webhook' reads the server-side webhook event subscription. All three
|
|
80
|
-
* are safe to call at any time — they never mutate state.
|
|
81
|
-
*/
|
|
82
|
-
export interface ReadOnlyQuerySpec {
|
|
83
|
-
field: string;
|
|
84
|
-
description: string;
|
|
85
|
-
endpoint: 'status' | 'keys' | 'webhook';
|
|
86
|
-
safetyTier: 'read';
|
|
87
|
-
example?: unknown;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* P11: derive the read-only query list for an entry. If the entry has
|
|
91
|
-
* explicit `statusQueries`, return them as-is; otherwise synthesize one
|
|
92
|
-
* ReadOnlyQuerySpec per `statusFields` entry, all keyed to the `status`
|
|
93
|
-
* endpoint. IR-category entries have no status channel so return [].
|
|
94
|
-
*/
|
|
95
|
-
export declare function deriveStatusQueries(entry: DeviceCatalogEntry): ReadOnlyQuerySpec[];
|
|
96
|
-
export declare const DEVICE_CATALOG: DeviceCatalogEntry[];
|
|
97
|
-
/** Find a catalog entry by exact name, alias, or case-insensitive substring. */
|
|
98
|
-
export declare function findCatalogEntry(query: string): DeviceCatalogEntry | DeviceCatalogEntry[] | null;
|
|
99
|
-
/**
|
|
100
|
-
* Derive the safety tier for a catalog command, honouring an explicit
|
|
101
|
-
* `safetyTier` when present and falling back to heuristic inference.
|
|
102
|
-
*
|
|
103
|
-
* The inference order is:
|
|
104
|
-
* 1. Explicit `spec.safetyTier`.
|
|
105
|
-
* 2. IR context (customize command OR entry.category === 'ir')
|
|
106
|
-
* → `'ir-fire-forget'`.
|
|
107
|
-
* 3. Default → `'mutation'`.
|
|
108
|
-
*/
|
|
109
|
-
export declare function deriveSafetyTier(spec: CommandSpec, entry?: Pick<DeviceCatalogEntry, 'category'>): SafetyTier;
|
|
110
|
-
/** Read the safety reason for a command. */
|
|
111
|
-
export declare function getCommandSafetyReason(spec: CommandSpec): string | null;
|
|
112
|
-
/**
|
|
113
|
-
* Pick up to 3 non-destructive, idempotent commands an agent can safely invoke
|
|
114
|
-
* to explore or exercise a device. Used by `devices describe --json` to hint
|
|
115
|
-
* at concrete next steps.
|
|
116
|
-
*/
|
|
117
|
-
export declare function suggestedActions(entry: DeviceCatalogEntry): Array<{
|
|
118
|
-
command: string;
|
|
119
|
-
parameter?: string;
|
|
120
|
-
description: string;
|
|
121
|
-
}>;
|
|
122
|
-
export interface CatalogOverlayEntry extends Partial<DeviceCatalogEntry> {
|
|
123
|
-
type: string;
|
|
124
|
-
remove?: boolean;
|
|
125
|
-
}
|
|
126
|
-
export interface OverlayLoadResult {
|
|
127
|
-
path: string;
|
|
128
|
-
exists: boolean;
|
|
129
|
-
entries: CatalogOverlayEntry[];
|
|
130
|
-
error?: string;
|
|
131
|
-
}
|
|
132
|
-
export declare function getCatalogOverlayPath(): string;
|
|
133
|
-
/** Read the overlay file. Never throws — returns `error` on bad files. */
|
|
134
|
-
export declare function loadCatalogOverlay(): OverlayLoadResult;
|
|
135
|
-
/** Clear the overlay cache (test helper; also useful for `catalog refresh`). */
|
|
136
|
-
export declare function resetCatalogOverlayCache(): void;
|
|
137
|
-
/** Merge built-in catalog with the on-disk overlay. */
|
|
138
|
-
export declare function getEffectiveCatalog(): DeviceCatalogEntry[];
|