@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.
- package/README.md +174 -18
- package/dist/api/client.d.ts +7 -1
- package/dist/api/client.js +44 -8
- package/dist/api/client.js.map +1 -1
- package/dist/commands/batch.d.ts +2 -0
- package/dist/commands/batch.js +252 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/cache.d.ts +2 -0
- package/dist/commands/cache.js +108 -0
- package/dist/commands/cache.js.map +1 -0
- package/dist/commands/capabilities.d.ts +2 -0
- package/dist/commands/capabilities.js +91 -0
- package/dist/commands/capabilities.js.map +1 -0
- package/dist/commands/catalog.d.ts +2 -0
- package/dist/commands/catalog.js +291 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/config.js +123 -10
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/device-meta.d.ts +2 -0
- package/dist/commands/device-meta.js +142 -0
- package/dist/commands/device-meta.js.map +1 -0
- package/dist/commands/devices.js +272 -152
- package/dist/commands/devices.js.map +1 -1
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +147 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.d.ts +15 -0
- package/dist/commands/events.js +188 -0
- package/dist/commands/events.js.map +1 -0
- package/dist/commands/expand.d.ts +2 -0
- package/dist/commands/expand.js +192 -0
- package/dist/commands/expand.js.map +1 -0
- package/dist/commands/explain.d.ts +2 -0
- package/dist/commands/explain.js +137 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/history.d.ts +2 -0
- package/dist/commands/history.js +104 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/mcp.d.ts +4 -0
- package/dist/commands/mcp.js +386 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/plan.d.ts +38 -0
- package/dist/commands/plan.js +356 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/quota.d.ts +2 -0
- package/dist/commands/quota.js +77 -0
- package/dist/commands/quota.js.map +1 -0
- package/dist/commands/scenes.js +19 -13
- package/dist/commands/scenes.js.map +1 -1
- package/dist/commands/schema.d.ts +2 -0
- package/dist/commands/schema.js +77 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +161 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/webhook.js +37 -22
- package/dist/commands/webhook.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.js +32 -6
- package/dist/config.js.map +1 -1
- package/dist/devices/cache.d.ts +50 -0
- package/dist/devices/cache.js +152 -1
- package/dist/devices/cache.js.map +1 -1
- package/dist/devices/catalog.d.ts +49 -0
- package/dist/devices/catalog.js +362 -92
- package/dist/devices/catalog.js.map +1 -1
- package/dist/devices/device-meta.d.ts +15 -0
- package/dist/devices/device-meta.js +52 -0
- package/dist/devices/device-meta.js.map +1 -0
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/devices.d.ts +144 -0
- package/dist/lib/devices.js +329 -0
- package/dist/lib/devices.js.map +1 -0
- package/dist/lib/scenes.d.ts +7 -0
- package/dist/lib/scenes.js +11 -0
- package/dist/lib/scenes.js.map +1 -0
- package/dist/utils/audit.d.ts +13 -0
- package/dist/utils/audit.js +43 -0
- package/dist/utils/audit.js.map +1 -0
- package/dist/utils/filter.d.ts +45 -0
- package/dist/utils/filter.js +96 -0
- package/dist/utils/filter.js.map +1 -0
- package/dist/utils/flags.d.ts +42 -0
- package/dist/utils/flags.js +108 -0
- package/dist/utils/flags.js.map +1 -1
- package/dist/utils/format.d.ts +9 -0
- package/dist/utils/format.js +109 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/name-resolver.d.ts +17 -0
- package/dist/utils/name-resolver.js +78 -0
- package/dist/utils/name-resolver.js.map +1 -0
- package/dist/utils/output.d.ts +18 -0
- package/dist/utils/output.js +66 -6
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/quota.d.ts +48 -0
- package/dist/utils/quota.js +144 -0
- package/dist/utils/quota.js.map +1 -0
- package/dist/utils/retry.d.ts +23 -0
- package/dist/utils/retry.js +60 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/string.d.ts +2 -0
- package/dist/utils/string.js +23 -0
- package/dist/utils/string.js.map +1 -0
- package/package.json +4 -1
package/dist/commands/config.js
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { saveConfig, showConfig, listProfiles } from '../config.js';
|
|
4
|
+
import { isJsonMode, printJson } from '../utils/output.js';
|
|
2
5
|
import chalk from 'chalk';
|
|
6
|
+
function parseEnvFile(file) {
|
|
7
|
+
const out = {};
|
|
8
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
9
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
10
|
+
const trimmed = line.trim();
|
|
11
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
12
|
+
continue;
|
|
13
|
+
const eq = trimmed.indexOf('=');
|
|
14
|
+
if (eq === -1)
|
|
15
|
+
continue;
|
|
16
|
+
const key = trimmed.slice(0, eq).trim();
|
|
17
|
+
let val = trimmed.slice(eq + 1).trim();
|
|
18
|
+
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
|
|
19
|
+
val = val.slice(1, -1);
|
|
20
|
+
}
|
|
21
|
+
if (key === 'SWITCHBOT_TOKEN')
|
|
22
|
+
out.token = val;
|
|
23
|
+
else if (key === 'SWITCHBOT_SECRET')
|
|
24
|
+
out.secret = val;
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
function readFromOp(ref) {
|
|
29
|
+
// 1Password CLI: `op read "op://vault/item/field"` → single line on stdout
|
|
30
|
+
const stdout = execFileSync('op', ['read', ref], { encoding: 'utf-8' });
|
|
31
|
+
return stdout.trim();
|
|
32
|
+
}
|
|
3
33
|
export function registerConfigCommand(program) {
|
|
4
34
|
const config = program
|
|
5
35
|
.command('config')
|
|
@@ -7,25 +37,92 @@ export function registerConfigCommand(program) {
|
|
|
7
37
|
.addHelpText('after', `
|
|
8
38
|
Credential priority:
|
|
9
39
|
1. Environment variables: SWITCHBOT_TOKEN and SWITCHBOT_SECRET
|
|
10
|
-
2.
|
|
40
|
+
2. --config <path> (explicit file override)
|
|
41
|
+
3. --profile <name> → ~/.switchbot/profiles/<name>.json
|
|
42
|
+
4. ~/.switchbot/config.json (default)
|
|
11
43
|
|
|
12
44
|
Obtain your token/secret from the SwitchBot mobile app:
|
|
13
45
|
Profile → Preferences → Developer Options → Get Token
|
|
14
46
|
`);
|
|
15
47
|
config
|
|
16
48
|
.command('set-token')
|
|
17
|
-
.description('Save token and secret
|
|
18
|
-
.argument('
|
|
19
|
-
.argument('
|
|
49
|
+
.description('Save token and secret (mode 0600). Use --profile to target a named profile.')
|
|
50
|
+
.argument('[token]', 'API token; omit when using --from-env-file / --from-op')
|
|
51
|
+
.argument('[secret]', 'API client secret; omit when using --from-env-file / --from-op')
|
|
52
|
+
.option('--from-env-file <path>', 'Read SWITCHBOT_TOKEN and SWITCHBOT_SECRET from a dotenv file')
|
|
53
|
+
.option('--from-op <tokenRef>', 'Read token via 1Password CLI (op read). Pair with --op-secret <ref>')
|
|
54
|
+
.option('--op-secret <secretRef>', '1Password reference for the secret, used with --from-op')
|
|
20
55
|
.addHelpText('after', `
|
|
21
|
-
|
|
22
|
-
$ switchbot config set-token
|
|
56
|
+
Examples:
|
|
57
|
+
$ switchbot config set-token <token> <secret>
|
|
58
|
+
$ switchbot --profile work config set-token <token> <secret>
|
|
59
|
+
$ switchbot config set-token --from-env-file ./.env
|
|
60
|
+
$ switchbot config set-token --from-op op://vault/switchbot/token --op-secret op://vault/switchbot/secret
|
|
23
61
|
|
|
24
|
-
|
|
62
|
+
Files are written with mode 0600. Profiles live under ~/.switchbot/profiles/<name>.json.
|
|
25
63
|
`)
|
|
26
|
-
.action((
|
|
64
|
+
.action(async (tokenArg, secretArg, options) => {
|
|
65
|
+
let token = tokenArg;
|
|
66
|
+
let secret = secretArg;
|
|
67
|
+
if (options.fromEnvFile) {
|
|
68
|
+
if (!fs.existsSync(options.fromEnvFile)) {
|
|
69
|
+
const msg = `--from-env-file: file not found: ${options.fromEnvFile}`;
|
|
70
|
+
if (isJsonMode()) {
|
|
71
|
+
console.error(JSON.stringify({ error: { code: 2, kind: 'usage', message: msg } }));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.error(msg);
|
|
75
|
+
}
|
|
76
|
+
process.exit(2);
|
|
77
|
+
}
|
|
78
|
+
const parsed = parseEnvFile(options.fromEnvFile);
|
|
79
|
+
token = token ?? parsed.token;
|
|
80
|
+
secret = secret ?? parsed.secret;
|
|
81
|
+
}
|
|
82
|
+
if (options.fromOp) {
|
|
83
|
+
if (!options.opSecret) {
|
|
84
|
+
const msg = '--from-op requires --op-secret <ref> for the secret reference.';
|
|
85
|
+
if (isJsonMode()) {
|
|
86
|
+
console.error(JSON.stringify({ error: { code: 2, kind: 'usage', message: msg } }));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.error(msg);
|
|
90
|
+
}
|
|
91
|
+
process.exit(2);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
token = readFromOp(options.fromOp);
|
|
95
|
+
secret = readFromOp(options.opSecret);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
const msg = `1Password CLI read failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
99
|
+
if (isJsonMode()) {
|
|
100
|
+
console.error(JSON.stringify({ error: { code: 1, kind: 'runtime', message: msg, hint: 'Ensure the "op" CLI is installed and authenticated (op signin).' } }));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.error(msg);
|
|
104
|
+
console.error('Ensure the "op" CLI is installed and authenticated (op signin).');
|
|
105
|
+
}
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!token || !secret) {
|
|
110
|
+
const msg = 'Missing token/secret. Provide positional arguments or use --from-env-file / --from-op.';
|
|
111
|
+
if (isJsonMode()) {
|
|
112
|
+
console.error(JSON.stringify({ error: { code: 2, kind: 'usage', message: msg } }));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.error(msg);
|
|
116
|
+
}
|
|
117
|
+
process.exit(2);
|
|
118
|
+
}
|
|
27
119
|
saveConfig(token, secret);
|
|
28
|
-
|
|
120
|
+
if (isJsonMode()) {
|
|
121
|
+
printJson({ ok: true, message: 'credentials saved' });
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log(chalk.green('✓ Credentials saved'));
|
|
125
|
+
}
|
|
29
126
|
});
|
|
30
127
|
config
|
|
31
128
|
.command('show')
|
|
@@ -33,5 +130,21 @@ Note: the file is written with mode 0600 so only your user can read it.
|
|
|
33
130
|
.action(() => {
|
|
34
131
|
showConfig();
|
|
35
132
|
});
|
|
133
|
+
config
|
|
134
|
+
.command('list-profiles')
|
|
135
|
+
.description('List named profiles under ~/.switchbot/profiles/')
|
|
136
|
+
.action(() => {
|
|
137
|
+
const profiles = listProfiles();
|
|
138
|
+
if (isJsonMode()) {
|
|
139
|
+
printJson({ profiles });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (profiles.length === 0) {
|
|
143
|
+
console.log('No profiles. Create one with: switchbot --profile <name> config set-token ...');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
for (const p of profiles)
|
|
147
|
+
console.log(p);
|
|
148
|
+
});
|
|
36
149
|
}
|
|
37
150
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { handleError, isJsonMode, printJson, printTable, UsageError } from '../utils/output.js';
|
|
2
|
+
import { loadDeviceMeta, setDeviceMeta, clearDeviceMeta, getDeviceMeta, getMetaFilePath, } from '../devices/device-meta.js';
|
|
3
|
+
export function registerDevicesMetaCommand(devices) {
|
|
4
|
+
const meta = devices
|
|
5
|
+
.command('meta')
|
|
6
|
+
.description('Manage local device metadata (alias, hide, notes) stored in ~/.switchbot/device-meta.json');
|
|
7
|
+
// switchbot devices meta set <deviceId>
|
|
8
|
+
meta
|
|
9
|
+
.command('set')
|
|
10
|
+
.description('Set local metadata for a device (alias, hide/show, notes)')
|
|
11
|
+
.argument('<deviceId>', 'Target device ID')
|
|
12
|
+
.option('--alias <name>', 'Local alias for the device (used with --name flag)')
|
|
13
|
+
.option('--hide', 'Hide this device from "devices list"')
|
|
14
|
+
.option('--show', 'Un-hide this device')
|
|
15
|
+
.option('--notes <text>', 'Freeform notes shown in "devices describe"')
|
|
16
|
+
.action((deviceId, options) => {
|
|
17
|
+
try {
|
|
18
|
+
if (options.hide && options.show) {
|
|
19
|
+
throw new UsageError('--hide and --show cannot be used together.');
|
|
20
|
+
}
|
|
21
|
+
if (!options.alias && !options.hide && !options.show && !options.notes) {
|
|
22
|
+
throw new UsageError('Specify at least one of: --alias, --hide, --show, --notes');
|
|
23
|
+
}
|
|
24
|
+
const patch = {};
|
|
25
|
+
if (options.alias !== undefined)
|
|
26
|
+
patch.alias = options.alias;
|
|
27
|
+
if (options.notes !== undefined)
|
|
28
|
+
patch.notes = options.notes;
|
|
29
|
+
if (options.hide)
|
|
30
|
+
patch.hidden = true;
|
|
31
|
+
if (options.show)
|
|
32
|
+
patch.hidden = false;
|
|
33
|
+
setDeviceMeta(deviceId, patch);
|
|
34
|
+
const updated = getDeviceMeta(deviceId);
|
|
35
|
+
if (isJsonMode()) {
|
|
36
|
+
printJson({ ok: true, deviceId, meta: updated });
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`✓ Metadata updated for ${deviceId}`);
|
|
40
|
+
if (updated?.alias)
|
|
41
|
+
console.log(` alias: ${updated.alias}`);
|
|
42
|
+
if (updated?.hidden)
|
|
43
|
+
console.log(` hidden: true`);
|
|
44
|
+
if (updated?.notes)
|
|
45
|
+
console.log(` notes: ${updated.notes}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
handleError(error);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// switchbot devices meta get <deviceId>
|
|
53
|
+
meta
|
|
54
|
+
.command('get')
|
|
55
|
+
.description('Show local metadata for a device')
|
|
56
|
+
.argument('<deviceId>', 'Target device ID')
|
|
57
|
+
.action((deviceId) => {
|
|
58
|
+
try {
|
|
59
|
+
const entry = getDeviceMeta(deviceId);
|
|
60
|
+
if (!entry) {
|
|
61
|
+
if (isJsonMode()) {
|
|
62
|
+
printJson({ deviceId, meta: null });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(`No local metadata for ${deviceId}`);
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (isJsonMode()) {
|
|
70
|
+
printJson({ deviceId, meta: entry });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
if (entry.alias)
|
|
74
|
+
console.log(`alias: ${entry.alias}`);
|
|
75
|
+
if (entry.hidden !== undefined)
|
|
76
|
+
console.log(`hidden: ${entry.hidden}`);
|
|
77
|
+
if (entry.notes)
|
|
78
|
+
console.log(`notes: ${entry.notes}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
handleError(error);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
// switchbot devices meta list
|
|
86
|
+
meta
|
|
87
|
+
.command('list')
|
|
88
|
+
.description('List all devices with local metadata')
|
|
89
|
+
.option('--hidden-only', 'Show only hidden devices')
|
|
90
|
+
.action((options) => {
|
|
91
|
+
try {
|
|
92
|
+
const file = loadDeviceMeta();
|
|
93
|
+
let entries = Object.entries(file.devices);
|
|
94
|
+
if (options.hiddenOnly)
|
|
95
|
+
entries = entries.filter(([, m]) => m.hidden);
|
|
96
|
+
if (entries.length === 0) {
|
|
97
|
+
if (isJsonMode()) {
|
|
98
|
+
printJson([]);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
console.log('No local metadata entries.');
|
|
102
|
+
console.log(`File: ${getMetaFilePath()}`);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (isJsonMode()) {
|
|
107
|
+
printJson(entries.map(([id, m]) => ({ deviceId: id, ...m })));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const rows = entries.map(([id, m]) => [
|
|
111
|
+
id,
|
|
112
|
+
m.alias ?? '—',
|
|
113
|
+
m.hidden ? 'yes' : '—',
|
|
114
|
+
m.notes ?? '—',
|
|
115
|
+
]);
|
|
116
|
+
printTable(['deviceId', 'alias', 'hidden', 'notes'], rows);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
handleError(error);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// switchbot devices meta clear <deviceId>
|
|
123
|
+
meta
|
|
124
|
+
.command('clear')
|
|
125
|
+
.description('Remove all local metadata for a device')
|
|
126
|
+
.argument('<deviceId>', 'Target device ID')
|
|
127
|
+
.action((deviceId) => {
|
|
128
|
+
try {
|
|
129
|
+
clearDeviceMeta(deviceId);
|
|
130
|
+
if (isJsonMode()) {
|
|
131
|
+
printJson({ ok: true, deviceId });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`✓ Metadata cleared for ${deviceId}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
handleError(error);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=device-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-meta.js","sourceRoot":"","sources":["../../src/commands/device-meta.ts"],"names":[],"mappings":"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"}
|